module Hasql.Engine.Decoders.Result where

import Hasql.Codecs.RequestingOid qualified as RequestingOid
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

-- |
-- Decoder of a query result.
newtype Result a
  = Result (RequestingOid.RequestingOid (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 RequestingOid.RequestingOid ResultDecoder.ResultDecoder)

unwrap :: Result a -> RequestingOid.RequestingOid (ResultDecoder.ResultDecoder a)
unwrap :: forall a. Result a -> RequestingOid (ResultDecoder a)
unwrap (Result RequestingOid (ResultDecoder a)
decoder) = RequestingOid (ResultDecoder a)
decoder

-- * Construction

-- |
-- Decode no value from the result.
--
-- Useful for statements like @INSERT@ or @CREATE@.
{-# INLINEABLE noResult #-}
noResult :: Result ()
noResult :: Result ()
noResult =
  RequestingOid (ResultDecoder ()) -> Result ()
forall a. RequestingOid (ResultDecoder a) -> Result a
Result (ResultDecoder () -> RequestingOid (ResultDecoder ())
forall a. a -> RequestingOid a
RequestingOid.lift ResultDecoder ()
ResultDecoder.ok)

-- |
-- Get the amount of rows affected by such statements as
-- @UPDATE@ or @DELETE@.
{-# INLINEABLE rowsAffected #-}
rowsAffected :: Result Int64
rowsAffected :: Result Int64
rowsAffected =
  RequestingOid (ResultDecoder Int64) -> Result Int64
forall a. RequestingOid (ResultDecoder a) -> Result a
Result (ResultDecoder Int64 -> RequestingOid (ResultDecoder Int64)
forall a. a -> RequestingOid a
RequestingOid.lift ResultDecoder Int64
ResultDecoder.rowsAffected)

-- |
-- Exactly one row.
-- Will raise the 'Hasql.Errors.UnexpectedRowCountStatementError' error if it's any other.
{-# INLINEABLE singleRow #-}
singleRow :: Row a -> Result a
singleRow :: forall a. Row a -> Result a
singleRow Row a
decoder =
  RequestingOid (ResultDecoder a) -> Result a
forall a. RequestingOid (ResultDecoder a) -> Result a
Result ((RowDecoder a -> ResultDecoder a)
-> LookingUp (Maybe Text, Text) (Word32, Word32) (RowDecoder a)
-> RequestingOid (ResultDecoder a)
forall a b.
(a -> b)
-> LookingUp (Maybe Text, Text) (Word32, Word32) a
-> LookingUp (Maybe Text, Text) (Word32, Word32) 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
-> LookingUp (Maybe Text, Text) (Word32, Word32) (RowDecoder a)
forall a. Row a -> RequestingOid (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 RequestingOid (ResultDecoder a)
decoder) =
  RequestingOid (ResultDecoder b) -> Result b
forall a. RequestingOid (ResultDecoder a) -> Result a
Result ((ResultDecoder a -> ResultDecoder b)
-> RequestingOid (ResultDecoder a)
-> RequestingOid (ResultDecoder b)
forall a b.
(a -> b)
-> LookingUp (Maybe Text, Text) (Word32, Word32) a
-> LookingUp (Maybe Text, Text) (Word32, Word32) 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) RequestingOid (ResultDecoder a)
decoder)

-- ** Multi-row traversers

-- |
-- Foldl multiple rows.
{-# INLINEABLE 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 =
  RequestingOid (ResultDecoder a) -> Result a
forall a. RequestingOid (ResultDecoder a) -> Result a
Result
    ((RowDecoder b -> ResultDecoder a)
-> LookingUp (Maybe Text, Text) (Word32, Word32) (RowDecoder b)
-> RequestingOid (ResultDecoder a)
forall a b.
(a -> b)
-> LookingUp (Maybe Text, Text) (Word32, Word32) a
-> LookingUp (Maybe Text, Text) (Word32, Word32) 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
-> LookingUp (Maybe Text, Text) (Word32, Word32) (RowDecoder b)
forall a. Row a -> RequestingOid (RowDecoder a)
Row.toDecoder Row b
decoder))

-- |
-- Foldr multiple rows.
{-# INLINEABLE 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 =
  RequestingOid (ResultDecoder a) -> Result a
forall a. RequestingOid (ResultDecoder a) -> Result a
Result
    ((RowDecoder b -> ResultDecoder a)
-> LookingUp (Maybe Text, Text) (Word32, Word32) (RowDecoder b)
-> RequestingOid (ResultDecoder a)
forall a b.
(a -> b)
-> LookingUp (Maybe Text, Text) (Word32, Word32) a
-> LookingUp (Maybe Text, Text) (Word32, Word32) 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
-> LookingUp (Maybe Text, Text) (Word32, Word32) (RowDecoder b)
forall a. Row a -> RequestingOid (RowDecoder a)
Row.toDecoder Row b
decoder))

-- ** Specialized multi-row results

-- |
-- Maybe one row or none.
{-# INLINEABLE rowMaybe #-}
rowMaybe :: Row a -> Result (Maybe a)
rowMaybe :: forall a. Row a -> Result (Maybe a)
rowMaybe Row a
decoder =
  RequestingOid (ResultDecoder (Maybe a)) -> Result (Maybe a)
forall a. RequestingOid (ResultDecoder a) -> Result a
Result
    ((RowDecoder a -> ResultDecoder (Maybe a))
-> LookingUp (Maybe Text, Text) (Word32, Word32) (RowDecoder a)
-> RequestingOid (ResultDecoder (Maybe a))
forall a b.
(a -> b)
-> LookingUp (Maybe Text, Text) (Word32, Word32) a
-> LookingUp (Maybe Text, Text) (Word32, Word32) 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
-> LookingUp (Maybe Text, Text) (Word32, Word32) (RowDecoder a)
forall a. Row a -> RequestingOid (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.
{-# INLINEABLE rowVector #-}
rowVector :: Row a -> Result (Vector a)
rowVector :: forall a. Row a -> Result (Vector a)
rowVector Row a
decoder =
  RequestingOid (ResultDecoder (Vector a)) -> Result (Vector a)
forall a. RequestingOid (ResultDecoder a) -> Result a
Result
    ((RowDecoder a -> ResultDecoder (Vector a))
-> LookingUp (Maybe Text, Text) (Word32, Word32) (RowDecoder a)
-> RequestingOid (ResultDecoder (Vector a))
forall a b.
(a -> b)
-> LookingUp (Maybe Text, Text) (Word32, Word32) a
-> LookingUp (Maybe Text, Text) (Word32, Word32) 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
-> LookingUp (Maybe Text, Text) (Word32, Word32) (RowDecoder a)
forall a. Row a -> RequestingOid (RowDecoder a)
Row.toDecoder Row a
decoder))

-- |
-- Zero or more rows packed into the list.
{-# INLINEABLE 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 []