Define IR types for AggregationPredicates.

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5258
GitOrigin-RevId: 172b9de69f44635c5700b3f75ce17304ec56c18a
This commit is contained in:
Philip Lykke Carlsen 2022-08-19 15:40:26 +00:00 committed by hasura-bot
parent 6040cb065e
commit 0e921ca9a5
20 changed files with 459 additions and 51 deletions

View File

@ -443,6 +443,7 @@ library
, Hasura.Backends.BigQuery.Instances.API
, Hasura.Backends.BigQuery.Instances.Execute
, Hasura.Backends.BigQuery.Instances.Schema
, Hasura.Backends.BigQuery.Instances.SchemaCache
, Hasura.Backends.BigQuery.Instances.Transport
, Hasura.Backends.BigQuery.Instances.Types
, Hasura.Backends.BigQuery.Instances.Metadata
@ -477,6 +478,7 @@ library
, Hasura.Backends.MSSQL.Instances.Execute
, Hasura.Backends.MSSQL.Instances.Metadata
, Hasura.Backends.MSSQL.Instances.Schema
, Hasura.Backends.MSSQL.Instances.SchemaCache
, Hasura.Backends.MSSQL.Instances.Transport
, Hasura.Backends.MSSQL.Instances.Types
, Hasura.Backends.MSSQL.Meta
@ -512,6 +514,7 @@ library
, Hasura.Backends.Postgres.Instances.Execute
, Hasura.Backends.Postgres.Instances.Metadata
, Hasura.Backends.Postgres.Instances.Schema
, Hasura.Backends.Postgres.Instances.SchemaCache
, Hasura.Backends.Postgres.Instances.Transport
, Hasura.Backends.Postgres.Instances.Types
, Hasura.Backends.Postgres.Schema.OnConflict
@ -563,6 +566,7 @@ library
, Hasura.Backends.MySQL.Instances.Types
, Hasura.Backends.MySQL.Instances.Metadata
, Hasura.Backends.MySQL.Instances.Schema
, Hasura.Backends.MySQL.Instances.SchemaCache
, Hasura.Backends.MySQL.Instances.Execute
, Hasura.Backends.MySQL.Instances.Transport
, Hasura.Backends.MySQL.SQL
@ -576,6 +580,7 @@ library
, Hasura.Backends.DataConnector.Adapter.ConfigTransform
, Hasura.Backends.DataConnector.Adapter.Metadata
, Hasura.Backends.DataConnector.Adapter.Schema
, Hasura.Backends.DataConnector.Adapter.SchemaCache
, Hasura.Backends.DataConnector.Adapter.Transport
, Hasura.Backends.DataConnector.Adapter.Types
, Hasura.Backends.DataConnector.Agent.Client
@ -697,7 +702,9 @@ library
, Hasura.RQL.Types.Roles.Internal
, Hasura.RQL.Types.ScheduledTrigger
, Hasura.RQL.Types.SchemaCache
, Hasura.RQL.Types.SchemaCache.AggregationPredicates
, Hasura.RQL.Types.SchemaCache.Build
, Hasura.RQL.Types.SchemaCache.Instances
, Hasura.RQL.Types.SchemaCacheTypes
, Hasura.RQL.Types.Source
, Hasura.RQL.Types.SourceCustomization
@ -758,6 +765,7 @@ library
, Hasura.RQL.DML.Types
, Hasura.RQL.IR.Action
, Hasura.RQL.IR.BoolExp
, Hasura.RQL.IR.BoolExp.AggregationPredicates
, Hasura.RQL.IR.Conflict
, Hasura.RQL.IR.Delete
, Hasura.RQL.IR.Insert

View File

