Здравствуйте. Сегодня я расскажу вам про Haskell и про то, что получается на стыке его ленивости и императивности всех окружающих программ.
Как вы, наверное, уже знаете, я написал этот сайт на Haskell с использованием Snap Framework. Так вот, для хранения данных у меня используется MySQL, а для работы с этими данными — целая куча библиотек: HDBC, HDBC-mysql, snaplet-hdbc. И где-то во всем этом зоопарке при выполнении запроса к базе возникала ошибка:
SqlError {seState = "", seNativeError = 2050, seErrorMsg = "Row retrieval was canceled by mysql_stmt_close() call"}
Гугл ничего не знал об этом, я тоже, поэтому ошибку отложил до лучших времен, благо возникала она нечасто и лечилась перезагрузкой страницы. И вот на глаза мне попалась такая страница на Stack Overflow. Я полез смотреть код Snap.Snaplet.Hdbc:
-- | Execute a @SELECT@ query on the database by passing the query as 'String',
-- together with a list of values to bind to it. A list of 'Row's is returned.
query
:: HasHdbc m c s
=> String -- ^ The raw SQL to execute. Use @?@ to indicate placeholders.
-> [SqlValue] -- ^ Values for each placeholder according to its position in
-- the SQL statement.
-> m [Row] -- ^ A 'Map' of attribute name to attribute value for each
-- row. Can be the empty list.
query sql bind = do
stmt <- prepare sql
liftIO $ HDBC.execute stmt bind
liftIO $ HDBC.fetchAllRowsMap' stmt
Вроде всё хорошо. Единственное: может, попробовать закрыть statement принудительно? Что я и сделал. Не поверите, помогло. По крайней мере ошибок я больше не увидел. Две переписанных мною функции:
query :: HasHdbc m c s => String -> [SqlValue] -> m [Row]
query sql bind = do
stmt <- prepare sql
liftIO $ HDBC.execute stmt bind
rows <- liftIO $ HDBC.fetchAllRowsMap' stmt
liftIO $ HDBC.finish stmt
return rows
query' :: HasHdbc m c s => String -> [SqlValue] -> m Integer
query' sql bind = withHdbc $ \conn -> do
stmt <- HDBC.prepare conn sql
count <- liftIO $ HDBC.execute stmt bind
liftIO $ HDBC.finish stmt
liftIO $ HDBC.commit conn
return count
Если вы вдруг снова увидите эту ошибку, вы же мне сообщите?
Хочется что-то добавить или сказать? Я всегда рад обсудить. Пишите на me@dikmax.name.