A database transaction groups operations into one unit: successful actions are committed, while exceptions roll them back so the database remains unchanged. section 16.3.3
Adding a todo entry safely
Wrap the INSERT and last-inserted-ID lookup in withTransaction. Catch SQLError with try, returning either the error or the new row ID; duplicate primary keys therefore do not leave a partial change. section 16.3.3
Listing 16.10 A function to add a TodoEntry to the database
import Control.Exception (try)
...
addEntry :: Connection -> TodoEntry -> IO (Either SQLError Int)
addEntry dbConn entry = try $ #1
withTransaction dbConn $ do #2
execute #3
dbConn
"INSERT INTO entries (id, text, checked, rank) \
\ VALUES (?,?,?,?)"
entry
newIdx <- lastInsertRowId dbConn #4
return $ fromIntegral newIdx #5
See the complete Haskell implementation combining try, withTransaction, INSERT, and lastInsertRowId. section 16.3.3













