module Hasql.Engine.Decoders.Result where

import Hasql.CodecsVocab.QualifiedTypeName qualified as CodecsVocab.QualifiedTypeName
import Hasql.CodecsVocab.TypeInfo qualified as CodecsVocab.TypeInfo
import Hasql.Comms.ResultDecoder qualified as ResultDecoder
import Hasql.Engine.Decoders.Row (Row (..))
import Hasql.Engine.Decoders.Row qualified as Row
import Hasql.Platform.Prelude
import Hasql.ToBeResolved qualified as ToBeResolved

-- |
-- Decoder of a query result.
newtype Result a
  = Result (ToBeResolved.ToBeResolved CodecsVocab.QualifiedTypeName.QualifiedTypeName CodecsVocab.TypeInfo.TypeInfo (ResultDecoder.ResultDecoder a))
  deriving
    ((forall a b. (a -> b) -> Result a -> Result b)
-> (forall a b. a -> Result b -> Result a) -> Functor Result
forall a b. a -> Result b -> Result a
forall a b. (a -> b) -> Result a -> Result 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) -> Result a -> Result b
fmap :: forall a b. (a -> b) -> Result a -> Result b
$c<$ :: forall a b. a -> Result b -> Result a
<$ :: forall a b. a -> Result b -> Result a
Functor, Functor Result
Functor Result =>
(forall a. a -> Result a)
-> (forall a b. Result (a -> b) -> Result a -> Result b)
-> (forall a b c.
    (a -> b -> c) -> Result a -> Result b -> Result c)
-> (forall a b. Result a -> Result b -> Result b)
-> (forall a b. Result a -> Result b -> Result a)
-> Applicative Result
forall a. a -> Result a
forall a b. Result a -> Result b -> Result a
forall a b. Result a -> Result b -> Result b
forall a b. Result (a -> b) -> Result a -> Result b
forall a b c. (a -> b -> c) -> Result a -> Result b -> Result 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 -> Result a
pure :: forall a. a -> Result a
$c<*> :: forall a b. Result (a -> b) -> Result a -> Result b
<*> :: forall a b. Result (a -> b) -> Result a -> Result b
$cliftA2 :: forall a b c. (a -> b -> c) -> Result a -> Result b -> Result c
liftA2 :: forall a b c. (a -> b -> c) -> Result a -> Result b -> Result c
$c*> :: forall a b. Result a -> Result b -> Result b
*> :: forall a b. Result a -> Result b -> Result b
$c<* :: forall a b. Result a -> Result b -> Result a
<* :: forall a b. Result a -> Result b -> Result a
Applicative, Functor Result
Functor Result =>
(forall a b. (a -> Maybe b) -> Result a -> Result b)
-> (forall a. Result (Maybe a) -> Result a)
-> (forall a. (a -> Bool) -> Result a -> Result a)
-> (forall a b. Result a -> Result b)
-> Filterable Result
forall a. Result (Maybe a) -> Result a
forall a. (a -> Bool) -> Result a -> Result a
forall a b. Result a -> Result b
forall a b. (a -> Maybe b) -> Result a -> Result b
forall (f :: * -> *).
Functor f =>
(forall a b. (a -> Maybe b) -> f a -> f b)
-> (forall a. f (Maybe a) -> f a)
-> (forall a. (a -> Bool) -> f a -> f a)
-> (forall a b. f a -> f b)
-> Filterable f
$cmapMaybe :: forall a b. (a -> Maybe b) -> Result a -> Result b
mapMaybe :: forall a b. (a -> Maybe b) -> Result a -> Result b
$ccatMaybes :: forall a. Result (Maybe a) -> Result a
catMaybes :: forall a. Result (Maybe a) -> Result a
$cfilter :: forall a. (a -> Bool) -> Result a -> Result a
filter :: forall a. (a -> Bool) -> Result a -> Result a
$cdrain :: forall a b. Result a -> Result b
drain :: forall a b. Result a -> Result b
Filterable)
    via (Compose (ToBeResolved.ToBeResolved CodecsVocab.QualifiedTypeName.QualifiedTypeName CodecsVocab.TypeInfo.TypeInfo) ResultDecoder.ResultDecoder)

