{-# LANGUAGE ApplicativeDo #-}

-- | This module defines the schema aspect of the default implementation of
-- aggregation predicates.
module Hasura.GraphQL.Schema.BoolExp.AggregationPredicates
  ( defaultAggregationPredicatesParser,

    -- * Data types describing aggregation functions supported by a backend
    FunctionSignature (..),
    ArgumentsSignature (..),
    ArgumentSignature (..),
  )
where

import Data.Functor.Compose
import Data.List.NonEmpty qualified as NE
import Hasura.GraphQL.Parser qualified as P
import Hasura.GraphQL.Schema.Backend
import Hasura.GraphQL.Schema.BoolExp
import Hasura.GraphQL.Schema.Common (MonadBuildSchemaBase, askTableInfo, textToName)
import Hasura.GraphQL.Schema.Parser
  ( InputFieldsParser,
    Kind (..),
    Parser,
  )
import Hasura.GraphQL.Schema.Table
import Hasura.Name qualified as Name
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp.AggregationPredicates
import Hasura.RQL.IR.Value
import Hasura.RQL.Types.Backend qualified as B
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common (relNameToTxt)
import Hasura.RQL.Types.Relationships.Local
import Hasura.RQL.Types.SchemaCache hiding (askTableInfo)
import Hasura.RQL.Types.Source
import Hasura.RQL.Types.Table
import Hasura.SQL.Backend (BackendType)
import Language.GraphQL.Draft.Syntax qualified as G

-- | This function is meant to serve as the default schema for Aggregation
-- Predicates represented in the IR by the type
-- 'Hasura.RQL.IR.BoolExp.AggregationPredicates.AggregationPredicates'.
defaultAggregationPredicatesParser ::
  forall b r m n.
  ( MonadBuildSchemaBase r m n,
    BackendSchema b,
    AggregationPredicatesSchema b
  ) =>
  [FunctionSignature b] ->
  SourceInfo b ->
  TableInfo b ->
  m (Maybe (InputFieldsParser n [AggregationPredicatesImplementation b (UnpreparedValue b)]))
defaultAggregationPredicatesParser :: [FunctionSignature b]
-> SourceInfo b
-> TableInfo b
-> m (Maybe
        (InputFieldsParser
           n [AggregationPredicatesImplementation b (UnpreparedValue b)]))
defaultAggregationPredicatesParser [FunctionSignature b]
aggFns SourceInfo b
si TableInfo b
ti = MaybeT
  m
  (InputFieldsParser
     n [AggregationPredicatesImplementation b (UnpreparedValue b)])
-> m (Maybe
        (InputFieldsParser
           n [AggregationPredicatesImplementation b (UnpreparedValue b)]))
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT do
  NonEmpty (RelInfo b)
arrayRelationships <- m (Maybe (NonEmpty (RelInfo b))) -> MaybeT m (NonEmpty (RelInfo b))
forall a. m (Maybe a) -> MaybeT m a
fails (m (Maybe (NonEmpty (RelInfo b)))
 -> MaybeT m (NonEmpty (RelInfo b)))
-> m (Maybe (NonEmpty (RelInfo b)))
-> MaybeT m (NonEmpty (RelInfo b))
forall a b. (a -> b) -> a -> b
$ Maybe (NonEmpty (RelInfo b)) -> m (Maybe (NonEmpty (RelInfo b)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (NonEmpty (RelInfo b)) -> m (Maybe (NonEmpty (RelInfo b))))
-> Maybe (NonEmpty (RelInfo b)) -> m (Maybe (NonEmpty (RelInfo b)))
forall a b. (a -> b) -> a -> b
$ [RelInfo b] -> Maybe (NonEmpty (RelInfo b))
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty ([RelInfo b] -> Maybe (NonEmpty (RelInfo b)))
-> [RelInfo b] -> Maybe (NonEmpty (RelInfo b))
forall a b. (a -> b) -> a -> b
$ TableInfo b -> [RelInfo b]
forall (b :: BackendType). TableInfo b -> [RelInfo b]
tableArrayRelationships TableInfo b
ti
  NonEmpty (FunctionSignature b)
aggregationFunctions <- m (Maybe (NonEmpty (FunctionSignature b)))
-> MaybeT m (NonEmpty (FunctionSignature b))
forall a. m (Maybe a) -> MaybeT m a
fails (m (Maybe (NonEmpty (FunctionSignature b)))
 -> MaybeT m (NonEmpty (FunctionSignature b)))
-> m (Maybe (NonEmpty (FunctionSignature b)))
-> MaybeT m (NonEmpty (FunctionSignature b))
forall a b. (a -> b) -> a -> b
$ Maybe (NonEmpty (FunctionSignature b))
-> m (Maybe (NonEmpty (FunctionSignature b)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (NonEmpty (FunctionSignature b))
 -> m (Maybe (NonEmpty (FunctionSignature b))))
-> Maybe (NonEmpty (FunctionSignature b))
-> m (Maybe (NonEmpty (FunctionSignature b)))
forall a b. (a -> b) -> a -> b
$ [FunctionSignature b] -> Maybe (NonEmpty (FunctionSignature b))
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty [FunctionSignature b]
aggFns

  NonEmpty
  (MaybeT
     m
     (InputFieldsParser
        n
        (Maybe
           (AggregationPredicatesImplementation b (UnpreparedValue b)))))
-> MaybeT
     m
     (InputFieldsParser
        n [AggregationPredicatesImplementation b (UnpreparedValue b)])
forall c.
NonEmpty (MaybeT m (InputFieldsParser n (Maybe c)))
-> MaybeT m (InputFieldsParser n [c])
buildAnyOptionalFields (NonEmpty
   (MaybeT
      m
      (InputFieldsParser
         n
         (Maybe
            (AggregationPredicatesImplementation b (UnpreparedValue b)))))
 -> MaybeT
      m
      (InputFieldsParser
         n [AggregationPredicatesImplementation b (UnpreparedValue b)]))
-> NonEmpty
     (MaybeT
        m
        (InputFieldsParser
           n
           (Maybe
              (AggregationPredicatesImplementation b (UnpreparedValue b)))))
-> MaybeT
     m
     (InputFieldsParser
        n [AggregationPredicatesImplementation b (UnpreparedValue b)])
forall a b. (a -> b) -> a -> b
$
    NonEmpty (RelInfo b)
arrayRelationships NonEmpty (RelInfo b)
-> (RelInfo b
    -> MaybeT
         m
         (InputFieldsParser
            n
            (Maybe
               (AggregationPredicatesImplementation b (UnpreparedValue b)))))
-> NonEmpty
     (MaybeT
        m
        (InputFieldsParser
           n
           (Maybe
              (AggregationPredicatesImplementation b (UnpreparedValue b)))))
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \RelInfo b
rel -> do
      TableInfo b
relTable <- SourceInfo b -> TableName b -> MaybeT m (TableInfo b)
forall (b :: BackendType) (m :: * -> *).
(Backend b, MonadError QErr m) =>
SourceInfo b -> TableName b -> m (TableInfo b)
askTableInfo SourceInfo b
si (RelInfo b -> TableName b
forall (b :: BackendType). RelInfo b -> TableName b
riRTable RelInfo b
rel)
      Name
relGqlName <- Text -> MaybeT m Name
forall (m :: * -> *). MonadError QErr m => Text -> m Name
textToName (Text -> MaybeT m Name) -> Text -> MaybeT m Name
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
rel
      Name
typeGqlName <- (Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
Name.__ Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
relGqlName) (Name -> Name) -> MaybeT m Name -> MaybeT m Name
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TableInfo b -> MaybeT m Name
forall (b :: BackendType) (m :: * -> *).
(Backend b, MonadError QErr m) =>
TableInfo b -> m Name
getTableGQLName TableInfo b
relTable

      -- We only make a field for aggregations over a relation if at least
      -- some aggregation predicates are callable.
      RelInfo b
-> Name
-> Name
-> InputFieldsParser n [AggregationPredicate b (UnpreparedValue b)]
-> InputFieldsParser
     n
     (Maybe (AggregationPredicatesImplementation b (UnpreparedValue b)))
relAggregateField RelInfo b
rel Name
relGqlName Name
typeGqlName
        -- We only return an InputFieldsParser for aggregation predicates,
        -- if we parse at least one aggregation predicate
        (InputFieldsParser n [AggregationPredicate b (UnpreparedValue b)]
 -> InputFieldsParser
      n
      (Maybe
         (AggregationPredicatesImplementation b (UnpreparedValue b))))
-> MaybeT
     m
     (InputFieldsParser n [AggregationPredicate b (UnpreparedValue b)])
-> MaybeT
     m
     (InputFieldsParser
        n
        (Maybe
           (AggregationPredicatesImplementation b (UnpreparedValue b))))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonEmpty
  (MaybeT
     m
     (InputFieldsParser
        n (Maybe (AggregationPredicate b (UnpreparedValue b)))))
-> MaybeT
     m
     (InputFieldsParser n [AggregationPredicate b (UnpreparedValue b)])
forall c.
NonEmpty (MaybeT m (InputFieldsParser n (Maybe c)))
-> MaybeT m (InputFieldsParser n [c])
buildAnyOptionalFields
          ( NonEmpty (FunctionSignature b)
aggregationFunctions NonEmpty (FunctionSignature b)
-> (FunctionSignature b
    -> MaybeT
         m
         (InputFieldsParser
            n (Maybe (AggregationPredicate b (UnpreparedValue b)))))
-> NonEmpty
     (MaybeT
        m
        (InputFieldsParser
           n (Maybe (AggregationPredicate b (UnpreparedValue b)))))
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \FunctionSignature {Text
Name
ScalarType b
ArgumentsSignature b
fnReturnType :: forall (b :: BackendType). FunctionSignature b -> ScalarType b
fnArguments :: forall (b :: BackendType).
FunctionSignature b -> ArgumentsSignature b
fnGQLName :: forall (b :: BackendType). FunctionSignature b -> Name
fnName :: forall (b :: BackendType). FunctionSignature b -> Text
fnReturnType :: ScalarType b
fnArguments :: ArgumentsSignature b
fnGQLName :: Name
fnName :: Text
..} -> do
              Name
-> Name
-> InputFieldsParser n (AggregationPredicate b (UnpreparedValue b))
-> InputFieldsParser
     n (Maybe (AggregationPredicate b (UnpreparedValue b)))
aggPredicateField Name
fnGQLName Name
typeGqlName (InputFieldsParser n (AggregationPredicate b (UnpreparedValue b))
 -> InputFieldsParser
      n (Maybe (AggregationPredicate b (UnpreparedValue b))))
-> MaybeT
     m
     (InputFieldsParser n (AggregationPredicate b (UnpreparedValue b)))
-> MaybeT
     m
     (InputFieldsParser
        n (Maybe (AggregationPredicate b (UnpreparedValue b))))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Compose
  (MaybeT m)
  (InputFieldsParser n)
  (AggregationPredicate b (UnpreparedValue b))
-> MaybeT
     m
     (InputFieldsParser n (AggregationPredicate b (UnpreparedValue b)))
forall a.
Compose (MaybeT m) (InputFieldsParser n) a
-> MaybeT m (InputFieldsParser n a)
unfuse do
                AggregationPredicateArguments b
aggPredArguments <-
                  -- We only include an aggregation predicate if we are able to
                  -- access columns all its arguments. This might fail due to
                  -- permissions or due to no columns of suitable types
                  -- existing on the table.
                  case ArgumentsSignature b
fnArguments of
                    ArgumentsSignature b
ArgumentsStar ->
                      AggregationPredicateArguments b
-> (NonEmpty (Column b) -> AggregationPredicateArguments b)
-> Maybe (NonEmpty (Column b))
-> AggregationPredicateArguments b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe AggregationPredicateArguments b
forall (b :: BackendType). AggregationPredicateArguments b
AggregationPredicateArgumentsStar NonEmpty (Column b) -> AggregationPredicateArguments b
forall (b :: BackendType).
NonEmpty (Column b) -> AggregationPredicateArguments b
AggregationPredicateArguments (Maybe (NonEmpty (Column b)) -> AggregationPredicateArguments b)
-> ([Column b] -> Maybe (NonEmpty (Column b)))
-> [Column b]
-> AggregationPredicateArguments b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Column b] -> Maybe (NonEmpty (Column b))
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty
                        ([Column b] -> AggregationPredicateArguments b)
-> Compose (MaybeT m) (InputFieldsParser n) [Column b]
-> Compose
     (MaybeT m) (InputFieldsParser n) (AggregationPredicateArguments b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MaybeT m (InputFieldsParser n [Column b])
-> Compose (MaybeT m) (InputFieldsParser n) [Column b]
forall a.
MaybeT m (InputFieldsParser n a)
-> Compose (MaybeT m) (InputFieldsParser n) a
fuse (Name
-> Maybe Description
-> [Column b]
-> Parser 'Both n [Column b]
-> InputFieldsParser n [Column b]
forall (k :: Kind) a.
('Input <: k) =>
Name
-> Maybe Description -> a -> Parser k n a -> InputFieldsParser n a
fieldOptionalDefault Name
Name._arguments Maybe Description
forall a. Maybe a
Nothing [] (Parser 'Both n [Column b] -> InputFieldsParser n [Column b])
-> (Parser MetadataObjId 'Both n (Column b)
    -> Parser 'Both n [Column b])
-> Parser MetadataObjId 'Both n (Column b)
-> InputFieldsParser n [Column b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parser MetadataObjId 'Both n (Column b)
-> Parser 'Both n [Column b]
forall origin (k :: Kind) (m :: * -> *) a.
(MonadParse m, 'Input <: k) =>
Parser origin k m a -> Parser origin k m [a]
P.list (Parser MetadataObjId 'Both n (Column b)
 -> InputFieldsParser n [Column b])
-> MaybeT m (Parser MetadataObjId 'Both n (Column b))
-> MaybeT m (InputFieldsParser n [Column b])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Maybe (Parser MetadataObjId 'Both n (Column b)))
-> MaybeT m (Parser MetadataObjId 'Both n (Column b))
forall a. m (Maybe a) -> MaybeT m a
fails (SourceInfo b
-> TableInfo b
-> m (Maybe (Parser MetadataObjId 'Both n (Column b)))
forall (b :: BackendType) r (m :: * -> *) (n :: * -> *).
(Backend b, MonadBuildSchemaBase r m n) =>
SourceInfo b
-> TableInfo b -> m (Maybe (Parser 'Both n (Column b)))
tableSelectColumnsEnum SourceInfo b
si TableInfo b
relTable))
                    Arguments NonEmpty (ArgumentSignature b)
args ->
                      NonEmpty (Column b) -> AggregationPredicateArguments b
forall (b :: BackendType).
NonEmpty (Column b) -> AggregationPredicateArguments b
AggregationPredicateArguments
                        (NonEmpty (Column b) -> AggregationPredicateArguments b)
-> Compose (MaybeT m) (InputFieldsParser n) (NonEmpty (Column b))
-> Compose
     (MaybeT m) (InputFieldsParser n) (AggregationPredicateArguments b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MaybeT m (InputFieldsParser n (NonEmpty (Column b)))
-> Compose (MaybeT m) (InputFieldsParser n) (NonEmpty (Column b))
forall a.
MaybeT m (InputFieldsParser n a)
-> Compose (MaybeT m) (InputFieldsParser n) a
fuse
                          ( Name
-> Maybe Description
-> Parser MetadataObjId 'Input n (NonEmpty (Column b))
-> InputFieldsParser n (NonEmpty (Column b))
forall (m :: * -> *) (k :: Kind) origin a.
(MonadParse m, 'Input <: k) =>
Name
-> Maybe Description
-> Parser origin k m a
-> InputFieldsParser origin m a
P.field Name
Name._arguments Maybe Description
forall a. Maybe a
Nothing
                              (Parser MetadataObjId 'Input n (NonEmpty (Column b))
 -> InputFieldsParser n (NonEmpty (Column b)))
-> (InputFieldsParser n (NonEmpty (Column b))
    -> Parser MetadataObjId 'Input n (NonEmpty (Column b)))
-> InputFieldsParser n (NonEmpty (Column b))
-> InputFieldsParser n (NonEmpty (Column b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name
-> Maybe Description
-> InputFieldsParser n (NonEmpty (Column b))
-> Parser MetadataObjId 'Input n (NonEmpty (Column b))
forall (m :: * -> *) origin a.
MonadParse m =>
Name
-> Maybe Description
-> InputFieldsParser origin m a
-> Parser origin 'Input m a
P.object (Name
typeGqlName Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
Name.__ Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
fnGQLName Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
Name.__ Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
Name._arguments) Maybe Description
forall a. Maybe a
Nothing
                              (InputFieldsParser n (NonEmpty (Column b))
 -> InputFieldsParser n (NonEmpty (Column b)))
-> MaybeT m (InputFieldsParser n (NonEmpty (Column b)))
-> MaybeT m (InputFieldsParser n (NonEmpty (Column b)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MaybeT m (NonEmpty (InputFieldsParser n (Column b)))
-> MaybeT m (InputFieldsParser n (NonEmpty (Column b)))
forall c.
MaybeT m (NonEmpty (InputFieldsParser n c))
-> MaybeT m (InputFieldsParser n (NonEmpty c))
buildAllFieldsNE
                                ( NonEmpty (ArgumentSignature b)
args NonEmpty (ArgumentSignature b)
-> (ArgumentSignature b
    -> MaybeT m (InputFieldsParser n (Column b)))
-> MaybeT m (NonEmpty (InputFieldsParser n (Column b)))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
t a -> (a -> f b) -> f (t b)
`for` \ArgumentSignature {Name
ScalarType b
argName :: forall (b :: BackendType). ArgumentSignature b -> Name
argType :: forall (b :: BackendType). ArgumentSignature b -> ScalarType b
argName :: Name
argType :: ScalarType b
..} ->
                                    Name
-> Maybe Description
-> Parser MetadataObjId 'Both n (Column b)
-> InputFieldsParser n (Column b)
forall (m :: * -> *) (k :: Kind) origin a.
(MonadParse m, 'Input <: k) =>
Name
-> Maybe Description
-> Parser origin k m a
-> InputFieldsParser origin m a
P.field Name
argName Maybe Description
forall a. Maybe a
Nothing (Parser MetadataObjId 'Both n (Column b)
 -> InputFieldsParser n (Column b))
-> MaybeT m (Parser MetadataObjId 'Both n (Column b))
-> MaybeT m (InputFieldsParser n (Column b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Maybe (Parser MetadataObjId 'Both n (Column b)))
-> MaybeT m (Parser MetadataObjId 'Both n (Column b))
forall a. m (Maybe a) -> MaybeT m a
fails ((ColumnType b -> Bool)
-> Name
-> SourceInfo b
-> TableInfo b
-> m (Maybe (Parser MetadataObjId 'Both n (Column b)))
forall (b :: BackendType) r (m :: * -> *) (n :: * -> *).
MonadBuildSchema b r m n =>
(ColumnType b -> Bool)
-> Name
-> SourceInfo b
-> TableInfo b
-> m (Maybe (Parser 'Both n (Column b)))
tableSelectColumnsPredEnum (ColumnType b -> ColumnType b -> Bool
forall a. Eq a => a -> a -> Bool
== (ScalarType b -> ColumnType b
forall (b :: BackendType). ScalarType b -> ColumnType b
ColumnScalar ScalarType b
argType)) Name
relGqlName SourceInfo b
si TableInfo b
relTable)
                                )
                          )

                Bool
aggPredDistinct <- MaybeT m (InputFieldsParser n Bool)
-> Compose (MaybeT m) (InputFieldsParser n) Bool
forall a.
MaybeT m (InputFieldsParser n a)
-> Compose (MaybeT m) (InputFieldsParser n) a
fuse (MaybeT m (InputFieldsParser n Bool)
 -> Compose (MaybeT m) (InputFieldsParser n) Bool)
-> MaybeT m (InputFieldsParser n Bool)
-> Compose (MaybeT m) (InputFieldsParser n) Bool
forall a b. (a -> b) -> a -> b
$ InputFieldsParser n Bool -> MaybeT m (InputFieldsParser n Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (InputFieldsParser n Bool -> MaybeT m (InputFieldsParser n Bool))
-> InputFieldsParser n Bool -> MaybeT m (InputFieldsParser n Bool)
forall a b. (a -> b) -> a -> b
$ Name
-> Maybe Description
-> Bool
-> Parser 'Both n Bool
-> InputFieldsParser n Bool
forall (k :: Kind) a.
('Input <: k) =>
Name
-> Maybe Description -> a -> Parser k n a -> InputFieldsParser n a
fieldOptionalDefault Name
Name._distinct Maybe Description
forall a. Maybe a
Nothing Bool
False Parser 'Both n Bool
forall (m :: * -> *) origin.
MonadParse m =>
Parser origin 'Both m Bool
P.boolean
                let aggPredFunctionName :: Text
aggPredFunctionName = Text
fnName
                [ComparisonExp b]
aggPredPredicate <- MaybeT m (InputFieldsParser n [ComparisonExp b])
-> Compose (MaybeT m) (InputFieldsParser n) [ComparisonExp b]
forall a.
MaybeT m (InputFieldsParser n a)
-> Compose (MaybeT m) (InputFieldsParser n) a
fuse (MaybeT m (InputFieldsParser n [ComparisonExp b])
 -> Compose (MaybeT m) (InputFieldsParser n) [ComparisonExp b])
-> MaybeT m (InputFieldsParser n [ComparisonExp b])
-> Compose (MaybeT m) (InputFieldsParser n) [ComparisonExp b]
forall a b. (a -> b) -> a -> b
$ Name
-> Maybe Description
-> Parser MetadataObjId 'Input n [ComparisonExp b]
-> InputFieldsParser n [ComparisonExp b]
forall (m :: * -> *) (k :: Kind) origin a.
(MonadParse m, 'Input <: k) =>
Name
-> Maybe Description
-> Parser origin k m a
-> InputFieldsParser origin m a
P.field Name
Name._predicate Maybe Description
forall a. Maybe a
Nothing (Parser MetadataObjId 'Input n [ComparisonExp b]
 -> InputFieldsParser n [ComparisonExp b])
-> MaybeT m (Parser MetadataObjId 'Input n [ComparisonExp b])
-> MaybeT m (InputFieldsParser n [ComparisonExp b])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Parser MetadataObjId 'Input n [ComparisonExp b])
-> MaybeT m (Parser MetadataObjId 'Input n [ComparisonExp b])
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (ColumnType b -> m (Parser MetadataObjId 'Input n [ComparisonExp b])
forall (b :: BackendType) r (m :: * -> *) (n :: * -> *).
(BackendSchema b, MonadBuildSchema b r m n) =>
ColumnType b -> m (Parser 'Input n [ComparisonExp b])
comparisonExps @b (ScalarType b -> ColumnType b
forall (b :: BackendType). ScalarType b -> ColumnType b
ColumnScalar ScalarType b
fnReturnType))
                Maybe (AnnBoolExp b (UnpreparedValue b))
aggPredFilter <- MaybeT
  m (InputFieldsParser n (Maybe (AnnBoolExp b (UnpreparedValue b))))
-> Compose
     (MaybeT m)
     (InputFieldsParser n)
     (Maybe (AnnBoolExp b (UnpreparedValue b)))
forall a.
MaybeT m (InputFieldsParser n a)
-> Compose (MaybeT m) (InputFieldsParser n) a
fuse (MaybeT
   m (InputFieldsParser n (Maybe (AnnBoolExp b (UnpreparedValue b))))
 -> Compose
      (MaybeT m)
      (InputFieldsParser n)
      (Maybe (AnnBoolExp b (UnpreparedValue b))))
-> MaybeT
     m (InputFieldsParser n (Maybe (AnnBoolExp b (UnpreparedValue b))))
-> Compose
     (MaybeT m)
     (InputFieldsParser n)
     (Maybe (AnnBoolExp b (UnpreparedValue b)))
forall a b. (a -> b) -> a -> b
$ Name
-> Maybe Description
-> Parser MetadataObjId 'Input n (AnnBoolExp b (UnpreparedValue b))
-> InputFieldsParser n (Maybe (AnnBoolExp b (UnpreparedValue b)))
forall (m :: * -> *) (k :: Kind) origin a.
(MonadParse m, 'Input <: k) =>
Name
-> Maybe Description
-> Parser origin k m a
-> InputFieldsParser origin m (Maybe a)
P.fieldOptional Name
Name._filter Maybe Description
forall a. Maybe a
Nothing (Parser MetadataObjId 'Input n (AnnBoolExp b (UnpreparedValue b))
 -> InputFieldsParser n (Maybe (AnnBoolExp b (UnpreparedValue b))))
-> MaybeT
     m
     (Parser MetadataObjId 'Input n (AnnBoolExp b (UnpreparedValue b)))
-> MaybeT
     m (InputFieldsParser n (Maybe (AnnBoolExp b (UnpreparedValue b))))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Parser
     MetadataObjId 'Input n (AnnBoolExp b (UnpreparedValue b)))
-> MaybeT
     m
     (Parser MetadataObjId 'Input n (AnnBoolExp b (UnpreparedValue b)))
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (SourceInfo b
-> TableInfo b
-> m (Parser
        MetadataObjId 'Input n (AnnBoolExp b (UnpreparedValue b)))
forall (b :: BackendType) r (m :: * -> *) (n :: * -> *).
(MonadBuildSchema b r m n, AggregationPredicatesSchema b) =>
SourceInfo b
-> TableInfo b
-> m (Parser 'Input n (AnnBoolExp b (UnpreparedValue b)))
boolExp SourceInfo b
si TableInfo b
relTable)
                pure $ AggregationPredicate :: forall (b :: BackendType) field.
Text
-> Bool
-> Maybe (AnnBoolExp b field)
-> AggregationPredicateArguments b
-> [OpExpG b field]
-> AggregationPredicate b field
AggregationPredicate {Bool
[ComparisonExp b]
Maybe (AnnBoolExp b (UnpreparedValue b))
Text
AggregationPredicateArguments b
aggPredPredicate :: [ComparisonExp b]
aggPredArguments :: AggregationPredicateArguments b
aggPredFilter :: Maybe (AnnBoolExp b (UnpreparedValue b))
aggPredDistinct :: Bool
aggPredFunctionName :: Text
aggPredFilter :: Maybe (AnnBoolExp b (UnpreparedValue b))
aggPredPredicate :: [ComparisonExp b]
aggPredFunctionName :: Text
aggPredDistinct :: Bool
aggPredArguments :: AggregationPredicateArguments b
..}
          )
  where
    -- Input field of the aggregation predicates for one array relation.
    relAggregateField ::
      RelInfo b ->
      G.Name ->
      G.Name ->
      (InputFieldsParser n [AggregationPredicate b (UnpreparedValue b)]) ->
      (InputFieldsParser n (Maybe (AggregationPredicatesImplementation b (UnpreparedValue b))))
    relAggregateField :: RelInfo b
-> Name
-> Name
-> InputFieldsParser n [AggregationPredicate b (UnpreparedValue b)]
-> InputFieldsParser
     n
     (Maybe (AggregationPredicatesImplementation b (UnpreparedValue b)))
relAggregateField RelInfo b
rel Name
typeGqlName Name
relGqlName =
      Name
-> Maybe Description
-> Parser
     MetadataObjId
     'Input
     n
     (AggregationPredicatesImplementation b (UnpreparedValue b))
-> InputFieldsParser
     n
     (Maybe (AggregationPredicatesImplementation b (UnpreparedValue b)))
forall (m :: * -> *) (k :: Kind) origin a.
(MonadParse m, 'Input <: k) =>
Name
-> Maybe Description
-> Parser origin k m a
-> InputFieldsParser origin m (Maybe a)
P.fieldOptional (Name
relGqlName Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
Name.__ Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
Name._aggregate) Maybe Description
forall a. Maybe a
Nothing
        (Parser
   MetadataObjId
   'Input
   n
   (AggregationPredicatesImplementation b (UnpreparedValue b))
 -> InputFieldsParser
      n
      (Maybe
         (AggregationPredicatesImplementation b (UnpreparedValue b))))
-> (InputFieldsParser
      n [AggregationPredicate b (UnpreparedValue b)]
    -> Parser
         MetadataObjId
         'Input
         n
         (AggregationPredicatesImplementation b (UnpreparedValue b)))
-> InputFieldsParser n [AggregationPredicate b (UnpreparedValue b)]
-> InputFieldsParser
     n
     (Maybe (AggregationPredicatesImplementation b (UnpreparedValue b)))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name
-> Maybe Description
-> InputFieldsParser
     MetadataObjId
     n
     (AggregationPredicatesImplementation b (UnpreparedValue b))
-> Parser
     MetadataObjId
     'Input
     n
     (AggregationPredicatesImplementation b (UnpreparedValue b))
forall (m :: * -> *) origin a.
MonadParse m =>
Name
-> Maybe Description
-> InputFieldsParser origin m a
-> Parser origin 'Input m a
P.object Name
typeGqlName Maybe Description
forall a. Maybe a
Nothing
        (InputFieldsParser
   MetadataObjId
   n
   (AggregationPredicatesImplementation b (UnpreparedValue b))
 -> Parser
      MetadataObjId
      'Input
      n
      (AggregationPredicatesImplementation b (UnpreparedValue b)))
-> (InputFieldsParser
      n [AggregationPredicate b (UnpreparedValue b)]
    -> InputFieldsParser
         MetadataObjId
         n
         (AggregationPredicatesImplementation b (UnpreparedValue b)))
-> InputFieldsParser n [AggregationPredicate b (UnpreparedValue b)]
-> Parser
     MetadataObjId
     'Input
     n
     (AggregationPredicatesImplementation b (UnpreparedValue b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([AggregationPredicate b (UnpreparedValue b)]
 -> AggregationPredicatesImplementation b (UnpreparedValue b))
-> InputFieldsParser n [AggregationPredicate b (UnpreparedValue b)]
-> InputFieldsParser
     MetadataObjId
     n
     (AggregationPredicatesImplementation b (UnpreparedValue b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (RelInfo b
-> [AggregationPredicate b (UnpreparedValue b)]
-> AggregationPredicatesImplementation b (UnpreparedValue b)
forall (b :: BackendType) field.
RelInfo b
-> [AggregationPredicate b field]
-> AggregationPredicatesImplementation b field
AggregationPredicatesImplementation RelInfo b
rel)

    -- Input field for a single aggregation predicate.
    aggPredicateField ::
      G.Name ->
      G.Name ->
      InputFieldsParser n (AggregationPredicate b (UnpreparedValue b)) ->
      InputFieldsParser n (Maybe (AggregationPredicate b (UnpreparedValue b)))
    aggPredicateField :: Name
-> Name
-> InputFieldsParser n (AggregationPredicate b (UnpreparedValue b))
-> InputFieldsParser
     n (Maybe (AggregationPredicate b (UnpreparedValue b)))
aggPredicateField Name
fnGQLName Name
typeGqlName =
      Name
-> Maybe Description
-> Parser
     MetadataObjId 'Input n (AggregationPredicate b (UnpreparedValue b))
-> InputFieldsParser
     n (Maybe (AggregationPredicate b (UnpreparedValue b)))
forall (m :: * -> *) (k :: Kind) origin a.
(MonadParse m, 'Input <: k) =>
Name
-> Maybe Description
-> Parser origin k m a
-> InputFieldsParser origin m (Maybe a)
P.fieldOptional Name
fnGQLName Maybe Description
forall a. Maybe a
Nothing (Parser
   MetadataObjId 'Input n (AggregationPredicate b (UnpreparedValue b))
 -> InputFieldsParser
      n (Maybe (AggregationPredicate b (UnpreparedValue b))))
-> (InputFieldsParser
      n (AggregationPredicate b (UnpreparedValue b))
    -> Parser
         MetadataObjId
         'Input
         n
         (AggregationPredicate b (UnpreparedValue b)))
-> InputFieldsParser n (AggregationPredicate b (UnpreparedValue b))
-> InputFieldsParser
     n (Maybe (AggregationPredicate b (UnpreparedValue b)))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name
-> Maybe Description
-> InputFieldsParser n (AggregationPredicate b (UnpreparedValue b))
-> Parser
     MetadataObjId 'Input n (AggregationPredicate b (UnpreparedValue b))
forall (m :: * -> *) origin a.
MonadParse m =>
Name
-> Maybe Description
-> InputFieldsParser origin m a
-> Parser origin 'Input m a
P.object (Name
typeGqlName Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
Name.__ Name -> Name -> Name
forall a. Semigroup a => a -> a -> a
<> Name
fnGQLName) Maybe Description
forall a. Maybe a
Nothing

    buildAnyOptionalFields :: NonEmpty (MaybeT m (InputFieldsParser n (Maybe c))) -> MaybeT m (InputFieldsParser n [c])
    buildAnyOptionalFields :: NonEmpty (MaybeT m (InputFieldsParser n (Maybe c)))
-> MaybeT m (InputFieldsParser n [c])
buildAnyOptionalFields = (NonEmpty (InputFieldsParser n (Maybe c))
 -> InputFieldsParser n [c])
-> MaybeT m (NonEmpty (InputFieldsParser n (Maybe c)))
-> MaybeT m (InputFieldsParser n [c])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap NonEmpty (InputFieldsParser n (Maybe c)) -> InputFieldsParser n [c]
forall a.
NonEmpty (InputFieldsParser n (Maybe a)) -> InputFieldsParser n [a]
collectOptionalFields (MaybeT m (NonEmpty (InputFieldsParser n (Maybe c)))
 -> MaybeT m (InputFieldsParser n [c]))
-> (NonEmpty (MaybeT m (InputFieldsParser n (Maybe c)))
    -> MaybeT m (NonEmpty (InputFieldsParser n (Maybe c))))
-> NonEmpty (MaybeT m (InputFieldsParser n (Maybe c)))
-> MaybeT m (InputFieldsParser n [c])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty (MaybeT m (InputFieldsParser n (Maybe c)))
-> MaybeT m (NonEmpty (InputFieldsParser n (Maybe c)))
forall (f :: * -> *) a.
Applicative f =>
NonEmpty (MaybeT f a) -> MaybeT f (NonEmpty a)
collectBranchesNE
      where
        -- Collect a non-empty list of optional input field parsers into one input field
        -- parser parsing a list of the specified values.
        collectOptionalFields :: NonEmpty (InputFieldsParser n (Maybe a)) -> InputFieldsParser n [a]
        collectOptionalFields :: NonEmpty (InputFieldsParser n (Maybe a)) -> InputFieldsParser n [a]
collectOptionalFields = (NonEmpty (Maybe a) -> [a])
-> InputFieldsParser MetadataObjId n (NonEmpty (Maybe a))
-> InputFieldsParser n [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Maybe a] -> [a]
forall (f :: * -> *) a. Filterable f => f (Maybe a) -> f a
catMaybes ([Maybe a] -> [a])
-> (NonEmpty (Maybe a) -> [Maybe a]) -> NonEmpty (Maybe a) -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty (Maybe a) -> [Maybe a]
forall a. NonEmpty a -> [a]
NE.toList) (InputFieldsParser MetadataObjId n (NonEmpty (Maybe a))
 -> InputFieldsParser n [a])
-> (NonEmpty (InputFieldsParser n (Maybe a))
    -> InputFieldsParser MetadataObjId n (NonEmpty (Maybe a)))
-> NonEmpty (InputFieldsParser n (Maybe a))
-> InputFieldsParser n [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty (InputFieldsParser n (Maybe a))
-> InputFieldsParser MetadataObjId n (NonEmpty (Maybe a))
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA

    buildAllFieldsNE :: MaybeT m (NonEmpty (InputFieldsParser n c)) -> MaybeT m (InputFieldsParser n (NonEmpty c))
    buildAllFieldsNE :: MaybeT m (NonEmpty (InputFieldsParser n c))
-> MaybeT m (InputFieldsParser n (NonEmpty c))
buildAllFieldsNE = (NonEmpty (InputFieldsParser n c)
 -> InputFieldsParser n (NonEmpty c))
-> MaybeT m (NonEmpty (InputFieldsParser n c))
-> MaybeT m (InputFieldsParser n (NonEmpty c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap NonEmpty (InputFieldsParser n c)
-> InputFieldsParser n (NonEmpty c)
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA

    -- Collect all the non-failed branches, failing if all branches failed.
    collectBranchesNE :: forall f a. Applicative f => NonEmpty (MaybeT f a) -> MaybeT f (NonEmpty a)
    collectBranchesNE :: NonEmpty (MaybeT f a) -> MaybeT f (NonEmpty a)
collectBranchesNE NonEmpty (MaybeT f a)
xs = f (Maybe (NonEmpty a)) -> MaybeT f (NonEmpty a)
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (f (Maybe (NonEmpty a)) -> MaybeT f (NonEmpty a))
-> f (Maybe (NonEmpty a)) -> MaybeT f (NonEmpty a)
forall a b. (a -> b) -> a -> b
$ [a] -> Maybe (NonEmpty a)
forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty ([a] -> Maybe (NonEmpty a))
-> (NonEmpty (Maybe a) -> [a])
-> NonEmpty (Maybe a)
-> Maybe (NonEmpty a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe a] -> [a]
forall (f :: * -> *) a. Filterable f => f (Maybe a) -> f a
catMaybes ([Maybe a] -> [a])
-> (NonEmpty (Maybe a) -> [Maybe a]) -> NonEmpty (Maybe a) -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty (Maybe a) -> [Maybe a]
forall a. NonEmpty a -> [a]
NE.toList (NonEmpty (Maybe a) -> Maybe (NonEmpty a))
-> f (NonEmpty (Maybe a)) -> f (Maybe (NonEmpty a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonEmpty (f (Maybe a)) -> f (NonEmpty (Maybe a))
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA (NonEmpty (MaybeT f a)
xs NonEmpty (MaybeT f a)
-> (MaybeT f a -> f (Maybe a)) -> NonEmpty (f (Maybe a))
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> MaybeT f a -> f (Maybe a)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT)

    -- Mark a computation as potentially failing.
    fails :: m (Maybe a) -> MaybeT m a
    fails :: m (Maybe a) -> MaybeT m a
fails = m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT

    -- Compose our monad with InputFieldsParser into one fused Applicative that
    -- acts on the parsed values directly.
    fuse :: MaybeT m (InputFieldsParser n a) -> Compose (MaybeT m) (InputFieldsParser n) a
    fuse :: MaybeT m (InputFieldsParser n a)
-> Compose (MaybeT m) (InputFieldsParser n) a
fuse = MaybeT m (InputFieldsParser n a)
-> Compose (MaybeT m) (InputFieldsParser n) a
forall k k1 (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose

    -- The inverse of 'fuse'.
    unfuse :: Compose (MaybeT m) (InputFieldsParser n) a -> MaybeT m (InputFieldsParser n a)
    unfuse :: Compose (MaybeT m) (InputFieldsParser n) a
-> MaybeT m (InputFieldsParser n a)
unfuse = Compose (MaybeT m) (InputFieldsParser n) a
-> MaybeT m (InputFieldsParser n a)
forall k1 (f :: k1 -> *) k2 (g :: k2 -> k1) (a :: k2).
Compose f g a -> f (g a)
getCompose

    -- Optional input field with a default value when the field is elided or null.
    fieldOptionalDefault ::
      forall k a. ('Input P.<: k) => G.Name -> Maybe G.Description -> a -> Parser k n a -> InputFieldsParser n a
    fieldOptionalDefault :: Name
-> Maybe Description -> a -> Parser k n a -> InputFieldsParser n a
fieldOptionalDefault Name
n Maybe Description
d a
a Parser k n a
p = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
a (Maybe a -> a)
-> InputFieldsParser MetadataObjId n (Maybe a)
-> InputFieldsParser n a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Name
-> Maybe Description
-> Parser k n a
-> InputFieldsParser MetadataObjId n (Maybe a)
forall (m :: * -> *) (k :: Kind) origin a.
(MonadParse m, 'Input <: k) =>
Name
-> Maybe Description
-> Parser origin k m a
-> InputFieldsParser origin m (Maybe a)
P.fieldOptional Name
n Maybe Description
d Parser k n a
p

data FunctionSignature (b :: BackendType) = FunctionSignature
  { FunctionSignature b -> Text
fnName :: Text,
    FunctionSignature b -> Name
fnGQLName :: G.Name,
    FunctionSignature b -> ArgumentsSignature b
fnArguments :: ArgumentsSignature b,
    FunctionSignature b -> ScalarType b
fnReturnType :: B.ScalarType b
  }

data ArgumentsSignature (b :: BackendType)
  = ArgumentsStar
  | Arguments (NonEmpty (ArgumentSignature b))

data ArgumentSignature (b :: BackendType) = ArgumentSignature
  { ArgumentSignature b -> ScalarType b
argType :: B.ScalarType b,
    ArgumentSignature b -> Name
argName :: G.Name
  }