Row retrieval was canceled
Вторник, 5 июня 2012

Здравствуйте. Сегодня я расскажу вам про 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

Если вы вдруг снова увидите эту ошибку, вы же мне сообщите?

← λValtari →