-- | Names of types that must be looked up at runtime before the decoder can run.
toUnknownTypes :: Result a -> HashSet CodecsVocab.QualifiedTypeName.QualifiedTypeName
toUnknownTypes :: forall a. Result a -> HashSet QualifiedTypeName
toUnknownTypes (Result (ToBeResolved.ToBeResolved [QualifiedTypeName]
unknownTypes (QualifiedTypeName -> TypeInfo) -> ResultDecoder a
_)) = [Item (HashSet QualifiedTypeName)] -> HashSet QualifiedTypeName
forall l. IsList l => [Item l] -> l
fromList [Item (HashSet QualifiedTypeName)]
[QualifiedTypeName]
unknownTypes

-- | Resolve the decoder given a resolver of type names to their OIDs.
toBase :: Result a -> (CodecsVocab.QualifiedTypeName.QualifiedTypeName -> CodecsVocab.TypeInfo.TypeInfo) -> ResultDecoder.ResultDecoder a
toBase :: forall a.
Result a -> (QualifiedTypeName -> TypeInfo) -> ResultDecoder a
toBase (Result (ToBeResolved.ToBeResolved [QualifiedTypeName]
_ (QualifiedTypeName -> TypeInfo) -> ResultDecoder a
decoder)) = (QualifiedTypeName -> TypeInfo) -> ResultDecoder a
decoder

-- * Construction

-- |
-- Decode no value from the result.
--
-- Useful for statements like @INSERT@ or @CREATE@.
{-# INLINE noResult #-}
noResult :: Result ()
noResult :: Result ()
noResult =
  ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder ())
-> Result ()
forall a.
ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
Result (ResultDecoder ()
-> ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder ())
forall a. a -> ToBeResolved QualifiedTypeName TypeInfo a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ResultDecoder ()
ResultDecoder.ok)

-- |
-- Get the amount of rows affected by such statements as
-- @UPDATE@ or @DELETE@.
{-# INLINE rowsAffected #-}
rowsAffected :: Result Int64
rowsAffected :: Result Int64
rowsAffected =
  ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder Int64)
-> Result Int64
forall a.
ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
Result (ResultDecoder Int64
-> ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder Int64)
forall a. a -> ToBeResolved QualifiedTypeName TypeInfo a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ResultDecoder Int64
ResultDecoder.rowsAffected)

-- |
-- Exactly one row.
-- Will raise the 'Hasql.Errors.UnexpectedRowCountStatementError' error if it's any other.
{-# INLINE singleRow #-}
singleRow :: Row a -> Result a
singleRow :: forall a. Row a -> Result a
singleRow Row a
decoder =
  ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
forall a.
ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
Result ((RowDecoder a -> ResultDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
forall a b.
(a -> b)
-> ToBeResolved QualifiedTypeName TypeInfo a
-> ToBeResolved QualifiedTypeName TypeInfo b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap RowDecoder a -> ResultDecoder a
forall a. RowDecoder a -> ResultDecoder a
ResultDecoder.single (Row a -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
forall a.
Row a -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
Row.toDecoder Row a
decoder))

refineResult :: (a -> Either Text b) -> Result a -> Result b
refineResult :: forall a b. (a -> Either Text b) -> Result a -> Result b
refineResult a -> Either Text b
refiner (Result ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
decoder) =
  ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder b)
-> Result b
forall a.
ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
Result ((ResultDecoder a -> ResultDecoder b)
-> ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder b)
forall a b.
(a -> b)
-> ToBeResolved QualifiedTypeName TypeInfo a
-> ToBeResolved QualifiedTypeName TypeInfo b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> Either Text b) -> ResultDecoder a -> ResultDecoder b
forall a b.
(a -> Either Text b) -> ResultDecoder a -> ResultDecoder b
ResultDecoder.refine a -> Either Text b
refiner) ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
decoder)

-- ** Multi-row traversers

