-- | Backend-neutral parameters as Hasql encoders.
module Arbiter.Hasql.Encode
  ( buildEncoder
  ) where

import Arbiter.Core.MonadArbiter (Col (..), ParamType (..), Params, SomeParam (..), storedBytes)
import Data.Functor.Contravariant (contramap)
import Hasql.Encoders qualified as E

-- | A parameter list as one positional encoder.
buildEncoder :: Params -> E.Params ()
buildEncoder :: Params -> Params ()
buildEncoder = (SomeParam -> Params ()) -> Params -> Params ()
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap SomeParam -> Params ()
encodeSomeParam

-- | Encode one parameter at its declared nullability.
encodeSomeParam :: SomeParam -> E.Params ()
encodeSomeParam :: SomeParam -> Params ()
encodeSomeParam (SomeParam ParamType a
paramType a
value) = (() -> a) -> Params a -> Params ()
forall a' a. (a' -> a) -> Params a -> Params a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap (a -> () -> a
forall a b. a -> b -> a
const a
value) (NullableOrNot Value a -> Params a
forall a. NullableOrNot Value a -> Params a
E.param (ParamType a -> NullableOrNot Value a
forall a. ParamType a -> NullableOrNot Value a
paramEncoder ParamType a
paramType))

paramEncoder :: ParamType a -> E.NullableOrNot E.Value a
paramEncoder :: forall a. ParamType a -> NullableOrNot Value a
paramEncoder (PScalar Col a
col) = Value a -> NullableOrNot Value a
forall (encoder :: * -> *) a. encoder a -> NullableOrNot encoder a
E.nonNullable (Col a -> Value a
forall a. Col a -> Value a
colEncoder Col a
col)
paramEncoder (PNullable Col a1
col) = Value a1 -> NullableOrNot Value (Maybe a1)
forall (encoder :: * -> *) a.
encoder a -> NullableOrNot encoder (Maybe a)
E.nullable (Col a1 -> Value a1
forall a. Col a -> Value a
colEncoder Col a1
col)
paramEncoder (PArray Col a1
col) = Value a -> NullableOrNot Value a
forall (encoder :: * -> *) a. encoder a -> NullableOrNot encoder a
E.nonNullable (Array a -> Value a
forall a. Array a -> Value a
E.array ((forall a. (a -> a1 -> a) -> a -> a -> a) -> Array a1 -> Array a
forall b c.
(forall a. (a -> b -> a) -> a -> c -> a) -> Array b -> Array c
E.dimension (a -> a1 -> a) -> a -> a -> a
(a -> a1 -> a) -> a -> [a1] -> a
forall a. (a -> a1 -> a) -> a -> a -> a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (NullableOrNot Value a1 -> Array a1
forall a. NullableOrNot Value a -> Array a
E.element (Value a1 -> NullableOrNot Value a1
forall (encoder :: * -> *) a. encoder a -> NullableOrNot encoder a
E.nonNullable (Col a1 -> Value a1
forall a. Col a -> Value a
colEncoder Col a1
col)))))
paramEncoder (PNullArray Col a1
col) = Value a -> NullableOrNot Value a
forall (encoder :: * -> *) a. encoder a -> NullableOrNot encoder a
E.nonNullable (Array a -> Value a
forall a. Array a -> Value a
E.array ((forall a. (a -> Maybe a1 -> a) -> a -> a -> a)
-> Array (Maybe a1) -> Array a
forall b c.
(forall a. (a -> b -> a) -> a -> c -> a) -> Array b -> Array c
E.dimension (a -> Maybe a1 -> a) -> a -> a -> a
(a -> Maybe a1 -> a) -> a -> [Maybe a1] -> a
forall a. (a -> Maybe a1 -> a) -> a -> a -> a
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (NullableOrNot Value (Maybe a1) -> Array (Maybe a1)
forall a. NullableOrNot Value a -> Array a
E.element (Value a1 -> NullableOrNot Value (Maybe a1)
forall (encoder :: * -> *) a.
encoder a -> NullableOrNot encoder (Maybe a)
E.nullable (Col a1 -> Value a1
forall a. Col a -> Value a
colEncoder Col a1
col)))))

-- | Encoder for a column type.
colEncoder :: Col a -> E.Value a
colEncoder :: forall a. Col a -> Value a
colEncoder Col a
CInt4 = Value a
Value Int32
E.int4
colEncoder Col a
CInt8 = Value a
Value Int64
E.int8
colEncoder Col a
CText = Value a
Value Text
E.text
colEncoder Col a
CBool = Value a
Value Bool
E.bool
colEncoder Col a
CTimestamptz = Value a
Value UTCTime
E.timestamptz
colEncoder Col a
CJsonb = Value a
Value Value
E.jsonb
colEncoder Col a
CStored = (a -> ByteString) -> Value ByteString -> Value a
forall a' a. (a' -> a) -> Value a -> Value a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap a -> ByteString
Stored payload -> ByteString
forall payload. Stored payload -> ByteString
storedBytes Value ByteString
E.jsonbBytes
colEncoder Col a
CFloat8 = Value a
Value Double
E.float8
colEncoder Col a
CUuid = Value a
Value UUID
E.uuid