module Hasql.Engine.Statement
( Statement (..),
preparable,
unpreparable,
refineResult,
toSql,
compilePreparedStatementData,
compileUnpreparedStatementData,
)
where
import Data.Text.Encoding qualified as TextEncoding
import Data.Vector qualified as Vector
import Hasql.Codecs.Encoders qualified as Encoders
import Hasql.Codecs.Encoders.Params qualified as Params
import Hasql.CodecsVocab qualified as CodecsVocab
import Hasql.CodecsVocab.TypeInfo qualified as CodecsVocab.TypeInfo
import Hasql.CodecsVocab.TypeRef qualified as CodecsVocab.TypeRef
import Hasql.CodecsVocab.TypeShape (TypeShape (..))
import Hasql.Comms.ResultDecoder qualified as ResultDecoder
import Hasql.Engine.Decoders.Result qualified as Decoders
import Hasql.Engine.Decoders.Result qualified as Decoders.Result
import Hasql.Platform.Prelude
data Statement params result
= Statement
{
forall params result. Statement params result -> ByteString
sql :: ByteString,
forall params result. Statement params result -> Vector TypeShape
columnsMetadata :: Vector TypeShape,
forall params result.
Statement params result
-> (QualifiedTypeName -> TypeInfo) -> params -> [Maybe ByteString]
serializer :: (CodecsVocab.QualifiedTypeName -> CodecsVocab.TypeInfo) -> params -> [Maybe ByteString],
forall params result. Statement params result -> params -> [Text]
printer :: params -> [Text],
forall params result.
Statement params result -> HashSet QualifiedTypeName
unknownTypes :: HashSet CodecsVocab.QualifiedTypeName,
forall params result.
Statement params result
-> (QualifiedTypeName -> TypeInfo) -> ResultDecoder result
decoder :: (CodecsVocab.QualifiedTypeName -> CodecsVocab.TypeInfo) -> ResultDecoder.ResultDecoder result,
forall params result. Statement params result -> Bool
isPrepared :: Bool
}
preparable ::
Text ->
Encoders.Params params ->
Decoders.Result result ->
Statement params result
preparable :: forall params result.
Text -> Params params -> Result result -> Statement params result
preparable Text
sqlText Params params
encoder Result result
resultDecoder =
Statement
{ sql :: ByteString
sql = Text -> ByteString
TextEncoding.encodeUtf8 Text
sqlText,
columnsMetadata :: Vector TypeShape
columnsMetadata = Params params -> Vector TypeShape
forall a. Params a -> Vector TypeShape
Params.toColumnsMetadata Params params
encoder,
serializer :: (QualifiedTypeName -> TypeInfo) -> params -> [Maybe ByteString]
serializer = Params params
-> (QualifiedTypeName -> TypeInfo) -> params -> [Maybe ByteString]
forall a.
Params a
-> (QualifiedTypeName -> TypeInfo) -> a -> [Maybe ByteString]
Params.toSerializer Params params
encoder,
printer :: params -> [Text]
printer = Params params -> params -> [Text]
forall a. Params a -> a -> [Text]
Params.toPrinter Params params
encoder,
unknownTypes :: HashSet QualifiedTypeName
unknownTypes = Params params -> HashSet QualifiedTypeName
forall a. Params a -> HashSet QualifiedTypeName
Params.toUnknownTypes Params params
encoder HashSet QualifiedTypeName
-> HashSet QualifiedTypeName -> HashSet QualifiedTypeName
forall a. Semigroup a => a -> a -> a
<> Result result -> HashSet QualifiedTypeName
forall a. Result a -> HashSet QualifiedTypeName
Decoders.Result.toUnknownTypes Result result
resultDecoder,
decoder :: (QualifiedTypeName -> TypeInfo) -> ResultDecoder result
decoder = Result result
-> (QualifiedTypeName -> TypeInfo) -> ResultDecoder result
forall a.
Result a -> (QualifiedTypeName -> TypeInfo) -> ResultDecoder a
Decoders.Result.toBase Result result
resultDecoder,
isPrepared :: Bool
isPrepared = Bool
True
}
unpreparable ::
Text ->
Encoders.Params params ->
Decoders.Result result ->
Statement params result
unpreparable :: forall params result.
Text -> Params params -> Result result -> Statement params result
unpreparable Text
sqlText Params params
encoder Result result
resultDecoder =
Statement
{ sql :: ByteString
sql = Text -> ByteString
TextEncoding.encodeUtf8 Text
sqlText,
columnsMetadata :: Vector TypeShape
columnsMetadata = Params params -> Vector TypeShape
forall a. Params a -> Vector TypeShape
Params.toColumnsMetadata Params params
encoder,
serializer :: (QualifiedTypeName -> TypeInfo) -> params -> [Maybe ByteString]
serializer = Params params
-> (QualifiedTypeName -> TypeInfo) -> params -> [Maybe ByteString]
forall a.
Params a
-> (QualifiedTypeName -> TypeInfo) -> a -> [Maybe ByteString]
Params.toSerializer Params params
encoder,
printer :: params -> [Text]
printer = Params params -> params -> [Text]
forall a. Params a -> a -> [Text]
Params.toPrinter Params params
encoder,
unknownTypes :: HashSet QualifiedTypeName
unknownTypes = Params params -> HashSet QualifiedTypeName
forall a. Params a -> HashSet QualifiedTypeName
Params.toUnknownTypes Params params
encoder HashSet QualifiedTypeName
-> HashSet QualifiedTypeName -> HashSet QualifiedTypeName
forall a. Semigroup a => a -> a -> a
<> Result result -> HashSet QualifiedTypeName
forall a. Result a -> HashSet QualifiedTypeName
Decoders.Result.toUnknownTypes Result result
resultDecoder,
decoder :: (QualifiedTypeName -> TypeInfo) -> ResultDecoder result
decoder = Result result
-> (QualifiedTypeName -> TypeInfo) -> ResultDecoder result
forall a.
Result a -> (QualifiedTypeName -> TypeInfo) -> ResultDecoder a
Decoders.Result.toBase Result result
resultDecoder,
isPrepared :: Bool
isPrepared = Bool
False
}
instance Functor (Statement params) where
{-# INLINE fmap #-}
fmap :: forall a b. (a -> b) -> Statement params a -> Statement params b
fmap a -> b
f Statement params a
stmt = Statement params a
stmt {decoder = fmap (fmap f) (decoder stmt)}
instance Filterable (Statement params) where
{-# INLINE mapMaybe #-}
mapMaybe :: forall a b.
(a -> Maybe b) -> Statement params a -> Statement params b
mapMaybe a -> Maybe b
filtrator Statement params a
stmt = Statement params a
stmt {decoder = fmap (mapMaybe filtrator) (decoder stmt)}
instance Profunctor Statement where
{-# INLINE dimap #-}
dimap :: forall a b c d.
(a -> b) -> (c -> d) -> Statement b c -> Statement a d
dimap a -> b
f1 c -> d
f2 Statement b c
stmt =
Statement b c
stmt
{ serializer = \QualifiedTypeName -> TypeInfo
resolve -> Statement b c
-> (QualifiedTypeName -> TypeInfo) -> b -> [Maybe ByteString]
forall params result.
Statement params result
-> (QualifiedTypeName -> TypeInfo) -> params -> [Maybe ByteString]
serializer Statement b c
stmt QualifiedTypeName -> TypeInfo
resolve (b -> [Maybe ByteString]) -> (a -> b) -> a -> [Maybe ByteString]
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
. a -> b
f1,
printer = printer stmt . f1,
decoder = fmap (fmap f2) (decoder stmt)
}
refineResult :: (a -> Either Text b) -> Statement params a -> Statement params b
refineResult :: forall a b params.
(a -> Either Text b) -> Statement params a -> Statement params b
refineResult a -> Either Text b
refiner Statement params a
stmt = Statement params a
stmt {decoder = fmap (ResultDecoder.refine refiner) (decoder stmt)}
toSql :: Statement params result -> Text
toSql :: forall params result. Statement params result -> Text
toSql Statement params result
stmt = ByteString -> Text
decodeUtf8Lenient (Statement params result -> ByteString
forall params result. Statement params result -> ByteString
sql Statement params result
stmt)
compilePreparedStatementData ::
Statement params result ->
(CodecsVocab.QualifiedTypeName -> CodecsVocab.TypeInfo) ->
params ->
([Word32], [Maybe (ByteString, Bool)])
compilePreparedStatementData :: forall params result.
Statement params result
-> (QualifiedTypeName -> TypeInfo)
-> params
-> ([Word32], [Maybe (ByteString, Bool)])
compilePreparedStatementData Statement params result
stmt QualifiedTypeName -> TypeInfo
resolve params
params =
[(Word32, Maybe (ByteString, Bool))]
-> ([Word32], [Maybe (ByteString, Bool)])
forall a b. [(a, b)] -> ([a], [b])
unzip
([(Word32, Maybe (ByteString, Bool))]
-> ([Word32], [Maybe (ByteString, Bool)]))
-> [(Word32, Maybe (ByteString, Bool))]
-> ([Word32], [Maybe (ByteString, Bool)])
forall a b. (a -> b) -> a -> b
$ (TypeShape
-> Maybe ByteString -> (Word32, Maybe (ByteString, Bool)))
-> [TypeShape]
-> [Maybe ByteString]
-> [(Word32, Maybe (ByteString, Bool))]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith
(\(TypeShape TypeRef
typeRef Word
dim Bool
fmt) Maybe ByteString
encoding -> ((QualifiedTypeName -> TypeInfo) -> TypeRef -> Word -> Word32
resolveOid QualifiedTypeName -> TypeInfo
resolve TypeRef
typeRef Word
dim, (ByteString -> (ByteString, Bool))
-> Maybe ByteString -> Maybe (ByteString, Bool)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (,Bool
fmt) Maybe ByteString
encoding))
(Vector TypeShape -> [TypeShape]
forall a. Vector a -> [a]
Vector.toList (Statement params result -> Vector TypeShape
forall params result. Statement params result -> Vector TypeShape
columnsMetadata Statement params result
stmt))
(Statement params result
-> (QualifiedTypeName -> TypeInfo) -> params -> [Maybe ByteString]
forall params result.
Statement params result
-> (QualifiedTypeName -> TypeInfo) -> params -> [Maybe ByteString]
serializer Statement params result
stmt QualifiedTypeName -> TypeInfo
resolve params
params)
compileUnpreparedStatementData ::
Statement params result ->
(CodecsVocab.QualifiedTypeName -> CodecsVocab.TypeInfo) ->
params ->
[Maybe (Word32, ByteString, Bool)]
compileUnpreparedStatementData :: forall params result.
Statement params result
-> (QualifiedTypeName -> TypeInfo)
-> params
-> [Maybe (Word32, ByteString, Bool)]
compileUnpreparedStatementData Statement params result
stmt QualifiedTypeName -> TypeInfo
resolve params
params =
(TypeShape -> Maybe ByteString -> Maybe (Word32, ByteString, Bool))
-> [TypeShape]
-> [Maybe ByteString]
-> [Maybe (Word32, ByteString, Bool)]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith
(\(TypeShape TypeRef
typeRef Word
dim Bool
fmt) Maybe ByteString
encoding -> (,,) (Word32 -> ByteString -> Bool -> (Word32, ByteString, Bool))
-> Maybe Word32
-> Maybe (ByteString -> Bool -> (Word32, ByteString, Bool))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word32 -> Maybe Word32
forall a. a -> Maybe a
Just ((QualifiedTypeName -> TypeInfo) -> TypeRef -> Word -> Word32
resolveOid QualifiedTypeName -> TypeInfo
resolve TypeRef
typeRef Word
dim) Maybe (ByteString -> Bool -> (Word32, ByteString, Bool))
-> Maybe ByteString -> Maybe (Bool -> (Word32, ByteString, Bool))
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe ByteString
encoding Maybe (Bool -> (Word32, ByteString, Bool))
-> Maybe Bool -> Maybe (Word32, ByteString, Bool)
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
fmt)
(Vector TypeShape -> [TypeShape]
forall a. Vector a -> [a]
Vector.toList (Statement params result -> Vector TypeShape
forall params result. Statement params result -> Vector TypeShape
columnsMetadata Statement params result
stmt))
(Statement params result
-> (QualifiedTypeName -> TypeInfo) -> params -> [Maybe ByteString]
forall params result.
Statement params result
-> (QualifiedTypeName -> TypeInfo) -> params -> [Maybe ByteString]
serializer Statement params result
stmt QualifiedTypeName -> TypeInfo
resolve params
params)
resolveOid :: (CodecsVocab.QualifiedTypeName -> CodecsVocab.TypeInfo) -> CodecsVocab.TypeRef.TypeRef -> Word -> Word32
resolveOid :: (QualifiedTypeName -> TypeInfo) -> TypeRef -> Word -> Word32
resolveOid QualifiedTypeName -> TypeInfo
resolve (CodecsVocab.TypeRef.NamedType QualifiedTypeName
name) Word
dim =
(if Word
dim Word -> Word -> Bool
forall a. Eq a => a -> a -> Bool
== Word
0 then TypeInfo -> Word32
CodecsVocab.TypeInfo.toBaseOid else TypeInfo -> Word32
CodecsVocab.TypeInfo.toArrayOid) (QualifiedTypeName -> TypeInfo
resolve QualifiedTypeName
name)
resolveOid QualifiedTypeName -> TypeInfo
_ (CodecsVocab.TypeRef.KnownOid Word32
oid) Word
_ = Word32
oid