module Hasql.Engine.Decoders.Row where

import Hasql.Codecs.Decoders
import Hasql.Codecs.Decoders.Value qualified as Value
import Hasql.CodecsVocab.QualifiedTypeName qualified as CodecsVocab.QualifiedTypeName
import Hasql.CodecsVocab.TypeInfo qualified as CodecsVocab.TypeInfo
import Hasql.Comms.RowDecoder qualified
import Hasql.Platform.Prelude
import Hasql.ToBeResolved qualified as ToBeResolved
import PostgreSQL.Binary.Decoding qualified as Binary

-- |
-- Decoder of an individual row,
-- which gets composed of column value decoders.
-- E.g.:
--
-- @
-- x :: 'Row' (Maybe Int64, Text, TimeOfDay)
-- x = (,,) '<$>' ('column' . 'nullable') 'int8' '<*>' ('column' . 'nonNullable') 'text' '<*>' ('column' . 'nonNullable') 'time'
-- @
newtype Row a
  = Row (ToBeResolved.ToBeResolved CodecsVocab.QualifiedTypeName.QualifiedTypeName CodecsVocab.TypeInfo.TypeInfo (Hasql.Comms.RowDecoder.RowDecoder a))
  deriving
    ((forall a b. (a -> b) -> Row a -> Row b)
-> (forall a b. a -> Row b -> Row a) -> Functor Row
forall a b. a -> Row b -> Row a
forall a b. (a -> b) -> Row a -> Row 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) -> Row a -> Row b
fmap :: forall a b. (a -> b) -> Row a -> Row b
$c<$ :: forall a b. a -> Row b -> Row a
<$ :: forall a b. a -> Row b -> Row a
Functor, Functor Row
Functor Row =>
(forall a. a -> Row a)
-> (forall a b. Row (a -> b) -> Row a -> Row b)
-> (forall a b c. (a -> b -> c) -> Row a -> Row b -> Row c)
-> (forall a b. Row a -> Row b -> Row b)
-> (forall a b. Row a -> Row b -> Row a)
-> Applicative Row
forall a. a -> Row a
forall a b. Row a -> Row b -> Row a
forall a b. Row a -> Row b -> Row b
forall a b. Row (a -> b) -> Row a -> Row b
forall a b c. (a -> b -> c) -> Row a -> Row b -> Row 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 -> Row a
pure :: forall a. a -> Row a
$c<*> :: forall a b. Row (a -> b) -> Row a -> Row b
<*> :: forall a b. Row (a -> b) -> Row a -> Row b
$cliftA2 :: forall a b c. (a -> b -> c) -> Row a -> Row b -> Row c
liftA2 :: forall a b c. (a -> b -> c) -> Row a -> Row b -> Row c
$c*> :: forall a b. Row a -> Row b -> Row b
*> :: forall a b. Row a -> Row b -> Row b
$c<* :: forall a b. Row a -> Row b -> Row a
<* :: forall a b. Row a -> Row b -> Row a
Applicative, Functor Row
Functor Row =>
(forall a b. (a -> Maybe b) -> Row a -> Row b)
-> (forall a. Row (Maybe a) -> Row a)
-> (forall a. (a -> Bool) -> Row a -> Row a)
-> (forall a b. Row a -> Row b)
-> Filterable Row
forall a. Row (Maybe a) -> Row a
forall a. (a -> Bool) -> Row a -> Row a
forall a b. Row a -> Row b
forall a b. (a -> Maybe b) -> Row a -> Row 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) -> Row a -> Row b
mapMaybe :: forall a b. (a -> Maybe b) -> Row a -> Row b
$ccatMaybes :: forall a. Row (Maybe a) -> Row a
catMaybes :: forall a. Row (Maybe a) -> Row a
$cfilter :: forall a. (a -> Bool) -> Row a -> Row a
filter :: forall a. (a -> Bool) -> Row a -> Row a
$cdrain :: forall a b. Row a -> Row b
drain :: forall a b. Row a -> Row b
Filterable)
    via (Compose (ToBeResolved.ToBeResolved CodecsVocab.QualifiedTypeName.QualifiedTypeName CodecsVocab.TypeInfo.TypeInfo) Hasql.Comms.RowDecoder.RowDecoder)

toDecoder ::
  Row a ->
  ToBeResolved.ToBeResolved CodecsVocab.QualifiedTypeName.QualifiedTypeName CodecsVocab.TypeInfo.TypeInfo (Hasql.Comms.RowDecoder.RowDecoder a)
toDecoder :: forall a.
Row a -> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
toDecoder (Row ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
f) = ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
f

-- |
-- Lift an individual value decoder to a composable row decoder.
{-# INLINE column #-}
column :: NullableOrNot Value a -> Row a
column :: forall a. NullableOrNot Value a -> Row a
column = \case
  Nullable Value a1
valueDecoder ->
    ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a) -> Row a
forall a.
ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a) -> Row a
Row case Value a1 -> Maybe Word32
forall a. Value a -> Maybe Word32
Value.toOid Value a1
valueDecoder of
      Just Word32
oid ->
        (Value a1 -> RowDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo (Value a1)
-> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder 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
          (Maybe Word32
-> (ByteString -> Either Text a1) -> RowDecoder (Maybe a1)
forall a.
Maybe Word32
-> (ByteString -> Either Text a) -> RowDecoder (Maybe a)
Hasql.Comms.RowDecoder.nullableColumn (Word32 -> Maybe Word32
forall a. a -> Maybe a
Just Word32
oid) ((ByteString -> Either Text a1) -> RowDecoder (Maybe a1))
-> (Value a1 -> ByteString -> Either Text a1)
-> Value a1
-> RowDecoder (Maybe a1)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Value a1 -> ByteString -> Either Text a1
forall a. Value a -> ByteString -> Either Text a
Binary.valueParser)
          (Value a1 -> ToBeResolved QualifiedTypeName TypeInfo (Value a1)
forall a.
Value a -> ToBeResolved QualifiedTypeName TypeInfo (Value a)
Value.toDecoder Value a1
valueDecoder)
      Maybe Word32
Nothing ->
        ( \TypeInfo
lookupResult Value a1
decoder ->
            Maybe Word32
-> (ByteString -> Either Text a1) -> RowDecoder (Maybe a1)
forall a.
Maybe Word32
-> (ByteString -> Either Text a) -> RowDecoder (Maybe a)
Hasql.Comms.RowDecoder.nullableColumn (Word32 -> Maybe Word32
forall a. a -> Maybe a
Just (Value a1 -> TypeInfo -> Word32
forall {a}. Value a -> TypeInfo -> Word32
chooseLookedUpOid Value a1
valueDecoder TypeInfo
lookupResult)) (Value a1 -> ByteString -> Either Text a1
forall a. Value a -> ByteString -> Either Text a
Binary.valueParser Value a1
decoder)
        )
          (TypeInfo -> Value a1 -> RowDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo TypeInfo
-> ToBeResolved
     QualifiedTypeName TypeInfo (Value a1 -> RowDecoder a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QualifiedTypeName
-> ToBeResolved QualifiedTypeName TypeInfo TypeInfo
forall k v. k -> ToBeResolved k v v
ToBeResolved.lookup (Maybe Text -> Text -> QualifiedTypeName
CodecsVocab.QualifiedTypeName.QualifiedTypeName (Value a1 -> Maybe Text
forall a. Value a -> Maybe Text
Value.toSchema Value a1
valueDecoder) (Value a1 -> Text
forall a. Value a -> Text
Value.toTypeName Value a1
valueDecoder))
          ToBeResolved QualifiedTypeName TypeInfo (Value a1 -> RowDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo (Value a1)
-> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
forall a b.
ToBeResolved QualifiedTypeName TypeInfo (a -> b)
-> ToBeResolved QualifiedTypeName TypeInfo a
-> ToBeResolved QualifiedTypeName TypeInfo b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Value a1 -> ToBeResolved QualifiedTypeName TypeInfo (Value a1)
forall a.
Value a -> ToBeResolved QualifiedTypeName TypeInfo (Value a)
Value.toDecoder Value a1
valueDecoder
  NonNullable Value a
valueDecoder ->
    ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a) -> Row a
forall a.
ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a) -> Row a
Row case Value a -> Maybe Word32
forall a. Value a -> Maybe Word32
Value.toOid Value a
valueDecoder of
      Just Word32
oid ->
        (Value a -> RowDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo (Value a)
-> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder 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
          (Maybe Word32 -> (ByteString -> Either Text a) -> RowDecoder a
forall a.
Maybe Word32 -> (ByteString -> Either Text a) -> RowDecoder a
Hasql.Comms.RowDecoder.nonNullableColumn (Word32 -> Maybe Word32
forall a. a -> Maybe a
Just Word32
oid) ((ByteString -> Either Text a) -> RowDecoder a)
-> (Value a -> ByteString -> Either Text a)
-> Value a
-> RowDecoder a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Value a -> ByteString -> Either Text a
forall a. Value a -> ByteString -> Either Text a
Binary.valueParser)
          (Value a -> ToBeResolved QualifiedTypeName TypeInfo (Value a)
forall a.
Value a -> ToBeResolved QualifiedTypeName TypeInfo (Value a)
Value.toDecoder Value a
valueDecoder)
      Maybe Word32
Nothing ->
        (\TypeInfo
lookupResult Value a
decoder -> Maybe Word32 -> (ByteString -> Either Text a) -> RowDecoder a
forall a.
Maybe Word32 -> (ByteString -> Either Text a) -> RowDecoder a
Hasql.Comms.RowDecoder.nonNullableColumn (Word32 -> Maybe Word32
forall a. a -> Maybe a
Just (Value a -> TypeInfo -> Word32
forall {a}. Value a -> TypeInfo -> Word32
chooseLookedUpOid Value a
valueDecoder TypeInfo
lookupResult)) (Value a -> ByteString -> Either Text a
forall a. Value a -> ByteString -> Either Text a
Binary.valueParser Value a
decoder))
          (TypeInfo -> Value a -> RowDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo TypeInfo
-> ToBeResolved
     QualifiedTypeName TypeInfo (Value a -> RowDecoder a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QualifiedTypeName
-> ToBeResolved QualifiedTypeName TypeInfo TypeInfo
forall k v. k -> ToBeResolved k v v
ToBeResolved.lookup (Maybe Text -> Text -> QualifiedTypeName
CodecsVocab.QualifiedTypeName.QualifiedTypeName (Value a -> Maybe Text
forall a. Value a -> Maybe Text
Value.toSchema Value a
valueDecoder) (Value a -> Text
forall a. Value a -> Text
Value.toTypeName Value a
valueDecoder))
          ToBeResolved QualifiedTypeName TypeInfo (Value a -> RowDecoder a)
-> ToBeResolved QualifiedTypeName TypeInfo (Value a)
-> ToBeResolved QualifiedTypeName TypeInfo (RowDecoder a)
forall a b.
ToBeResolved QualifiedTypeName TypeInfo (a -> b)
-> ToBeResolved QualifiedTypeName TypeInfo a
-> ToBeResolved QualifiedTypeName TypeInfo b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Value a -> ToBeResolved QualifiedTypeName TypeInfo (Value a)
forall a.
Value a -> ToBeResolved QualifiedTypeName TypeInfo (Value a)
Value.toDecoder Value a
valueDecoder
  where
    chooseLookedUpOid :: Value a -> TypeInfo -> Word32
chooseLookedUpOid Value a
valueDecoder TypeInfo
typeInfo =
      if Value a -> Word
forall a. Value a -> Word
Value.toDimensionality Value a
valueDecoder Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
> Word
0
        then TypeInfo -> Word32
CodecsVocab.TypeInfo.toArrayOid TypeInfo
typeInfo
        else TypeInfo -> Word32
CodecsVocab.TypeInfo.toBaseOid TypeInfo
typeInfo