module Hasql.Transaction.Transaction where
import Hasql.Transaction.Prelude hiding (map, retry)
import Hasql.Transaction.Requisites.Model
import Hasql.Session (Session)
import Hasql.Statement (Statement)
import qualified Hasql.Session as Session
data Transaction i o =
Transaction Mode Level [i -> StateT Condemnation Session o]
deriving instance Functor (Transaction i)
instance Applicative (Transaction i) where
pure = Transaction Read ReadCommitted . pure . const . pure
(<*>) = binOp $ \ lSession rSession i -> lSession i <*> rSession i
instance Alternative (Transaction i) where
empty = retry
(<|>) (Transaction lMode lLevel lList) (Transaction rMode rLevel rList) =
Transaction (max lMode rMode) (max lLevel rLevel) (lList <> rList)
instance Profunctor Transaction where
dimap fn1 fn2 = map $ \ session -> fmap fn2 . session . fn1
instance Strong Transaction where
first' = first
second' = second
instance Choice Transaction where
left' = left
right' = right
instance Semigroupoid Transaction where
o = binOp (<=<)
instance Category Transaction where
id = Transaction Read ReadCommitted []
(.) = o
instance Arrow Transaction where
arr fn = Transaction Read ReadCommitted (return (return . fn))
(***) = binOp $ \ lSession rSession (li, ri) -> (,) <$> lSession li <*> rSession ri
instance ArrowChoice Transaction where
(+++) = binOp $ \ lSession rSession -> either (fmap Left . lSession) (fmap Right . rSession)
instance ArrowZero Transaction where
zeroArrow = retry
instance ArrowPlus Transaction where
(<+>) = (<|>)
{-# INLINE binOp #-}
binOp ::
(
(li -> StateT Condemnation Session lo) ->
(ri -> StateT Condemnation Session ro) ->
(i -> StateT Condemnation Session o)
) ->
Transaction li lo -> Transaction ri ro -> Transaction i o
binOp composeSessions (Transaction lMode lLevel lList) (Transaction rMode rLevel rList) = let
mode = max lMode rMode
level = max lLevel rLevel
list = composeSessions <$> lList <*> rList
in Transaction mode level list
{-# INLINE map #-}
map ::
((i1 -> StateT Condemnation Session o1) -> (i2 -> StateT Condemnation Session o2)) ->
Transaction i1 o1 -> Transaction i2 o2
map sessionFn (Transaction mode isolation list) = Transaction mode isolation (fmap sessionFn list)
condemn :: Transaction () ()
condemn = Transaction Read ReadCommitted [\ _ -> put Condemned]
sql :: Mode -> Level -> ByteString -> Transaction () ()
sql mode level sql = session mode level $ \ _ -> Session.sql sql
statement :: Mode -> Level -> Statement i o -> Transaction i o
statement mode level statement = session mode level $ \ i -> Session.statement i statement
session :: Mode -> Level -> (i -> Session o) -> Transaction i o
session mode level sessionFn = Transaction mode level [lift . sessionFn]
retry :: Transaction i o
retry = Transaction Read ReadCommitted []