module Hasql.Connection
(
Connection,
B.ConnectionSettings(..),
Error(..),
Notification(..),
open,
session,
batch,
close,
)
where
import Hasql.Prelude hiding (interact)
import Hasql.Core.Model
import qualified Hasql.Core.Dispatcher as A
import qualified Hasql.Core.Socket as B
import qualified Hasql.Core.Request as C
import qualified Hasql.Core.PreparedStatementRegistry as D
import qualified Hasql.Core.Batch as E
import qualified Hasql.Core.Session as F
import qualified Hasql.Core.UnauthenticatedSession as G
data Connection =
Connection !B.Socket !A.Dispatcher !(MVar D.Registry) !Bool
open :: B.ConnectionSettings -> ByteString -> ByteString -> Maybe ByteString -> (Notification -> IO ()) -> IO (Either Error Connection)
open transportSettings username password databaseMaybe sendNotification =
do
connectionResult <- B.connect transportSettings
case connectionResult of
Left message -> return (Left (TransportError message))
Right socket -> do
dispatcher <- A.start socket sendNotification
handshakeResult <- A.interact dispatcher (G.handshake username password databaseMaybe [])
case handshakeResult of
Left error -> return (Left error)
Right errorOrIdt -> case errorOrIdt of
Left error -> return (Left (TransportError error))
Right idt -> do
psrVar <- newMVar D.nil
return (Right (Connection socket dispatcher psrVar idt))
session :: Connection -> F.Session result -> IO (Either Error result)
session connection (F.Session free) =
runExceptT (iterM (\x -> join (ExceptT (batch connection x))) free)
batch :: Connection -> E.Batch result -> IO (Either Error result)
batch (Connection _ dispatcher psrVar idt) (E.Batch batchFn) =
do
psr <- takeMVar psrVar
case batchFn idt psr of
(request, newPsr) -> do
result <- A.performRequest dispatcher (request <* C.sync)
putMVar psrVar $ case result of
Left (BackendError _ _) -> psr
_ -> newPsr
return result
close :: Connection -> IO ()
close (Connection socket dispatcher _ _) =
A.stop dispatcher >> B.close socket