-- | This module relates to the processing of Order-By clauses.
module Hasura.Backends.Postgres.Translate.Select.Internal.OrderBy
  ( processOrderByItems,
  )
where

import Control.Lens ((^?))
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
import Data.List.NonEmpty qualified as NE
import Hasura.Backends.Postgres.SQL.DML qualified as S
import Hasura.Backends.Postgres.SQL.Types
  ( IsIdentifier (toIdentifier),
    PGCol (..),
    QualifiedFunction,
    TableIdentifier (..),
    qualifiedObjectToText,
    tableIdentifierToIdentifier,
  )
import Hasura.Backends.Postgres.Translate.BoolExp (toSQLBoolExp)
import Hasura.Backends.Postgres.Translate.Select.Internal.Aliases
  ( contextualizeBaseTableColumn,
    mkAggregateOrderByAlias,
    mkAnnOrderByAlias,
    mkArrayRelationAlias,
    mkArrayRelationSourcePrefix,
    mkBaseTableIdentifier,
    mkComputedFieldTableIdentifier,
    mkObjectRelationTableAlias,
    mkOrderByFieldName,
  )
import Hasura.Backends.Postgres.Translate.Select.Internal.Extractor
  ( aggregateFieldsToExtractorExps,
    mkAggregateOrderByExtractorAndFields,
    withRedactionExp,
  )
import Hasura.Backends.Postgres.Translate.Select.Internal.Helpers (fromTableRowArgs)
import Hasura.Backends.Postgres.Translate.Select.Internal.JoinTree
  ( withWriteArrayRelation,
    withWriteComputedFieldTableSet,
    withWriteObjectRelation,
  )
import Hasura.Backends.Postgres.Translate.Types
import Hasura.Backends.Postgres.Types.Function (ArgumentExp)
import Hasura.Function.Cache (FunctionArgsExpG (..))
import Hasura.Prelude
import Hasura.RQL.IR.OrderBy
  ( OrderByItemG (OrderByItemG, obiColumn),
  )
import Hasura.RQL.IR.Select
import Hasura.RQL.IR.Select.Lenses
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Relationships.Local
import Hasura.RQL.Types.Schema.Options qualified as Options

{- Note [Optimizing queries using limit/offset]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Refer to the issue https://github.com/hasura/graphql-engine/issues/5745

Before this change, limit/offset/distinct_on is applied at outer selection
node along with order by clause. This greatly reduces query performance if
our base selection table contains many rows and relationships are selected
which joins remote tables. We need to optimize application of limit wrt to
order by input.

If "Order by" is not present:
  Apply limit/offset/distinct on at the base table selection
Else if "Order by" contains only columns:
  Apply limit/offset/distinct_on at the base table selection along with order by
Otherwise:
  Apply limit/offset/distinct_on at the node selection along with order by
-}

