module Hasura.Backends.Postgres.Translate.Select.Internal.Extractor
( aggregateFieldsToExtractorExps,
mkAggregateOrderByExtractorAndFields,
mkRawComputedFieldExpression,
withJsonAggExtr,
asSingleRowExtr,
asJsonAggExtr,
withColumnOp,
withRedactionExp,
)
where
import Control.Monad.Writer.Strict
import Data.List.NonEmpty qualified as NE
import Hasura.Backends.Postgres.SQL.DML qualified as S
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Backends.Postgres.Translate.BoolExp (toSQLBoolExp)
import Hasura.Backends.Postgres.Translate.Select.Internal.Aliases
import Hasura.Backends.Postgres.Translate.Select.Internal.Helpers (fromTableRowArgs)
import Hasura.Backends.Postgres.Translate.Types (PermissionLimitSubQuery (..))
import Hasura.Backends.Postgres.Types.Aggregates
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.IR.Select
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
aggregateFieldsToExtractorExps ::
forall pgKind.
(Backend ('Postgres pgKind)) =>
TableIdentifier ->
AggregateFields ('Postgres pgKind) S.SQLExp ->
[(S.ColumnAlias, S.SQLExp)]
TableIdentifier
sourcePrefix AggregateFields ('Postgres pgKind) SQLExp
aggregateFields =
(((FieldName, AggregateField ('Postgres pgKind) SQLExp)
-> [(ColumnAlias, SQLExp)])
-> AggregateFields ('Postgres pgKind) SQLExp
-> [(ColumnAlias, SQLExp)])
-> AggregateFields ('Postgres pgKind) SQLExp
-> ((FieldName, AggregateField ('Postgres pgKind) SQLExp)
-> [(ColumnAlias, SQLExp)])
-> [(ColumnAlias, SQLExp)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((FieldName, AggregateField ('Postgres pgKind) SQLExp)
-> [(ColumnAlias, SQLExp)])
-> AggregateFields ('Postgres pgKind) SQLExp
-> [(ColumnAlias, SQLExp)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap AggregateFields ('Postgres pgKind) SQLExp
aggregateFields (((FieldName, AggregateField ('Postgres pgKind) SQLExp)
-> [(ColumnAlias, SQLExp)])
-> [(ColumnAlias, SQLExp)])
-> ((FieldName, AggregateField ('Postgres pgKind) SQLExp)
-> [(ColumnAlias, SQLExp)])
-> [(ColumnAlias, SQLExp)]
forall a b. (a -> b) -> a -> b
$ \(FieldName
aggregateFieldName, AggregateField ('Postgres pgKind) SQLExp
field) ->
case AggregateField ('Postgres pgKind) SQLExp
field of
AFCount CountType ('Postgres pgKind) SQLExp
cty -> case CountAggregate pgKind SQLExp
-> CountType (PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)
forall (pgKind :: PostgresKind) v.
CountAggregate pgKind v
-> CountType (PGCol, AnnRedactionExp ('Postgres pgKind) v)
getCountType CountType ('Postgres pgKind) SQLExp
CountAggregate pgKind SQLExp
cty of
CountType (PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)
S.CTStar -> []
S.CTSimple [(PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)]
cols -> [(PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)]
-> [(ColumnAlias, SQLExp)]
colsToExps [(PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)]
cols
S.CTDistinct [(PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)]
cols -> [(PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)]
-> [(ColumnAlias, SQLExp)]
colsToExps [(PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)]
cols
AFOp AggregateOp ('Postgres pgKind) SQLExp
aggOp -> ((FieldName, SelectionField ('Postgres pgKind) SQLExp)
-> Maybe (ColumnAlias, SQLExp))
-> [(FieldName, SelectionField ('Postgres pgKind) SQLExp)]
-> [(ColumnAlias, SQLExp)]
forall a b. (a -> Maybe b) -> [a] -> [b]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe (FieldName
-> (FieldName, SelectionField ('Postgres pgKind) SQLExp)
-> Maybe (ColumnAlias, SQLExp)
colToMaybeExp FieldName
aggregateFieldName) ([(FieldName, SelectionField ('Postgres pgKind) SQLExp)]
-> [(ColumnAlias, SQLExp)])
-> [(FieldName, SelectionField ('Postgres pgKind) SQLExp)]
-> [(ColumnAlias, SQLExp)]
forall a b. (a -> b) -> a -> b
$ AggregateOp ('Postgres pgKind) SQLExp
-> [(FieldName, SelectionField ('Postgres pgKind) SQLExp)]
forall (b :: BackendType) v. AggregateOp b v -> SelectionFields b v
_aoFields AggregateOp ('Postgres pgKind) SQLExp
aggOp
AFExp Text
_ -> []
where
colsToExps :: [(PGCol, AnnRedactionExp ('Postgres pgKind) S.SQLExp)] -> [(S.ColumnAlias, S.SQLExp)]
colsToExps :: [(PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)]
-> [(ColumnAlias, SQLExp)]
colsToExps = ((PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)
-> (ColumnAlias, SQLExp))
-> [(PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)]
-> [(ColumnAlias, SQLExp)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(PGCol
col, AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp) -> AnnRedactionExp ('Postgres pgKind) SQLExp
-> PGCol -> (ColumnAlias, SQLExp)
mkColumnExp AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp PGCol
col)
colToMaybeExp ::
FieldName ->
(FieldName, SelectionField ('Postgres pgKind) S.SQLExp) ->
Maybe (S.ColumnAlias, S.SQLExp)
colToMaybeExp :: FieldName
-> (FieldName, SelectionField ('Postgres pgKind) SQLExp)
-> Maybe (ColumnAlias, SQLExp)
colToMaybeExp FieldName
aggregateFieldName = \case
(FieldName
_fieldName, SFCol Column ('Postgres pgKind)
col ColumnType ('Postgres pgKind)
_ AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp) -> (ColumnAlias, SQLExp) -> Maybe (ColumnAlias, SQLExp)
forall a. a -> Maybe a
Just ((ColumnAlias, SQLExp) -> Maybe (ColumnAlias, SQLExp))
-> (ColumnAlias, SQLExp) -> Maybe (ColumnAlias, SQLExp)
forall a b. (a -> b) -> a -> b
$ AnnRedactionExp ('Postgres pgKind) SQLExp
-> PGCol -> (ColumnAlias, SQLExp)
mkColumnExp AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp Column ('Postgres pgKind)
PGCol
col
(FieldName
fieldName, SFComputedField ComputedFieldName
_name ComputedFieldScalarSelect ('Postgres pgKind) SQLExp
cfss) -> (ColumnAlias, SQLExp) -> Maybe (ColumnAlias, SQLExp)
forall a. a -> Maybe a
Just ((ColumnAlias, SQLExp) -> Maybe (ColumnAlias, SQLExp))
-> (ColumnAlias, SQLExp) -> Maybe (ColumnAlias, SQLExp)
forall a b. (a -> b) -> a -> b
$ FieldName
-> FieldName
-> ComputedFieldScalarSelect ('Postgres pgKind) SQLExp
-> (ColumnAlias, SQLExp)
mkComputedFieldExp FieldName
aggregateFieldName FieldName
fieldName ComputedFieldScalarSelect ('Postgres pgKind) SQLExp
cfss
(FieldName
_fieldName, SFExp Text
_text) -> Maybe (ColumnAlias, SQLExp)
forall a. Maybe a
Nothing
mkColumnExp ::
AnnRedactionExp ('Postgres pgKind) S.SQLExp ->
PGCol ->
(S.ColumnAlias, S.SQLExp)
mkColumnExp :: AnnRedactionExp ('Postgres pgKind) SQLExp
-> PGCol -> (ColumnAlias, SQLExp)
mkColumnExp AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp PGCol
column =
let baseTableIdentifier :: TableIdentifier
baseTableIdentifier = TableIdentifier -> TableIdentifier
mkBaseTableIdentifier TableIdentifier
sourcePrefix
baseTableQual :: Qual
baseTableQual = TableIdentifier -> Maybe TypeAnn -> Qual
S.QualifiedIdentifier TableIdentifier
baseTableIdentifier Maybe TypeAnn
forall a. Maybe a
Nothing
qualifiedColumn :: SQLExp
qualifiedColumn = Qual
-> AnnRedactionExp ('Postgres pgKind) SQLExp -> SQLExp -> SQLExp
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual
-> AnnRedactionExp ('Postgres pgKind) SQLExp -> SQLExp -> SQLExp
withRedactionExp Qual
baseTableQual AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ TableIdentifier -> Identifier -> SQLExp
forall b. IsIdentifier b => TableIdentifier -> b -> SQLExp
S.mkQIdenExp TableIdentifier
baseTableIdentifier (PGCol -> Identifier
forall a. IsIdentifier a => a -> Identifier
toIdentifier PGCol
column)
columnAlias :: ColumnAlias
columnAlias = TableIdentifier -> PGCol -> ColumnAlias
contextualizeBaseTableColumn TableIdentifier
sourcePrefix PGCol
column
in (ColumnAlias -> ColumnAlias
forall a. IsIdentifier a => a -> ColumnAlias
S.toColumnAlias ColumnAlias
columnAlias, SQLExp
qualifiedColumn)
mkComputedFieldExp :: FieldName -> FieldName -> ComputedFieldScalarSelect ('Postgres pgKind) S.SQLExp -> (S.ColumnAlias, S.SQLExp)
mkComputedFieldExp :: FieldName
-> FieldName
-> ComputedFieldScalarSelect ('Postgres pgKind) SQLExp
-> (ColumnAlias, SQLExp)
mkComputedFieldExp FieldName
aggregateFieldName FieldName
computedFieldFieldName ComputedFieldScalarSelect ('Postgres pgKind) SQLExp
computedFieldScalarSelect =
(TableIdentifier -> FieldName -> FieldName -> ColumnAlias
contextualizeAggregateInput TableIdentifier
sourcePrefix FieldName
aggregateFieldName FieldName
computedFieldFieldName, TableIdentifier
-> ComputedFieldScalarSelect ('Postgres pgKind) SQLExp -> SQLExp
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
TableIdentifier
-> ComputedFieldScalarSelect ('Postgres pgKind) SQLExp -> SQLExp
mkRawComputedFieldExpression TableIdentifier
sourcePrefix ComputedFieldScalarSelect ('Postgres pgKind) SQLExp
computedFieldScalarSelect)
mkAggregateOrderByExtractorAndFields ::
forall pgKind.
(Backend ('Postgres pgKind)) =>
TableIdentifier ->
AnnotatedAggregateOrderBy ('Postgres pgKind) S.SQLExp ->
(S.Extractor, AggregateFields ('Postgres pgKind) S.SQLExp)
mkAggregateOrderByExtractorAndFields :: forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
TableIdentifier
-> AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
-> (Extractor, AggregateFields ('Postgres pgKind) SQLExp)
mkAggregateOrderByExtractorAndFields TableIdentifier
sourcePrefix AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
annAggOrderBy =
case AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
annAggOrderBy of
AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
AAOCount ->
( SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
S.countStar Maybe ColumnAlias
alias,
[(Text -> FieldName
FieldName Text
"count", CountType ('Postgres pgKind) SQLExp
-> AggregateField ('Postgres pgKind) SQLExp
forall (b :: BackendType) v. CountType b v -> AggregateField b v
AFCount (CountType ('Postgres pgKind) SQLExp
-> AggregateField ('Postgres pgKind) SQLExp)
-> CountType ('Postgres pgKind) SQLExp
-> AggregateField ('Postgres pgKind) SQLExp
forall a b. (a -> b) -> a -> b
$ CountType (PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)
-> CountAggregate pgKind SQLExp
forall (pgKind :: PostgresKind) v.
CountType (PGCol, AnnRedactionExp ('Postgres pgKind) v)
-> CountAggregate pgKind v
CountAggregate CountType (PGCol, AnnRedactionExp ('Postgres pgKind) SQLExp)
forall columnType. CountType columnType
S.CTStar)]
)
AAOOp (AggregateOrderByColumn Text
opText ColumnType ('Postgres pgKind)
_resultType ColumnInfo ('Postgres pgKind)
pgColumnInfo AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp) ->
let pgColumn :: Column ('Postgres pgKind)
pgColumn = ColumnInfo ('Postgres pgKind) -> Column ('Postgres pgKind)
forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn ColumnInfo ('Postgres pgKind)
pgColumnInfo
pgType :: ColumnType ('Postgres pgKind)
pgType = ColumnInfo ('Postgres pgKind) -> ColumnType ('Postgres pgKind)
forall (b :: BackendType). ColumnInfo b -> ColumnType b
ciType ColumnInfo ('Postgres pgKind)
pgColumnInfo
in ( SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor (Text -> [SQLExp] -> Maybe OrderByExp -> SQLExp
S.SEFnApp Text
opText [QIdentifier -> SQLExp
S.SEQIdentifier (QIdentifier -> SQLExp) -> QIdentifier -> SQLExp
forall a b. (a -> b) -> a -> b
$ PGCol -> QIdentifier
columnToQIdentifier Column ('Postgres pgKind)
PGCol
pgColumn] Maybe OrderByExp
forall a. Maybe a
Nothing) Maybe ColumnAlias
alias,
[ ( Text -> FieldName
FieldName Text
opText,
AggregateOp ('Postgres pgKind) SQLExp
-> AggregateField ('Postgres pgKind) SQLExp
forall (b :: BackendType) v. AggregateOp b v -> AggregateField b v
AFOp
(AggregateOp ('Postgres pgKind) SQLExp
-> AggregateField ('Postgres pgKind) SQLExp)
-> AggregateOp ('Postgres pgKind) SQLExp
-> AggregateField ('Postgres pgKind) SQLExp
forall a b. (a -> b) -> a -> b
$ Text
-> SelectionFields ('Postgres pgKind) SQLExp
-> AggregateOp ('Postgres pgKind) SQLExp
forall (b :: BackendType) v.
Text -> SelectionFields b v -> AggregateOp b v
AggregateOp
Text
opText
[ ( forall (b :: BackendType). Backend b => Column b -> FieldName
fromCol @('Postgres pgKind) Column ('Postgres pgKind)
pgColumn,
Column ('Postgres pgKind)
-> ColumnType ('Postgres pgKind)
-> AnnRedactionExp ('Postgres pgKind) SQLExp
-> SelectionField ('Postgres pgKind) SQLExp
forall (b :: BackendType) v.
Column b
-> ColumnType b -> AnnRedactionExp b v -> SelectionField b v
SFCol Column ('Postgres pgKind)
pgColumn ColumnType ('Postgres pgKind)
pgType AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp
)
]
)
]
)
where
alias :: Maybe ColumnAlias
alias = ColumnAlias -> Maybe ColumnAlias
forall a. a -> Maybe a
Just (ColumnAlias -> Maybe ColumnAlias)
-> ColumnAlias -> Maybe ColumnAlias
forall a b. (a -> b) -> a -> b
$ AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp -> ColumnAlias
forall (pgKind :: PostgresKind) v.
AnnotatedAggregateOrderBy ('Postgres pgKind) v -> ColumnAlias
mkAggregateOrderByAlias AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
annAggOrderBy
columnToQIdentifier :: PGCol -> S.QIdentifier
columnToQIdentifier :: PGCol -> QIdentifier
columnToQIdentifier = TableIdentifier -> ColumnAlias -> QIdentifier
forall b. IsIdentifier b => TableIdentifier -> b -> QIdentifier
S.mkQIdentifier TableIdentifier
sourcePrefix (ColumnAlias -> QIdentifier)
-> (PGCol -> ColumnAlias) -> PGCol -> QIdentifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TableIdentifier -> PGCol -> ColumnAlias
contextualizeBaseTableColumn TableIdentifier
sourcePrefix
mkRawComputedFieldExpression ::
forall pgKind.
(Backend ('Postgres pgKind)) =>
TableIdentifier ->
ComputedFieldScalarSelect ('Postgres pgKind) S.SQLExp ->
S.SQLExp
mkRawComputedFieldExpression :: forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
TableIdentifier
-> ComputedFieldScalarSelect ('Postgres pgKind) SQLExp -> SQLExp
mkRawComputedFieldExpression TableIdentifier
sourcePrefix (ComputedFieldScalarSelect FunctionName ('Postgres pgKind)
fn FunctionArgsExp ('Postgres pgKind) SQLExp
args ScalarType ('Postgres pgKind)
_ Maybe (ScalarSelectionArguments ('Postgres pgKind))
colOpM AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp) =
Qual
-> AnnRedactionExp ('Postgres pgKind) SQLExp -> SQLExp -> SQLExp
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual
-> AnnRedactionExp ('Postgres pgKind) SQLExp -> SQLExp -> SQLExp
withRedactionExp (TableIdentifier -> Maybe TypeAnn -> Qual
S.QualifiedIdentifier (TableIdentifier -> TableIdentifier
mkBaseTableIdentifier TableIdentifier
sourcePrefix) Maybe TypeAnn
forall a. Maybe a
Nothing) AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp
(SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ Maybe ColumnOp -> SQLExp -> SQLExp
withColumnOp Maybe (ScalarSelectionArguments ('Postgres pgKind))
Maybe ColumnOp
colOpM
(SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ FunctionExp -> SQLExp
S.SEFunction
(FunctionExp -> SQLExp) -> FunctionExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ QualifiedFunction
-> FunctionArgs -> Maybe FunctionAlias -> FunctionExp
S.FunctionExp FunctionName ('Postgres pgKind)
QualifiedFunction
fn (TableIdentifier
-> FunctionArgsExpG (ArgumentExp SQLExp) -> FunctionArgs
fromTableRowArgs TableIdentifier
sourcePrefix FunctionArgsExp ('Postgres pgKind) SQLExp
FunctionArgsExpG (ArgumentExp SQLExp)
args) Maybe FunctionAlias
forall a. Maybe a
Nothing
withJsonAggExtr ::
PermissionLimitSubQuery -> Maybe S.OrderByExp -> S.ColumnAlias -> S.SQLExp
withJsonAggExtr :: PermissionLimitSubQuery
-> Maybe OrderByExp -> ColumnAlias -> SQLExp
withJsonAggExtr PermissionLimitSubQuery
permLimitSubQuery Maybe OrderByExp
ordBy ColumnAlias
alias =
case PermissionLimitSubQuery
permLimitSubQuery of
PLSQRequired Int
permLimit -> Int -> SQLExp
withPermLimit Int
permLimit
PermissionLimitSubQuery
PLSQNotRequired -> SQLExp
simpleJsonAgg
where
simpleJsonAgg :: SQLExp
simpleJsonAgg = SQLExp -> Maybe OrderByExp -> SQLExp
mkSimpleJsonAgg SQLExp
rowIdenExp Maybe OrderByExp
ordBy
rowIdenExp :: SQLExp
rowIdenExp = Identifier -> SQLExp
S.SEIdentifier (Identifier -> SQLExp) -> Identifier -> SQLExp
forall a b. (a -> b) -> a -> b
$ ColumnAlias -> Identifier
forall a. IsIdentifier a => a -> Identifier
toIdentifier ColumnAlias
alias
subSelAls :: TableAlias
subSelAls = Text -> TableAlias
S.mkTableAlias Text
"sub_query"
subSelIdentifier :: TableIdentifier
subSelIdentifier = TableAlias -> TableIdentifier
S.tableAliasToIdentifier TableAlias
subSelAls
unnestTable :: TableAlias
unnestTable = Text -> TableAlias
S.mkTableAlias Text
"unnest_table"
unnestTableIdentifier :: TableIdentifier
unnestTableIdentifier = TableAlias -> TableIdentifier
S.tableAliasToIdentifier TableAlias
unnestTable
mkSimpleJsonAgg :: SQLExp -> Maybe OrderByExp -> SQLExp
mkSimpleJsonAgg SQLExp
rowExp Maybe OrderByExp
ob =
let jsonAggExp :: SQLExp
jsonAggExp = Text -> [SQLExp] -> Maybe OrderByExp -> SQLExp
S.SEFnApp Text
"json_agg" [SQLExp
rowExp] Maybe OrderByExp
ob
in Text -> [SQLExp] -> Maybe OrderByExp -> SQLExp
S.SEFnApp Text
"coalesce" [SQLExp
jsonAggExp, Text -> SQLExp
S.SELit Text
"[]"] Maybe OrderByExp
forall a. Maybe a
Nothing
withPermLimit :: Int -> SQLExp
withPermLimit Int
limit =
let subSelect :: Select
subSelect = Int -> Select
mkSubSelect Int
limit
rowIdentifier :: SQLExp
rowIdentifier = TableIdentifier -> ColumnAlias -> SQLExp
forall b. IsIdentifier b => TableIdentifier -> b -> SQLExp
S.mkQIdenExp TableIdentifier
subSelIdentifier ColumnAlias
alias
extr :: Extractor
extr = SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor (SQLExp -> Maybe OrderByExp -> SQLExp
mkSimpleJsonAgg SQLExp
rowIdentifier Maybe OrderByExp
newOrderBy) Maybe ColumnAlias
forall a. Maybe a
Nothing
fromExp :: FromExp
fromExp =
[FromItem] -> FromExp
S.FromExp
([FromItem] -> FromExp) -> [FromItem] -> FromExp
forall a b. (a -> b) -> a -> b
$ FromItem -> [FromItem]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure
(FromItem -> [FromItem]) -> FromItem -> [FromItem]
forall a b. (a -> b) -> a -> b
$ Select -> TableAlias -> FromItem
S.mkSelFromItem Select
subSelect
(TableAlias -> FromItem) -> TableAlias -> FromItem
forall a b. (a -> b) -> a -> b
$ TableAlias -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias TableAlias
subSelAls
in Select -> SQLExp
S.SESelect
(Select -> SQLExp) -> Select -> SQLExp
forall a b. (a -> b) -> a -> b
$ Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr = Extractor -> [Extractor]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure Extractor
extr,
selFrom :: Maybe FromExp
S.selFrom = FromExp -> Maybe FromExp
forall a. a -> Maybe a
Just FromExp
fromExp
}
mkSubSelect :: Int -> Select
mkSubSelect Int
limit =
let jsonRowExtr :: Extractor
jsonRowExtr =
(SQLExp -> Maybe ColumnAlias -> Extractor)
-> Maybe ColumnAlias -> SQLExp -> Extractor
forall a b c. (a -> b -> c) -> b -> a -> c
flip SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor (ColumnAlias -> Maybe ColumnAlias
forall a. a -> Maybe a
Just ColumnAlias
alias)
(SQLExp -> Extractor) -> SQLExp -> Extractor
forall a b. (a -> b) -> a -> b
$ TableIdentifier -> ColumnAlias -> SQLExp
forall b. IsIdentifier b => TableIdentifier -> b -> SQLExp
S.mkQIdenExp TableIdentifier
unnestTableIdentifier ColumnAlias
alias
obExtrs :: [Extractor]
obExtrs = ((Identifier -> Extractor) -> [Identifier] -> [Extractor])
-> [Identifier] -> (Identifier -> Extractor) -> [Extractor]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Identifier -> Extractor) -> [Identifier] -> [Extractor]
forall a b. (a -> b) -> [a] -> [b]
map [Identifier]
newOBAliases ((Identifier -> Extractor) -> [Extractor])
-> (Identifier -> Extractor) -> [Extractor]
forall a b. (a -> b) -> a -> b
$ \Identifier
a ->
SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor (TableIdentifier -> Identifier -> SQLExp
forall b. IsIdentifier b => TableIdentifier -> b -> SQLExp
S.mkQIdenExp TableIdentifier
unnestTableIdentifier Identifier
a) (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
a
in Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr = Extractor
jsonRowExtr Extractor -> [Extractor] -> [Extractor]
forall a. a -> [a] -> [a]
: [Extractor]
obExtrs,
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 a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure FromItem
unnestFromItem,
selLimit :: Maybe LimitExp
S.selLimit = LimitExp -> Maybe LimitExp
forall a. a -> Maybe a
Just (LimitExp -> Maybe LimitExp) -> LimitExp -> Maybe LimitExp
forall a b. (a -> b) -> a -> b
$ SQLExp -> LimitExp
S.LimitExp (SQLExp -> LimitExp) -> SQLExp -> LimitExp
forall a b. (a -> b) -> a -> b
$ Int -> SQLExp
S.intToSQLExp Int
limit,
selOrderBy :: Maybe OrderByExp
S.selOrderBy = Maybe OrderByExp
newOrderBy
}
unnestFromItem :: FromItem
unnestFromItem =
let arrayAggItems :: [SQLExp]
arrayAggItems = ((SQLExp -> SQLExp) -> [SQLExp] -> [SQLExp])
-> [SQLExp] -> (SQLExp -> SQLExp) -> [SQLExp]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (SQLExp -> SQLExp) -> [SQLExp] -> [SQLExp]
forall a b. (a -> b) -> [a] -> [b]
map (SQLExp
rowIdenExp SQLExp -> [SQLExp] -> [SQLExp]
forall a. a -> [a] -> [a]
: [SQLExp]
obCols)
((SQLExp -> SQLExp) -> [SQLExp]) -> (SQLExp -> SQLExp) -> [SQLExp]
forall a b. (a -> b) -> a -> b
$ \SQLExp
s -> Text -> [SQLExp] -> Maybe OrderByExp -> SQLExp
S.SEFnApp Text
"array_agg" [SQLExp
s] Maybe OrderByExp
forall a. Maybe a
Nothing
in [SQLExp] -> TableAlias -> [ColumnAlias] -> FromItem
S.FIUnnest [SQLExp]
arrayAggItems (TableAlias -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias TableAlias
unnestTable)
([ColumnAlias] -> FromItem) -> [ColumnAlias] -> FromItem
forall a b. (a -> b) -> a -> b
$ ColumnAlias
alias
ColumnAlias -> [ColumnAlias] -> [ColumnAlias]
forall a. a -> [a] -> [a]
: (Identifier -> ColumnAlias) -> [Identifier] -> [ColumnAlias]
forall a b. (a -> b) -> [a] -> [b]
map Identifier -> ColumnAlias
forall a. IsIdentifier a => a -> ColumnAlias
S.toColumnAlias [Identifier]
newOBAliases
newOrderBy :: Maybe OrderByExp
newOrderBy = NonEmpty OrderByItem -> OrderByExp
S.OrderByExp (NonEmpty OrderByItem -> OrderByExp)
-> Maybe (NonEmpty OrderByItem) -> Maybe OrderByExp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [OrderByItem] -> Maybe (NonEmpty OrderByItem)
forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty [OrderByItem]
newOBItems
([OrderByItem]
newOBItems, [SQLExp]
obCols, [Identifier]
newOBAliases) = ([OrderByItem], [SQLExp], [Identifier])
-> (OrderByExp -> ([OrderByItem], [SQLExp], [Identifier]))
-> Maybe OrderByExp
-> ([OrderByItem], [SQLExp], [Identifier])
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([], [], []) OrderByExp -> ([OrderByItem], [SQLExp], [Identifier])
transformOrderBy Maybe OrderByExp
ordBy
transformOrderBy :: OrderByExp -> ([OrderByItem], [SQLExp], [Identifier])
transformOrderBy (S.OrderByExp NonEmpty OrderByItem
l) = [(OrderByItem, SQLExp, Identifier)]
-> ([OrderByItem], [SQLExp], [Identifier])
forall a b c. [(a, b, c)] -> ([a], [b], [c])
unzip3
([(OrderByItem, SQLExp, Identifier)]
-> ([OrderByItem], [SQLExp], [Identifier]))
-> [(OrderByItem, SQLExp, Identifier)]
-> ([OrderByItem], [SQLExp], [Identifier])
forall a b. (a -> b) -> a -> b
$ (((OrderByItem, Int) -> (OrderByItem, SQLExp, Identifier))
-> [(OrderByItem, Int)] -> [(OrderByItem, SQLExp, Identifier)])
-> [(OrderByItem, Int)]
-> ((OrderByItem, Int) -> (OrderByItem, SQLExp, Identifier))
-> [(OrderByItem, SQLExp, Identifier)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((OrderByItem, Int) -> (OrderByItem, SQLExp, Identifier))
-> [(OrderByItem, Int)] -> [(OrderByItem, SQLExp, Identifier)]
forall a b. (a -> b) -> [a] -> [b]
map ([OrderByItem] -> [Int] -> [(OrderByItem, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip (NonEmpty OrderByItem -> [OrderByItem]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList NonEmpty OrderByItem
l) [Int
1 ..])
(((OrderByItem, Int) -> (OrderByItem, SQLExp, Identifier))
-> [(OrderByItem, SQLExp, Identifier)])
-> ((OrderByItem, Int) -> (OrderByItem, SQLExp, Identifier))
-> [(OrderByItem, SQLExp, Identifier)]
forall a b. (a -> b) -> a -> b
$ \(OrderByItem
obItem, Int
i :: Int) ->
let iden :: Identifier
iden = Text -> Identifier
Identifier (Text -> Identifier) -> Text -> Identifier
forall a b. (a -> b) -> a -> b
$ Text
"ob_col_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
tshow Int
i
in ( OrderByItem
obItem {oExpression :: SQLExp
S.oExpression = Identifier -> SQLExp
S.SEIdentifier Identifier
iden},
OrderByItem -> SQLExp
S.oExpression OrderByItem
obItem,
Identifier
iden
)
asSingleRowExtr :: S.ColumnAlias -> S.SQLExp
asSingleRowExtr :: ColumnAlias -> SQLExp
asSingleRowExtr ColumnAlias
col =
Text -> [SQLExp] -> Maybe OrderByExp -> SQLExp
S.SEFnApp Text
"coalesce" [SQLExp
jsonAgg, Text -> SQLExp
S.SELit Text
"null"] Maybe OrderByExp
forall a. Maybe a
Nothing
where
jsonAgg :: SQLExp
jsonAgg =
SQLOp -> [SQLExp] -> SQLExp
S.SEOpApp
(Text -> SQLOp
S.SQLOp Text
"->")
[ Text -> [SQLExp] -> Maybe OrderByExp -> SQLExp
S.SEFnApp Text
"json_agg" [Identifier -> SQLExp
S.SEIdentifier (Identifier -> SQLExp) -> Identifier -> SQLExp
forall a b. (a -> b) -> a -> b
$ ColumnAlias -> Identifier
forall a. IsIdentifier a => a -> Identifier
toIdentifier ColumnAlias
col] Maybe OrderByExp
forall a. Maybe a
Nothing,
Text -> SQLExp
S.SEUnsafe Text
"0"
]
asJsonAggExtr ::
JsonAggSelect -> S.ColumnAlias -> PermissionLimitSubQuery -> Maybe S.OrderByExp -> S.Extractor
asJsonAggExtr :: JsonAggSelect
-> ColumnAlias
-> PermissionLimitSubQuery
-> Maybe OrderByExp
-> Extractor
asJsonAggExtr JsonAggSelect
jsonAggSelect ColumnAlias
als PermissionLimitSubQuery
permLimitSubQuery Maybe OrderByExp
ordByExpM =
(SQLExp -> Maybe ColumnAlias -> Extractor)
-> Maybe ColumnAlias -> SQLExp -> Extractor
forall a b c. (a -> b -> c) -> b -> a -> c
flip SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor (ColumnAlias -> Maybe ColumnAlias
forall a. a -> Maybe a
Just ColumnAlias
als) (SQLExp -> Extractor) -> SQLExp -> Extractor
forall a b. (a -> b) -> a -> b
$ case JsonAggSelect
jsonAggSelect of
JsonAggSelect
JASMultipleRows -> PermissionLimitSubQuery
-> Maybe OrderByExp -> ColumnAlias -> SQLExp
withJsonAggExtr PermissionLimitSubQuery
permLimitSubQuery Maybe OrderByExp
ordByExpM ColumnAlias
als
JsonAggSelect
JASSingleObject -> ColumnAlias -> SQLExp
asSingleRowExtr ColumnAlias
als
withColumnOp :: Maybe S.ColumnOp -> S.SQLExp -> S.SQLExp
withColumnOp :: Maybe ColumnOp -> SQLExp -> SQLExp
withColumnOp Maybe ColumnOp
colOpM SQLExp
sqlExp = case Maybe ColumnOp
colOpM of
Maybe ColumnOp
Nothing -> SQLExp
sqlExp
Just (S.ColumnOp SQLOp
opText SQLExp
cExp) -> SQLOp -> SQLExp -> SQLExp -> SQLExp
S.mkSQLOpExp SQLOp
opText SQLExp
sqlExp SQLExp
cExp
withRedactionExp ::
(Backend ('Postgres pgKind)) =>
S.Qual ->
AnnRedactionExp ('Postgres pgKind) S.SQLExp ->
S.SQLExp ->
S.SQLExp
withRedactionExp :: forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual
-> AnnRedactionExp ('Postgres pgKind) SQLExp -> SQLExp -> SQLExp
withRedactionExp Qual
tableQual AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp SQLExp
sqlExpression =
case AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp of
AnnRedactionExp ('Postgres pgKind) SQLExp
NoRedaction -> SQLExp
sqlExpression
RedactIfFalse GBoolExp
('Postgres pgKind) (AnnBoolExpFld ('Postgres pgKind) SQLExp)
gBoolExp ->
let boolExp :: BoolExp
boolExp =
BoolExp -> BoolExp
S.simplifyBoolExp
(BoolExp -> BoolExp) -> BoolExp -> BoolExp
forall a b. (a -> b) -> a -> b
$ Qual
-> GBoolExp
('Postgres pgKind)
(AnnBoolExpFld
('Postgres pgKind) (SQLExpression ('Postgres pgKind)))
-> BoolExp
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual -> AnnBoolExpSQL ('Postgres pgKind) -> BoolExp
toSQLBoolExp Qual
tableQual
(GBoolExp
('Postgres pgKind)
(AnnBoolExpFld
('Postgres pgKind) (SQLExpression ('Postgres pgKind)))
-> BoolExp)
-> GBoolExp
('Postgres pgKind)
(AnnBoolExpFld
('Postgres pgKind) (SQLExpression ('Postgres pgKind)))
-> BoolExp
forall a b. (a -> b) -> a -> b
$ GBoolExp
('Postgres pgKind)
(AnnBoolExpFld
('Postgres pgKind) (SQLExpression ('Postgres pgKind)))
GBoolExp
('Postgres pgKind) (AnnBoolExpFld ('Postgres pgKind) SQLExp)
gBoolExp
in BoolExp -> SQLExp -> SQLExp -> SQLExp
S.SECond BoolExp
boolExp SQLExp
sqlExpression SQLExp
S.SENull