{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Hasql.Interpolate.Internal.EncodeRow
( EncodeRow (..),
GEncodeRow (..),
toTable,
)
where
import Control.Monad
import Data.Functor.Contravariant
import Data.List (intersperse)
import Data.Monoid
import GHC.Generics
import qualified Hasql.Encoders as E
import Hasql.Interpolate.Internal.EncodeRow.TH
import Hasql.Interpolate.Internal.Encoder
import Hasql.Interpolate.Internal.Sql
import Hasql.Interpolate.Internal.TH (addParam)
class EncodeRow a where
unzipWithEncoder :: (forall x. (a -> x -> x) -> x -> E.Params x -> Int -> r) -> r
default unzipWithEncoder ::
(Generic a, GEncodeRow (Rep a)) =>
(forall x. (a -> x -> x) -> x -> E.Params x -> Int -> r) ->
r
unzipWithEncoder forall x. (a -> x -> x) -> x -> Params x -> Int -> r
k = forall (a :: * -> *) p r.
GEncodeRow a =>
(forall x. (a p -> x -> x) -> x -> Params x -> Int -> r) -> r
gUnzipWithEncoder \Rep a Any -> x -> x
cons x
nil Params x
enc Int
fc ->
forall x. (a -> x -> x) -> x -> Params x -> Int -> r
k (Rep a Any -> x -> x
cons forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a x. Generic a => a -> Rep a x
from) x
nil Params x
enc Int
fc
{-# INLINE unzipWithEncoder #-}
class GEncodeRow a where
gUnzipWithEncoder :: (forall x. (a p -> x -> x) -> x -> E.Params x -> Int -> r) -> r
toTable :: EncodeRow a => [a] -> Sql
toTable :: forall a. EncodeRow a => [a] -> Sql
toTable [a]
xs = forall a r.
EncodeRow a =>
(forall x. (a -> x -> x) -> x -> Params x -> Int -> r) -> r
unzipWithEncoder \a -> x -> x
cons x
nil Params x
enc Int
i ->
let unzippedEncoder :: Params ()
unzippedEncoder = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> x -> x
cons x
nil [a]
xs forall (f :: * -> *) b a. Contravariant f => b -> f b -> f a
>$ Params x
enc
queryString :: StateT Int Identity Builder
queryString = forall {k} (f :: k -> *) (a :: k). Ap f a -> f a
getAp forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure Builder
"unnest(" forall a. Semigroup a => a -> a -> a
<> (forall a. Monoid a => [a] -> a
mconcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> [a] -> [a]
intersperse Builder
", " forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} (f :: k -> *) (a :: k). f a -> Ap f a
Ap (forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
i StateT Int Identity Builder
addParam)) forall a. Semigroup a => a -> a -> a
<> forall (f :: * -> *) a. Applicative f => a -> f a
pure Builder
")"
in StateT Int Identity Builder -> Params () -> Sql
Sql StateT Int Identity Builder
queryString Params ()
unzippedEncoder
{-# INLINE toTable #-}
instance GEncodeRow x => GEncodeRow (M1 t i x) where
gUnzipWithEncoder :: forall p r.
(forall x. (M1 t i x p -> x -> x) -> x -> Params x -> Int -> r)
-> r
gUnzipWithEncoder forall x. (M1 t i x p -> x -> x) -> x -> Params x -> Int -> r
k = forall (a :: * -> *) p r.
GEncodeRow a =>
(forall x. (a p -> x -> x) -> x -> Params x -> Int -> r) -> r
gUnzipWithEncoder \x p -> x -> x
cons x
nil Params x
enc Int
i ->
forall x. (M1 t i x p -> x -> x) -> x -> Params x -> Int -> r
k (\(M1 x p
a) -> x p -> x -> x
cons x p
a) x
nil Params x
enc Int
i
{-# INLINE gUnzipWithEncoder #-}
instance (GEncodeRow a, GEncodeRow b) => GEncodeRow (a :*: b) where
gUnzipWithEncoder :: forall p r.
(forall x. ((:*:) a b p -> x -> x) -> x -> Params x -> Int -> r)
-> r
gUnzipWithEncoder forall x. ((:*:) a b p -> x -> x) -> x -> Params x -> Int -> r
k = forall (a :: * -> *) p r.
GEncodeRow a =>
(forall x. (a p -> x -> x) -> x -> Params x -> Int -> r) -> r
gUnzipWithEncoder \a p -> x -> x
consa x
nila Params x
enca Int
ia -> forall (a :: * -> *) p r.
GEncodeRow a =>
(forall x. (a p -> x -> x) -> x -> Params x -> Int -> r) -> r
gUnzipWithEncoder \b p -> x -> x
consb x
nilb Params x
encb Int
ib ->
forall x. ((:*:) a b p -> x -> x) -> x -> Params x -> Int -> r
k
( \(a p
a :*: b p
b) ~(x
as, x
bs) ->
(a p -> x -> x
consa a p
a x
as, b p -> x -> x
consb b p
b x
bs)
)
(x
nila, x
nilb)
(forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap forall a b. (a, b) -> a
fst Params x
enca forall a. Semigroup a => a -> a -> a
<> forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap forall a b. (a, b) -> b
snd Params x
encb)
(Int
ia forall a. Num a => a -> a -> a
+ Int
ib)
{-# INLINE gUnzipWithEncoder #-}
instance EncodeField a => GEncodeRow (K1 i a) where
gUnzipWithEncoder :: forall p r.
(forall x. (K1 i a p -> x -> x) -> x -> Params x -> Int -> r) -> r
gUnzipWithEncoder forall x. (K1 i a p -> x -> x) -> x -> Params x -> Int -> r
k =
forall x. (K1 i a p -> x -> x) -> x -> Params x -> Int -> r
k (\(K1 a
a) [a]
b -> a
a forall a. a -> [a] -> [a]
: [a]
b) [] (forall a. NullableOrNot Value a -> Params a
E.param (forall (encoder :: * -> *) a. encoder a -> NullableOrNot encoder a
E.nonNullable (forall (foldable :: * -> *) element.
Foldable foldable =>
NullableOrNot Value element -> Value (foldable element)
E.foldableArray forall a. EncodeField a => NullableOrNot Value a
encodeField))) Int
1
{-# INLINE gUnzipWithEncoder #-}
$(traverse genEncodeRowInstance [2 .. 8])