{-# LANGUAGE AllowAmbiguousTypes, ScopedTypeVariables, TypeApplications, DataKinds, TypeFamilies, PolyKinds, ConstraintKinds, TypeOperators, BangPatterns, FlexibleContexts #-}
module IHP.Fetch.Statement
( buildQueryListStatement
, buildQueryVectorStatement
, buildQueryMaybeStatement
, buildCountStatement
, buildExistsStatement
) where
import Prelude
import IHP.ModelSupport (Table(..), GetModelByTableName)
import IHP.Hasql.FromRow (FromRowHasql(..))
import qualified Hasql.Statement as Hasql
import qualified Hasql.Decoders as Decoders
import IHP.QueryBuilder.Types (QueryBuilder(..), SQLQuery(..))
import IHP.QueryBuilder.Compiler (buildQuery)
import IHP.QueryBuilder.HasqlCompiler (buildStatement, buildWrappedStatement)
import GHC.TypeLits (KnownSymbol)
import Data.Int (Int64)
import Data.Vector (Vector)
buildQueryListStatement :: forall model table.
( Table model
, model ~ GetModelByTableName table, KnownSymbol table, FromRowHasql model
) => QueryBuilder table -> Hasql.Statement () [model]
buildQueryListStatement :: forall model (table :: Symbol).
(Table model, model ~ GetModelByTableName table, KnownSymbol table,
FromRowHasql model) =>
QueryBuilder table -> Statement () [model]
buildQueryListStatement !QueryBuilder table
queryBuilder =
SQLQuery -> Result [model] -> Statement () [model]
forall a. SQLQuery -> Result a -> Statement () a
buildStatement (QueryBuilder table -> SQLQuery
forall (table :: Symbol).
KnownSymbol table =>
QueryBuilder table -> SQLQuery
buildQuery QueryBuilder table
queryBuilder) (Row model -> Result [model]
forall a. Row a -> Result [a]
Decoders.rowList (forall a. FromRowHasql a => Row a
hasqlRowDecoder @model))
buildQueryVectorStatement :: forall model table.
( Table model
, model ~ GetModelByTableName table, KnownSymbol table, FromRowHasql model
) => QueryBuilder table -> Hasql.Statement () (Vector model)
buildQueryVectorStatement :: forall model (table :: Symbol).
(Table model, model ~ GetModelByTableName table, KnownSymbol table,
FromRowHasql model) =>
QueryBuilder table -> Statement () (Vector model)
buildQueryVectorStatement !QueryBuilder table
queryBuilder =
SQLQuery -> Result (Vector model) -> Statement () (Vector model)
forall a. SQLQuery -> Result a -> Statement () a
buildStatement (QueryBuilder table -> SQLQuery
forall (table :: Symbol).
KnownSymbol table =>
QueryBuilder table -> SQLQuery
buildQuery QueryBuilder table
queryBuilder) (Row model -> Result (Vector model)
forall a. Row a -> Result (Vector a)
Decoders.rowVector (forall a. FromRowHasql a => Row a
hasqlRowDecoder @model))
buildQueryMaybeStatement :: forall model table.
( Table model
, model ~ GetModelByTableName table, KnownSymbol table, FromRowHasql model
) => QueryBuilder table -> Hasql.Statement () (Maybe model)
buildQueryMaybeStatement :: forall model (table :: Symbol).
(Table model, model ~ GetModelByTableName table, KnownSymbol table,
FromRowHasql model) =>
QueryBuilder table -> Statement () (Maybe model)
buildQueryMaybeStatement !QueryBuilder table
queryBuilder =
SQLQuery -> Result (Maybe model) -> Statement () (Maybe model)
forall a. SQLQuery -> Result a -> Statement () a
buildStatement ((QueryBuilder table -> SQLQuery
forall (table :: Symbol).
KnownSymbol table =>
QueryBuilder table -> SQLQuery
buildQuery QueryBuilder table
queryBuilder) { limitClause = Just 1 }) (Row model -> Result (Maybe model)
forall a. Row a -> Result (Maybe a)
Decoders.rowMaybe (forall a. FromRowHasql a => Row a
hasqlRowDecoder @model))
buildCountStatement :: forall table.
( KnownSymbol table
) => QueryBuilder table -> Hasql.Statement () Int64
buildCountStatement :: forall (table :: Symbol).
KnownSymbol table =>
QueryBuilder table -> Statement () Int64
buildCountStatement !QueryBuilder table
queryBuilder =
Text -> SQLQuery -> Text -> Result Int64 -> Statement () Int64
forall a. Text -> SQLQuery -> Text -> Result a -> Statement () a
buildWrappedStatement Text
"SELECT COUNT(*) FROM (" (QueryBuilder table -> SQLQuery
forall (table :: Symbol).
KnownSymbol table =>
QueryBuilder table -> SQLQuery
buildQuery QueryBuilder table
queryBuilder) Text
") AS _count_values" (Row Int64 -> Result Int64
forall a. Row a -> Result a
Decoders.singleRow (NullableOrNot Value Int64 -> Row Int64
forall a. NullableOrNot Value a -> Row a
Decoders.column (Value Int64 -> NullableOrNot Value Int64
forall (decoder :: * -> *) a. decoder a -> NullableOrNot decoder a
Decoders.nonNullable Value Int64
Decoders.int8)))
buildExistsStatement :: forall table.
( KnownSymbol table
) => QueryBuilder table -> Hasql.Statement () Bool
buildExistsStatement :: forall (table :: Symbol).
KnownSymbol table =>
QueryBuilder table -> Statement () Bool
buildExistsStatement !QueryBuilder table
queryBuilder =
Text -> SQLQuery -> Text -> Result Bool -> Statement () Bool
forall a. Text -> SQLQuery -> Text -> Result a -> Statement () a
buildWrappedStatement Text
"SELECT EXISTS (" (QueryBuilder table -> SQLQuery
forall (table :: Symbol).
KnownSymbol table =>
QueryBuilder table -> SQLQuery
buildQuery QueryBuilder table
queryBuilder) Text
") AS _exists_values" (Row Bool -> Result Bool
forall a. Row a -> Result a
Decoders.singleRow (NullableOrNot Value Bool -> Row Bool
forall a. NullableOrNot Value a -> Row a
Decoders.column (Value Bool -> NullableOrNot Value Bool
forall (decoder :: * -> *) a. decoder a -> NullableOrNot decoder a
Decoders.nonNullable Value Bool
Decoders.bool)))