mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-10-05 14:28:08 +03:00
Remove circular dependency in schema building code
### Description The main goal of this PR is, as stated, to remove the circular dependency in the schema building code. This cycle arises from the existence of remote relationships: when we build the schema for a source A, a remote relationship might force us to jump to the schema of a source B, or some remote schema. As a result, we end up having to do a dispatch from a "leaf" of the schema, similar to the one done at the root. In turn, this forces us to carry along in the schema a lot of information required for that dispatch, AND it forces us to import the instances in scope, creating an import loop. As discussed in #4489, this PR implements the "dependency injection" solution: we pass to the schema a function to call to do the dispatch, and to get a generated field for a remote relationship. That way, this function can be chosen at the root level, and the leaves need not be aware of the overall context. This PR grew a bit bigger than that, however; in an attempt to try and remove the `SourceCache` from the schema altogether, it changed a lot of functions across the schema building code, to thread along the `SourceInfo b` of the source being built. This avoids having to do cache lookups within a given source. A few cases remain, such as relay, that we might try to tackle in a subsequent PR. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4557 GitOrigin-RevId: 9388e48372877520a72a9fd1677005df9f7b2d72
This commit is contained in:
parent
cbe0479406
commit
498442b1d3
@ -33,6 +33,7 @@ import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.ComputedField
|
||||
import Hasura.RQL.Types.Function
|
||||
import Hasura.RQL.Types.SchemaCache hiding (askTableInfo)
|
||||
import Hasura.RQL.Types.Source (SourceInfo)
|
||||
import Hasura.RQL.Types.SourceCustomization (NamingCase)
|
||||
import Hasura.RQL.Types.Table
|
||||
import Hasura.SQL.Backend
|
||||
@ -76,7 +77,7 @@ instance BackendSchema 'BigQuery where
|
||||
|
||||
bqBuildTableRelayQueryFields ::
|
||||
MonadBuildSchema 'BigQuery r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'BigQuery ->
|
||||
TableName 'BigQuery ->
|
||||
TableInfo 'BigQuery ->
|
||||
C.GQLNameIdentifier ->
|
||||
@ -88,7 +89,7 @@ bqBuildTableRelayQueryFields _sourceName _tableName _tableInfo _gqlName _pkeyCol
|
||||
bqBuildTableInsertMutationFields ::
|
||||
MonadBuildSchema 'BigQuery r m n =>
|
||||
Scenario ->
|
||||
SourceName ->
|
||||
SourceInfo 'BigQuery ->
|
||||
TableName 'BigQuery ->
|
||||
TableInfo 'BigQuery ->
|
||||
C.GQLNameIdentifier ->
|
||||
@ -98,7 +99,7 @@ bqBuildTableInsertMutationFields _scenario _sourceName _tableName _tableInfo _gq
|
||||
|
||||
bqBuildTableUpdateMutationFields ::
|
||||
MonadBuildSchema 'BigQuery r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'BigQuery ->
|
||||
TableName 'BigQuery ->
|
||||
TableInfo 'BigQuery ->
|
||||
C.GQLNameIdentifier ->
|
||||
@ -108,7 +109,7 @@ bqBuildTableUpdateMutationFields _sourceName _tableName _tableInfo _gqlName =
|
||||
|
||||
bqBuildTableDeleteMutationFields ::
|
||||
MonadBuildSchema 'BigQuery r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'BigQuery ->
|
||||
TableName 'BigQuery ->
|
||||
TableInfo 'BigQuery ->
|
||||
C.GQLNameIdentifier ->
|
||||
@ -118,7 +119,7 @@ bqBuildTableDeleteMutationFields _sourceName _tableName _tableInfo _gqlName =
|
||||
|
||||
bqBuildFunctionQueryFields ::
|
||||
MonadBuildSchema 'BigQuery r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'BigQuery ->
|
||||
FunctionName 'BigQuery ->
|
||||
FunctionInfo 'BigQuery ->
|
||||
TableName 'BigQuery ->
|
||||
@ -128,7 +129,7 @@ bqBuildFunctionQueryFields _ _ _ _ =
|
||||
|
||||
bqBuildFunctionRelayQueryFields ::
|
||||
MonadBuildSchema 'BigQuery r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'BigQuery ->
|
||||
FunctionName 'BigQuery ->
|
||||
FunctionInfo 'BigQuery ->
|
||||
TableName 'BigQuery ->
|
||||
@ -139,7 +140,7 @@ bqBuildFunctionRelayQueryFields _sourceName _functionName _functionInfo _tableNa
|
||||
|
||||
bqBuildFunctionMutationFields ::
|
||||
MonadBuildSchema 'BigQuery r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'BigQuery ->
|
||||
FunctionName 'BigQuery ->
|
||||
FunctionInfo 'BigQuery ->
|
||||
TableName 'BigQuery ->
|
||||
@ -248,11 +249,11 @@ bqOrderByOperators _tCase =
|
||||
|
||||
bqComparisonExps ::
|
||||
forall m n r.
|
||||
(BackendSchema 'BigQuery, MonadSchema n m, MonadError QErr m, MonadReader r m, Has QueryContext r, Has MkTypename r, Has NamingCase r) =>
|
||||
(MonadBuildSchema 'BigQuery r m n) =>
|
||||
ColumnType 'BigQuery ->
|
||||
m (Parser 'Input n [ComparisonExp 'BigQuery])
|
||||
bqComparisonExps = P.memoize 'comparisonExps $ \columnType -> do
|
||||
collapseIfNull <- asks $ qcDangerousBooleanCollapse . getter
|
||||
collapseIfNull <- retrieve soDangerousBooleanCollapse
|
||||
dWithinGeogOpParser <- geographyWithinDistanceInput
|
||||
tCase <- asks getter
|
||||
-- see Note [Columns in comparison expression are never nullable]
|
||||
@ -395,13 +396,13 @@ geographyWithinDistanceInput = do
|
||||
bqComputedField ::
|
||||
forall r m n.
|
||||
MonadBuildSchema 'BigQuery r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'BigQuery ->
|
||||
ComputedFieldInfo 'BigQuery ->
|
||||
TableName 'BigQuery ->
|
||||
TableInfo 'BigQuery ->
|
||||
m (Maybe (FieldParser n (AnnotatedField 'BigQuery)))
|
||||
bqComputedField sourceName ComputedFieldInfo {..} tableName _tableInfo = runMaybeT do
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
fieldName <- lift $ textToName $ computedFieldNameToText _cfiName
|
||||
functionArgsParser <- lift $ computedFieldFunctionArgs _cfiFunction
|
||||
case _cfiReturnType of
|
||||
|
@ -25,7 +25,7 @@ import Hasura.Prelude
|
||||
import Hasura.RQL.IR.Select (SelectArgsG (..))
|
||||
import Hasura.RQL.Types.Backend qualified as RQL
|
||||
import Hasura.RQL.Types.Column qualified as RQL
|
||||
import Hasura.RQL.Types.Common qualified as RQL
|
||||
import Hasura.RQL.Types.Source qualified as RQL
|
||||
import Hasura.RQL.Types.SourceCustomization (NamingCase)
|
||||
import Hasura.RQL.Types.Table qualified as RQL
|
||||
import Hasura.SQL.Backend (BackendType (..))
|
||||
@ -74,7 +74,7 @@ instance BackendSchema 'DataConnector where
|
||||
|
||||
experimentalBuildTableRelayQueryFields ::
|
||||
MonadBuildSchema 'DataConnector r m n =>
|
||||
RQL.SourceName ->
|
||||
RQL.SourceInfo 'DataConnector ->
|
||||
RQL.TableName 'DataConnector ->
|
||||
RQL.TableInfo 'DataConnector ->
|
||||
GQLNameIdentifier ->
|
||||
@ -124,14 +124,14 @@ comparisonExps' ::
|
||||
MonadSchema n m,
|
||||
MonadError QErr m,
|
||||
MonadReader r m,
|
||||
Has GS.C.QueryContext r,
|
||||
Has GS.C.SchemaOptions r,
|
||||
Has NamingCase r
|
||||
) =>
|
||||
RQL.ColumnType 'DataConnector ->
|
||||
m (P.Parser 'P.Input n [ComparisonExp 'DataConnector])
|
||||
comparisonExps' = P.memoize 'comparisonExps' $ \columnType -> do
|
||||
tCase <- asks getter
|
||||
collapseIfNull <- asks $ GS.C.qcDangerousBooleanCollapse . getter
|
||||
collapseIfNull <- GS.C.retrieve GS.C.soDangerousBooleanCollapse
|
||||
typedParser <- columnParser' columnType (GQL.Nullability False)
|
||||
nullableTextParser <- columnParser' (RQL.ColumnScalar IR.S.T.String) (GQL.Nullability True)
|
||||
textParser <- columnParser' (RQL.ColumnScalar IR.S.T.String) (GQL.Nullability False)
|
||||
@ -170,7 +170,7 @@ comparisonExps' = P.memoize 'comparisonExps' $ \columnType -> do
|
||||
tableArgs' ::
|
||||
forall r m n.
|
||||
MonadBuildSchema 'DataConnector r m n =>
|
||||
RQL.SourceName ->
|
||||
RQL.SourceInfo 'DataConnector ->
|
||||
RQL.TableInfo 'DataConnector ->
|
||||
m (P.InputFieldsParser n (SelectArgsG 'DataConnector (P.UnpreparedValue 'DataConnector)))
|
||||
tableArgs' sourceName tableInfo = do
|
||||
|
@ -40,6 +40,7 @@ import Hasura.RQL.Types.ComputedField
|
||||
import Hasura.RQL.Types.Function
|
||||
import Hasura.RQL.Types.Relationships.Local
|
||||
import Hasura.RQL.Types.SchemaCache
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization (NamingCase)
|
||||
import Hasura.RQL.Types.Table
|
||||
import Hasura.SQL.Backend
|
||||
@ -87,7 +88,7 @@ instance BackendSchema 'MSSQL where
|
||||
|
||||
msBuildTableRelayQueryFields ::
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
TableName 'MSSQL ->
|
||||
TableInfo 'MSSQL ->
|
||||
C.GQLNameIdentifier ->
|
||||
@ -99,7 +100,7 @@ msBuildTableRelayQueryFields _sourceName _tableName _tableInfo _gqlName _pkeyCol
|
||||
backendInsertParser ::
|
||||
forall m r n.
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
TableInfo 'MSSQL ->
|
||||
m (InputFieldsParser n (BackendInsert (UnpreparedValue 'MSSQL)))
|
||||
backendInsertParser sourceName tableInfo = do
|
||||
@ -111,7 +112,7 @@ backendInsertParser sourceName tableInfo = do
|
||||
|
||||
msBuildTableUpdateMutationFields ::
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
TableName 'MSSQL ->
|
||||
TableInfo 'MSSQL ->
|
||||
C.GQLNameIdentifier ->
|
||||
@ -142,7 +143,7 @@ this. Should we save it?
|
||||
|
||||
msBuildTableDeleteMutationFields ::
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
TableName 'MSSQL ->
|
||||
TableInfo 'MSSQL ->
|
||||
G.Name ->
|
||||
@ -155,7 +156,7 @@ msBuildTableDeleteMutationFields _sourceName _tableName _tableInfo _gqlName _del
|
||||
|
||||
msBuildFunctionQueryFields ::
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
FunctionName 'MSSQL ->
|
||||
FunctionInfo 'MSSQL ->
|
||||
TableName 'MSSQL ->
|
||||
@ -165,7 +166,7 @@ msBuildFunctionQueryFields _ _ _ _ =
|
||||
|
||||
msBuildFunctionRelayQueryFields ::
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
FunctionName 'MSSQL ->
|
||||
FunctionInfo 'MSSQL ->
|
||||
TableName 'MSSQL ->
|
||||
@ -176,7 +177,7 @@ msBuildFunctionRelayQueryFields _sourceName _functionName _functionInfo _tableNa
|
||||
|
||||
msBuildFunctionMutationFields ::
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
FunctionName 'MSSQL ->
|
||||
FunctionInfo 'MSSQL ->
|
||||
TableName 'MSSQL ->
|
||||
@ -191,7 +192,7 @@ msBuildFunctionMutationFields _ _ _ _ =
|
||||
msTableArgs ::
|
||||
forall r m n.
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
TableInfo 'MSSQL ->
|
||||
m (InputFieldsParser n (IR.SelectArgsG 'MSSQL (UnpreparedValue 'MSSQL)))
|
||||
msTableArgs sourceName tableInfo = do
|
||||
@ -215,7 +216,7 @@ msTableArgs sourceName tableInfo = do
|
||||
msMkRelationshipParser ::
|
||||
forall r m n.
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
RelInfo 'MSSQL ->
|
||||
m (Maybe (InputFieldsParser n (Maybe (IR.AnnotatedInsertField 'MSSQL (UnpreparedValue 'MSSQL)))))
|
||||
msMkRelationshipParser _sourceName _relationshipInfo = do
|
||||
@ -335,7 +336,7 @@ msComparisonExps ::
|
||||
MonadSchema n m,
|
||||
MonadError QErr m,
|
||||
MonadReader r m,
|
||||
Has QueryContext r,
|
||||
Has SchemaOptions r,
|
||||
Has MkTypename r,
|
||||
Has NamingCase r
|
||||
) =>
|
||||
@ -343,7 +344,7 @@ msComparisonExps ::
|
||||
m (Parser 'Input n [ComparisonExp 'MSSQL])
|
||||
msComparisonExps = P.memoize 'comparisonExps \columnType -> do
|
||||
-- see Note [Columns in comparison expression are never nullable]
|
||||
collapseIfNull <- asks $ qcDangerousBooleanCollapse . getter
|
||||
collapseIfNull <- retrieve soDangerousBooleanCollapse
|
||||
|
||||
-- parsers used for individual values
|
||||
typedParser <- columnParser columnType (G.Nullability False)
|
||||
@ -448,7 +449,7 @@ msCountTypeInput = \case
|
||||
-- Currently unsupported: returns Nothing for now.
|
||||
msComputedField ::
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
ComputedFieldInfo 'MSSQL ->
|
||||
TableName 'MSSQL ->
|
||||
TableInfo 'MSSQL ->
|
||||
|
@ -33,8 +33,8 @@ import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.RQL.Types.Column
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.SchemaCache
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.Table
|
||||
import Hasura.SQL.Backend
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
@ -55,24 +55,24 @@ import Language.GraphQL.Draft.Syntax qualified as G
|
||||
ifMatchedFieldParser ::
|
||||
forall r m n.
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
TableInfo 'MSSQL ->
|
||||
m (InputFieldsParser n (Maybe (IfMatched (UnpreparedValue 'MSSQL))))
|
||||
ifMatchedFieldParser sourceName tableInfo = do
|
||||
maybeObject <- ifMatchedObjectParser sourceName tableInfo
|
||||
ifMatchedFieldParser sourceInfo tableInfo = do
|
||||
maybeObject <- ifMatchedObjectParser sourceInfo tableInfo
|
||||
return $ withJust maybeObject $ P.fieldOptional G._if_matched (Just "upsert condition")
|
||||
|
||||
-- | Parse a @tablename_if_matched@ object.
|
||||
ifMatchedObjectParser ::
|
||||
forall r m n.
|
||||
MonadBuildSchema 'MSSQL r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
TableInfo 'MSSQL ->
|
||||
m (Maybe (Parser 'Input n (IfMatched (UnpreparedValue 'MSSQL))))
|
||||
ifMatchedObjectParser sourceName tableInfo = runMaybeT do
|
||||
ifMatchedObjectParser sourceInfo tableInfo = runMaybeT do
|
||||
-- Short-circuit if we don't have sufficient permissions.
|
||||
updatePerms <- MaybeT $ _permUpd <$> tablePermissions tableInfo
|
||||
matchColumnsEnum <- MaybeT $ tableInsertMatchColumnsEnum sourceName tableInfo
|
||||
matchColumnsEnum <- MaybeT $ tableInsertMatchColumnsEnum sourceInfo tableInfo
|
||||
lift do
|
||||
updateColumnsEnum <- updateColumnsPlaceholderParser tableInfo
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
@ -83,7 +83,7 @@ ifMatchedObjectParser sourceName tableInfo = runMaybeT do
|
||||
matchColumnsName = G._match_columns
|
||||
updateColumnsName = G._update_columns
|
||||
whereName = G._where
|
||||
whereExpParser <- boolExp sourceName tableInfo
|
||||
whereExpParser <- boolExp sourceInfo tableInfo
|
||||
pure $
|
||||
P.object objectName (Just objectDesc) do
|
||||
_imConditions <-
|
||||
@ -109,12 +109,12 @@ ifMatchedObjectParser sourceName tableInfo = runMaybeT do
|
||||
tableInsertMatchColumnsEnum ::
|
||||
forall r m n.
|
||||
MonadBuildSchemaBase r m n =>
|
||||
SourceName ->
|
||||
SourceInfo 'MSSQL ->
|
||||
TableInfo 'MSSQL ->
|
||||
m (Maybe (Parser 'Both n (Column 'MSSQL)))
|
||||
tableInsertMatchColumnsEnum sourceName tableInfo = do
|
||||
tableInsertMatchColumnsEnum sourceInfo tableInfo = do
|
||||
tableGQLName <- getTableGQLName @'MSSQL tableInfo
|
||||
columns <- tableSelectColumns sourceName tableInfo
|
||||
columns <- tableSelectColumns sourceInfo tableInfo
|
||||
enumName <- P.mkTypename $ tableGQLName <> G.__insert_match_column
|
||||
let description =
|
||||
Just $
|
||||
|
@ -27,9 +27,9 @@ import Hasura.RQL.IR
|
||||
import Hasura.RQL.IR.Select qualified as IR
|
||||
import Hasura.RQL.Types.Backend as RQL
|
||||
import Hasura.RQL.Types.Column as RQL
|
||||
import Hasura.RQL.Types.Common as RQL
|
||||
import Hasura.RQL.Types.Function as RQL
|
||||
import Hasura.RQL.Types.SchemaCache as RQL
|
||||
import Hasura.RQL.Types.Source as RQL
|
||||
import Hasura.RQL.Types.SourceCustomization (NamingCase)
|
||||
import Hasura.SQL.Backend
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
@ -60,12 +60,12 @@ instance BackendSchema 'MySQL where
|
||||
mysqlTableArgs ::
|
||||
forall r m n.
|
||||
MonadBuildSchema 'MySQL r m n =>
|
||||
SourceName ->
|
||||
RQL.SourceInfo 'MySQL ->
|
||||
TableInfo 'MySQL ->
|
||||
m (InputFieldsParser n (IR.SelectArgsG 'MySQL (UnpreparedValue 'MySQL)))
|
||||
mysqlTableArgs sourceName tableInfo = do
|
||||
whereParser <- tableWhereArg sourceName tableInfo
|
||||
orderByParser <- tableOrderByArg sourceName tableInfo
|
||||
mysqlTableArgs sourceInfo tableInfo = do
|
||||
whereParser <- tableWhereArg sourceInfo tableInfo
|
||||
orderByParser <- tableOrderByArg sourceInfo tableInfo
|
||||
pure do
|
||||
whereArg <- whereParser
|
||||
orderByArg <- orderByParser
|
||||
@ -82,49 +82,49 @@ mysqlTableArgs sourceName tableInfo = do
|
||||
|
||||
buildTableRelayQueryFields' ::
|
||||
MonadBuildSchema 'MySQL r m n =>
|
||||
SourceName ->
|
||||
RQL.SourceInfo 'MySQL ->
|
||||
RQL.TableName 'MySQL ->
|
||||
TableInfo 'MySQL ->
|
||||
C.GQLNameIdentifier ->
|
||||
NESeq (ColumnInfo 'MySQL) ->
|
||||
m [a]
|
||||
buildTableRelayQueryFields' _sourceName _tableName _tableInfo _gqlName _pkeyColumns =
|
||||
buildTableRelayQueryFields' _sourceInfo _tableName _tableInfo _gqlName _pkeyColumns =
|
||||
pure []
|
||||
|
||||
buildTableInsertMutationFields' ::
|
||||
MonadBuildSchema 'MySQL r m n =>
|
||||
Scenario ->
|
||||
SourceName ->
|
||||
RQL.SourceInfo 'MySQL ->
|
||||
RQL.TableName 'MySQL ->
|
||||
TableInfo 'MySQL ->
|
||||
C.GQLNameIdentifier ->
|
||||
m [a]
|
||||
buildTableInsertMutationFields' _scenario _sourceName _tableName _tableInfo _gqlName =
|
||||
buildTableInsertMutationFields' _scenario _sourceInfo _tableName _tableInfo _gqlName =
|
||||
pure []
|
||||
|
||||
buildTableUpdateMutationFields' ::
|
||||
MonadBuildSchema 'MySQL r m n =>
|
||||
SourceName ->
|
||||
RQL.SourceInfo 'MySQL ->
|
||||
RQL.TableName 'MySQL ->
|
||||
TableInfo 'MySQL ->
|
||||
C.GQLNameIdentifier ->
|
||||
m [a]
|
||||
buildTableUpdateMutationFields' _sourceName _tableName _tableInfo _gqlName =
|
||||
buildTableUpdateMutationFields' _sourceInfo _tableName _tableInfo _gqlName =
|
||||
pure []
|
||||
|
||||
buildTableDeleteMutationFields' ::
|
||||
MonadBuildSchema 'MySQL r m n =>
|
||||
SourceName ->
|
||||
RQL.SourceInfo 'MySQL ->
|
||||
RQL.TableName 'MySQL ->
|
||||
TableInfo 'MySQL ->
|
||||
C.GQLNameIdentifier ->
|
||||
m [a]
|
||||
buildTableDeleteMutationFields' _sourceName _tableName _tableInfo _gqlName =
|
||||
buildTableDeleteMutationFields' _sourceInfo _tableName _tableInfo _gqlName =
|
||||
pure []
|
||||
|
||||
buildFunctionQueryFields' ::
|
||||
MonadBuildSchema 'MySQL r m n =>
|
||||
SourceName ->
|
||||
RQL.SourceInfo 'MySQL ->
|
||||
FunctionName 'MySQL ->
|
||||
FunctionInfo 'MySQL ->
|
||||
RQL.TableName 'MySQL ->
|
||||
@ -134,18 +134,18 @@ buildFunctionQueryFields' _ _ _ _ =
|
||||
|
||||
buildFunctionRelayQueryFields' ::
|
||||
MonadBuildSchema 'MySQL r m n =>
|
||||
SourceName ->
|
||||
RQL.SourceInfo 'MySQL ->
|
||||
FunctionName 'MySQL ->
|
||||
FunctionInfo 'MySQL ->
|
||||
RQL.TableName 'MySQL ->
|
||||
NESeq (ColumnInfo 'MySQL) ->
|
||||
m [a]
|
||||
buildFunctionRelayQueryFields' _sourceName _functionName _functionInfo _tableName _pkeyColumns =
|
||||
buildFunctionRelayQueryFields' _sourceInfo _functionName _functionInfo _tableName _pkeyColumns =
|
||||
pure []
|
||||
|
||||
buildFunctionMutationFields' ::
|
||||
MonadBuildSchema 'MySQL r m n =>
|
||||
SourceName ->
|
||||
RQL.SourceInfo 'MySQL ->
|
||||
FunctionName 'MySQL ->
|
||||
FunctionInfo 'MySQL ->
|
||||
RQL.TableName 'MySQL ->
|
||||
|
@ -58,6 +58,7 @@ import Hasura.RQL.Types.Backend (Backend (..))
|
||||
import Hasura.RQL.Types.Column
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.Function (FunctionInfo)
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization
|
||||
import Hasura.RQL.Types.Table (RolePermInfo (..), SelPermInfo, TableInfo, UpdPermInfo)
|
||||
import Hasura.SQL.Backend (BackendType (Postgres), PostgresKind (Citus, Vanilla))
|
||||
@ -79,7 +80,7 @@ import Language.GraphQL.Draft.Syntax qualified as G
|
||||
class PostgresSchema (pgKind :: PostgresKind) where
|
||||
pgkBuildTableRelayQueryFields ::
|
||||
BS.MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
TableName ('Postgres pgKind) ->
|
||||
TableInfo ('Postgres pgKind) ->
|
||||
C.GQLNameIdentifier ->
|
||||
@ -87,7 +88,7 @@ class PostgresSchema (pgKind :: PostgresKind) where
|
||||
m [FieldParser n (QueryDB ('Postgres pgKind) (RemoteRelationshipField UnpreparedValue) (UnpreparedValue ('Postgres pgKind)))]
|
||||
pgkBuildFunctionRelayQueryFields ::
|
||||
BS.MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
FunctionName ('Postgres pgKind) ->
|
||||
FunctionInfo ('Postgres pgKind) ->
|
||||
TableName ('Postgres pgKind) ->
|
||||
@ -174,7 +175,7 @@ instance
|
||||
backendInsertParser ::
|
||||
forall pgKind m r n.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
TableInfo ('Postgres pgKind) ->
|
||||
m (InputFieldsParser n (PGIR.BackendInsert pgKind (UnpreparedValue ('Postgres pgKind))))
|
||||
backendInsertParser sourceName tableInfo =
|
||||
@ -186,7 +187,7 @@ backendInsertParser sourceName tableInfo =
|
||||
buildTableRelayQueryFields ::
|
||||
forall pgKind m n r.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
TableName ('Postgres pgKind) ->
|
||||
TableInfo ('Postgres pgKind) ->
|
||||
C.GQLNameIdentifier ->
|
||||
@ -203,7 +204,7 @@ buildTableRelayQueryFields sourceName tableName tableInfo gqlName pkeyColumns =
|
||||
pgkBuildTableUpdateMutationFields ::
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
-- | The source that the table lives in
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
-- | The name of the table being acted on
|
||||
TableName ('Postgres pgKind) ->
|
||||
-- | table info
|
||||
@ -226,7 +227,7 @@ pgkBuildTableUpdateMutationFields sourceName tableName tableInfo gqlName =
|
||||
buildFunctionRelayQueryFields ::
|
||||
forall pgKind m n r.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
FunctionName ('Postgres pgKind) ->
|
||||
FunctionInfo ('Postgres pgKind) ->
|
||||
TableName ('Postgres pgKind) ->
|
||||
@ -357,7 +358,7 @@ comparisonExps ::
|
||||
MonadSchema n m,
|
||||
MonadError QErr m,
|
||||
MonadReader r m,
|
||||
Has QueryContext r,
|
||||
Has SchemaOptions r,
|
||||
Has MkTypename r,
|
||||
Has NamingCase r
|
||||
) =>
|
||||
@ -365,7 +366,7 @@ comparisonExps ::
|
||||
m (Parser 'Input n [ComparisonExp ('Postgres pgKind)])
|
||||
comparisonExps = P.memoize 'comparisonExps \columnType -> do
|
||||
-- see Note [Columns in comparison expression are never nullable]
|
||||
collapseIfNull <- asks $ qcDangerousBooleanCollapse . getter
|
||||
collapseIfNull <- retrieve soDangerousBooleanCollapse
|
||||
|
||||
-- parsers used for comparison arguments
|
||||
geogInputParser <- geographyWithinDistanceInput
|
||||
|
@ -31,8 +31,8 @@ import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.IR.Insert qualified as IR
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.SchemaCache
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization (applyFieldNameCaseCust)
|
||||
import Hasura.RQL.Types.Table
|
||||
import Hasura.SQL.Backend
|
||||
@ -53,14 +53,14 @@ import Language.GraphQL.Draft.Syntax qualified as G
|
||||
onConflictFieldParser ::
|
||||
forall pgKind r m n.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
TableInfo ('Postgres pgKind) ->
|
||||
m (InputFieldsParser n (Maybe (IR.OnConflictClause ('Postgres pgKind) (UnpreparedValue ('Postgres pgKind)))))
|
||||
onConflictFieldParser sourceName tableInfo = do
|
||||
onConflictFieldParser sourceInfo tableInfo = do
|
||||
tCase <- asks getter
|
||||
updatePerms <- _permUpd <$> tablePermissions tableInfo
|
||||
let maybeConstraints = tciUniqueOrPrimaryKeyConstraints . _tiCoreInfo $ tableInfo
|
||||
maybeConflictObject = conflictObjectParser sourceName tableInfo <$> maybeConstraints <*> updatePerms
|
||||
maybeConflictObject = conflictObjectParser sourceInfo tableInfo <$> maybeConstraints <*> updatePerms
|
||||
case maybeConflictObject of
|
||||
Just conflictObject -> conflictObject <&> P.fieldOptional (applyFieldNameCaseCust tCase G._on_conflict) (Just "upsert condition")
|
||||
Nothing -> return $ pure Nothing
|
||||
@ -69,15 +69,15 @@ onConflictFieldParser sourceName tableInfo = do
|
||||
conflictObjectParser ::
|
||||
forall pgKind r m n.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
TableInfo ('Postgres pgKind) ->
|
||||
NonEmpty (Constraint ('Postgres pgKind)) ->
|
||||
UpdPermInfo ('Postgres pgKind) ->
|
||||
m (Parser 'Input n (IR.OnConflictClause ('Postgres pgKind) (UnpreparedValue ('Postgres pgKind))))
|
||||
conflictObjectParser sourceName tableInfo constraints updatePerms = do
|
||||
conflictObjectParser sourceInfo tableInfo constraints updatePerms = do
|
||||
updateColumnsEnum <- updateColumnsPlaceholderParser tableInfo
|
||||
constraintParser <- conflictConstraint constraints sourceName tableInfo
|
||||
whereExpParser <- boolExp sourceName tableInfo
|
||||
constraintParser <- conflictConstraint constraints sourceInfo tableInfo
|
||||
whereExpParser <- boolExp sourceInfo tableInfo
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
objectName <- P.mkTypename $ tableGQLName <> G.__on_conflict
|
||||
|
||||
@ -116,11 +116,11 @@ conflictConstraint ::
|
||||
forall pgKind r m n.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
NonEmpty (Constraint ('Postgres pgKind)) ->
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
TableInfo ('Postgres pgKind) ->
|
||||
m (Parser 'Both n (ConstraintName ('Postgres pgKind)))
|
||||
conflictConstraint constraints sourceName tableInfo =
|
||||
memoizeOn 'conflictConstraint (sourceName, tableName) $ do
|
||||
conflictConstraint constraints sourceInfo tableInfo =
|
||||
memoizeOn 'conflictConstraint (_siName sourceInfo, tableName) $ do
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
constraintEnumValues <- for constraints \constraint -> do
|
||||
name <- textToName $ toTxt $ _cName constraint
|
||||
|
@ -23,7 +23,7 @@ import Hasura.Base.Error
|
||||
import Hasura.GraphQL.Execute.Types
|
||||
import Hasura.GraphQL.Parser.Constants qualified as G
|
||||
import Hasura.GraphQL.Parser.Monad (ParseT, runSchemaT)
|
||||
import Hasura.GraphQL.Schema.Common (QueryContext (..))
|
||||
import Hasura.GraphQL.Schema.Common
|
||||
import Hasura.GraphQL.Schema.Remote (buildRemoteParser)
|
||||
import Hasura.GraphQL.Transport.HTTP.Protocol
|
||||
import Hasura.HTTP
|
||||
@ -33,7 +33,6 @@ import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.Function
|
||||
import Hasura.RQL.Types.RemoteSchema
|
||||
import Hasura.RQL.Types.SchemaCache
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization
|
||||
import Hasura.Server.Utils
|
||||
import Hasura.Session
|
||||
@ -80,9 +79,12 @@ fetchRemoteSchema env manager _rscName rsDef@ValidatedRemoteSchemaDef {..} = do
|
||||
-- properly for each role at schema generation time, but this allows us to
|
||||
-- quickly reject an invalid schema.
|
||||
void $
|
||||
runSchemaT $
|
||||
flip runReaderT minimumValidContext $
|
||||
buildRemoteParser @_ @_ @(ParseT Identity) _rscIntroOriginal _rscRemoteRelationships _rscInfo
|
||||
flip runReaderT minimumValidContext $
|
||||
runSchemaT $
|
||||
buildRemoteParser @_ @_ @(ParseT Identity)
|
||||
_rscIntroOriginal
|
||||
_rscRemoteRelationships
|
||||
_rscInfo
|
||||
|
||||
-- The 'rawIntrospectionResult' contains the 'Bytestring' response of
|
||||
-- the introspection result of the remote server. We store this in the
|
||||
@ -113,28 +115,29 @@ fetchRemoteSchema env manager _rscName rsDef@ValidatedRemoteSchemaDef {..} = do
|
||||
-- the remote schema.
|
||||
minimumValidContext =
|
||||
( adminRoleName :: RoleName,
|
||||
mempty :: SourceCache,
|
||||
mempty :: CustomizeRemoteFieldName,
|
||||
mempty :: RemoteSchemaMap,
|
||||
mempty :: MkTypename,
|
||||
mempty :: MkRootFieldName,
|
||||
HasuraCase :: NamingCase,
|
||||
QueryContext
|
||||
SchemaOptions
|
||||
{ -- doesn't apply to remote schemas
|
||||
qcStringifyNum = LeaveNumbersAlone,
|
||||
soStringifyNum = LeaveNumbersAlone,
|
||||
-- doesn't apply to remote schemas
|
||||
qcDangerousBooleanCollapse = True,
|
||||
soDangerousBooleanCollapse = True,
|
||||
-- we don't support remote schemas in Relay, but the check is
|
||||
-- performed ahead of time, meaning that the value here is
|
||||
-- irrelevant
|
||||
qcQueryType = QueryHasura,
|
||||
soQueryType = QueryHasura,
|
||||
-- doesn't apply to remote schemas
|
||||
qcFunctionPermsContext = FunctionPermissionsInferred,
|
||||
soFunctionPermsContext = FunctionPermissionsInferred,
|
||||
-- we default to no permissions
|
||||
qcRemoteSchemaPermsCtx = RemoteSchemaPermsDisabled,
|
||||
soRemoteSchemaPermsCtx = RemoteSchemaPermsDisabled,
|
||||
-- doesn't apply to remote schemas
|
||||
qcOptimizePermissionFilters = False
|
||||
}
|
||||
soOptimizePermissionFilters = False
|
||||
},
|
||||
SchemaContext
|
||||
mempty
|
||||
ignoreRemoteRelationship
|
||||
)
|
||||
|
||||
-- | Sends a GraphQL query to the given server.
|
||||
|
@ -36,6 +36,7 @@ import Hasura.GraphQL.Schema.Instances ()
|
||||
import Hasura.GraphQL.Schema.Introspect
|
||||
import Hasura.GraphQL.Schema.Postgres
|
||||
import Hasura.GraphQL.Schema.Remote (buildRemoteParser)
|
||||
import Hasura.GraphQL.Schema.RemoteRelationship
|
||||
import Hasura.GraphQL.Schema.Select
|
||||
import Hasura.GraphQL.Schema.Table
|
||||
import Hasura.Prelude
|
||||
@ -176,15 +177,19 @@ buildRoleContext options sources remotes allActionInfos customTypes role remoteS
|
||||
queryType,
|
||||
functionPermsCtx
|
||||
) = options
|
||||
roleQueryContext =
|
||||
QueryContext
|
||||
schemaOptions =
|
||||
SchemaOptions
|
||||
stringifyNum
|
||||
dangerousBooleanCollapse
|
||||
queryType
|
||||
functionPermsCtx
|
||||
remoteSchemaPermsCtx
|
||||
optimizePermissionFilters
|
||||
runMonadSchema role roleQueryContext sources (fst <$> remotes) $ do
|
||||
schemaContext =
|
||||
SchemaContext
|
||||
sources
|
||||
(remoteRelationshipField sources (fst <$> remotes))
|
||||
runMonadSchema schemaOptions schemaContext role $ do
|
||||
-- build all sources
|
||||
(sourcesQueryFields, sourcesMutationFrontendFields, sourcesMutationBackendFields, subscriptionFields) <-
|
||||
fmap mconcat $ traverse (buildBackendSource buildSource) $ toList sources
|
||||
@ -261,15 +266,15 @@ buildRoleContext options sources remotes allActionInfos customTypes role remoteS
|
||||
[FieldParser (P.ParseT Identity) (NamespacedField (MutationRootField UnpreparedValue))],
|
||||
[FieldParser (P.ParseT Identity) (NamespacedField (QueryRootField UnpreparedValue))]
|
||||
)
|
||||
buildSource (SourceInfo sourceName tables functions sourceConfig queryTagsConfig sourceCustomization') =
|
||||
buildSource sourceInfo@(SourceInfo _ tables functions _ _ sourceCustomization') =
|
||||
withSourceCustomization sourceCustomization (namingConventionSupport @b) globalDefaultNC do
|
||||
let validFunctions = takeValidFunctions functions
|
||||
validTables = takeValidTables tables
|
||||
mkTypename <- asks getter
|
||||
uncustomizedQueryFields <- buildQueryFields sourceName sourceConfig validTables validFunctions queryTagsConfig
|
||||
uncustomizedQueryFields <- buildQueryFields sourceInfo validTables validFunctions
|
||||
uncustomizedStreamSubscriptionFields <-
|
||||
case streamingSubscriptionsCtx of
|
||||
StreamingSubscriptionsEnabled -> buildTableStreamSubscriptionFields sourceName sourceConfig validTables queryTagsConfig
|
||||
StreamingSubscriptionsEnabled -> buildTableStreamSubscriptionFields sourceInfo validTables
|
||||
StreamingSubscriptionsDisabled -> pure mempty
|
||||
(,,,)
|
||||
<$> customizeFields
|
||||
@ -279,11 +284,11 @@ buildRoleContext options sources remotes allActionInfos customTypes role remoteS
|
||||
<*> customizeFields
|
||||
sourceCustomization
|
||||
(mkTypename <> P.MkTypename (<> G.__mutation_frontend))
|
||||
(buildMutationFields Frontend sourceName sourceConfig validTables validFunctions queryTagsConfig)
|
||||
(buildMutationFields Frontend sourceInfo validTables validFunctions)
|
||||
<*> customizeFields
|
||||
sourceCustomization
|
||||
(mkTypename <> P.MkTypename (<> G.__mutation_backend))
|
||||
(buildMutationFields Backend sourceName sourceConfig validTables validFunctions queryTagsConfig)
|
||||
(buildMutationFields Backend sourceInfo validTables validFunctions)
|
||||
<*> customizeFields
|
||||
sourceCustomization
|
||||
(mkTypename <> P.MkTypename (<> G.__subscription))
|
||||
@ -310,18 +315,22 @@ buildRelayRoleContext options sources allActionInfos customTypes role expFeature
|
||||
queryType,
|
||||
functionPermsCtx
|
||||
) = options
|
||||
-- TODO: At the time of writing this, remote schema queries are not supported in relay.
|
||||
-- When they are supported, we should get do what `buildRoleContext` does. Since, they
|
||||
-- are not supported yet, we use `mempty` below for `RemoteSchemaMap`.
|
||||
roleQueryContext =
|
||||
QueryContext
|
||||
schemaOptions =
|
||||
SchemaOptions
|
||||
stringifyNum
|
||||
dangerousBooleanCollapse
|
||||
queryType
|
||||
functionPermsCtx
|
||||
RemoteSchemaPermsDisabled
|
||||
optimizePermissionFilters
|
||||
runMonadSchema role roleQueryContext sources mempty do
|
||||
-- TODO: At the time of writing this, remote schema queries are not supported in relay.
|
||||
-- When they are supported, we should get do what `buildRoleContext` does. Since, they
|
||||
-- are not supported yet, we use `mempty` below for `RemoteSchemaMap`.
|
||||
schemaContext =
|
||||
SchemaContext
|
||||
sources
|
||||
(remoteRelationshipField sources mempty)
|
||||
runMonadSchema schemaOptions schemaContext role do
|
||||
fieldsList <- traverse (buildBackendSource buildSource) $ toList sources
|
||||
|
||||
-- Add node root field.
|
||||
@ -381,7 +390,7 @@ buildRelayRoleContext options sources allActionInfos customTypes role expFeature
|
||||
[FieldParser (P.ParseT Identity) (NamespacedField (MutationRootField UnpreparedValue))],
|
||||
[FieldParser (P.ParseT Identity) (NamespacedField (MutationRootField UnpreparedValue))]
|
||||
)
|
||||
buildSource (SourceInfo sourceName tables functions sourceConfig queryTagsConfig sourceCustomization') =
|
||||
buildSource sourceInfo@(SourceInfo _ tables functions _ _ sourceCustomization') =
|
||||
withSourceCustomization sourceCustomization (namingConventionSupport @b) globalDefaultNC do
|
||||
let validFunctions = takeValidFunctions functions
|
||||
validTables = takeValidTables tables
|
||||
@ -391,15 +400,15 @@ buildRelayRoleContext options sources allActionInfos customTypes role expFeature
|
||||
<$> customizeFields
|
||||
sourceCustomization
|
||||
(mkTypename <> P.MkTypename (<> G.__query))
|
||||
(buildRelayQueryFields sourceName sourceConfig validTables validFunctions queryTagsConfig)
|
||||
(buildRelayQueryFields sourceInfo validTables validFunctions)
|
||||
<*> customizeFields
|
||||
sourceCustomization
|
||||
(mkTypename <> P.MkTypename (<> G.__mutation_frontend))
|
||||
(buildMutationFields Frontend sourceName sourceConfig validTables validFunctions queryTagsConfig)
|
||||
(buildMutationFields Frontend sourceInfo validTables validFunctions)
|
||||
<*> customizeFields
|
||||
sourceCustomization
|
||||
(mkTypename <> P.MkTypename (<> G.__mutation_backend))
|
||||
(buildMutationFields Backend sourceName sourceConfig validTables validFunctions queryTagsConfig)
|
||||
(buildMutationFields Backend sourceInfo validTables validFunctions)
|
||||
where
|
||||
sourceCustomization =
|
||||
if EFNamingConventions `elem` expFeatures
|
||||
@ -429,14 +438,18 @@ unauthenticatedContext allRemotes remoteSchemaPermsCtx = do
|
||||
-- building a restricted schema; namely, we erase all remote relationships
|
||||
-- from the remote schema contexts, meaning that all the information that is
|
||||
-- needed for sources is completely irrelevant and filled with default values.
|
||||
let fakeQueryContext =
|
||||
QueryContext
|
||||
let fakeSchemaOptions =
|
||||
SchemaOptions
|
||||
LeaveNumbersAlone -- stringifyNum doesn't apply to remotes
|
||||
True -- booleanCollapse doesn't apply to remotes
|
||||
QueryHasura
|
||||
FunctionPermissionsInferred -- function permissions don't apply to remotes
|
||||
remoteSchemaPermsCtx
|
||||
False
|
||||
fakeSchemaContext =
|
||||
SchemaContext
|
||||
mempty
|
||||
ignoreRemoteRelationship
|
||||
-- chosen arbitrarily to be as improbable as possible
|
||||
fakeRole = mkRoleNameSafe [NT.nonEmptyTextQQ|MyNameIsOzymandiasKingOfKingsLookOnMyWorksYeMightyAndDespair|]
|
||||
-- we delete all references to remote joins
|
||||
@ -444,7 +457,7 @@ unauthenticatedContext allRemotes remoteSchemaPermsCtx = do
|
||||
allRemotes <&> first \context ->
|
||||
context {_rscRemoteRelationships = mempty}
|
||||
|
||||
runMonadSchema fakeRole fakeQueryContext mempty mempty do
|
||||
runMonadSchema fakeSchemaOptions fakeSchemaContext fakeRole do
|
||||
(queryFields, mutationFields, subscriptionFields, remoteErrors) <- case remoteSchemaPermsCtx of
|
||||
RemoteSchemaPermsEnabled ->
|
||||
-- Permissions are enabled, unauthenticated users have access to nothing.
|
||||
@ -548,94 +561,95 @@ buildRemoteSchemaParser remoteSchemaPermsCtx roleName context = do
|
||||
buildQueryFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceConfig b ->
|
||||
SourceInfo b ->
|
||||
TableCache b ->
|
||||
FunctionCache b ->
|
||||
Maybe QueryTagsConfig ->
|
||||
m [P.FieldParser n (QueryRootField UnpreparedValue)]
|
||||
buildQueryFields sourceName sourceConfig tables (takeExposedAs FEAQuery -> functions) queryTagsConfig = do
|
||||
buildQueryFields sourceInfo tables (takeExposedAs FEAQuery -> functions) = do
|
||||
roleName <- asks getter
|
||||
functionPermsCtx <- asks $ qcFunctionPermsContext . getter
|
||||
functionPermsCtx <- retrieve soFunctionPermsContext
|
||||
tableSelectExpParsers <- for (Map.toList tables) \(tableName, tableInfo) -> do
|
||||
tableIdentifierName <- getTableIdentifierName @b tableInfo
|
||||
mkRF $ buildTableQueryFields sourceName tableName tableInfo tableIdentifierName
|
||||
mkRF $ buildTableQueryFields sourceInfo tableName tableInfo tableIdentifierName
|
||||
functionSelectExpParsers <- for (Map.toList functions) \(functionName, functionInfo) -> runMaybeT $ do
|
||||
guard $
|
||||
roleName == adminRoleName
|
||||
|| roleName `Map.member` _fiPermissions functionInfo
|
||||
|| functionPermsCtx == FunctionPermissionsInferred
|
||||
let targetTableName = _fiReturnType functionInfo
|
||||
lift $ mkRF $ buildFunctionQueryFields sourceName functionName functionInfo targetTableName
|
||||
lift $ mkRF $ buildFunctionQueryFields sourceInfo functionName functionInfo targetTableName
|
||||
pure $ concat $ tableSelectExpParsers <> catMaybes functionSelectExpParsers
|
||||
where
|
||||
mkRF = mkRootField sourceName sourceConfig queryTagsConfig QDBR
|
||||
sourceName = _siName sourceInfo
|
||||
sourceConfig = _siConfiguration sourceInfo
|
||||
queryTagsConfig = _siQueryTagsConfig sourceInfo
|
||||
|
||||
buildTableStreamSubscriptionFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceConfig b ->
|
||||
SourceInfo b ->
|
||||
TableCache b ->
|
||||
Maybe QueryTagsConfig ->
|
||||
m [P.FieldParser n (QueryRootField UnpreparedValue)]
|
||||
buildTableStreamSubscriptionFields sourceName sourceConfig tables queryTagsConfig = do
|
||||
buildTableStreamSubscriptionFields sourceInfo tables = do
|
||||
tableSelectExpParsers <- for (Map.toList tables) \(tableName, tableInfo) -> do
|
||||
tableGQLName <- getTableIdentifierName @b tableInfo
|
||||
mkRF $
|
||||
buildTableStreamingSubscriptionFields
|
||||
sourceName
|
||||
sourceInfo
|
||||
tableName
|
||||
tableInfo
|
||||
tableGQLName
|
||||
pure $ concat tableSelectExpParsers
|
||||
where
|
||||
mkRF = mkRootField sourceName sourceConfig queryTagsConfig QDBR
|
||||
sourceName = _siName sourceInfo
|
||||
sourceConfig = _siConfiguration sourceInfo
|
||||
queryTagsConfig = _siQueryTagsConfig sourceInfo
|
||||
|
||||
buildRelayQueryFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceConfig b ->
|
||||
SourceInfo b ->
|
||||
TableCache b ->
|
||||
FunctionCache b ->
|
||||
Maybe QueryTagsConfig ->
|
||||
m [P.FieldParser n (QueryRootField UnpreparedValue)]
|
||||
buildRelayQueryFields sourceName sourceConfig tables (takeExposedAs FEAQuery -> functions) queryTagsConfig = do
|
||||
buildRelayQueryFields sourceInfo tables (takeExposedAs FEAQuery -> functions) = do
|
||||
tableConnectionFields <- for (Map.toList tables) \(tableName, tableInfo) -> runMaybeT do
|
||||
tableIdentifierName <- getTableIdentifierName @b tableInfo
|
||||
pkeyColumns <- hoistMaybe $ tableInfo ^? tiCoreInfo . tciPrimaryKey . _Just . pkColumns
|
||||
lift $ mkRF $ buildTableRelayQueryFields sourceName tableName tableInfo tableIdentifierName pkeyColumns
|
||||
lift $ mkRF $ buildTableRelayQueryFields sourceInfo tableName tableInfo tableIdentifierName pkeyColumns
|
||||
functionConnectionFields <- for (Map.toList functions) $ \(functionName, functionInfo) -> runMaybeT do
|
||||
let returnTableName = _fiReturnType functionInfo
|
||||
-- FIXME: only extract the TableInfo once to avoid redundant cache lookups
|
||||
returnTableInfo <- lift $ askTableInfo sourceName returnTableName
|
||||
returnTableInfo <- lift $ askTableInfo sourceInfo returnTableName
|
||||
pkeyColumns <- MaybeT $ (^? tiCoreInfo . tciPrimaryKey . _Just . pkColumns) <$> pure returnTableInfo
|
||||
lift $ mkRF $ buildFunctionRelayQueryFields sourceName functionName functionInfo returnTableName pkeyColumns
|
||||
lift $ mkRF $ buildFunctionRelayQueryFields sourceInfo functionName functionInfo returnTableName pkeyColumns
|
||||
pure $ concat $ catMaybes $ tableConnectionFields <> functionConnectionFields
|
||||
where
|
||||
mkRF = mkRootField sourceName sourceConfig queryTagsConfig QDBR
|
||||
sourceName = _siName sourceInfo
|
||||
sourceConfig = _siConfiguration sourceInfo
|
||||
queryTagsConfig = _siQueryTagsConfig sourceInfo
|
||||
|
||||
buildMutationFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
Scenario ->
|
||||
SourceName ->
|
||||
SourceConfig b ->
|
||||
SourceInfo b ->
|
||||
TableCache b ->
|
||||
FunctionCache b ->
|
||||
Maybe QueryTagsConfig ->
|
||||
m [P.FieldParser n (MutationRootField UnpreparedValue)]
|
||||
buildMutationFields scenario sourceName sourceConfig tables (takeExposedAs FEAMutation -> functions) queryTagsConfig = do
|
||||
buildMutationFields scenario sourceInfo tables (takeExposedAs FEAMutation -> functions) = do
|
||||
roleName <- asks getter
|
||||
tableMutations <- for (Map.toList tables) \(tableName, tableInfo) -> do
|
||||
tableIdentifierName <- getTableIdentifierName @b tableInfo
|
||||
inserts <-
|
||||
mkRF (MDBR . MDBInsert) $ buildTableInsertMutationFields scenario sourceName tableName tableInfo tableIdentifierName
|
||||
mkRF (MDBR . MDBInsert) $ buildTableInsertMutationFields scenario sourceInfo tableName tableInfo tableIdentifierName
|
||||
updates <-
|
||||
mkRF (MDBR . MDBUpdate) $ buildTableUpdateMutationFields @b sourceName tableName tableInfo tableIdentifierName
|
||||
mkRF (MDBR . MDBUpdate) $ buildTableUpdateMutationFields sourceInfo tableName tableInfo tableIdentifierName
|
||||
deletes <-
|
||||
mkRF (MDBR . MDBDelete) $ buildTableDeleteMutationFields sourceName tableName tableInfo tableIdentifierName
|
||||
mkRF (MDBR . MDBDelete) $ buildTableDeleteMutationFields sourceInfo tableName tableInfo tableIdentifierName
|
||||
pure $ concat [inserts, updates, deletes]
|
||||
functionMutations <- for (Map.toList functions) \(functionName, functionInfo) -> runMaybeT $ do
|
||||
let targetTableName = _fiReturnType functionInfo
|
||||
@ -645,11 +659,14 @@ buildMutationFields scenario sourceName sourceConfig tables (takeExposedAs FEAMu
|
||||
-- when function permissions are inferred, we don't expose the
|
||||
-- mutation functions for non-admin roles. See Note [Function Permissions]
|
||||
roleName == adminRoleName || roleName `Map.member` (_fiPermissions functionInfo)
|
||||
lift $ mkRF MDBR $ buildFunctionMutationFields sourceName functionName functionInfo targetTableName
|
||||
lift $ mkRF MDBR $ buildFunctionMutationFields sourceInfo functionName functionInfo targetTableName
|
||||
pure $ concat $ tableMutations <> catMaybes functionMutations
|
||||
where
|
||||
mkRF :: forall a db remote action raw. (a -> db b) -> m [FieldParser n a] -> m [FieldParser n (RootField db remote action raw)]
|
||||
mkRF = mkRootField sourceName sourceConfig queryTagsConfig
|
||||
sourceName = _siName sourceInfo
|
||||
sourceConfig = _siConfiguration sourceInfo
|
||||
queryTagsConfig = _siQueryTagsConfig sourceInfo
|
||||
|
||||
----------------------------------------------------------------
|
||||
-- Building root parser from fields
|
||||
@ -821,13 +838,12 @@ type ConcreteSchemaT m a =
|
||||
P.SchemaT
|
||||
(P.ParseT Identity)
|
||||
( ReaderT
|
||||
( RoleName,
|
||||
SourceCache,
|
||||
QueryContext,
|
||||
P.MkTypename,
|
||||
( SchemaOptions,
|
||||
SchemaContext,
|
||||
RoleName,
|
||||
MkTypename,
|
||||
MkRootFieldName,
|
||||
CustomizeRemoteFieldName,
|
||||
RemoteSchemaMap,
|
||||
NamingCase
|
||||
)
|
||||
m
|
||||
@ -837,14 +853,14 @@ type ConcreteSchemaT m a =
|
||||
runMonadSchema ::
|
||||
forall m a.
|
||||
Monad m =>
|
||||
SchemaOptions ->
|
||||
SchemaContext ->
|
||||
RoleName ->
|
||||
QueryContext ->
|
||||
SourceCache ->
|
||||
RemoteSchemaMap ->
|
||||
ConcreteSchemaT m a ->
|
||||
m a
|
||||
runMonadSchema roleName queryContext sources remotes m =
|
||||
P.runSchemaT m `runReaderT` (roleName, sources, queryContext, mempty, mempty, mempty, remotes, HasuraCase)
|
||||
runMonadSchema options context roleName m =
|
||||
flip runReaderT (options, context, roleName, mempty, mempty, mempty, HasuraCase) $
|
||||
P.runSchemaT m
|
||||
|
||||
buildBackendSource ::
|
||||
(forall b. BackendSchema b => SourceInfo b -> r) ->
|
||||
|
@ -29,7 +29,6 @@ import Hasura.GraphQL.Parser.Constants qualified as G
|
||||
import Hasura.GraphQL.Parser.Internal.Parser qualified as P
|
||||
import Hasura.GraphQL.Schema.Backend
|
||||
import Hasura.GraphQL.Schema.Common
|
||||
import Hasura.GraphQL.Schema.Select
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.Action qualified as IR
|
||||
import Hasura.RQL.IR.Root qualified as IR
|
||||
@ -185,7 +184,7 @@ actionAsyncQuery objectTypes actionInfo = runMaybeT do
|
||||
let selectionSet = customScalarParser ast
|
||||
pure $ P.selection fieldName description actionIdInputField selectionSet <&> (,[])
|
||||
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
pure $
|
||||
parserOutput
|
||||
<&> \(idArg, fields) ->
|
||||
@ -261,7 +260,8 @@ actionOutputFields outputType annotatedObject objectTypes = do
|
||||
TypeRelationship (TableInfo ('Postgres 'Vanilla)) (ColumnInfo ('Postgres 'Vanilla)) ->
|
||||
m (Maybe [FieldParser n (AnnotatedActionField)])
|
||||
relationshipFieldParser (TypeRelationship relationshipName relType sourceName tableInfo fieldMapping) = runMaybeT do
|
||||
sourceInfo <- MaybeT $ asks $ (unsafeSourceInfo @('Postgres 'Vanilla) <=< Map.lookup sourceName) . getter
|
||||
sourceCache <- lift $ retrieve scSourceCache
|
||||
sourceInfo <- hoistMaybe $ unsafeSourceInfo @('Postgres 'Vanilla) =<< Map.lookup sourceName sourceCache
|
||||
relName <- hoistMaybe $ RelName <$> mkNonEmptyText (toTxt relationshipName)
|
||||
|
||||
-- `lhsJoinFields` is a map of `x: y`
|
||||
@ -295,6 +295,7 @@ actionOutputFields outputType annotatedObject objectTypes = do
|
||||
_rsfiMapping = joinMapping
|
||||
}
|
||||
}
|
||||
RemoteRelationshipParserBuilder remoteRelationshipField <- retrieve scRemoteRelationshipParserBuilder
|
||||
remoteRelationshipFieldParsers <- MaybeT $ remoteRelationshipField remoteFieldInfo
|
||||
pure $ remoteRelationshipFieldParsers <&> fmap (IR.ACFRemote . IR.ActionRemoteRelationshipSelect lhsJoinFields)
|
||||
|
||||
|
@ -51,6 +51,7 @@ import Hasura.RQL.Types.ComputedField
|
||||
import Hasura.RQL.Types.Function
|
||||
import Hasura.RQL.Types.Relationships.Local
|
||||
import Hasura.RQL.Types.SchemaCache
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization (NamingCase)
|
||||
import Hasura.RQL.Types.Table
|
||||
import Hasura.SQL.Backend
|
||||
@ -98,21 +99,21 @@ class
|
||||
-- top level parsers
|
||||
buildTableQueryFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
GQLNameIdentifier ->
|
||||
m [FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))]
|
||||
buildTableStreamingSubscriptionFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
GQLNameIdentifier ->
|
||||
m [FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))]
|
||||
buildTableRelayQueryFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
GQLNameIdentifier ->
|
||||
@ -121,7 +122,7 @@ class
|
||||
buildTableInsertMutationFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
Scenario ->
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
GQLNameIdentifier ->
|
||||
@ -136,7 +137,7 @@ class
|
||||
buildTableUpdateMutationFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
-- | The source that the table lives in
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | The name of the table being acted on
|
||||
TableName b ->
|
||||
-- | table info
|
||||
@ -147,7 +148,7 @@ class
|
||||
|
||||
buildTableDeleteMutationFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
GQLNameIdentifier ->
|
||||
@ -155,7 +156,7 @@ class
|
||||
|
||||
buildFunctionQueryFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
FunctionName b ->
|
||||
FunctionInfo b ->
|
||||
TableName b ->
|
||||
@ -163,7 +164,7 @@ class
|
||||
|
||||
buildFunctionRelayQueryFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
FunctionName b ->
|
||||
FunctionInfo b ->
|
||||
TableName b ->
|
||||
@ -172,7 +173,7 @@ class
|
||||
|
||||
buildFunctionMutationFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
FunctionName b ->
|
||||
FunctionInfo b ->
|
||||
TableName b ->
|
||||
@ -181,7 +182,7 @@ class
|
||||
-- table components
|
||||
tableArguments ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (InputFieldsParser n (IR.SelectArgsG b (UnpreparedValue b)))
|
||||
|
||||
@ -189,7 +190,7 @@ class
|
||||
-- relationships altogether.
|
||||
mkRelationshipParser ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
RelInfo b ->
|
||||
m (Maybe (InputFieldsParser n (Maybe (IR.AnnotatedInsertField b (UnpreparedValue b)))))
|
||||
mkRelationshipParser _ _ = pure Nothing
|
||||
@ -232,7 +233,7 @@ class
|
||||
-- | Computed field parser
|
||||
computedField ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
ComputedFieldInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
|
@ -28,11 +28,11 @@ import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.RQL.Types.Column
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.ComputedField
|
||||
import Hasura.RQL.Types.Function
|
||||
import Hasura.RQL.Types.Relationships.Local
|
||||
import Hasura.RQL.Types.SchemaCache hiding (askTableInfo)
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization (NamingCase, applyFieldNameCaseIdentifier)
|
||||
import Hasura.RQL.Types.Table
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
@ -48,10 +48,10 @@ import Language.GraphQL.Draft.Syntax qualified as G
|
||||
boolExp ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Parser 'Input n (AnnBoolExp b (UnpreparedValue b)))
|
||||
boolExp sourceName tableInfo = memoizeOn 'boolExp (sourceName, tableName) $ do
|
||||
boolExp sourceInfo tableInfo = memoizeOn 'boolExp (_siName sourceInfo, tableName) $ do
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
name <- P.mkTypename $ tableGQLName <> G.__bool_exp
|
||||
let description =
|
||||
@ -59,9 +59,9 @@ boolExp sourceName tableInfo = memoizeOn 'boolExp (sourceName, tableName) $ do
|
||||
"Boolean expression to filter rows from the table " <> tableName
|
||||
<<> ". All fields are combined with a logical 'AND'."
|
||||
|
||||
fieldInfos <- tableSelectFields sourceName tableInfo
|
||||
fieldInfos <- tableSelectFields sourceInfo tableInfo
|
||||
tableFieldParsers <- catMaybes <$> traverse mkField fieldInfos
|
||||
recur <- boolExp sourceName tableInfo
|
||||
recur <- boolExp sourceInfo tableInfo
|
||||
-- Bafflingly, ApplicativeDo doesn’t work if we inline this definition (I
|
||||
-- think the TH splices throw it off), so we have to define it separately.
|
||||
let specialFieldParsers =
|
||||
@ -89,12 +89,12 @@ boolExp sourceName tableInfo = memoizeOn 'boolExp (sourceName, tableName) $ do
|
||||
lift $ fmap (AVColumn columnInfo) <$> comparisonExps @b (ciType columnInfo)
|
||||
-- field_name: field_type_bool_exp
|
||||
FIRelationship relationshipInfo -> do
|
||||
remoteTableInfo <- askTableInfo sourceName $ riRTable relationshipInfo
|
||||
remoteTableInfo <- askTableInfo sourceInfo $ riRTable relationshipInfo
|
||||
remotePermissions <- lift $ tableSelectPermissions remoteTableInfo
|
||||
let remoteTableFilter =
|
||||
fmap partialSQLExpToUnpreparedValue
|
||||
<$> maybe annBoolExpTrue spiFilter remotePermissions
|
||||
remoteBoolExp <- lift $ boolExp sourceName remoteTableInfo
|
||||
remoteBoolExp <- lift $ boolExp sourceInfo remoteTableInfo
|
||||
pure $ fmap (AVRelationship relationshipInfo . andAnnBoolExps remoteTableFilter) remoteBoolExp
|
||||
FIComputedField ComputedFieldInfo {..} -> do
|
||||
let ComputedFieldFunction {..} = _cfiFunction
|
||||
@ -109,8 +109,8 @@ boolExp sourceName tableInfo = memoizeOn 'boolExp (sourceName, tableName) $ do
|
||||
<$> case computedFieldReturnType @b _cfiReturnType of
|
||||
ReturnsScalar scalarType -> lift $ fmap CFBEScalar <$> comparisonExps @b (ColumnScalar scalarType)
|
||||
ReturnsTable table -> do
|
||||
info <- askTableInfo @b sourceName table
|
||||
lift $ fmap (CFBETable table) <$> boolExp sourceName info
|
||||
info <- askTableInfo sourceInfo table
|
||||
lift $ fmap (CFBETable table) <$> boolExp sourceInfo info
|
||||
ReturnsOthers -> hoistMaybe Nothing
|
||||
_ -> hoistMaybe Nothing
|
||||
|
||||
|
@ -70,6 +70,7 @@ import Hasura.RQL.Types.Backend
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.Function
|
||||
import Hasura.RQL.Types.SchemaCache
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization
|
||||
import Hasura.RQL.Types.Table
|
||||
import Hasura.SQL.Backend
|
||||
@ -95,12 +96,12 @@ setFieldNameCase tCase tInfo crf getFieldName tableName =
|
||||
buildTableQueryFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
C.GQLNameIdentifier ->
|
||||
(m [FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))])
|
||||
buildTableQueryFields sourceName tableName tableInfo gqlName = do
|
||||
buildTableQueryFields sourceInfo tableName tableInfo gqlName = do
|
||||
tCase <- asks getter
|
||||
-- select table
|
||||
selectName <- mkRootFieldName $ setFieldNameCase tCase tableInfo _tcrfSelect mkSelectField gqlName
|
||||
@ -110,9 +111,9 @@ buildTableQueryFields sourceName tableName tableInfo gqlName = do
|
||||
selectAggName <- mkRootFieldName $ setFieldNameCase tCase tableInfo _tcrfSelectAggregate mkSelectAggregateField gqlName
|
||||
catMaybes
|
||||
<$> sequenceA
|
||||
[ optionalFieldParser QDBMultipleRows $ selectTable sourceName tableInfo selectName selectDesc,
|
||||
optionalFieldParser QDBSingleRow $ selectTableByPk sourceName tableInfo selectPKName selectPKDesc,
|
||||
optionalFieldParser QDBAggregation $ selectTableAggregate sourceName tableInfo selectAggName selectAggDesc
|
||||
[ optionalFieldParser QDBMultipleRows $ selectTable sourceInfo tableInfo selectName selectDesc,
|
||||
optionalFieldParser QDBSingleRow $ selectTableByPk sourceInfo tableInfo selectPKName selectPKDesc,
|
||||
optionalFieldParser QDBAggregation $ selectTableAggregate sourceInfo tableInfo selectAggName selectAggDesc
|
||||
]
|
||||
where
|
||||
selectDesc = buildFieldDescription defaultSelectDesc $ _crfComment _tcrfSelect
|
||||
@ -126,42 +127,42 @@ buildTableQueryFields sourceName tableName tableInfo gqlName = do
|
||||
buildTableStreamingSubscriptionFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
C.GQLNameIdentifier ->
|
||||
m [FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))]
|
||||
buildTableStreamingSubscriptionFields sourceName tableName tableInfo gqlName = do
|
||||
buildTableStreamingSubscriptionFields sourceInfo tableName tableInfo gqlName = do
|
||||
tCase <- asks getter
|
||||
let customRootFields = _tcCustomRootFields $ _tciCustomConfig $ _tiCoreInfo tableInfo
|
||||
selectDesc = Just $ G.Description $ "fetch data from the table in a streaming manner : " <>> tableName
|
||||
selectStreamName <- mkRootFieldName $ setFieldNameCase tCase tableInfo (_tcrfSelect customRootFields) mkSelectStreamField gqlName
|
||||
catMaybes
|
||||
<$> sequenceA
|
||||
[ optionalFieldParser QDBStreamMultipleRows $ selectStreamTable sourceName tableInfo selectStreamName selectDesc
|
||||
[ optionalFieldParser QDBStreamMultipleRows $ selectStreamTable sourceInfo tableInfo selectStreamName selectDesc
|
||||
]
|
||||
|
||||
buildTableInsertMutationFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
(SourceName -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
(SourceInfo b -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
Scenario ->
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
C.GQLNameIdentifier ->
|
||||
m [FieldParser n (AnnotatedInsert b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))]
|
||||
buildTableInsertMutationFields backendInsertAction scenario sourceName tableName tableInfo gqlName = do
|
||||
buildTableInsertMutationFields backendInsertAction scenario sourceInfo tableName tableInfo gqlName = do
|
||||
tCase <- asks getter
|
||||
-- insert in table
|
||||
insertName <- mkRootFieldName $ setFieldNameCase tCase tableInfo _tcrfInsert mkInsertField gqlName
|
||||
-- insert one in table
|
||||
insertOneName <- mkRootFieldName $ setFieldNameCase tCase tableInfo _tcrfInsertOne mkInsertOneField gqlName
|
||||
insert <- insertIntoTable backendInsertAction scenario sourceName tableInfo insertName insertDesc
|
||||
insert <- insertIntoTable backendInsertAction scenario sourceInfo tableInfo insertName insertDesc
|
||||
-- Select permissions are required for insertOne: the selection set is the
|
||||
-- same as a select on that table, and it therefore can't be populated if the
|
||||
-- user doesn't have select permissions.
|
||||
insertOne <- insertOneIntoTable backendInsertAction scenario sourceName tableInfo insertOneName insertOneDesc
|
||||
insertOne <- insertOneIntoTable backendInsertAction scenario sourceInfo tableInfo insertOneName insertOneDesc
|
||||
pure $ catMaybes [insert, insertOne]
|
||||
where
|
||||
insertDesc = buildFieldDescription defaultInsertDesc $ _crfComment _tcrfInsert
|
||||
@ -200,7 +201,7 @@ buildTableUpdateMutationFields ::
|
||||
(InputFieldsParser n (BackendUpdate b (UnpreparedValue b)))
|
||||
) ->
|
||||
-- | The source that the table lives in
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | The name of the table being acted on
|
||||
TableName b ->
|
||||
-- | table info
|
||||
@ -208,18 +209,18 @@ buildTableUpdateMutationFields ::
|
||||
-- | field display name
|
||||
C.GQLNameIdentifier ->
|
||||
m [FieldParser n (AnnotatedUpdateG b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))]
|
||||
buildTableUpdateMutationFields mkBackendUpdate sourceName tableName tableInfo gqlName = do
|
||||
buildTableUpdateMutationFields mkBackendUpdate sourceInfo tableName tableInfo gqlName = do
|
||||
tCase <- asks getter
|
||||
backendUpdate <- mkBackendUpdate tableInfo
|
||||
-- update table
|
||||
updateName <- mkRootFieldName $ setFieldNameCase tCase tableInfo _tcrfUpdate mkUpdateField gqlName
|
||||
-- update table by pk
|
||||
updatePKName <- mkRootFieldName $ setFieldNameCase tCase tableInfo _tcrfUpdateByPk mkUpdateByPkField gqlName
|
||||
update <- updateTable backendUpdate sourceName tableInfo updateName updateDesc
|
||||
update <- updateTable backendUpdate sourceInfo tableInfo updateName updateDesc
|
||||
-- Primary keys can only be tested in the `where` clause if a primary key
|
||||
-- exists on the table and if the user has select permissions on all columns
|
||||
-- that make up the key.
|
||||
updateByPk <- updateTableByPk backendUpdate sourceName tableInfo updatePKName updatePKDesc
|
||||
updateByPk <- updateTableByPk backendUpdate sourceInfo tableInfo updatePKName updatePKDesc
|
||||
pure $ catMaybes [update, updateByPk]
|
||||
where
|
||||
updateDesc = buildFieldDescription defaultUpdateDesc $ _crfComment _tcrfUpdate
|
||||
@ -231,22 +232,22 @@ buildTableUpdateMutationFields mkBackendUpdate sourceName tableName tableInfo gq
|
||||
buildTableDeleteMutationFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
C.GQLNameIdentifier ->
|
||||
m [FieldParser n (AnnDelG b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))]
|
||||
buildTableDeleteMutationFields sourceName tableName tableInfo gqlName = do
|
||||
buildTableDeleteMutationFields sourceInfo tableName tableInfo gqlName = do
|
||||
tCase <- asks getter
|
||||
-- delete from table
|
||||
deleteName <- mkRootFieldName $ setFieldNameCase tCase tableInfo _tcrfDelete mkDeleteField gqlName
|
||||
-- delete from table by pk
|
||||
deletePKName <- mkRootFieldName $ setFieldNameCase tCase tableInfo _tcrfDeleteByPk mkDeleteByPkField gqlName
|
||||
delete <- deleteFromTable sourceName tableInfo deleteName deleteDesc
|
||||
delete <- deleteFromTable sourceInfo tableInfo deleteName deleteDesc
|
||||
-- Primary keys can only be tested in the `where` clause if the user has
|
||||
-- select permissions for them, which at the very least requires select
|
||||
-- permissions.
|
||||
deleteByPk <- deleteFromTableByPk sourceName tableInfo deletePKName deletePKDesc
|
||||
deleteByPk <- deleteFromTableByPk sourceInfo tableInfo deletePKName deletePKDesc
|
||||
pure $ catMaybes [delete, deleteByPk]
|
||||
where
|
||||
deleteDesc = buildFieldDescription defaultDeleteDesc $ _crfComment _tcrfDelete
|
||||
@ -258,12 +259,12 @@ buildTableDeleteMutationFields sourceName tableName tableInfo gqlName = do
|
||||
buildFunctionQueryFieldsPG ::
|
||||
forall r m n pgKind.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
FunctionName ('Postgres pgKind) ->
|
||||
FunctionInfo ('Postgres pgKind) ->
|
||||
TableName ('Postgres pgKind) ->
|
||||
m [FieldParser n (QueryDB ('Postgres pgKind) (RemoteRelationshipField UnpreparedValue) (UnpreparedValue ('Postgres pgKind)))]
|
||||
buildFunctionQueryFieldsPG sourceName functionName functionInfo tableName = do
|
||||
buildFunctionQueryFieldsPG sourceInfo functionName functionInfo tableName = do
|
||||
let -- select function
|
||||
funcDesc =
|
||||
Just . G.Description $
|
||||
@ -279,24 +280,24 @@ buildFunctionQueryFieldsPG sourceName functionName functionInfo tableName = do
|
||||
|
||||
catMaybes
|
||||
<$> sequenceA
|
||||
[ optionalFieldParser (queryResultType) $ selectFunction sourceName functionInfo funcDesc,
|
||||
optionalFieldParser (QDBAggregation) $ selectFunctionAggregate sourceName functionInfo funcAggDesc
|
||||
[ optionalFieldParser (queryResultType) $ selectFunction sourceInfo functionInfo funcDesc,
|
||||
optionalFieldParser (QDBAggregation) $ selectFunctionAggregate sourceInfo functionInfo funcAggDesc
|
||||
]
|
||||
|
||||
buildFunctionMutationFieldsPG ::
|
||||
forall r m n pgKind.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
FunctionName ('Postgres pgKind) ->
|
||||
FunctionInfo ('Postgres pgKind) ->
|
||||
TableName ('Postgres pgKind) ->
|
||||
m [FieldParser n (MutationDB ('Postgres pgKind) (RemoteRelationshipField UnpreparedValue) (UnpreparedValue ('Postgres pgKind)))]
|
||||
buildFunctionMutationFieldsPG sourceName functionName functionInfo tableName = do
|
||||
buildFunctionMutationFieldsPG sourceInfo functionName functionInfo tableName = do
|
||||
let funcDesc = Just $ G.Description $ "execute VOLATILE function " <> functionName <<> " which returns " <>> tableName
|
||||
jsonAggSelect = _fiJsonAggSelect functionInfo
|
||||
catMaybes
|
||||
<$> sequenceA
|
||||
[ optionalFieldParser (MDBFunction jsonAggSelect) $ selectFunction sourceName functionInfo funcDesc
|
||||
[ optionalFieldParser (MDBFunction jsonAggSelect) $ selectFunction sourceInfo functionInfo funcDesc
|
||||
-- TODO: do we want aggregate mutation functions?
|
||||
]
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
|
||||
module Hasura.GraphQL.Schema.Common
|
||||
( MonadBuildSchemaBase,
|
||||
( SchemaOptions (..),
|
||||
SchemaContext (..),
|
||||
RemoteRelationshipParserBuilder (..),
|
||||
MonadBuildSchemaBase,
|
||||
retrieve,
|
||||
ignoreRemoteRelationship,
|
||||
AggSelectExp,
|
||||
AnnotatedField,
|
||||
AnnotatedFields,
|
||||
@ -10,7 +15,6 @@ module Hasura.GraphQL.Schema.Common
|
||||
AnnotatedActionField,
|
||||
AnnotatedActionFields,
|
||||
EdgeFields,
|
||||
QueryContext (..),
|
||||
Scenario (..),
|
||||
SelectArgs,
|
||||
SelectStreamArgs,
|
||||
@ -52,38 +56,94 @@ import Hasura.GraphQL.Namespace (NamespacedField)
|
||||
import Hasura.GraphQL.Parser qualified as P
|
||||
import Hasura.GraphQL.Parser.Constants qualified as G
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.Action qualified as IR
|
||||
import Hasura.RQL.IR qualified as IR
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.IR.RemoteSchema qualified as IR
|
||||
import Hasura.RQL.IR.Root qualified as IR
|
||||
import Hasura.RQL.IR.Select qualified as IR
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.RQL.Types.Column
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.Function
|
||||
import Hasura.RQL.Types.Relationships.Remote
|
||||
import Hasura.RQL.Types.RemoteSchema
|
||||
import Hasura.RQL.Types.SchemaCache hiding (askTableInfo)
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization
|
||||
import Hasura.SQL.AnyBackend qualified as AB
|
||||
import Hasura.Session (RoleName)
|
||||
import Language.GraphQL.Draft.Syntax as G
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
|
||||
-- | the set of common constraints required to build the schema
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
-- | Aggregation of options required to build the schema.
|
||||
data SchemaOptions = SchemaOptions
|
||||
{ -- | how numbers should be represented in the ouput; this option does not
|
||||
-- influence the schema, but is bundled in the resulting IR
|
||||
soStringifyNum :: StringifyNumbers,
|
||||
-- | should boolean fields be collapsed to True when null is given?
|
||||
soDangerousBooleanCollapse :: Bool,
|
||||
-- | what kind of schema is being built (Hasura or Relay)
|
||||
soQueryType :: ET.GraphQLQueryType,
|
||||
-- | whether function permissions should be inferred
|
||||
soFunctionPermsContext :: FunctionPermissionsCtx,
|
||||
-- | whether remote schema permissions are enabled
|
||||
soRemoteSchemaPermsCtx :: RemoteSchemaPermsCtx,
|
||||
-- | 'True' when we should attempt to use experimental SQL optimization passes
|
||||
soOptimizePermissionFilters :: Bool
|
||||
}
|
||||
|
||||
-- | Aggregation of contextual information required to build the schema.
|
||||
data SchemaContext = SchemaContext
|
||||
{ -- | the set of all sources (TODO: remove this?)
|
||||
scSourceCache :: SourceCache,
|
||||
-- | how to process remote relationships
|
||||
scRemoteRelationshipParserBuilder :: RemoteRelationshipParserBuilder
|
||||
}
|
||||
|
||||
-- | The set of common constraints required to build the schema.
|
||||
type MonadBuildSchemaBase r m n =
|
||||
( MonadError QErr m,
|
||||
MonadReader r m,
|
||||
P.MonadSchema n m,
|
||||
Has SchemaOptions r,
|
||||
Has SchemaContext r,
|
||||
-- TODO: make all `Has x r` explicit fields of 'SchemaContext'
|
||||
Has RoleName r,
|
||||
Has SourceCache r,
|
||||
Has QueryContext r,
|
||||
Has MkTypename r,
|
||||
Has MkRootFieldName r,
|
||||
Has CustomizeRemoteFieldName r,
|
||||
Has RemoteSchemaMap r,
|
||||
Has NamingCase r
|
||||
)
|
||||
|
||||
-- | How a remote relationship field should be processed when building a
|
||||
-- schema. Injecting this function from the top level avoids having to know how
|
||||
-- to do top-level dispatch from deep within the schema code.
|
||||
--
|
||||
-- Note: the inner function type uses an existential qualifier: it is expected
|
||||
-- that the given function will work for _any_ monad @m@ that has the relevant
|
||||
-- constraints. This prevents us from passing a function that is specfic to the
|
||||
-- monad in which the schema construction will run, but avoids having to
|
||||
-- propagate type annotations to each call site.
|
||||
newtype RemoteRelationshipParserBuilder
|
||||
= RemoteRelationshipParserBuilder
|
||||
( forall lhsJoinField r n m.
|
||||
MonadBuildSchemaBase r m n =>
|
||||
RemoteFieldInfo lhsJoinField ->
|
||||
m (Maybe [P.FieldParser n (IR.RemoteRelationshipField P.UnpreparedValue)])
|
||||
)
|
||||
|
||||
-- | A 'RemoteRelationshipParserBuilder' that ignores the field altogether, that can
|
||||
-- be used in tests or to build a source or remote schema in isolation.
|
||||
ignoreRemoteRelationship :: RemoteRelationshipParserBuilder
|
||||
ignoreRemoteRelationship = RemoteRelationshipParserBuilder $ const $ pure Nothing
|
||||
|
||||
-- TODO: move this to Prelude?
|
||||
retrieve ::
|
||||
(MonadReader r m, Has a r) =>
|
||||
(a -> b) ->
|
||||
m b
|
||||
retrieve f = asks $ f . getter
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
type SelectExp b = IR.AnnSimpleSelectG b (IR.RemoteRelationshipField P.UnpreparedValue) (P.UnpreparedValue b)
|
||||
|
||||
type StreamSelectExp b = IR.AnnSimpleStreamSelectG b (IR.RemoteRelationshipField P.UnpreparedValue) (P.UnpreparedValue b)
|
||||
@ -110,23 +170,14 @@ type AnnotatedActionFields = IR.ActionFieldsG (IR.RemoteRelationshipField P.Unpr
|
||||
|
||||
type AnnotatedActionField = IR.ActionFieldG (IR.RemoteRelationshipField P.UnpreparedValue)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
data RemoteSchemaParser n = RemoteSchemaParser
|
||||
{ piQuery :: [P.FieldParser n (NamespacedField (IR.RemoteSchemaRootField (IR.RemoteRelationshipField P.UnpreparedValue) RemoteSchemaVariable))],
|
||||
piMutation :: Maybe [P.FieldParser n (NamespacedField (IR.RemoteSchemaRootField (IR.RemoteRelationshipField P.UnpreparedValue) RemoteSchemaVariable))],
|
||||
piSubscription :: Maybe [P.FieldParser n (NamespacedField (IR.RemoteSchemaRootField (IR.RemoteRelationshipField P.UnpreparedValue) RemoteSchemaVariable))]
|
||||
}
|
||||
|
||||
data QueryContext = QueryContext
|
||||
{ qcStringifyNum :: StringifyNumbers,
|
||||
-- | should boolean fields be collapsed to True when null is given?
|
||||
qcDangerousBooleanCollapse :: Bool,
|
||||
qcQueryType :: ET.GraphQLQueryType,
|
||||
qcFunctionPermsContext :: FunctionPermissionsCtx,
|
||||
qcRemoteSchemaPermsCtx :: RemoteSchemaPermsCtx,
|
||||
-- | 'True' when we should attempt to use experimental SQL optimization passes
|
||||
qcOptimizePermissionFilters :: Bool
|
||||
}
|
||||
|
||||
getTableRoles :: BackendSourceInfo -> [RoleName]
|
||||
getTableRoles bsi = AB.dispatchAnyBackend @Backend bsi go
|
||||
where
|
||||
@ -137,19 +188,14 @@ getTableRoles bsi = AB.dispatchAnyBackend @Backend bsi go
|
||||
-- supposed to ensure all dependencies are resolved.
|
||||
-- TODO: deduplicate this with `CacheRM`.
|
||||
askTableInfo ::
|
||||
forall b r m.
|
||||
(Backend b, MonadError QErr m, MonadReader r m, Has SourceCache r) =>
|
||||
SourceName ->
|
||||
forall b m.
|
||||
(Backend b, MonadError QErr m) =>
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
m (TableInfo b)
|
||||
askTableInfo sourceName tableName = do
|
||||
tableInfo <- asks $ getTableInfo . getter
|
||||
-- This should never fail, since the schema cache construction process is
|
||||
-- supposed to ensure that all dependencies are resolved.
|
||||
tableInfo `onNothing` throw500 ("askTableInfo: no info for table " <> dquote tableName <> " in source " <> dquote sourceName)
|
||||
where
|
||||
getTableInfo :: SourceCache -> Maybe (TableInfo b)
|
||||
getTableInfo = Map.lookup tableName <=< unsafeSourceTables <=< Map.lookup sourceName
|
||||
askTableInfo SourceInfo {..} tableName =
|
||||
Map.lookup tableName _siTables
|
||||
`onNothing` throw500 ("askTableInfo: no info for table " <> dquote tableName <> " in source " <> dquote _siName)
|
||||
|
||||
-- | Whether the request is sent with `x-hasura-use-backend-only-permissions` set to `true`.
|
||||
data Scenario = Backend | Frontend deriving (Enum, Show, Eq)
|
||||
@ -197,7 +243,7 @@ numericAggOperators =
|
||||
]
|
||||
|
||||
comparisonAggOperators :: [G.Name]
|
||||
comparisonAggOperators = [$$(litName "max"), $$(litName "min")]
|
||||
comparisonAggOperators = [$$(G.litName "max"), $$(G.litName "min")]
|
||||
|
||||
data NodeIdVersion
|
||||
= NIVersion1
|
||||
|
@ -42,6 +42,7 @@ import Hasura.RQL.Types.Column
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.Relationships.Local
|
||||
import Hasura.RQL.Types.SchemaCache hiding (askTableInfo)
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.Table
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
|
||||
@ -56,9 +57,9 @@ import Language.GraphQL.Draft.Syntax qualified as G
|
||||
insertIntoTable ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
(SourceName -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
(SourceInfo b -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
Scenario ->
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | qualified name of the table
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -66,7 +67,7 @@ insertIntoTable ::
|
||||
-- | field description, if any
|
||||
Maybe G.Description ->
|
||||
m (Maybe (FieldParser n (IR.AnnotatedInsert b (IR.RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))))
|
||||
insertIntoTable backendInsertAction scenario sourceName tableInfo fieldName description = runMaybeT $ do
|
||||
insertIntoTable backendInsertAction scenario sourceInfo tableInfo fieldName description = runMaybeT $ do
|
||||
let viewInfo = _tciViewInfo $ _tiCoreInfo tableInfo
|
||||
guard $ isMutable viIsInsertable viewInfo
|
||||
insertPerms <- MaybeT $ _permIns <$> tablePermissions tableInfo
|
||||
@ -75,10 +76,10 @@ insertIntoTable backendInsertAction scenario sourceName tableInfo fieldName desc
|
||||
lift do
|
||||
updatePerms <- _permUpd <$> tablePermissions tableInfo
|
||||
-- objects [{ ... }]
|
||||
objectParser <- tableFieldsInput sourceName tableInfo
|
||||
backendInsertParser <- backendInsertAction sourceName tableInfo
|
||||
objectParser <- tableFieldsInput sourceInfo tableInfo
|
||||
backendInsertParser <- backendInsertAction sourceInfo tableInfo
|
||||
-- returning clause, affected rows, etc.
|
||||
selectionParser <- mutationSelectionSet sourceName tableInfo
|
||||
selectionParser <- mutationSelectionSet sourceInfo tableInfo
|
||||
let argsParser = do
|
||||
backendInsert <- backendInsertParser
|
||||
objects <- mkObjectsArg objectParser
|
||||
@ -101,10 +102,10 @@ insertIntoTable backendInsertAction scenario sourceName tableInfo fieldName desc
|
||||
insertOneIntoTable ::
|
||||
forall b r m n.
|
||||
(MonadBuildSchema b r m n) =>
|
||||
(SourceName -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
(SourceInfo b -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
Scenario ->
|
||||
-- | source of the table
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | table info
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -112,17 +113,17 @@ insertOneIntoTable ::
|
||||
-- | field description, if any
|
||||
Maybe G.Description ->
|
||||
m (Maybe (FieldParser n (IR.AnnotatedInsert b (IR.RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))))
|
||||
insertOneIntoTable backendInsertAction scenario sourceName tableInfo fieldName description = runMaybeT do
|
||||
insertOneIntoTable backendInsertAction scenario sourceInfo tableInfo fieldName description = runMaybeT do
|
||||
let viewInfo = _tciViewInfo $ _tiCoreInfo tableInfo
|
||||
guard $ isMutable viIsInsertable viewInfo
|
||||
insertPerms <- MaybeT $ _permIns <$> tablePermissions tableInfo
|
||||
-- If we're in a frontend scenario, we should not include backend_only inserts
|
||||
guard $ not $ scenario == Frontend && ipiBackendOnly insertPerms
|
||||
selectionParser <- MaybeT $ tableSelectionSet sourceName tableInfo
|
||||
selectionParser <- MaybeT $ tableSelectionSet sourceInfo tableInfo
|
||||
lift do
|
||||
updatePerms <- _permUpd <$> tablePermissions tableInfo
|
||||
objectParser <- tableFieldsInput sourceName tableInfo
|
||||
backendInsertParser <- backendInsertAction sourceName tableInfo
|
||||
objectParser <- tableFieldsInput sourceInfo tableInfo
|
||||
backendInsertParser <- backendInsertAction sourceInfo tableInfo
|
||||
let argsParser = do
|
||||
backendInsert <- backendInsertParser
|
||||
object <- mkObjectArg objectParser
|
||||
@ -156,12 +157,12 @@ insertOneIntoTable backendInsertAction scenario sourceName tableInfo fieldName d
|
||||
tableFieldsInput ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | qualified name of the table
|
||||
TableInfo b ->
|
||||
m (Parser 'Input n (IR.AnnotatedInsertRow b (UnpreparedValue b)))
|
||||
tableFieldsInput sourceName tableInfo =
|
||||
memoizeOn 'tableFieldsInput (sourceName, tableName) do
|
||||
tableFieldsInput sourceInfo tableInfo =
|
||||
memoizeOn 'tableFieldsInput (_siName sourceInfo, tableName) do
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
objectFields <- traverse mkFieldParser (Map.elems allFields)
|
||||
objectName <- P.mkTypename $ tableGQLName <> G.__insert_input
|
||||
@ -191,7 +192,7 @@ tableFieldsInput sourceName tableInfo =
|
||||
if (_cmIsInsertable $ ciMutability columnInfo)
|
||||
then mkColumnParser columnInfo
|
||||
else pure Nothing
|
||||
FIRelationship relInfo -> mkRelationshipParser sourceName relInfo
|
||||
FIRelationship relInfo -> mkRelationshipParser sourceInfo relInfo
|
||||
|
||||
mkColumnParser ::
|
||||
ColumnInfo b ->
|
||||
@ -210,25 +211,25 @@ tableFieldsInput sourceName tableInfo =
|
||||
mkDefaultRelationshipParser ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
(SourceName -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
(SourceInfo b -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
XNestedInserts b ->
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
RelInfo b ->
|
||||
m (Maybe (InputFieldsParser n (Maybe (IR.AnnotatedInsertField b (UnpreparedValue b)))))
|
||||
mkDefaultRelationshipParser backendInsertAction xNestedInserts sourceName relationshipInfo = runMaybeT do
|
||||
mkDefaultRelationshipParser backendInsertAction xNestedInserts sourceInfo relationshipInfo = runMaybeT do
|
||||
let otherTableName = riRTable relationshipInfo
|
||||
relName = riName relationshipInfo
|
||||
otherTableInfo <- askTableInfo sourceName otherTableName
|
||||
otherTableInfo <- askTableInfo sourceInfo otherTableName
|
||||
relFieldName <- lift $ textToName $ relNameToTxt relName
|
||||
case riType relationshipInfo of
|
||||
ObjRel -> do
|
||||
parser <- MaybeT $ objectRelationshipInput backendInsertAction sourceName otherTableInfo
|
||||
parser <- MaybeT $ objectRelationshipInput backendInsertAction sourceInfo otherTableInfo
|
||||
pure $
|
||||
P.fieldOptional relFieldName Nothing (P.nullable parser) <&> \objRelIns -> do
|
||||
rel <- join objRelIns
|
||||
Just $ IR.AIObjectRelationship xNestedInserts $ IR.RelationInsert rel relationshipInfo
|
||||
ArrRel -> do
|
||||
parser <- MaybeT $ arrayRelationshipInput backendInsertAction sourceName otherTableInfo
|
||||
parser <- MaybeT $ arrayRelationshipInput backendInsertAction sourceInfo otherTableInfo
|
||||
pure $
|
||||
P.fieldOptional relFieldName Nothing (P.nullable parser) <&> \arrRelIns -> do
|
||||
rel <- join arrRelIns
|
||||
@ -245,18 +246,18 @@ mkDefaultRelationshipParser backendInsertAction xNestedInserts sourceName relati
|
||||
objectRelationshipInput ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
(SourceName -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
SourceName ->
|
||||
(SourceInfo b -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Maybe (Parser 'Input n (IR.SingleObjectInsert b (UnpreparedValue b))))
|
||||
objectRelationshipInput backendInsertAction sourceName tableInfo = runMaybeT $ do
|
||||
objectRelationshipInput backendInsertAction sourceInfo tableInfo = runMaybeT $ do
|
||||
insertPerms <- MaybeT $ _permIns <$> tablePermissions tableInfo
|
||||
lift $ memoizeOn 'objectRelationshipInput (sourceName, tableName) do
|
||||
lift $ memoizeOn 'objectRelationshipInput (_siName sourceInfo, tableName) do
|
||||
updatePerms <- _permUpd <$> tablePermissions tableInfo
|
||||
_selectPerms <- _permSel <$> tablePermissions tableInfo
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
objectParser <- tableFieldsInput sourceName tableInfo
|
||||
backendInsertParser <- backendInsertAction sourceName tableInfo
|
||||
objectParser <- tableFieldsInput sourceInfo tableInfo
|
||||
backendInsertParser <- backendInsertAction sourceInfo tableInfo
|
||||
inputName <- P.mkTypename $ tableGQLName <> G.__obj_rel_insert_input
|
||||
let objectName = G._data
|
||||
inputDesc = G.Description $ "input type for inserting object relation for remote table " <>> tableName
|
||||
@ -278,18 +279,18 @@ objectRelationshipInput backendInsertAction sourceName tableInfo = runMaybeT $ d
|
||||
arrayRelationshipInput ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
(SourceName -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
SourceName ->
|
||||
(SourceInfo b -> TableInfo b -> m (InputFieldsParser n (BackendInsert b (UnpreparedValue b)))) ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Maybe (Parser 'Input n (IR.MultiObjectInsert b (UnpreparedValue b))))
|
||||
arrayRelationshipInput backendInsertAction sourceName tableInfo = runMaybeT $ do
|
||||
arrayRelationshipInput backendInsertAction sourceInfo tableInfo = runMaybeT $ do
|
||||
insertPerms <- MaybeT $ _permIns <$> tablePermissions tableInfo
|
||||
lift $ memoizeOn 'arrayRelationshipInput (sourceName, tableName) do
|
||||
lift $ memoizeOn 'arrayRelationshipInput (_siName sourceInfo, tableName) do
|
||||
updatePerms <- _permUpd <$> tablePermissions tableInfo
|
||||
_selectPerms <- _permSel <$> tablePermissions tableInfo
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
objectParser <- tableFieldsInput sourceName tableInfo
|
||||
backendInsertParser <- backendInsertAction sourceName tableInfo
|
||||
objectParser <- tableFieldsInput sourceInfo tableInfo
|
||||
backendInsertParser <- backendInsertAction sourceInfo tableInfo
|
||||
inputName <- P.mkTypename $ tableGQLName <> G.__arr_rel_insert_input
|
||||
let objectsName = G._data
|
||||
inputDesc = G.Description $ "input type for inserting array relation for remote table " <>> tableName
|
||||
@ -335,7 +336,7 @@ deleteFromTable ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
-- | table source
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | table info
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -343,15 +344,15 @@ deleteFromTable ::
|
||||
-- | field description, if any
|
||||
Maybe G.Description ->
|
||||
m (Maybe (FieldParser n (IR.AnnDelG b (IR.RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))))
|
||||
deleteFromTable sourceName tableInfo fieldName description = runMaybeT $ do
|
||||
deleteFromTable sourceInfo tableInfo fieldName description = runMaybeT $ do
|
||||
let viewInfo = _tciViewInfo $ _tiCoreInfo tableInfo
|
||||
guard $ isMutable viIsInsertable viewInfo
|
||||
deletePerms <- MaybeT $ _permDel <$> tablePermissions tableInfo
|
||||
lift do
|
||||
let whereName = G._where
|
||||
whereDesc = "filter the rows which have to be deleted"
|
||||
whereArg <- P.field whereName (Just whereDesc) <$> boolExp sourceName tableInfo
|
||||
selection <- mutationSelectionSet sourceName tableInfo
|
||||
whereArg <- P.field whereName (Just whereDesc) <$> boolExp sourceInfo tableInfo
|
||||
selection <- mutationSelectionSet sourceInfo tableInfo
|
||||
let columns = tableColumns tableInfo
|
||||
pure $
|
||||
P.subselection fieldName description whereArg selection
|
||||
@ -364,7 +365,7 @@ deleteFromTableByPk ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
-- | table source
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | table info
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -372,12 +373,12 @@ deleteFromTableByPk ::
|
||||
-- | field description, if any
|
||||
Maybe G.Description ->
|
||||
m (Maybe (FieldParser n (IR.AnnDelG b (IR.RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))))
|
||||
deleteFromTableByPk sourceName tableInfo fieldName description = runMaybeT $ do
|
||||
deleteFromTableByPk sourceInfo tableInfo fieldName description = runMaybeT $ do
|
||||
let viewInfo = _tciViewInfo $ _tiCoreInfo tableInfo
|
||||
guard $ isMutable viIsInsertable viewInfo
|
||||
pkArgs <- MaybeT $ primaryKeysArguments tableInfo
|
||||
deletePerms <- MaybeT $ _permDel <$> tablePermissions tableInfo
|
||||
selection <- MaybeT $ tableSelectionSet sourceName tableInfo
|
||||
selection <- MaybeT $ tableSelectionSet sourceInfo tableInfo
|
||||
let columns = tableColumns tableInfo
|
||||
pure $
|
||||
P.subselection fieldName description pkArgs selection
|
||||
@ -407,15 +408,15 @@ mkDeleteObject table columns deletePerms (whereExp, mutationOutput) =
|
||||
mutationSelectionSet ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Parser 'Output n (IR.MutFldsG b (IR.RemoteRelationshipField UnpreparedValue) (UnpreparedValue b)))
|
||||
mutationSelectionSet sourceName tableInfo =
|
||||
memoizeOn 'mutationSelectionSet (sourceName, tableName) do
|
||||
mutationSelectionSet sourceInfo tableInfo =
|
||||
memoizeOn 'mutationSelectionSet (_siName sourceInfo, tableName) do
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
returning <- runMaybeT do
|
||||
_permissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
tableSet <- MaybeT $ tableSelectionList sourceName tableInfo
|
||||
tableSet <- MaybeT $ tableSelectionList sourceInfo tableInfo
|
||||
let returningName = G._returning
|
||||
returningDesc = "data from the rows affected by the mutation"
|
||||
pure $ IR.MRet <$> P.subselection_ returningName (Just returningDesc) tableSet
|
||||
|
@ -30,6 +30,7 @@ import Hasura.RQL.Types.ComputedField
|
||||
import Hasura.RQL.Types.Function
|
||||
import Hasura.RQL.Types.Relationships.Local
|
||||
import Hasura.RQL.Types.SchemaCache hiding (askTableInfo)
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization
|
||||
import Hasura.RQL.Types.Table
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
@ -57,17 +58,17 @@ orderByOperator tCase = case tCase of
|
||||
orderByExp ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Parser 'Input n [IR.AnnotatedOrderByItemG b (UnpreparedValue b)])
|
||||
orderByExp sourceName tableInfo = memoizeOn 'orderByExp (sourceName, tableInfoName tableInfo) $ do
|
||||
orderByExp sourceInfo tableInfo = memoizeOn 'orderByExp (_siName sourceInfo, tableInfoName tableInfo) $ do
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
tCase <- asks getter
|
||||
name <- P.mkTypename $ tableGQLName <> G.__order_by
|
||||
let description =
|
||||
G.Description $
|
||||
"Ordering options when selecting data from " <> tableInfoName tableInfo <<> "."
|
||||
tableFields <- tableSelectFields sourceName tableInfo
|
||||
tableFields <- tableSelectFields sourceInfo tableInfo
|
||||
fieldParsers <- sequenceA . catMaybes <$> traverse (mkField tCase) tableFields
|
||||
pure $ concat . catMaybes <$> P.object name (Just description) fieldParsers
|
||||
where
|
||||
@ -86,19 +87,19 @@ orderByExp sourceName tableInfo = memoizeOn 'orderByExp (sourceName, tableInfoNa
|
||||
(orderByOperator @b tCase)
|
||||
<&> fmap (pure . mkOrderByItemG @b (IR.AOCColumn columnInfo)) . join
|
||||
FIRelationship relationshipInfo -> do
|
||||
remoteTableInfo <- askTableInfo @b sourceName $ riRTable relationshipInfo
|
||||
remoteTableInfo <- askTableInfo sourceInfo $ riRTable relationshipInfo
|
||||
fieldName <- hoistMaybe $ G.mkName $ relNameToTxt $ riName relationshipInfo
|
||||
perms <- MaybeT $ tableSelectPermissions remoteTableInfo
|
||||
let newPerms = fmap partialSQLExpToUnpreparedValue <$> spiFilter perms
|
||||
case riType relationshipInfo of
|
||||
ObjRel -> do
|
||||
otherTableParser <- lift $ orderByExp sourceName remoteTableInfo
|
||||
otherTableParser <- lift $ orderByExp sourceInfo remoteTableInfo
|
||||
pure $ do
|
||||
otherTableOrderBy <- join <$> P.fieldOptional fieldName Nothing (P.nullable otherTableParser)
|
||||
pure $ fmap (map $ fmap $ IR.AOCObjectRelation relationshipInfo newPerms) otherTableOrderBy
|
||||
ArrRel -> do
|
||||
let aggregateFieldName = fieldName <> G.__aggregate
|
||||
aggregationParser <- lift $ orderByAggregation sourceName remoteTableInfo
|
||||
aggregationParser <- lift $ orderByAggregation sourceInfo remoteTableInfo
|
||||
pure $ do
|
||||
aggregationOrderBy <- join <$> P.fieldOptional aggregateFieldName Nothing (P.nullable aggregationParser)
|
||||
pure $ fmap (map $ fmap $ IR.AOCArrayAggregation relationshipInfo newPerms) aggregationOrderBy
|
||||
@ -122,10 +123,10 @@ orderByExp sourceName tableInfo = memoizeOn 'orderByExp (sourceName, tableInfoNa
|
||||
<&> fmap (pure . mkOrderByItemG @b (IR.AOCComputedField computedFieldOrderBy)) . join
|
||||
ReturnsTable table -> do
|
||||
let aggregateFieldName = fieldName <> G.__aggregate
|
||||
tableInfo' <- askTableInfo @b sourceName table
|
||||
tableInfo' <- askTableInfo sourceInfo table
|
||||
perms <- MaybeT $ tableSelectPermissions tableInfo'
|
||||
let newPerms = fmap partialSQLExpToUnpreparedValue <$> spiFilter perms
|
||||
aggregationParser <- lift $ orderByAggregation sourceName tableInfo'
|
||||
aggregationParser <- lift $ orderByAggregation sourceInfo tableInfo'
|
||||
pure $ do
|
||||
aggregationOrderBy <- join <$> P.fieldOptional aggregateFieldName Nothing (P.nullable aggregationParser)
|
||||
pure $
|
||||
@ -147,17 +148,17 @@ orderByExp sourceName tableInfo = memoizeOn 'orderByExp (sourceName, tableInfoNa
|
||||
orderByAggregation ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Parser 'Input n [IR.OrderByItemG b (IR.AnnotatedAggregateOrderBy b)])
|
||||
orderByAggregation sourceName tableInfo = memoizeOn 'orderByAggregation (sourceName, tableName) do
|
||||
orderByAggregation sourceInfo tableInfo = memoizeOn 'orderByAggregation (_siName sourceInfo, tableName) do
|
||||
-- WIP NOTE
|
||||
-- there is heavy duplication between this and Select.tableAggregationFields
|
||||
-- it might be worth putting some of it in common, just to avoid issues when
|
||||
-- we change one but not the other?
|
||||
tableGQLName <- getTableGQLName @b tableInfo
|
||||
tCase <- asks getter
|
||||
allColumns <- tableSelectColumns sourceName tableInfo
|
||||
allColumns <- tableSelectColumns sourceInfo tableInfo
|
||||
mkTypename <- asks getter
|
||||
let numColumns = onlyNumCols allColumns
|
||||
compColumns = onlyComparableCols allColumns
|
||||
|
@ -1,5 +1,5 @@
|
||||
{-# LANGUAGE RecursiveDo #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
{-# LANGUAGE TemplateHaskellQuotes #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
|
||||
module Hasura.GraphQL.Schema.Remote
|
||||
@ -25,7 +25,6 @@ import Hasura.GraphQL.Parser.Constants qualified as G
|
||||
import Hasura.GraphQL.Parser.Internal.Parser qualified as P
|
||||
import Hasura.GraphQL.Parser.Internal.TypeChecking qualified as P
|
||||
import Hasura.GraphQL.Schema.Common
|
||||
import {-# SOURCE #-} Hasura.GraphQL.Schema.RemoteRelationship
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.RemoteSchema qualified as IR
|
||||
import Hasura.RQL.IR.Root qualified as IR
|
||||
@ -565,6 +564,7 @@ remoteSchemaRelationships relationships typeName =
|
||||
Nothing -> pure []
|
||||
Just rels ->
|
||||
concat <$> for (toList rels) \remoteFieldInfo -> do
|
||||
RemoteRelationshipParserBuilder remoteRelationshipField <- retrieve scRemoteRelationshipParserBuilder
|
||||
relationshipFields <- fromMaybe [] <$> remoteRelationshipField remoteFieldInfo
|
||||
let lhsFields = _rfiLHS remoteFieldInfo
|
||||
pure $ map (fmap (IR.SchemaRemoteRelationshipSelect lhsFields)) relationshipFields
|
||||
|
@ -30,6 +30,7 @@ import Hasura.RQL.Types.Relationships.ToSchema qualified as Remote
|
||||
import Hasura.RQL.Types.RemoteSchema
|
||||
import Hasura.RQL.Types.ResultCustomization
|
||||
import Hasura.RQL.Types.SchemaCache hiding (askTableInfo)
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization (NamingCase (..), mkCustomizedTypename)
|
||||
import Hasura.SQL.AnyBackend
|
||||
import Hasura.Session
|
||||
@ -37,34 +38,34 @@ import Language.GraphQL.Draft.Syntax qualified as G
|
||||
|
||||
-- | Remote relationship field parsers
|
||||
remoteRelationshipField ::
|
||||
forall r m n lhsJoinField.
|
||||
(MonadBuildSchemaBase r m n) =>
|
||||
RemoteFieldInfo lhsJoinField ->
|
||||
m (Maybe [FieldParser n (IR.RemoteRelationshipField UnpreparedValue)])
|
||||
remoteRelationshipField RemoteFieldInfo {..} = runMaybeT do
|
||||
queryType <- asks $ qcQueryType . getter
|
||||
-- https://github.com/hasura/graphql-engine/issues/5144
|
||||
-- The above issue is easily fixable by removing the following guard
|
||||
guard $ queryType == ET.QueryHasura
|
||||
case _rfiRHS of
|
||||
RFISource anyRemoteSourceFieldInfo ->
|
||||
dispatchAnyBackend @BackendSchema anyRemoteSourceFieldInfo \remoteSourceFieldInfo -> do
|
||||
fields <- lift $ remoteRelationshipToSourceField remoteSourceFieldInfo
|
||||
pure $ fmap (IR.RemoteSourceField . mkAnyBackend) <$> fields
|
||||
RFISchema remoteSchema -> do
|
||||
fields <- MaybeT $ remoteRelationshipToSchemaField _rfiLHS remoteSchema
|
||||
pure $ pure $ IR.RemoteSchemaField <$> fields
|
||||
SourceCache ->
|
||||
RemoteSchemaMap ->
|
||||
RemoteRelationshipParserBuilder
|
||||
remoteRelationshipField sourceCache remoteSchemaCache = RemoteRelationshipParserBuilder
|
||||
\RemoteFieldInfo {..} -> runMaybeT do
|
||||
queryType <- retrieve soQueryType
|
||||
-- https://github.com/hasura/graphql-engine/issues/5144
|
||||
-- The above issue is easily fixable by removing the following guard
|
||||
guard $ queryType == ET.QueryHasura
|
||||
case _rfiRHS of
|
||||
RFISource anyRemoteSourceFieldInfo ->
|
||||
dispatchAnyBackend @BackendSchema anyRemoteSourceFieldInfo \remoteSourceFieldInfo -> do
|
||||
fields <- lift $ remoteRelationshipToSourceField sourceCache remoteSourceFieldInfo
|
||||
pure $ fmap (IR.RemoteSourceField . mkAnyBackend) <$> fields
|
||||
RFISchema remoteSchema -> do
|
||||
fields <- MaybeT $ remoteRelationshipToSchemaField remoteSchemaCache _rfiLHS remoteSchema
|
||||
pure $ pure $ IR.RemoteSchemaField <$> fields
|
||||
|
||||
-- | Parser(s) for remote relationship fields to a remote schema
|
||||
remoteRelationshipToSchemaField ::
|
||||
forall r m n lhsJoinField.
|
||||
(MonadBuildSchemaBase r m n) =>
|
||||
RemoteSchemaMap ->
|
||||
Map.HashMap FieldName lhsJoinField ->
|
||||
RemoteSchemaFieldInfo ->
|
||||
m (Maybe (FieldParser n (IR.RemoteSchemaSelect (IR.RemoteRelationshipField UnpreparedValue))))
|
||||
remoteRelationshipToSchemaField lhsFields RemoteSchemaFieldInfo {..} = runMaybeT do
|
||||
remoteSchemaCache <- asks getter
|
||||
remoteSchemaPermsCtx <- asks $ qcRemoteSchemaPermsCtx . getter
|
||||
remoteRelationshipToSchemaField remoteSchemaCache lhsFields RemoteSchemaFieldInfo {..} = runMaybeT do
|
||||
remoteSchemaPermsCtx <- retrieve soRemoteSchemaPermsCtx
|
||||
roleName <- asks getter
|
||||
remoteSchemaContext <-
|
||||
Map.lookup _rrfiRemoteSchemaName remoteSchemaCache
|
||||
@ -173,11 +174,15 @@ lookupNestedFieldType parentTypeName remoteSchemaIntrospection (fieldCall :| res
|
||||
remoteRelationshipToSourceField ::
|
||||
forall r m n tgt.
|
||||
(MonadBuildSchemaBase r m n, BackendSchema tgt) =>
|
||||
SourceCache ->
|
||||
RemoteSourceFieldInfo tgt ->
|
||||
m [FieldParser n (IR.RemoteSourceSelect (IR.RemoteRelationshipField UnpreparedValue) UnpreparedValue tgt)]
|
||||
remoteRelationshipToSourceField RemoteSourceFieldInfo {..} =
|
||||
remoteRelationshipToSourceField sourceCache RemoteSourceFieldInfo {..} =
|
||||
withTypenameCustomization (mkCustomizedTypename (Just _rsfiSourceCustomization) HasuraCase) do
|
||||
tableInfo <- askTableInfo @tgt _rsfiSource _rsfiTable
|
||||
sourceInfo <-
|
||||
onNothing (unsafeSourceInfo @tgt =<< Map.lookup _rsfiSource sourceCache) $
|
||||
throw500 $ "source not found " <> dquote _rsfiSource
|
||||
tableInfo <- askTableInfo sourceInfo _rsfiTable
|
||||
fieldName <- textToName $ relNameToTxt _rsfiName
|
||||
maybePerms <- tableSelectPermissions @tgt tableInfo
|
||||
case maybePerms of
|
||||
@ -185,7 +190,7 @@ remoteRelationshipToSourceField RemoteSourceFieldInfo {..} =
|
||||
Just tablePerms -> do
|
||||
parsers <- case _rsfiType of
|
||||
ObjRel -> do
|
||||
selectionSetParserM <- tableSelectionSet _rsfiSource tableInfo
|
||||
selectionSetParserM <- tableSelectionSet sourceInfo tableInfo
|
||||
pure $ case selectionSetParserM of
|
||||
Nothing -> []
|
||||
Just selectionSetParser ->
|
||||
@ -195,8 +200,8 @@ remoteRelationshipToSourceField RemoteSourceFieldInfo {..} =
|
||||
IR.AnnObjectSelectG fields _rsfiTable $ IR._tpFilter $ tablePermissionsInfo tablePerms
|
||||
ArrRel -> do
|
||||
let aggFieldName = fieldName <> G.__aggregate
|
||||
selectionSetParser <- selectTable _rsfiSource tableInfo fieldName Nothing
|
||||
aggSelectionSetParser <- selectTableAggregate _rsfiSource tableInfo aggFieldName Nothing
|
||||
selectionSetParser <- selectTable sourceInfo tableInfo fieldName Nothing
|
||||
aggSelectionSetParser <- selectTableAggregate sourceInfo tableInfo aggFieldName Nothing
|
||||
pure $
|
||||
catMaybes
|
||||
[ selectionSetParser <&> fmap IR.SourceRelationshipArray,
|
||||
|
@ -1,16 +0,0 @@
|
||||
module Hasura.GraphQL.Schema.RemoteRelationship
|
||||
( remoteRelationshipField,
|
||||
)
|
||||
where
|
||||
|
||||
import Hasura.GraphQL.Parser
|
||||
import Hasura.GraphQL.Schema.Common
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.Root qualified as IR
|
||||
import Hasura.RQL.Types.Relationships.Remote
|
||||
|
||||
remoteRelationshipField ::
|
||||
forall r m n lhsJoinField.
|
||||
(MonadBuildSchemaBase r m n) =>
|
||||
RemoteFieldInfo lhsJoinField ->
|
||||
m (Maybe [FieldParser n (IR.RemoteRelationshipField UnpreparedValue)])
|
@ -15,7 +15,6 @@ module Hasura.GraphQL.Schema.Select
|
||||
selectFunctionAggregate,
|
||||
selectFunctionConnection,
|
||||
computedFieldPG,
|
||||
remoteRelationshipField,
|
||||
defaultTableArgs,
|
||||
tableWhereArg,
|
||||
tableOrderByArg,
|
||||
@ -68,7 +67,6 @@ import Hasura.GraphQL.Schema.Backend
|
||||
import Hasura.GraphQL.Schema.BoolExp
|
||||
import Hasura.GraphQL.Schema.Common
|
||||
import Hasura.GraphQL.Schema.OrderBy
|
||||
import {-# SOURCE #-} Hasura.GraphQL.Schema.RemoteRelationship
|
||||
import Hasura.GraphQL.Schema.Table
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR qualified as IR
|
||||
@ -108,7 +106,7 @@ import Language.GraphQL.Draft.Syntax qualified as G
|
||||
selectTable ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | table info
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -116,12 +114,12 @@ selectTable ::
|
||||
-- | field description, if any
|
||||
Maybe G.Description ->
|
||||
m (Maybe (FieldParser n (SelectExp b)))
|
||||
selectTable sourceName tableInfo fieldName description = runMaybeT do
|
||||
selectTable sourceInfo tableInfo fieldName description = runMaybeT do
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
selectionSetParser <- MaybeT $ tableSelectionList sourceName tableInfo
|
||||
lift $ memoizeOn 'selectTable (sourceName, tableName, fieldName) do
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
tableArgsParser <- tableArguments sourceName tableInfo
|
||||
selectionSetParser <- MaybeT $ tableSelectionList sourceInfo tableInfo
|
||||
lift $ memoizeOn 'selectTable (_siName sourceInfo, tableName, fieldName) do
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
tableArgsParser <- tableArguments sourceInfo tableInfo
|
||||
pure $
|
||||
P.subselection fieldName description tableArgsParser selectionSetParser
|
||||
<&> \(args, fields) ->
|
||||
@ -157,7 +155,7 @@ selectTable sourceName tableInfo fieldName description = runMaybeT do
|
||||
selectTableConnection ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | table info
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -167,13 +165,13 @@ selectTableConnection ::
|
||||
-- | primary key columns
|
||||
PrimaryKeyColumns b ->
|
||||
m (Maybe (FieldParser n (ConnectionSelectExp b)))
|
||||
selectTableConnection sourceName tableInfo fieldName description pkeyColumns = runMaybeT do
|
||||
selectTableConnection sourceInfo tableInfo fieldName description pkeyColumns = runMaybeT do
|
||||
xRelayInfo <- hoistMaybe $ relayExtension @b
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
selectionSetParser <- fmap P.nonNullableParser <$> MaybeT $ tableConnectionSelectionSet sourceName tableInfo
|
||||
lift $ memoizeOn 'selectTableConnection (sourceName, tableName, fieldName) do
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
selectArgsParser <- tableConnectionArgs pkeyColumns sourceName tableInfo
|
||||
selectionSetParser <- fmap P.nonNullableParser <$> MaybeT $ tableConnectionSelectionSet sourceInfo tableInfo
|
||||
lift $ memoizeOn 'selectTableConnection (_siName sourceInfo, tableName, fieldName) do
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
selectArgsParser <- tableConnectionArgs pkeyColumns sourceInfo tableInfo
|
||||
pure $
|
||||
P.subselection fieldName description selectArgsParser selectionSetParser
|
||||
<&> \((args, split, slice), fields) ->
|
||||
@ -207,7 +205,7 @@ selectTableConnection sourceName tableInfo fieldName description pkeyColumns = r
|
||||
selectTableByPk ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | table info
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -215,13 +213,13 @@ selectTableByPk ::
|
||||
-- | field description, if any
|
||||
Maybe G.Description ->
|
||||
m (Maybe (FieldParser n (SelectExp b)))
|
||||
selectTableByPk sourceName tableInfo fieldName description = runMaybeT do
|
||||
selectTableByPk sourceInfo tableInfo fieldName description = runMaybeT do
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
primaryKeys <- hoistMaybe $ fmap _pkColumns . _tciPrimaryKey . _tiCoreInfo $ tableInfo
|
||||
selectionSetParser <- MaybeT $ tableSelectionSet sourceName tableInfo
|
||||
selectionSetParser <- MaybeT $ tableSelectionSet sourceInfo tableInfo
|
||||
guard $ all (\c -> ciColumn c `Map.member` spiCols selectPermissions) primaryKeys
|
||||
lift $ memoizeOn 'selectTableByPk (sourceName, tableName, fieldName) do
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
lift $ memoizeOn 'selectTableByPk (_siName sourceInfo, tableName, fieldName) do
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
argsParser <-
|
||||
sequenceA <$> for primaryKeys \columnInfo -> do
|
||||
field <- columnParser (ciType columnInfo) (G.Nullability $ ciIsNullable columnInfo)
|
||||
@ -258,7 +256,7 @@ selectTableByPk sourceName tableInfo fieldName description = runMaybeT do
|
||||
selectTableAggregate ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | table info
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -266,16 +264,16 @@ selectTableAggregate ::
|
||||
-- | field description, if any
|
||||
Maybe G.Description ->
|
||||
m (Maybe (FieldParser n (AggSelectExp b)))
|
||||
selectTableAggregate sourceName tableInfo fieldName description = runMaybeT $ do
|
||||
selectTableAggregate sourceInfo tableInfo fieldName description = runMaybeT $ do
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
guard $ spiAllowAgg selectPermissions
|
||||
xNodesAgg <- hoistMaybe $ nodesAggExtension @b
|
||||
nodesParser <- MaybeT $ tableSelectionList sourceName tableInfo
|
||||
lift $ memoizeOn 'selectTableAggregate (sourceName, tableName, fieldName) do
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
nodesParser <- MaybeT $ tableSelectionList sourceInfo tableInfo
|
||||
lift $ memoizeOn 'selectTableAggregate (_siName sourceInfo, tableName, fieldName) do
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
tableArgsParser <- tableArguments sourceName tableInfo
|
||||
aggregateParser <- tableAggregationFields sourceName tableInfo
|
||||
tableArgsParser <- tableArguments sourceInfo tableInfo
|
||||
aggregateParser <- tableAggregationFields sourceInfo tableInfo
|
||||
selectionName <- P.mkTypename $ tableGQLName <> G.__aggregate
|
||||
let aggregationParser =
|
||||
P.nonNullableParser $
|
||||
@ -364,12 +362,12 @@ cause errors on the client side, for the following reasons:
|
||||
tableSelectionSet ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Maybe (Parser 'Output n (AnnotatedFields b)))
|
||||
tableSelectionSet sourceName tableInfo = runMaybeT do
|
||||
tableSelectionSet sourceInfo tableInfo = runMaybeT do
|
||||
_selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
lift $ memoizeOn 'tableSelectionSet (sourceName, tableName) do
|
||||
lift $ memoizeOn 'tableSelectionSet (_siName sourceInfo, tableName) do
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
objectTypename <- P.mkTypename tableGQLName
|
||||
let xRelay = relayExtension @b
|
||||
@ -380,7 +378,7 @@ tableSelectionSet sourceName tableInfo = runMaybeT do
|
||||
concat
|
||||
<$> for
|
||||
tableFields
|
||||
(fieldSelection sourceName tableName tableInfo tablePkeyColumns)
|
||||
(fieldSelection sourceInfo tableName tableInfo tablePkeyColumns)
|
||||
|
||||
-- We don't check *here* that the subselection set is non-empty,
|
||||
-- even though the GraphQL specification requires that it is (see
|
||||
@ -390,7 +388,7 @@ tableSelectionSet sourceName tableInfo = runMaybeT do
|
||||
-- required, meaning that not having this check here does not allow
|
||||
-- for the construction of invalid queries.
|
||||
|
||||
queryType <- asks $ qcQueryType . getter
|
||||
queryType <- retrieve soQueryType
|
||||
case (queryType, tablePkeyColumns, xRelay) of
|
||||
-- A relay table
|
||||
(ET.QueryRelay, Just pkeyColumns, Just xRelayInfo) -> do
|
||||
@ -414,11 +412,11 @@ tableSelectionSet sourceName tableInfo = runMaybeT do
|
||||
-- > table_name: [table!]!
|
||||
tableSelectionList ::
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Maybe (Parser 'Output n (AnnotatedFields b)))
|
||||
tableSelectionList sourceName tableInfo =
|
||||
fmap nonNullableObjectList <$> tableSelectionSet sourceName tableInfo
|
||||
tableSelectionList sourceInfo tableInfo =
|
||||
fmap nonNullableObjectList <$> tableSelectionSet sourceInfo tableInfo
|
||||
|
||||
-- | Converts an output type parser from object_type to [object_type!]!
|
||||
nonNullableObjectList :: Parser 'Output m a -> Parser 'Output m a
|
||||
@ -446,14 +444,14 @@ nonNullableObjectList =
|
||||
tableConnectionSelectionSet ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Maybe (Parser 'Output n (ConnectionFields b)))
|
||||
tableConnectionSelectionSet sourceName tableInfo = runMaybeT do
|
||||
tableConnectionSelectionSet sourceInfo tableInfo = runMaybeT do
|
||||
tableGQLName <- lift $ getTableGQLName tableInfo
|
||||
_selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
edgesParser <- MaybeT $ tableEdgesSelectionSet tableGQLName
|
||||
lift $ memoizeOn 'tableConnectionSelectionSet (sourceName, tableName) do
|
||||
lift $ memoizeOn 'tableConnectionSelectionSet (_siName sourceInfo, tableName) do
|
||||
connectionTypeName <- P.mkTypename $ tableGQLName <> G._Connection
|
||||
let pageInfo =
|
||||
P.subselection_
|
||||
@ -514,7 +512,7 @@ tableConnectionSelectionSet sourceName tableInfo = runMaybeT do
|
||||
tableEdgesSelectionSet ::
|
||||
G.Name -> m (Maybe (Parser 'Output n (EdgeFields b)))
|
||||
tableEdgesSelectionSet tableGQLName = runMaybeT do
|
||||
edgeNodeParser <- MaybeT $ fmap P.nonNullableParser <$> tableSelectionSet sourceName tableInfo
|
||||
edgeNodeParser <- MaybeT $ fmap P.nonNullableParser <$> tableSelectionSet sourceInfo tableInfo
|
||||
edgesType <- lift $ P.mkTypename $ tableGQLName <> G._Edge
|
||||
let cursor =
|
||||
P.selection_
|
||||
@ -538,20 +536,20 @@ selectFunction ::
|
||||
forall r m n pgKind.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
-- | source name
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
-- | SQL function info
|
||||
FunctionInfo ('Postgres pgKind) ->
|
||||
-- | field description, if any
|
||||
Maybe G.Description ->
|
||||
m (Maybe (FieldParser n (SelectExp ('Postgres pgKind))))
|
||||
selectFunction sourceName fi@FunctionInfo {..} description = runMaybeT do
|
||||
tableInfo <- lift $ askTableInfo sourceName _fiReturnType
|
||||
selectFunction sourceInfo fi@FunctionInfo {..} description = runMaybeT do
|
||||
tableInfo <- lift $ askTableInfo sourceInfo _fiReturnType
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
selectionSetParser <- MaybeT $ returnFunctionParser sourceName tableInfo
|
||||
selectionSetParser <- MaybeT $ returnFunctionParser sourceInfo tableInfo
|
||||
lift do
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
tableArgsParser <- tableArguments sourceName tableInfo
|
||||
functionArgsParser <- customSQLFunctionArgs fi _fiGQLName _fiGQLArgsName
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
tableArgsParser <- tableArguments sourceInfo tableInfo
|
||||
functionArgsParser <- customSQLFunctionArgs sourceInfo fi _fiGQLName _fiGQLArgsName
|
||||
let argsParser = liftA2 (,) functionArgsParser tableArgsParser
|
||||
functionFieldName <- mkRootFieldName _fiGQLName
|
||||
pure $
|
||||
@ -574,25 +572,25 @@ selectFunctionAggregate ::
|
||||
forall r m n pgKind.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
-- | source name
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
-- | SQL function info
|
||||
FunctionInfo ('Postgres pgKind) ->
|
||||
-- | field description, if any
|
||||
Maybe G.Description ->
|
||||
m (Maybe (FieldParser n (AggSelectExp ('Postgres pgKind))))
|
||||
selectFunctionAggregate sourceName fi@FunctionInfo {..} description = runMaybeT do
|
||||
targetTableInfo <- askTableInfo sourceName _fiReturnType
|
||||
selectFunctionAggregate sourceInfo fi@FunctionInfo {..} description = runMaybeT do
|
||||
targetTableInfo <- askTableInfo sourceInfo _fiReturnType
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions targetTableInfo
|
||||
guard $ spiAllowAgg selectPermissions
|
||||
xNodesAgg <- hoistMaybe $ nodesAggExtension @('Postgres pgKind)
|
||||
tableInfo <- askTableInfo sourceName _fiReturnType
|
||||
nodesParser <- MaybeT $ tableSelectionList sourceName tableInfo
|
||||
tableInfo <- askTableInfo sourceInfo _fiReturnType
|
||||
nodesParser <- MaybeT $ tableSelectionList sourceInfo tableInfo
|
||||
lift do
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
tableArgsParser <- tableArguments sourceName tableInfo
|
||||
functionArgsParser <- customSQLFunctionArgs fi _fiGQLAggregateName _fiGQLArgsName
|
||||
aggregateParser <- tableAggregationFields sourceName tableInfo
|
||||
tableArgsParser <- tableArguments sourceInfo tableInfo
|
||||
functionArgsParser <- customSQLFunctionArgs sourceInfo fi _fiGQLAggregateName _fiGQLArgsName
|
||||
aggregateParser <- tableAggregationFields sourceInfo tableInfo
|
||||
selectionName <- P.mkTypename =<< pure (tableGQLName <> G.__aggregate)
|
||||
aggregateFieldName <- mkRootFieldName _fiGQLAggregateName
|
||||
let argsParser = liftA2 (,) functionArgsParser tableArgsParser
|
||||
@ -620,7 +618,7 @@ selectFunctionConnection ::
|
||||
forall pgKind r m n.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
-- | source name
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
-- | SQL function info
|
||||
FunctionInfo ('Postgres pgKind) ->
|
||||
-- | field description, if any
|
||||
@ -628,17 +626,17 @@ selectFunctionConnection ::
|
||||
-- | primary key columns of the target table
|
||||
PrimaryKeyColumns ('Postgres pgKind) ->
|
||||
m (Maybe (FieldParser n (ConnectionSelectExp ('Postgres pgKind))))
|
||||
selectFunctionConnection sourceName fi@FunctionInfo {..} description pkeyColumns = runMaybeT do
|
||||
returnTableInfo <- lift $ askTableInfo sourceName _fiReturnType
|
||||
selectFunctionConnection sourceInfo fi@FunctionInfo {..} description pkeyColumns = runMaybeT do
|
||||
returnTableInfo <- lift $ askTableInfo sourceInfo _fiReturnType
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions returnTableInfo
|
||||
xRelayInfo <- hoistMaybe $ relayExtension @('Postgres pgKind)
|
||||
tableInfo <- lift $ askTableInfo sourceName _fiReturnType
|
||||
selectionSetParser <- MaybeT $ tableConnectionSelectionSet sourceName tableInfo
|
||||
tableInfo <- lift $ askTableInfo sourceInfo _fiReturnType
|
||||
selectionSetParser <- MaybeT $ tableConnectionSelectionSet sourceInfo tableInfo
|
||||
lift do
|
||||
fieldName <- mkRootFieldName $ _fiGQLName <> G.__connection
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
tableConnectionArgsParser <- tableConnectionArgs pkeyColumns sourceName tableInfo
|
||||
functionArgsParser <- customSQLFunctionArgs fi _fiGQLName _fiGQLArgsName
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
tableConnectionArgsParser <- tableConnectionArgs pkeyColumns sourceInfo tableInfo
|
||||
functionArgsParser <- customSQLFunctionArgs sourceInfo fi _fiGQLName _fiGQLArgsName
|
||||
let argsParser = liftA2 (,) functionArgsParser tableConnectionArgsParser
|
||||
pure $
|
||||
P.subselection fieldName description argsParser selectionSetParser
|
||||
@ -673,13 +671,13 @@ selectFunctionConnection sourceName fi@FunctionInfo {..} description pkeyColumns
|
||||
defaultTableArgs ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (InputFieldsParser n (SelectArgs b))
|
||||
defaultTableArgs sourceName tableInfo = do
|
||||
whereParser <- tableWhereArg sourceName tableInfo
|
||||
orderByParser <- tableOrderByArg sourceName tableInfo
|
||||
distinctParser <- tableDistinctArg sourceName tableInfo
|
||||
defaultTableArgs sourceInfo tableInfo = do
|
||||
whereParser <- tableWhereArg sourceInfo tableInfo
|
||||
orderByParser <- tableOrderByArg sourceInfo tableInfo
|
||||
distinctParser <- tableDistinctArg sourceInfo tableInfo
|
||||
let result = do
|
||||
whereArg <- whereParser
|
||||
orderByArg <- orderByParser
|
||||
@ -721,11 +719,11 @@ defaultTableArgs sourceName tableInfo = do
|
||||
tableWhereArg ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (InputFieldsParser n (Maybe (IR.AnnBoolExp b (UnpreparedValue b))))
|
||||
tableWhereArg sourceName tableInfo = do
|
||||
boolExpParser <- boolExp sourceName tableInfo
|
||||
tableWhereArg sourceInfo tableInfo = do
|
||||
boolExpParser <- boolExp sourceInfo tableInfo
|
||||
pure $
|
||||
fmap join $
|
||||
P.fieldOptional whereName whereDesc $
|
||||
@ -739,12 +737,12 @@ tableWhereArg sourceName tableInfo = do
|
||||
tableOrderByArg ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (InputFieldsParser n (Maybe (NonEmpty (IR.AnnotatedOrderByItemG b (UnpreparedValue b)))))
|
||||
tableOrderByArg sourceName tableInfo = do
|
||||
tableOrderByArg sourceInfo tableInfo = do
|
||||
tCase <- asks getter
|
||||
orderByParser <- orderByExp sourceName tableInfo
|
||||
orderByParser <- orderByExp sourceInfo tableInfo
|
||||
let orderByName = applyFieldNameCaseCust tCase G._order_by
|
||||
orderByDesc = Just $ G.Description "sort the rows by one or more columns"
|
||||
pure $ do
|
||||
@ -758,12 +756,12 @@ tableOrderByArg sourceName tableInfo = do
|
||||
tableDistinctArg ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (InputFieldsParser n (Maybe (NonEmpty (Column b))))
|
||||
tableDistinctArg sourceName tableInfo = do
|
||||
tableDistinctArg sourceInfo tableInfo = do
|
||||
tCase <- asks getter
|
||||
columnsEnum <- tableSelectColumnsEnum sourceName tableInfo
|
||||
columnsEnum <- tableSelectColumnsEnum sourceInfo tableInfo
|
||||
let distinctOnName = applyFieldNameCaseCust tCase G._distinct_on
|
||||
distinctOnDesc = Just $ G.Description "distinct select on columns"
|
||||
pure do
|
||||
@ -815,7 +813,7 @@ tableConnectionArgs ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
PrimaryKeyColumns b ->
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m
|
||||
( InputFieldsParser
|
||||
@ -825,10 +823,10 @@ tableConnectionArgs ::
|
||||
Maybe IR.ConnectionSlice
|
||||
)
|
||||
)
|
||||
tableConnectionArgs pkeyColumns sourceName tableInfo = do
|
||||
whereParser <- tableWhereArg sourceName tableInfo
|
||||
orderByParser <- fmap (fmap appendPrimaryKeyOrderBy) <$> tableOrderByArg sourceName tableInfo
|
||||
distinctParser <- tableDistinctArg sourceName tableInfo
|
||||
tableConnectionArgs pkeyColumns sourceInfo tableInfo = do
|
||||
whereParser <- tableWhereArg sourceInfo tableInfo
|
||||
orderByParser <- fmap (fmap appendPrimaryKeyOrderBy) <$> tableOrderByArg sourceInfo tableInfo
|
||||
distinctParser <- tableDistinctArg sourceInfo tableInfo
|
||||
let maybeFirst = fmap join $ P.fieldOptional G._first Nothing $ P.nullable P.nonNegativeInt
|
||||
maybeLast = fmap join $ P.fieldOptional G._last Nothing $ P.nullable P.nonNegativeInt
|
||||
maybeAfter = fmap join $ P.fieldOptional G._after Nothing $ P.nullable base64Text
|
||||
@ -960,45 +958,46 @@ tableConnectionArgs pkeyColumns sourceName tableInfo = do
|
||||
tableAggregationFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Parser 'Output n (IR.AggregateFields b))
|
||||
tableAggregationFields sourceName tableInfo = memoizeOn 'tableAggregationFields (sourceName, tableInfoName tableInfo) do
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
allColumns <- tableSelectColumns sourceName tableInfo
|
||||
tCase <- asks getter
|
||||
let numericColumns = onlyNumCols allColumns
|
||||
comparableColumns = onlyComparableCols allColumns
|
||||
description = G.Description $ "aggregate fields of " <>> tableInfoName tableInfo
|
||||
selectName <- P.mkTypename $ tableGQLName <> G.__aggregate_fields
|
||||
count <- countField
|
||||
mkTypename <- asks getter
|
||||
numericAndComparable <-
|
||||
fmap concat $
|
||||
sequenceA $
|
||||
catMaybes
|
||||
[ -- operators on numeric columns
|
||||
if null numericColumns
|
||||
then Nothing
|
||||
else Just $
|
||||
for numericAggOperators $ \operator -> do
|
||||
let fieldNameCase = applyFieldNameCaseCust tCase operator
|
||||
numFields <- mkNumericAggFields operator numericColumns
|
||||
pure $ parseAggOperator mkTypename operator fieldNameCase tableGQLName numFields,
|
||||
-- operators on comparable columns
|
||||
if null comparableColumns
|
||||
then Nothing
|
||||
else Just $ do
|
||||
comparableFields <- traverse mkColumnAggField comparableColumns
|
||||
pure $
|
||||
comparisonAggOperators & map \operator ->
|
||||
tableAggregationFields sourceInfo tableInfo =
|
||||
memoizeOn 'tableAggregationFields (_siName sourceInfo, tableInfoName tableInfo) do
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
tCase <- asks getter
|
||||
allColumns <- tableSelectColumns sourceInfo tableInfo
|
||||
let numericColumns = onlyNumCols allColumns
|
||||
comparableColumns = onlyComparableCols allColumns
|
||||
description = G.Description $ "aggregate fields of " <>> tableInfoName tableInfo
|
||||
selectName <- P.mkTypename $ tableGQLName <> G.__aggregate_fields
|
||||
count <- countField
|
||||
mkTypename <- asks getter
|
||||
numericAndComparable <-
|
||||
fmap concat $
|
||||
sequenceA $
|
||||
catMaybes
|
||||
[ -- operators on numeric columns
|
||||
if null numericColumns
|
||||
then Nothing
|
||||
else Just $
|
||||
for numericAggOperators $ \operator -> do
|
||||
let fieldNameCase = applyFieldNameCaseCust tCase operator
|
||||
in parseAggOperator mkTypename operator fieldNameCase tableGQLName comparableFields
|
||||
]
|
||||
let aggregateFields = count : numericAndComparable
|
||||
pure $
|
||||
P.selectionSet selectName (Just description) aggregateFields
|
||||
<&> parsedSelectionsToFields IR.AFExp
|
||||
numFields <- mkNumericAggFields operator numericColumns
|
||||
pure $ parseAggOperator mkTypename operator fieldNameCase tableGQLName numFields,
|
||||
-- operators on comparable columns
|
||||
if null comparableColumns
|
||||
then Nothing
|
||||
else Just $ do
|
||||
comparableFields <- traverse mkColumnAggField comparableColumns
|
||||
pure $
|
||||
comparisonAggOperators & map \operator ->
|
||||
let fieldNameCase = applyFieldNameCaseCust tCase operator
|
||||
in parseAggOperator mkTypename operator fieldNameCase tableGQLName comparableFields
|
||||
]
|
||||
let aggregateFields = count : numericAndComparable
|
||||
pure $
|
||||
P.selectionSet selectName (Just description) aggregateFields
|
||||
<&> parsedSelectionsToFields IR.AFExp
|
||||
where
|
||||
mkNumericAggFields :: G.Name -> [ColumnInfo b] -> m [FieldParser n (IR.ColFld b)]
|
||||
mkNumericAggFields name
|
||||
@ -1023,7 +1022,7 @@ tableAggregationFields sourceName tableInfo = memoizeOn 'tableAggregationFields
|
||||
|
||||
countField :: m (FieldParser n (IR.AggregateField b))
|
||||
countField = do
|
||||
columnsEnum <- tableSelectColumnsEnum sourceName tableInfo
|
||||
columnsEnum <- tableSelectColumnsEnum sourceInfo tableInfo
|
||||
let distinctName = G._distinct
|
||||
args = do
|
||||
distinct <- P.fieldOptional distinctName Nothing P.boolean
|
||||
@ -1060,16 +1059,16 @@ tableAggregationFields sourceName tableInfo = memoizeOn 'tableAggregationFields
|
||||
fieldSelection ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
TableInfo b ->
|
||||
Maybe (PrimaryKeyColumns b) ->
|
||||
FieldInfo b ->
|
||||
m [FieldParser n (AnnotatedField b)]
|
||||
fieldSelection sourceName table tableInfo maybePkeyColumns = \case
|
||||
fieldSelection sourceInfo table tableInfo maybePkeyColumns = \case
|
||||
FIColumn columnInfo ->
|
||||
maybeToList <$> runMaybeT do
|
||||
queryType <- asks $ qcQueryType . getter
|
||||
queryType <- retrieve soQueryType
|
||||
let fieldName = ciName columnInfo
|
||||
if fieldName == G._id && queryType == ET.QueryRelay
|
||||
then do
|
||||
@ -1111,20 +1110,21 @@ fieldSelection sourceName table tableInfo maybePkeyColumns = \case
|
||||
P.selection fieldName (ciDescription columnInfo) pathArg field
|
||||
<&> IR.mkAnnColumnField (ciColumn columnInfo) (ciType columnInfo) caseBoolExpUnpreparedValue
|
||||
FIRelationship relationshipInfo ->
|
||||
concat . maybeToList <$> relationshipField sourceName table relationshipInfo
|
||||
concat . maybeToList <$> relationshipField sourceInfo table relationshipInfo
|
||||
FIComputedField computedFieldInfo ->
|
||||
maybeToList <$> computedField sourceName computedFieldInfo table tableInfo
|
||||
maybeToList <$> computedField sourceInfo computedFieldInfo table tableInfo
|
||||
FIRemoteRelationship remoteFieldInfo -> do
|
||||
queryType <- asks $ qcQueryType . getter
|
||||
queryType <- retrieve soQueryType
|
||||
case (queryType, _rfiRHS remoteFieldInfo) of
|
||||
(ET.QueryRelay, RFISchema _) ->
|
||||
-- Remote schemas aren't currently supported in Relay, and we therefore
|
||||
-- cannot include remote relationships to them while building a
|
||||
-- Relay-specific schema: attempting to do so would raise an error, as
|
||||
-- 'remoteRelationshipField' would attempt to look into the
|
||||
-- 'QueryContext' for information about the targeted schema.
|
||||
-- 'SchemaOptions' for information about the targeted schema.
|
||||
pure []
|
||||
_ -> do
|
||||
RemoteRelationshipParserBuilder remoteRelationshipField <- retrieve scRemoteRelationshipParserBuilder
|
||||
relationshipFields <- fromMaybe [] <$> remoteRelationshipField remoteFieldInfo
|
||||
let lhsFields = _rfiLHS remoteFieldInfo
|
||||
pure $ map (fmap (IR.AFRemote . IR.RemoteRelationshipSelect lhsFields)) relationshipFields
|
||||
@ -1213,20 +1213,20 @@ join) satisfies `p(T)`.
|
||||
relationshipField ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableName b ->
|
||||
RelInfo b ->
|
||||
m (Maybe [FieldParser n (AnnotatedField b)])
|
||||
relationshipField sourceName table ri = runMaybeT do
|
||||
relationshipField sourceInfo table ri = runMaybeT do
|
||||
tCase <- asks getter
|
||||
optimizePermissionFilters <- asks $ qcOptimizePermissionFilters . getter
|
||||
otherTableInfo <- lift $ askTableInfo sourceName $ riRTable ri
|
||||
optimizePermissionFilters <- retrieve soOptimizePermissionFilters
|
||||
otherTableInfo <- lift $ askTableInfo sourceInfo $ riRTable ri
|
||||
remotePerms <- MaybeT $ tableSelectPermissions otherTableInfo
|
||||
relFieldName <- lift $ textToName $ relNameToTxt $ riName ri
|
||||
-- START black magic to deduplicate permission checks
|
||||
thisTablePerm <-
|
||||
IR._tpFilter . tablePermissionsInfo
|
||||
<$> MaybeT (tableSelectPermissions =<< askTableInfo @b sourceName table)
|
||||
<$> MaybeT (tableSelectPermissions =<< askTableInfo sourceInfo table)
|
||||
let deduplicatePermissions :: AnnBoolExp b (UnpreparedValue b) -> AnnBoolExp b (UnpreparedValue b)
|
||||
deduplicatePermissions x =
|
||||
case (optimizePermissionFilters, x) of
|
||||
@ -1251,7 +1251,7 @@ relationshipField sourceName table ri = runMaybeT do
|
||||
case riType ri of
|
||||
ObjRel -> do
|
||||
let desc = Just $ G.Description "An object relationship"
|
||||
selectionSetParser <- MaybeT $ tableSelectionSet sourceName otherTableInfo
|
||||
selectionSetParser <- MaybeT $ tableSelectionSet sourceInfo otherTableInfo
|
||||
-- We need to set the correct nullability of our GraphQL field. Manual
|
||||
-- relationships are always nullable, and so are "reverse" object
|
||||
-- relationships, i.e. Hasura relationships that are generated from a
|
||||
@ -1287,7 +1287,7 @@ relationshipField sourceName table ri = runMaybeT do
|
||||
nullable <- case (riIsManual ri, riInsertOrder ri) of
|
||||
-- Automatically generated forward relationship
|
||||
(False, BeforeParent) -> do
|
||||
tableInfo <- askTableInfo @b sourceName table
|
||||
tableInfo <- askTableInfo sourceInfo table
|
||||
let columns = Map.keys $ riMapping ri
|
||||
fieldInfoMap = _tciFieldInfoMap $ _tiCoreInfo tableInfo
|
||||
findColumn col = Map.lookup (fromCol @b col) fieldInfoMap ^? _Just . _FIColumn
|
||||
@ -1311,7 +1311,7 @@ relationshipField sourceName table ri = runMaybeT do
|
||||
IR._tpFilter $ tablePermissionsInfo remotePerms
|
||||
ArrRel -> do
|
||||
let arrayRelDesc = Just $ G.Description "An array relationship"
|
||||
otherTableParser <- MaybeT $ selectTable sourceName otherTableInfo relFieldName arrayRelDesc
|
||||
otherTableParser <- MaybeT $ selectTable sourceInfo otherTableInfo relFieldName arrayRelDesc
|
||||
let arrayRelField =
|
||||
otherTableParser <&> \selectExp ->
|
||||
IR.AFArrayRelation $
|
||||
@ -1320,10 +1320,10 @@ relationshipField sourceName table ri = runMaybeT do
|
||||
deduplicatePermissions' selectExp
|
||||
relAggFieldName = applyFieldNameCaseCust tCase $ relFieldName <> G.__aggregate
|
||||
relAggDesc = Just $ G.Description "An aggregate relationship"
|
||||
remoteAggField <- lift $ selectTableAggregate sourceName otherTableInfo relAggFieldName relAggDesc
|
||||
remoteAggField <- lift $ selectTableAggregate sourceInfo otherTableInfo relAggFieldName relAggDesc
|
||||
remoteConnectionField <- runMaybeT $ do
|
||||
-- Parse array connection field only for relay schema
|
||||
queryType <- asks $ qcQueryType . getter
|
||||
queryType <- retrieve soQueryType
|
||||
guard $ queryType == ET.QueryRelay
|
||||
_xRelayInfo <- hoistMaybe $ relayExtension @b
|
||||
pkeyColumns <-
|
||||
@ -1332,7 +1332,7 @@ relationshipField sourceName table ri = runMaybeT do
|
||||
<$> pure otherTableInfo
|
||||
let relConnectionName = relFieldName <> G.__connection
|
||||
relConnectionDesc = Just $ G.Description "An array relationship connection"
|
||||
MaybeT $ lift $ selectTableConnection sourceName otherTableInfo relConnectionName relConnectionDesc pkeyColumns
|
||||
MaybeT $ lift $ selectTableConnection sourceInfo otherTableInfo relConnectionName relConnectionDesc pkeyColumns
|
||||
pure $
|
||||
catMaybes
|
||||
[ Just arrayRelField,
|
||||
@ -1344,14 +1344,14 @@ relationshipField sourceName table ri = runMaybeT do
|
||||
computedFieldPG ::
|
||||
forall pgKind r m n.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceName ->
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
ComputedFieldInfo ('Postgres pgKind) ->
|
||||
TableName ('Postgres pgKind) ->
|
||||
TableInfo ('Postgres pgKind) ->
|
||||
m (Maybe (FieldParser n (AnnotatedField ('Postgres pgKind))))
|
||||
computedFieldPG sourceName ComputedFieldInfo {..} parentTable tableInfo = runMaybeT do
|
||||
computedFieldPG sourceInfo ComputedFieldInfo {..} parentTable tableInfo = runMaybeT do
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
fieldName <- lift $ textToName $ computedFieldNameToText _cfiName
|
||||
functionArgsParser <- lift $ computedFieldFunctionArgs _cfiFunction
|
||||
case _cfiReturnType of
|
||||
@ -1380,10 +1380,10 @@ computedFieldPG sourceName ComputedFieldInfo {..} parentTable tableInfo = runMay
|
||||
dummyParser <- lift $ columnParser @('Postgres pgKind) (ColumnScalar scalarReturnType) (G.Nullability True)
|
||||
pure $ P.selection fieldName fieldDescription fieldArgsParser dummyParser
|
||||
PG.CFRSetofTable tableName -> do
|
||||
otherTableInfo <- lift $ askTableInfo sourceName tableName
|
||||
otherTableInfo <- lift $ askTableInfo sourceInfo tableName
|
||||
remotePerms <- MaybeT $ tableSelectPermissions otherTableInfo
|
||||
selectionSetParser <- MaybeT (fmap (P.multiple . P.nonNullableParser) <$> tableSelectionSet sourceName otherTableInfo)
|
||||
selectArgsParser <- lift $ tableArguments sourceName otherTableInfo
|
||||
selectionSetParser <- MaybeT (fmap (P.multiple . P.nonNullableParser) <$> tableSelectionSet sourceInfo otherTableInfo)
|
||||
selectArgsParser <- lift $ tableArguments sourceInfo otherTableInfo
|
||||
let fieldArgsParser = liftA2 (,) functionArgsParser selectArgsParser
|
||||
pure $
|
||||
P.subselection fieldName fieldDescription fieldArgsParser selectionSetParser
|
||||
@ -1405,7 +1405,8 @@ computedFieldPG sourceName ComputedFieldInfo {..} parentTable tableInfo = runMay
|
||||
ComputedFieldFunction ('Postgres pgKind) ->
|
||||
m (InputFieldsParser n (FunctionArgsExp ('Postgres pgKind) (UnpreparedValue ('Postgres pgKind))))
|
||||
computedFieldFunctionArgs ComputedFieldFunction {..} =
|
||||
functionArgs (FTAComputedField _cfiName sourceName parentTable) (IAUserProvided <$> _cffInputArgs) <&> fmap addTableAndSessionArgument
|
||||
functionArgs sourceInfo (FTAComputedField _cfiName (_siName sourceInfo) parentTable) (IAUserProvided <$> _cffInputArgs)
|
||||
<&> fmap addTableAndSessionArgument
|
||||
where
|
||||
addTableAndSessionArgument args@(FunctionArgsExp positional named) =
|
||||
let withTable = case PG._cffaTableArgument _cffComputedFieldImplicitArgs of
|
||||
@ -1421,12 +1422,14 @@ computedFieldPG sourceName ComputedFieldInfo {..} parentTable tableInfo = runMay
|
||||
-- > function_name(args: function_args)
|
||||
customSQLFunctionArgs ::
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
FunctionInfo ('Postgres pgKind) ->
|
||||
G.Name ->
|
||||
G.Name ->
|
||||
m (InputFieldsParser n (FunctionArgsExp ('Postgres pgKind) (UnpreparedValue ('Postgres pgKind))))
|
||||
customSQLFunctionArgs FunctionInfo {..} functionName functionArgsName =
|
||||
customSQLFunctionArgs sourceInfo FunctionInfo {..} functionName functionArgsName =
|
||||
functionArgs
|
||||
sourceInfo
|
||||
( FTACustomFunction $
|
||||
CustomFunctionNames
|
||||
{ cfnFunctionName = functionName,
|
||||
@ -1449,10 +1452,11 @@ customSQLFunctionArgs FunctionInfo {..} functionName functionArgsName =
|
||||
functionArgs ::
|
||||
forall r m n pgKind.
|
||||
MonadBuildSchema ('Postgres pgKind) r m n =>
|
||||
SourceInfo ('Postgres pgKind) ->
|
||||
FunctionTrackedAs ('Postgres pgKind) ->
|
||||
Seq.Seq (FunctionInputArgument ('Postgres pgKind)) ->
|
||||
m (InputFieldsParser n (FunctionArgsExp ('Postgres pgKind) (UnpreparedValue ('Postgres pgKind))))
|
||||
functionArgs functionTrackedAs (toList -> inputArgs) = do
|
||||
functionArgs sourceInfo functionTrackedAs (toList -> inputArgs) = do
|
||||
-- First, we iterate through the original sql arguments in order, to find the
|
||||
-- corresponding graphql names. At the same time, we create the input field
|
||||
-- parsers, in three groups: session argument, optional arguments, and
|
||||
@ -1476,8 +1480,8 @@ functionArgs functionTrackedAs (toList -> inputArgs) = do
|
||||
objectName <-
|
||||
P.mkTypename
|
||||
=<< case functionTrackedAs of
|
||||
FTAComputedField computedFieldName sourceName tableName -> do
|
||||
tableInfo <- askTableInfo sourceName tableName
|
||||
FTAComputedField computedFieldName _sourceName tableName -> do
|
||||
tableInfo <- askTableInfo sourceInfo tableName
|
||||
computedFieldGQLName <- textToName $ computedFieldNameToText computedFieldName
|
||||
tableGQLName <- getTableGQLName @('Postgres pgKind) tableInfo
|
||||
pure $ computedFieldGQLName <> G.__ <> tableGQLName <> G.__args
|
||||
@ -1661,24 +1665,27 @@ nodePG = memoizeOn 'nodePG () do
|
||||
let idDescription = G.Description "A globally unique identifier"
|
||||
idField = P.selection_ G._id (Just idDescription) P.identifier
|
||||
nodeInterfaceDescription = G.Description "An object with globally unique ID"
|
||||
sources :: SourceCache <- asks getter
|
||||
sources <- retrieve scSourceCache
|
||||
tCase <- asks getter
|
||||
let allTables = Map.fromList $ do
|
||||
-- FIXME? When source name is used in type generation?
|
||||
(source, sourceInfo) <- Map.toList sources
|
||||
tableName <- maybe [] (Map.keys . takeValidTables) $ unsafeSourceTables @('Postgres 'Vanilla) sourceInfo
|
||||
sourceConfig <- maybeToList $ unsafeSourceConfiguration @('Postgres 'Vanilla) sourceInfo
|
||||
pure (tableName, (source, sourceConfig, AB.runBackend sourceInfo _siCustomization))
|
||||
tables <-
|
||||
Map.catMaybes <$> flip Map.traverseWithKey allTables \table (source, sourceConfig, SourceCustomization {..}) -> runMaybeT do
|
||||
tableInfo <- lift $ askTableInfo source table
|
||||
tablePkeyColumns <- hoistMaybe $ tableInfo ^? tiCoreInfo . tciPrimaryKey . _Just . pkColumns
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
annotatedFieldsParser <-
|
||||
MaybeT $
|
||||
P.withTypenameCustomization (mkCustomizedTypename _scTypeNames tCase) $
|
||||
tableSelectionSet source tableInfo
|
||||
pure $ (source,sourceConfig,selectPermissions,tablePkeyColumns,) <$> annotatedFieldsParser
|
||||
Map.fromList . catMaybes <$> sequence do
|
||||
(sourceName, sourceInfo) <- Map.toList sources
|
||||
pgInfo <- maybeToList $ AB.unpackAnyBackend @('Postgres 'Vanilla) sourceInfo
|
||||
tableName <- Map.keys $ takeValidTables $ _siTables pgInfo
|
||||
pure $ runMaybeT do
|
||||
tableInfo <- lift $ askTableInfo pgInfo tableName
|
||||
tablePkeyColumns <- hoistMaybe $ tableInfo ^? tiCoreInfo . tciPrimaryKey . _Just . pkColumns
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
annotatedFieldsParser <-
|
||||
MaybeT $
|
||||
P.withTypenameCustomization
|
||||
(mkCustomizedTypename (_scTypeNames $ _siCustomization pgInfo) tCase)
|
||||
(tableSelectionSet pgInfo tableInfo)
|
||||
pure
|
||||
( tableName,
|
||||
(sourceName,_siConfiguration pgInfo,selectPermissions,tablePkeyColumns,)
|
||||
<$> annotatedFieldsParser
|
||||
)
|
||||
pure $
|
||||
P.selectionSetInterface
|
||||
G._Node
|
||||
@ -1693,7 +1700,7 @@ nodeField ::
|
||||
nodeField = do
|
||||
let idDescription = G.Description "A globally unique id"
|
||||
idArgument = P.field G._id (Just idDescription) P.identifier
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
nodeObject <- node
|
||||
return $
|
||||
P.subselection G._node Nothing idArgument nodeObject
|
||||
|
@ -26,8 +26,8 @@ import Hasura.GraphQL.Schema.Table (getTableGQLName, tableSelectColumns, tableSe
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.Select qualified as IR
|
||||
import Hasura.RQL.Types.Column
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.SchemaCache
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization (NamingCase, applyFieldNameCaseCust, applyTypeNameCaseCust)
|
||||
import Hasura.RQL.Types.Subscription
|
||||
import Hasura.RQL.Types.Table
|
||||
@ -114,12 +114,12 @@ streamColumnParserArg colInfo = do
|
||||
streamColumnValueParser ::
|
||||
forall b n m r.
|
||||
(BackendSchema b, MonadSchema n m, Has P.MkTypename r, MonadReader r m, MonadError QErr m, Has NamingCase r) =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
G.Name ->
|
||||
[ColumnInfo b] ->
|
||||
m (Parser 'Input n [(ColumnInfo b, ColumnValue b)])
|
||||
streamColumnValueParser sourceName tableGQLName colInfos =
|
||||
memoizeOn 'streamColumnValueParser (sourceName, tableGQLName) $ do
|
||||
streamColumnValueParser sourceInfo tableGQLName colInfos =
|
||||
memoizeOn 'streamColumnValueParser (_siName sourceInfo, tableGQLName) $ do
|
||||
tCase <- asks getter
|
||||
columnVals <- sequenceA <$> traverse streamColumnParserArg colInfos
|
||||
objName <- P.mkTypename $ tableGQLName <> applyTypeNameCaseCust tCase G.__stream_cursor_value_input
|
||||
@ -138,13 +138,13 @@ streamColumnValueParserArg ::
|
||||
MonadError QErr m,
|
||||
Has NamingCase r
|
||||
) =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
G.Name ->
|
||||
[ColumnInfo b] ->
|
||||
m (InputFieldsParser n [(ColumnInfo b, ColumnValue b)])
|
||||
streamColumnValueParserArg sourceName tableGQLName colInfos = do
|
||||
streamColumnValueParserArg sourceInfo tableGQLName colInfos = do
|
||||
tCase <- asks getter
|
||||
columnValueParser <- streamColumnValueParser sourceName tableGQLName colInfos
|
||||
columnValueParser <- streamColumnValueParser sourceInfo tableGQLName colInfos
|
||||
pure do
|
||||
P.field (applyFieldNameCaseCust tCase G._initial_value) (Just $ G.Description "Stream column input with initial value") columnValueParser
|
||||
|
||||
@ -155,13 +155,13 @@ streamColumnValueParserArg sourceName tableGQLName colInfos = do
|
||||
tableStreamColumnArg ::
|
||||
forall n m r b.
|
||||
(BackendSchema b, MonadSchema n m, Has P.MkTypename r, MonadReader r m, MonadError QErr m, Has NamingCase r) =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
G.Name ->
|
||||
[ColumnInfo b] ->
|
||||
m (InputFieldsParser n [IR.StreamCursorItem b])
|
||||
tableStreamColumnArg sourceName tableGQLName colInfos = do
|
||||
tableStreamColumnArg sourceInfo tableGQLName colInfos = do
|
||||
cursorOrderingParser <- cursorOrderingArg
|
||||
streamColumnParser <- streamColumnValueParserArg sourceName tableGQLName colInfos
|
||||
streamColumnParser <- streamColumnValueParserArg sourceInfo tableGQLName colInfos
|
||||
pure $ do
|
||||
orderingArg <- cursorOrderingParser
|
||||
columnArg <- streamColumnParser
|
||||
@ -176,18 +176,18 @@ tableStreamColumnArg sourceName tableGQLName colInfos = do
|
||||
tableStreamCursorExp ::
|
||||
forall m n r b.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Parser 'Input n [(IR.StreamCursorItem b)])
|
||||
tableStreamCursorExp sourceName tableInfo =
|
||||
memoizeOn 'tableStreamCursorExp (sourceName, tableInfoName tableInfo) $ do
|
||||
tableStreamCursorExp sourceInfo tableInfo =
|
||||
memoizeOn 'tableStreamCursorExp (_siName sourceInfo, tableInfoName tableInfo) $ do
|
||||
tCase <- asks getter
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
columnInfos <- tableSelectColumns sourceName tableInfo
|
||||
columnInfos <- tableSelectColumns sourceInfo tableInfo
|
||||
objName <- P.mkTypename $ tableGQLName <> applyTypeNameCaseCust tCase G.__stream_cursor_input
|
||||
let description =
|
||||
G.Description $ "Streaming cursor of the table " <>> tableGQLName
|
||||
columnParsers <- tableStreamColumnArg sourceName tableGQLName columnInfos
|
||||
columnParsers <- tableStreamColumnArg sourceInfo tableGQLName columnInfos
|
||||
pure $ P.object objName (Just description) columnParsers
|
||||
|
||||
-- | Argument to accept the cursor input object.
|
||||
@ -195,11 +195,11 @@ tableStreamCursorExp sourceName tableInfo =
|
||||
tableStreamCursorArg ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (InputFieldsParser n [IR.StreamCursorItem b])
|
||||
tableStreamCursorArg sourceName tableInfo = do
|
||||
cursorParser <- tableStreamCursorExp sourceName tableInfo
|
||||
tableStreamCursorArg sourceInfo tableInfo = do
|
||||
cursorParser <- tableStreamCursorExp sourceInfo tableInfo
|
||||
pure $ do
|
||||
cursorArgs <-
|
||||
P.field cursorName cursorDesc $ P.list $ P.nullable cursorParser
|
||||
@ -213,13 +213,13 @@ tableStreamCursorArg sourceName tableInfo = do
|
||||
tableStreamArguments ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (InputFieldsParser n (SelectStreamArgs b))
|
||||
tableStreamArguments sourceName tableInfo = do
|
||||
tableStreamArguments sourceInfo tableInfo = do
|
||||
tCase <- asks getter
|
||||
whereParser <- tableWhereArg sourceName tableInfo
|
||||
cursorParser <- tableStreamCursorArg sourceName tableInfo
|
||||
whereParser <- tableWhereArg sourceInfo tableInfo
|
||||
cursorParser <- tableStreamCursorArg sourceInfo tableInfo
|
||||
pure $ do
|
||||
whereArg <- whereParser
|
||||
cursorArg <-
|
||||
@ -235,7 +235,7 @@ tableStreamArguments sourceName tableInfo = do
|
||||
selectStreamTable ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | table info
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -243,14 +243,14 @@ selectStreamTable ::
|
||||
-- | field description, if any
|
||||
Maybe G.Description ->
|
||||
m (Maybe (P.FieldParser n (StreamSelectExp b)))
|
||||
selectStreamTable sourceName tableInfo fieldName description = runMaybeT $ do
|
||||
selectStreamTable sourceInfo tableInfo fieldName description = runMaybeT $ do
|
||||
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
|
||||
xStreamSubscription <- hoistMaybe $ streamSubscriptionExtension @b
|
||||
stringifyNum <- asks $ qcStringifyNum . getter
|
||||
tableStreamArgsParser <- lift $ tableStreamArguments sourceName tableInfo
|
||||
selectionSetParser <- MaybeT $ tableSelectionList sourceName tableInfo
|
||||
stringifyNum <- retrieve soStringifyNum
|
||||
tableStreamArgsParser <- lift $ tableStreamArguments sourceInfo tableInfo
|
||||
selectionSetParser <- MaybeT $ tableSelectionList sourceInfo tableInfo
|
||||
lift $
|
||||
memoizeOn 'selectStreamTable (sourceName, tableName, fieldName) $ do
|
||||
memoizeOn 'selectStreamTable (_siName sourceInfo, tableName, fieldName) $ do
|
||||
pure $
|
||||
P.subselection fieldName description tableStreamArgsParser selectionSetParser
|
||||
<&> \(args, fields) ->
|
||||
|
@ -28,7 +28,6 @@ import Hasura.GraphQL.Schema.Common
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend
|
||||
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.SchemaCache hiding (askTableInfo)
|
||||
@ -85,12 +84,12 @@ getTableIdentifierName tableInfo =
|
||||
tableSelectColumnsEnum ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m (Maybe (Parser 'Both n (Column b)))
|
||||
tableSelectColumnsEnum sourceName tableInfo = do
|
||||
tableSelectColumnsEnum sourceInfo tableInfo = do
|
||||
tableGQLName <- getTableGQLName @b tableInfo
|
||||
columns <- tableSelectColumns sourceName tableInfo
|
||||
columns <- tableSelectColumns sourceInfo tableInfo
|
||||
enumName <- P.mkTypename $ tableGQLName <> G.__select_column
|
||||
let description =
|
||||
Just $
|
||||
@ -173,13 +172,12 @@ tableSelectFields ::
|
||||
( Backend b,
|
||||
MonadError QErr m,
|
||||
MonadReader r m,
|
||||
Has SourceCache r,
|
||||
Has RoleName r
|
||||
) =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m [FieldInfo b]
|
||||
tableSelectFields sourceName tableInfo = do
|
||||
tableSelectFields sourceInfo tableInfo = do
|
||||
let tableFields = _tciFieldInfoMap . _tiCoreInfo $ tableInfo
|
||||
permissions <- tableSelectPermissions tableInfo
|
||||
filterM (canBeSelected permissions) $ Map.elems tableFields
|
||||
@ -188,14 +186,14 @@ tableSelectFields sourceName tableInfo = do
|
||||
canBeSelected (Just permissions) (FIColumn columnInfo) =
|
||||
pure $ Map.member (ciColumn columnInfo) (spiCols permissions)
|
||||
canBeSelected _ (FIRelationship relationshipInfo) = do
|
||||
tableInfo' <- askTableInfo sourceName $ riRTable relationshipInfo
|
||||
tableInfo' <- askTableInfo sourceInfo $ riRTable relationshipInfo
|
||||
isJust <$> tableSelectPermissions @b tableInfo'
|
||||
canBeSelected (Just permissions) (FIComputedField computedFieldInfo) =
|
||||
case computedFieldReturnType @b (_cfiReturnType computedFieldInfo) of
|
||||
ReturnsScalar _ ->
|
||||
pure $ Map.member (_cfiName computedFieldInfo) $ spiScalarComputedFields permissions
|
||||
ReturnsTable tableName -> do
|
||||
tableInfo' <- askTableInfo sourceName tableName
|
||||
tableInfo' <- askTableInfo sourceInfo tableName
|
||||
isJust <$> tableSelectPermissions @b tableInfo'
|
||||
ReturnsOthers -> pure False
|
||||
canBeSelected _ (FIRemoteRelationship _) = pure True
|
||||
@ -215,14 +213,13 @@ tableSelectColumns ::
|
||||
( Backend b,
|
||||
MonadError QErr m,
|
||||
MonadReader r m,
|
||||
Has SourceCache r,
|
||||
Has RoleName r
|
||||
) =>
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
TableInfo b ->
|
||||
m [ColumnInfo b]
|
||||
tableSelectColumns sourceName tableInfo =
|
||||
mapMaybe columnInfo <$> tableSelectFields sourceName tableInfo
|
||||
tableSelectColumns sourceInfo tableInfo =
|
||||
mapMaybe columnInfo <$> tableSelectFields sourceInfo tableInfo
|
||||
where
|
||||
columnInfo (FIColumn ci) = Just ci
|
||||
columnInfo _ = Nothing
|
||||
|
@ -35,7 +35,7 @@ import Hasura.RQL.IR.Root (RemoteRelationshipField)
|
||||
import Hasura.RQL.IR.Update (AnnotatedUpdateG (..))
|
||||
import Hasura.RQL.Types.Backend (Backend (..))
|
||||
import Hasura.RQL.Types.Column (ColumnInfo (..), isNumCol)
|
||||
import Hasura.RQL.Types.Common (SourceName)
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization (NamingCase)
|
||||
import Hasura.RQL.Types.Table
|
||||
import Language.GraphQL.Draft.Syntax (Description (..), Name (..), Nullability (..), litName)
|
||||
@ -264,7 +264,7 @@ updateTable ::
|
||||
-- | backend-specific data needed to perform an update mutation
|
||||
P.InputFieldsParser n (BackendUpdate b (P.UnpreparedValue b)) ->
|
||||
-- | table source
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | table info
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -272,7 +272,7 @@ updateTable ::
|
||||
-- | field description, if any
|
||||
Maybe Description ->
|
||||
m (Maybe (P.FieldParser n (AnnotatedUpdateG b (RemoteRelationshipField P.UnpreparedValue) (P.UnpreparedValue b))))
|
||||
updateTable backendUpdate sourceName tableInfo fieldName description = runMaybeT do
|
||||
updateTable backendUpdate sourceInfo tableInfo fieldName description = runMaybeT do
|
||||
let tableName = tableInfoName tableInfo
|
||||
columns = tableColumns tableInfo
|
||||
whereName = $$(litName "where")
|
||||
@ -280,8 +280,8 @@ updateTable backendUpdate sourceName tableInfo fieldName description = runMaybeT
|
||||
viewInfo = _tciViewInfo $ _tiCoreInfo tableInfo
|
||||
guard $ isMutable viIsUpdatable viewInfo
|
||||
updatePerms <- MaybeT $ _permUpd <$> tablePermissions tableInfo
|
||||
whereArg <- lift $ P.field whereName (Just whereDesc) <$> boolExp sourceName tableInfo
|
||||
selection <- lift $ mutationSelectionSet sourceName tableInfo
|
||||
whereArg <- lift $ P.field whereName (Just whereDesc) <$> boolExp sourceInfo tableInfo
|
||||
selection <- lift $ mutationSelectionSet sourceInfo tableInfo
|
||||
let argsParser = liftA2 (,) backendUpdate whereArg
|
||||
pure $
|
||||
P.subselection fieldName description argsParser selection
|
||||
@ -297,7 +297,7 @@ updateTableByPk ::
|
||||
-- | backend-specific data needed to perform an update mutation
|
||||
P.InputFieldsParser n (BackendUpdate b (P.UnpreparedValue b)) ->
|
||||
-- | table source
|
||||
SourceName ->
|
||||
SourceInfo b ->
|
||||
-- | table info
|
||||
TableInfo b ->
|
||||
-- | field display name
|
||||
@ -305,14 +305,14 @@ updateTableByPk ::
|
||||
-- | field description, if any
|
||||
Maybe Description ->
|
||||
m (Maybe (P.FieldParser n (AnnotatedUpdateG b (RemoteRelationshipField P.UnpreparedValue) (P.UnpreparedValue b))))
|
||||
updateTableByPk backendUpdate sourceName tableInfo fieldName description = runMaybeT $ do
|
||||
updateTableByPk backendUpdate sourceInfo tableInfo fieldName description = runMaybeT $ do
|
||||
let columns = tableColumns tableInfo
|
||||
tableName = tableInfoName tableInfo
|
||||
viewInfo = _tciViewInfo $ _tiCoreInfo tableInfo
|
||||
guard $ isMutable viIsUpdatable viewInfo
|
||||
updatePerms <- MaybeT $ _permUpd <$> tablePermissions tableInfo
|
||||
pkArgs <- MaybeT $ primaryKeysArguments tableInfo
|
||||
selection <- MaybeT $ tableSelectionSet sourceName tableInfo
|
||||
selection <- MaybeT $ tableSelectionSet sourceInfo tableInfo
|
||||
lift $ do
|
||||
tableGQLName <- getTableGQLName tableInfo
|
||||
pkObjectName <- P.mkTypename $ tableGQLName <> $$(litName "_pk_columns_input")
|
||||
|
@ -17,7 +17,7 @@ import Hasura.GraphQL.Namespace
|
||||
import Hasura.GraphQL.Parser.Column (UnpreparedValue)
|
||||
import Hasura.GraphQL.Parser.Constants qualified as G
|
||||
import Hasura.GraphQL.Parser.Internal.Parser qualified as P
|
||||
import Hasura.GraphQL.Parser.Monad
|
||||
import Hasura.GraphQL.Parser.Monad (runSchemaT)
|
||||
import Hasura.GraphQL.Parser.Schema
|
||||
import Hasura.GraphQL.Parser.TestUtils
|
||||
import Hasura.GraphQL.Schema.Common
|
||||
@ -28,7 +28,6 @@ import Hasura.RQL.IR.Root
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.RemoteSchema
|
||||
import Hasura.RQL.Types.SchemaCache
|
||||
import Hasura.RQL.Types.Source
|
||||
import Hasura.RQL.Types.SourceCustomization
|
||||
import Hasura.Session
|
||||
import Language.GraphQL.Draft.Parser qualified as G
|
||||
@ -117,19 +116,20 @@ buildQueryParsers introspection = do
|
||||
-- schema. Here, since there are no relationships to a source in this
|
||||
-- test, we are free to give 'undefined' for such fields, as they won't be
|
||||
-- evaluated.
|
||||
sourceContext =
|
||||
schemaInfo =
|
||||
( adminRoleName :: RoleName,
|
||||
undefined :: SourceCache,
|
||||
undefined :: QueryContext,
|
||||
mempty :: CustomizeRemoteFieldName,
|
||||
mempty :: RemoteSchemaMap,
|
||||
mempty :: MkTypename,
|
||||
mempty :: MkRootFieldName,
|
||||
HasuraCase :: NamingCase
|
||||
HasuraCase :: NamingCase,
|
||||
undefined :: SchemaOptions,
|
||||
SchemaContext
|
||||
mempty
|
||||
ignoreRemoteRelationship
|
||||
)
|
||||
RemoteSchemaParser query _ _ <-
|
||||
runError $
|
||||
flip runReaderT sourceContext $
|
||||
flip runReaderT schemaInfo $
|
||||
runSchemaT $
|
||||
buildRemoteParser introResult remoteSchemaRels remoteSchemaInfo
|
||||
pure $
|
||||
|
@ -23,8 +23,9 @@ import Hasura.RQL.IR.BoolExp (AnnBoolExpFld (..), GBoolExp (..), PartialSQLExp (
|
||||
import Hasura.RQL.IR.Root (RemoteRelationshipField)
|
||||
import Hasura.RQL.IR.Update (AnnotatedUpdateG (..))
|
||||
import Hasura.RQL.Types.Column (ColumnInfo (..), ColumnMutability (..), ColumnType (..))
|
||||
import Hasura.RQL.Types.Common (Comment (..), FieldName (..), SourceName, SystemDefined (..))
|
||||
import Hasura.RQL.Types.Common (Comment (..), FieldName (..), SystemDefined (..))
|
||||
import Hasura.RQL.Types.Instances ()
|
||||
import Hasura.RQL.Types.Source (SourceInfo)
|
||||
import Hasura.RQL.Types.Table (CustomRootField (..), FieldInfo (..), RolePermInfo (..), SelPermInfo (..), TableConfig (..), TableCoreInfoG (..), TableCustomRootFields (..), TableInfo (..), UpdPermInfo (..))
|
||||
import Hasura.SQL.Backend (BackendType (Postgres), PostgresKind (Vanilla))
|
||||
import Language.GraphQL.Draft.Syntax (unsafeMkName)
|
||||
@ -85,7 +86,7 @@ mkParser :: QualifiedTable -> [ColumnInfoBuilder] -> SchemaTestT [Parser]
|
||||
mkParser table cib =
|
||||
Build.buildTableUpdateMutationFields
|
||||
backendUpdateParser
|
||||
sourceName
|
||||
sourceInfo
|
||||
table
|
||||
tableInfo
|
||||
name
|
||||
@ -114,8 +115,8 @@ mkParser table cib =
|
||||
upiFilter = BoolAnd $ fmap (\ci -> BoolFld $ AVColumn ci []) columnInfos
|
||||
|
||||
------------------------------------------
|
||||
sourceName :: SourceName
|
||||
sourceName = undefined
|
||||
sourceInfo :: SourceInfo PG
|
||||
sourceInfo = undefined
|
||||
|
||||
------------------------------------------
|
||||
tableInfo :: TableInfo PG
|
||||
|
@ -18,13 +18,11 @@ import Hasura.Base.Error (Code, QErr)
|
||||
import Hasura.GraphQL.Execute.Types (GraphQLQueryType (..))
|
||||
import Hasura.GraphQL.Parser.Class (MonadParse (..), MonadSchema (..))
|
||||
import Hasura.GraphQL.Parser.Schema (MkTypename (..))
|
||||
import Hasura.GraphQL.Schema.Common (QueryContext (..))
|
||||
import Hasura.GraphQL.Schema.Common (SchemaContext (..), SchemaOptions (..), ignoreRemoteRelationship)
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Common (StringifyNumbers (LeaveNumbersAlone))
|
||||
import Hasura.RQL.Types.Function (FunctionPermissionsCtx (..))
|
||||
import Hasura.RQL.Types.RemoteSchema (RemoteSchemaPermsCtx (..))
|
||||
import Hasura.RQL.Types.SchemaCache (RemoteSchemaMap)
|
||||
import Hasura.RQL.Types.Source (SourceCache)
|
||||
import Hasura.RQL.Types.SourceCustomization (CustomizeRemoteFieldName, MkRootFieldName, NamingCase (..))
|
||||
import Hasura.Session (RoleName, adminRoleName)
|
||||
import Language.Haskell.TH.Syntax qualified as TH
|
||||
@ -52,20 +50,6 @@ instance Has NamingCase SchemaEnvironment where
|
||||
modifier :: (NamingCase -> NamingCase) -> SchemaEnvironment -> SchemaEnvironment
|
||||
modifier = notImplemented "modifier<Has NamingCase SchemaEnvironment>"
|
||||
|
||||
instance Has SourceCache SchemaEnvironment where
|
||||
getter :: SchemaEnvironment -> SourceCache
|
||||
getter = notImplemented "getter<Has SourceCache SchemaEnvironment>"
|
||||
|
||||
modifier :: (SourceCache -> SourceCache) -> SchemaEnvironment -> SchemaEnvironment
|
||||
modifier = notImplemented "modifier<Has SourceCache SchemaEnvironment>"
|
||||
|
||||
instance Has RemoteSchemaMap SchemaEnvironment where
|
||||
getter :: SchemaEnvironment -> RemoteSchemaMap
|
||||
getter = notImplemented "getter<Has RemoteSchemaMap SchemaEnvironment>"
|
||||
|
||||
modifier :: (RemoteSchemaMap -> RemoteSchemaMap) -> SchemaEnvironment -> SchemaEnvironment
|
||||
modifier = notImplemented "modifier<Has RemoteSchemaMap SchemaEnvironment>"
|
||||
|
||||
instance Has RoleName SchemaEnvironment where
|
||||
getter :: SchemaEnvironment -> RoleName
|
||||
getter = const adminRoleName
|
||||
@ -73,23 +57,33 @@ instance Has RoleName SchemaEnvironment where
|
||||
modifier :: (RoleName -> RoleName) -> SchemaEnvironment -> SchemaEnvironment
|
||||
modifier = notImplemented "modifier<Has RoleName SchemaEnvironment>"
|
||||
|
||||
queryContext :: QueryContext
|
||||
queryContext =
|
||||
QueryContext
|
||||
{ qcStringifyNum = LeaveNumbersAlone,
|
||||
qcDangerousBooleanCollapse = False,
|
||||
qcQueryType = QueryHasura,
|
||||
qcFunctionPermsContext = FunctionPermissionsInferred,
|
||||
qcRemoteSchemaPermsCtx = RemoteSchemaPermsDisabled,
|
||||
qcOptimizePermissionFilters = False
|
||||
}
|
||||
instance Has SchemaOptions SchemaEnvironment where
|
||||
getter :: SchemaEnvironment -> SchemaOptions
|
||||
getter =
|
||||
const
|
||||
SchemaOptions
|
||||
{ soStringifyNum = LeaveNumbersAlone,
|
||||
soDangerousBooleanCollapse = False,
|
||||
soQueryType = QueryHasura,
|
||||
soFunctionPermsContext = FunctionPermissionsInferred,
|
||||
soRemoteSchemaPermsCtx = RemoteSchemaPermsDisabled,
|
||||
soOptimizePermissionFilters = False
|
||||
}
|
||||
|
||||
instance Has QueryContext SchemaEnvironment where
|
||||
getter :: SchemaEnvironment -> QueryContext
|
||||
getter = const queryContext
|
||||
modifier :: (SchemaOptions -> SchemaOptions) -> SchemaEnvironment -> SchemaEnvironment
|
||||
modifier = notImplemented "modifier<Has SchemaOptions SchemaEnvironment>"
|
||||
|
||||
modifier :: (QueryContext -> QueryContext) -> SchemaEnvironment -> SchemaEnvironment
|
||||
modifier = notImplemented "modifier<Has QueryContext SchemaEnvironment>"
|
||||
instance Has SchemaContext SchemaEnvironment where
|
||||
getter :: SchemaEnvironment -> SchemaContext
|
||||
getter =
|
||||
const
|
||||
SchemaContext
|
||||
{ scSourceCache = notImplemented "scSourceCache",
|
||||
scRemoteRelationshipParserBuilder = ignoreRemoteRelationship
|
||||
}
|
||||
|
||||
modifier :: (SchemaContext -> SchemaContext) -> SchemaEnvironment -> SchemaEnvironment
|
||||
modifier = notImplemented "modifier<Has SchemaContext SchemaEnvironment>"
|
||||
|
||||
instance Has MkTypename SchemaEnvironment where
|
||||
getter :: SchemaEnvironment -> MkTypename
|
||||
|
Loading…
Reference in New Issue
Block a user