-- | Postgres Translate Returning
--
-- Combinators and helpers for dealing with GraphQL returning statements.
module Hasura.Backends.Postgres.Translate.Returning
  ( MutationCTE (..),
    getMutationCTE,
    checkPermissionRequired,
    mkMutFldExp,
    mkDefaultMutFlds,
    mkCheckErrorExp,
    mkMutationOutputExp,
    checkConstraintIdentifier,
    asCheckErrorExtractor,
  )
where

import Data.Coerce
import Hasura.Backends.Postgres.SQL.DML qualified as S
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Backends.Postgres.Translate.Select
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.GraphQL.Schema.Options qualified as Options
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.IR.Returning
import Hasura.RQL.IR.Select
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Table
import Hasura.SQL.Backend

-- | The postgres common table expression (CTE) for mutation queries.
-- This CTE expression is used to generate mutation field output expression,
-- see Note [Mutation output expression].
data MutationCTE
  = -- | A Mutation with check constraint validation (Insert or Update)
    MCCheckConstraint S.TopLevelCTE
  | -- | A Select statement which emits mutated table rows
    MCSelectValues S.Select
  | -- | A Delete statement
    MCDelete S.SQLDelete
  deriving (Int -> MutationCTE -> ShowS
[MutationCTE] -> ShowS
MutationCTE -> String
(Int -> MutationCTE -> ShowS)
-> (MutationCTE -> String)
-> ([MutationCTE] -> ShowS)
-> Show MutationCTE
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MutationCTE] -> ShowS
$cshowList :: [MutationCTE] -> ShowS
show :: MutationCTE -> String
$cshow :: MutationCTE -> String
showsPrec :: Int -> MutationCTE -> ShowS
$cshowsPrec :: Int -> MutationCTE -> ShowS
Show, MutationCTE -> MutationCTE -> Bool
(MutationCTE -> MutationCTE -> Bool)
-> (MutationCTE -> MutationCTE -> Bool) -> Eq MutationCTE
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MutationCTE -> MutationCTE -> Bool
$c/= :: MutationCTE -> MutationCTE -> Bool
== :: MutationCTE -> MutationCTE -> Bool
$c== :: MutationCTE -> MutationCTE -> Bool
Eq)

getMutationCTE :: MutationCTE -> S.TopLevelCTE
getMutationCTE :: MutationCTE -> TopLevelCTE
getMutationCTE = \case
  MCCheckConstraint TopLevelCTE
cte -> TopLevelCTE
cte
  MCSelectValues Select
select -> Select -> TopLevelCTE
S.CTESelect Select
select
  MCDelete SQLDelete
delete -> SQLDelete -> TopLevelCTE
S.CTEDelete SQLDelete
delete

checkPermissionRequired :: MutationCTE -> Bool
checkPermissionRequired :: MutationCTE -> Bool
checkPermissionRequired = \case
  MCCheckConstraint TopLevelCTE
_ -> Bool
True
  MCSelectValues Select
_ -> Bool
False
  MCDelete SQLDelete
_ -> Bool
False

