hasql/library/Hasql/Private/Session.hs

66 lines
2.5 KiB
Haskell
Raw Normal View History

2022-06-20 13:54:54 +03:00
module Hasql.Private.Session where
2015-12-21 16:11:14 +03:00
2022-06-20 13:54:54 +03:00
import qualified Hasql.Private.Connection as Connection
import qualified Hasql.Private.Decoders.Result as Decoders.Result
2022-06-20 13:54:54 +03:00
import qualified Hasql.Private.Decoders.Results as Decoders.Results
2019-05-20 19:27:10 +03:00
import qualified Hasql.Private.Encoders as Encoders
2022-06-20 13:54:54 +03:00
import qualified Hasql.Private.Encoders.Params as Encoders.Params
import Hasql.Private.Errors
2015-12-21 16:11:14 +03:00
import qualified Hasql.Private.IO as IO
2022-06-20 13:54:54 +03:00
import Hasql.Private.Prelude
2018-05-23 13:33:34 +03:00
import qualified Hasql.Statement as Statement
2015-12-21 16:11:14 +03:00
-- |
-- A batch of actions to be executed in the context of a database connection.
2022-06-20 13:54:54 +03:00
newtype Session a
= Session (ReaderT Connection.Connection (ExceptT QueryError IO) a)
2022-01-02 19:27:38 +03:00
deriving (Functor, Applicative, Monad, MonadError QueryError, MonadIO, MonadReader Connection.Connection)
2015-12-21 16:45:10 +03:00
-- |
-- Executes a bunch of commands on the provided connection.
run :: Session a -> Connection.Connection -> IO (Either QueryError a)
2015-12-21 16:45:10 +03:00
run (Session impl) connection =
2023-10-13 02:24:12 +03:00
runExceptT
$ runReaderT impl connection
2015-12-21 16:11:14 +03:00
-- |
-- Possibly a multi-statement query,
-- which however cannot be parameterized or prepared,
-- nor can any results of it be collected.
sql :: ByteString -> Session ()
sql sql =
2023-10-13 02:24:12 +03:00
Session
$ ReaderT
$ \(Connection.Connection pqConnectionRef integerDatetimes registry) ->
ExceptT
$ fmap (mapLeft (QueryError sql []))
$ withMVar pqConnectionRef
$ \pqConnection -> do
r1 <- IO.sendNonparametricStatement pqConnection sql
r2 <- IO.getResults pqConnection integerDatetimes decoder
return $ r1 *> r2
2016-01-22 18:50:13 +03:00
where
decoder =
2019-05-21 13:25:22 +03:00
Decoders.Results.single Decoders.Result.noResult
2015-12-21 16:11:14 +03:00
-- |
2018-05-23 13:33:34 +03:00
-- Parameters and a specification of a parametric single-statement query to apply them to.
statement :: params -> Statement.Statement params result -> Session result
2019-05-20 19:27:10 +03:00
statement input (Statement.Statement template (Encoders.Params paramsEncoder) decoder preparable) =
2023-10-13 02:24:12 +03:00
Session
$ ReaderT
$ \(Connection.Connection pqConnectionRef integerDatetimes registry) ->
ExceptT
$ fmap (mapLeft (QueryError template inputReps))
$ withMVar pqConnectionRef
$ \pqConnection -> do
r1 <- IO.sendParametricStatement pqConnection integerDatetimes registry template paramsEncoder preparable input
r2 <- IO.getResults pqConnection integerDatetimes (unsafeCoerce decoder)
return $ r1 *> r2
where
inputReps =
2022-06-20 13:54:54 +03:00
let Encoders.Params.Params (Op encoderOp) = paramsEncoder
step (_, _, _, rendering) acc =
rendering : acc
in foldr step [] (encoderOp input)