processOrderByItems ::
  forall pgKind m.
  ( MonadReader Options.StringifyNumbers m,
    MonadWriter SelectWriter m,
    Backend ('Postgres pgKind)
  ) =>
  TableIdentifier ->
  S.Qual ->
  FieldName ->
  SimilarArrayFields ->
  Maybe (NE.NonEmpty (AnnDistinctColumn ('Postgres pgKind) S.SQLExp)) ->
  Maybe (NE.NonEmpty (AnnotatedOrderByItem ('Postgres pgKind))) ->
  m
    ( [(S.ColumnAlias, S.SQLExp)], -- Order by Extractors
      SelectSorting,
      Maybe S.SQLExp -- The cursor expression
    )
processOrderByItems :: forall (pgKind :: PostgresKind) (m :: * -> *).
(MonadReader StringifyNumbers m, MonadWriter SelectWriter m,
 Backend ('Postgres pgKind)) =>
TableIdentifier
-> Qual
-> FieldName
-> SimilarArrayFields
-> Maybe (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp))
-> Maybe (NonEmpty (AnnotatedOrderByItem ('Postgres pgKind)))
-> m ([(ColumnAlias, SQLExp)], SelectSorting, Maybe SQLExp)
processOrderByItems TableIdentifier
sourcePrefix' Qual
selectSourceQual FieldName
fieldAlias' SimilarArrayFields
similarArrayFields Maybe (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp))
distOnCols = \case
  Maybe (NonEmpty (AnnotatedOrderByItem ('Postgres pgKind)))
Nothing -> ([(ColumnAlias, SQLExp)], SelectSorting, Maybe SQLExp)
-> m ([(ColumnAlias, SQLExp)], SelectSorting, Maybe SQLExp)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([], Maybe DistinctExpr -> SelectSorting
NoSorting (Maybe DistinctExpr -> SelectSorting)
-> Maybe DistinctExpr -> SelectSorting
forall a b. (a -> b) -> a -> b
$ Qual
-> NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> DistinctExpr
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual
-> NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> DistinctExpr
applyDistinctOnAtBase Qual
selectSourceQual (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
 -> DistinctExpr)
-> Maybe (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp))
-> Maybe DistinctExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp))
distOnCols, Maybe SQLExp
forall a. Maybe a
Nothing)
  Just NonEmpty (AnnotatedOrderByItem ('Postgres pgKind))
orderByItems -> do
    NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp)))
orderByItemExps <- NonEmpty (AnnotatedOrderByItemG ('Postgres pgKind) SQLExp)
-> (AnnotatedOrderByItemG ('Postgres pgKind) SQLExp
    -> m (OrderByItemG
            ('Postgres pgKind)
            (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
             (ColumnAlias, SQLExp))))
-> m (NonEmpty
        (OrderByItemG
           ('Postgres pgKind)
           (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
            (ColumnAlias, SQLExp))))
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM NonEmpty (AnnotatedOrderByItem ('Postgres pgKind))
NonEmpty (AnnotatedOrderByItemG ('Postgres pgKind) SQLExp)
orderByItems AnnotatedOrderByItem ('Postgres pgKind)
-> m (OrderByItemG
        ('Postgres pgKind)
        (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
         (ColumnAlias, SQLExp)))
AnnotatedOrderByItemG ('Postgres pgKind) SQLExp
-> m (OrderByItemG
        ('Postgres pgKind)
        (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
         (ColumnAlias, SQLExp)))
processAnnOrderByItem
    let (SelectSorting
sorting, [(ColumnAlias, SQLExp)]
distinctOnExtractors) = NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp)))
-> (SelectSorting, [(ColumnAlias, SQLExp)])
generateSorting NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp)))
orderByItemExps
        orderByExtractors :: [(ColumnAlias, SQLExp)]
orderByExtractors = [[(ColumnAlias, SQLExp)]] -> [(ColumnAlias, SQLExp)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[(ColumnAlias, SQLExp)]] -> [(ColumnAlias, SQLExp)])
-> [[(ColumnAlias, SQLExp)]] -> [(ColumnAlias, SQLExp)]
forall a b. (a -> b) -> a -> b
$ NonEmpty [(ColumnAlias, SQLExp)] -> [[(ColumnAlias, SQLExp)]]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (NonEmpty [(ColumnAlias, SQLExp)] -> [[(ColumnAlias, SQLExp)]])
-> NonEmpty [(ColumnAlias, SQLExp)] -> [[(ColumnAlias, SQLExp)]]
forall a b. (a -> b) -> a -> b
$ ((AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
  (ColumnAlias, SQLExp))
 -> (ColumnAlias, SQLExp))
-> [(AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
     (ColumnAlias, SQLExp))]
-> [(ColumnAlias, SQLExp)]
forall a b. (a -> b) -> [a] -> [b]
map (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
 (ColumnAlias, SQLExp))
-> (ColumnAlias, SQLExp)
forall a b. (a, b) -> b
snd ([(AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
   (ColumnAlias, SQLExp))]
 -> [(ColumnAlias, SQLExp)])
-> (OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
       (ColumnAlias, SQLExp))
    -> [(AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
         (ColumnAlias, SQLExp))])
-> OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp))
-> [(ColumnAlias, SQLExp)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OrderByItemG
  ('Postgres pgKind)
  (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
   (ColumnAlias, SQLExp))
-> [(AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
     (ColumnAlias, SQLExp))]
forall a. OrderByItemG ('Postgres pgKind) a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))
 -> [(ColumnAlias, SQLExp)])
-> NonEmpty
     (OrderByItemG
        ('Postgres pgKind)
        (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
         (ColumnAlias, SQLExp)))
-> NonEmpty [(ColumnAlias, SQLExp)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp)))
orderByItemExps
        cursor :: SQLExp
cursor = [OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement
      ('Postgres pgKind) (SQLExpression ('Postgres pgKind)),
    (ColumnAlias, SQLExpression ('Postgres pgKind)))]
-> SQLExp
mkCursorExp ([OrderByItemG
    ('Postgres pgKind)
    (AnnotatedOrderByElement
       ('Postgres pgKind) (SQLExpression ('Postgres pgKind)),
     (ColumnAlias, SQLExpression ('Postgres pgKind)))]
 -> SQLExp)
-> [OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement
         ('Postgres pgKind) (SQLExpression ('Postgres pgKind)),
       (ColumnAlias, SQLExpression ('Postgres pgKind)))]
-> SQLExp
forall a b. (a -> b) -> a -> b
$ NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp)))
-> [OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
       (ColumnAlias, SQLExp))]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp)))
orderByItemExps
    ([(ColumnAlias, SQLExp)], SelectSorting, Maybe SQLExp)
-> m ([(ColumnAlias, SQLExp)], SelectSorting, Maybe SQLExp)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([(ColumnAlias, SQLExp)]
orderByExtractors [(ColumnAlias, SQLExp)]
-> [(ColumnAlias, SQLExp)] -> [(ColumnAlias, SQLExp)]
forall a. Semigroup a => a -> a -> a
<> [(ColumnAlias, SQLExp)]
distinctOnExtractors, SelectSorting
sorting, SQLExp -> Maybe SQLExp
forall a. a -> Maybe a
Just SQLExp
cursor)
  where
    processAnnOrderByItem ::
      AnnotatedOrderByItem ('Postgres pgKind) ->
      m
        ( OrderByItemG
            ('Postgres pgKind)
            ( AnnotatedOrderByElement ('Postgres pgKind) S.SQLExp,
              (S.ColumnAlias, S.SQLExp)
            )
        )
    processAnnOrderByItem :: AnnotatedOrderByItem ('Postgres pgKind)
-> m (OrderByItemG
        ('Postgres pgKind)
        (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
         (ColumnAlias, SQLExp)))
processAnnOrderByItem AnnotatedOrderByItem ('Postgres pgKind)
orderByItem =
      AnnotatedOrderByItemG ('Postgres pgKind) SQLExp
-> (AnnotatedOrderByElement ('Postgres pgKind) SQLExp
    -> m (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
          (ColumnAlias, SQLExp)))
-> m (OrderByItemG
        ('Postgres pgKind)
        (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
         (ColumnAlias, SQLExp)))
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM AnnotatedOrderByItem ('Postgres pgKind)
AnnotatedOrderByItemG ('Postgres pgKind) SQLExp
orderByItem ((AnnotatedOrderByElement ('Postgres pgKind) SQLExp
  -> m (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
        (ColumnAlias, SQLExp)))
 -> m (OrderByItemG
         ('Postgres pgKind)
         (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
          (ColumnAlias, SQLExp))))
-> (AnnotatedOrderByElement ('Postgres pgKind) SQLExp
    -> m (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
          (ColumnAlias, SQLExp)))
-> m (OrderByItemG
        ('Postgres pgKind)
        (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
         (ColumnAlias, SQLExp)))
forall a b. (a -> b) -> a -> b
$ \AnnotatedOrderByElement ('Postgres pgKind) SQLExp
ordByCol ->
        (AnnotatedOrderByElement ('Postgres pgKind) SQLExp
ordByCol,)
          ((ColumnAlias, SQLExp)
 -> (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
     (ColumnAlias, SQLExp)))
-> m (ColumnAlias, SQLExp)
-> m (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TableIdentifier
-> FieldName
-> AnnotatedOrderByElement ('Postgres pgKind) SQLExp
-> m (ColumnAlias, SQLExp)
processAnnotatedOrderByElement TableIdentifier
sourcePrefix' FieldName
fieldAlias' AnnotatedOrderByElement ('Postgres pgKind) SQLExp
ordByCol

    processAnnotatedOrderByElement ::
      TableIdentifier -> FieldName -> AnnotatedOrderByElement ('Postgres pgKind) S.SQLExp -> m (S.ColumnAlias, S.SQLExp)
    processAnnotatedOrderByElement :: TableIdentifier
-> FieldName
-> AnnotatedOrderByElement ('Postgres pgKind) SQLExp
-> m (ColumnAlias, SQLExp)
processAnnotatedOrderByElement TableIdentifier
sourcePrefix FieldName
fieldAlias AnnotatedOrderByElement ('Postgres pgKind) SQLExp
annObCol = do
      let ordByAlias :: ColumnAlias
ordByAlias = TableIdentifier
-> FieldName
-> SimilarArrayFields
-> AnnotatedOrderByElement ('Postgres pgKind) SQLExp
-> ColumnAlias
forall (pgKind :: PostgresKind) v.
TableIdentifier
-> FieldName
-> SimilarArrayFields
-> AnnotatedOrderByElement ('Postgres pgKind) v
-> ColumnAlias
mkAnnOrderByAlias TableIdentifier
sourcePrefix FieldName
fieldAlias SimilarArrayFields
similarArrayFields AnnotatedOrderByElement ('Postgres pgKind) SQLExp
annObCol
      let baseTableIdentifier :: TableIdentifier
baseTableIdentifier = TableIdentifier -> TableIdentifier
mkBaseTableIdentifier TableIdentifier
sourcePrefix
      (ColumnAlias
ordByAlias,) (SQLExp -> (ColumnAlias, SQLExp))
-> m SQLExp -> m (ColumnAlias, SQLExp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> case AnnotatedOrderByElement ('Postgres pgKind) SQLExp
annObCol of
        AOCColumn ColumnInfo ('Postgres pgKind)
pgColInfo AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp ->
          SQLExp -> m SQLExp
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
            (SQLExp -> m SQLExp) -> SQLExp -> m SQLExp
forall a b. (a -> b) -> a -> b
$ 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
baseTableIdentifier Maybe TypeAnn
forall a. Maybe a
Nothing) AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp
            (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ TableIdentifier -> PGCol -> SQLExp
forall b. IsIdentifier b => TableIdentifier -> b -> SQLExp
S.mkQIdenExp TableIdentifier
baseTableIdentifier
            (PGCol -> SQLExp) -> PGCol -> SQLExp
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
        AOCObjectRelation RelInfo ('Postgres pgKind)
relInfo AnnBoolExp ('Postgres pgKind) SQLExp
relFilter AnnotatedOrderByElement ('Postgres pgKind) SQLExp
rest -> m (ObjectRelationSource, InsOrdHashMap ColumnAlias SQLExp, SQLExp)
-> m SQLExp
forall (m :: * -> *) a.
MonadWriter SelectWriter m =>
m (ObjectRelationSource, InsOrdHashMap ColumnAlias SQLExp, a)
-> m a
withWriteObjectRelation (m (ObjectRelationSource, InsOrdHashMap ColumnAlias SQLExp, SQLExp)
 -> m SQLExp)
-> m (ObjectRelationSource, InsOrdHashMap ColumnAlias SQLExp,
      SQLExp)
-> m SQLExp
forall a b. (a -> b) -> a -> b
$ do
          let RelInfo {riName :: forall (b :: BackendType). RelInfo b -> RelName
riName = RelName
relName, riMapping :: forall (b :: BackendType).
RelInfo b -> HashMap (Column b) (Column b)
riMapping = HashMap (Column ('Postgres pgKind)) (Column ('Postgres pgKind))
colMapping, riTarget :: forall (b :: BackendType). RelInfo b -> RelTarget b
riTarget = RelTarget ('Postgres pgKind)
relTarget} = RelInfo ('Postgres pgKind)
relInfo
              relSourcePrefix :: TableIdentifier
relSourcePrefix = TableIdentifier -> RelName -> TableIdentifier
mkObjectRelationTableAlias TableIdentifier
sourcePrefix RelName
relName
              fieldName :: FieldName
fieldName = RelName -> FieldName
forall a. ToTxt a => a -> FieldName
mkOrderByFieldName RelName
relName
          case RelTarget ('Postgres pgKind)
relTarget of
            RelTargetNativeQuery NativeQueryName
_ -> [Char]
-> m (ObjectRelationSource, InsOrdHashMap ColumnAlias SQLExp,
      SQLExp)
forall a. HasCallStack => [Char] -> a
error [Char]
"processAnnotatedOrderByElement RelTargetNativeQuery (AOCObjectRelation)"
            RelTargetTable TableName ('Postgres pgKind)
relTable -> do
              (ColumnAlias
relOrderByAlias, SQLExp
relOrdByExp) <-
                TableIdentifier
-> FieldName
-> AnnotatedOrderByElement ('Postgres pgKind) SQLExp
-> m (ColumnAlias, SQLExp)
processAnnotatedOrderByElement TableIdentifier
relSourcePrefix FieldName
fieldName AnnotatedOrderByElement ('Postgres pgKind) SQLExp
rest
              let selectSource :: ObjectSelectSource
selectSource =
                    Identifier -> FromItem -> BoolExp -> ObjectSelectSource
ObjectSelectSource
                      (TableIdentifier -> Identifier
tableIdentifierToIdentifier TableIdentifier
relSourcePrefix)
                      (QualifiedTable -> Maybe TableAlias -> FromItem
S.FISimple TableName ('Postgres pgKind)
QualifiedTable
relTable Maybe TableAlias
forall a. Maybe a
Nothing)
                      (Qual -> AnnBoolExpSQL ('Postgres pgKind) -> BoolExp
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual -> AnnBoolExpSQL ('Postgres pgKind) -> BoolExp
toSQLBoolExp (QualifiedTable -> Qual
S.QualTable TableName ('Postgres pgKind)
QualifiedTable
relTable) AnnBoolExpSQL ('Postgres pgKind)
AnnBoolExp ('Postgres pgKind) SQLExp
relFilter)
                  relSource :: ObjectRelationSource
relSource = RelName
-> HashMap PGCol PGCol
-> ObjectSelectSource
-> Nullable
-> ObjectRelationSource
ObjectRelationSource RelName
relName HashMap (Column ('Postgres pgKind)) (Column ('Postgres pgKind))
HashMap PGCol PGCol
colMapping ObjectSelectSource
selectSource Nullable
Nullable
              (ObjectRelationSource, InsOrdHashMap ColumnAlias SQLExp, SQLExp)
-> m (ObjectRelationSource, InsOrdHashMap ColumnAlias SQLExp,
      SQLExp)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
                ( ObjectRelationSource
relSource,
                  ColumnAlias -> SQLExp -> InsOrdHashMap ColumnAlias SQLExp
forall k v. Hashable k => k -> v -> InsOrdHashMap k v
InsOrdHashMap.singleton ColumnAlias
relOrderByAlias SQLExp
relOrdByExp,
                  TableIdentifier -> ColumnAlias -> SQLExp
forall b. IsIdentifier b => TableIdentifier -> b -> SQLExp
S.mkQIdenExp TableIdentifier
relSourcePrefix ColumnAlias
relOrderByAlias
                )
        AOCArrayAggregation RelInfo ('Postgres pgKind)
relInfo AnnBoolExp ('Postgres pgKind) SQLExp
relFilter AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
aggOrderBy -> m (ArrayRelationSource, Extractor,
   InsOrdHashMap ColumnAlias SQLExp, SQLExp)
-> m SQLExp
forall (m :: * -> *) a.
MonadWriter SelectWriter m =>
m (ArrayRelationSource, Extractor,
   InsOrdHashMap ColumnAlias SQLExp, a)
-> m a
withWriteArrayRelation (m (ArrayRelationSource, Extractor,
    InsOrdHashMap ColumnAlias SQLExp, SQLExp)
 -> m SQLExp)
-> m (ArrayRelationSource, Extractor,
      InsOrdHashMap ColumnAlias SQLExp, SQLExp)
-> m SQLExp
forall a b. (a -> b) -> a -> b
$ do
          let RelInfo {riName :: forall (b :: BackendType). RelInfo b -> RelName
riName = RelName
relName, riMapping :: forall (b :: BackendType).
RelInfo b -> HashMap (Column b) (Column b)
riMapping = HashMap (Column ('Postgres pgKind)) (Column ('Postgres pgKind))
colMapping, riTarget :: forall (b :: BackendType). RelInfo b -> RelTarget b
riTarget = RelTarget ('Postgres pgKind)
relTarget} = RelInfo ('Postgres pgKind)
relInfo
          case RelTarget ('Postgres pgKind)
relTarget of
            RelTargetNativeQuery NativeQueryName
_ -> [Char]
-> m (ArrayRelationSource, Extractor,
      InsOrdHashMap ColumnAlias SQLExp, SQLExp)
forall a. HasCallStack => [Char] -> a
error [Char]
"processAnnotatedOrderByElement RelTargetNativeQuery (AOCArrayAggregation)"
            RelTargetTable TableName ('Postgres pgKind)
relTable -> do
              let fieldName :: FieldName
fieldName = RelName -> FieldName
forall a. ToTxt a => a -> FieldName
mkOrderByFieldName RelName
relName
                  relSourcePrefix :: TableIdentifier
relSourcePrefix =
                    TableIdentifier
-> FieldName -> SimilarArrayFields -> FieldName -> TableIdentifier
mkArrayRelationSourcePrefix
                      TableIdentifier
sourcePrefix
                      FieldName
fieldAlias
                      SimilarArrayFields
similarArrayFields
                      FieldName
fieldName
                  relAlias :: TableAlias
relAlias = FieldName -> SimilarArrayFields -> FieldName -> TableAlias
mkArrayRelationAlias FieldName
fieldAlias SimilarArrayFields
similarArrayFields FieldName
fieldName
                  (Extractor
topExtractor, AggregateFields ('Postgres pgKind) SQLExp
fields) = TableIdentifier
-> AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
-> (Extractor, AggregateFields ('Postgres pgKind) SQLExp)
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
TableIdentifier
-> AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
-> (Extractor, AggregateFields ('Postgres pgKind) SQLExp)
mkAggregateOrderByExtractorAndFields TableIdentifier
relSourcePrefix AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
aggOrderBy
                  selectSource :: SelectSource
selectSource =
                    Identifier
-> FromItem -> BoolExp -> SortingAndSlicing -> SelectSource
SelectSource
                      (TableIdentifier -> Identifier
tableIdentifierToIdentifier TableIdentifier
relSourcePrefix)
                      (QualifiedTable -> Maybe TableAlias -> FromItem
S.FISimple TableName ('Postgres pgKind)
QualifiedTable
relTable Maybe TableAlias
forall a. Maybe a
Nothing)
                      (Qual -> AnnBoolExpSQL ('Postgres pgKind) -> BoolExp
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual -> AnnBoolExpSQL ('Postgres pgKind) -> BoolExp
toSQLBoolExp (QualifiedTable -> Qual
S.QualTable TableName ('Postgres pgKind)
QualifiedTable
relTable) AnnBoolExpSQL ('Postgres pgKind)
AnnBoolExp ('Postgres pgKind) SQLExp
relFilter)
                      SortingAndSlicing
noSortingAndSlicing
                  relSource :: ArrayRelationSource
relSource = TableAlias
-> HashMap PGCol PGCol -> SelectSource -> ArrayRelationSource
ArrayRelationSource TableAlias
relAlias HashMap (Column ('Postgres pgKind)) (Column ('Postgres pgKind))
HashMap PGCol PGCol
colMapping SelectSource
selectSource
              (ArrayRelationSource, Extractor, InsOrdHashMap ColumnAlias SQLExp,
 SQLExp)
-> m (ArrayRelationSource, Extractor,
      InsOrdHashMap ColumnAlias SQLExp, SQLExp)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
                ( ArrayRelationSource
relSource,
                  Extractor
topExtractor,
                  [(ColumnAlias, SQLExp)] -> InsOrdHashMap ColumnAlias SQLExp
forall k v. (Eq k, Hashable k) => [(k, v)] -> InsOrdHashMap k v
InsOrdHashMap.fromList ([(ColumnAlias, SQLExp)] -> InsOrdHashMap ColumnAlias SQLExp)
-> [(ColumnAlias, SQLExp)] -> InsOrdHashMap ColumnAlias SQLExp
forall a b. (a -> b) -> a -> b
$ TableIdentifier
-> AggregateFields ('Postgres pgKind) SQLExp
-> [(ColumnAlias, SQLExp)]
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
TableIdentifier
-> AggregateFields ('Postgres pgKind) SQLExp
-> [(ColumnAlias, SQLExp)]
aggregateFieldsToExtractorExps TableIdentifier
relSourcePrefix AggregateFields ('Postgres pgKind) SQLExp
fields,
                  TableIdentifier -> ColumnAlias -> SQLExp
forall b. IsIdentifier b => TableIdentifier -> b -> SQLExp
S.mkQIdenExp TableIdentifier
relSourcePrefix (AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp -> ColumnAlias
forall (pgKind :: PostgresKind) v.
AnnotatedAggregateOrderBy ('Postgres pgKind) v -> ColumnAlias
mkAggregateOrderByAlias AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
aggOrderBy)
                )
        AOCComputedField ComputedFieldOrderBy {ComputedFieldName
FunctionName ('Postgres pgKind)
XComputedField ('Postgres pgKind)
FunctionArgsExp ('Postgres pgKind) SQLExp
ComputedFieldOrderByElement ('Postgres pgKind) SQLExp
_cfobXField :: XComputedField ('Postgres pgKind)
_cfobName :: ComputedFieldName
_cfobFunction :: FunctionName ('Postgres pgKind)
_cfobFunctionArgsExp :: FunctionArgsExp ('Postgres pgKind) SQLExp
_cfobOrderByElement :: ComputedFieldOrderByElement ('Postgres pgKind) SQLExp
$sel:_cfobXField:ComputedFieldOrderBy :: forall (b :: BackendType) v.
ComputedFieldOrderBy b v -> XComputedField b
$sel:_cfobName:ComputedFieldOrderBy :: forall (b :: BackendType) v.
ComputedFieldOrderBy b v -> ComputedFieldName
$sel:_cfobFunction:ComputedFieldOrderBy :: forall (b :: BackendType) v.
ComputedFieldOrderBy b v -> FunctionName b
$sel:_cfobFunctionArgsExp:ComputedFieldOrderBy :: forall (b :: BackendType) v.
ComputedFieldOrderBy b v -> FunctionArgsExp b v
$sel:_cfobOrderByElement:ComputedFieldOrderBy :: forall (b :: BackendType) v.
ComputedFieldOrderBy b v -> ComputedFieldOrderByElement b v
..} ->
          case ComputedFieldOrderByElement ('Postgres pgKind) SQLExp
_cfobOrderByElement of
            CFOBEScalar ScalarType ('Postgres pgKind)
_ AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp -> do
              let functionArgs :: FunctionArgs
functionArgs = TableIdentifier
-> FunctionArgsExpG (ArgumentExp SQLExp) -> FunctionArgs
fromTableRowArgs TableIdentifier
sourcePrefix FunctionArgsExp ('Postgres pgKind) SQLExp
FunctionArgsExpG (ArgumentExp SQLExp)
_cfobFunctionArgsExp
                  functionExp :: FunctionExp
functionExp = QualifiedFunction
-> FunctionArgs -> Maybe FunctionAlias -> FunctionExp
S.FunctionExp FunctionName ('Postgres pgKind)
QualifiedFunction
_cfobFunction FunctionArgs
functionArgs Maybe FunctionAlias
forall a. Maybe a
Nothing
              SQLExp -> m SQLExp
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
                (SQLExp -> m SQLExp) -> SQLExp -> m SQLExp
forall a b. (a -> b) -> a -> b
$ 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
baseTableIdentifier Maybe TypeAnn
forall a. Maybe a
Nothing) AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp
                (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ FunctionExp -> SQLExp
S.SEFunction FunctionExp
functionExp
            CFOBETableAggregation TableName ('Postgres pgKind)
_ AnnBoolExp ('Postgres pgKind) SQLExp
tableFilter AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
aggOrderBy -> m (ComputedFieldTableSetSource, Extractor,
   InsOrdHashMap ColumnAlias SQLExp, SQLExp)
-> m SQLExp
forall (m :: * -> *) a.
MonadWriter SelectWriter m =>
m (ComputedFieldTableSetSource, Extractor,
   InsOrdHashMap ColumnAlias SQLExp, a)
-> m a
withWriteComputedFieldTableSet (m (ComputedFieldTableSetSource, Extractor,
    InsOrdHashMap ColumnAlias SQLExp, SQLExp)
 -> m SQLExp)
-> m (ComputedFieldTableSetSource, Extractor,
      InsOrdHashMap ColumnAlias SQLExp, SQLExp)
-> m SQLExp
forall a b. (a -> b) -> a -> b
$ do
              let fieldName :: FieldName
fieldName = ComputedFieldName -> FieldName
forall a. ToTxt a => a -> FieldName
mkOrderByFieldName ComputedFieldName
_cfobName
                  computedFieldSourcePrefix :: TableIdentifier
computedFieldSourcePrefix = TableIdentifier -> FieldName -> TableIdentifier
mkComputedFieldTableIdentifier TableIdentifier
sourcePrefix FieldName
fieldName
                  (Extractor
topExtractor, AggregateFields ('Postgres pgKind) SQLExp
fields) = TableIdentifier
-> AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
-> (Extractor, AggregateFields ('Postgres pgKind) SQLExp)
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
TableIdentifier
-> AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
-> (Extractor, AggregateFields ('Postgres pgKind) SQLExp)
mkAggregateOrderByExtractorAndFields TableIdentifier
computedFieldSourcePrefix AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
aggOrderBy
                  fromItem :: FromItem
fromItem =
                    TableIdentifier
-> QualifiedFunction
-> FunctionArgsExpG (ArgumentExp SQLExp)
-> FromItem
functionToFromItem TableIdentifier
sourcePrefix FunctionName ('Postgres pgKind)
QualifiedFunction
_cfobFunction FunctionArgsExp ('Postgres pgKind) SQLExp
FunctionArgsExpG (ArgumentExp SQLExp)
_cfobFunctionArgsExp
                  functionQual :: Qual
functionQual = TableIdentifier -> Maybe TypeAnn -> Qual
S.QualifiedIdentifier (Text -> TableIdentifier
TableIdentifier (Text -> TableIdentifier) -> Text -> TableIdentifier
forall a b. (a -> b) -> a -> b
$ QualifiedFunction -> Text
forall a. ToTxt a => QualifiedObject a -> Text
qualifiedObjectToText FunctionName ('Postgres pgKind)
QualifiedFunction
_cfobFunction) Maybe TypeAnn
forall a. Maybe a
Nothing
                  selectSource :: SelectSource
selectSource =
                    Identifier
-> FromItem -> BoolExp -> SortingAndSlicing -> SelectSource
SelectSource
                      (TableIdentifier -> Identifier
tableIdentifierToIdentifier TableIdentifier
computedFieldSourcePrefix)
                      FromItem
fromItem
                      (Qual -> AnnBoolExpSQL ('Postgres pgKind) -> BoolExp
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual -> AnnBoolExpSQL ('Postgres pgKind) -> BoolExp
toSQLBoolExp Qual
functionQual AnnBoolExpSQL ('Postgres pgKind)
AnnBoolExp ('Postgres pgKind) SQLExp
tableFilter)
                      SortingAndSlicing
noSortingAndSlicing
                  source :: ComputedFieldTableSetSource
source = FieldName -> SelectSource -> ComputedFieldTableSetSource
ComputedFieldTableSetSource FieldName
fieldName SelectSource
selectSource
              (ComputedFieldTableSetSource, Extractor,
 InsOrdHashMap ColumnAlias SQLExp, SQLExp)
-> m (ComputedFieldTableSetSource, Extractor,
      InsOrdHashMap ColumnAlias SQLExp, SQLExp)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
                ( ComputedFieldTableSetSource
source,
                  Extractor
topExtractor,
                  [(ColumnAlias, SQLExp)] -> InsOrdHashMap ColumnAlias SQLExp
forall k v. (Eq k, Hashable k) => [(k, v)] -> InsOrdHashMap k v
InsOrdHashMap.fromList ([(ColumnAlias, SQLExp)] -> InsOrdHashMap ColumnAlias SQLExp)
-> [(ColumnAlias, SQLExp)] -> InsOrdHashMap ColumnAlias SQLExp
forall a b. (a -> b) -> a -> b
$ TableIdentifier
-> AggregateFields ('Postgres pgKind) SQLExp
-> [(ColumnAlias, SQLExp)]
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
TableIdentifier
-> AggregateFields ('Postgres pgKind) SQLExp
-> [(ColumnAlias, SQLExp)]
aggregateFieldsToExtractorExps TableIdentifier
computedFieldSourcePrefix AggregateFields ('Postgres pgKind) SQLExp
fields,
                  TableIdentifier -> ColumnAlias -> SQLExp
forall b. IsIdentifier b => TableIdentifier -> b -> SQLExp
S.mkQIdenExp TableIdentifier
computedFieldSourcePrefix (AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp -> ColumnAlias
forall (pgKind :: PostgresKind) v.
AnnotatedAggregateOrderBy ('Postgres pgKind) v -> ColumnAlias
mkAggregateOrderByAlias AnnotatedAggregateOrderBy ('Postgres pgKind) SQLExp
aggOrderBy)
                )

    functionToFromItem :: TableIdentifier -> QualifiedFunction -> FunctionArgsExpG (ArgumentExp S.SQLExp) -> S.FromItem
    functionToFromItem :: TableIdentifier
-> QualifiedFunction
-> FunctionArgsExpG (ArgumentExp SQLExp)
-> FromItem
functionToFromItem TableIdentifier
prefix QualifiedFunction
qf FunctionArgsExpG (ArgumentExp SQLExp)
args =
      FunctionExp -> FromItem
S.FIFunc
        (FunctionExp -> FromItem) -> FunctionExp -> FromItem
forall a b. (a -> b) -> a -> b
$ QualifiedFunction
-> FunctionArgs -> Maybe FunctionAlias -> FunctionExp
S.FunctionExp QualifiedFunction
qf (TableIdentifier
-> FunctionArgsExpG (ArgumentExp SQLExp) -> FunctionArgs
fromTableRowArgs TableIdentifier
prefix FunctionArgsExpG (ArgumentExp SQLExp)
args)
        (Maybe FunctionAlias -> FunctionExp)
-> Maybe FunctionAlias -> FunctionExp
forall a b. (a -> b) -> a -> b
$ FunctionAlias -> Maybe FunctionAlias
forall a. a -> Maybe a
Just
        (FunctionAlias -> Maybe FunctionAlias)
-> FunctionAlias -> Maybe FunctionAlias
forall a b. (a -> b) -> a -> b
$ QualifiedFunction
-> Maybe [(ColumnAlias, PGScalarType)] -> FunctionAlias
S.mkFunctionAlias QualifiedFunction
qf Maybe [(ColumnAlias, PGScalarType)]
forall a. Maybe a
Nothing

    generateSorting ::
      NE.NonEmpty (OrderByItemG ('Postgres pgKind) (AnnotatedOrderByElement ('Postgres pgKind) S.SQLExp, (S.ColumnAlias, S.SQLExp))) ->
      ( SelectSorting,
        [(S.ColumnAlias, S.SQLExp)] -- 'distinct on' column extractors
      )
    generateSorting :: NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp)))
-> (SelectSorting, [(ColumnAlias, SQLExp)])
generateSorting orderByExps :: NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp)))
orderByExps@(OrderByItemG
  ('Postgres pgKind)
  (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
   (ColumnAlias, SQLExp))
firstOrderBy NE.:| [OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))]
restOrderBys) =
      case (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
 (ColumnAlias, SQLExp))
-> AnnotatedOrderByElement ('Postgres pgKind) SQLExp
forall a b. (a, b) -> a
fst ((AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
  (ColumnAlias, SQLExp))
 -> AnnotatedOrderByElement ('Postgres pgKind) SQLExp)
-> (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))
-> AnnotatedOrderByElement ('Postgres pgKind) SQLExp
forall a b. (a -> b) -> a -> b
$ OrderByItemG
  ('Postgres pgKind)
  (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
   (ColumnAlias, SQLExp))
-> (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))
forall (b :: BackendType) a. OrderByItemG b a -> a
obiColumn OrderByItemG
  ('Postgres pgKind)
  (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
   (ColumnAlias, SQLExp))
firstOrderBy of
        AOCColumn ColumnInfo ('Postgres pgKind)
columnInfo AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp ->
          -- If rest order by expressions are all columns then apply order by clause at base selection.
          if (OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))
 -> Bool)
-> [OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
       (ColumnAlias, SQLExp))]
-> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Maybe
  (ColumnInfo ('Postgres pgKind),
   AnnRedactionExp ('Postgres pgKind) SQLExp)
-> Bool
forall a. Maybe a -> Bool
isJust (Maybe
   (ColumnInfo ('Postgres pgKind),
    AnnRedactionExp ('Postgres pgKind) SQLExp)
 -> Bool)
-> (OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
       (ColumnAlias, SQLExp))
    -> Maybe
         (ColumnInfo ('Postgres pgKind),
          AnnRedactionExp ('Postgres pgKind) SQLExp))
-> OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp))
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
 (ColumnAlias, SQLExp))
-> Maybe
     (ColumnInfo ('Postgres pgKind),
      AnnRedactionExp ('Postgres pgKind) SQLExp)
forall {b :: BackendType} {v} {b}.
(AnnotatedOrderByElement b v, b)
-> Maybe (ColumnInfo b, AnnRedactionExp b v)
getColumnOrderBy ((AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
  (ColumnAlias, SQLExp))
 -> Maybe
      (ColumnInfo ('Postgres pgKind),
       AnnRedactionExp ('Postgres pgKind) SQLExp))
-> (OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
       (ColumnAlias, SQLExp))
    -> (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
        (ColumnAlias, SQLExp)))
-> OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp))
-> Maybe
     (ColumnInfo ('Postgres pgKind),
      AnnRedactionExp ('Postgres pgKind) SQLExp)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OrderByItemG
  ('Postgres pgKind)
  (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
   (ColumnAlias, SQLExp))
-> (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))
forall (b :: BackendType) a. OrderByItemG b a -> a
obiColumn) [OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))]
restOrderBys
            then -- Collect column order by expressions from the rest.

              let restColumnOrderBys :: [OrderByItemG
   ('Postgres pgKind)
   (ColumnInfo ('Postgres pgKind),
    AnnRedactionExp ('Postgres pgKind) SQLExp)]
restColumnOrderBys = (OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))
 -> Maybe
      (OrderByItemG
         ('Postgres pgKind)
         (ColumnInfo ('Postgres pgKind),
          AnnRedactionExp ('Postgres pgKind) SQLExp)))
-> [OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
       (ColumnAlias, SQLExp))]
-> [OrderByItemG
      ('Postgres pgKind)
      (ColumnInfo ('Postgres pgKind),
       AnnRedactionExp ('Postgres pgKind) SQLExp)]
forall a b. (a -> Maybe b) -> [a] -> [b]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe (((AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
  (ColumnAlias, SQLExp))
 -> Maybe
      (ColumnInfo ('Postgres pgKind),
       AnnRedactionExp ('Postgres pgKind) SQLExp))
-> OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp))
-> Maybe
     (OrderByItemG
        ('Postgres pgKind)
        (ColumnInfo ('Postgres pgKind),
         AnnRedactionExp ('Postgres pgKind) SQLExp))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b)
-> OrderByItemG ('Postgres pgKind) a
-> f (OrderByItemG ('Postgres pgKind) b)
traverse (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
 (ColumnAlias, SQLExp))
-> Maybe
     (ColumnInfo ('Postgres pgKind),
      AnnRedactionExp ('Postgres pgKind) SQLExp)
forall {b :: BackendType} {v} {b}.
(AnnotatedOrderByElement b v, b)
-> Maybe (ColumnInfo b, AnnRedactionExp b v)
getColumnOrderBy) [OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))]
restOrderBys
                  firstColumnOrderBy :: OrderByItemG
  ('Postgres pgKind)
  (ColumnInfo ('Postgres pgKind),
   AnnRedactionExp ('Postgres pgKind) SQLExp)
firstColumnOrderBy = OrderByItemG
  ('Postgres pgKind)
  (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
   (ColumnAlias, SQLExp))
firstOrderBy {obiColumn :: (ColumnInfo ('Postgres pgKind),
 AnnRedactionExp ('Postgres pgKind) SQLExp)
obiColumn = (ColumnInfo ('Postgres pgKind)
columnInfo, AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp)}
               in NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (ColumnInfo ('Postgres pgKind),
      AnnRedactionExp ('Postgres pgKind) SQLExp))
-> (SelectSorting, [(ColumnAlias, SQLExp)])
sortAtNodeAndBase (NonEmpty
   (OrderByItemG
      ('Postgres pgKind)
      (ColumnInfo ('Postgres pgKind),
       AnnRedactionExp ('Postgres pgKind) SQLExp))
 -> (SelectSorting, [(ColumnAlias, SQLExp)]))
-> NonEmpty
     (OrderByItemG
        ('Postgres pgKind)
        (ColumnInfo ('Postgres pgKind),
         AnnRedactionExp ('Postgres pgKind) SQLExp))
-> (SelectSorting, [(ColumnAlias, SQLExp)])
forall a b. (a -> b) -> a -> b
$ OrderByItemG
  ('Postgres pgKind)
  (ColumnInfo ('Postgres pgKind),
   AnnRedactionExp ('Postgres pgKind) SQLExp)
firstColumnOrderBy OrderByItemG
  ('Postgres pgKind)
  (ColumnInfo ('Postgres pgKind),
   AnnRedactionExp ('Postgres pgKind) SQLExp)
-> [OrderByItemG
      ('Postgres pgKind)
      (ColumnInfo ('Postgres pgKind),
       AnnRedactionExp ('Postgres pgKind) SQLExp)]
-> NonEmpty
     (OrderByItemG
        ('Postgres pgKind)
        (ColumnInfo ('Postgres pgKind),
         AnnRedactionExp ('Postgres pgKind) SQLExp))
forall a. a -> [a] -> NonEmpty a
NE.:| [OrderByItemG
   ('Postgres pgKind)
   (ColumnInfo ('Postgres pgKind),
    AnnRedactionExp ('Postgres pgKind) SQLExp)]
restColumnOrderBys
            else -- Else rest order by expressions contain atleast one non-column order by.
            -- So, apply order by clause at node selection.
              (SelectSorting, [(ColumnAlias, SQLExp)])
sortOnlyAtNode
        AnnotatedOrderByElement ('Postgres pgKind) SQLExp
_ ->
          -- First order by expression is non-column. So, apply order by clause at node selection.
          (SelectSorting, [(ColumnAlias, SQLExp)])
sortOnlyAtNode
      where
        getColumnOrderBy :: (AnnotatedOrderByElement b v, b)
-> Maybe (ColumnInfo b, AnnRedactionExp b v)
getColumnOrderBy = (AnnotatedOrderByElement b v
-> Getting
     (First (ColumnInfo b, AnnRedactionExp b v))
     (AnnotatedOrderByElement b v)
     (ColumnInfo b, AnnRedactionExp b v)
-> Maybe (ColumnInfo b, AnnRedactionExp b v)
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting
  (First (ColumnInfo b, AnnRedactionExp b v))
  (AnnotatedOrderByElement b v)
  (ColumnInfo b, AnnRedactionExp b v)
forall (b :: BackendType) v (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p (ColumnInfo b, AnnRedactionExp b v)
  (f (ColumnInfo b, AnnRedactionExp b v))
-> p (AnnotatedOrderByElement b v)
     (f (AnnotatedOrderByElement b v))
_AOCColumn) (AnnotatedOrderByElement b v
 -> Maybe (ColumnInfo b, AnnRedactionExp b v))
-> ((AnnotatedOrderByElement b v, b)
    -> AnnotatedOrderByElement b v)
-> (AnnotatedOrderByElement b v, b)
-> Maybe (ColumnInfo b, AnnRedactionExp b v)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (AnnotatedOrderByElement b v, b) -> AnnotatedOrderByElement b v
forall a b. (a, b) -> a
fst

        (OrderByExp
nodeOrderBy, Maybe DistinctExpr
nodeDistinctOn, [(ColumnAlias, SQLExp)]
nodeDistinctOnExtractors) =
          let toOrderByExp :: OrderByItemG b (a, (a, b)) -> OrderByItem
toOrderByExp OrderByItemG b (a, (a, b))
orderByItemExp =
                let OrderByItemG Maybe (BasicOrderType b)
obTyM a
expAlias Maybe (NullsOrderType b)
obNullsM = (a, b) -> a
forall a b. (a, b) -> a
fst ((a, b) -> a) -> ((a, (a, b)) -> (a, b)) -> (a, (a, b)) -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a, (a, b)) -> (a, b)
forall a b. (a, b) -> b
snd ((a, (a, b)) -> a)
-> OrderByItemG b (a, (a, b)) -> OrderByItemG b a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> OrderByItemG b (a, (a, b))
orderByItemExp
                 in SQLExp -> Maybe OrderType -> Maybe NullsOrder -> OrderByItem
S.OrderByItem (Identifier -> SQLExp
S.SEIdentifier (Identifier -> SQLExp) -> Identifier -> SQLExp
forall a b. (a -> b) -> a -> b
$ a -> Identifier
forall a. IsIdentifier a => a -> Identifier
toIdentifier a
expAlias) Maybe (BasicOrderType b)
Maybe OrderType
obTyM Maybe (NullsOrderType b)
Maybe NullsOrder
obNullsM
              orderByExp :: OrderByExp
orderByExp = NonEmpty OrderByItem -> OrderByExp
S.OrderByExp (NonEmpty OrderByItem -> OrderByExp)
-> NonEmpty OrderByItem -> OrderByExp
forall a b. (a -> b) -> a -> b
$ OrderByItemG
  ('Postgres pgKind)
  (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
   (ColumnAlias, SQLExp))
-> OrderByItem
forall {b :: BackendType} {a} {a} {b}.
(BasicOrderType b ~ OrderType, NullsOrderType b ~ NullsOrder,
 IsIdentifier a) =>
OrderByItemG b (a, (a, b)) -> OrderByItem
toOrderByExp (OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))
 -> OrderByItem)
-> NonEmpty
     (OrderByItemG
        ('Postgres pgKind)
        (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
         (ColumnAlias, SQLExp)))
-> NonEmpty OrderByItem
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
      (ColumnAlias, SQLExp)))
orderByExps
              (Maybe DistinctExpr
maybeDistOn, Maybe [(ColumnAlias, SQLExp)]
distOnExtrs) = Maybe (DistinctExpr, [(ColumnAlias, SQLExp)])
-> (Maybe DistinctExpr, Maybe [(ColumnAlias, SQLExp)])
forall (f :: * -> *) a b. Functor f => f (a, b) -> (f a, f b)
NE.unzip (Maybe (DistinctExpr, [(ColumnAlias, SQLExp)])
 -> (Maybe DistinctExpr, Maybe [(ColumnAlias, SQLExp)]))
-> Maybe (DistinctExpr, [(ColumnAlias, SQLExp)])
-> (Maybe DistinctExpr, Maybe [(ColumnAlias, SQLExp)])
forall a b. (a -> b) -> a -> b
$ TableIdentifier
-> NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> (DistinctExpr, [(ColumnAlias, SQLExp)])
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
TableIdentifier
-> NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> (DistinctExpr, [(ColumnAlias, SQLExp)])
applyDistinctOnAtNode TableIdentifier
sourcePrefix' (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
 -> (DistinctExpr, [(ColumnAlias, SQLExp)]))
-> Maybe (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp))
-> Maybe (DistinctExpr, [(ColumnAlias, SQLExp)])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp))
distOnCols
           in (OrderByExp
orderByExp, Maybe DistinctExpr
maybeDistOn, [(ColumnAlias, SQLExp)]
-> Maybe [(ColumnAlias, SQLExp)] -> [(ColumnAlias, SQLExp)]
forall a. a -> Maybe a -> a
fromMaybe [] Maybe [(ColumnAlias, SQLExp)]
distOnExtrs)

        sortOnlyAtNode :: (SelectSorting, [(ColumnAlias, SQLExp)])
sortOnlyAtNode =
          (DistinctAndOrderByExpr -> SelectSorting
Sorting (DistinctAndOrderByExpr -> SelectSorting)
-> DistinctAndOrderByExpr -> SelectSorting
forall a b. (a -> b) -> a -> b
$ (OrderByExp, Maybe DistinctExpr)
-> Maybe (OrderByExp, Maybe DistinctExpr) -> DistinctAndOrderByExpr
ASorting (OrderByExp
nodeOrderBy, Maybe DistinctExpr
nodeDistinctOn) Maybe (OrderByExp, Maybe DistinctExpr)
forall a. Maybe a
Nothing, [(ColumnAlias, SQLExp)]
nodeDistinctOnExtractors)

        sortAtNodeAndBase :: NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (ColumnInfo ('Postgres pgKind),
      AnnRedactionExp ('Postgres pgKind) SQLExp))
-> (SelectSorting, [(ColumnAlias, SQLExp)])
sortAtNodeAndBase NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (ColumnInfo ('Postgres pgKind),
      AnnRedactionExp ('Postgres pgKind) SQLExp))
baseColumnOrderBys =
          let mkBaseOrderByItem :: OrderByItemG
  ('Postgres pgKind)
  (ColumnInfo ('Postgres pgKind),
   AnnRedactionExp ('Postgres pgKind) SQLExp)
-> OrderByItem
mkBaseOrderByItem (OrderByItemG Maybe (BasicOrderType ('Postgres pgKind))
orderByType (ColumnInfo ('Postgres pgKind)
columnInfo, AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp) Maybe (NullsOrderType ('Postgres pgKind))
nullsOrder) =
                let columnExp :: SQLExp
columnExp =
                      Qual
-> AnnRedactionExp ('Postgres pgKind) SQLExp -> SQLExp -> SQLExp
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual
-> AnnRedactionExp ('Postgres pgKind) SQLExp -> SQLExp -> SQLExp
withRedactionExp Qual
selectSourceQual AnnRedactionExp ('Postgres pgKind) SQLExp
redactionExp
                        (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ PGCol -> SQLExp
forall a. IsIdentifier a => a -> SQLExp
S.mkSIdenExp (ColumnInfo ('Postgres pgKind) -> Column ('Postgres pgKind)
forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn ColumnInfo ('Postgres pgKind)
columnInfo)
                 in SQLExp -> Maybe OrderType -> Maybe NullsOrder -> OrderByItem
S.OrderByItem SQLExp
columnExp Maybe (BasicOrderType ('Postgres pgKind))
Maybe OrderType
orderByType Maybe (NullsOrderType ('Postgres pgKind))
Maybe NullsOrder
nullsOrder
              baseOrderByExp :: OrderByExp
baseOrderByExp = NonEmpty OrderByItem -> OrderByExp
S.OrderByExp (NonEmpty OrderByItem -> OrderByExp)
-> NonEmpty OrderByItem -> OrderByExp
forall a b. (a -> b) -> a -> b
$ OrderByItemG
  ('Postgres pgKind)
  (ColumnInfo ('Postgres pgKind),
   AnnRedactionExp ('Postgres pgKind) SQLExp)
-> OrderByItem
mkBaseOrderByItem (OrderByItemG
   ('Postgres pgKind)
   (ColumnInfo ('Postgres pgKind),
    AnnRedactionExp ('Postgres pgKind) SQLExp)
 -> OrderByItem)
-> NonEmpty
     (OrderByItemG
        ('Postgres pgKind)
        (ColumnInfo ('Postgres pgKind),
         AnnRedactionExp ('Postgres pgKind) SQLExp))
-> NonEmpty OrderByItem
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonEmpty
  (OrderByItemG
     ('Postgres pgKind)
     (ColumnInfo ('Postgres pgKind),
      AnnRedactionExp ('Postgres pgKind) SQLExp))
baseColumnOrderBys
              baseDistOnExp :: Maybe DistinctExpr
baseDistOnExp = Qual
-> NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> DistinctExpr
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual
-> NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> DistinctExpr
applyDistinctOnAtBase Qual
selectSourceQual (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
 -> DistinctExpr)
-> Maybe (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp))
-> Maybe DistinctExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp))
distOnCols
              sorting :: SelectSorting
sorting = DistinctAndOrderByExpr -> SelectSorting
Sorting (DistinctAndOrderByExpr -> SelectSorting)
-> DistinctAndOrderByExpr -> SelectSorting
forall a b. (a -> b) -> a -> b
$ (OrderByExp, Maybe DistinctExpr)
-> Maybe (OrderByExp, Maybe DistinctExpr) -> DistinctAndOrderByExpr
ASorting (OrderByExp
nodeOrderBy, Maybe DistinctExpr
nodeDistinctOn) (Maybe (OrderByExp, Maybe DistinctExpr) -> DistinctAndOrderByExpr)
-> Maybe (OrderByExp, Maybe DistinctExpr) -> DistinctAndOrderByExpr
forall a b. (a -> b) -> a -> b
$ (OrderByExp, Maybe DistinctExpr)
-> Maybe (OrderByExp, Maybe DistinctExpr)
forall a. a -> Maybe a
Just (OrderByExp
baseOrderByExp, Maybe DistinctExpr
baseDistOnExp)
           in (SelectSorting
sorting, [(ColumnAlias, SQLExp)]
nodeDistinctOnExtractors)

    mkCursorExp ::
      [OrderByItemG ('Postgres pgKind) (AnnotatedOrderByElement ('Postgres pgKind) (SQLExpression ('Postgres pgKind)), (S.ColumnAlias, SQLExpression ('Postgres pgKind)))] ->
      S.SQLExp
    mkCursorExp :: [OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement
      ('Postgres pgKind) (SQLExpression ('Postgres pgKind)),
    (ColumnAlias, SQLExpression ('Postgres pgKind)))]
-> SQLExp
mkCursorExp [OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement
      ('Postgres pgKind) (SQLExpression ('Postgres pgKind)),
    (ColumnAlias, SQLExpression ('Postgres pgKind)))]
orderByItemExps =
      [SQLExp] -> SQLExp
S.applyJsonBuildObj
        ([SQLExp] -> SQLExp) -> [SQLExp] -> SQLExp
forall a b. (a -> b) -> a -> b
$ ((OrderByItemG
    ('Postgres pgKind)
    (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
     (ColumnAlias, SQLExp))
  -> [SQLExp])
 -> [OrderByItemG
       ('Postgres pgKind)
       (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
        (ColumnAlias, SQLExp))]
 -> [SQLExp])
-> [OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
       (ColumnAlias, SQLExp))]
-> (OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
       (ColumnAlias, SQLExp))
    -> [SQLExp])
-> [SQLExp]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))
 -> [SQLExp])
-> [OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
       (ColumnAlias, SQLExp))]
-> [SQLExp]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap [OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement
      ('Postgres pgKind) (SQLExpression ('Postgres pgKind)),
    (ColumnAlias, SQLExpression ('Postgres pgKind)))]
[OrderByItemG
   ('Postgres pgKind)
   (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
    (ColumnAlias, SQLExp))]
orderByItemExps
        ((OrderByItemG
    ('Postgres pgKind)
    (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
     (ColumnAlias, SQLExp))
  -> [SQLExp])
 -> [SQLExp])
-> (OrderByItemG
      ('Postgres pgKind)
      (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
       (ColumnAlias, SQLExp))
    -> [SQLExp])
-> [SQLExp]
forall a b. (a -> b) -> a -> b
$ \OrderByItemG
  ('Postgres pgKind)
  (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
   (ColumnAlias, SQLExp))
orderByItemExp ->
          let OrderByItemG Maybe (BasicOrderType ('Postgres pgKind))
_ (AnnotatedOrderByElement ('Postgres pgKind) SQLExp
annObCol, (ColumnAlias
_, SQLExp
valExp)) Maybe (NullsOrderType ('Postgres pgKind))
_ = OrderByItemG
  ('Postgres pgKind)
  (AnnotatedOrderByElement ('Postgres pgKind) SQLExp,
   (ColumnAlias, SQLExp))
orderByItemExp
           in SQLExp
-> AnnotatedOrderByElement ('Postgres pgKind) SQLExp -> [SQLExp]
forall {b :: BackendType} {v}.
(Column b ~ PGCol) =>
SQLExp -> AnnotatedOrderByElement b v -> [SQLExp]
annObColToJSONField SQLExp
valExp AnnotatedOrderByElement ('Postgres pgKind) SQLExp
annObCol
      where
        mkAggOrderByValExp :: SQLExp -> AnnotatedAggregateOrderBy b v -> [SQLExp]
mkAggOrderByValExp SQLExp
valExp = \case
          AnnotatedAggregateOrderBy b v
AAOCount -> [Text -> SQLExp
S.SELit Text
"count", SQLExp
valExp]
          AAOOp (AggregateOrderByColumn Text
opText ColumnType b
_resultType ColumnInfo b
colInfo AnnRedactionExp b v
_redactionExp) ->
            [ Text -> SQLExp
S.SELit Text
opText,
              [SQLExp] -> SQLExp
S.applyJsonBuildObj [Text -> SQLExp
S.SELit (Text -> SQLExp) -> Text -> SQLExp
forall a b. (a -> b) -> a -> b
$ PGCol -> Text
getPGColTxt (PGCol -> Text) -> PGCol -> Text
forall a b. (a -> b) -> a -> b
$ ColumnInfo b -> Column b
forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn ColumnInfo b
colInfo, SQLExp
valExp]
            ]

        annObColToJSONField :: SQLExp -> AnnotatedOrderByElement b v -> [SQLExp]
annObColToJSONField SQLExp
valExp = \case
          AOCColumn ColumnInfo b
pgCol AnnRedactionExp b v
_redactionExp -> [Text -> SQLExp
S.SELit (Text -> SQLExp) -> Text -> SQLExp
forall a b. (a -> b) -> a -> b
$ PGCol -> Text
getPGColTxt (PGCol -> Text) -> PGCol -> Text
forall a b. (a -> b) -> a -> b
$ ColumnInfo b -> Column b
forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn ColumnInfo b
pgCol, SQLExp
valExp]
          AOCObjectRelation RelInfo b
relInfo AnnBoolExp b v
_ AnnotatedOrderByElement b v
obCol ->
            [ Text -> SQLExp
S.SELit (Text -> SQLExp) -> Text -> SQLExp
forall a b. (a -> b) -> a -> b
$ RelName -> Text
relNameToTxt (RelName -> Text) -> RelName -> Text
forall a b. (a -> b) -> a -> b
$ RelInfo b -> RelName
forall (b :: BackendType). RelInfo b -> RelName
riName RelInfo b
relInfo,
              [SQLExp] -> SQLExp
S.applyJsonBuildObj ([SQLExp] -> SQLExp) -> [SQLExp] -> SQLExp
forall a b. (a -> b) -> a -> b
$ SQLExp -> AnnotatedOrderByElement b v -> [SQLExp]
annObColToJSONField SQLExp
valExp AnnotatedOrderByElement b v
obCol
            ]
          AOCArrayAggregation RelInfo b
relInfo AnnBoolExp b v
_ AnnotatedAggregateOrderBy b v
aggOrderBy ->
            [ Text -> SQLExp
S.SELit (Text -> SQLExp) -> Text -> SQLExp
forall a b. (a -> b) -> a -> b
$ RelName -> Text
relNameToTxt (RelInfo b -> RelName
forall (b :: BackendType). RelInfo b -> RelName
riName RelInfo b
relInfo) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_aggregate",
              [SQLExp] -> SQLExp
S.applyJsonBuildObj ([SQLExp] -> SQLExp) -> [SQLExp] -> SQLExp
forall a b. (a -> b) -> a -> b
$ SQLExp -> AnnotatedAggregateOrderBy b v -> [SQLExp]
forall {b :: BackendType} {v}.
(Column b ~ PGCol) =>
SQLExp -> AnnotatedAggregateOrderBy b v -> [SQLExp]
mkAggOrderByValExp SQLExp
valExp AnnotatedAggregateOrderBy b v
aggOrderBy
            ]
          AOCComputedField ComputedFieldOrderBy b v
cfOrderBy ->
            let fieldNameText :: Text
fieldNameText = ComputedFieldName -> Text
computedFieldNameToText (ComputedFieldName -> Text) -> ComputedFieldName -> Text
forall a b. (a -> b) -> a -> b
$ ComputedFieldOrderBy b v -> ComputedFieldName
forall (b :: BackendType) v.
ComputedFieldOrderBy b v -> ComputedFieldName
_cfobName ComputedFieldOrderBy b v
cfOrderBy
             in case ComputedFieldOrderBy b v -> ComputedFieldOrderByElement b v
forall (b :: BackendType) v.
ComputedFieldOrderBy b v -> ComputedFieldOrderByElement b v
_cfobOrderByElement ComputedFieldOrderBy b v
cfOrderBy of
                  CFOBEScalar ScalarType b
_ AnnRedactionExp b v
_redactionExp -> [Text -> SQLExp
S.SELit Text
fieldNameText, SQLExp
valExp]
                  CFOBETableAggregation TableName b
_ AnnBoolExp b v
_ AnnotatedAggregateOrderBy b v
aggOrderBy ->
                    [ Text -> SQLExp
S.SELit (Text -> SQLExp) -> Text -> SQLExp
forall a b. (a -> b) -> a -> b
$ Text
fieldNameText Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_aggregate",
                      [SQLExp] -> SQLExp
S.applyJsonBuildObj ([SQLExp] -> SQLExp) -> [SQLExp] -> SQLExp
forall a b. (a -> b) -> a -> b
$ SQLExp -> AnnotatedAggregateOrderBy b v -> [SQLExp]
forall {b :: BackendType} {v}.
(Column b ~ PGCol) =>
SQLExp -> AnnotatedAggregateOrderBy b v -> [SQLExp]
mkAggOrderByValExp SQLExp
valExp AnnotatedAggregateOrderBy b v
aggOrderBy
                    ]

applyDistinctOnAtBase ::
  forall pgKind.
  (Backend ('Postgres pgKind)) =>
  S.Qual ->
  NE.NonEmpty (AnnDistinctColumn ('Postgres pgKind) S.SQLExp) ->
  S.DistinctExpr
applyDistinctOnAtBase :: forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual
-> NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> DistinctExpr
applyDistinctOnAtBase Qual
selectSourceQual NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
distinctColumns =
  let distinctExps :: [SQLExp]
distinctExps =
        NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
distinctColumns
          NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> (NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
    -> [AnnDistinctColumn ('Postgres pgKind) SQLExp])
-> [AnnDistinctColumn ('Postgres pgKind) SQLExp]
forall a b. a -> (a -> b) -> b
& NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> [AnnDistinctColumn ('Postgres pgKind) SQLExp]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList
          [AnnDistinctColumn ('Postgres pgKind) SQLExp]
-> (AnnDistinctColumn ('Postgres pgKind) SQLExp -> SQLExp)
-> [SQLExp]
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (\AnnDistinctColumn {Column ('Postgres pgKind)
AnnRedactionExp ('Postgres pgKind) SQLExp
_adcColumn :: Column ('Postgres pgKind)
_adcRedactionExpression :: AnnRedactionExp ('Postgres pgKind) SQLExp
$sel:_adcColumn:AnnDistinctColumn :: forall (b :: BackendType) v. AnnDistinctColumn b v -> Column b
$sel:_adcRedactionExpression:AnnDistinctColumn :: forall (b :: BackendType) v.
AnnDistinctColumn b v -> AnnRedactionExp b v
..} -> Qual
-> AnnRedactionExp ('Postgres pgKind) SQLExp -> SQLExp -> SQLExp
forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
Qual
-> AnnRedactionExp ('Postgres pgKind) SQLExp -> SQLExp -> SQLExp
withRedactionExp Qual
selectSourceQual AnnRedactionExp ('Postgres pgKind) SQLExp
_adcRedactionExpression (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ PGCol -> SQLExp
forall a. IsIdentifier a => a -> SQLExp
S.mkSIdenExp Column ('Postgres pgKind)
PGCol
_adcColumn)
   in [SQLExp] -> DistinctExpr
S.DistinctOn [SQLExp]
distinctExps

applyDistinctOnAtNode ::
  forall pgKind.
  (Backend ('Postgres pgKind)) =>
  TableIdentifier ->
  NE.NonEmpty (AnnDistinctColumn ('Postgres pgKind) S.SQLExp) ->
  ( S.DistinctExpr,
    [(S.ColumnAlias, S.SQLExp)] -- additional column extractors
  )
applyDistinctOnAtNode :: forall (pgKind :: PostgresKind).
Backend ('Postgres pgKind) =>
TableIdentifier
-> NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> (DistinctExpr, [(ColumnAlias, SQLExp)])
applyDistinctOnAtNode TableIdentifier
pfx NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
distinctColumns = (DistinctExpr
distinctOnExp, [(ColumnAlias, SQLExp)]
extractors)
  where
    columns :: [PGCol]
columns = AnnDistinctColumn ('Postgres pgKind) SQLExp
-> Column ('Postgres pgKind)
AnnDistinctColumn ('Postgres pgKind) SQLExp -> PGCol
forall (b :: BackendType) v. AnnDistinctColumn b v -> Column b
_adcColumn (AnnDistinctColumn ('Postgres pgKind) SQLExp -> PGCol)
-> [AnnDistinctColumn ('Postgres pgKind) SQLExp] -> [PGCol]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> [AnnDistinctColumn ('Postgres pgKind) SQLExp]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
distinctColumns
    distinctOnExp :: DistinctExpr
distinctOnExp = [SQLExp] -> DistinctExpr
S.DistinctOn ([SQLExp] -> DistinctExpr) -> [SQLExp] -> DistinctExpr
forall a b. (a -> b) -> a -> b
$ (PGCol -> SQLExp) -> [PGCol] -> [SQLExp]
forall a b. (a -> b) -> [a] -> [b]
map (Identifier -> SQLExp
S.SEIdentifier (Identifier -> SQLExp) -> (PGCol -> Identifier) -> PGCol -> SQLExp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ColumnAlias -> Identifier
forall a. IsIdentifier a => a -> Identifier
toIdentifier (ColumnAlias -> Identifier)
-> (PGCol -> ColumnAlias) -> PGCol -> Identifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PGCol -> ColumnAlias
mkQColAlias) [PGCol]
columns
    baseTableIdentifier :: TableIdentifier
baseTableIdentifier = TableIdentifier -> TableIdentifier
mkBaseTableIdentifier TableIdentifier
pfx
    mkExtractor :: AnnDistinctColumn ('Postgres pgKind) SQLExp
-> (ColumnAlias, SQLExp)
mkExtractor AnnDistinctColumn {Column ('Postgres pgKind)
AnnRedactionExp ('Postgres pgKind) SQLExp
$sel:_adcColumn:AnnDistinctColumn :: forall (b :: BackendType) v. AnnDistinctColumn b v -> Column b
$sel:_adcRedactionExpression:AnnDistinctColumn :: forall (b :: BackendType) v.
AnnDistinctColumn b v -> AnnRedactionExp b v
_adcColumn :: Column ('Postgres pgKind)
_adcRedactionExpression :: AnnRedactionExp ('Postgres pgKind) SQLExp
..} =
      let extractorExp :: SQLExp
extractorExp =
            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
baseTableIdentifier Maybe TypeAnn
forall a. Maybe a
Nothing) AnnRedactionExp ('Postgres pgKind) SQLExp
_adcRedactionExpression
              (SQLExp -> SQLExp) -> SQLExp -> SQLExp
forall a b. (a -> b) -> a -> b
$ TableIdentifier -> PGCol -> SQLExp
forall b. IsIdentifier b => TableIdentifier -> b -> SQLExp
S.mkQIdenExp TableIdentifier
baseTableIdentifier Column ('Postgres pgKind)
PGCol
_adcColumn
       in (PGCol -> ColumnAlias
mkQColAlias Column ('Postgres pgKind)
PGCol
_adcColumn, SQLExp
extractorExp)
    mkQColAlias :: PGCol -> ColumnAlias
mkQColAlias = TableIdentifier -> PGCol -> ColumnAlias
contextualizeBaseTableColumn TableIdentifier
pfx
    extractors :: [(ColumnAlias, SQLExp)]
extractors = AnnDistinctColumn ('Postgres pgKind) SQLExp
-> (ColumnAlias, SQLExp)
mkExtractor (AnnDistinctColumn ('Postgres pgKind) SQLExp
 -> (ColumnAlias, SQLExp))
-> [AnnDistinctColumn ('Postgres pgKind) SQLExp]
-> [(ColumnAlias, SQLExp)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
-> [AnnDistinctColumn ('Postgres pgKind) SQLExp]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList NonEmpty (AnnDistinctColumn ('Postgres pgKind) SQLExp)
distinctColumns