From 279f22ed089b4cfd01c71fb56cfe615dc4127c9d Mon Sep 17 00:00:00 2001 From: Kirill Zaborsky Date: Wed, 15 Dec 2021 18:18:56 +0300 Subject: [PATCH] Fix support for multiple array relationships in BigQuery PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3003 GitOrigin-RevId: 7a9bf10be6436da2d87d5555f589e23c40c76dd6 --- CHANGELOG.md | 1 + .../Hasura/Backends/BigQuery/FromIr.hs | 22 ++- .../bigquery/nested_array_relationships.yaml | 153 ++++++++++++++++++ .../bigquery/schema_setup_bigquery.yaml | 15 ++ .../bigquery/setup_bigquery.yaml | 61 +++++++ server/tests-py/test_graphql_queries.py | 3 + 6 files changed, 251 insertions(+), 4 deletions(-) create mode 100644 server/tests-py/queries/graphql_query/bigquery/nested_array_relationships.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index c7077a21a33..e1c2c56bf4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ - server: provide option to explicitly recreate event triggers for sources in the `reload_metadata` API - server: fix `gen_hasura_uuid` migration to be idempotent, so that it doesn't fail if the database is already initialised with source migrations. - server: fix mssql `table_by_pk` query returning empty array (fix #7784) +- server: fix BigQuery queries failing with more than one array relationship - console: add comments to tracked functions - console: add select all columns option while selecting the columns in event triggers - console: add request transforms for events diff --git a/server/src-lib/Hasura/Backends/BigQuery/FromIr.hs b/server/src-lib/Hasura/Backends/BigQuery/FromIr.hs index 32e4cd00ab6..315cfe97bea 100644 --- a/server/src-lib/Hasura/Backends/BigQuery/FromIr.hs +++ b/server/src-lib/Hasura/Backends/BigQuery/FromIr.hs @@ -1249,7 +1249,7 @@ fromArrayRelationSelectG annRelationSelectG = do ArrayAgg { arrayAggProjections = fmap - aliasToFieldProjection + (aliasToFieldProjection (fromAlias (selectFrom select))) (selectProjections select), arrayAggOrderBy = Nothing, arrayAggTop = selectTop select @@ -1352,9 +1352,12 @@ fromArrayRelationSelectG annRelationSelectG = do } = annRelationSelectG -- | For entity projections, convert any entity aliases to their field --- names. TODO: Add an explanation for this. -aliasToFieldProjection :: Projection -> Projection -aliasToFieldProjection = +-- names. ArrayEntityProjection and ExpressionProjection get converted +-- to aliases to fields with the same names as all the expressions +-- have already aliases applied in select from ArrayAgg +-- (created in Hasura.Backends.BigQuery.ToQuery.fromArrayAgg) +aliasToFieldProjection :: EntityAlias -> Projection -> Projection +aliasToFieldProjection (EntityAlias selectAlias) = \case EntityProjection Aliased {aliasedAlias = name, aliasedThing = fields} -> EntityProjection @@ -1365,7 +1368,18 @@ aliasToFieldProjection = (\(FieldName {..}, origin) -> (FieldName {fieldNameEntity = name, ..}, origin)) fields } + ArrayEntityProjection _ aliased -> + aliasColumn aliased + ExpressionProjection aliased -> + aliasColumn aliased p -> p + where + aliasColumn :: Aliased a -> Projection + aliasColumn aliased = + ExpressionProjection + aliased + { aliasedThing = ColumnExpression (FieldName {fieldName = aliasedAlias aliased, fieldNameEntity = selectAlias}) + } fromRelName :: Rql.RelName -> FromIr Text fromRelName relName = diff --git a/server/tests-py/queries/graphql_query/bigquery/nested_array_relationships.yaml b/server/tests-py/queries/graphql_query/bigquery/nested_array_relationships.yaml new file mode 100644 index 00000000000..ef690d64f3d --- /dev/null +++ b/server/tests-py/queries/graphql_query/bigquery/nested_array_relationships.yaml @@ -0,0 +1,153 @@ +- description: Author with articles with cited articles + url: /v1/graphql + status: 200 + response: + data: + hasura_test_author: + - id: '1' + name: Author 1 + articles: + - id: '1' + title: Title 1 + content: Content 1 + article_citations: + - description: citing the 2nd + cited_article: + id: '2' + title: Title 2 + content: Content 2 + - description: citing the third as well + cited_article: + id: '3' + title: Title 3 + content: Content 3 + - id: '2' + title: Title 2 + content: Content 2 + article_citations: + - description: the second also cites the third + cited_article: + id: '3' + title: Title 3 + content: Content 3 + - id: '2' + name: Author 2 + articles: + - id: '3' + title: Title 3 + content: Content 3 + article_citations: [] + query: + query: | + query { + hasura_test_author (order_by: {id: asc}) { + id + name + articles (order_by: {id:asc}){ + id + title + content + article_citations { + description + cited_article { + id + title + content + } + } + } + } + } + +- description: Author with articles with count of cited articles + url: /v1/graphql + status: 200 + response: + data: + hasura_test_author: + - id: '1' + name: Author 1 + articles: + - id: '1' + title: Title 1 + content: Content 1 + article_citations_aggregate: + aggregate: + count: '2' + - id: '2' + title: Title 2 + content: Content 2 + article_citations_aggregate: + aggregate: + count: '1' + - id: '2' + name: Author 2 + articles: + - id: '3' + title: Title 3 + content: Content 3 + article_citations_aggregate: + aggregate: + count: '0' + query: + query: | + query { + hasura_test_author (order_by: {id: asc}) { + id + name + articles (order_by: {id:asc}){ + id + title + content + article_citations_aggregate { + aggregate { + count + } + } + } + } + } + +- description: Author with articles with article_citations in remote source + url: /v1/graphql + status: 200 + response: + data: + hasura_test_author: + - id: '1' + name: Author 1 + articles: + - id: '1' + title: Title 1 + content: Content 1 + article_citations2: + - description: citing the 2nd + - description: citing the third as well + - id: '2' + title: Title 2 + content: Content 2 + article_citations2: + - description: the second also cites the third + - id: '2' + name: Author 2 + articles: + - id: '3' + title: Title 3 + content: Content 3 + article_citations2: [] + query: + query: | + query { + hasura_test_author (order_by: {id: asc}) { + id + name + articles (order_by: {id:asc}){ + id + title + content + article_citations2 { + description + } + } + } + } diff --git a/server/tests-py/queries/graphql_query/bigquery/schema_setup_bigquery.yaml b/server/tests-py/queries/graphql_query/bigquery/schema_setup_bigquery.yaml index 0624defeeb8..e75d0c45b5c 100644 --- a/server/tests-py/queries/graphql_query/bigquery/schema_setup_bigquery.yaml +++ b/server/tests-py/queries/graphql_query/bigquery/schema_setup_bigquery.yaml @@ -152,3 +152,18 @@ args: "fear innoculum", 1002 ); SELECT * from hasura_test.Album; + + CREATE TABLE `hasura_test.article_citation` ( + `article_id` INT64, + `cited_article_id` INT64, + `description` STRING, + ); + INSERT INTO hasura_test.article_citation + (article_id, cited_article_id, description) + VALUES (1, 2, 'citing the 2nd'), + (1, 3, 'citing the third as well'), + (2, 3, 'the second also cites the third'); + + -- a copy for remote joins as we can't have the same table tracked in two sources + CREATE TABLE `hasura_test.article_citation2` + AS SELECT * FROM `hasura_test.article_citation`; diff --git a/server/tests-py/queries/graphql_query/bigquery/setup_bigquery.yaml b/server/tests-py/queries/graphql_query/bigquery/setup_bigquery.yaml index 7dfa406a501..0c33c65bb51 100644 --- a/server/tests-py/queries/graphql_query/bigquery/setup_bigquery.yaml +++ b/server/tests-py/queries/graphql_query/bigquery/setup_bigquery.yaml @@ -176,6 +176,13 @@ args: dataset: hasura_test name: all_types +- type: bigquery_track_table + args: + source: bigquery + table: + dataset: hasura_test + name: article_citation + # === hasura_global_limited === ## track tables @@ -224,6 +231,36 @@ args: column_mapping: artist_self_id: artist_other_id +- type: bigquery_create_array_relationship + args: + source: bigquery + table: + dataset: hasura_test + name: article + name: article_citations + using: + manual_configuration: + remote_table: + dataset: hasura_test + name: article_citation + column_mapping: + id: article_id + +- type: bigquery_create_object_relationship + args: + source: bigquery + table: + dataset: hasura_test + name: article_citation + name: cited_article + using: + manual_configuration: + remote_table: + dataset: hasura_test + name: article + column_mapping: + cited_article_id: id + # === hasura_test/bigquery2 === - type: bigquery_track_table args: @@ -265,3 +302,27 @@ args: table: name: article2 dataset: hasura_test + +- type: bigquery_track_table + args: + source: bigquery2 + table: + dataset: hasura_test + name: article_citation2 + +- type: bigquery_create_remote_relationship + args: + source: bigquery + table: + dataset: hasura_test + name: article + name: article_citations2 + definition: + to_source: + relationship_type: array + field_mapping: + id: article_id + source: bigquery2 + table: + name: article_citation2 + dataset: hasura_test diff --git a/server/tests-py/test_graphql_queries.py b/server/tests-py/test_graphql_queries.py index 46f55d5671c..675678cfa82 100644 --- a/server/tests-py/test_graphql_queries.py +++ b/server/tests-py/test_graphql_queries.py @@ -210,6 +210,9 @@ class TestGraphQLQueryBasicBigquery: def test_basic_remote_join(self, hge_ctx, transport): check_query_f(hge_ctx, self.dir() + "/basic_remote_joins.yaml", transport) + def test_nested_array_relationships(self, hge_ctx, transport): + check_query_f(hge_ctx, self.dir() + "/nested_array_relationships.yaml", transport) + @classmethod def dir(cls): return 'queries/graphql_query/bigquery'