@ -0,0 +1,12 @@
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- This module houses type class instances on the BigQuery backend that relate
-- to the Schema Cache.
module Hasura.Backends.BigQuery.Instances.SchemaCache () where
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.SchemaCacheTypes (GetAggregationPredicatesDeps)
import Hasura.SQL.Backend (BackendType (BigQuery))
instance (Backend 'BigQuery) => GetAggregationPredicatesDeps 'BigQuery

View File

@ -0,0 +1,12 @@
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- This module houses type class instances on the DataConnector backends that relate
-- to the Schema Cache.
module Hasura.Backends.DataConnector.Adapter.SchemaCache () where
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.SchemaCacheTypes (GetAggregationPredicatesDeps)
import Hasura.SQL.Backend (BackendType (DataConnector))
instance (Backend 'DataConnector) => GetAggregationPredicatesDeps 'DataConnector

View File

@ -0,0 +1,12 @@
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- This module houses type class instances on the MSSQL backend that relate
-- to the Schema Cache.
module Hasura.Backends.MSSQL.Instances.SchemaCache () where
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.SchemaCacheTypes (GetAggregationPredicatesDeps)
import Hasura.SQL.Backend (BackendType (MSSQL))
instance (Backend 'MSSQL) => GetAggregationPredicatesDeps 'MSSQL

View File

@ -0,0 +1,12 @@
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- This module houses type class instances on the MySQL backend that relate
-- to the Schema Cache.
module Hasura.Backends.MySQL.Instances.SchemaCache () where
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.SchemaCacheTypes (GetAggregationPredicatesDeps)
import Hasura.SQL.Backend (BackendType (MySQL))
instance (Backend 'MySQL) => GetAggregationPredicatesDeps 'MySQL

View File

@ -0,0 +1,12 @@
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- This module houses type class instances on the Postgres backends that relate
-- to the Schema Cache.
module Hasura.Backends.Postgres.Instances.SchemaCache () where
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.SchemaCacheTypes (GetAggregationPredicatesDeps)
import Hasura.SQL.Backend (BackendType (Postgres))
instance (Backend ('Postgres pgKind)) => GetAggregationPredicatesDeps ('Postgres pgKind)

View File

@ -25,7 +25,7 @@ import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Function
import Hasura.RQL.Types.Metadata.Backend
import Hasura.RQL.Types.Relationships.Local
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.SchemaCache hiding (BoolExpCtx (..), BoolExpM (..))
import Hasura.RQL.Types.Table
import Hasura.SQL.Backend
import Hasura.SQL.Types

View File

@ -52,6 +52,7 @@ import Hasura.RQL.Types.Permission
import Hasura.RQL.Types.Relationships.Local
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.SchemaCache.Build
import Hasura.RQL.Types.SchemaCacheTypes
import Hasura.RQL.Types.Table
import Hasura.SQL.AnyBackend qualified as AB
import Hasura.SQL.Types
@ -213,7 +214,11 @@ addPermissionToMetadata permDef = case _pdPermission permDef of
DelPerm' _ -> tmDeletePermissions %~ OMap.insert (_pdRole permDef) permDef
buildPermInfo ::
(BackendMetadata b, QErrM m, TableCoreInfoRM b m) =>
( BackendMetadata b,
QErrM m,
TableCoreInfoRM b m,
GetAggregationPredicatesDeps b
) =>
SourceName ->
TableName b ->
FieldInfoMap (FieldInfo b) ->
@ -292,7 +297,11 @@ runDropPerm permType (DropPerm source table role) = do
buildInsPermInfo ::
forall b m.
(QErrM m, TableCoreInfoRM b m, BackendMetadata b) =>
( QErrM m,
TableCoreInfoRM b m,
BackendMetadata b,
GetAggregationPredicatesDeps b
) =>
SourceName ->
TableName b ->
FieldInfoMap (FieldInfo b) ->
@ -394,7 +403,11 @@ validateAllowedRootFields sourceName tableName roleName streamSubsCtx SelPerm {.
buildSelPermInfo ::
forall b m.
(QErrM m, TableCoreInfoRM b m, BackendMetadata b) =>
( QErrM m,
TableCoreInfoRM b m,
BackendMetadata b,
GetAggregationPredicatesDeps b
) =>
SourceName ->
TableName b ->
FieldInfoMap (FieldInfo b) ->
@ -455,7 +468,11 @@ buildSelPermInfo source tableName fieldInfoMap roleName streamSubsCtx sp = withP
buildUpdPermInfo ::
forall b m.
(QErrM m, TableCoreInfoRM b m, BackendMetadata b) =>
( QErrM m,
TableCoreInfoRM b m,
BackendMetadata b,
GetAggregationPredicatesDeps b
) =>
SourceName ->
TableName b ->
FieldInfoMap (FieldInfo b) ->
@ -498,7 +515,11 @@ buildUpdPermInfo source tn fieldInfoMap (UpdPerm colSpec set fltr check backendO
buildDelPermInfo ::
forall b m.
(QErrM m, TableCoreInfoRM b m, BackendMetadata b) =>
( QErrM m,
TableCoreInfoRM b m,
BackendMetadata b,
GetAggregationPredicatesDeps b
) =>
SourceName ->
TableName b ->
FieldInfoMap (FieldInfo b) ->

View File

@ -30,6 +30,7 @@ import Hasura.RQL.Types.Metadata.Backend
import Hasura.RQL.Types.Permission
import Hasura.RQL.Types.Relationships.Local
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.SchemaCacheTypes
import Hasura.RQL.Types.Table
import Hasura.Server.Utils
import Hasura.Session
@ -78,7 +79,11 @@ data CreatePermP1Res a = CreatePermP1Res
deriving (Show, Eq)
procBoolExp ::
(QErrM m, TableCoreInfoRM b m, BackendMetadata b) =>
( QErrM m,
TableCoreInfoRM b m,
BackendMetadata b,
GetAggregationPredicatesDeps b
) =>
SourceName ->
TableName b ->
FieldInfoMap (FieldInfo b) ->

View File

@ -82,6 +82,7 @@ import Hasura.RQL.Types.Roles.Internal (CheckPermission (..))
import Hasura.RQL.Types.ScheduledTrigger
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.SchemaCache.Build
import Hasura.RQL.Types.SchemaCache.Instances ()
import Hasura.RQL.Types.SchemaCacheTypes
import Hasura.RQL.Types.Source
import Hasura.RQL.Types.SourceCustomization
@ -477,7 +478,8 @@ buildSchemaCacheRule logger env = proc (metadata, invalidationKeys) -> do
ArrowWriter (Seq CollectedInfo) arr,
HasServerConfigCtx m,
MonadError QErr m,
BackendMetadata b
BackendMetadata b,
GetAggregationPredicatesDeps b
) =>
( HashMap SourceName (AB.AnyBackend PartiallyResolvedSource),
SourceMetadata b,
@ -710,7 +712,13 @@ buildSchemaCacheRule logger env = proc (metadata, invalidationKeys) -> do
(|
Inc.keyed
( \_ exists ->
AB.dispatchAnyBackendArrow @BackendMetadata @BackendMetadata
-- Note that it's a bit of a coincidence that
-- 'AB.dispatchAnyBackendArrow' accepts exactly two constraints,
-- and that we happen to want to apply to exactly two
-- constraints.
-- Ideally the function should be able to take an arbitrary
-- number of constraints.
AB.dispatchAnyBackendArrow @BackendMetadata @GetAggregationPredicatesDeps
( proc
( partiallyResolvedSource :: PartiallyResolvedSource b,
(allResolvedSources, remoteSchemaCtxMap, orderedRoles)

View File

@ -208,7 +208,8 @@ buildTablePermissions ::
ArrowWriter (Seq CollectedInfo) arr,
BackendMetadata b,
HasServerConfigCtx m,
Inc.Cacheable (Proxy b)
Inc.Cacheable (Proxy b),
GetAggregationPredicatesDeps b
) =>
( Proxy b,
SourceName,
@ -334,7 +335,8 @@ buildPermission ::
Inc.Cacheable (Proxy b),
MonadError QErr m,
HasServerConfigCtx m,
BackendMetadata b
BackendMetadata b,
GetAggregationPredicatesDeps b
) =>
( Proxy b,
Inc.Dependency (TableCoreCache b),

View File

@ -501,21 +501,24 @@ instance
) =>
Hashable (AnnComputedFieldBoolExp b a)
-- | This type is used for boolean terms in GBoolExp in the schema; there are two kinds boolean
-- | This type is used for boolean terms in GBoolExp in the schema; there are four kinds boolean
-- terms:
-- - operators on a column of the current table, using the 'OpExpG' kind of operators
-- - arbitrary expressions on columns of tables in relationships (in the same source)
-- - A computed field of the current table
-- - aggregation operations on array relationships on the current tables.
--
-- This type is parameterized over the type of leaf values, the values on which we operate.
data AnnBoolExpFld (backend :: BackendType) leaf
= AVColumn (ColumnInfo backend) [OpExpG backend leaf]
| AVRelationship (RelInfo backend) (AnnBoolExp backend leaf)
| AVComputedField (AnnComputedFieldBoolExp backend leaf)
| AVAggregationPredicates (AggregationPredicates backend leaf)
deriving (Functor, Foldable, Traversable, Generic)
deriving instance
( Backend b,
Eq (AggregationPredicates b a),
Eq (AnnBoolExp b a),
Eq (AnnComputedFieldBoolExp b a),
Eq (OpExpG b a)
@ -524,6 +527,7 @@ deriving instance
deriving instance
( Backend b,
Show (AggregationPredicates b a),
Show (AnnBoolExp b a),
Show (AnnComputedFieldBoolExp b a),
Show (OpExpG b a)
@ -532,6 +536,7 @@ deriving instance
instance
( Backend b,
NFData (AggregationPredicates b a),
NFData (AnnBoolExp b a),
NFData (AnnComputedFieldBoolExp b a),
NFData (OpExpG b a)
@ -540,6 +545,7 @@ instance
instance
( Backend b,
Cacheable (AggregationPredicates b a),
Cacheable (AnnBoolExp b a),
Cacheable (AnnComputedFieldBoolExp b a),
Cacheable (OpExpG b a)
@ -548,6 +554,7 @@ instance
instance
( Backend b,
Hashable (AggregationPredicates b a),
Hashable (AnnBoolExp b a),
Hashable (AnnComputedFieldBoolExp b a),
Hashable (OpExpG b a)
@ -556,6 +563,7 @@ instance
instance
( Backend b,
ToJSONKeyValue (AggregationPredicates b a),
ToJSONKeyValue (OpExpG b a),
ToJSON a
) =>
@ -577,6 +585,7 @@ instance
CFBEScalar opExps -> toJSON (function, object . pure . toJSONKeyValue <$> opExps)
CFBETable _ boolExp -> toJSON (function, toJSON boolExp)
)
AVAggregationPredicates avAggregationPredicates -> toJSONKeyValue avAggregationPredicates
-- | A simple alias for the kind of boolean expressions used in the schema, that ties together
-- 'GBoolExp', 'OpExpG', and 'AnnBoolExpFld'.

View File

@ -0,0 +1,183 @@
{-# LANGUAGE UndecidableInstances #-}
-- | This module contains the default types and function that model aggregation
-- predicates.
module Hasura.RQL.IR.BoolExp.AggregationPredicates
( AggregationPredicatesImplementation (..),
AggregationPredicate (..),
AggregationPredicateArguments (..),
)
where
import Data.Aeson
import Data.Aeson.Extended (ToJSONKeyValue (..))
import Data.Aeson.Key (fromText)
import Hasura.Incremental (Cacheable)
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp (AnnBoolExp, OpExpG)
import Hasura.RQL.Types.Backend (Backend (Column))
import Hasura.RQL.Types.Backend qualified as B
import Hasura.RQL.Types.Relationships.Local (RelInfo)
import Hasura.SQL.Backend (BackendType)
-- | This type the default non-empty implementation of the
-- 'AggregationPredicates' type family of 'class Backend'.
--
-- This represents an _applied_ aggregation predicate, i.e. _not_ an aggegation
-- function in isolation.
--
-- In the default schema implementation, this type results from parsing graphql such as:
--
-- table(_where(
-- <relation>_aggregate:
-- {<functionname>: {
-- arguments: <arguments>,
-- predicate: <predicate>,
-- distinct: bool
-- }
-- }
-- ))
-- { ... }
--
-- Note that we make no attemt at modelling window functions or so-called
-- 'analytical' functions such as 'percentile_cont'.
data AggregationPredicatesImplementation (b :: BackendType) field = AggregationPredicatesImplementation
{ aggRelation :: RelInfo b,
aggPredicates :: [AggregationPredicate b field]
}
deriving stock (Foldable, Traversable, Functor, Generic)
deriving instance
( B.Backend b,
Eq (AggregationPredicate b field)
) =>
Eq (AggregationPredicatesImplementation b field)
deriving instance
( B.Backend b,
Show (AggregationPredicate b field)
) =>
Show (AggregationPredicatesImplementation b field)
instance
( B.Backend b,
Cacheable (AggregationPredicate b field)
) =>
Cacheable (AggregationPredicatesImplementation b field)
instance
( B.Backend b,
Hashable (AggregationPredicate b field)
) =>
Hashable (AggregationPredicatesImplementation b field)
instance
( B.Backend b,
NFData (AggregationPredicate b field)
) =>
NFData (AggregationPredicatesImplementation b field)
instance
( ToJSON (AnnBoolExp b field),
ToJSON (AggregationPredicate b field),
ToJSON (OpExpG b field),
B.Backend b
) =>
ToJSON (AggregationPredicatesImplementation b field)
instance
( Backend b,
ToJSONKeyValue (AggregationPredicate b field)
) =>
ToJSONKeyValue (AggregationPredicatesImplementation b field)
where
toJSONKeyValue AggregationPredicatesImplementation {..} =
( fromText "aggregation_predicates",
toJSON
[ ("predicates" :: Text, toJSON $ map toJSONKeyValue aggPredicates),
("relation", toJSON aggRelation)
]
)
data AggregationPredicate (b :: BackendType) field = AggregationPredicate
{ aggPredFunctionName :: Text,
aggPredDistinct :: Bool,
aggPredFilter :: Maybe (AnnBoolExp b field),
aggPredArguments :: AggregationPredicateArguments b,
aggPredPredicate :: [OpExpG b field]
}
deriving stock (Foldable, Traversable, Functor, Generic)
deriving instance
( B.Backend b,
Eq (AnnBoolExp b field),
Eq (OpExpG b field),
Eq (AggregationPredicateArguments b)
) =>
Eq (AggregationPredicate b field)
deriving instance
( B.Backend b,
Show (AnnBoolExp b field),
Show (OpExpG b field),
Show (AggregationPredicateArguments b)
) =>
Show (AggregationPredicate b field)
instance
( B.Backend b,
Hashable (B.BooleanOperators b field),
Hashable (AnnBoolExp b field),
Hashable field
) =>
Hashable (AggregationPredicate b field)
instance
( B.Backend b,
Cacheable (AggregationPredicateArguments b),
Cacheable (AnnBoolExp b field),
Cacheable (OpExpG b field)
) =>
Cacheable (AggregationPredicate b field)
instance
( B.Backend b,
NFData (AggregationPredicateArguments b),
NFData (AnnBoolExp b field),
NFData (OpExpG b field)
) =>
NFData (AggregationPredicate b field)
instance
( ToJSON (AggregationPredicateArguments b),
ToJSON (AnnBoolExp b field),
ToJSONKeyValue (OpExpG b field)
) =>
ToJSONKeyValue (AggregationPredicate b field)
where
toJSONKeyValue AggregationPredicate {..} =
( fromText aggPredFunctionName,
toJSON
[ ("aggPredDistinct" :: Text, toJSON aggPredDistinct),
("aggPredFilter", toJSON aggPredFilter),
("aggPredArguments", toJSON aggPredArguments),
("aggPredPredicate", toJSON (map toJSONKeyValue aggPredPredicate))
]
)
data AggregationPredicateArguments (b :: BackendType)
= AggregationPredicateArgumentsStar
| AggregationPredicateArguments (NonEmpty (Column b))
deriving stock (Generic)
deriving instance B.Backend b => Eq (AggregationPredicateArguments b)
deriving instance B.Backend b => Show (AggregationPredicateArguments b)
instance Backend b => Hashable (AggregationPredicateArguments b)
instance Backend b => Cacheable (AggregationPredicateArguments b)
instance Backend b => NFData (AggregationPredicateArguments b)
instance (Backend b) => ToJSON (AggregationPredicateArguments b)

View File

@ -86,7 +86,6 @@ class
Ord (FunctionName b),
Ord (ScalarType b),
Data (TableName b),
Traversable (BooleanOperators b),
FromJSON (BackendConfig b),
FromJSON (Column b),
FromJSON (ConstraintName b),
@ -152,12 +151,16 @@ class
Eq (XStreamingSubscription b),
Show (XStreamingSubscription b),
-- Intermediate Representations
Traversable (BooleanOperators b),
Functor (BackendUpdate b),
Foldable (BackendUpdate b),
Traversable (BackendUpdate b),
Functor (BackendInsert b),
Foldable (BackendInsert b),
Traversable (BackendInsert b)
Traversable (BackendInsert b),
Functor (AggregationPredicates b),
Foldable (AggregationPredicates b),
Traversable (AggregationPredicates b)
) =>
Backend (b :: BackendType)
where
@ -194,7 +197,6 @@ class
type ScalarValue b :: Type
type ScalarType b :: Type
type BooleanOperators b :: Type -> Type
type SQLExpression b :: Type
type ComputedFieldDefinition b :: Type
@ -215,6 +217,9 @@ class
type FunctionArgument b :: Type
-- | Function input argument expression
--
-- It is parameterised over the type of fields, which changes during the IR
-- translation phases.
type FunctionArgumentExp b :: Type -> Type
-- | Computed field function argument values which are being implicitly inferred from table and/or session information
@ -225,14 +230,36 @@ class
-- Backend-specific IR types
-- | Intermediate Representation of extensions to the shared set of boolean
-- operators on table fields.
--
-- It is parameterised over the type of fields, which changes during the IR
-- translation phases.
type BooleanOperators b :: Type -> Type
-- | Intermediate Representation of aggregation predicates.
-- The default implementation makes aggregation predicates uninstantiable.
--
-- It is parameterised over the type of fields, which changes during the IR
-- translation phases.
type AggregationPredicates b :: Type -> Type
type AggregationPredicates b = Const Void
-- | Intermediate Representation of Update Mutations.
-- The default implementation makes update expressions uninstantiable.
--
-- It is parameterised over the type of fields, which changes during the IR
-- translation phases.
type BackendUpdate b :: Type -> Type
type BackendUpdate b = Const Void
-- | Intermediate Representation of Insert Mutations.
-- The default implementation makes insert expressions uninstantiable.
--
-- It is parameterised over the type of fields, which changes during the IR
-- translation phases.
type BackendInsert b :: Type -> Type
type BackendInsert b = Const Void

View File

@ -30,8 +30,10 @@ import Network.HTTP.Client qualified as HTTP
class
( Backend b,
Eq (AggregationPredicates b (PartialSQLExp b)),
Eq (BooleanOperators b (PartialSQLExp b)),
Eq (FunctionArgumentExp b (PartialSQLExp b)),
Hashable (AggregationPredicates b (PartialSQLExp b)),
Hashable (BooleanOperators b (PartialSQLExp b)),
Hashable (FunctionArgumentExp b (PartialSQLExp b))
) =>

View File

@ -83,7 +83,6 @@ module Hasura.RQL.Types.SchemaCache
getCols,
getRels,
getComputedFieldInfos,
RelInfo (..),
RolePermInfoMap,
InsPermInfo (..),
UpdPermInfo (..),
@ -112,6 +111,9 @@ module Hasura.RQL.Types.SchemaCache
initialResourceVersion,
getBoolExpDeps,
InlinedAllowlist,
BoolExpM (..),
BoolExpCtx (..),
getOpExpDeps,
)
where
@ -711,21 +713,10 @@ getRemoteDependencies schemaCache sourceName =
SORemoteSchemaPermission {} -> False
SORole {} -> False
-- | The table type context of schema dependency discovery. Boolean expressions
-- may refer to a so-called 'root table' (identified by a '$'-sign in the
-- expression input syntax) or the 'current' table.
data BoolExpCtx b = BoolExpCtx
{ source :: SourceName,
-- | Reference to the 'current' table type.
currTable :: TableName b,
-- | Reference to the 'root' table type.
rootTable :: TableName b
}
-- | Discover the schema dependencies of an @AnnBoolExpPartialSQL@.
getBoolExpDeps ::
forall b.
Backend b =>
(GetAggregationPredicatesDeps b) =>
SourceName ->
TableName b ->
AnnBoolExpPartialSQL b ->
@ -733,17 +724,9 @@ getBoolExpDeps ::
getBoolExpDeps source tableName =
runBoolExpM (BoolExpCtx {source = source, currTable = tableName, rootTable = tableName}) . getBoolExpDeps'
-- | The monad for doing schema dependency discovery for boolean expressions.
-- maintains the table context of the expressions being translated.
newtype BoolExpM b a = BoolExpM {unBoolExpM :: Reader (BoolExpCtx b) a}
deriving (Functor, Applicative, Monad, MonadReader (BoolExpCtx b))
runBoolExpM :: BoolExpCtx b -> BoolExpM b a -> a
runBoolExpM ctx = flip runReader ctx . unBoolExpM
getBoolExpDeps' ::
forall b.
Backend b =>
(Backend b, GetAggregationPredicatesDeps b) =>
AnnBoolExpPartialSQL b ->
BoolExpM b [SchemaDependency]
getBoolExpDeps' = \case
@ -767,7 +750,7 @@ getBoolExpDeps' = \case
getColExpDeps ::
forall b.
Backend b =>
(Backend b, GetAggregationPredicatesDeps b) =>
AnnBoolExpFld b (PartialSQLExp b) ->
BoolExpM b [SchemaDependency]
getColExpDeps bexp = do
@ -777,7 +760,7 @@ getColExpDeps bexp = do
let columnName = ciColumn colInfo
colDepReason = bool DRSessionVariable DROnType $ any hasStaticExp opExps
colDep = mkColDep @b colDepReason source currTable columnName
in (colDep :) <$> mkOpExpDeps opExps
in (colDep :) <$> getOpExpDeps opExps
AVRelationship relInfo relBoolExp ->
let relationshipName = riName relInfo
relationshipTable = riRTable relInfo
@ -797,19 +780,24 @@ getColExpDeps bexp = do
let computedFieldDep =
mkComputedFieldDep' $
bool DRSessionVariable DROnType $ any hasStaticExp opExps
in (computedFieldDep :) <$> mkOpExpDeps opExps
in (computedFieldDep :) <$> getOpExpDeps opExps
CFBETable cfTable cfTableBoolExp ->
(mkComputedFieldDep' DROnType :) <$> local (\e -> e {currTable = cfTable}) (getBoolExpDeps' cfTableBoolExp)
where
mkOpExpDeps :: [OpExpG b (PartialSQLExp b)] -> BoolExpM b [SchemaDependency]
mkOpExpDeps opExps = do
BoolExpCtx {source, rootTable, currTable} <- ask
pure $ do
RootOrCurrentColumn rootOrCol col <- mapMaybe opExpDepCol opExps
let table = case rootOrCol of
IsRoot -> rootTable
IsCurrent -> currTable
pure $ mkColDep @b DROnType source table col
AVAggregationPredicates aggPreds -> getAggregationPredicateDeps aggPreds
getOpExpDeps ::
forall b.
(Backend b) =>
[OpExpG b (PartialSQLExp b)] ->
BoolExpM b [SchemaDependency]
getOpExpDeps opExps = do
BoolExpCtx {source, rootTable, currTable} <- ask
pure $ do
RootOrCurrentColumn rootOrCol col <- mapMaybe opExpDepCol opExps
let table = case rootOrCol of
IsRoot -> rootTable
IsCurrent -> currTable
pure $ mkColDep @b DROnType source table col
-- | Asking for a table's fields info without explicit @'SourceName' argument.
-- The source name is implicitly inferred from @'SourceM' via @'TableCoreInfoRM'.

View File

@ -0,0 +1,46 @@
-- | This module defines the schema dependency gathering aspect of the default
-- implementation of aggregation predicates.
module Hasura.RQL.Types.SchemaCache.AggregationPredicates
( defaultGetAggregationPredicateDeps,
)
where
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp (PartialSQLExp)
import Hasura.RQL.IR.BoolExp.AggregationPredicates
( AggregationPredicate (..),
AggregationPredicatesImplementation (AggregationPredicatesImplementation),
)
import Hasura.RQL.Types.Backend (Backend)
import Hasura.RQL.Types.Relationships.Local
( RelInfo (..),
)
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.SchemaCacheTypes
import Hasura.SQL.AnyBackend qualified as AB
defaultGetAggregationPredicateDeps ::
forall b.
(Backend b, GetAggregationPredicatesDeps b) =>
AggregationPredicatesImplementation b (PartialSQLExp b) ->
BoolExpM b [SchemaDependency]
defaultGetAggregationPredicateDeps (AggregationPredicatesImplementation relInfo functions) = do
BoolExpCtx {source, currTable} <- ask
let relationshipName = riName relInfo
relationshipTable = riRTable relInfo
schemaDependency =
SchemaDependency
( SOSourceObj source $
AB.mkAnyBackend $
SOITableObj @b currTable (TORel relationshipName)
)
DROnType
in (schemaDependency :) <$> local (\e -> e {currTable = relationshipTable}) (concat <$> traverse getFunctionDeps functions)
where
getFunctionDeps :: AggregationPredicate b (PartialSQLExp b) -> BoolExpM b [SchemaDependency]
getFunctionDeps AggregationPredicate {..} =
do
BoolExpCtx {source, currTable} <- ask
let filterDeps = maybe [] (getBoolExpDeps source currTable) aggPredFilter
predicateDeps <- getOpExpDeps aggPredPredicate
return $ filterDeps ++ predicateDeps

View File

@ -0,0 +1,11 @@
{-# OPTIONS_GHC -Wno-dodgy-exports #-}
--
module Hasura.RQL.Types.SchemaCache.Instances (module I) where
import Hasura.Backends.BigQuery.Instances.SchemaCache as I ()
import Hasura.Backends.DataConnector.Adapter.SchemaCache as I ()
import Hasura.Backends.MSSQL.Instances.SchemaCache as I ()
import Hasura.Backends.MySQL.Instances.SchemaCache as I ()
import Hasura.Backends.Postgres.Instances.SchemaCache as I ()

View File

@ -1,7 +1,11 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
module Hasura.RQL.Types.SchemaCacheTypes
( DependencyReason (..),
( BoolExpM (..),
GetAggregationPredicatesDeps (..),
BoolExpCtx (..),
DependencyReason (..),
SchemaDependency (..),
SchemaObjId (..),
SourceObjId (..),
@ -12,17 +16,20 @@ module Hasura.RQL.Types.SchemaCacheTypes
reportDependentObjectsExist,
reportSchemaObj,
reportSchemaObjs,
runBoolExpM,
)
where
import Data.Aeson
import Data.Aeson.TH
import Data.Aeson.Types
import Data.Functor.Const
import Data.Text qualified as T
import Data.Text.Extended
import Data.Text.NonEmpty
import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp (PartialSQLExp)
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
@ -215,3 +222,33 @@ purgeDependentObject source sourceObjId = case sourceObjId of
throw500 $
"unexpected dependent object: "
<> reportSchemaObj (SOSourceObj source $ AB.mkAnyBackend sourceObjId)
-- | Type class to collect schema dependencies from backend-specific aggregation predicates.
class Backend b => GetAggregationPredicatesDeps b where
getAggregationPredicateDeps ::
AggregationPredicates b (PartialSQLExp b) ->
BoolExpM b [SchemaDependency]
default getAggregationPredicateDeps ::
(AggregationPredicates b ~ Const Void) =>
AggregationPredicates b (PartialSQLExp b) ->
BoolExpM b [SchemaDependency]
getAggregationPredicateDeps = absurd . getConst
-- | The monad for doing schema dependency discovery for boolean expressions.
-- maintains the table context of the expressions being translated.
newtype BoolExpM b a = BoolExpM {unBoolExpM :: Reader (BoolExpCtx b) a}
deriving (Functor, Applicative, Monad, MonadReader (BoolExpCtx b))
-- | The table type context of schema dependency discovery. Boolean expressions
-- may refer to a so-called 'root table' (identified by a '$'-sign in the
-- expression input syntax) or the 'current' table.
data BoolExpCtx b = BoolExpCtx
{ source :: SourceName,
-- | Reference to the 'current' table type.
currTable :: TableName b,
-- | Reference to the 'root' table type.
rootTable :: TableName b
}
runBoolExpM :: BoolExpCtx b -> BoolExpM b a -> a
runBoolExpM ctx = flip runReader ctx . unBoolExpM

View File

@ -44,6 +44,7 @@ import Hasura.RQL.Types.Action
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.CustomTypes
import Hasura.RQL.Types.Metadata.Instances ()
import Hasura.RQL.Types.Relationships.Local
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.Source
import Hasura.RQL.Types.Table