-- |
-- Foldl multiple rows.
{-# INLINE foldlRows #-}
foldlRows :: (a -> b -> a) -> a -> Row b -> Result a
foldlRows :: forall a b. (a -> b -> a) -> a -> Row b -> Result a
foldlRows a -> b -> a
step a
init Row b
decoder =
  ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
forall a.
ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
Result
    ((RowDecoder b -> ResultDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder b)
-> ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
forall a b.
(a -> b)
-> ToBeResolved QualifiedTypeName TypeInfo a
-> ToBeResolved QualifiedTypeName TypeInfo b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> b -> a) -> a -> RowDecoder b -> ResultDecoder a
forall a b. (a -> b -> a) -> a -> RowDecoder b -> ResultDecoder a
ResultDecoder.foldl a -> b -> a
step a
init) (Row b -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder b)
forall a.
Row a -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
Row.toDecoder Row b
decoder))

-- |
-- Foldr multiple rows.
{-# INLINE foldrRows #-}
foldrRows :: (b -> a -> a) -> a -> Row b -> Result a
foldrRows :: forall b a. (b -> a -> a) -> a -> Row b -> Result a
foldrRows b -> a -> a
step a
init Row b
decoder =
  ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
forall a.
ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
Result
    ((RowDecoder b -> ResultDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder b)
-> ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
forall a b.
(a -> b)
-> ToBeResolved QualifiedTypeName TypeInfo a
-> ToBeResolved QualifiedTypeName TypeInfo b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((b -> a -> a) -> a -> RowDecoder b -> ResultDecoder a
forall b a. (b -> a -> a) -> a -> RowDecoder b -> ResultDecoder a
ResultDecoder.foldr b -> a -> a
step a
init) (Row b -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder b)
forall a.
Row a -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
Row.toDecoder Row b
decoder))

-- ** Specialized multi-row results

-- |
-- Maybe one row or none.
{-# INLINE rowMaybe #-}
rowMaybe :: Row a -> Result (Maybe a)
rowMaybe :: forall a. Row a -> Result (Maybe a)
rowMaybe Row a
decoder =
  ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder (Maybe a))
-> Result (Maybe a)
forall a.
ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
Result
    ((RowDecoder a -> ResultDecoder (Maybe a))
-> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
-> ToBeResolved
     QualifiedTypeName TypeInfo (ResultDecoder (Maybe a))
forall a b.
(a -> b)
-> ToBeResolved QualifiedTypeName TypeInfo a
-> ToBeResolved QualifiedTypeName TypeInfo b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap RowDecoder a -> ResultDecoder (Maybe a)
forall a. RowDecoder a -> ResultDecoder (Maybe a)
ResultDecoder.maybe (Row a -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
forall a.
Row a -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
Row.toDecoder Row a
decoder))

-- |
-- Zero or more rows packed into the vector.
--
-- It's recommended to prefer this function to 'rowList',
-- since it performs notably better.
{-# INLINE rowVector #-}
rowVector :: Row a -> Result (Vector a)
rowVector :: forall a. Row a -> Result (Vector a)
rowVector Row a
decoder =
  ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder (Vector a))
-> Result (Vector a)
forall a.
ToBeResolved QualifiedTypeName TypeInfo (ResultDecoder a)
-> Result a
Result
    ((RowDecoder a -> ResultDecoder (Vector a))
-> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
-> ToBeResolved
     QualifiedTypeName TypeInfo (ResultDecoder (Vector a))
forall a b.
(a -> b)
-> ToBeResolved QualifiedTypeName TypeInfo a
-> ToBeResolved QualifiedTypeName TypeInfo b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap RowDecoder a -> ResultDecoder (Vector a)
forall a. RowDecoder a -> ResultDecoder (Vector a)
ResultDecoder.vector (Row a -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
forall a.
Row a -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
Row.toDecoder Row a
decoder))

-- |
-- Zero or more rows packed into the list.
{-# INLINE rowList #-}
rowList :: Row a -> Result [a]
rowList :: forall a. Row a -> Result [a]
rowList =
  (a -> [a] -> [a]) -> [a] -> Row a -> Result [a]
forall b a. (b -> a -> a) -> a -> Row b -> Result a
foldrRows a -> [a] -> [a]
forall a. a -> [a] -> [a]
strictCons []