From 4b0f5f09c94482caec2619e772cbb06b0a3b647a Mon Sep 17 00:00:00 2001 From: Evie Ciobanu Date: Mon, 26 Jul 2021 16:03:51 +0300 Subject: [PATCH] server: add IR support for DB-to-DB joins GJ IR changes cherry-picked from the original GJ branch. There is a separate (can be merged independently) PR for metadata changes (#1727) and there will be a different PR upcoming PR for execution changes. https://github.com/hasura/graphql-engine-mono/pull/1810 Co-authored-by: Vamshi Surabhi <6562944+0x777@users.noreply.github.com> GitOrigin-RevId: c31956af29dc9c9b75d002aba7d93c230697c5f4 --- .../Hasura/Backends/BigQuery/FromIr.hs | 11 ---- .../Backends/BigQuery/Instances/Schema.hs | 14 ++--- .../src-lib/Hasura/Backends/MSSQL/FromIr.hs | 12 ---- .../Hasura/Backends/MSSQL/Instances/Schema.hs | 14 ++--- .../Hasura/Backends/MySQL/Instances/Schema.hs | 14 ++--- .../Backends/Postgres/Instances/Schema.hs | 8 +-- .../Backends/Postgres/Translate/Select.hs | 7 --- server/src-lib/Hasura/GraphQL/Context.hs | 4 +- server/src-lib/Hasura/GraphQL/Execute.hs | 4 +- .../Hasura/GraphQL/Execute/Mutation.hs | 4 +- .../src-lib/Hasura/GraphQL/Execute/Query.hs | 6 +- .../GraphQL/Execute/RemoteJoin/Collect.hs | 63 ++++++++++--------- server/src-lib/Hasura/GraphQL/Explain.hs | 2 +- server/src-lib/Hasura/GraphQL/Schema.hs | 56 ++++++++--------- .../src-lib/Hasura/GraphQL/Schema/Action.hs | 10 +-- .../src-lib/Hasura/GraphQL/Schema/Backend.hs | 16 ++--- server/src-lib/Hasura/GraphQL/Schema/Build.hs | 12 ++-- .../src-lib/Hasura/GraphQL/Schema/Common.hs | 16 ++--- .../src-lib/Hasura/GraphQL/Schema/Mutation.hs | 23 +++---- .../src-lib/Hasura/GraphQL/Schema/Postgres.hs | 7 +-- .../src-lib/Hasura/GraphQL/Schema/Select.hs | 8 +-- .../src-lib/Hasura/GraphQL/Transport/HTTP.hs | 2 +- server/src-lib/Hasura/RQL/IR/Root.hs | 13 +++- server/src-lib/Hasura/RQL/IR/Select.hs | 58 +++++++++++++---- 24 files changed, 200 insertions(+), 184 deletions(-) diff --git a/server/src-lib/Hasura/Backends/BigQuery/FromIr.hs b/server/src-lib/Hasura/Backends/BigQuery/FromIr.hs index 33c604ae1df..479de0a0ee1 100644 --- a/server/src-lib/Hasura/Backends/BigQuery/FromIr.hs +++ b/server/src-lib/Hasura/Backends/BigQuery/FromIr.hs @@ -791,17 +791,6 @@ fromAnnFieldsG existingJoins stringifyNumbers (Rql.FieldName name, field) = (\aliasedThing -> JoinFieldSource (Aliased {aliasedThing, aliasedAlias = name})) (fromArraySelectG arraySelectG) - -- this will be gone once the code which collects remote joins from the IR - -- emits a modified IR where remote relationships can't be reached - Ir.AFRemote _ -> - pure - (ExpressionFieldSource - Aliased - { aliasedThing = BigQuery.ValueExpression (StringValue "null: remote field selected") - , aliasedAlias = name - }) - -- TODO: implement this - Ir.AFDBRemote _ -> error "FIXME" -- | Here is where we project a field as a column expression. If diff --git a/server/src-lib/Hasura/Backends/BigQuery/Instances/Schema.hs b/server/src-lib/Hasura/Backends/BigQuery/Instances/Schema.hs index 7ad2536fd77..c4c6f83e4bb 100644 --- a/server/src-lib/Hasura/Backends/BigQuery/Instances/Schema.hs +++ b/server/src-lib/Hasura/Backends/BigQuery/Instances/Schema.hs @@ -77,7 +77,7 @@ bqBuildTableRelayQueryFields -> G.Name -> NESeq (ColumnInfo 'BigQuery) -> SelPermInfo 'BigQuery - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] bqBuildTableRelayQueryFields _sourceName _sourceInfo _tableName _tableInfo _gqlName _pkeyColumns _selPerms = pure [] @@ -91,7 +91,7 @@ bqBuildTableInsertMutationFields -> InsPermInfo 'BigQuery -> Maybe (SelPermInfo 'BigQuery) -> Maybe (UpdPermInfo 'BigQuery) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] bqBuildTableInsertMutationFields _sourceName _sourceInfo _tableName _tableInfo _gqlName _insPerms _selPerms _updPerms = pure [] @@ -104,7 +104,7 @@ bqBuildTableUpdateMutationFields -> G.Name -> UpdPermInfo 'BigQuery -> Maybe (SelPermInfo 'BigQuery) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] bqBuildTableUpdateMutationFields _sourceName _sourceInfo _tableName _tableInfo _gqlName _updPerns _selPerms = pure [] @@ -117,7 +117,7 @@ bqBuildTableDeleteMutationFields -> G.Name -> DelPermInfo 'BigQuery -> Maybe (SelPermInfo 'BigQuery) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] bqBuildTableDeleteMutationFields _sourceName _sourceInfo _tableName _tableInfo _gqlName _delPerns _selPerms = pure [] @@ -129,7 +129,7 @@ bqBuildFunctionQueryFields -> FunctionInfo 'BigQuery -> TableName 'BigQuery -> SelPermInfo 'BigQuery - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] bqBuildFunctionQueryFields _ _ _ _ _ _ = pure [] @@ -142,7 +142,7 @@ bqBuildFunctionRelayQueryFields -> TableName 'BigQuery -> NESeq (ColumnInfo 'BigQuery) -> SelPermInfo 'BigQuery - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] bqBuildFunctionRelayQueryFields _sourceName _sourceInfo _functionName _functionInfo _tableName _pkeyColumns _selPerms = pure [] @@ -154,7 +154,7 @@ bqBuildFunctionMutationFields -> FunctionInfo 'BigQuery -> TableName 'BigQuery -> SelPermInfo 'BigQuery - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] bqBuildFunctionMutationFields _ _ _ _ _ _ = pure [] diff --git a/server/src-lib/Hasura/Backends/MSSQL/FromIr.hs b/server/src-lib/Hasura/Backends/MSSQL/FromIr.hs index 718c61aaa61..7cf4695a971 100644 --- a/server/src-lib/Hasura/Backends/MSSQL/FromIr.hs +++ b/server/src-lib/Hasura/Backends/MSSQL/FromIr.hs @@ -727,18 +727,6 @@ fromAnnFieldsG existingJoins stringifyNumbers (IR.FieldName name, field) = (\aliasedThing -> JoinFieldSource (Aliased {aliasedThing, aliasedAlias = name})) (fromArraySelectG arraySelectG) - -- this will be gone once the code which collects remote joins from the IR - -- emits a modified IR where remote relationships can't be reached - IR.AFRemote _ -> - pure - (ExpressionFieldSource - Aliased - { aliasedThing = TSQL.ValueExpression - (ODBC.TextValue "null: remote field selected") - , aliasedAlias = name - }) - -- TODO: implement this - IR.AFDBRemote _ -> error "FIXME" -- | Here is where we project a field as a column expression. If -- number stringification is on, then we wrap it in a diff --git a/server/src-lib/Hasura/Backends/MSSQL/Instances/Schema.hs b/server/src-lib/Hasura/Backends/MSSQL/Instances/Schema.hs index 655e27f23cd..931cf2b9644 100644 --- a/server/src-lib/Hasura/Backends/MSSQL/Instances/Schema.hs +++ b/server/src-lib/Hasura/Backends/MSSQL/Instances/Schema.hs @@ -79,7 +79,7 @@ msBuildTableRelayQueryFields -> G.Name -> NESeq (ColumnInfo 'MSSQL) -> SelPermInfo 'MSSQL - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] msBuildTableRelayQueryFields _sourceName _sourceInfo _tableName _tableInfo _gqlName _pkeyColumns _selPerms = pure [] @@ -93,7 +93,7 @@ msBuildTableInsertMutationFields -> InsPermInfo 'MSSQL -> Maybe (SelPermInfo 'MSSQL) -> Maybe (UpdPermInfo 'MSSQL) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] msBuildTableInsertMutationFields _sourceName _sourceInfo _tableName _tableInfo _gqlName _insPerms _selPerms _updPerms = pure [] @@ -106,7 +106,7 @@ msBuildTableUpdateMutationFields -> G.Name -> UpdPermInfo 'MSSQL -> Maybe (SelPermInfo 'MSSQL) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] msBuildTableUpdateMutationFields _sourceName _sourceInfo _tableName _tableInfo _gqlName _updPerns _selPerms = pure [] @@ -119,7 +119,7 @@ msBuildTableDeleteMutationFields -> G.Name -> DelPermInfo 'MSSQL -> Maybe (SelPermInfo 'MSSQL) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] msBuildTableDeleteMutationFields _sourceName _sourceInfo _tableName _tableInfo _gqlName _delPerns _selPerms = pure [] @@ -131,7 +131,7 @@ msBuildFunctionQueryFields -> FunctionInfo 'MSSQL -> TableName 'MSSQL -> SelPermInfo 'MSSQL - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] msBuildFunctionQueryFields _ _ _ _ _ _ = pure [] @@ -144,7 +144,7 @@ msBuildFunctionRelayQueryFields -> TableName 'MSSQL -> NESeq (ColumnInfo 'MSSQL) -> SelPermInfo 'MSSQL - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] msBuildFunctionRelayQueryFields _sourceName _sourceInfo _functionName _functionInfo _tableName _pkeyColumns _selPerms = pure [] @@ -156,7 +156,7 @@ msBuildFunctionMutationFields -> FunctionInfo 'MSSQL -> TableName 'MSSQL -> SelPermInfo 'MSSQL - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] msBuildFunctionMutationFields _ _ _ _ _ _ = pure [] diff --git a/server/src-lib/Hasura/Backends/MySQL/Instances/Schema.hs b/server/src-lib/Hasura/Backends/MySQL/Instances/Schema.hs index bebd27eaee5..6e00e9a84bf 100644 --- a/server/src-lib/Hasura/Backends/MySQL/Instances/Schema.hs +++ b/server/src-lib/Hasura/Backends/MySQL/Instances/Schema.hs @@ -79,7 +79,7 @@ buildTableRelayQueryFields' :: G.Name -> NESeq (ColumnInfo 'MySQL) -> SelPermInfo 'MySQL -> - m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + m [FieldParser n (QueryRootField UnpreparedValue)] buildTableRelayQueryFields' _sourceName _sourceInfo _tableName _tableInfo _gqlName _pkeyColumns _selPerms = pure [] @@ -94,7 +94,7 @@ buildTableInsertMutationFields' :: InsPermInfo 'MySQL -> Maybe (SelPermInfo 'MySQL) -> Maybe (UpdPermInfo 'MySQL) -> - m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + m [FieldParser n (MutationRootField UnpreparedValue)] buildTableInsertMutationFields' _sourceName _sourceInfo _tableName _tableInfo _gqlName _insPerms _selPerms _updPerms = pure [] @@ -108,7 +108,7 @@ buildTableUpdateMutationFields' :: G.Name -> UpdPermInfo 'MySQL -> Maybe (SelPermInfo 'MySQL) -> - m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + m [FieldParser n (MutationRootField UnpreparedValue)] buildTableUpdateMutationFields' _sourceName _sourceInfo _tableName _tableInfo _gqlName _updPerns _selPerms = pure [] @@ -122,7 +122,7 @@ buildTableDeleteMutationFields' :: G.Name -> DelPermInfo 'MySQL -> Maybe (SelPermInfo 'MySQL) -> - m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + m [FieldParser n (MutationRootField UnpreparedValue)] buildTableDeleteMutationFields' _sourceName _sourceInfo _tableName _tableInfo _gqlName _delPerns _selPerms = pure [] @@ -135,7 +135,7 @@ buildFunctionQueryFields' :: FunctionInfo 'MySQL -> RQL.TableName 'MySQL -> SelPermInfo 'MySQL -> - m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + m [FieldParser n (QueryRootField UnpreparedValue)] buildFunctionQueryFields' _ _ _ _ _ _ = pure [] @@ -149,7 +149,7 @@ buildFunctionRelayQueryFields' :: RQL.TableName 'MySQL -> NESeq (ColumnInfo 'MySQL) -> SelPermInfo 'MySQL -> - m [(FieldParser n (QueryRootField UnpreparedValue UnpreparedValue))] + m [FieldParser n (QueryRootField UnpreparedValue)] buildFunctionRelayQueryFields' _sourceName _sourceInfo _functionName _functionInfo _tableName _pkeyColumns _selPerms = pure [] @@ -162,7 +162,7 @@ buildFunctionMutationFields' :: FunctionInfo 'MySQL -> RQL.TableName 'MySQL -> SelPermInfo 'MySQL -> - m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + m [FieldParser n (MutationRootField UnpreparedValue)] buildFunctionMutationFields' _ _ _ _ _ _ = pure [] diff --git a/server/src-lib/Hasura/Backends/Postgres/Instances/Schema.hs b/server/src-lib/Hasura/Backends/Postgres/Instances/Schema.hs index b986cb3cf3c..a0b972421e1 100644 --- a/server/src-lib/Hasura/Backends/Postgres/Instances/Schema.hs +++ b/server/src-lib/Hasura/Backends/Postgres/Instances/Schema.hs @@ -67,7 +67,7 @@ class PostgresSchema (pgKind :: PostgresKind) where -> G.Name -> NESeq (ColumnInfo ('Postgres pgKind)) -> SelPermInfo ('Postgres pgKind) - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] pgkBuildFunctionRelayQueryFields :: BS.MonadBuildSchema ('Postgres pgKind) r m n => SourceName @@ -77,7 +77,7 @@ class PostgresSchema (pgKind :: PostgresKind) where -> TableName ('Postgres pgKind) -> NESeq (ColumnInfo ('Postgres pgKind)) -> SelPermInfo ('Postgres pgKind) - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] pgkRelayExtension :: Maybe (XRelay ('Postgres pgKind)) pgkNode @@ -161,7 +161,7 @@ buildTableRelayQueryFields -> G.Name -> NESeq (ColumnInfo ('Postgres pgKind)) -> SelPermInfo ('Postgres pgKind) - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] buildTableRelayQueryFields sourceName sourceInfo tableName tableInfo gqlName pkeyColumns selPerms = do let mkRF = RFDB sourceName @@ -184,7 +184,7 @@ buildFunctionRelayQueryFields -> TableName ('Postgres pgKind) -> NESeq (ColumnInfo ('Postgres pgKind)) -> SelPermInfo ('Postgres pgKind) - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] buildFunctionRelayQueryFields sourceName sourceInfo functionName functionInfo tableName pkeyColumns selPerms = do funcName <- functionGraphQLName @('Postgres pgKind) functionName `onLeft` throwError let diff --git a/server/src-lib/Hasura/Backends/Postgres/Translate/Select.hs b/server/src-lib/Hasura/Backends/Postgres/Translate/Select.hs index ab0716ea04d..aa9c30f1ec3 100644 --- a/server/src-lib/Hasura/Backends/Postgres/Translate/Select.hs +++ b/server/src-lib/Hasura/Backends/Postgres/Translate/Select.hs @@ -876,10 +876,6 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields = do AFColumn c -> toSQLCol c - -- this will be gone once the code which collects remote joins from the IR - -- emits a modified IR where remote relationships can't be reached - AFRemote _ -> pure $ S.SELit "null: remote field selected" - AFObjectRelation objSel -> withWriteObjectRelation $ do let AnnRelationSelectG relName relMapping annObjSel = objSel AnnObjectSelectG objAnnFields tableFrom tableFilter = annObjSel @@ -928,9 +924,6 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields = do , S.mkQIdenExp computedFieldSourcePrefix fieldName ) - -- TODO: implement this - AFDBRemote _ -> error "FIXME" - pure $ annRowToJson @pgKind fieldAlias fieldExps diff --git a/server/src-lib/Hasura/GraphQL/Context.hs b/server/src-lib/Hasura/GraphQL/Context.hs index 162c5671e63..0ee978ef68a 100644 --- a/server/src-lib/Hasura/GraphQL/Context.hs +++ b/server/src-lib/Hasura/GraphQL/Context.hs @@ -30,8 +30,8 @@ data RoleContext a $(deriveToJSON hasuraJSON ''RoleContext) data GQLContext = GQLContext - { gqlQueryParser :: ParserFn (InsOrdHashMap G.Name (IR.QueryRootField UnpreparedValue UnpreparedValue)) - , gqlMutationParser :: Maybe (ParserFn (InsOrdHashMap G.Name (IR.MutationRootField UnpreparedValue UnpreparedValue))) + { gqlQueryParser :: ParserFn (InsOrdHashMap G.Name (IR.QueryRootField UnpreparedValue)) + , gqlMutationParser :: Maybe (ParserFn (InsOrdHashMap G.Name (IR.MutationRootField UnpreparedValue))) } instance J.ToJSON GQLContext where diff --git a/server/src-lib/Hasura/GraphQL/Execute.hs b/server/src-lib/Hasura/GraphQL/Execute.hs index b3174ae54c1..5740ab8b62c 100644 --- a/server/src-lib/Hasura/GraphQL/Execute.hs +++ b/server/src-lib/Hasura/GraphQL/Execute.hs @@ -131,7 +131,7 @@ getExecPlanPartial userInfo sc queryType req = -- The graphql query is resolved into a sequence of execution operations data ResolvedExecutionPlan - = QueryExecutionPlan EB.ExecutionPlan [IR.QueryRootField UnpreparedValue UnpreparedValue] DirectiveMap + = QueryExecutionPlan EB.ExecutionPlan [IR.QueryRootField UnpreparedValue] DirectiveMap -- ^ query execution; remote schemas and introspection possible | MutationExecutionPlan EB.ExecutionPlan -- ^ mutation execution; only __typename introspection supported @@ -157,7 +157,7 @@ data SubscriptionExecution buildSubscriptionPlan :: (MonadError QErr m) => UserInfo - -> InsOrdHashMap G.Name (IR.QueryRootField UnpreparedValue UnpreparedValue) + -> InsOrdHashMap G.Name (IR.QueryRootField UnpreparedValue) -> m SubscriptionExecution buildSubscriptionPlan userInfo rootFields = do (onSourceFields, noRelationActionFields) <- foldlM go (mempty, mempty) (OMap.toList rootFields) diff --git a/server/src-lib/Hasura/GraphQL/Execute/Mutation.hs b/server/src-lib/Hasura/GraphQL/Execute/Mutation.hs index 2502ae10d58..76f93cc90d5 100644 --- a/server/src-lib/Hasura/GraphQL/Execute/Mutation.hs +++ b/server/src-lib/Hasura/GraphQL/Execute/Mutation.hs @@ -84,7 +84,7 @@ convertMutationSelectionSet env logger gqlContext SQLGenCtx{stringifyNum} userIn (resolvedDirectives, resolvedSelSet) <- resolveVariables varDefs (fromMaybe Map.empty varValsM) directives fields -- Parse the GraphQL query into the RQL AST (unpreparedQueries, _reusability) - :: (OMap.InsOrdHashMap G.Name (MutationRootField UnpreparedValue UnpreparedValue), QueryReusability) + :: (OMap.InsOrdHashMap G.Name (MutationRootField UnpreparedValue), QueryReusability) <-(mutationParser >>> (`onLeft` reportParseErrors)) resolvedSelSet -- Process directives on the mutation @@ -95,7 +95,7 @@ convertMutationSelectionSet env logger gqlContext SQLGenCtx{stringifyNum} userIn txs <- for unpreparedQueries \case RFDB sourceName exists -> AB.dispatchAnyBackend @BackendExecute exists - \(SourceConfigWith sourceConfig (MDBR db :: MutationDBRoot UnpreparedValue UnpreparedValue b)) -> do + \(SourceConfigWith (sourceConfig :: SourceConfig b) (MDBR db)) -> do let (noRelsDBAST, remoteJoins) = RJ.getRemoteJoinsMutationDB db dbStepInfo <- mkDBMutationPlan @b userInfo stringifyNum sourceName sourceConfig noRelsDBAST pure $ ExecStepDB [] (AB.mkAnyBackend dbStepInfo) remoteJoins diff --git a/server/src-lib/Hasura/GraphQL/Execute/Query.hs b/server/src-lib/Hasura/GraphQL/Execute/Query.hs index a67373d0f6d..6c3e476b081 100644 --- a/server/src-lib/Hasura/GraphQL/Execute/Query.hs +++ b/server/src-lib/Hasura/GraphQL/Execute/Query.hs @@ -41,7 +41,7 @@ parseGraphQLQuery -> Maybe (HashMap G.Name J.Value) -> [G.Directive G.Name] -> G.SelectionSet G.NoFragments G.Name - -> m ( InsOrdHashMap G.Name (QueryRootField UnpreparedValue UnpreparedValue) + -> m ( InsOrdHashMap G.Name (QueryRootField UnpreparedValue) , QueryReusability , [G.Directive Variable] , G.SelectionSet G.NoFragments Variable @@ -69,7 +69,7 @@ convertQuerySelSet -> [G.VariableDefinition] -> Maybe GH.VariableValues -> SetGraphqlIntrospectionOptions - -> m (ExecutionPlan, [QueryRootField UnpreparedValue UnpreparedValue], G.SelectionSet G.NoFragments Variable, DirectiveMap) + -> m (ExecutionPlan, [QueryRootField UnpreparedValue], G.SelectionSet G.NoFragments Variable, DirectiveMap) convertQuerySelSet env logger gqlContext userInfo manager reqHeaders directives fields varDefs varValsM introspectionDisabledRoles = do -- Parse the GraphQL query into the RQL AST @@ -86,7 +86,7 @@ convertQuerySelSet env logger gqlContext userInfo manager reqHeaders directives executionPlan <- for unpreparedQueries \case RFDB sourceName exists -> AB.dispatchAnyBackend @BackendExecute exists - \(SourceConfigWith sourceConfig (QDBR db :: QueryDBRoot UnpreparedValue UnpreparedValue b)) -> do + \(SourceConfigWith (sourceConfig :: (SourceConfig b)) (QDBR db)) -> do let (noRelsDBAST, remoteJoins) = RJ.getRemoteJoins db dbStepInfo <- mkDBQueryPlan @b userInfo sourceName sourceConfig noRelsDBAST pure $ ExecStepDB [] (AB.mkAnyBackend dbStepInfo) remoteJoins diff --git a/server/src-lib/Hasura/GraphQL/Execute/RemoteJoin/Collect.hs b/server/src-lib/Hasura/GraphQL/Execute/RemoteJoin/Collect.hs index 1962f08f517..1ef7eac5cb5 100644 --- a/server/src-lib/Hasura/GraphQL/Execute/RemoteJoin/Collect.hs +++ b/server/src-lib/Hasura/GraphQL/Execute/RemoteJoin/Collect.hs @@ -52,8 +52,8 @@ import Hasura.RQL.Types -- | Collects remote joins from the AST and also adds the necessary join fields getRemoteJoins - :: (Backend b) - => QueryDB b r (UnpreparedValue b) + :: Backend b + => QueryDB b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> (QueryDB b (Const Void) (UnpreparedValue b), Maybe RemoteJoins) getRemoteJoins = \case QDBMultipleRows s -> first QDBMultipleRows $ getRemoteJoinsSelect s @@ -63,32 +63,32 @@ getRemoteJoins = \case -- | Traverse through 'AnnSimpleSel' and collect remote join fields (if any). getRemoteJoinsSelect - :: (Backend b) - => AnnSimpleSelectG b r (UnpreparedValue b) + :: Backend b + => AnnSimpleSelectG b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> (AnnSimpleSelectG b (Const Void) (UnpreparedValue b), Maybe RemoteJoins) getRemoteJoinsSelect = second mapToNonEmpty . flip runState mempty . transformSelect mempty -- | Traverse through @'AnnAggregateSelect' and collect remote join fields (if any). getRemoteJoinsAggregateSelect - :: (Backend b) - => AnnAggregateSelectG b r (UnpreparedValue b) + :: Backend b + => AnnAggregateSelectG b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> (AnnAggregateSelectG b (Const Void) (UnpreparedValue b), Maybe RemoteJoins) getRemoteJoinsAggregateSelect = second mapToNonEmpty . flip runState mempty . transformAggregateSelect mempty -- | Traverse through @'ConnectionSelect' and collect remote join fields (if any). getRemoteJoinsConnectionSelect - :: (Backend b) - => ConnectionSelect b r (UnpreparedValue b) + :: Backend b + => ConnectionSelect b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> (ConnectionSelect b (Const Void) (UnpreparedValue b), Maybe RemoteJoins) getRemoteJoinsConnectionSelect = second mapToNonEmpty . flip runState mempty . transformConnectionSelect mempty -- | Traverse through 'MutationOutput' and collect remote join fields (if any) getRemoteJoinsMutationOutput - :: (Backend b) - => MutationOutputG b r (UnpreparedValue b) + :: Backend b + => MutationOutputG b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> (MutationOutputG b (Const Void) (UnpreparedValue b), Maybe RemoteJoins) getRemoteJoinsMutationOutput = second mapToNonEmpty . flip runState mempty . transformMutationOutput mempty @@ -111,15 +111,15 @@ getRemoteJoinsMutationOutput = -- local helpers getRemoteJoinsAnnFields - :: (Backend b) - => AnnFieldsG b r (UnpreparedValue b) + :: Backend b + => AnnFieldsG b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> (AnnFieldsG b (Const Void) (UnpreparedValue b), Maybe RemoteJoins) getRemoteJoinsAnnFields = second mapToNonEmpty . flip runState mempty . transformAnnFields mempty getRemoteJoinsMutationDB - :: (Backend b) - => MutationDB b r (UnpreparedValue b) + :: Backend b + => MutationDB b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> (MutationDB b (Const Void) (UnpreparedValue b), Maybe RemoteJoins) getRemoteJoinsMutationDB = \case MDBInsert insert -> @@ -145,7 +145,7 @@ getRemoteJoinsMutationDB = \case getRemoteJoinsSyncAction :: (Backend b) - => AnnActionExecution b r (UnpreparedValue b) + => AnnActionExecution b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> (AnnActionExecution b (Const Void) (UnpreparedValue b), Maybe RemoteJoins) getRemoteJoinsSyncAction actionExecution = let (fields', remoteJoins) = getRemoteJoinsAnnFields $ _aaeFields actionExecution @@ -153,7 +153,7 @@ getRemoteJoinsSyncAction actionExecution = getRemoteJoinsActionQuery :: (Backend b) - => ActionQuery b r (UnpreparedValue b) + => ActionQuery b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> (ActionQuery b (Const Void) (UnpreparedValue b), Maybe RemoteJoins) getRemoteJoinsActionQuery = \case AQQuery sync -> @@ -180,7 +180,7 @@ getRemoteJoinsActionQuery = \case getRemoteJoinsActionMutation :: (Backend b) - => ActionMutation b r (UnpreparedValue b) + => ActionMutation b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> (ActionMutation b (Const Void) (UnpreparedValue b), Maybe RemoteJoins) getRemoteJoinsActionMutation = \case AMSync sync -> first AMSync $ getRemoteJoinsSyncAction sync @@ -190,7 +190,7 @@ getRemoteJoinsActionMutation = \case transformSelect :: (Backend b) => FieldPath - -> AnnSimpleSelectG b r (UnpreparedValue b) + -> AnnSimpleSelectG b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> State RemoteJoinMap (AnnSimpleSelectG b (Const Void) (UnpreparedValue b)) transformSelect path sel = do let fields = _asnFields sel @@ -201,7 +201,7 @@ transformSelect path sel = do transformAggregateSelect :: (Backend b) => FieldPath - -> AnnAggregateSelectG b r (UnpreparedValue b) + -> AnnAggregateSelectG b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> State RemoteJoinMap (AnnAggregateSelectG b (Const Void) (UnpreparedValue b)) transformAggregateSelect path sel = do let aggFields = _asnFields sel @@ -215,7 +215,7 @@ transformAggregateSelect path sel = do transformConnectionSelect :: (Backend b) => FieldPath - -> ConnectionSelect b r (UnpreparedValue b) + -> ConnectionSelect b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> State RemoteJoinMap (ConnectionSelect b (Const Void) (UnpreparedValue b)) transformConnectionSelect path ConnectionSelect{..} = do let connectionFields = _asnFields _csSelect @@ -238,7 +238,7 @@ transformConnectionSelect path ConnectionSelect{..} = do transformObjectSelect :: (Backend b) => FieldPath - -> AnnObjectSelectG b r (UnpreparedValue b) + -> AnnObjectSelectG b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> State RemoteJoinMap (AnnObjectSelectG b (Const Void) (UnpreparedValue b)) transformObjectSelect path sel = do let fields = _aosFields sel @@ -246,10 +246,9 @@ transformObjectSelect path sel = do pure sel{_aosFields = transformedFields} transformAnnFields - :: forall b r - . (Backend b) + :: forall b . Backend b => FieldPath - -> AnnFieldsG b r (UnpreparedValue b) + -> AnnFieldsG b (RemoteSelect UnpreparedValue) (UnpreparedValue b) -> State RemoteJoinMap (AnnFieldsG b (Const Void) (UnpreparedValue b)) transformAnnFields path fields = do @@ -260,9 +259,14 @@ transformAnnFields path fields = do let columnsInSelSet = HS.fromList $ map (pgiColumn . _acfInfo . snd) $ getFields _AFColumn fields scalarComputedFieldsInSelSet = HS.fromList $ map ((^. _2) . snd) $ getFields _AFComputedField fields - remoteSelects = getFields (_AFRemote) fields + + remoteSelects = getFields (_AFRemote.to getRemoteSchemaSelect) fields + getRemoteSchemaSelect = \case + RemoteSelectRemoteSchema s -> s + RemoteSelectSource _s -> error "remote source relationshsip found" + remoteJoins = remoteSelects <&> \(fieldName, remoteSelect) -> - let RemoteSelect argsMap selSet hasuraFields remoteFields rsi = remoteSelect + let RemoteSchemaSelect argsMap selSet hasuraFields remoteFields rsi = remoteSelect hasuraFieldNames = HS.map dbJoinFieldToName hasuraFields -- See Note [Phantom fields in Remote Joins] @@ -291,10 +295,11 @@ transformAnnFields path fields = do AFComputedField x n <$> case computedField of CFSScalar cfss cbe -> pure $ CFSScalar cfss cbe CFSTable jas annSel -> CFSTable jas <$> transformSelect fieldPath annSel - AFRemote rs -> pure $ AFRemote rs + -- we generate this so that the response has a key with the relationship, + -- without which preserving the order of fields in the final response + -- would require a lot of bookkeeping + AFRemote _rs -> pure $ AFExpression "remote relationship placeholder" AFExpression t -> pure $ AFExpression t - -- TODO: implement this - AFDBRemote _ -> error "FIXME" case NE.nonEmpty remoteJoins of Nothing -> pure transformedFields diff --git a/server/src-lib/Hasura/GraphQL/Explain.hs b/server/src-lib/Hasura/GraphQL/Explain.hs index 032827c05d7..a30491fe4a5 100644 --- a/server/src-lib/Hasura/GraphQL/Explain.hs +++ b/server/src-lib/Hasura/GraphQL/Explain.hs @@ -53,7 +53,7 @@ explainQueryField ) => UserInfo -> G.Name - -> QueryRootField UnpreparedValue UnpreparedValue + -> QueryRootField UnpreparedValue -> m EncJSON explainQueryField userInfo fieldName rootField = do case rootField of diff --git a/server/src-lib/Hasura/GraphQL/Schema.hs b/server/src-lib/Hasura/GraphQL/Schema.hs index a7f8e0a972f..e501a9c072a 100644 --- a/server/src-lib/Hasura/GraphQL/Schema.hs +++ b/server/src-lib/Hasura/GraphQL/Schema.hs @@ -207,9 +207,9 @@ buildRoleContext getMutationRemotes = concatMap (concat . piMutation) buildSource :: forall b. BackendSchema b => SourceInfo b -> - ConcreteSchemaT m ( [FieldParser (P.ParseT Identity) (QueryRootField UnpreparedValue UnpreparedValue)] - , [FieldParser (P.ParseT Identity) (MutationRootField UnpreparedValue UnpreparedValue)] - , [FieldParser (P.ParseT Identity) (MutationRootField UnpreparedValue UnpreparedValue)] + ConcreteSchemaT m ( [FieldParser (P.ParseT Identity) (QueryRootField UnpreparedValue)] + , [FieldParser (P.ParseT Identity) (MutationRootField UnpreparedValue)] + , [FieldParser (P.ParseT Identity) (MutationRootField UnpreparedValue)] ) buildSource (SourceInfo sourceName tables functions sourceConfig) = do let validFunctions = takeValidFunctions functions @@ -276,9 +276,9 @@ buildRelayRoleContext where buildSource :: forall b. BackendSchema b => SourceInfo b -> - ConcreteSchemaT m ( [FieldParser (P.ParseT Identity) (QueryRootField UnpreparedValue UnpreparedValue)] - , [FieldParser (P.ParseT Identity) (MutationRootField UnpreparedValue UnpreparedValue)] - , [FieldParser (P.ParseT Identity) (MutationRootField UnpreparedValue UnpreparedValue)] + ConcreteSchemaT m ( [FieldParser (P.ParseT Identity) (QueryRootField UnpreparedValue)] + , [FieldParser (P.ParseT Identity) (MutationRootField UnpreparedValue)] + , [FieldParser (P.ParseT Identity) (MutationRootField UnpreparedValue)] ) buildSource (SourceInfo sourceName tables functions sourceConfig) = do let validFunctions = takeValidFunctions functions @@ -296,8 +296,8 @@ buildFullestDBSchema -> SourceCache -> [ActionInfo] -> NonObjectTypeMap - -> m ( Parser 'Output (P.ParseT Identity) (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue UnpreparedValue)) - , Maybe (Parser 'Output (P.ParseT Identity) (OMap.InsOrdHashMap G.Name (MutationRootField UnpreparedValue UnpreparedValue))) + -> m ( Parser 'Output (P.ParseT Identity) (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue)) + , Maybe (Parser 'Output (P.ParseT Identity) (OMap.InsOrdHashMap G.Name (MutationRootField UnpreparedValue))) ) buildFullestDBSchema queryContext sources allActionInfos nonObjectCustomTypes = runMonadSchema adminRoleName queryContext sources do @@ -317,8 +317,8 @@ buildFullestDBSchema queryContext sources allActionInfos nonObjectCustomTypes = where buildSource :: forall b. BackendSchema b => SourceInfo b -> - ConcreteSchemaT m ( [FieldParser (P.ParseT Identity) (QueryRootField UnpreparedValue UnpreparedValue)] - , [FieldParser (P.ParseT Identity) (MutationRootField UnpreparedValue UnpreparedValue)] + ConcreteSchemaT m ( [FieldParser (P.ParseT Identity) (QueryRootField UnpreparedValue)] + , [FieldParser (P.ParseT Identity) (MutationRootField UnpreparedValue)] ) buildSource (SourceInfo sourceName tables functions sourceConfig) = do let validFunctions = takeValidFunctions functions @@ -432,7 +432,7 @@ buildQueryFields -> SourceConfig b -> TableCache b -> FunctionCache b - -> m [P.FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [P.FieldParser n (QueryRootField UnpreparedValue)] buildQueryFields sourceName sourceConfig tables (takeExposedAs FEAQuery -> functions) = do roleName <- askRoleName functionPermsCtx <- asks $ qcFunctionPermsContext . getter @@ -459,7 +459,7 @@ buildRelayQueryFields -> SourceConfig b -> TableCache b -> FunctionCache b - -> m [P.FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [P.FieldParser n (QueryRootField UnpreparedValue)] buildRelayQueryFields sourceName sourceConfig tables (takeExposedAs FEAQuery -> functions) = do tableConnectionFields <- for (Map.toList tables) \(tableName, tableInfo) -> runMaybeT do tableGQLName <- getTableGQLName @b tableInfo @@ -484,7 +484,7 @@ buildMutationFields -> SourceConfig b -> TableCache b -> FunctionCache b - -> m [P.FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [P.FieldParser n (MutationRootField UnpreparedValue)] buildMutationFields scenario sourceName sourceConfig tables (takeExposedAs FEAMutation -> functions) = do roleName <- askRoleName tableMutations <- for (Map.toList tables) \(tableName, tableInfo) -> do @@ -540,13 +540,13 @@ buildQueryParser , MonadRole r m , Has QueryContext r ) - => [P.FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + => [P.FieldParser n (QueryRootField UnpreparedValue)] -> [P.FieldParser n RemoteField] -> [ActionInfo] -> NonObjectTypeMap - -> Maybe (Parser 'Output n (OMap.InsOrdHashMap G.Name (MutationRootField UnpreparedValue UnpreparedValue))) - -> Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue UnpreparedValue)) - -> m (Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue UnpreparedValue))) + -> Maybe (Parser 'Output n (OMap.InsOrdHashMap G.Name (MutationRootField UnpreparedValue))) + -> Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue)) + -> m (Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue))) buildQueryParser pgQueryFields remoteFields allActions nonObjectCustomTypes mutationParser subscriptionParser = do actionQueryFields <- concat <$> traverse (buildActionQueryFields nonObjectCustomTypes) allActions let allQueryFields = pgQueryFields <> actionQueryFields <> map (fmap RFRemote) remoteFields @@ -554,10 +554,10 @@ buildQueryParser pgQueryFields remoteFields allActions nonObjectCustomTypes muta queryWithIntrospectionHelper :: forall n m. (MonadSchema n m, MonadError QErr m) - => [P.FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] - -> Maybe (Parser 'Output n (OMap.InsOrdHashMap G.Name (MutationRootField UnpreparedValue UnpreparedValue))) - -> Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue UnpreparedValue)) - -> m (Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue UnpreparedValue))) + => [P.FieldParser n (QueryRootField UnpreparedValue)] + -> Maybe (Parser 'Output n (OMap.InsOrdHashMap G.Name (MutationRootField UnpreparedValue))) + -> Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue)) + -> m (Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue))) queryWithIntrospectionHelper basicQueryFP mutationP subscriptionP = do basicQueryP <- queryRootFromFields basicQueryFP emptyIntro <- emptyIntrospection @@ -588,15 +588,15 @@ queryWithIntrospectionHelper basicQueryFP mutationP subscriptionP = do queryRootFromFields :: forall n m . (MonadError QErr m, MonadParse n) - => [P.FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] - -> m (Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue UnpreparedValue))) + => [P.FieldParser n (QueryRootField UnpreparedValue)] + -> m (Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue))) queryRootFromFields fps = P.safeSelectionSet queryRoot Nothing fps <&> fmap (fmap typenameToRawRF) emptyIntrospection :: forall m n . (MonadSchema n m, MonadError QErr m) - => m [P.FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + => m [P.FieldParser n (QueryRootField UnpreparedValue)] emptyIntrospection = do emptyQueryP <- queryRootFromFields @n [] introspectionTypes <- collectTypes (P.parserType emptyQueryP) @@ -630,9 +630,9 @@ buildSubscriptionParser , MonadRole r m , Has QueryContext r ) - => [P.FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + => [P.FieldParser n (QueryRootField UnpreparedValue)] -> [ActionInfo] - -> m (Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue UnpreparedValue))) + -> m (Parser 'Output n (OMap.InsOrdHashMap G.Name (QueryRootField UnpreparedValue))) buildSubscriptionParser queryFields allActions = do actionSubscriptionFields <- concat <$> traverse buildActionSubscriptionFields allActions let subscriptionFields = queryFields <> actionSubscriptionFields @@ -648,8 +648,8 @@ buildMutationParser => [P.FieldParser n RemoteField] -> [ActionInfo] -> NonObjectTypeMap - -> [P.FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] - -> m (Maybe (Parser 'Output n (OMap.InsOrdHashMap G.Name (MutationRootField UnpreparedValue UnpreparedValue)))) + -> [P.FieldParser n (MutationRootField UnpreparedValue)] + -> m (Maybe (Parser 'Output n (OMap.InsOrdHashMap G.Name (MutationRootField UnpreparedValue)))) buildMutationParser allRemotes allActions nonObjectCustomTypes mutationFields = do actionParsers <- concat <$> traverse (buildActionMutationFields nonObjectCustomTypes) allActions let mutationFieldsParser = diff --git a/server/src-lib/Hasura/GraphQL/Schema/Action.hs b/server/src-lib/Hasura/GraphQL/Schema/Action.hs index 9a8fd41ca68..7e1749042df 100644 --- a/server/src-lib/Hasura/GraphQL/Schema/Action.hs +++ b/server/src-lib/Hasura/GraphQL/Schema/Action.hs @@ -47,7 +47,7 @@ actionExecute . MonadBuildSchema ('Postgres 'Vanilla) r m n => NonObjectTypeMap -> ActionInfo - -> m (Maybe (FieldParser n (AnnActionExecution ('Postgres 'Vanilla) UnpreparedValue (UnpreparedValue ('Postgres 'Vanilla))))) + -> m (Maybe (FieldParser n (AnnActionExecution ('Postgres 'Vanilla) (RQL.RemoteSelect UnpreparedValue) (UnpreparedValue ('Postgres 'Vanilla))))) actionExecute nonObjectTypeMap actionInfo = runMaybeT do roleName <- askRoleName guard (roleName == adminRoleName || roleName `Map.member` permissions) @@ -113,7 +113,7 @@ actionAsyncQuery :: forall r m n . MonadBuildSchema ('Postgres 'Vanilla) r m n => ActionInfo - -> m (Maybe (FieldParser n (AnnActionAsyncQuery ('Postgres 'Vanilla) UnpreparedValue (UnpreparedValue ('Postgres 'Vanilla))))) + -> m (Maybe (FieldParser n (AnnActionAsyncQuery ('Postgres 'Vanilla) (RQL.RemoteSelect UnpreparedValue) (UnpreparedValue ('Postgres 'Vanilla))))) actionAsyncQuery actionInfo = runMaybeT do roleName <- askRoleName guard $ roleName == adminRoleName || roleName `Map.member` permissions @@ -172,7 +172,7 @@ actionOutputFields . MonadBuildSchema ('Postgres 'Vanilla) r m n => G.GType -> AnnotatedObjectType - -> m (Parser 'Output n (RQL.AnnFieldsG ('Postgres 'Vanilla) UnpreparedValue (UnpreparedValue ('Postgres 'Vanilla)))) + -> m (Parser 'Output n (AnnotatedFields ('Postgres 'Vanilla))) actionOutputFields outputType annotatedObject = do let outputObject = _aotDefinition annotatedObject scalarOrEnumFields = map outputFieldParser $ toList $ _otdFields outputObject @@ -194,7 +194,7 @@ actionOutputFields outputType annotatedObject = do outputFieldParser :: ObjectFieldDefinition (G.GType, AnnotatedObjectFieldType) - -> FieldParser n (RQL.AnnFieldG ('Postgres 'Vanilla) UnpreparedValue (UnpreparedValue ('Postgres 'Vanilla))) + -> FieldParser n (AnnotatedField ('Postgres 'Vanilla)) outputFieldParser (ObjectFieldDefinition name _ description (gType, objectFieldType)) = let fieldName = unObjectFieldName name selection = P.selection_ fieldName description $ case objectFieldType of @@ -211,7 +211,7 @@ actionOutputFields outputType annotatedObject = do relationshipFieldParser :: TypeRelationship (TableInfo ('Postgres 'Vanilla)) (ColumnInfo ('Postgres 'Vanilla)) - -> m (Maybe [FieldParser n (RQL.AnnFieldG ('Postgres 'Vanilla) UnpreparedValue (UnpreparedValue ('Postgres 'Vanilla)))]) + -> m (Maybe [FieldParser n (AnnotatedField ('Postgres 'Vanilla))]) relationshipFieldParser (TypeRelationship relName relType sourceName tableInfo fieldMapping) = runMaybeT do let tableName = _tciName $ _tiCoreInfo tableInfo fieldName = unRelationshipName relName diff --git a/server/src-lib/Hasura/GraphQL/Schema/Backend.hs b/server/src-lib/Hasura/GraphQL/Schema/Backend.hs index 821529a1cc0..5fbb9b6a630 100644 --- a/server/src-lib/Hasura/GraphQL/Schema/Backend.hs +++ b/server/src-lib/Hasura/GraphQL/Schema/Backend.hs @@ -72,7 +72,7 @@ class Backend b => BackendSchema (b :: BackendType) where -> TableInfo b -> G.Name -> SelPermInfo b - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] buildTableRelayQueryFields :: MonadBuildSchema b r m n => SourceName @@ -82,7 +82,7 @@ class Backend b => BackendSchema (b :: BackendType) where -> G.Name -> NESeq (ColumnInfo b) -> SelPermInfo b - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] buildTableInsertMutationFields :: MonadBuildSchema b r m n => SourceName @@ -93,7 +93,7 @@ class Backend b => BackendSchema (b :: BackendType) where -> InsPermInfo b -> Maybe (SelPermInfo b) -> Maybe (UpdPermInfo b) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] buildTableUpdateMutationFields :: MonadBuildSchema b r m n => SourceName @@ -103,7 +103,7 @@ class Backend b => BackendSchema (b :: BackendType) where -> G.Name -> UpdPermInfo b -> Maybe (SelPermInfo b) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] buildTableDeleteMutationFields :: MonadBuildSchema b r m n => SourceName @@ -113,7 +113,7 @@ class Backend b => BackendSchema (b :: BackendType) where -> G.Name -> DelPermInfo b -> Maybe (SelPermInfo b) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] buildFunctionQueryFields :: MonadBuildSchema b r m n => SourceName @@ -122,7 +122,7 @@ class Backend b => BackendSchema (b :: BackendType) where -> FunctionInfo b -> TableName b -> SelPermInfo b - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] buildFunctionRelayQueryFields :: MonadBuildSchema b r m n => SourceName @@ -132,7 +132,7 @@ class Backend b => BackendSchema (b :: BackendType) where -> TableName b -> NESeq (ColumnInfo b) -> SelPermInfo b - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] buildFunctionMutationFields :: MonadBuildSchema b r m n => SourceName @@ -141,7 +141,7 @@ class Backend b => BackendSchema (b :: BackendType) where -> FunctionInfo b -> TableName b -> SelPermInfo b - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] -- table components tableArguments diff --git a/server/src-lib/Hasura/GraphQL/Schema/Build.hs b/server/src-lib/Hasura/GraphQL/Schema/Build.hs index 804068d106b..c6f2a59172a 100644 --- a/server/src-lib/Hasura/GraphQL/Schema/Build.hs +++ b/server/src-lib/Hasura/GraphQL/Schema/Build.hs @@ -30,7 +30,7 @@ buildTableQueryFields -> TableInfo b -> G.Name -> SelPermInfo b - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] buildTableQueryFields sourceName sourceInfo tableName tableInfo gqlName selPerms = do let mkRF = RFDB sourceName @@ -64,7 +64,7 @@ buildTableInsertMutationFields -> InsPermInfo b -> Maybe (SelPermInfo b) -> Maybe (UpdPermInfo b) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] buildTableInsertMutationFields sourceName sourceInfo tableName tableInfo gqlName insPerms mSelPerms mUpdPerms = do let mkRF = RFDB sourceName @@ -96,7 +96,7 @@ buildTableUpdateMutationFields -> G.Name -> UpdPermInfo b -> Maybe (SelPermInfo b) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] buildTableUpdateMutationFields sourceName sourceInfo tableName tableInfo gqlName updPerms mSelPerms = do let mkRF = RFDB sourceName @@ -127,7 +127,7 @@ buildTableDeleteMutationFields -> G.Name -> DelPermInfo b -> Maybe (SelPermInfo b) - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] buildTableDeleteMutationFields sourceName sourceInfo tableName tableInfo gqlName delPerms mSelPerms = do let mkRF = RFDB sourceName @@ -157,7 +157,7 @@ buildFunctionQueryFields -> FunctionInfo b -> TableName b -> SelPermInfo b - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] buildFunctionQueryFields sourceName sourceInfo functionName functionInfo tableName selPerms = do funcName <- functionGraphQLName @b functionName `onLeft` throwError let @@ -188,7 +188,7 @@ buildFunctionMutationFields -> FunctionInfo b -> TableName b -> SelPermInfo b - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] buildFunctionMutationFields sourceName sourceInfo functionName functionInfo tableName selPerms = do funcName <- functionGraphQLName @b functionName `onLeft` throwError let diff --git a/server/src-lib/Hasura/GraphQL/Schema/Common.hs b/server/src-lib/Hasura/GraphQL/Schema/Common.hs index 3dd1dbc25d7..8d5be22979f 100644 --- a/server/src-lib/Hasura/GraphQL/Schema/Common.hs +++ b/server/src-lib/Hasura/GraphQL/Schema/Common.hs @@ -21,13 +21,15 @@ import Hasura.GraphQL.Parser (UnpreparedValue) import Hasura.RQL.Types -type SelectExp b = IR.AnnSimpleSelectG b UnpreparedValue (UnpreparedValue b) -type AggSelectExp b = IR.AnnAggregateSelectG b UnpreparedValue (UnpreparedValue b) -type ConnectionSelectExp b = IR.ConnectionSelect b UnpreparedValue (UnpreparedValue b) -type SelectArgs b = IR.SelectArgsG b (UnpreparedValue b) -type TablePerms b = IR.TablePermG b (UnpreparedValue b) -type AnnotatedFields b = IR.AnnFieldsG b UnpreparedValue (UnpreparedValue b) -type AnnotatedField b = IR.AnnFieldG b UnpreparedValue (UnpreparedValue b) +type SelectExp b = IR.AnnSimpleSelectG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b) +type AggSelectExp b = IR.AnnAggregateSelectG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b) +type ConnectionSelectExp b = IR.ConnectionSelect b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b) +type SelectArgs b = IR.SelectArgsG b (UnpreparedValue b) +type TablePerms b = IR.TablePermG b (UnpreparedValue b) +type AnnotatedFields b = IR.AnnFieldsG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b) +type AnnotatedField b = IR.AnnFieldG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b) +type ConnectionFields b = IR.ConnectionFields b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b) +type EdgeFields b = IR.EdgeFields b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b) data QueryContext = QueryContext diff --git a/server/src-lib/Hasura/GraphQL/Schema/Mutation.hs b/server/src-lib/Hasura/GraphQL/Schema/Mutation.hs index b4107759f57..4dde06f48b8 100644 --- a/server/src-lib/Hasura/GraphQL/Schema/Mutation.hs +++ b/server/src-lib/Hasura/GraphQL/Schema/Mutation.hs @@ -22,6 +22,7 @@ import qualified Hasura.GraphQL.Parser as P import qualified Hasura.RQL.IR.Delete as IR import qualified Hasura.RQL.IR.Insert as IR import qualified Hasura.RQL.IR.Returning as IR +import qualified Hasura.RQL.IR.Select as IR import qualified Hasura.RQL.IR.Update as IR import Hasura.GraphQL.Parser (FieldParser, InputFieldsParser, Kind (..), Parser, @@ -48,7 +49,7 @@ insertIntoTable -> InsPermInfo b -- ^ insert permissions of the table -> Maybe (SelPermInfo b) -- ^ select permissions of the table (if any) -> Maybe (UpdPermInfo b) -- ^ update permissions of the table (if any) - -> m (FieldParser n (IR.AnnInsert b UnpreparedValue (UnpreparedValue b))) + -> m (FieldParser n (IR.AnnInsert b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b))) insertIntoTable sourceName tableInfo fieldName description insertPerms selectPerms updatePerms = do let columns = tableColumns tableInfo selectionParser <- mutationSelectionSet sourceName tableInfo selectPerms @@ -86,7 +87,7 @@ insertOneIntoTable -> InsPermInfo b -- ^ insert permissions of the table -> SelPermInfo b -- ^ select permissions of the table -> Maybe (UpdPermInfo b) -- ^ update permissions of the table (if any) - -> m (FieldParser n (IR.AnnInsert b UnpreparedValue (UnpreparedValue b))) + -> m (FieldParser n (IR.AnnInsert b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b))) insertOneIntoTable sourceName tableInfo fieldName description insertPerms selectPerms updatePerms = do let columns = tableColumns tableInfo selectionParser <- tableSelectionSet sourceName tableInfo selectPerms @@ -298,7 +299,7 @@ updateTable -> Maybe G.Description -- ^ field description, if any -> UpdPermInfo b -- ^ update permissions of the table -> Maybe (SelPermInfo b) -- ^ select permissions of the table (if any) - -> m (Maybe (FieldParser n (IR.AnnUpdG b UnpreparedValue (UnpreparedValue b)))) + -> m (Maybe (FieldParser n (IR.AnnUpdG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b)))) updateTable sourceName tableInfo fieldName description updatePerms selectPerms = runMaybeT $ do let whereName = $$(G.litName "where") whereDesc = "filter the rows which have to be updated" @@ -324,7 +325,7 @@ updateTableByPk -> Maybe G.Description -- ^ field description, if any -> UpdPermInfo b -- ^ update permissions of the table -> SelPermInfo b -- ^ select permissions of the table - -> m (Maybe (FieldParser n (IR.AnnUpdG b UnpreparedValue (UnpreparedValue b)))) + -> m (Maybe (FieldParser n (IR.AnnUpdG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b)))) updateTableByPk sourceName tableInfo fieldName description updatePerms selectPerms = runMaybeT $ do tableGQLName <- getTableGQLName tableInfo let columns = tableColumns tableInfo @@ -350,9 +351,9 @@ mkUpdateObject -> ( ( [(Column b, IR.UpdOpExpG (UnpreparedValue b))] , AnnBoolExp b (UnpreparedValue b) ) - , IR.MutationOutputG b UnpreparedValue (UnpreparedValue b) + , IR.MutationOutputG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b) ) - -> IR.AnnUpdG b UnpreparedValue (UnpreparedValue b) + -> IR.AnnUpdG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b) mkUpdateObject table columns updatePerms ((opExps, whereExp), mutationOutput) = IR.AnnUpd { IR.uqp1Table = table , IR.uqp1OpExps = opExps @@ -379,7 +380,7 @@ deleteFromTable -> Maybe G.Description -- ^ field description, if any -> DelPermInfo b -- ^ delete permissions of the table -> Maybe (SelPermInfo b) -- ^ select permissions of the table (if any) - -> m (FieldParser n (IR.AnnDelG b UnpreparedValue (UnpreparedValue b))) + -> m (FieldParser n (IR.AnnDelG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b))) deleteFromTable sourceName tableInfo fieldName description deletePerms selectPerms = do let whereName = $$(G.litName "where") whereDesc = "filter the rows which have to be deleted" @@ -401,7 +402,7 @@ deleteFromTableByPk -> Maybe G.Description -- ^ field description, if any -> DelPermInfo b -- ^ delete permissions of the table -> SelPermInfo b -- ^ select permissions of the table - -> m (Maybe (FieldParser n (IR.AnnDelG b UnpreparedValue (UnpreparedValue b)))) + -> m (Maybe (FieldParser n (IR.AnnDelG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b)))) deleteFromTableByPk sourceName tableInfo fieldName description deletePerms selectPerms = runMaybeT $ do let columns = tableColumns tableInfo pkArgs <- MaybeT $ primaryKeysArguments tableInfo selectPerms @@ -414,8 +415,8 @@ mkDeleteObject => TableName b -> [ColumnInfo b] -> DelPermInfo b - -> (AnnBoolExp b (UnpreparedValue b), IR.MutationOutputG b UnpreparedValue (UnpreparedValue b)) - -> IR.AnnDelG b UnpreparedValue (UnpreparedValue b) + -> (AnnBoolExp b (UnpreparedValue b), IR.MutationOutputG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b)) + -> IR.AnnDelG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b) mkDeleteObject table columns deletePerms (whereExp, mutationOutput) = IR.AnnDel { IR.dqp1Table = table , IR.dqp1Where = (permissionFilter, whereExp) @@ -436,7 +437,7 @@ mutationSelectionSet => SourceName -> TableInfo b -> Maybe (SelPermInfo b) - -> m (Parser 'Output n (IR.MutFldsG b UnpreparedValue (UnpreparedValue b))) + -> m (Parser 'Output n (IR.MutFldsG b (IR.RemoteSelect UnpreparedValue) (UnpreparedValue b))) mutationSelectionSet sourceName tableInfo selectPerms = memoizeOn 'mutationSelectionSet (sourceName, tableName) do tableGQLName <- getTableGQLName tableInfo diff --git a/server/src-lib/Hasura/GraphQL/Schema/Postgres.hs b/server/src-lib/Hasura/GraphQL/Schema/Postgres.hs index e367f64ad13..9110812a1c4 100644 --- a/server/src-lib/Hasura/GraphQL/Schema/Postgres.hs +++ b/server/src-lib/Hasura/GraphQL/Schema/Postgres.hs @@ -20,7 +20,7 @@ buildActionQueryFields :: MonadBuildSchema ('Postgres 'Vanilla) r m n => NonObjectTypeMap -> ActionInfo - -> m [FieldParser n (QueryRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] buildActionQueryFields nonObjectCustomTypes actionInfo = maybeToList <$> case _adType (_aiDefinition actionInfo) of ActionQuery -> @@ -33,7 +33,7 @@ buildActionMutationFields :: MonadBuildSchema ('Postgres 'Vanilla) r m n => NonObjectTypeMap -> ActionInfo - -> m [FieldParser n (MutationRootField UnpreparedValue UnpreparedValue)] + -> m [FieldParser n (MutationRootField UnpreparedValue)] buildActionMutationFields nonObjectCustomTypes actionInfo = maybeToList <$> case _adType (_aiDefinition actionInfo) of ActionQuery -> pure Nothing @@ -45,8 +45,7 @@ buildActionMutationFields nonObjectCustomTypes actionInfo = buildActionSubscriptionFields :: MonadBuildSchema ('Postgres 'Vanilla) r m n => ActionInfo - -> m [FieldParser n (QueryRootField UnpreparedValue - UnpreparedValue)] + -> m [FieldParser n (QueryRootField UnpreparedValue)] buildActionSubscriptionFields actionInfo = maybeToList <$> case _adType (_aiDefinition actionInfo) of ActionQuery -> pure Nothing diff --git a/server/src-lib/Hasura/GraphQL/Schema/Select.hs b/server/src-lib/Hasura/GraphQL/Schema/Select.hs index 43cea1fb966..39f1c4d3ea4 100644 --- a/server/src-lib/Hasura/GraphQL/Schema/Select.hs +++ b/server/src-lib/Hasura/GraphQL/Schema/Select.hs @@ -398,7 +398,7 @@ tableConnectionSelectionSet => SourceName -> TableInfo b -> SelPermInfo b - -> m (Parser 'Output n (IR.ConnectionFields b UnpreparedValue (UnpreparedValue b))) + -> m (Parser 'Output n (ConnectionFields b)) tableConnectionSelectionSet sourceName tableInfo selectPermissions = memoizeOn 'tableConnectionSelectionSet (sourceName, tableName) do tableGQLName <- getTableGQLName tableInfo edgesParser <- tableEdgesSelectionSet tableGQLName @@ -432,7 +432,7 @@ tableConnectionSelectionSet sourceName tableInfo selectPermissions = memoizeOn ' <&> parsedSelectionsToFields IR.PageInfoTypename tableEdgesSelectionSet - :: G.Name -> m (Parser 'Output n (IR.EdgeFields b UnpreparedValue (UnpreparedValue b))) + :: G.Name -> m (Parser 'Output n (EdgeFields b)) tableEdgesSelectionSet tableGQLName = do edgeNodeParser <- P.nonNullableParser <$> tableSelectionSet sourceName tableInfo selectPermissions let edgesType = tableGQLName <> $$(G.litName "Edge") @@ -1155,7 +1155,7 @@ remoteRelationshipField remoteFieldInfo = runMaybeT do `P.bindField` \G.Field{ G._fArguments = args, G._fSelectionSet = selSet } -> do let remoteArgs = Map.toList args <&> \(argName, argVal) -> IR.RemoteFieldArgument argName $ P.GraphQLValue $ argVal - pure $ IR.AFRemote $ IR.RemoteSelect + pure $ IR.AFRemote $ IR.RemoteSelectRemoteSchema $ IR.RemoteSchemaSelect { _rselArgs = remoteArgs , _rselSelection = selSet , _rselHasuraFields = _rfiHasuraFields remoteSchema @@ -1410,7 +1410,7 @@ nodePG = memoizeOn 'nodePG () do nodeField :: forall m n r . MonadBuildSchema ('Postgres 'Vanilla) r m n - => m (P.FieldParser n (IR.QueryRootField UnpreparedValue UnpreparedValue)) + => m (P.FieldParser n (IR.QueryRootField UnpreparedValue)) nodeField = do let idDescription = G.Description "A globally unique id" idArgument = P.field $$(G.litName "id") (Just idDescription) P.identifier diff --git a/server/src-lib/Hasura/GraphQL/Transport/HTTP.hs b/server/src-lib/Hasura/GraphQL/Transport/HTTP.hs index c6cbeb5d5db..5eabda8309e 100644 --- a/server/src-lib/Hasura/GraphQL/Transport/HTTP.hs +++ b/server/src-lib/Hasura/GraphQL/Transport/HTTP.hs @@ -167,7 +167,7 @@ runSessVarPred = filterSessionVariables . unSessVarPred -- | Filter out only those session variables used by the query AST provided filterVariablesFromQuery :: Backend backend - => [RootField (QueryDBRoot UnpreparedValue UnpreparedValue) RemoteField (ActionQuery backend UnpreparedValue (UnpreparedValue backend)) d] + => [RootField (QueryDBRoot (RemoteSelect UnpreparedValue) UnpreparedValue) RemoteField (ActionQuery backend (RemoteSelect UnpreparedValue) (UnpreparedValue backend)) d] -> SessVarPred filterVariablesFromQuery query = fold $ rootToSessVarPreds =<< query where diff --git a/server/src-lib/Hasura/RQL/IR/Root.hs b/server/src-lib/Hasura/RQL/IR/Root.hs index 46e69c9971f..6528b87467b 100644 --- a/server/src-lib/Hasura/RQL/IR/Root.hs +++ b/server/src-lib/Hasura/RQL/IR/Root.hs @@ -72,7 +72,14 @@ data ActionMutation (b :: BackendType) (r :: BackendType -> Type) v newtype QueryDBRoot r v b = QDBR (QueryDB b r (v b)) newtype MutationDBRoot r v b = MDBR (MutationDB b r (v b)) +-- | Represents a query root field to an action +type QueryActionRoot v + = ActionQuery ('Postgres 'Vanilla) (RemoteSelect v) (v ('Postgres 'Vanilla)) -type QueryRootField r v = RootField (QueryDBRoot r v) RQL.RemoteField (ActionQuery ('Postgres 'Vanilla) r (v ('Postgres 'Vanilla))) JO.Value -type MutationRootField r v = RootField (MutationDBRoot r v) RQL.RemoteField (ActionMutation ('Postgres 'Vanilla) r (v ('Postgres 'Vanilla))) JO.Value -type SubscriptionRootField r v = RootField (QueryDBRoot r v) Void Void Void +-- | Represents a mutation root field to an action +type MutationActionRoot v + = ActionMutation ('Postgres 'Vanilla) (RemoteSelect v) (v ('Postgres 'Vanilla)) + +type QueryRootField v = RootField (QueryDBRoot (RemoteSelect v) v) RQL.RemoteField (QueryActionRoot v) JO.Value +type MutationRootField v = RootField (MutationDBRoot (RemoteSelect v) v) RQL.RemoteField (MutationActionRoot v) JO.Value +type SubscriptionRootField v = RootField (QueryDBRoot (RemoteSelect v) v) Void Void Void diff --git a/server/src-lib/Hasura/RQL/IR/Select.hs b/server/src-lib/Hasura/RQL/IR/Select.hs index ef2db9628d7..0836e6b1f76 100644 --- a/server/src-lib/Hasura/RQL/IR/Select.hs +++ b/server/src-lib/Hasura/RQL/IR/Select.hs @@ -188,8 +188,11 @@ data AnnFieldG (b :: BackendType) (r :: BackendType -> Type) v | AFObjectRelation !(ObjectRelationSelectG b r v) | AFArrayRelation !(ArraySelectG b r v) | AFComputedField !(XComputedField b) !ComputedFieldName !(ComputedFieldSelect b r v) - | AFRemote !(RemoteSelect b) - | AFDBRemote !(AB.AnyBackend (DBRemoteSelect b r)) + -- | A relationship to a remote source/remote schema. Its kind is + -- (r :: BackendType -> Type) so that AFRemote can capture something + -- that is specific to the backend AnnFieldG. See RemoteSelect. When + -- remote joins are extracted from the structure, 'r' becomes 'Const Void' + | AFRemote !(r b) | AFNodeId !(XRelay b) !(TableName b) !(PrimaryKeyColumns b) | AFExpression !Text deriving (Functor, Foldable, Traversable) @@ -361,7 +364,7 @@ type ArraySelect b = ArraySelectG b (Const Void) (SQLExpression b) type ArraySelectFieldsG b r v = Fields (ArraySelectG b r v) --- Remote schema relationship +-- Remote schema relationships data RemoteFieldArgument = RemoteFieldArgument @@ -369,8 +372,8 @@ data RemoteFieldArgument , _rfaValue :: !(InputValue RemoteSchemaVariable) } deriving (Eq,Show) -data RemoteSelect (b :: BackendType) - = RemoteSelect +data RemoteSchemaSelect (b :: BackendType) + = RemoteSchemaSelect { _rselArgs :: ![RemoteFieldArgument] , _rselSelection :: !(G.SelectionSet G.NoFragments RemoteSchemaVariable) , _rselHasuraFields :: !(HashSet (DBJoinField b)) @@ -378,16 +381,45 @@ data RemoteSelect (b :: BackendType) , _rselRemoteSchema :: !RemoteSchemaInfo } +-- | Captures the selection set of a remote source relationship. +data SourceRelationshipSelection + (b :: BackendType) + (r :: BackendType -> Type) + (vf :: BackendType -> Type) + = SourceRelationshipObject !(AnnObjectSelectG b r (vf b)) + | SourceRelationshipArray !(AnnSimpleSelectG b r (vf b)) + | SourceRelationshipArrayAggregate !(AnnAggregateSelectG b r (vf b)) --- Remote db relationship - -data DBRemoteSelect (src :: BackendType) (r :: BackendType -> Type) (tgt :: BackendType) - = DBRemoteSelect - { _dbrselHasuraColumns :: ![(ColumnInfo src, ColumnInfo tgt)] - , _dbrselTargetQuery :: !(QueryDB tgt r (r tgt)) - , _dbrselTargetConfig :: !(SourceConfig tgt) - } +-- | A relationship to a remote source. 'vf' (could use a better name) is +-- analogous to 'v' in other IR types such as 'AnnFieldG'. vf's kind is +-- (BackendType -> Type) instead of v's 'Type' so that 'v' of 'AnnFieldG' can +-- be specific to the backend that it captures ('b' of an AnnFieldG changes as +-- we walk down the IR branches which capture relationships to other databases) +data RemoteSourceSelect + (src :: BackendType) + (vf :: BackendType -> Type) + (tgt :: BackendType) + = RemoteSourceSelect + { _rssSourceName :: !SourceName + , _rssSourceConfig :: !(SourceConfig tgt) + , _rssSelection :: !(SourceRelationshipSelection tgt (RemoteSelect vf) vf) + , _rssJoinMapping :: !(HM.HashMap FieldName (ColumnInfo src, ScalarType tgt, Column tgt)) + -- ^ Additional information about the source's join columns: + -- (ColumnInfo src) so that we can add the join column to the AST + -- (ScalarType tgt) so that the remote can interpret the join values coming + -- from src + -- (Column tgt) so that an appropriate join condition / IN clause can be built + -- by the remote + } +-- | A remote relationship to either a remote schema or a remote source. +-- See RemoteSourceSelect for explanation on 'vf'. +data RemoteSelect + (vf :: BackendType -> Type) + (src :: BackendType) + = RemoteSelectRemoteSchema !(RemoteSchemaSelect src) + -- ^ AnyBackend is used here to capture a relationship to an arbitrary target + | RemoteSelectSource !(AB.AnyBackend (RemoteSourceSelect src vf)) -- Permissions