hasql-1.10.3.4: src/library/Hasql/Comms/RowReader.hs
-- | Lower level context focused on just the actual decoding of values. No metadata involved.
module Hasql.Comms.RowReader
( RowReader,
nullableColumn,
nonNullableColumn,
-- * Errors
Error (..),
CellError (..),
-- * Relations
toHandler,
)
where
import Hasql.Platform.Prelude
import Hasql.Pq qualified as Pq
data Error
= CellError
-- | Column index, 0-based.
Int
-- | OID of the column type as reported by Postgres.
Word32
-- | Underlying error.
CellError
| RefinementError Text
deriving stock (Eq, Show)
data CellError
= DecodingCellError Text
| UnexpectedNullCellError
deriving stock (Eq, Show)
newtype RowReader a
= RowReader (StateT Pq.Column (ReaderT Env (ExceptT Error IO)) a)
deriving
(Functor, Applicative)
via (StateT Pq.Column (ReaderT Env (ExceptT Error IO)))
data Env
= Env
Pq.Result
Pq.Row
-- * Instances
instance Filterable RowReader where
{-# INLINE mapMaybe #-}
mapMaybe fn (RowReader run) =
RowReader do
result <- run
case fn result of
Just refined -> pure refined
Nothing -> throwError (RefinementError "Filtration failed")
-- * Functions
{-# INLINE toHandler #-}
toHandler :: RowReader a -> Pq.Result -> Pq.Row -> IO (Either Error a)
toHandler (RowReader f) result row =
let env = Env result row
in runExceptT (runReaderT (evalStateT f 0) env)
-- |
-- Next value, decoded using the provided value decoder.
{-# INLINE column #-}
column :: (Maybe a -> Maybe b) -> (ByteString -> Either Text a) -> RowReader b
column processNullable valueDec = RowReader do
col <- get
Env result row <- ask
let colInt = Pq.colToInt col
put (succ col)
valueMaybe <- liftIO ({-# SCC "getvalue'" #-} Pq.getvalue' result row col)
valueMaybe <- case valueMaybe of
Nothing -> pure Nothing
Just v ->
case {-# SCC "decode" #-} valueDec v of
Left err -> do
oid <- Pq.oidToWord32 <$> liftIO (Pq.ftype result col)
throwError (CellError colInt oid (DecodingCellError err))
Right decoded -> pure (Just decoded)
case processNullable valueMaybe of
Nothing -> do
oid <- Pq.oidToWord32 <$> liftIO (Pq.ftype result col)
throwError (CellError colInt oid UnexpectedNullCellError)
Just decoded -> pure decoded
-- |
-- Next value, decoded using the provided value decoder.
{-# INLINE nullableColumn #-}
nullableColumn :: (ByteString -> Either Text a) -> RowReader (Maybe a)
nullableColumn = column Just
-- |
-- Next value, decoded using the provided value decoder.
{-# INLINE nonNullableColumn #-}
nonNullableColumn :: (ByteString -> Either Text a) -> RowReader a
nonNullableColumn = column id