module Data.CQRS.EventStore.Backend.Sqlite3Utils
( sourceQuery
, execSql
, withTransaction
) where
import Control.Exception (catch, bracket, onException, SomeException)
import Control.Monad.IO.Class (liftIO)
import Data.Conduit (ResourceT, Source, bracketP, yield)
import Data.Text (Text)
import qualified Database.SQLite3 as SQL
import Database.SQLite3 (Database, Statement, SQLData(..), StepResult(..))
beginTransaction :: Database -> IO ()
beginTransaction database = execSql database "BEGIN TRANSACTION;" []
commitTransaction :: Database -> IO ()
commitTransaction database = execSql database "COMMIT TRANSACTION;" []
rollbackTransaction :: Database -> IO ()
rollbackTransaction database = execSql database "ROLLBACK TRANSACTION;" []
withSqlStatement :: Database -> Text -> [SQLData] -> (Statement -> IO a) -> IO a
withSqlStatement database sql parameters action =
bracket (SQL.prepare database sql) SQL.finalize $ \statement -> do
SQL.bind statement parameters
action statement
execSql :: Database -> Text -> [SQLData] -> IO ()
execSql database sql parameters =
withSqlStatement database sql parameters $ \stmt -> do
_ <- SQL.step stmt
return ()
data State = Unbound | Bound
deriving (Eq)
sourceQuery :: Database -> Text -> [SQLData] -> Source (ResourceT IO) [SQLData]
sourceQuery database sql parameters =
bracketP (SQL.prepare database sql)
(SQL.finalize)
run
where
run stmt = do
liftIO $ SQL.bind stmt parameters
loop stmt
loop stmt = do
nextResult <- liftIO $ SQL.step stmt
case nextResult of
Done -> return ()
Row -> do
(liftIO $ SQL.columns stmt) >>= yield
loop stmt
withTransaction :: Database -> IO a -> IO a
withTransaction database action = do
beginTransaction database
onException runAction tryRollback
where
runAction = do
r <- action
commitTransaction database
return r
tryRollback =
catch (rollbackTransaction database) (\(_::SomeException) -> return ())