From 55def8faa744380ab80a1c45ede9abe7ee60800e Mon Sep 17 00:00:00 2001 From: Shahzad Lone Date: Thu, 14 Sep 2023 10:32:22 -0400 Subject: [PATCH 1/3] PR: Remove the explain tests under query folder --- tests/integration/query/one_to_many/utils.go | 2 - .../one_to_many/with_average_filter_test.go | 116 ---------- .../one_to_many/with_count_filter_test.go | 207 ------------------ 3 files changed, 325 deletions(-) delete mode 100644 tests/integration/query/one_to_many/with_average_filter_test.go diff --git a/tests/integration/query/one_to_many/utils.go b/tests/integration/query/one_to_many/utils.go index e8ae79efa2..d1e25df661 100644 --- a/tests/integration/query/one_to_many/utils.go +++ b/tests/integration/query/one_to_many/utils.go @@ -16,8 +16,6 @@ import ( testUtils "github.com/sourcenetwork/defradb/tests/integration" ) -type dataMap = map[string]any - var bookAuthorGQLSchema = (` type Book { name: String diff --git a/tests/integration/query/one_to_many/with_average_filter_test.go b/tests/integration/query/one_to_many/with_average_filter_test.go deleted file mode 100644 index 1404be5962..0000000000 --- a/tests/integration/query/one_to_many/with_average_filter_test.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2022 Democratized Data Foundation -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -package one_to_many - -import ( - "testing" - - testUtils "github.com/sourcenetwork/defradb/tests/integration" -) - -// This test asserts that only a single join is used - the _avg reuses the rendered join as they -// have matching filters (average adds a ne nil filter). -func TestQueryOneToManyWithAverageAndChildNeNilFilterSharesJoinField(t *testing.T) { - test := testUtils.RequestTestCase{ - Description: "One-to-many relation query from many side with average", - Request: `query @explain { - Author { - name - _avg(published: {field: rating}) - published(filter: {rating: {_ne: null}}){ - name - } - } - }`, - Results: []dataMap{ - { - "explain": dataMap{ - "selectTopNode": dataMap{ - "averageNode": dataMap{ - "countNode": dataMap{ - "sources": []dataMap{ - { - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "fieldName": "published", - }, - }, - "sumNode": dataMap{ - "sources": []dataMap{ - { - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "fieldName": "published", - "childFieldName": "rating", - }, - }, - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "typeIndexJoin": dataMap{ - "joinType": "typeJoinMany", - "rootName": "author", - "root": dataMap{ - "scanNode": dataMap{ - "filter": nil, - "collectionID": "2", - "collectionName": "Author", - "spans": []dataMap{ - { - "start": "/2", - "end": "/3", - }, - }, - }, - }, - "subTypeName": "published", - "subType": dataMap{ - "selectTopNode": dataMap{ - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "scanNode": dataMap{ - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "collectionID": "1", - "collectionName": "Book", - "spans": []dataMap{ - { - "start": "/1", - "end": "/2", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - - executeTestCase(t, test) -} diff --git a/tests/integration/query/one_to_many/with_count_filter_test.go b/tests/integration/query/one_to_many/with_count_filter_test.go index 9deecae01f..b367e6c856 100644 --- a/tests/integration/query/one_to_many/with_count_filter_test.go +++ b/tests/integration/query/one_to_many/with_count_filter_test.go @@ -153,210 +153,3 @@ func TestQueryOneToManyWithCountWithFilterAndChildFilter(t *testing.T) { executeTestCase(t, test) } - -// This test asserts that only a single join is used - the _count reuses the rendered join as they -// have matching filters. -func TestQueryOneToManyWithCountWithFilterAndChildFilterSharesJoinField(t *testing.T) { - test := testUtils.RequestTestCase{ - Description: "One-to-many relation query from many side with count with filter", - Request: `query @explain { - Author { - name - _count(published: {filter: {rating: {_ne: null}}}) - published(filter: {rating: {_ne: null}}){ - name - } - } - }`, - Results: []dataMap{ - { - "explain": dataMap{ - "selectTopNode": dataMap{ - "countNode": dataMap{ - "sources": []dataMap{ - { - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "fieldName": "published", - }, - }, - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "typeIndexJoin": dataMap{ - "joinType": "typeJoinMany", - "rootName": "author", - "root": dataMap{ - "scanNode": dataMap{ - "filter": nil, - "collectionID": "2", - "collectionName": "Author", - "spans": []dataMap{ - { - "start": "/2", - "end": "/3", - }, - }, - }, - }, - "subTypeName": "published", - "subType": dataMap{ - "selectTopNode": dataMap{ - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "scanNode": dataMap{ - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "collectionID": "1", - "collectionName": "Book", - "spans": []dataMap{ - { - "start": "/1", - "end": "/2", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - - executeTestCase(t, test) -} - -// This test asserts that two joins are used - the _count cannot reuse the rendered join as they -// dont have matching filters. -func TestQueryOneToManyWithCountAndChildFilterDoesNotShareJoinField(t *testing.T) { - test := testUtils.RequestTestCase{ - Description: "One-to-many relation query from many side with count", - Request: `query @explain { - Author { - name - _count(published: {}) - published(filter: {rating: {_ne: null}}){ - name - } - } - }`, - Results: []dataMap{ - { - "explain": dataMap{ - "selectTopNode": dataMap{ - "countNode": dataMap{ - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "parallelNode": []dataMap{ - { - "typeIndexJoin": dataMap{ - "joinType": "typeJoinMany", - "root": dataMap{ - "scanNode": dataMap{ - "collectionID": "2", - "collectionName": "Author", - "filter": nil, - "spans": []dataMap{ - { - "end": "/3", - "start": "/2", - }, - }, - }, - }, - "rootName": "author", - "subType": dataMap{ - "selectTopNode": dataMap{ - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "scanNode": dataMap{ - "collectionID": "1", - "collectionName": "Book", - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "spans": []dataMap{ - { - "end": "/2", - "start": "/1", - }, - }, - }, - }, - }, - }, - "subTypeName": "published", - }, - }, - { - "typeIndexJoin": dataMap{ - "joinType": "typeJoinMany", - "root": dataMap{ - "scanNode": dataMap{ - "collectionID": "2", - "collectionName": "Author", - "filter": nil, - "spans": []dataMap{ - { - "end": "/3", - "start": "/2", - }, - }, - }, - }, - "rootName": "author", - "subType": dataMap{ - "selectTopNode": dataMap{ - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "scanNode": dataMap{ - "collectionID": "1", - "collectionName": "Book", - "filter": nil, - "spans": []dataMap{ - { - "end": "/2", - "start": "/1", - }, - }, - }, - }, - }, - }, - "subTypeName": "published", - }, - }, - }, - }, - "sources": []dataMap{ - { - "fieldName": "published", - "filter": nil, - }, - }, - }, - }, - }, - }, - }, - } - - executeTestCase(t, test) -} From de0052c0d88a2301786878934bf510580aca873b Mon Sep 17 00:00:00 2001 From: Shahzad Lone Date: Thu, 14 Sep 2023 10:33:22 -0400 Subject: [PATCH 2/3] PR: Add the explain tests converted to new setup --- .../explain/default/with_average_join_test.go | 127 +++++++++ .../explain/default/with_count_join_test.go | 262 ++++++++++++++++++ tests/integration/explain/fixture.go | 1 + 3 files changed, 390 insertions(+) diff --git a/tests/integration/explain/default/with_average_join_test.go b/tests/integration/explain/default/with_average_join_test.go index a48a1b97d2..1612455e57 100644 --- a/tests/integration/explain/default/with_average_join_test.go +++ b/tests/integration/explain/default/with_average_join_test.go @@ -347,3 +347,130 @@ func TestDefaultExplainRequestWithAverageOnMultipleJoinedFieldsWithFilter(t *tes explainUtils.ExecuteTestCase(t, test) } + +// This test asserts that only a single index join is used (not parallelNode) because the +// _avg reuses the rendered join as they have matching filters (average adds a ne nil filter). +func TestDefaultExplainRequestOneToManyWithAverageAndChildNeNilFilterSharesJoinField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (default) 1-to-M relation request from many side with average filter shared.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain { + Author { + name + _avg(books: {field: rating}) + books(filter: {rating: {_ne: null}}){ + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "averageNode": dataMap{ + "countNode": dataMap{ + "sumNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": normalTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + + ExpectedFullGraph: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "averageNode": dataMap{ + "countNode": dataMap{ + "sources": []dataMap{ + { + "filter": dataMap{ + "rating": dataMap{ + "_ne": nil, + }, + }, + "fieldName": "books", + }, + }, + "sumNode": dataMap{ + "sources": []dataMap{ + { + "filter": dataMap{ + "rating": dataMap{ + "_ne": nil, + }, + }, + "fieldName": "books", + "childFieldName": "rating", + }, + }, + "selectNode": dataMap{ + "_keys": nil, + "filter": nil, + "typeIndexJoin": dataMap{ + "joinType": "typeJoinMany", + "rootName": "author", + "root": dataMap{ + "scanNode": dataMap{ + "filter": nil, + "collectionID": "3", + "collectionName": "Author", + "spans": []dataMap{ + { + "start": "/3", + "end": "/4", + }, + }, + }, + }, + "subTypeName": "books", + "subType": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "_keys": nil, + "filter": nil, + "scanNode": dataMap{ + "filter": dataMap{ + "rating": dataMap{ + "_ne": nil, + }, + }, + "collectionID": "2", + "collectionName": "Book", + "spans": []dataMap{ + { + "start": "/2", + "end": "/3", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/default/with_count_join_test.go b/tests/integration/explain/default/with_count_join_test.go index 6c116529a7..30ec8011fb 100644 --- a/tests/integration/explain/default/with_count_join_test.go +++ b/tests/integration/explain/default/with_count_join_test.go @@ -260,3 +260,265 @@ func TestDefaultExplainRequestWithCountOnOneToManyJoinedFieldWithManySources(t * explainUtils.ExecuteTestCase(t, test) } + +// This test asserts that only a single index join is used (not parallelNode) because the +// _count reuses the rendered join as they have matching filters. +func TestDefaultExplainRequestOneToManyWithCountWithFilterAndChildFilterSharesJoinField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (default) 1-to-M relation request from many side with count filter shared.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain { + Author { + name + _count(books: {filter: {rating: {_ne: null}}}) + books(filter: {rating: {_ne: null}}){ + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "countNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": normalTypeJoinPattern, + }, + }, + }, + }, + }, + }, + + ExpectedFullGraph: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "countNode": dataMap{ + "sources": []dataMap{ + { + "filter": dataMap{ + "rating": dataMap{ + "_ne": nil, + }, + }, + "fieldName": "books", + }, + }, + "selectNode": dataMap{ + "_keys": nil, + "filter": nil, + "typeIndexJoin": dataMap{ + "joinType": "typeJoinMany", + "rootName": "author", + "root": dataMap{ + "scanNode": dataMap{ + "filter": nil, + "collectionID": "3", + "collectionName": "Author", + "spans": []dataMap{ + { + "start": "/3", + "end": "/4", + }, + }, + }, + }, + "subTypeName": "books", + "subType": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "_keys": nil, + "filter": nil, + "scanNode": dataMap{ + "filter": dataMap{ + "rating": dataMap{ + "_ne": nil, + }, + }, + "collectionID": "2", + "collectionName": "Book", + "spans": []dataMap{ + { + "start": "/2", + "end": "/3", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +// This test asserts that two joins are used (with parallelNode) because _count cannot +// reuse the rendered join as they dont have matching filters. +func TestDefaultExplainRequestOneToManyWithCountAndChildFilterDoesNotShareJoinField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (default) 1-to-M relation request from many side with count filter not shared.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain { + Author { + name + _count(books: {}) + books(filter: {rating: {_ne: null}}){ + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "countNode": dataMap{ + "selectNode": dataMap{ + "parallelNode": []dataMap{ + { + "typeIndexJoin": normalTypeJoinPattern, + }, + { + "typeIndexJoin": normalTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + + ExpectedFullGraph: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "countNode": dataMap{ + "sources": []dataMap{ + { + "fieldName": "books", + "filter": nil, + }, + }, + "selectNode": dataMap{ + "_keys": nil, + "filter": nil, + "parallelNode": []dataMap{ + { + "typeIndexJoin": dataMap{ + "joinType": "typeJoinMany", + "rootName": "author", + "root": dataMap{ + "scanNode": dataMap{ + "collectionID": "3", + "collectionName": "Author", + "filter": nil, + "spans": []dataMap{ + { + "start": "/3", + "end": "/4", + }, + }, + }, + }, + "subTypeName": "books", + "subType": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "_keys": nil, + "filter": nil, + "scanNode": dataMap{ + "collectionID": "2", + "collectionName": "Book", + "filter": dataMap{ + "rating": dataMap{ + "_ne": nil, + }, + }, + "spans": []dataMap{ + { + "start": "/2", + "end": "/3", + }, + }, + }, + }, + }, + }, + }, + }, + { + "typeIndexJoin": dataMap{ + "joinType": "typeJoinMany", + "rootName": "author", + "root": dataMap{ + "scanNode": dataMap{ + "collectionID": "3", + "collectionName": "Author", + "filter": nil, + "spans": []dataMap{ + { + "start": "/3", + "end": "/4", + }, + }, + }, + }, + "subTypeName": "books", + "subType": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "_keys": nil, + "filter": nil, + "scanNode": dataMap{ + "collectionID": "2", + "collectionName": "Book", + "filter": nil, + "spans": []dataMap{ + { + "start": "/2", + "end": "/3", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/fixture.go b/tests/integration/explain/fixture.go index 31b819e650..c531d95a84 100644 --- a/tests/integration/explain/fixture.go +++ b/tests/integration/explain/fixture.go @@ -27,6 +27,7 @@ var SchemaForExplainTests = testUtils.SchemaUpdate{ type Book { name: String author: Author + rating: Float pages: Int chapterPages: [Int!] } From b31e934888bafa7d9a2bd57588c1e7de983ba2c6 Mon Sep 17 00:00:00 2001 From: Shahzad Lone Date: Thu, 14 Sep 2023 10:37:02 -0400 Subject: [PATCH 3/3] PR: Shrink the tests furthur as we only care about the pattern showing typeIndexJoin with or without parallelNode. --- .../explain/default/with_average_join_test.go | 81 --------- .../explain/default/with_count_join_test.go | 171 ------------------ 2 files changed, 252 deletions(-) diff --git a/tests/integration/explain/default/with_average_join_test.go b/tests/integration/explain/default/with_average_join_test.go index 1612455e57..265ca932ce 100644 --- a/tests/integration/explain/default/with_average_join_test.go +++ b/tests/integration/explain/default/with_average_join_test.go @@ -387,87 +387,6 @@ func TestDefaultExplainRequestOneToManyWithAverageAndChildNeNilFilterSharesJoinF }, }, }, - - ExpectedFullGraph: []dataMap{ - { - "explain": dataMap{ - "selectTopNode": dataMap{ - "averageNode": dataMap{ - "countNode": dataMap{ - "sources": []dataMap{ - { - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "fieldName": "books", - }, - }, - "sumNode": dataMap{ - "sources": []dataMap{ - { - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "fieldName": "books", - "childFieldName": "rating", - }, - }, - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "typeIndexJoin": dataMap{ - "joinType": "typeJoinMany", - "rootName": "author", - "root": dataMap{ - "scanNode": dataMap{ - "filter": nil, - "collectionID": "3", - "collectionName": "Author", - "spans": []dataMap{ - { - "start": "/3", - "end": "/4", - }, - }, - }, - }, - "subTypeName": "books", - "subType": dataMap{ - "selectTopNode": dataMap{ - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "scanNode": dataMap{ - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "collectionID": "2", - "collectionName": "Book", - "spans": []dataMap{ - { - "start": "/2", - "end": "/3", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, }, }, } diff --git a/tests/integration/explain/default/with_count_join_test.go b/tests/integration/explain/default/with_count_join_test.go index 30ec8011fb..3f7802820d 100644 --- a/tests/integration/explain/default/with_count_join_test.go +++ b/tests/integration/explain/default/with_count_join_test.go @@ -296,72 +296,6 @@ func TestDefaultExplainRequestOneToManyWithCountWithFilterAndChildFilterSharesJo }, }, }, - - ExpectedFullGraph: []dataMap{ - { - "explain": dataMap{ - "selectTopNode": dataMap{ - "countNode": dataMap{ - "sources": []dataMap{ - { - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "fieldName": "books", - }, - }, - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "typeIndexJoin": dataMap{ - "joinType": "typeJoinMany", - "rootName": "author", - "root": dataMap{ - "scanNode": dataMap{ - "filter": nil, - "collectionID": "3", - "collectionName": "Author", - "spans": []dataMap{ - { - "start": "/3", - "end": "/4", - }, - }, - }, - }, - "subTypeName": "books", - "subType": dataMap{ - "selectTopNode": dataMap{ - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "scanNode": dataMap{ - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "collectionID": "2", - "collectionName": "Book", - "spans": []dataMap{ - { - "start": "/2", - "end": "/3", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, }, }, } @@ -411,111 +345,6 @@ func TestDefaultExplainRequestOneToManyWithCountAndChildFilterDoesNotShareJoinFi }, }, }, - - ExpectedFullGraph: []dataMap{ - { - "explain": dataMap{ - "selectTopNode": dataMap{ - "countNode": dataMap{ - "sources": []dataMap{ - { - "fieldName": "books", - "filter": nil, - }, - }, - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "parallelNode": []dataMap{ - { - "typeIndexJoin": dataMap{ - "joinType": "typeJoinMany", - "rootName": "author", - "root": dataMap{ - "scanNode": dataMap{ - "collectionID": "3", - "collectionName": "Author", - "filter": nil, - "spans": []dataMap{ - { - "start": "/3", - "end": "/4", - }, - }, - }, - }, - "subTypeName": "books", - "subType": dataMap{ - "selectTopNode": dataMap{ - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "scanNode": dataMap{ - "collectionID": "2", - "collectionName": "Book", - "filter": dataMap{ - "rating": dataMap{ - "_ne": nil, - }, - }, - "spans": []dataMap{ - { - "start": "/2", - "end": "/3", - }, - }, - }, - }, - }, - }, - }, - }, - { - "typeIndexJoin": dataMap{ - "joinType": "typeJoinMany", - "rootName": "author", - "root": dataMap{ - "scanNode": dataMap{ - "collectionID": "3", - "collectionName": "Author", - "filter": nil, - "spans": []dataMap{ - { - "start": "/3", - "end": "/4", - }, - }, - }, - }, - "subTypeName": "books", - "subType": dataMap{ - "selectTopNode": dataMap{ - "selectNode": dataMap{ - "_keys": nil, - "filter": nil, - "scanNode": dataMap{ - "collectionID": "2", - "collectionName": "Book", - "filter": nil, - "spans": []dataMap{ - { - "start": "/2", - "end": "/3", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, }, }, }