diff --git a/client/request/explain.go b/client/request/explain.go index ee8cb2b388..36d5df4cbe 100644 --- a/client/request/explain.go +++ b/client/request/explain.go @@ -17,4 +17,5 @@ type ExplainType string const ( SimpleExplain ExplainType = "simple" ExecuteExplain ExplainType = "execute" + DebugExplain ExplainType = "debug" ) diff --git a/planner/explain.go b/planner/explain.go index 0f669fd55e..560063b4ba 100644 --- a/planner/explain.go +++ b/planner/explain.go @@ -56,14 +56,114 @@ const ( dataLabel = "data" fieldNameLabel = "fieldName" filterLabel = "filter" - keysLabel = "_keys" idsLabel = "ids" + joinRootLabel = "root" + joinSubTypeLabel = "subType" + keysLabel = "_keys" limitLabel = "limit" offsetLabel = "offset" sourcesLabel = "sources" spansLabel = "spans" ) +// buildDebugExplainGraph dumps the entire plan graph as is, with all the plan nodes. +// +// Note: This also includes plan nodes that aren't "explainable". +func buildDebugExplainGraph(source planNode) (map[string]any, error) { + explainGraph := map[string]any{} + + if source == nil { + return explainGraph, nil + } + + switch node := source.(type) { + // Walk the multiple children if it is a MultiNode. + case MultiNode: + multiChildExplainGraph := []map[string]any{} + for _, childSource := range node.Children() { + childExplainGraph, err := buildDebugExplainGraph(childSource) + if err != nil { + return nil, err + } + multiChildExplainGraph = append(multiChildExplainGraph, childExplainGraph) + } + nodeLabelTitle := strcase.ToLowerCamel(node.Kind()) + explainGraph[nodeLabelTitle] = multiChildExplainGraph + + case *typeJoinMany: + var explainGraphBuilder = map[string]any{} + + // If root is not the last child then keep walking and explaining the root graph. + if node.root != nil { + indexJoinRootExplainGraph, err := buildDebugExplainGraph(node.root) + if err != nil { + return nil, err + } + // Add the explaination of the rest of the explain graph under the "root" graph. + explainGraphBuilder[joinRootLabel] = indexJoinRootExplainGraph + } + + if node.subType != nil { + indexJoinSubTypeExplainGraph, err := buildDebugExplainGraph(node.subType) + if err != nil { + return nil, err + } + // Add the explaination of the rest of the explain graph under the "subType" graph. + explainGraphBuilder[joinSubTypeLabel] = indexJoinSubTypeExplainGraph + } + + nodeLabelTitle := strcase.ToLowerCamel(node.Kind()) + explainGraph[nodeLabelTitle] = explainGraphBuilder + + case *typeJoinOne: + var explainGraphBuilder = map[string]any{} + + // If root is not the last child then keep walking and explaining the root graph. + if node.root != nil { + indexJoinRootExplainGraph, err := buildDebugExplainGraph(node.root) + if err != nil { + return nil, err + } + // Add the explaination of the rest of the explain graph under the "root" graph. + explainGraphBuilder[joinRootLabel] = indexJoinRootExplainGraph + } else { + explainGraphBuilder[joinRootLabel] = nil + } + + if node.subType != nil { + indexJoinSubTypeExplainGraph, err := buildDebugExplainGraph(node.subType) + if err != nil { + return nil, err + } + // Add the explaination of the rest of the explain graph under the "subType" graph. + explainGraphBuilder[joinSubTypeLabel] = indexJoinSubTypeExplainGraph + } else { + explainGraphBuilder[joinSubTypeLabel] = nil + } + + nodeLabelTitle := strcase.ToLowerCamel(node.Kind()) + explainGraph[nodeLabelTitle] = explainGraphBuilder + + default: + var explainGraphBuilder = map[string]any{} + + // If not the last child then keep walking the graph to find more plan nodes. + // Also make sure the next source / child isn't a recursive `topLevelNode`. + if next := node.Source(); next != nil && next.Kind() != topLevelNodeKind { + var err error + explainGraphBuilder, err = buildDebugExplainGraph(next) + if err != nil { + return nil, err + } + } + // Add the graph of the next node under current node. + nodeLabelTitle := strcase.ToLowerCamel(node.Kind()) + explainGraph[nodeLabelTitle] = explainGraphBuilder + } + + return explainGraph, nil +} + // buildSimpleExplainGraph builds the explainGraph from the given top level plan. // // Request: @@ -135,7 +235,7 @@ func buildSimpleExplainGraph(source planNode) (map[string]any, error) { return nil, err } // Add the explaination of the rest of the explain graph under the "root" graph. - indexJoinGraph["root"] = indexJoinRootExplainGraph + indexJoinGraph[joinRootLabel] = indexJoinRootExplainGraph } // Add this restructured typeIndexJoin explain graph. explainGraph[strcase.ToLowerCamel(node.Kind())] = indexJoinGraph @@ -346,6 +446,22 @@ func (p *Planner) explainRequest( return explainResult, nil + case request.DebugExplain: + // walks through the plan graph, and outputs the concrete planNodes that should + // be executed, maintaining their order in the plan graph (does not actually execute them). + explainGraph, err := buildDebugExplainGraph(plan) + if err != nil { + return nil, err + } + + explainResult := []map[string]any{ + { + request.ExplainLabel: explainGraph, + }, + } + + return explainResult, nil + case request.ExecuteExplain: return p.executeAndExplainRequest(ctx, plan) diff --git a/planner/type_join.go b/planner/type_join.go index 2bb26cab08..9d3d982c0e 100644 --- a/planner/type_join.go +++ b/planner/type_join.go @@ -138,7 +138,6 @@ func (n *typeIndexJoin) simpleExplain() (map[string]any, error) { joinDirectionLabel = "direction" joinDirectionPrimaryLabel = "primary" joinDirectionSecondaryLabel = "secondary" - joinSubTypeLabel = "subType" joinSubTypeNameLabel = "subTypeName" joinRootLabel = "rootName" ) diff --git a/request/graphql/parser/request.go b/request/graphql/parser/request.go index b2680971bc..31f59b7e2f 100644 --- a/request/graphql/parser/request.go +++ b/request/graphql/parser/request.go @@ -145,6 +145,9 @@ func parseExplainDirective(astDirective *ast.Directive) (immutable.Option[reques case schemaTypes.ExplainArgExecute: return immutable.Some(request.ExecuteExplain), nil + case schemaTypes.ExplainArgDebug: + return immutable.Some(request.DebugExplain), nil + default: return immutable.None[request.ExplainType](), ErrUnknownExplainType } diff --git a/request/graphql/schema/types/types.go b/request/graphql/schema/types/types.go index ae01b30255..530b6c55c5 100644 --- a/request/graphql/schema/types/types.go +++ b/request/graphql/schema/types/types.go @@ -22,6 +22,7 @@ const ( ExplainArgNameType string = "type" ExplainArgSimple string = "simple" ExplainArgExecute string = "execute" + ExplainArgDebug string = "debug" ) var ( @@ -53,6 +54,11 @@ var ( Value: ExplainArgExecute, Description: "Deeper explaination - insights gathered by executing the plan graph.", }, + + ExplainArgDebug: &gql.EnumValueConfig{ + Value: ExplainArgDebug, + Description: "Like simple explain, but more verbose nodes (no attributes).", + }, }, }) diff --git a/tests/integration/explain/debug/basic_test.go b/tests/integration/explain/debug/basic_test.go new file mode 100644 index 0000000000..f97305d091 --- /dev/null +++ b/tests/integration/explain/debug/basic_test.go @@ -0,0 +1,41 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequest(t *testing.T) { + test := testUtils.TestCase{ + Description: "Explain (debug) a basic request, assert full graph.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + Request: `query @explain(type: debug) { + Author { + name + age + } + }`, + + ExpectedFullGraph: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/create_test.go b/tests/integration/explain/debug/create_test.go new file mode 100644 index 0000000000..029c0eaefe --- /dev/null +++ b/tests/integration/explain/debug/create_test.go @@ -0,0 +1,78 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var createPattern = dataMap{ + "explain": dataMap{ + "createNode": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, +} + +func TestDebugExplainMutationRequestWithCreate(t *testing.T) { + test := testUtils.TestCase{ + Description: "Explain (debug) mutation request with create.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + create_Author(data: "{\"name\": \"Shahzad Lone\",\"age\": 27,\"verified\": true}") { + name + age + } + }`, + + ExpectedPatterns: []dataMap{createPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainMutationRequestDoesNotCreateDocGivenDuplicate(t *testing.T) { + test := testUtils.TestCase{ + Description: "Explain (debug) mutation request with create, document exists.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + create_Author(data: "{\"name\": \"Shahzad Lone\",\"age\": 27}") { + name + age + } + }`, + + ExpectedPatterns: []dataMap{createPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/dagscan_test.go b/tests/integration/explain/debug/dagscan_test.go new file mode 100644 index 0000000000..647d378907 --- /dev/null +++ b/tests/integration/explain/debug/dagscan_test.go @@ -0,0 +1,188 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var dagScanPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "dagScanNode": dataMap{}, + }, + }, + }, +} + +func TestDebugExplainCommitsDagScanQueryOp(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) commits query-op.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + commits (dockey: "bae-41598f0c-19bc-5da6-813b-e80f14a10df3", fieldId: "1") { + links { + cid + } + } + }`, + + ExpectedFullGraph: []dataMap{dagScanPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainCommitsDagScanQueryOpWithoutField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) commits query-op with only dockey (no field).", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + commits (dockey: "bae-41598f0c-19bc-5da6-813b-e80f14a10df3") { + links { + cid + } + } + }`, + + ExpectedFullGraph: []dataMap{dagScanPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainLatestCommitsDagScanQueryOp(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) latestCommits query-op.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + latestCommits(dockey: "bae-41598f0c-19bc-5da6-813b-e80f14a10df3", fieldId: "1") { + cid + links { + cid + } + } + }`, + + ExpectedFullGraph: []dataMap{dagScanPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainLatestCommitsDagScanQueryOpWithoutField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) latestCommits query-op with only dockey (no field).", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + latestCommits(dockey: "bae-41598f0c-19bc-5da6-813b-e80f14a10df3") { + cid + links { + cid + } + } + }`, + + ExpectedFullGraph: []dataMap{dagScanPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainLatestCommitsDagScanWithoutDocKey_Failure(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) latestCommits query without DocKey.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + latestCommits(fieldId: "1") { + cid + links { + cid + } + } + }`, + + ExpectedError: "Field \"latestCommits\" argument \"dockey\" of type \"ID!\" is required but not provided.", + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainLatestCommitsDagScanWithoutAnyArguments_Failure(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) latestCommits query without any arguments.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + latestCommits { + cid + links { + cid + } + } + }`, + + ExpectedError: "Field \"latestCommits\" argument \"dockey\" of type \"ID!\" is required but not provided.", + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/delete_test.go b/tests/integration/explain/debug/delete_test.go new file mode 100644 index 0000000000..083c6163c2 --- /dev/null +++ b/tests/integration/explain/debug/delete_test.go @@ -0,0 +1,185 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var deletePattern = dataMap{ + "explain": dataMap{ + "deleteNode": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, +} + +func TestDebugExplainMutationRequestWithDeleteUsingFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) mutation request with delete using filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + delete_Author(filter: {name: {_eq: "Shahzad"}}) { + _key + } + }`, + + ExpectedPatterns: []dataMap{deletePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainMutationRequestWithDeleteUsingFilterToMatchEverything(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) mutation request with delete using filter to match everything.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + delete_Author(filter: {}) { + DeletedKeyByFilter: _key + } + }`, + + ExpectedPatterns: []dataMap{deletePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainMutationRequestWithDeleteUsingId(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) mutation request with delete using id.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + delete_Author(id: "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d") { + _key + } + }`, + + ExpectedPatterns: []dataMap{deletePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainMutationRequestWithDeleteUsingIds(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) mutation request with delete using ids.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + delete_Author(ids: [ + "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d", + "bae-bfbfc89c-0d63-5ea4-81a3-3ebd295be67f" + ]) { + AliasKey: _key + } + }`, + + ExpectedPatterns: []dataMap{deletePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainMutationRequestWithDeleteUsingNoIds(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) mutation request with delete using no ids.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + delete_Author(ids: []) { + _key + } + }`, + + ExpectedPatterns: []dataMap{deletePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainMutationRequestWithDeleteUsingFilterAndIds(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) mutation request with delete using filter and ids.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + delete_Author( + ids: ["bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d", "test"], + filter: { + _and: [ + {age: {_lt: 26}}, + {verified: {_eq: true}}, + ] + } + ) { + _key + } + }`, + + ExpectedPatterns: []dataMap{deletePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/delete_with_error_test.go b/tests/integration/explain/debug/delete_with_error_test.go new file mode 100644 index 0000000000..208106e098 --- /dev/null +++ b/tests/integration/explain/debug/delete_with_error_test.go @@ -0,0 +1,45 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainMutationRequestWithDeleteHavingNoSubSelection(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) multation request with delete having no sub-selection.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + delete_Author( + ids: [ + "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d", + "bae-bfbfc89c-0d63-5ea4-81a3-3ebd295be67f" + ] + ) + }`, + + ExpectedError: "Field \"delete_Author\" of type \"[Author]\" must have a sub selection.", + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/fixture.go b/tests/integration/explain/debug/fixture.go new file mode 100644 index 0000000000..f77c0a3839 --- /dev/null +++ b/tests/integration/explain/debug/fixture.go @@ -0,0 +1,23 @@ +// Copyright 2023 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 test_explain_debug + +type dataMap = map[string]any + +var basicPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, +} diff --git a/tests/integration/explain/debug/group_test.go b/tests/integration/explain/debug/group_test.go new file mode 100644 index 0000000000..af738627b8 --- /dev/null +++ b/tests/integration/explain/debug/group_test.go @@ -0,0 +1,86 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var groupPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "groupNode": dataMap{ + "selectNode": dataMap{ + "pipeNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithGroupByOnParent(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with group-by on parent.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author (groupBy: [age]) { + age + _group { + name + } + } + }`, + + ExpectedFullGraph: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithGroupByTwoFieldsOnParent(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with group-by two fields on parent.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author (groupBy: [age, name]) { + age + _group { + name + } + } + }`, + + ExpectedFullGraph: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/group_with_average_test.go b/tests/integration/explain/debug/group_with_average_test.go new file mode 100644 index 0000000000..e001c1a529 --- /dev/null +++ b/tests/integration/explain/debug/group_with_average_test.go @@ -0,0 +1,157 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var debugGroupAveragePattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "averageNode": dataMap{ + "countNode": dataMap{ + "sumNode": dataMap{ + "groupNode": dataMap{ + "selectNode": dataMap{ + "pipeNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithGroupByWithAverageOnAnInnerField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with group-by with average on inner field.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author (groupBy: [name]) { + name + _avg(_group: {field: age}) + } + }`, + + ExpectedPatterns: []dataMap{debugGroupAveragePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithAverageInsideTheInnerGroupOnAField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with group-by with average of the inner _group on a field.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author (groupBy: [name]) { + name + _avg(_group: {field: _avg}) + _group(groupBy: [verified]) { + verified + _avg(_group: {field: age}) + } + } + }`, + + ExpectedPatterns: []dataMap{debugGroupAveragePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithAverageInsideTheInnerGroupOnAFieldAndNestedGroupBy(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with group-by with average of the inner _group on a field and nested group-by.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author (groupBy: [name]) { + name + _avg(_group: {field: _avg}) + _group(groupBy: [verified]) { + verified + _avg(_group: {field: age}) + _group (groupBy: [age]){ + age + } + } + } + }`, + + ExpectedPatterns: []dataMap{debugGroupAveragePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithAverageInsideTheInnerGroupAndNestedGroupByWithAverage(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with average inside the inner _group and nested groupBy with average.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author (groupBy: [name]) { + name + _avg(_group: {field: _avg}) + _group(groupBy: [verified]) { + verified + _avg(_group: {field: age}) + _group (groupBy: [age]){ + age + _avg(_group: {field: age}) + } + } + } + }`, + + ExpectedPatterns: []dataMap{debugGroupAveragePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/group_with_dockey_child_test.go b/tests/integration/explain/debug/group_with_dockey_child_test.go new file mode 100644 index 0000000000..bc6555b961 --- /dev/null +++ b/tests/integration/explain/debug/group_with_dockey_child_test.go @@ -0,0 +1,47 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithDockeysOnInnerGroupSelection(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with dockeys on inner _group.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + groupBy: [age] + ) { + age + _group(dockeys: ["bae-6a4c5bc5-b044-5a03-a868-8260af6f2254"]) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/group_with_dockey_test.go b/tests/integration/explain/debug/group_with_dockey_test.go new file mode 100644 index 0000000000..fc53731c6a --- /dev/null +++ b/tests/integration/explain/debug/group_with_dockey_test.go @@ -0,0 +1,82 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithDockeyOnParentGroupBy(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with a dockey on parent groupBy.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + groupBy: [age], + dockey: "bae-6a4c5bc5-b044-5a03-a868-8260af6f2254" + ) { + age + _group { + name + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithDockeysAndFilterOnParentGroupBy(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with dockeys and filter on parent groupBy.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + groupBy: [age], + filter: {age: {_eq: 20}}, + dockeys: [ + "bae-6a4c5bc5-b044-5a03-a868-8260af6f2254", + "bae-4ea9d148-13f3-5a48-a0ef-9ffd344caeed" + ] + ) { + age + _group { + name + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/group_with_filter_child_test.go b/tests/integration/explain/debug/group_with_filter_child_test.go new file mode 100644 index 0000000000..61a8a72f3e --- /dev/null +++ b/tests/integration/explain/debug/group_with_filter_child_test.go @@ -0,0 +1,75 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithFilterOnInnerGroupSelection(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with filter on the inner _group selection.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author (groupBy: [age]) { + age + _group(filter: {age: {_gt: 63}}) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithFilterOnParentGroupByAndInnerGroupSelection(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with filter on parent groupBy and on the inner _group selection.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author ( + groupBy: [age], + filter: {age: {_gt: 62}} + ) { + age + _group(filter: {age: {_gt: 63}}) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/group_with_filter_test.go b/tests/integration/explain/debug/group_with_filter_test.go new file mode 100644 index 0000000000..b55d798c3a --- /dev/null +++ b/tests/integration/explain/debug/group_with_filter_test.go @@ -0,0 +1,48 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithFilterOnGroupByParent(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with filter on parent groupBy.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author ( + groupBy: [age], + filter: {age: {_gt: 63}} + ) { + age + _group { + name + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/group_with_limit_child_test.go b/tests/integration/explain/debug/group_with_limit_child_test.go new file mode 100644 index 0000000000..335c8866f0 --- /dev/null +++ b/tests/integration/explain/debug/group_with_limit_child_test.go @@ -0,0 +1,75 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithLimitAndOffsetOnInnerGroupSelection(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with limit and offset on inner _group selection.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(groupBy: [name]) { + name + _group(limit: 2, offset: 1) { + age + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithLimitAndOffsetOnMultipleInnerGroupSelections(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with limit and offset on multiple inner _group selections.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(groupBy: [name]) { + name + innerFirstGroup: _group(limit: 1, offset: 2) { + age + } + innerSecondGroup: _group(limit: 2) { + age + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/group_with_limit_test.go b/tests/integration/explain/debug/group_with_limit_test.go new file mode 100644 index 0000000000..82c84969fc --- /dev/null +++ b/tests/integration/explain/debug/group_with_limit_test.go @@ -0,0 +1,95 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var debugGroupLimitPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "limitNode": dataMap{ + "groupNode": dataMap{ + "selectNode": dataMap{ + "pipeNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithLimitAndOffsetOnParentGroupBy(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with limit and offset on parent groupBy.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + groupBy: [name], + limit: 1, + offset: 1 + ) { + name + _group { + age + } + } + }`, + + ExpectedPatterns: []dataMap{debugGroupLimitPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithLimitOnParentGroupByAndInnerGroupSelection(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with limit and offset on parent groupBy and inner _group selection.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + groupBy: [name], + limit: 1 + ) { + name + _group(limit: 2) { + age + } + } + }`, + + ExpectedPatterns: []dataMap{debugGroupLimitPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/group_with_order_child_test.go b/tests/integration/explain/debug/group_with_order_child_test.go new file mode 100644 index 0000000000..19d97424dc --- /dev/null +++ b/tests/integration/explain/debug/group_with_order_child_test.go @@ -0,0 +1,105 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithDescendingOrderOnInnerGroupSelection(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with order (descending) on inner _group selection.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(groupBy: [name]) { + name + _group (order: {age: DESC}){ + age + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithAscendingOrderOnInnerGroupSelection(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with order (ascending) on inner _group selection.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(groupBy: [name]) { + name + _group (order: {age: ASC}){ + age + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithOrderOnNestedParentGroupByAndOnNestedParentsInnerGroupSelection(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with order on nested parent groupBy and on nested parent's inner _group.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(groupBy: [name]) { + name + _group ( + groupBy: [verified], + order: {verified: ASC} + ){ + verified + _group (order: {age: DESC}) { + age + } + } + } + }`, + + ExpectedPatterns: []dataMap{groupPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/group_with_order_test.go b/tests/integration/explain/debug/group_with_order_test.go new file mode 100644 index 0000000000..a7e3b717b0 --- /dev/null +++ b/tests/integration/explain/debug/group_with_order_test.go @@ -0,0 +1,124 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var debugGroupOrderPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "orderNode": dataMap{ + "groupNode": dataMap{ + "selectNode": dataMap{ + "pipeNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithDescendingOrderOnParentGroupBy(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with order (descending) on parent groupBy.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + groupBy: [name], + order: {name: DESC} + ) { + name + _group { + age + } + } + }`, + + ExpectedPatterns: []dataMap{debugGroupOrderPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithAscendingOrderOnParentGroupBy(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with order (ascending) on parent groupBy.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + groupBy: [name], + order: {name: ASC} + ) { + name + _group { + age + } + } + }`, + + ExpectedPatterns: []dataMap{debugGroupOrderPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithOrderOnParentGroupByAndOnInnerGroupSelection(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with order on parent groupBy and inner _group selection.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + groupBy: [name], + order: {name: DESC} + ) { + name + _group (order: {age: ASC}){ + age + } + } + }`, + + ExpectedPatterns: []dataMap{debugGroupOrderPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/top_with_average_test.go b/tests/integration/explain/debug/top_with_average_test.go new file mode 100644 index 0000000000..de16b72c4b --- /dev/null +++ b/tests/integration/explain/debug/top_with_average_test.go @@ -0,0 +1,98 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var topLevelAveragePattern = dataMap{ + "explain": dataMap{ + "topLevelNode": []dataMap{ + { + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + { + "sumNode": dataMap{}, + }, + { + "countNode": dataMap{}, + }, + { + "averageNode": dataMap{}, + }, + }, + }, +} + +func TestDebugExplainTopLevelAverageRequest(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) top-level average request with filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + _avg( + Author: { + field: age + } + ) + }`, + + ExpectedPatterns: []dataMap{topLevelAveragePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainTopLevelAverageRequestWithFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) top-level average request with filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + _avg( + Author: { + field: age, + filter: { + age: { + _gt: 26 + } + } + } + ) + }`, + + ExpectedPatterns: []dataMap{topLevelAveragePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/top_with_count_test.go b/tests/integration/explain/debug/top_with_count_test.go new file mode 100644 index 0000000000..cceb3d1467 --- /dev/null +++ b/tests/integration/explain/debug/top_with_count_test.go @@ -0,0 +1,87 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var topLevelCountPattern = dataMap{ + "explain": dataMap{ + "topLevelNode": []dataMap{ + { + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + { + "countNode": dataMap{}, + }, + }, + }, +} + +func TestDebugExplainTopLevelCountRequest(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) top-level count request.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + _count(Author: {}) + }`, + + ExpectedPatterns: []dataMap{topLevelCountPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainTopLevelCountRequestWithFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) top-level count request with filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + _count( + Author: { + filter: { + age: { + _gt: 26 + } + } + } + ) + }`, + + ExpectedPatterns: []dataMap{topLevelCountPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/top_with_sum_test.go b/tests/integration/explain/debug/top_with_sum_test.go new file mode 100644 index 0000000000..ba2381a7cf --- /dev/null +++ b/tests/integration/explain/debug/top_with_sum_test.go @@ -0,0 +1,92 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var topLevelSumPattern = dataMap{ + "explain": dataMap{ + "topLevelNode": []dataMap{ + { + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + { + "sumNode": dataMap{}, + }, + }, + }, +} + +func TestDebugExplainTopLevelSumRequest(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) top-level sum request.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + _sum( + Author: { + field: age + } + ) + }`, + + ExpectedPatterns: []dataMap{topLevelSumPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainTopLevelSumRequestWithFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) top-level sum request with filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + _sum( + Author: { + field: age, + filter: { + age: { + _gt: 26 + } + } + } + ) + }`, + + ExpectedPatterns: []dataMap{topLevelSumPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/type_join_many_test.go b/tests/integration/explain/debug/type_join_many_test.go new file mode 100644 index 0000000000..85ca3399a5 --- /dev/null +++ b/tests/integration/explain/debug/type_join_many_test.go @@ -0,0 +1,56 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithAOneToManyJoin(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with a 1-to-M join.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + articles { + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": normalTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/type_join_one_test.go b/tests/integration/explain/debug/type_join_one_test.go new file mode 100644 index 0000000000..55b1bc9b57 --- /dev/null +++ b/tests/integration/explain/debug/type_join_one_test.go @@ -0,0 +1,111 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithAOneToOneJoin(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with a 1-to-1 join.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + OnlyEmail: contact { + email + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinOne": normalTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithTwoLevelDeepNestedJoins(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with two level deep nested joins.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + contact { + email + address { + city + } + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinOne": dataMap{ + "root": dataMap{ + "scanNode": dataMap{}, + }, + "subType": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinOne": normalTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/type_join_test.go b/tests/integration/explain/debug/type_join_test.go new file mode 100644 index 0000000000..21608521c4 --- /dev/null +++ b/tests/integration/explain/debug/type_join_test.go @@ -0,0 +1,105 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var normalTypeJoinPattern = dataMap{ + "root": dataMap{ + "scanNode": dataMap{}, + }, + "subType": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, +} + +var debugTypeJoinPattern = dataMap{ + "root": dataMap{ + "multiScanNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + "subType": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, +} + +func TestDebugExplainRequestWith2SingleJoinsAnd1ManyJoin(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with 2 single joins and 1 many join.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + OnlyEmail: contact { + email + } + articles { + name + } + contact { + cell + email + } + } + }`, + + ExpectedFullGraph: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "parallelNode": []dataMap{ + { + "typeIndexJoin": dataMap{ + "typeJoinOne": debugTypeJoinPattern, + }, + }, + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + { + "typeIndexJoin": dataMap{ + "typeJoinOne": debugTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/type_join_with_filter_and_key_test.go b/tests/integration/explain/debug/type_join_with_filter_and_key_test.go new file mode 100644 index 0000000000..5219c5c874 --- /dev/null +++ b/tests/integration/explain/debug/type_join_with_filter_and_key_test.go @@ -0,0 +1,117 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithRelatedAndRegularFilterAndKeys(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with related and regular filter + keys.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + filter: { + name: {_eq: "John Grisham"}, + books: {name: {_eq: "Painted House"}} + }, + dockeys: [ + "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d", + "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f8e" + ] + ) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": normalTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithManyRelatedFiltersAndKey(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with many related filters + key.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + filter: { + name: {_eq: "Cornelia Funke"}, + articles: {name: {_eq: "To my dear readers"}}, + books: {name: {_eq: "Theif Lord"}} + }, + dockeys: ["bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d"] + ) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "parallelNode": []dataMap{ + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/type_join_with_filter_test.go b/tests/integration/explain/debug/type_join_with_filter_test.go new file mode 100644 index 0000000000..2d4940b5bc --- /dev/null +++ b/tests/integration/explain/debug/type_join_with_filter_test.go @@ -0,0 +1,112 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithRelatedAndRegularFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with related and regular filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + filter: { + name: {_eq: "John Grisham"}, + books: {name: {_eq: "Painted House"}} + } + ) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": normalTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithManyRelatedFilters(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with many related filters.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + filter: { + name: {_eq: "Cornelia Funke"}, + articles: {name: {_eq: "To my dear readers"}}, + books: {name: {_eq: "Theif Lord"}} + } + ) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "parallelNode": []dataMap{ + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/update_test.go b/tests/integration/explain/debug/update_test.go new file mode 100644 index 0000000000..8a479837d6 --- /dev/null +++ b/tests/integration/explain/debug/update_test.go @@ -0,0 +1,161 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var updatePattern = dataMap{ + "explain": dataMap{ + "updateNode": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, +} + +func TestDebugExplainMutationRequestWithUpdateUsingBooleanFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) mutation request with update using boolean filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + update_Author( + filter: { + verified: { + _eq: true + } + }, + data: "{\"age\": 59}" + ) { + _key + name + age + } + }`, + + ExpectedPatterns: []dataMap{updatePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainMutationRequestWithUpdateUsingIds(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) mutation request with update using ids.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + update_Author( + ids: [ + "bae-bfbfc89c-0d63-5ea4-81a3-3ebd295be67f", + "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d" + ], + data: "{\"age\": 59}" + ) { + _key + name + age + } + }`, + + ExpectedPatterns: []dataMap{updatePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainMutationRequestWithUpdateUsingId(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) mutation request with update using id.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + update_Author( + id: "bae-bfbfc89c-0d63-5ea4-81a3-3ebd295be67f", + data: "{\"age\": 59}" + ) { + _key + name + age + } + }`, + + ExpectedPatterns: []dataMap{updatePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainMutationRequestWithUpdateUsingIdsAndFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) mutation request with update using both ids and filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `mutation @explain(type: debug) { + update_Author( + filter: { + verified: { + _eq: true + } + }, + ids: [ + "bae-bfbfc89c-0d63-5ea4-81a3-3ebd295be67f", + "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d" + ], + data: "{\"age\": 59}" + ) { + _key + name + age + } + }`, + + ExpectedPatterns: []dataMap{updatePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_average_join_test.go b/tests/integration/explain/debug/with_average_join_test.go new file mode 100644 index 0000000000..63d910d117 --- /dev/null +++ b/tests/integration/explain/debug/with_average_join_test.go @@ -0,0 +1,116 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var debugAverageTypeIndexJoinManyPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "averageNode": dataMap{ + "countNode": dataMap{ + "sumNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": normalTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithAverageOnJoinedField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with average on joined/related field.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + _avg(books: {field: pages}) + } + }`, + + ExpectedPatterns: []dataMap{debugAverageTypeIndexJoinManyPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithAverageOnMultipleJoinedFieldsWithFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with average on multiple joined fields with filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + _avg( + books: {field: pages}, + articles: {field: pages, filter: {pages: {_gt: 3}}} + ) + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "averageNode": dataMap{ + "countNode": dataMap{ + "sumNode": dataMap{ + "selectNode": dataMap{ + "parallelNode": []dataMap{ + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_average_test.go b/tests/integration/explain/debug/with_average_test.go new file mode 100644 index 0000000000..9bc0f70194 --- /dev/null +++ b/tests/integration/explain/debug/with_average_test.go @@ -0,0 +1,59 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var averagePattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "averageNode": dataMap{ + "countNode": dataMap{ + "sumNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithAverageOnArrayField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with average on array field.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Book { + name + _avg(chapterPages: {}) + } + }`, + + ExpectedFullGraph: []dataMap{averagePattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_count_join_test.go b/tests/integration/explain/debug/with_count_join_test.go new file mode 100644 index 0000000000..ae96eeb2c5 --- /dev/null +++ b/tests/integration/explain/debug/with_count_join_test.go @@ -0,0 +1,108 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var debugCountTypeIndexJoinManyPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "countNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": normalTypeJoinPattern, + }, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithCountOnOneToManyJoinedField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with count on a one-to-many joined field.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + numberOfBooks: _count(books: {}) + } + }`, + + ExpectedPatterns: []dataMap{debugCountTypeIndexJoinManyPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithCountOnOneToManyJoinedFieldWithManySources(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with count on a one-to-many joined field with many sources.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + numberOfBooks: _count( + books: {} + articles: {} + ) + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "countNode": dataMap{ + "selectNode": dataMap{ + "parallelNode": []dataMap{ + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_count_test.go b/tests/integration/explain/debug/with_count_test.go new file mode 100644 index 0000000000..ec542bed8e --- /dev/null +++ b/tests/integration/explain/debug/with_count_test.go @@ -0,0 +1,55 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var countPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "countNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithCountOnInlineArrayField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with count on an inline array field.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Book { + name + _count(chapterPages: {}) + } + }`, + + ExpectedPatterns: []dataMap{countPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_filter_key_test.go b/tests/integration/explain/debug/with_filter_key_test.go new file mode 100644 index 0000000000..5ca0939150 --- /dev/null +++ b/tests/integration/explain/debug/with_filter_key_test.go @@ -0,0 +1,159 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithDocKeyFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with dockey filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(dockey: "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d") { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithDocKeysFilterUsingOneKey(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with dockeys filter using one key.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(dockeys: ["bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d"]) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithDocKeysFilterUsingMultipleButDuplicateKeys(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with dockeys filter using multiple but duplicate keys.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + dockeys: [ + "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d", + "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d" + ] + ) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithDocKeysFilterUsingMultipleUniqueKeys(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with dockeys filter using multiple unique keys.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + dockeys: [ + "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d", + "bae-bfbfc89c-0d63-5ea4-81a3-3ebd295be67f" + ] + ) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithMatchingKeyFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with a filter to match key.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + filter: { + _key: { + _eq: "bae-079d0bd8-4b1b-5f5f-bd95-4d915c277f9d" + } + } + ) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_filter_test.go b/tests/integration/explain/debug/with_filter_test.go new file mode 100644 index 0000000000..67f69a406c --- /dev/null +++ b/tests/integration/explain/debug/with_filter_test.go @@ -0,0 +1,168 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithStringEqualFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with string equal (_eq) filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(filter: {name: {_eq: "Lone"}}) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithIntegerEqualFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with integer equal (_eq) filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(filter: {age: {_eq: 26}}) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithGreaterThanFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with greater than (_gt) filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(filter: {age: {_gt: 20}}) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithLogicalCompoundAndFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with logical compound (_and) filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(filter: {_and: [{age: {_gt: 20}}, {age: {_lt: 50}}]}) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithLogicalCompoundOrFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with logical compound (_or) filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(filter: {_or: [{age: {_eq: 55}}, {age: {_eq: 19}}]}) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithMatchInsideList(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request filtering values that match within (_in) a list.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(filter: {age: {_in: [19, 40, 55]}}) { + name + age + } + }`, + + ExpectedPatterns: []dataMap{basicPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_limit_count_test.go b/tests/integration/explain/debug/with_limit_count_test.go new file mode 100644 index 0000000000..84327fdaae --- /dev/null +++ b/tests/integration/explain/debug/with_limit_count_test.go @@ -0,0 +1,120 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +func TestDebugExplainRequestWithOnlyLimitOnRelatedChildWithCount(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with limit on related child with count.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + numberOfArts: _count(articles: {}) + articles(limit: 2) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "countNode": dataMap{ + "selectNode": dataMap{ + "parallelNode": []dataMap{ + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugLimitTypeJoinManyPattern, + }, + }, + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithLimitArgsOnParentAndRelatedChildWithCount(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with limit args on parent and related child with count.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(limit: 3, offset: 1) { + numberOfArts: _count(articles: {}) + articles(limit: 2) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "limitNode": dataMap{ + "countNode": dataMap{ + "selectNode": dataMap{ + "parallelNode": []dataMap{ + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugLimitTypeJoinManyPattern, + }, + }, + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_limit_join_test.go b/tests/integration/explain/debug/with_limit_join_test.go new file mode 100644 index 0000000000..028ac2f69b --- /dev/null +++ b/tests/integration/explain/debug/with_limit_join_test.go @@ -0,0 +1,208 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var limitTypeJoinPattern = dataMap{ + "root": dataMap{ + "scanNode": dataMap{}, + }, + "subType": dataMap{ + "selectTopNode": dataMap{ + "limitNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, +} + +var debugLimitTypeJoinManyPattern = dataMap{ + "root": dataMap{ + "multiScanNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + "subType": dataMap{ + "selectTopNode": dataMap{ + "limitNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithOnlyLimitOnRelatedChild(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with only limit on related child.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + articles(limit: 1) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": limitTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithOnlyOffsetOnRelatedChild(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with only offset on related child.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + articles(offset: 2) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": limitTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithBothLimitAndOffsetOnRelatedChild(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with both limit and offset on related child.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + articles(limit: 2, offset: 2) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": limitTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithLimitOnRelatedChildAndBothLimitAndOffsetOnParent(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with limit on related child & both limit + offset on parent.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(limit: 3, offset: 1) { + name + articles(limit: 2) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "limitNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": limitTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_limit_test.go b/tests/integration/explain/debug/with_limit_test.go new file mode 100644 index 0000000000..993032a364 --- /dev/null +++ b/tests/integration/explain/debug/with_limit_test.go @@ -0,0 +1,102 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var limitPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "limitNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithOnlyLimit(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with only limit.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(limit: 2) { + name + } + }`, + + ExpectedPatterns: []dataMap{limitPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithOnlyOffset(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with only offset.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(offset: 2) { + name + } + }`, + + ExpectedPatterns: []dataMap{limitPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithLimitAndOffset(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with limit and offset.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(limit: 3, offset: 1) { + name + } + }`, + + ExpectedPatterns: []dataMap{limitPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_order_join_test.go b/tests/integration/explain/debug/with_order_join_test.go new file mode 100644 index 0000000000..77190b5941 --- /dev/null +++ b/tests/integration/explain/debug/with_order_join_test.go @@ -0,0 +1,157 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var orderTypeJoinPattern = dataMap{ + "root": dataMap{ + "scanNode": dataMap{}, + }, + "subType": dataMap{ + "selectTopNode": dataMap{ + "orderNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithOrderFieldOnRelatedChild(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with order field on a related child.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + articles(order: {name: DESC}) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": orderTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithOrderFieldOnParentAndRelatedChild(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with order field on parent and related child.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(order: {name: ASC}) { + name + articles(order: {name: DESC}) { + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "orderNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": orderTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWhereParentIsOrderedByItsRelatedChild(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request where parent is ordered by it's related child.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author( + order: { + articles: {name: ASC} + } + ) { + articles { + name + } + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "orderNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": normalTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_order_test.go b/tests/integration/explain/debug/with_order_test.go new file mode 100644 index 0000000000..cdcdfe35ac --- /dev/null +++ b/tests/integration/explain/debug/with_order_test.go @@ -0,0 +1,80 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var orderPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "orderNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithAscendingOrderOnParent(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with ascending order on parent.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(order: {age: ASC}) { + name + age + } + }`, + + ExpectedFullGraph: []dataMap{orderPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithMultiOrderFieldsOnParent(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with multiple order fields on parent.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author(order: {name: ASC, age: DESC}) { + name + age + } + }`, + + ExpectedFullGraph: []dataMap{orderPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_sum_join_test.go b/tests/integration/explain/debug/with_sum_join_test.go new file mode 100644 index 0000000000..66c68be8ed --- /dev/null +++ b/tests/integration/explain/debug/with_sum_join_test.go @@ -0,0 +1,145 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var debugSumTypeIndexJoinManyPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "sumNode": dataMap{ + "selectNode": dataMap{ + "typeIndexJoin": dataMap{ + "typeJoinMany": normalTypeJoinPattern, + }, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithSumOnOneToManyJoinedField(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with sum on a one-to-many joined field.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + _key + TotalPages: _sum( + books: {field: pages} + ) + } + }`, + + ExpectedPatterns: []dataMap{debugSumTypeIndexJoinManyPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithSumOnOneToManyJoinedFieldWithFilter(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with sum on a one-to-many joined field, with filter.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + TotalPages: _sum( + articles: { + field: pages, + filter: { + name: { + _eq: "To my dear readers" + } + } + } + ) + } + }`, + + ExpectedPatterns: []dataMap{debugSumTypeIndexJoinManyPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} + +func TestDebugExplainRequestWithSumOnOneToManyJoinedFieldWithManySources(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with sum on a one-to-many joined field with many sources.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Author { + name + TotalPages: _sum( + books: {field: pages}, + articles: {field: pages} + ) + } + }`, + + ExpectedPatterns: []dataMap{ + { + "explain": dataMap{ + "selectTopNode": dataMap{ + "sumNode": dataMap{ + "selectNode": dataMap{ + "parallelNode": []dataMap{ + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + { + "typeIndexJoin": dataMap{ + "typeJoinMany": debugTypeJoinPattern, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/debug/with_sum_test.go b/tests/integration/explain/debug/with_sum_test.go new file mode 100644 index 0000000000..00ed6ddcc7 --- /dev/null +++ b/tests/integration/explain/debug/with_sum_test.go @@ -0,0 +1,55 @@ +// Copyright 2023 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 test_explain_debug + +import ( + "testing" + + testUtils "github.com/sourcenetwork/defradb/tests/integration" + explainUtils "github.com/sourcenetwork/defradb/tests/integration/explain" +) + +var sumPattern = dataMap{ + "explain": dataMap{ + "selectTopNode": dataMap{ + "sumNode": dataMap{ + "selectNode": dataMap{ + "scanNode": dataMap{}, + }, + }, + }, + }, +} + +func TestDebugExplainRequestWithSumOnInlineArrayField_ChildFieldWillBeEmpty(t *testing.T) { + test := testUtils.TestCase{ + + Description: "Explain (debug) request with sum on an inline array field.", + + Actions: []any{ + explainUtils.SchemaForExplainTests, + + testUtils.ExplainRequest{ + + Request: `query @explain(type: debug) { + Book { + name + NotSureWhySomeoneWouldSumTheChapterPagesButHereItIs: _sum(chapterPages: {}) + } + }`, + + ExpectedPatterns: []dataMap{sumPattern}, + }, + }, + } + + explainUtils.ExecuteTestCase(t, test) +} diff --git a/tests/integration/explain/default/create_test.go b/tests/integration/explain/default/create_test.go index c061e2d2c8..eaecd7879f 100644 --- a/tests/integration/explain/default/create_test.go +++ b/tests/integration/explain/default/create_test.go @@ -83,6 +83,8 @@ func TestDefaultExplainMutationRequestDoesNotCreateDocGivenDuplicate(t *testing. } }`, + ExpectedPatterns: []dataMap{createPattern}, + ExpectedTargets: []testUtils.PlanNodeTargetCase{ { TargetNodeName: "createNode",