withTransaction :: Database -> IO a -> IO a
withTransaction conn body =
mask $ \restore -> do
exec conn "BEGIN"
a <- restore (body a) `onException` exec conn "ROLLBACK"
exec conn "COMMIT"
return a
Namely, ROLLBACK throws an exception if no transaction is in progress, and some errors automatically roll back the transaction. To address this problem precisely, I need a binding for sqlite3_get_autocommit:
withTransaction :: Database -> IO a -> IO a
withTransaction conn body =
mask $ \restore -> do
exec conn "BEGIN"
a <- restore (body a) `onException` do
autocommit <- getAutoCommit conn
when (not autocommit) $ exec conn "ROLLBACK"
exec conn "COMMIT"
return a
I only exported this from Database.SQLite3.Direct to avoid cluttering the main API, and in case we want to use a more intuitive name than SQLite uses, like:
active <- isTransactionActive conn
when active $ exec conn "ROLLBACK"
Thanks! Appreciate your finding and dealing with this case. I agree that we should have a better-named front-facing interface for this; would you like to do that, as well?
I encountered a problem with this pattern:
Namely,
ROLLBACK
throws an exception if no transaction is in progress, and some errors automatically roll back the transaction. To address this problem precisely, I need a binding for sqlite3_get_autocommit:I only exported this from Database.SQLite3.Direct to avoid cluttering the main API, and in case we want to use a more intuitive name than SQLite uses, like: