module Hasql.Engine.Contexts.Session where
import Data.HashMap.Strict qualified as HashMap
import Data.HashSet qualified as HashSet
import Hasql.Codecs.RequestingOid qualified as RequestingOid
import Hasql.Codecs.Vocab.OidCache qualified as OidCache
import Hasql.Codecs.Vocab.QualifiedTypeName qualified as Vocab.QualifiedTypeName
import Hasql.Comms.Roundtrip qualified as Comms.Roundtrip
import Hasql.Engine.Contexts.Pipeline qualified as Pipeline
import Hasql.Engine.Errors qualified as Errors
import Hasql.Engine.PqProcedures.SelectTypeInfo qualified as PqProcedures.SelectTypeInfo
import Hasql.Engine.Statement qualified as Statement
import Hasql.Engine.Structures.ConnectionState qualified as ConnectionState
import Hasql.Engine.Structures.StatementCache qualified as StatementCache
import Hasql.Platform.Prelude
import Hasql.Pq qualified as Pq
newtype Session a
= Session (ConnectionState.ConnectionState -> IO (Either Errors.SessionError a, ConnectionState.ConnectionState))
deriving
((forall a b. (a -> b) -> Session a -> Session b)
-> (forall a b. a -> Session b -> Session a) -> Functor Session
forall a b. a -> Session b -> Session a
forall a b. (a -> b) -> Session a -> Session b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> Session a -> Session b
fmap :: forall a b. (a -> b) -> Session a -> Session b
$c<$ :: forall a b. a -> Session b -> Session a
<$ :: forall a b. a -> Session b -> Session a
Functor, Functor Session
Functor Session =>
(forall a. a -> Session a)
-> (forall a b. Session (a -> b) -> Session a -> Session b)
-> (forall a b c.
(a -> b -> c) -> Session a -> Session b -> Session c)
-> (forall a b. Session a -> Session b -> Session b)
-> (forall a b. Session a -> Session b -> Session a)
-> Applicative Session
forall a. a -> Session a
forall a b. Session a -> Session b -> Session a
forall a b. Session a -> Session b -> Session b
forall a b. Session (a -> b) -> Session a -> Session b
forall a b c. (a -> b -> c) -> Session a -> Session b -> Session c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall a. a -> Session a
pure :: forall a. a -> Session a
$c<*> :: forall a b. Session (a -> b) -> Session a -> Session b
<*> :: forall a b. Session (a -> b) -> Session a -> Session b
$cliftA2 :: forall a b c. (a -> b -> c) -> Session a -> Session b -> Session c
liftA2 :: forall a b c. (a -> b -> c) -> Session a -> Session b -> Session c
$c*> :: forall a b. Session a -> Session b -> Session b
*> :: forall a b. Session a -> Session b -> Session b
$c<* :: forall a b. Session a -> Session b -> Session a
<* :: forall a b. Session a -> Session b -> Session a
Applicative, Applicative Session
Applicative Session =>
(forall a b. Session a -> (a -> Session b) -> Session b)
-> (forall a b. Session a -> Session b -> Session b)
-> (forall a. a -> Session a)
-> Monad Session
forall a. a -> Session a
forall a b. Session a -> Session b -> Session b
forall a b. Session a -> (a -> Session b) -> Session b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall a b. Session a -> (a -> Session b) -> Session b
>>= :: forall a b. Session a -> (a -> Session b) -> Session b
$c>> :: forall a b. Session a -> Session b -> Session b
>> :: forall a b. Session a -> Session b -> Session b
$creturn :: forall a. a -> Session a
return :: forall a. a -> Session a
Monad, MonadError Errors.SessionError, Monad Session
Monad Session => (forall a. IO a -> Session a) -> MonadIO Session
forall a. IO a -> Session a
forall (m :: * -> *).
Monad m =>
(forall a. IO a -> m a) -> MonadIO m
$cliftIO :: forall a. IO a -> Session a
liftIO :: forall a. IO a -> Session a
MonadIO)
via (ExceptT Errors.SessionError (StateT ConnectionState.ConnectionState IO))
run :: Session a -> ConnectionState.ConnectionState -> IO (Either Errors.SessionError a, ConnectionState.ConnectionState)
run :: forall a.
Session a
-> ConnectionState -> IO (Either SessionError a, ConnectionState)
run (Session ConnectionState -> IO (Either SessionError a, ConnectionState)
session) ConnectionState
connectionState = ConnectionState -> IO (Either SessionError a, ConnectionState)
session ConnectionState
connectionState
script :: ByteString -> Session ()
script :: ByteString -> Session ()
script ByteString
sql =
(ConnectionState -> IO (Either SessionError (), ConnectionState))
-> Session ()
forall a.
(ConnectionState -> IO (Either SessionError a, ConnectionState))
-> Session a
Session \ConnectionState
connectionState -> do
let connection :: Connection
connection = ConnectionState -> Connection
ConnectionState.connection ConnectionState
connectionState
Either (Error (Maybe ByteString)) ()
result <- Roundtrip (Maybe ByteString) ()
-> Connection -> IO (Either (Error (Maybe ByteString)) ())
forall context a.
Roundtrip context a -> Connection -> IO (Either (Error context) a)
Comms.Roundtrip.toSerialIO (Maybe ByteString -> ByteString -> Roundtrip (Maybe ByteString) ()
forall context. context -> ByteString -> Roundtrip context ()
Comms.Roundtrip.script (ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
sql) ByteString
sql) Connection
connection
case Either (Error (Maybe ByteString)) ()
result of
Left Error (Maybe ByteString)
err -> case Error (Maybe ByteString)
err of
Comms.Roundtrip.ClientError Maybe ByteString
_ Maybe ByteString
details -> do
(Either SessionError (), ConnectionState)
-> IO (Either SessionError (), ConnectionState)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
( SessionError -> Either SessionError ()
forall a b. a -> Either a b
Left (Text -> SessionError
Errors.ConnectionSessionError (Text -> (ByteString -> Text) -> Maybe ByteString -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" ByteString -> Text
decodeUtf8Lenient Maybe ByteString
details)),
ConnectionState
connectionState
)
Comms.Roundtrip.ServerError Error (Maybe ByteString)
recvError ->
(Either SessionError (), ConnectionState)
-> IO (Either SessionError (), ConnectionState)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
( SessionError -> Either SessionError ()
forall a b. a -> Either a b
Left (ByteString -> Error (Maybe ByteString) -> SessionError
Errors.fromRecvErrorInScript ByteString
sql Error (Maybe ByteString)
recvError),
ConnectionState
connectionState
)
Right () ->
(Either SessionError (), ConnectionState)
-> IO (Either SessionError (), ConnectionState)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
( () -> Either SessionError ()
forall a b. b -> Either a b
Right (),
ConnectionState
connectionState
)
statement ::
Statement.Statement params result ->
params ->
Session result
statement :: forall params result.
Statement params result -> params -> Session result
statement Statement params result
stmt params
params =
(ConnectionState
-> IO (Either SessionError result, ConnectionState))
-> Session result
forall a.
(ConnectionState -> IO (Either SessionError a, ConnectionState))
-> Session a
Session \ConnectionState
connectionState -> do
let usePreparedStatements :: Bool
usePreparedStatements = ConnectionState -> Bool
ConnectionState.preparedStatements ConnectionState
connectionState
statementCache :: StatementCache
statementCache = ConnectionState -> StatementCache
ConnectionState.statementCache ConnectionState
connectionState
oidCache :: OidCache
oidCache = ConnectionState -> OidCache
ConnectionState.oidCache ConnectionState
connectionState
connection :: Connection
connection = ConnectionState -> Connection
ConnectionState.connection ConnectionState
connectionState
sql :: ByteString
sql = Statement params result -> ByteString
forall params result. Statement params result -> ByteString
Statement.sql Statement params result
stmt
missingTypes :: HashSet QualifiedTypeName
missingTypes = HashSet QualifiedTypeName -> OidCache -> HashSet QualifiedTypeName
OidCache.selectUnknownNames (Statement params result -> HashSet QualifiedTypeName
forall params result.
Statement params result -> HashSet QualifiedTypeName
Statement.unknownTypes Statement params result
stmt) OidCache
oidCache
Either SessionError OidCache
resolvedOidCache <-
if HashSet QualifiedTypeName -> Bool
forall a. HashSet a -> Bool
HashSet.null HashSet QualifiedTypeName
missingTypes
then Either SessionError OidCache -> IO (Either SessionError OidCache)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (OidCache -> Either SessionError OidCache
forall a b. b -> Either a b
Right OidCache
oidCache)
else do
Either SessionError SelectTypeInfoResult
oidCacheUpdates <-
Connection
-> SelectTypeInfo -> IO (Either SessionError SelectTypeInfoResult)
PqProcedures.SelectTypeInfo.run Connection
connection (HashSet QualifiedTypeName -> SelectTypeInfo
PqProcedures.SelectTypeInfo.SelectTypeInfo HashSet QualifiedTypeName
missingTypes)
pure $ case Either SessionError SelectTypeInfoResult
oidCacheUpdates of
Left SessionError
err -> SessionError -> Either SessionError OidCache
forall a b. a -> Either a b
Left SessionError
err
Right SelectTypeInfoResult
oidCacheUpdates ->
let foundTypes :: HashSet QualifiedTypeName
foundTypes = SelectTypeInfoResult -> HashSet QualifiedTypeName
forall k a. HashMap k a -> HashSet k
HashMap.keysSet SelectTypeInfoResult
oidCacheUpdates
notFoundTypes :: HashSet QualifiedTypeName
notFoundTypes = HashSet QualifiedTypeName
-> HashSet QualifiedTypeName -> HashSet QualifiedTypeName
forall a. Hashable a => HashSet a -> HashSet a -> HashSet a
HashSet.difference HashSet QualifiedTypeName
missingTypes HashSet QualifiedTypeName
foundTypes
in if Bool -> Bool
not (HashSet QualifiedTypeName -> Bool
forall a. HashSet a -> Bool
HashSet.null HashSet QualifiedTypeName
notFoundTypes)
then SessionError -> Either SessionError OidCache
forall a b. a -> Either a b
Left (HashSet (Maybe Text, Text) -> SessionError
Errors.MissingTypesSessionError ((QualifiedTypeName -> (Maybe Text, Text))
-> HashSet QualifiedTypeName -> HashSet (Maybe Text, Text)
forall b a. Hashable b => (a -> b) -> HashSet a -> HashSet b
HashSet.map QualifiedTypeName -> (Maybe Text, Text)
Vocab.QualifiedTypeName.toNameTuple HashSet QualifiedTypeName
notFoundTypes))
else OidCache -> Either SessionError OidCache
forall a b. b -> Either a b
Right (OidCache
oidCache OidCache -> OidCache -> OidCache
forall a. Semigroup a => a -> a -> a
<> SelectTypeInfoResult -> OidCache
OidCache.fromHashMap SelectTypeInfoResult
oidCacheUpdates)
case Either SessionError OidCache
resolvedOidCache of
Left SessionError
err -> (Either SessionError result, ConnectionState)
-> IO (Either SessionError result, ConnectionState)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SessionError -> Either SessionError result
forall a b. a -> Either a b
Left SessionError
err, ConnectionState
connectionState)
Right OidCache
newOidCache -> do
let decoder' :: ResultDecoder result
decoder' = RequestingOid (ResultDecoder result)
-> OidCache -> ResultDecoder result
forall a. RequestingOid a -> OidCache -> a
RequestingOid.toBase (Statement params result -> RequestingOid (ResultDecoder result)
forall params result.
Statement params result -> RequestingOid (ResultDecoder result)
Statement.decoder Statement params result
stmt) OidCache
newOidCache
prepared :: Bool
prepared = Bool
usePreparedStatements Bool -> Bool -> Bool
&& Statement params result -> Bool
forall params result. Statement params result -> Bool
Statement.isPrepared Statement params result
stmt
context :: Maybe (Int, Int, ByteString, [Text], Bool)
context = (Int, Int, ByteString, [Text], Bool)
-> Maybe (Int, Int, ByteString, [Text], Bool)
forall a. a -> Maybe a
Just (Int
1, Int
0, ByteString
sql, Statement params result -> params -> [Text]
forall params result. Statement params result -> params -> [Text]
Statement.printer Statement params result
stmt params
params, Bool
prepared)
mapError :: Error (Maybe (Int, Int, ByteString, [Text], Bool)) -> SessionError
mapError = \case
Comms.Roundtrip.ClientError Maybe (Int, Int, ByteString, [Text], Bool)
_ Maybe ByteString
details ->
Text -> SessionError
Errors.ConnectionSessionError (Text -> (ByteString -> Text) -> Maybe ByteString -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" ByteString -> Text
decodeUtf8Lenient Maybe ByteString
details)
Comms.Roundtrip.ServerError Error (Maybe (Int, Int, ByteString, [Text], Bool))
recvError ->
Error (Maybe (Int, Int, ByteString, [Text], Bool)) -> SessionError
Errors.fromRecvError Error (Maybe (Int, Int, ByteString, [Text], Bool))
recvError
withState :: (Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result,
StatementCache)
-> (Either SessionError result, ConnectionState)
withState (Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) result
result, StatementCache
newStatementCache) =
( (Error (Maybe (Int, Int, ByteString, [Text], Bool))
-> SessionError)
-> Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result
-> Either SessionError result
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Error (Maybe (Int, Int, ByteString, [Text], Bool)) -> SessionError
mapError Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) result
result,
ConnectionState
connectionState
{ ConnectionState.oidCache = newOidCache,
ConnectionState.statementCache = newStatementCache
}
)
((Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result,
StatementCache)
-> (Either SessionError result, ConnectionState))
-> IO
(Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result,
StatementCache)
-> IO (Either SessionError result, ConnectionState)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result,
StatementCache)
-> (Either SessionError result, ConnectionState)
withState
(IO
(Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result,
StatementCache)
-> IO (Either SessionError result, ConnectionState))
-> IO
(Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result,
StatementCache)
-> IO (Either SessionError result, ConnectionState)
forall a b. (a -> b) -> a -> b
$ if Bool
prepared
then do
let ([Word32]
oidList, [Maybe (ByteString, Bool)]
valueAndFormatList) =
Statement params result
-> OidCache -> params -> ([Word32], [Maybe (ByteString, Bool)])
forall params result.
Statement params result
-> OidCache -> params -> ([Word32], [Maybe (ByteString, Bool)])
Statement.compilePreparedStatementData Statement params result
stmt OidCache
newOidCache params
params
pqOidList :: [Oid]
pqOidList = (Word32 -> Oid) -> [Word32] -> [Oid]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (CUInt -> Oid
Pq.Oid (CUInt -> Oid) -> (Word32 -> CUInt) -> Word32 -> Oid
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Word32 -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral) [Word32]
oidList
encodedParams :: [Maybe (ByteString, Format)]
encodedParams =
[Maybe (ByteString, Bool)]
valueAndFormatList
[Maybe (ByteString, Bool)]
-> ([Maybe (ByteString, Bool)] -> [Maybe (ByteString, Format)])
-> [Maybe (ByteString, Format)]
forall a b. a -> (a -> b) -> b
& (Maybe (ByteString, Bool) -> Maybe (ByteString, Format))
-> [Maybe (ByteString, Bool)] -> [Maybe (ByteString, Format)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((ByteString, Bool) -> (ByteString, Format))
-> Maybe (ByteString, Bool) -> Maybe (ByteString, Format)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(ByteString
bytes, Bool
format) -> (ByteString
bytes, Format -> Format -> Bool -> Format
forall a. a -> a -> Bool -> a
bool Format
Pq.Binary Format
Pq.Text Bool
format)))
execute :: ByteString
-> IO
(Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result)
execute ByteString
remoteKey =
Roundtrip (Maybe (Int, Int, ByteString, [Text], Bool)) result
-> Connection
-> IO
(Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result)
forall context a.
Roundtrip context a -> Connection -> IO (Either (Error context) a)
Comms.Roundtrip.toSerialIO
(Maybe (Int, Int, ByteString, [Text], Bool)
-> ByteString
-> [Maybe (ByteString, Format)]
-> Format
-> ResultDecoder result
-> Roundtrip (Maybe (Int, Int, ByteString, [Text], Bool)) result
forall context a.
context
-> ByteString
-> [Maybe (ByteString, Format)]
-> Format
-> ResultDecoder a
-> Roundtrip context a
Comms.Roundtrip.queryPrepared Maybe (Int, Int, ByteString, [Text], Bool)
context ByteString
remoteKey [Maybe (ByteString, Format)]
encodedParams Format
Pq.Binary ResultDecoder result
decoder')
Connection
connection
case ByteString -> [Oid] -> StatementCache -> Maybe ByteString
StatementCache.lookup ByteString
sql [Oid]
pqOidList StatementCache
statementCache of
Just ByteString
remoteKey -> do
Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) result
result <- ByteString
-> IO
(Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result)
execute ByteString
remoteKey
pure (Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) result
result, StatementCache
statementCache)
Maybe ByteString
Nothing -> do
let (ByteString
remoteKey, StatementCache
newStatementCache) = ByteString
-> [Oid] -> StatementCache -> (ByteString, StatementCache)
StatementCache.insert ByteString
sql [Oid]
pqOidList StatementCache
statementCache
Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) ()
prepareResult <-
Roundtrip (Maybe (Int, Int, ByteString, [Text], Bool)) ()
-> Connection
-> IO
(Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) ())
forall context a.
Roundtrip context a -> Connection -> IO (Either (Error context) a)
Comms.Roundtrip.toSerialIO
(Maybe (Int, Int, ByteString, [Text], Bool)
-> ByteString
-> ByteString
-> [Oid]
-> Roundtrip (Maybe (Int, Int, ByteString, [Text], Bool)) ()
forall context.
context
-> ByteString -> ByteString -> [Oid] -> Roundtrip context ()
Comms.Roundtrip.prepare Maybe (Int, Int, ByteString, [Text], Bool)
context ByteString
remoteKey ByteString
sql [Oid]
pqOidList)
Connection
connection
case Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) ()
prepareResult of
Left Error (Maybe (Int, Int, ByteString, [Text], Bool))
err -> (Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result,
StatementCache)
-> IO
(Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result,
StatementCache)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Error (Maybe (Int, Int, ByteString, [Text], Bool))
-> Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result
forall a b. a -> Either a b
Left Error (Maybe (Int, Int, ByteString, [Text], Bool))
err, StatementCache
statementCache)
Right () -> do
Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) result
result <- ByteString
-> IO
(Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result)
execute ByteString
remoteKey
pure (Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) result
result, StatementCache
newStatementCache)
else do
let encodedParams :: [Maybe (Oid, ByteString, Format)]
encodedParams =
Statement params result
-> OidCache -> params -> [Maybe (Word32, ByteString, Bool)]
forall params result.
Statement params result
-> OidCache -> params -> [Maybe (Word32, ByteString, Bool)]
Statement.compileUnpreparedStatementData Statement params result
stmt OidCache
newOidCache params
params
[Maybe (Word32, ByteString, Bool)]
-> ([Maybe (Word32, ByteString, Bool)]
-> [Maybe (Oid, ByteString, Format)])
-> [Maybe (Oid, ByteString, Format)]
forall a b. a -> (a -> b) -> b
& (Maybe (Word32, ByteString, Bool)
-> Maybe (Oid, ByteString, Format))
-> [Maybe (Word32, ByteString, Bool)]
-> [Maybe (Oid, ByteString, Format)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (((Word32, ByteString, Bool) -> (Oid, ByteString, Format))
-> Maybe (Word32, ByteString, Bool)
-> Maybe (Oid, ByteString, Format)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Word32
oid, ByteString
bytes, Bool
format) -> (CUInt -> Oid
Pq.Oid (Word32 -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
oid), ByteString
bytes, Format -> Format -> Bool -> Format
forall a. a -> a -> Bool -> a
bool Format
Pq.Binary Format
Pq.Text Bool
format)))
Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) result
result <-
Roundtrip (Maybe (Int, Int, ByteString, [Text], Bool)) result
-> Connection
-> IO
(Either
(Error (Maybe (Int, Int, ByteString, [Text], Bool))) result)
forall context a.
Roundtrip context a -> Connection -> IO (Either (Error context) a)
Comms.Roundtrip.toSerialIO
(Maybe (Int, Int, ByteString, [Text], Bool)
-> ByteString
-> [Maybe (Oid, ByteString, Format)]
-> Format
-> ResultDecoder result
-> Roundtrip (Maybe (Int, Int, ByteString, [Text], Bool)) result
forall context a.
context
-> ByteString
-> [Maybe (Oid, ByteString, Format)]
-> Format
-> ResultDecoder a
-> Roundtrip context a
Comms.Roundtrip.queryParams Maybe (Int, Int, ByteString, [Text], Bool)
context ByteString
sql [Maybe (Oid, ByteString, Format)]
encodedParams Format
Pq.Binary ResultDecoder result
decoder')
Connection
connection
pure (Either (Error (Maybe (Int, Int, ByteString, [Text], Bool))) result
result, StatementCache
statementCache)
pipeline :: Pipeline.Pipeline result -> Session result
pipeline :: forall result. Pipeline result -> Session result
pipeline Pipeline result
pipeline = (ConnectionState
-> IO (Either SessionError result, ConnectionState))
-> Session result
forall a.
(ConnectionState -> IO (Either SessionError a, ConnectionState))
-> Session a
Session \ConnectionState
connectionState -> do
let usePreparedStatements :: Bool
usePreparedStatements = ConnectionState -> Bool
ConnectionState.preparedStatements ConnectionState
connectionState
statementCache :: StatementCache
statementCache = ConnectionState -> StatementCache
ConnectionState.statementCache ConnectionState
connectionState
oidCache :: OidCache
oidCache = ConnectionState -> OidCache
ConnectionState.oidCache ConnectionState
connectionState
pqConnection :: Connection
pqConnection = ConnectionState -> Connection
ConnectionState.connection ConnectionState
connectionState
in do
(Either SessionError result
result, OidCache
newOidCache, StatementCache
newStatementCache) <- Pipeline result
-> Bool
-> Connection
-> OidCache
-> StatementCache
-> IO (Either SessionError result, OidCache, StatementCache)
forall a.
Pipeline a
-> Bool
-> Connection
-> OidCache
-> StatementCache
-> IO (Either SessionError a, OidCache, StatementCache)
Pipeline.run Pipeline result
pipeline Bool
usePreparedStatements Connection
pqConnection OidCache
oidCache StatementCache
statementCache
let newConnectionState :: ConnectionState
newConnectionState =
ConnectionState
connectionState
{ ConnectionState.oidCache = newOidCache,
ConnectionState.statementCache = newStatementCache
}
(Either SessionError result, ConnectionState)
-> IO (Either SessionError result, ConnectionState)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either SessionError result
result, ConnectionState
newConnectionState)
onLibpqConnection ::
(Pq.Connection -> IO (Either Errors.SessionError a, Pq.Connection)) ->
Session a
onLibpqConnection :: forall a.
(Connection -> IO (Either SessionError a, Connection)) -> Session a
onLibpqConnection Connection -> IO (Either SessionError a, Connection)
f = (ConnectionState -> IO (Either SessionError a, ConnectionState))
-> Session a
forall a.
(ConnectionState -> IO (Either SessionError a, ConnectionState))
-> Session a
Session \ConnectionState
connectionState -> do
let pqConnection :: Connection
pqConnection = ConnectionState -> Connection
ConnectionState.connection ConnectionState
connectionState
(Either SessionError a
result, Connection
newConnection) <- Connection -> IO (Either SessionError a, Connection)
f Connection
pqConnection
let newState :: ConnectionState
newState = Connection -> ConnectionState -> ConnectionState
ConnectionState.setConnection Connection
newConnection ConnectionState
connectionState
(Either SessionError a, ConnectionState)
-> IO (Either SessionError a, ConnectionState)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either SessionError a
result, ConnectionState
newState)