module Hasura.Backends.Postgres.Translate.Select.Internal.GenerateSelect
( generateSQLSelect,
generateSQLSelectFromArrayNode,
connectionToSelectWith,
)
where
import Data.HashMap.Strict qualified as HM
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.Select.Internal.Aliases (mkBaseTableAlias)
import Hasura.Backends.Postgres.Translate.Select.Internal.Helpers
( cursorIdentifier,
cursorsSelectAliasIdentifier,
endCursorIdentifier,
hasNextPageIdentifier,
hasPreviousPageIdentifier,
mkFirstElementExp,
mkLastElementExp,
pageInfoSelectAliasIdentifier,
startCursorIdentifier,
)
import Hasura.Backends.Postgres.Translate.Types
import Hasura.Prelude
import Hasura.RQL.IR.Select (ConnectionSlice (SliceFirst, SliceLast))
generateSQLSelect ::
S.BoolExp ->
SelectSource ->
SelectNode ->
S.Select
generateSQLSelect :: BoolExp -> SelectSource -> SelectNode -> Select
generateSQLSelect BoolExp
joinCondition SelectSource
selectSource SelectNode
selectNode =
Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr = [SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
e (Maybe ColumnAlias -> Extractor) -> Maybe ColumnAlias -> Extractor
forall a b. (a -> b) -> a -> b
$ ColumnAlias -> Maybe ColumnAlias
forall a. a -> Maybe a
Just ColumnAlias
a | (ColumnAlias
a, SQLExp
e) <- HashMap ColumnAlias SQLExp -> [(ColumnAlias, SQLExp)]
forall k v. HashMap k v -> [(k, v)]
HM.toList HashMap ColumnAlias SQLExp
extractors],
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
joinedFrom],
selOrderBy :: Maybe OrderByExp
S.selOrderBy = Maybe OrderByExp
nodeOrderBy,
selLimit :: Maybe LimitExp
S.selLimit = SQLExp -> LimitExp
S.LimitExp (SQLExp -> LimitExp) -> (Int -> SQLExp) -> Int -> LimitExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> SQLExp
S.intToSQLExp (Int -> LimitExp) -> Maybe Int -> Maybe LimitExp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SelectSlicing -> Maybe Int
_ssLimit SelectSlicing
nodeSlicing,
selOffset :: Maybe OffsetExp
S.selOffset = SQLExp -> OffsetExp
S.OffsetExp (SQLExp -> OffsetExp) -> (Int64 -> SQLExp) -> Int64 -> OffsetExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> SQLExp
S.int64ToSQLExp (Int64 -> OffsetExp) -> Maybe Int64 -> Maybe OffsetExp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SelectSlicing -> Maybe Int64
_ssOffset SelectSlicing
nodeSlicing,
selDistinct :: Maybe DistinctExpr
S.selDistinct = Maybe DistinctExpr
nodeDistinctOn
}
where
SelectSource Identifier
sourcePrefix FromItem
fromItem BoolExp
whereExp SortingAndSlicing
sortAndSlice = SelectSource
selectSource
SelectNode HashMap ColumnAlias SQLExp
extractors JoinTree
joinTree = SelectNode
selectNode
JoinTree HashMap ObjectRelationSource SelectNode
objectRelations HashMap ArrayRelationSource MultiRowSelectNode
arrayRelations HashMap ArrayConnectionSource MultiRowSelectNode
arrayConnections HashMap ComputedFieldTableSetSource MultiRowSelectNode
computedFields = JoinTree
joinTree
ApplySortingAndSlicing
(Maybe OrderByExp
baseOrderBy, SelectSlicing
baseSlicing, Maybe DistinctExpr
baseDistinctOn)
(Maybe OrderByExp
nodeOrderBy, SelectSlicing
nodeSlicing, Maybe DistinctExpr
nodeDistinctOn) = SortingAndSlicing -> ApplySortingAndSlicing
applySortingAndSlicing SortingAndSlicing
sortAndSlice
baseSelect :: Select
baseSelect =
Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr = [SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor (Maybe Qual -> SQLExp
S.SEStar Maybe Qual
forall a. Maybe a
Nothing) 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
fromItem],
selWhere :: Maybe WhereFrag
S.selWhere = WhereFrag -> Maybe WhereFrag
forall a. a -> Maybe a
Just (WhereFrag -> Maybe WhereFrag) -> WhereFrag -> Maybe WhereFrag
forall a b. (a -> b) -> a -> b
$ BoolExp -> BoolExp -> WhereFrag
injectJoinCond BoolExp
joinCondition BoolExp
whereExp,
selOrderBy :: Maybe OrderByExp
S.selOrderBy = Maybe OrderByExp
baseOrderBy,
selLimit :: Maybe LimitExp
S.selLimit = SQLExp -> LimitExp
S.LimitExp (SQLExp -> LimitExp) -> (Int -> SQLExp) -> Int -> LimitExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> SQLExp
S.intToSQLExp (Int -> LimitExp) -> Maybe Int -> Maybe LimitExp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SelectSlicing -> Maybe Int
_ssLimit SelectSlicing
baseSlicing,
selOffset :: Maybe OffsetExp
S.selOffset = SQLExp -> OffsetExp
S.OffsetExp (SQLExp -> OffsetExp) -> (Int64 -> SQLExp) -> Int64 -> OffsetExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> SQLExp
S.int64ToSQLExp (Int64 -> OffsetExp) -> Maybe Int64 -> Maybe OffsetExp
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SelectSlicing -> Maybe Int64
_ssOffset SelectSlicing
baseSlicing,
selDistinct :: Maybe DistinctExpr
S.selDistinct = Maybe DistinctExpr
baseDistinctOn
}
baseSelectAlias :: TableAlias
baseSelectAlias = Identifier -> TableAlias
mkBaseTableAlias Identifier
sourcePrefix
baseFromItem :: FromItem
baseFromItem = Select -> TableAlias -> FromItem
S.mkSelFromItem Select
baseSelect TableAlias
baseSelectAlias
injectJoinCond ::
S.BoolExp ->
S.BoolExp ->
S.WhereFrag
injectJoinCond :: BoolExp -> BoolExp -> WhereFrag
injectJoinCond BoolExp
joinCond BoolExp
whereCond =
BoolExp -> WhereFrag
S.WhereFrag (BoolExp -> WhereFrag) -> BoolExp -> WhereFrag
forall a b. (a -> b) -> a -> b
$ BoolExp -> BoolExp
S.simplifyBoolExp (BoolExp -> BoolExp) -> BoolExp -> BoolExp
forall a b. (a -> b) -> a -> b
$ BinOp -> BoolExp -> BoolExp -> BoolExp
S.BEBin BinOp
S.AndOp BoolExp
joinCond BoolExp
whereCond
leftOuterJoin :: FromItem -> FromItem -> FromItem
leftOuterJoin FromItem
current FromItem
new =
JoinExpr -> FromItem
S.FIJoin (JoinExpr -> FromItem) -> JoinExpr -> FromItem
forall a b. (a -> b) -> a -> b
$
FromItem -> JoinType -> FromItem -> JoinCond -> JoinExpr
S.JoinExpr FromItem
current JoinType
S.LeftOuter FromItem
new (JoinCond -> JoinExpr) -> JoinCond -> JoinExpr
forall a b. (a -> b) -> a -> b
$
BoolExp -> JoinCond
S.JoinOn (BoolExp -> JoinCond) -> BoolExp -> JoinCond
forall a b. (a -> b) -> a -> b
$ Bool -> BoolExp
S.BELit Bool
True
joinedFrom :: S.FromItem
joinedFrom :: FromItem
joinedFrom =
(FromItem -> FromItem -> FromItem)
-> FromItem -> [FromItem] -> FromItem
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' FromItem -> FromItem -> FromItem
leftOuterJoin FromItem
baseFromItem ([FromItem] -> FromItem) -> [FromItem] -> FromItem
forall a b. (a -> b) -> a -> b
$
((ObjectRelationSource, SelectNode) -> FromItem)
-> [(ObjectRelationSource, SelectNode)] -> [FromItem]
forall a b. (a -> b) -> [a] -> [b]
map (ObjectRelationSource, SelectNode) -> FromItem
objectRelationToFromItem (HashMap ObjectRelationSource SelectNode
-> [(ObjectRelationSource, SelectNode)]
forall k v. HashMap k v -> [(k, v)]
HM.toList HashMap ObjectRelationSource SelectNode
objectRelations)
[FromItem] -> [FromItem] -> [FromItem]
forall a. Semigroup a => a -> a -> a
<> ((ArrayRelationSource, MultiRowSelectNode) -> FromItem)
-> [(ArrayRelationSource, MultiRowSelectNode)] -> [FromItem]
forall a b. (a -> b) -> [a] -> [b]
map (ArrayRelationSource, MultiRowSelectNode) -> FromItem
arrayRelationToFromItem (HashMap ArrayRelationSource MultiRowSelectNode
-> [(ArrayRelationSource, MultiRowSelectNode)]
forall k v. HashMap k v -> [(k, v)]
HM.toList HashMap ArrayRelationSource MultiRowSelectNode
arrayRelations)
[FromItem] -> [FromItem] -> [FromItem]
forall a. Semigroup a => a -> a -> a
<> ((ArrayConnectionSource, MultiRowSelectNode) -> FromItem)
-> [(ArrayConnectionSource, MultiRowSelectNode)] -> [FromItem]
forall a b. (a -> b) -> [a] -> [b]
map (ArrayConnectionSource, MultiRowSelectNode) -> FromItem
arrayConnectionToFromItem (HashMap ArrayConnectionSource MultiRowSelectNode
-> [(ArrayConnectionSource, MultiRowSelectNode)]
forall k v. HashMap k v -> [(k, v)]
HM.toList HashMap ArrayConnectionSource MultiRowSelectNode
arrayConnections)
[FromItem] -> [FromItem] -> [FromItem]
forall a. Semigroup a => a -> a -> a
<> ((ComputedFieldTableSetSource, MultiRowSelectNode) -> FromItem)
-> [(ComputedFieldTableSetSource, MultiRowSelectNode)]
-> [FromItem]
forall a b. (a -> b) -> [a] -> [b]
map (ComputedFieldTableSetSource, MultiRowSelectNode) -> FromItem
computedFieldToFromItem (HashMap ComputedFieldTableSetSource MultiRowSelectNode
-> [(ComputedFieldTableSetSource, MultiRowSelectNode)]
forall k v. HashMap k v -> [(k, v)]
HM.toList HashMap ComputedFieldTableSetSource MultiRowSelectNode
computedFields)
objectRelationToFromItem ::
(ObjectRelationSource, SelectNode) -> S.FromItem
objectRelationToFromItem :: (ObjectRelationSource, SelectNode) -> FromItem
objectRelationToFromItem (ObjectRelationSource
objectRelationSource, SelectNode
node) =
let ObjectRelationSource RelName
_ HashMap PGCol PGCol
colMapping ObjectSelectSource
objectSelectSource = ObjectRelationSource
objectRelationSource
alias :: TableAlias
alias = Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias (Identifier -> TableAlias) -> Identifier -> TableAlias
forall a b. (a -> b) -> a -> b
$ ObjectSelectSource -> Identifier
_ossPrefix ObjectSelectSource
objectSelectSource
source :: SelectSource
source = ObjectSelectSource -> SelectSource
objectSelectSourceToSelectSource ObjectSelectSource
objectSelectSource
select :: Select
select = BoolExp -> SelectSource -> SelectNode -> Select
generateSQLSelect (TableAlias -> HashMap PGCol PGCol -> BoolExp
mkJoinCond TableAlias
baseSelectAlias HashMap PGCol PGCol
colMapping) SelectSource
source SelectNode
node
in Select -> TableAlias -> FromItem
S.mkLateralFromItem Select
select TableAlias
alias
arrayRelationToFromItem ::
(ArrayRelationSource, MultiRowSelectNode) -> S.FromItem
arrayRelationToFromItem :: (ArrayRelationSource, MultiRowSelectNode) -> FromItem
arrayRelationToFromItem (ArrayRelationSource
arrayRelationSource, MultiRowSelectNode
arraySelectNode) =
let ArrayRelationSource TableAlias
_ HashMap PGCol PGCol
colMapping SelectSource
source = ArrayRelationSource
arrayRelationSource
alias :: TableAlias
alias = Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias (Identifier -> TableAlias) -> Identifier -> TableAlias
forall a b. (a -> b) -> a -> b
$ SelectSource -> Identifier
_ssPrefix SelectSource
source
select :: Select
select =
SelectSource -> MultiRowSelectNode -> BoolExp -> Select
generateSQLSelectFromArrayNode SelectSource
source MultiRowSelectNode
arraySelectNode (BoolExp -> Select) -> BoolExp -> Select
forall a b. (a -> b) -> a -> b
$
TableAlias -> HashMap PGCol PGCol -> BoolExp
mkJoinCond TableAlias
baseSelectAlias HashMap PGCol PGCol
colMapping
in Select -> TableAlias -> FromItem
S.mkLateralFromItem Select
select TableAlias
alias
arrayConnectionToFromItem ::
(ArrayConnectionSource, MultiRowSelectNode) -> S.FromItem
arrayConnectionToFromItem :: (ArrayConnectionSource, MultiRowSelectNode) -> FromItem
arrayConnectionToFromItem (ArrayConnectionSource
arrayConnectionSource, MultiRowSelectNode
arraySelectNode) =
let selectWith :: SelectWithG Select
selectWith = TableAlias
-> ArrayConnectionSource
-> MultiRowSelectNode
-> SelectWithG Select
connectionToSelectWith TableAlias
baseSelectAlias ArrayConnectionSource
arrayConnectionSource MultiRowSelectNode
arraySelectNode
alias :: TableAlias
alias = Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias (Identifier -> TableAlias) -> Identifier -> TableAlias
forall a b. (a -> b) -> a -> b
$ SelectSource -> Identifier
_ssPrefix (SelectSource -> Identifier) -> SelectSource -> Identifier
forall a b. (a -> b) -> a -> b
$ ArrayConnectionSource -> SelectSource
_acsSource ArrayConnectionSource
arrayConnectionSource
in Lateral -> SelectWithG Select -> TableAlias -> FromItem
S.FISelectWith (Bool -> Lateral
S.Lateral Bool
True) SelectWithG Select
selectWith TableAlias
alias
computedFieldToFromItem ::
(ComputedFieldTableSetSource, MultiRowSelectNode) -> S.FromItem
computedFieldToFromItem :: (ComputedFieldTableSetSource, MultiRowSelectNode) -> FromItem
computedFieldToFromItem (ComputedFieldTableSetSource
computedFieldTableSource, MultiRowSelectNode
node) =
let ComputedFieldTableSetSource FieldName
_ SelectSource
source = ComputedFieldTableSetSource
computedFieldTableSource
internalSelect :: Select
internalSelect = BoolExp -> SelectSource -> SelectNode -> Select
generateSQLSelect (Bool -> BoolExp
S.BELit Bool
True) SelectSource
source (SelectNode -> Select) -> SelectNode -> Select
forall a b. (a -> b) -> a -> b
$ MultiRowSelectNode -> SelectNode
_mrsnSelectNode MultiRowSelectNode
node
alias :: TableAlias
alias = Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias (Identifier -> TableAlias) -> Identifier -> TableAlias
forall a b. (a -> b) -> a -> b
$ SelectSource -> Identifier
_ssPrefix SelectSource
source
select :: Select
select =
Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr = MultiRowSelectNode -> [Extractor]
_mrsnTopExtractors MultiRowSelectNode
node,
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 [Select -> TableAlias -> FromItem
S.mkSelFromItem Select
internalSelect TableAlias
alias]
}
in Select -> TableAlias -> FromItem
S.mkLateralFromItem Select
select TableAlias
alias
generateSQLSelectFromArrayNode ::
SelectSource ->
MultiRowSelectNode ->
S.BoolExp ->
S.Select
generateSQLSelectFromArrayNode :: SelectSource -> MultiRowSelectNode -> BoolExp -> Select
generateSQLSelectFromArrayNode SelectSource
selectSource MultiRowSelectNode
arraySelectNode BoolExp
joinCondition =
Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr = [Extractor]
topExtractors,
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
selectFrom]
}
where
MultiRowSelectNode [Extractor]
topExtractors SelectNode
selectNode = MultiRowSelectNode
arraySelectNode
selectFrom :: FromItem
selectFrom =
Select -> TableAlias -> FromItem
S.mkSelFromItem
(BoolExp -> SelectSource -> SelectNode -> Select
generateSQLSelect BoolExp
joinCondition SelectSource
selectSource SelectNode
selectNode)
(TableAlias -> FromItem) -> TableAlias -> FromItem
forall a b. (a -> b) -> a -> b
$ Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias (Identifier -> TableAlias) -> Identifier -> TableAlias
forall a b. (a -> b) -> a -> b
$ SelectSource -> Identifier
_ssPrefix SelectSource
selectSource
mkJoinCond :: S.TableAlias -> HashMap PGCol PGCol -> S.BoolExp
mkJoinCond :: TableAlias -> HashMap PGCol PGCol -> BoolExp
mkJoinCond TableAlias
baseTablepfx HashMap PGCol PGCol
colMapn =
(BoolExp -> BoolExp -> BoolExp) -> BoolExp -> [BoolExp] -> BoolExp
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (BinOp -> BoolExp -> BoolExp -> BoolExp
S.BEBin BinOp
S.AndOp) (Bool -> BoolExp
S.BELit Bool
True) ([BoolExp] -> BoolExp) -> [BoolExp] -> BoolExp
forall a b. (a -> b) -> a -> b
$
(((PGCol, PGCol) -> BoolExp) -> [(PGCol, PGCol)] -> [BoolExp])
-> [(PGCol, PGCol)] -> ((PGCol, PGCol) -> BoolExp) -> [BoolExp]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((PGCol, PGCol) -> BoolExp) -> [(PGCol, PGCol)] -> [BoolExp]
forall a b. (a -> b) -> [a] -> [b]
map (HashMap PGCol PGCol -> [(PGCol, PGCol)]
forall k v. HashMap k v -> [(k, v)]
HM.toList HashMap PGCol PGCol
colMapn) (((PGCol, PGCol) -> BoolExp) -> [BoolExp])
-> ((PGCol, PGCol) -> BoolExp) -> [BoolExp]
forall a b. (a -> b) -> a -> b
$ \(PGCol
lCol, PGCol
rCol) ->
CompareOp -> SQLExp -> SQLExp -> BoolExp
S.BECompare CompareOp
S.SEQ (TableAlias -> PGCol -> SQLExp
forall a b. (IsIdentifier a, IsIdentifier b) => a -> b -> SQLExp
S.mkQIdenExp TableAlias
baseTablepfx PGCol
lCol) (PGCol -> SQLExp
forall a. IsIdentifier a => a -> SQLExp
S.mkSIdenExp PGCol
rCol)
connectionToSelectWith ::
S.TableAlias ->
ArrayConnectionSource ->
MultiRowSelectNode ->
S.SelectWithG S.Select
connectionToSelectWith :: TableAlias
-> ArrayConnectionSource
-> MultiRowSelectNode
-> SelectWithG Select
connectionToSelectWith TableAlias
baseSelectAlias ArrayConnectionSource
arrayConnectionSource MultiRowSelectNode
arraySelectNode =
let extractionSelect :: Select
extractionSelect =
Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr = [Extractor]
topExtractors,
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 [Identifier -> FromItem
S.FIIdentifier Identifier
finalSelectIdentifier]
}
in [(TableAlias, Select)] -> Select -> SelectWithG Select
forall statement.
[(TableAlias, statement)] -> Select -> SelectWithG statement
S.SelectWith [(TableAlias, Select)]
fromBaseSelections Select
extractionSelect
where
ArrayConnectionSource TableAlias
_ HashMap PGCol PGCol
columnMapping Maybe BoolExp
maybeSplit Maybe ConnectionSlice
maybeSlice SelectSource
selectSource =
ArrayConnectionSource
arrayConnectionSource
MultiRowSelectNode [Extractor]
topExtractors SelectNode
selectNode = MultiRowSelectNode
arraySelectNode
baseSelectIdentifier :: Identifier
baseSelectIdentifier = Text -> Identifier
Identifier Text
"__base_select"
splitSelectIdentifier :: Identifier
splitSelectIdentifier = Text -> Identifier
Identifier Text
"__split_select"
sliceSelectIdentifier :: Identifier
sliceSelectIdentifier = Text -> Identifier
Identifier Text
"__slice_select"
finalSelectIdentifier :: Identifier
finalSelectIdentifier = Text -> Identifier
Identifier Text
"__final_select"
rowNumberIdentifier :: Identifier
rowNumberIdentifier = Text -> Identifier
Identifier Text
"__row_number"
rowNumberExp :: SQLExp
rowNumberExp = Text -> SQLExp
S.SEUnsafe Text
"(row_number() over (partition by 1))"
startRowNumberIdentifier :: Identifier
startRowNumberIdentifier = Text -> Identifier
Identifier Text
"__start_row_number"
endRowNumberIdentifier :: Identifier
endRowNumberIdentifier = Text -> Identifier
Identifier Text
"__end_row_number"
startCursorExp :: SQLExp
startCursorExp = SQLExp -> SQLExp
mkFirstElementExp (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ Identifier -> SQLExp
S.SEIdentifier Identifier
cursorIdentifier
endCursorExp :: SQLExp
endCursorExp = SQLExp -> SQLExp
mkLastElementExp (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ Identifier -> SQLExp
S.SEIdentifier Identifier
cursorIdentifier
startRowNumberExp :: SQLExp
startRowNumberExp = SQLExp -> SQLExp
mkFirstElementExp (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ Identifier -> SQLExp
S.SEIdentifier Identifier
rowNumberIdentifier
endRowNumberExp :: SQLExp
endRowNumberExp = SQLExp -> SQLExp
mkLastElementExp (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ Identifier -> SQLExp
S.SEIdentifier Identifier
rowNumberIdentifier
fromBaseSelections :: [(TableAlias, Select)]
fromBaseSelections =
let joinCond :: BoolExp
joinCond = TableAlias -> HashMap PGCol PGCol -> BoolExp
mkJoinCond TableAlias
baseSelectAlias HashMap PGCol PGCol
columnMapping
baseSelectFrom :: FromItem
baseSelectFrom =
Select -> TableAlias -> FromItem
S.mkSelFromItem
(BoolExp -> SelectSource -> SelectNode -> Select
generateSQLSelect BoolExp
joinCond SelectSource
selectSource SelectNode
selectNode)
(TableAlias -> FromItem) -> TableAlias -> FromItem
forall a b. (a -> b) -> a -> b
$ Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias (Identifier -> TableAlias) -> Identifier -> TableAlias
forall a b. (a -> b) -> a -> b
$ SelectSource -> Identifier
_ssPrefix SelectSource
selectSource
select :: Select
select =
Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr =
[ Extractor
S.selectStar,
SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
rowNumberExp (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
rowNumberIdentifier
],
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
baseSelectFrom]
}
in (Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias Identifier
baseSelectIdentifier, Select
select) (TableAlias, Select)
-> [(TableAlias, Select)] -> [(TableAlias, Select)]
forall a. a -> [a] -> [a]
: [(TableAlias, Select)]
fromSplitSelection
mkStarSelect :: Identifier -> Select
mkStarSelect Identifier
fromIdentifier =
Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr = [Extractor
S.selectStar],
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 [Identifier -> FromItem
S.FIIdentifier Identifier
fromIdentifier]
}
fromSplitSelection :: [(TableAlias, Select)]
fromSplitSelection = case Maybe BoolExp
maybeSplit of
Maybe BoolExp
Nothing -> Identifier -> [(TableAlias, Select)]
fromSliceSelection Identifier
baseSelectIdentifier
Just BoolExp
splitBool ->
let select :: Select
select =
(Identifier -> Select
mkStarSelect Identifier
baseSelectIdentifier) {selWhere :: Maybe WhereFrag
S.selWhere = WhereFrag -> Maybe WhereFrag
forall a. a -> Maybe a
Just (WhereFrag -> Maybe WhereFrag) -> WhereFrag -> Maybe WhereFrag
forall a b. (a -> b) -> a -> b
$ BoolExp -> WhereFrag
S.WhereFrag BoolExp
splitBool}
in (Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias Identifier
splitSelectIdentifier, Select
select) (TableAlias, Select)
-> [(TableAlias, Select)] -> [(TableAlias, Select)]
forall a. a -> [a] -> [a]
: Identifier -> [(TableAlias, Select)]
fromSliceSelection Identifier
splitSelectIdentifier
fromSliceSelection :: Identifier -> [(TableAlias, Select)]
fromSliceSelection Identifier
prevSelect = case Maybe ConnectionSlice
maybeSlice of
Maybe ConnectionSlice
Nothing -> Identifier -> [(TableAlias, Select)]
fromFinalSelect Identifier
prevSelect
Just ConnectionSlice
slice ->
let select :: Select
select = case ConnectionSlice
slice of
SliceFirst Int
limit ->
(Identifier -> Select
mkStarSelect Identifier
prevSelect)
{ selLimit :: Maybe LimitExp
S.selLimit = (LimitExp -> Maybe LimitExp
forall a. a -> Maybe a
Just (LimitExp -> Maybe LimitExp)
-> (Int -> LimitExp) -> Int -> Maybe LimitExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SQLExp -> LimitExp
S.LimitExp (SQLExp -> LimitExp) -> (Int -> SQLExp) -> Int -> LimitExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> SQLExp
S.intToSQLExp) Int
limit
}
SliceLast Int
limit ->
let mkRowNumberOrderBy :: OrderType -> OrderByExp
mkRowNumberOrderBy OrderType
obType =
let orderByItem :: OrderByItem
orderByItem =
SQLExp -> Maybe OrderType -> Maybe NullsOrder -> OrderByItem
S.OrderByItem (Identifier -> SQLExp
S.SEIdentifier Identifier
rowNumberIdentifier) (OrderType -> Maybe OrderType
forall a. a -> Maybe a
Just OrderType
obType) Maybe NullsOrder
forall a. Maybe a
Nothing
in NonEmpty OrderByItem -> OrderByExp
S.OrderByExp (NonEmpty OrderByItem -> OrderByExp)
-> NonEmpty OrderByItem -> OrderByExp
forall a b. (a -> b) -> a -> b
$ OrderByItem
orderByItem OrderByItem -> [OrderByItem] -> NonEmpty OrderByItem
forall a. a -> [a] -> NonEmpty a
NE.:| []
sliceLastSelect :: Select
sliceLastSelect =
(Identifier -> Select
mkStarSelect Identifier
prevSelect)
{ selLimit :: Maybe LimitExp
S.selLimit = (LimitExp -> Maybe LimitExp
forall a. a -> Maybe a
Just (LimitExp -> Maybe LimitExp)
-> (Int -> LimitExp) -> Int -> Maybe LimitExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SQLExp -> LimitExp
S.LimitExp (SQLExp -> LimitExp) -> (Int -> SQLExp) -> Int -> LimitExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> SQLExp
S.intToSQLExp) Int
limit,
selOrderBy :: Maybe OrderByExp
S.selOrderBy = OrderByExp -> Maybe OrderByExp
forall a. a -> Maybe a
Just (OrderByExp -> Maybe OrderByExp) -> OrderByExp -> Maybe OrderByExp
forall a b. (a -> b) -> a -> b
$ OrderType -> OrderByExp
mkRowNumberOrderBy OrderType
S.OTDesc
}
sliceLastSelectFrom :: FromItem
sliceLastSelectFrom =
Select -> TableAlias -> FromItem
S.mkSelFromItem Select
sliceLastSelect (TableAlias -> FromItem) -> TableAlias -> FromItem
forall a b. (a -> b) -> a -> b
$ Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias Identifier
sliceSelectIdentifier
in Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr = [Extractor
S.selectStar],
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
sliceLastSelectFrom],
selOrderBy :: Maybe OrderByExp
S.selOrderBy = OrderByExp -> Maybe OrderByExp
forall a. a -> Maybe a
Just (OrderByExp -> Maybe OrderByExp) -> OrderByExp -> Maybe OrderByExp
forall a b. (a -> b) -> a -> b
$ OrderType -> OrderByExp
mkRowNumberOrderBy OrderType
S.OTAsc
}
in (Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias Identifier
sliceSelectIdentifier, Select
select) (TableAlias, Select)
-> [(TableAlias, Select)] -> [(TableAlias, Select)]
forall a. a -> [a] -> [a]
: Identifier -> [(TableAlias, Select)]
fromFinalSelect Identifier
sliceSelectIdentifier
fromFinalSelect :: Identifier -> [(TableAlias, Select)]
fromFinalSelect Identifier
prevSelect =
let select :: Select
select = Identifier -> Select
mkStarSelect Identifier
prevSelect
in (Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias Identifier
finalSelectIdentifier, Select
select) (TableAlias, Select)
-> [(TableAlias, Select)] -> [(TableAlias, Select)]
forall a. a -> [a] -> [a]
: [(TableAlias, Select)]
fromCursorSelection
fromCursorSelection :: [(TableAlias, Select)]
fromCursorSelection =
let extrs :: [Extractor]
extrs =
[ SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
startCursorExp (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
startCursorIdentifier,
SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
endCursorExp (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
endCursorIdentifier,
SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
startRowNumberExp (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
startRowNumberIdentifier,
SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
endRowNumberExp (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
endRowNumberIdentifier
]
select :: Select
select =
Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr = [Extractor]
extrs,
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 [Identifier -> FromItem
S.FIIdentifier Identifier
finalSelectIdentifier]
}
in (Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias Identifier
cursorsSelectAliasIdentifier, Select
select) (TableAlias, Select)
-> [(TableAlias, Select)] -> [(TableAlias, Select)]
forall a. a -> [a] -> [a]
: [(TableAlias, Select)]
fromPageInfoSelection
fromPageInfoSelection :: [(TableAlias, Select)]
fromPageInfoSelection =
let hasPrevPage :: SQLExp
hasPrevPage =
BoolExp -> SQLExp
S.SEBool (BoolExp -> SQLExp) -> BoolExp -> SQLExp
forall a b. (a -> b) -> a -> b
$
FromItem -> BoolExp -> BoolExp
S.mkExists (Identifier -> FromItem
S.FIIdentifier Identifier
baseSelectIdentifier) (BoolExp -> BoolExp) -> BoolExp -> BoolExp
forall a b. (a -> b) -> a -> b
$
CompareOp -> SQLExp -> SQLExp -> BoolExp
S.BECompare CompareOp
S.SLT (Identifier -> SQLExp
S.SEIdentifier Identifier
rowNumberIdentifier) (SQLExp -> BoolExp) -> SQLExp -> BoolExp
forall a b. (a -> b) -> a -> b
$
Select -> SQLExp
S.SESelect (Select -> SQLExp) -> Select -> SQLExp
forall a b. (a -> b) -> a -> b
$
Select
S.mkSelect
{ 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 [Identifier -> FromItem
S.FIIdentifier Identifier
cursorsSelectAliasIdentifier],
selExtr :: [Extractor]
S.selExtr = [SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor (Identifier -> SQLExp
S.SEIdentifier Identifier
startRowNumberIdentifier) Maybe ColumnAlias
forall a. Maybe a
Nothing]
}
hasNextPage :: SQLExp
hasNextPage =
BoolExp -> SQLExp
S.SEBool (BoolExp -> SQLExp) -> BoolExp -> SQLExp
forall a b. (a -> b) -> a -> b
$
FromItem -> BoolExp -> BoolExp
S.mkExists (Identifier -> FromItem
S.FIIdentifier Identifier
baseSelectIdentifier) (BoolExp -> BoolExp) -> BoolExp -> BoolExp
forall a b. (a -> b) -> a -> b
$
CompareOp -> SQLExp -> SQLExp -> BoolExp
S.BECompare CompareOp
S.SGT (Identifier -> SQLExp
S.SEIdentifier Identifier
rowNumberIdentifier) (SQLExp -> BoolExp) -> SQLExp -> BoolExp
forall a b. (a -> b) -> a -> b
$
Select -> SQLExp
S.SESelect (Select -> SQLExp) -> Select -> SQLExp
forall a b. (a -> b) -> a -> b
$
Select
S.mkSelect
{ 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 [Identifier -> FromItem
S.FIIdentifier Identifier
cursorsSelectAliasIdentifier],
selExtr :: [Extractor]
S.selExtr = [SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor (Identifier -> SQLExp
S.SEIdentifier Identifier
endRowNumberIdentifier) Maybe ColumnAlias
forall a. Maybe a
Nothing]
}
select :: Select
select =
Select
S.mkSelect
{ selExtr :: [Extractor]
S.selExtr =
[ SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
hasPrevPage (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
hasPreviousPageIdentifier,
SQLExp -> Maybe ColumnAlias -> Extractor
S.Extractor SQLExp
hasNextPage (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
hasNextPageIdentifier
]
}
in (TableAlias, Select) -> [(TableAlias, Select)]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Identifier -> TableAlias
forall a. IsIdentifier a => a -> TableAlias
S.toTableAlias Identifier
pageInfoSelectAliasIdentifier, Select
select)