module Hasql.Transaction
(
Mode(..),
IsolationLevel(..),
Transaction,
run,
sql,
query,
)
where
import Hasql.Transaction.Prelude
import qualified Hasql.Query as Query
import qualified Hasql.Session as Session
import qualified Hasql.Transaction.Queries as Queries
newtype Transaction a =
Transaction (Session.Session a)
deriving (Functor, Applicative, Monad)
data Mode =
Read |
Write |
WriteWithoutCommitting
deriving (Show, Eq, Ord, Enum, Bounded)
data IsolationLevel =
ReadCommitted |
RepeatableRead |
Serializable
deriving (Show, Eq, Ord, Enum, Bounded)
run :: Transaction a -> IsolationLevel -> Mode -> Session.Session a
run (Transaction session) isolation mode =
fix $
\ recur ->
do
resultEither <- do
Session.query () (Queries.beginTransaction mode')
tryError $ do
result <- session
Session.query () (bool Queries.abortTransaction Queries.commitTransaction commit)
return result
case resultEither of
Left error -> do
Session.query () Queries.abortTransaction
case error of
Session.ResultError (Session.ServerError "40001" _ _ _) ->
recur
_ ->
throwError error
Right result -> do
pure result
where
mode' =
(unsafeCoerce isolation, write)
(write, commit) =
case mode of
Read -> (False, True)
Write -> (True, True)
WriteWithoutCommitting -> (True, False)
sql :: ByteString -> Transaction ()
sql sql =
Transaction $ Session.sql sql
query :: a -> Query.Query a b -> Transaction b
query params query =
Transaction $ Session.query params query