pgColsToSelFlds ::
  forall pgKind.
  Backend ('Postgres pgKind) =>
  [ColumnInfo ('Postgres pgKind)] ->
  [(FieldName, AnnField ('Postgres pgKind))]
pgColsToSelFlds :: [ColumnInfo ('Postgres pgKind)]
-> [(FieldName, AnnField ('Postgres pgKind))]
pgColsToSelFlds [ColumnInfo ('Postgres pgKind)]
cols =
  ((ColumnInfo ('Postgres pgKind)
  -> (FieldName, AnnFieldG ('Postgres pgKind) Void SQLExp))
 -> [ColumnInfo ('Postgres pgKind)]
 -> [(FieldName, AnnFieldG ('Postgres pgKind) Void SQLExp)])
-> [ColumnInfo ('Postgres pgKind)]
-> (ColumnInfo ('Postgres pgKind)
    -> (FieldName, AnnFieldG ('Postgres pgKind) Void SQLExp))
-> [(FieldName, AnnFieldG ('Postgres pgKind) Void SQLExp)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (ColumnInfo ('Postgres pgKind)
 -> (FieldName, AnnFieldG ('Postgres pgKind) Void SQLExp))
-> [ColumnInfo ('Postgres pgKind)]
-> [(FieldName, AnnFieldG ('Postgres pgKind) Void SQLExp)]
forall a b. (a -> b) -> [a] -> [b]
map [ColumnInfo ('Postgres pgKind)]
cols ((ColumnInfo ('Postgres pgKind)
  -> (FieldName, AnnFieldG ('Postgres pgKind) Void SQLExp))
 -> [(FieldName, AnnFieldG ('Postgres pgKind) Void SQLExp)])
-> (ColumnInfo ('Postgres pgKind)
    -> (FieldName, AnnFieldG ('Postgres pgKind) Void SQLExp))
-> [(FieldName, AnnFieldG ('Postgres pgKind) Void SQLExp)]
forall a b. (a -> b) -> a -> b
$
    \ColumnInfo ('Postgres pgKind)
pgColInfo ->
      ( Backend ('Postgres pgKind) =>
Column ('Postgres pgKind) -> FieldName
forall (b :: BackendType). Backend b => Column b -> FieldName
fromCol @('Postgres pgKind) (Column ('Postgres pgKind) -> FieldName)
-> Column ('Postgres pgKind) -> FieldName
forall a b. (a -> b) -> a -> b
$ ColumnInfo ('Postgres pgKind) -> Column ('Postgres pgKind)
forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn ColumnInfo ('Postgres pgKind)
pgColInfo,
        Column ('Postgres pgKind)
-> ColumnType ('Postgres pgKind)
-> Maybe (AnnColumnCaseBoolExp ('Postgres pgKind) SQLExp)
-> Maybe (ScalarSelectionArguments ('Postgres pgKind))
-> AnnFieldG ('Postgres pgKind) Void SQLExp
forall (backend :: BackendType) v r.
Column backend
-> ColumnType backend
-> Maybe (AnnColumnCaseBoolExp backend v)
-> Maybe (ScalarSelectionArguments backend)
-> AnnFieldG backend r v
mkAnnColumnField (ColumnInfo ('Postgres pgKind) -> Column ('Postgres pgKind)
forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn ColumnInfo ('Postgres pgKind)
pgColInfo) (ColumnInfo ('Postgres pgKind) -> ColumnType ('Postgres pgKind)
forall (b :: BackendType). ColumnInfo b -> ColumnType b
ciType ColumnInfo ('Postgres pgKind)
pgColInfo) Maybe (AnnColumnCaseBoolExp ('Postgres pgKind) SQLExp)
forall a. Maybe a
Nothing Maybe (ScalarSelectionArguments ('Postgres pgKind))
forall a. Maybe a
Nothing
        --  ^^ Nothing because mutations aren't supported
        --  with inherited role
      )

mkDefaultMutFlds ::
  Backend ('Postgres pgKind) =>
  Maybe [ColumnInfo ('Postgres pgKind)] ->
  MutationOutput ('Postgres pgKind)
mkDefaultMutFlds :: Maybe [ColumnInfo ('Postgres pgKind)]
-> MutationOutput ('Postgres pgKind)
mkDefaultMutFlds =
  MutFldsG ('Postgres pgKind) Void SQLExp
-> MutationOutputG ('Postgres pgKind) Void SQLExp
forall (b :: BackendType) r v.
MutFldsG b r v -> MutationOutputG b r v
MOutMultirowFields (MutFldsG ('Postgres pgKind) Void SQLExp
 -> MutationOutputG ('Postgres pgKind) Void SQLExp)
-> (Maybe [ColumnInfo ('Postgres pgKind)]
    -> MutFldsG ('Postgres pgKind) Void SQLExp)
-> Maybe [ColumnInfo ('Postgres pgKind)]
-> MutationOutputG ('Postgres pgKind) Void SQLExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
    Maybe [ColumnInfo ('Postgres pgKind)]
Nothing -> MutFldsG ('Postgres pgKind) Void SQLExp
forall (b :: BackendType) r v. [(FieldName, MutFldG b r v)]
mutFlds
    Just [ColumnInfo ('Postgres pgKind)]
cols -> (FieldName
"returning", AnnFieldsG ('Postgres pgKind) Void SQLExp
-> MutFldG ('Postgres pgKind) Void SQLExp
forall (b :: BackendType) r v. AnnFieldsG b r v -> MutFldG b r v
MRet (AnnFieldsG ('Postgres pgKind) Void SQLExp
 -> MutFldG ('Postgres pgKind) Void SQLExp)
-> AnnFieldsG ('Postgres pgKind) Void SQLExp
-> MutFldG ('Postgres pgKind) Void SQLExp
forall a b. (a -> b) -> a -> b
$ [ColumnInfo ('Postgres pgKind)]
-> [(FieldName, AnnField ('Postgres pgKind))]
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
[ColumnInfo ('Postgres pgKind)]
-> [(FieldName, AnnField ('Postgres pgKind))]
pgColsToSelFlds [ColumnInfo ('Postgres pgKind)]
cols) (FieldName, MutFldG ('Postgres pgKind) Void SQLExp)
-> MutFldsG ('Postgres pgKind) Void SQLExp
-> MutFldsG ('Postgres pgKind) Void SQLExp
forall a. a -> [a] -> [a]
: MutFldsG ('Postgres pgKind) Void SQLExp
forall (b :: BackendType) r v. [(FieldName, MutFldG b r v)]
mutFlds
  where
    mutFlds :: [(FieldName, MutFldG b r v)]
mutFlds = [(FieldName
"affected_rows", MutFldG b r v
forall (b :: BackendType) r v. MutFldG b r v
MCount)]

mkMutFldExp ::
  ( Backend ('Postgres pgKind),
    PostgresAnnotatedFieldJSON pgKind
  ) =>
  Identifier ->
  Maybe Int ->
  Options.StringifyNumbers ->
  Maybe NamingCase ->
  MutFld ('Postgres pgKind) ->
  S.SQLExp
mkMutFldExp :: Identifier
-> Maybe Int
-> StringifyNumbers
-> Maybe NamingCase
-> MutFld ('Postgres pgKind)
-> SQLExp
mkMutFldExp Identifier
cteAlias Maybe Int
preCalAffRows StringifyNumbers
strfyNum Maybe NamingCase
tCase = \case
  MutFld ('Postgres pgKind)
MCount ->
    let countExp :: SQLExp
countExp =
          Select -> SQLExp
S.SESelect (Select -> SQLExp) -> Select -> SQLExp
forall a b. (a -> b) -> a -> b
$
            Select
S.mkSelect
              { selExtr :: [Extractor]
S.selExtr = [SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
S.countStar Maybe ColumnAlias
forall a. Maybe a
Nothing],
                selFrom :: Maybe FromExp
S.selFrom = FromExp -> Maybe FromExp
forall a. a -> Maybe a
Just (FromExp -> Maybe FromExp) -> FromExp -> Maybe FromExp
forall a b. (a -> b) -> a -> b
$ [FromItem] -> FromExp
S.FromExp ([FromItem] -> FromExp) -> [FromItem] -> FromExp
forall a b. (a -> b) -> a -> b
$ FromItem -> [FromItem]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FromItem -> [FromItem]) -> FromItem -> [FromItem]
forall a b. (a -> b) -> a -> b
$ Identifier -> FromItem
S.FIIdentifier Identifier
cteAlias
              }
     in SQLExp -> (Int -> SQLExp) -> Maybe Int -> SQLExp
forall b a. b -> (a -> b) -> Maybe a -> b
maybe SQLExp
countExp (Text -> SQLExp
S.SEUnsafe (Text -> SQLExp) -> (Int -> Text) -> Int -> SQLExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text
forall a. Show a => a -> Text
tshow) Maybe Int
preCalAffRows
  MExp Text
t -> Text -> SQLExp
S.SELit Text
t
  MRet AnnFieldsG
  ('Postgres pgKind) Void (SQLExpression ('Postgres pgKind))
selFlds ->
    let tabFrom :: SelectFromG ('Postgres pgKind) SQLExp
tabFrom = FIIdentifier -> SelectFromG ('Postgres pgKind) SQLExp
forall (b :: BackendType) v. FIIdentifier -> SelectFromG b v
FromIdentifier (FIIdentifier -> SelectFromG ('Postgres pgKind) SQLExp)
-> FIIdentifier -> SelectFromG ('Postgres pgKind) SQLExp
forall a b. (a -> b) -> a -> b
$ Identifier -> FIIdentifier
toFIIdentifier Identifier
cteAlias
        tabPerm :: TablePermG b v
tabPerm = AnnBoolExp b v -> Maybe Int -> TablePermG b v
forall (b :: BackendType) v.
AnnBoolExp b v -> Maybe Int -> TablePermG b v
TablePerm AnnBoolExp b v
forall (backend :: BackendType) scalar. AnnBoolExp backend scalar
annBoolExpTrue Maybe Int
forall a. Maybe a
Nothing
     in Select -> SQLExp
S.SESelect (Select -> SQLExp) -> Select -> SQLExp
forall a b. (a -> b) -> a -> b
$
          JsonAggSelect -> AnnSimpleSelect ('Postgres pgKind) -> Select
forall (pgKind :: PostgresKind).
(Backend ('Postgres pgKind), PostgresAnnotatedFieldJSON pgKind) =>
JsonAggSelect -> AnnSimpleSelect ('Postgres pgKind) -> Select
mkSQLSelect JsonAggSelect
JASMultipleRows (AnnSimpleSelect ('Postgres pgKind) -> Select)
-> AnnSimpleSelect ('Postgres pgKind) -> Select
forall a b. (a -> b) -> a -> b
$
            Fields (AnnFieldG ('Postgres pgKind) Void SQLExp)
-> SelectFromG ('Postgres pgKind) SQLExp
-> TablePermG ('Postgres pgKind) SQLExp
-> SelectArgsG ('Postgres pgKind) SQLExp
-> StringifyNumbers
-> Maybe NamingCase
-> AnnSelectG
     ('Postgres pgKind) (AnnFieldG ('Postgres pgKind) Void) SQLExp
forall (b :: BackendType) (f :: * -> *) v.
Fields (f v)
-> SelectFromG b v
-> TablePermG b v
-> SelectArgsG b v
-> StringifyNumbers
-> Maybe NamingCase
-> AnnSelectG b f v
AnnSelectG AnnFieldsG
  ('Postgres pgKind) Void (SQLExpression ('Postgres pgKind))
Fields (AnnFieldG ('Postgres pgKind) Void SQLExp)
selFlds SelectFromG ('Postgres pgKind) SQLExp
tabFrom TablePermG ('Postgres pgKind) SQLExp
forall (b :: BackendType) v. TablePermG b v
tabPerm SelectArgsG ('Postgres pgKind) SQLExp
forall (backend :: BackendType) v. SelectArgsG backend v
noSelectArgs StringifyNumbers
strfyNum Maybe NamingCase
tCase

toFIIdentifier :: Identifier -> FIIdentifier
toFIIdentifier :: Identifier -> FIIdentifier
toFIIdentifier = Text -> FIIdentifier
coerce (Text -> FIIdentifier)
-> (Identifier -> Text) -> Identifier -> FIIdentifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identifier -> Text
getIdenTxt
{-# INLINE toFIIdentifier #-}

{- Note [Mutation output expression]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An example output expression for INSERT mutation:

WITH "mra__<table-name>" AS (
  INSERT INTO <table-name> (<insert-column>[..])
  VALUES
    (<insert-value-row>[..])
    ON CONFLICT ON CONSTRAINT "<table-constraint-name>" DO NOTHING RETURNING *,
    -- An extra column expression which performs the 'CHECK' validation
    (<CHECK Condition>) AS "check__constraint"
),
"aca__<table-name>" AS (
  -- Only extract columns from mutated rows. Columns sorted by ordinal position so that
  -- resulted rows can be casted to table type.
  SELECT (<table-column>[..])
  FROM
    "mra__<table-name>"
)
<SELECT statement to generate mutation response using 'aca__<table-name>' as FROM
 and bool_and("check__constraint") from "mra__<table-name>">
-}

-- | Generate mutation output expression with given mutation CTE statement.
-- See Note [Mutation output expression].
mkMutationOutputExp ::
  ( Backend ('Postgres pgKind),
    PostgresAnnotatedFieldJSON pgKind
  ) =>
  QualifiedTable ->
  [ColumnInfo ('Postgres pgKind)] ->
  Maybe Int ->
  MutationCTE ->
  MutationOutput ('Postgres pgKind) ->
  Options.StringifyNumbers ->
  Maybe NamingCase ->
  S.SelectWith
mkMutationOutputExp :: QualifiedTable
-> [ColumnInfo ('Postgres pgKind)]
-> Maybe Int
-> MutationCTE
-> MutationOutput ('Postgres pgKind)
-> StringifyNumbers
-> Maybe NamingCase
-> SelectWith
mkMutationOutputExp QualifiedTable
qt [ColumnInfo ('Postgres pgKind)]
allCols Maybe Int
preCalAffRows MutationCTE
cte MutationOutput ('Postgres pgKind)
mutOutput StringifyNumbers
strfyNum Maybe NamingCase
tCase =
  [(TableAlias, TopLevelCTE)] -> Select -> SelectWith
forall statement.
[(TableAlias, statement)] -> Select -> SelectWithG statement
S.SelectWith
    [ (Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias Identifier
mutationResultAlias, MutationCTE -> TopLevelCTE
getMutationCTE MutationCTE
cte),
      (Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias Identifier
allColumnsAlias, TopLevelCTE
allColumnsSelect)
    ]
    Select
sel
  where
    mutationResultAlias :: Identifier
mutationResultAlias = Text -> Identifier
Identifier (Text -> Identifier) -> Text -> Identifier
forall a b. (a -> b) -> a -> b
$ Text
"mra__" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> QualifiedTable -> Text
forall a. ToTxt a => QualifiedObject a -> Text
snakeCaseQualifiedObject QualifiedTable
qt
    allColumnsAlias :: Identifier
allColumnsAlias = Text -> Identifier
Identifier (Text -> Identifier) -> Text -> Identifier
forall a b. (a -> b) -> a -> b
$ Text
"aca__" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> QualifiedTable -> Text
forall a. ToTxt a => QualifiedObject a -> Text
snakeCaseQualifiedObject QualifiedTable
qt
    allColumnsSelect :: TopLevelCTE
allColumnsSelect =
      Select -> TopLevelCTE
S.CTESelect (Select -> TopLevelCTE) -> Select -> TopLevelCTE
forall a b. (a -> b) -> a -> b
$
        Select
S.mkSelect
          { selExtr :: [Extractor]
S.selExtr = (ColumnInfo ('Postgres pgKind) -> Extractor)
-> [ColumnInfo ('Postgres pgKind)] -> [Extractor]
forall a b. (a -> b) -> [a] -> [b]
map (PGCol -> Extractor
forall a. IsIdentifier a => a -> Extractor
S.mkExtr (PGCol -> Extractor)
-> (ColumnInfo ('Postgres pgKind) -> PGCol)
-> ColumnInfo ('Postgres pgKind)
-> Extractor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ColumnInfo ('Postgres pgKind) -> PGCol
forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn) ([ColumnInfo ('Postgres pgKind)] -> [ColumnInfo ('Postgres pgKind)]
forall (backend :: BackendType).
[ColumnInfo backend] -> [ColumnInfo backend]
sortCols [ColumnInfo ('Postgres pgKind)]
allCols),
            selFrom :: Maybe FromExp
S.selFrom = FromExp -> Maybe FromExp
forall a. a -> Maybe a
Just (FromExp -> Maybe FromExp) -> FromExp -> Maybe FromExp
forall a b. (a -> b) -> a -> b
$ Identifier -> FromExp
forall a. IsIdentifier a => a -> FromExp
S.mkIdenFromExp Identifier
mutationResultAlias
          }

    sel :: Select
sel =
      Select
S.mkSelect
        { selExtr :: [Extractor]
S.selExtr =
            SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
extrExp Maybe ColumnAlias
forall a. Maybe a
Nothing Extractor -> [Extractor] -> [Extractor]
forall a. a -> [a] -> [a]
:
            [Extractor] -> [Extractor] -> Bool -> [Extractor]
forall a. a -> a -> Bool -> a
bool [] [SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
checkErrorExp Maybe ColumnAlias
forall a. Maybe a
Nothing] (MutationCTE -> Bool
checkPermissionRequired MutationCTE
cte)
        }
      where
        checkErrorExp :: SQLExp
checkErrorExp = Identifier -> SQLExp
forall a. IsIdentifier a => a -> SQLExp
mkCheckErrorExp Identifier
mutationResultAlias
        extrExp :: SQLExp
extrExp = case MutationOutput ('Postgres pgKind)
mutOutput of
          MOutMultirowFields MutFldsG ('Postgres pgKind) Void (SQLExpression ('Postgres pgKind))
mutFlds ->
            let jsonBuildObjArgs :: [SQLExp]
jsonBuildObjArgs = (((FieldName, MutFldG ('Postgres pgKind) Void SQLExp) -> [SQLExp])
 -> [(FieldName, MutFldG ('Postgres pgKind) Void SQLExp)]
 -> [SQLExp])
-> [(FieldName, MutFldG ('Postgres pgKind) Void SQLExp)]
-> ((FieldName, MutFldG ('Postgres pgKind) Void SQLExp)
    -> [SQLExp])
-> [SQLExp]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((FieldName, MutFldG ('Postgres pgKind) Void SQLExp) -> [SQLExp])
-> [(FieldName, MutFldG ('Postgres pgKind) Void SQLExp)]
-> [SQLExp]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap MutFldsG ('Postgres pgKind) Void (SQLExpression ('Postgres pgKind))
[(FieldName, MutFldG ('Postgres pgKind) Void SQLExp)]
mutFlds (((FieldName, MutFldG ('Postgres pgKind) Void SQLExp) -> [SQLExp])
 -> [SQLExp])
-> ((FieldName, MutFldG ('Postgres pgKind) Void SQLExp)
    -> [SQLExp])
-> [SQLExp]
forall a b. (a -> b) -> a -> b
$
                  \(FieldName Text
k, MutFldG ('Postgres pgKind) Void SQLExp
mutFld) ->
                    [ Text -> SQLExp
S.SELit Text
k,
                      Identifier
-> Maybe Int
-> StringifyNumbers
-> Maybe NamingCase
-> MutFld ('Postgres pgKind)
-> SQLExp
forall (pgKind :: PostgresKind).
(Backend ('Postgres pgKind), PostgresAnnotatedFieldJSON pgKind) =>
Identifier
-> Maybe Int
-> StringifyNumbers
-> Maybe NamingCase
-> MutFld ('Postgres pgKind)
-> SQLExp
mkMutFldExp Identifier
allColumnsAlias Maybe Int
preCalAffRows StringifyNumbers
strfyNum Maybe NamingCase
tCase MutFld ('Postgres pgKind)
MutFldG ('Postgres pgKind) Void SQLExp
mutFld
                    ]
             in Text -> [SQLExp] -> Maybe OrderByExp -> SQLExp
S.SEFnApp Text
"json_build_object" [SQLExp]
jsonBuildObjArgs Maybe OrderByExp
forall a. Maybe a
Nothing
          MOutSinglerowObject AnnFieldsG
  ('Postgres pgKind) Void (SQLExpression ('Postgres pgKind))
annFlds ->
            let tabFrom :: SelectFromG ('Postgres pgKind) SQLExp
tabFrom = FIIdentifier -> SelectFromG ('Postgres pgKind) SQLExp
forall (b :: BackendType) v. FIIdentifier -> SelectFromG b v
FromIdentifier (FIIdentifier -> SelectFromG ('Postgres pgKind) SQLExp)
-> FIIdentifier -> SelectFromG ('Postgres pgKind) SQLExp
forall a b. (a -> b) -> a -> b
$ Identifier -> FIIdentifier
toFIIdentifier Identifier
allColumnsAlias
                tabPerm :: TablePermG b v
tabPerm = AnnBoolExp b v -> Maybe Int -> TablePermG b v
forall (b :: BackendType) v.
AnnBoolExp b v -> Maybe Int -> TablePermG b v
TablePerm AnnBoolExp b v
forall (backend :: BackendType) scalar. AnnBoolExp backend scalar
annBoolExpTrue Maybe Int
forall a. Maybe a
Nothing
             in Select -> SQLExp
S.SESelect (Select -> SQLExp) -> Select -> SQLExp
forall a b. (a -> b) -> a -> b
$
                  JsonAggSelect -> AnnSimpleSelect ('Postgres pgKind) -> Select
forall (pgKind :: PostgresKind).
(Backend ('Postgres pgKind), PostgresAnnotatedFieldJSON pgKind) =>
JsonAggSelect -> AnnSimpleSelect ('Postgres pgKind) -> Select
mkSQLSelect JsonAggSelect
JASSingleObject (AnnSimpleSelect ('Postgres pgKind) -> Select)
-> AnnSimpleSelect ('Postgres pgKind) -> Select
forall a b. (a -> b) -> a -> b
$
                    Fields (AnnFieldG ('Postgres pgKind) Void SQLExp)
-> SelectFromG ('Postgres pgKind) SQLExp
-> TablePermG ('Postgres pgKind) SQLExp
-> SelectArgsG ('Postgres pgKind) SQLExp
-> StringifyNumbers
-> Maybe NamingCase
-> AnnSelectG
     ('Postgres pgKind) (AnnFieldG ('Postgres pgKind) Void) SQLExp
forall (b :: BackendType) (f :: * -> *) v.
Fields (f v)
-> SelectFromG b v
-> TablePermG b v
-> SelectArgsG b v
-> StringifyNumbers
-> Maybe NamingCase
-> AnnSelectG b f v
AnnSelectG AnnFieldsG
  ('Postgres pgKind) Void (SQLExpression ('Postgres pgKind))
Fields (AnnFieldG ('Postgres pgKind) Void SQLExp)
annFlds SelectFromG ('Postgres pgKind) SQLExp
tabFrom TablePermG ('Postgres pgKind) SQLExp
forall (b :: BackendType) v. TablePermG b v
tabPerm SelectArgsG ('Postgres pgKind) SQLExp
forall (backend :: BackendType) v. SelectArgsG backend v
noSelectArgs StringifyNumbers
strfyNum Maybe NamingCase
tCase

mkCheckErrorExp :: IsIdentifier a => a -> S.SQLExp
mkCheckErrorExp :: a -> SQLExp
mkCheckErrorExp a
alias =
  let boolAndCheckConstraint :: SQLExp
boolAndCheckConstraint =
        SQLExp -> SQLExp -> SQLExp
S.handleIfNull (BoolExp -> SQLExp
S.SEBool (BoolExp -> SQLExp) -> BoolExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ Bool -> BoolExp
S.BELit Bool
True) (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$
          Text -> [SQLExp] -> Maybe OrderByExp -> SQLExp
S.SEFnApp Text
"bool_and" [Identifier -> SQLExp
S.SEIdentifier Identifier
checkConstraintIdentifier] Maybe OrderByExp
forall a. Maybe a
Nothing
   in Select -> SQLExp
S.SESelect (Select -> SQLExp) -> Select -> SQLExp
forall a b. (a -> b) -> a -> b
$
        Select
S.mkSelect
          { selExtr :: [Extractor]
S.selExtr = [SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
boolAndCheckConstraint Maybe ColumnAlias
forall a. Maybe a
Nothing],
            selFrom :: Maybe FromExp
S.selFrom = FromExp -> Maybe FromExp
forall a. a -> Maybe a
Just (FromExp -> Maybe FromExp) -> FromExp -> Maybe FromExp
forall a b. (a -> b) -> a -> b
$ a -> FromExp
forall a. IsIdentifier a => a -> FromExp
S.mkIdenFromExp a
alias
          }

checkConstraintIdentifier :: Identifier
checkConstraintIdentifier :: Identifier
checkConstraintIdentifier = Text -> Identifier
Identifier Text
"check__constraint"

asCheckErrorExtractor :: S.SQLExp -> S.Extractor
asCheckErrorExtractor :: SQLExp -> Extractor
asCheckErrorExtractor SQLExp
s =
  SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
s (Maybe ColumnAlias -> Extractor) -> Maybe ColumnAlias -> Extractor
forall a b. (a -> b) -> a -> b
$ ColumnAlias -> Maybe ColumnAlias
forall a. a -> Maybe a
Just (ColumnAlias -> Maybe ColumnAlias)
-> ColumnAlias -> Maybe ColumnAlias
forall a b. (a -> b) -> a -> b
$ Identifier -> ColumnAlias
forall a. IsIdentifier a => a -> ColumnAlias
S.toColumnAlias Identifier
checkConstraintIdentifier