module Database.PostgreSQL.Store.Errand (
ErrandError (..),
Errand,
runErrand,
raiseErrandError,
executeQuery,
query,
query_
) where
import Control.Monad.Trans.Class
import Control.Monad.Trans.Except
import Control.Monad.Trans.Reader
import qualified Data.ByteString as B
import qualified Database.PostgreSQL.LibPQ as P
import Database.PostgreSQL.Store.Query
import Database.PostgreSQL.Store.Result
import Database.PostgreSQL.Store.Columns
data ErrandError
= NoResult
| ExecError P.ExecStatus (Maybe B.ByteString)
| ResultError ResultError
| UnexpectedEmptyResult
| UserError String
deriving (Show, Eq)
type Errand = ReaderT P.Connection (ExceptT ErrandError IO)
runErrand :: P.Connection -> Errand a -> IO (Either ErrandError a)
runErrand con errand =
runExceptT (runReaderT errand con)
raiseErrandError :: ErrandError -> Errand a
raiseErrandError err =
lift (ExceptT (pure (Left err)))
executeQuery :: Query -> Errand P.Result
executeQuery (Query statement params) = do
con <- ask
lift $ do
res <- ExceptT (transformResult <$> P.execParams con statement transformedParams P.Text)
status <- lift (P.resultStatus res)
case status of
P.CommandOk -> pure res
P.TuplesOk -> pure res
other -> do
msg <- lift (P.resultErrorMessage res)
throwE (ExecError other msg)
where
transformResult =
maybe (Left NoResult) pure
transformParam Value {..} = Just (valueType, valueData, valueFormat)
transformParam NullValue = Nothing
transformedParams =
map transformParam params
query :: (Result a) => Query -> Errand [a]
query qry = do
result <- executeQuery qry
lift (withExceptT ResultError (runResultProcessor result resultProcessor))
query_ :: Query -> Errand ()
query_ qry =
() <$ executeQuery qry