Skip to content

Commit

Permalink
fix(GraphQL): Added support for parameterized cascade with variables. (
Browse files Browse the repository at this point in the history
…#7477)

Fixes: GRAPHQL-1007
We haven't added support to pass arguments of parameterized cascade through variables when we added parameterized cascade.
In this PR we have added it and also some tests and validation checks.
  • Loading branch information
JatinDev543 authored Feb 26, 2021
1 parent 3b0e19f commit 97f280f
Show file tree
Hide file tree
Showing 12 changed files with 243 additions and 46 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ require (
github.com/dgraph-io/badger/v3 v3.0.0-20210209201111-6c35ad6c28e0
github.com/dgraph-io/dgo/v200 v200.0.0-20210212152539-e0a5bde40ba2
github.com/dgraph-io/gqlgen v0.13.2
github.com/dgraph-io/gqlparser/v2 v2.1.5
github.com/dgraph-io/gqlparser/v2 v2.1.8
github.com/dgraph-io/graphql-transport-ws v0.0.0-20210223074046-e5b8b80bb4ed
github.com/dgraph-io/ristretto v0.0.4-0.20210223002318-8ec1dc18f880
github.com/dgraph-io/simdjson-go v0.3.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ github.com/dgraph-io/dgo/v200 v200.0.0-20210212152539-e0a5bde40ba2/go.mod h1:zCf
github.com/dgraph-io/gqlgen v0.13.2 h1:TNhndk+eHKj5qE7BenKKSYdSIdOGhLqxR1rCiMso9KM=
github.com/dgraph-io/gqlgen v0.13.2/go.mod h1:iCOrOv9lngN7KAo+jMgvUPVDlYHdf7qDwsTkQby2Sis=
github.com/dgraph-io/gqlparser/v2 v2.1.1/go.mod h1:MYS4jppjyx8b9tuUtjV7jU1UFZK6P9fvO8TsIsQtRKU=
github.com/dgraph-io/gqlparser/v2 v2.1.5 h1:FNFSzyOEZ8gs97SLBtn2Pez9f12emvsQ6Vv6oNtg5rc=
github.com/dgraph-io/gqlparser/v2 v2.1.5/go.mod h1:MYS4jppjyx8b9tuUtjV7jU1UFZK6P9fvO8TsIsQtRKU=
github.com/dgraph-io/gqlparser/v2 v2.1.8 h1:d4CprjlDyMNGvnZG/pKqe6Oj6qQd4V0TVsuOIjCKXWQ=
github.com/dgraph-io/gqlparser/v2 v2.1.8/go.mod h1:MYS4jppjyx8b9tuUtjV7jU1UFZK6P9fvO8TsIsQtRKU=
github.com/dgraph-io/graphql-transport-ws v0.0.0-20210223074046-e5b8b80bb4ed h1:pgGMBoTtFhR+xkyzINaToLYRurHn+6pxMYffIGmmEPc=
github.com/dgraph-io/graphql-transport-ws v0.0.0-20210223074046-e5b8b80bb4ed/go.mod h1:7z3c/5w0sMYYZF5bHsrh8IH4fKwG5O5Y70cPH1ZLLRQ=
github.com/dgraph-io/ristretto v0.0.4-0.20210205182321-f8e4908e34d1/go.mod h1:tv2ec8nA7vRpSYX7/MbP52ihrUMXIHit54CQMq8npXQ=
Expand Down
96 changes: 86 additions & 10 deletions graphql/e2e/common/error_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
[ { "message": "Cannot query field \"getAuthorszzz\" on type \"Query\". Did you mean
\"getAuthor\" or \"getauthor1\"?",
"locations": [ { "line": 2, "column": 3 } ] } ]

-
name: "Unknown field"
gqlrequest: |
query {
getAuthor(id: "0x1") { namezzz }
}
gqlvariables: |
gqlvariables: |
{ }
errors:
[ { "message": "Cannot query field \"namezzz\" on type \"Author\". Did you mean \"name\"?",
Expand All @@ -29,7 +29,7 @@
query {
getAuthor(id: $theID) { name }
}
gqlvariables: |
gqlvariables: |
{ }
errors:
[ { "message": "Variable \"$theID\" is not defined.",
Expand All @@ -41,7 +41,7 @@
query {
queryAuthor(filter: { reputation: { le: "hi there" } }) { name }
}
gqlvariables: |
gqlvariables: |
{ }
errors:
[ { "message": "Expected type Float, found \"hi there\".",
Expand All @@ -53,7 +53,7 @@
query queryAuthor($filter: AuthorFiltarzzz!) {
queryAuthor(filter: $filter) { name }
}
gqlvariables: |
gqlvariables: |
{ "filter": "type was wrong" }
errors:
[ { "message": "Variable type provided AuthorFiltarzzz! is incompatible with expected
Expand All @@ -71,7 +71,7 @@
query queryAuthor($filter: AuthorFilter!) {
queryAuthor(filter: $filter) { name }
}
gqlvariables: |
gqlvariables: |
{ "filter": 57 }
errors:
[ { "message": "must be a AuthorFilter",
Expand Down Expand Up @@ -101,7 +101,7 @@
"locations": [ { "line": 2, "column": 3 } ] } ]

-
name: "@cascade only accepts those fields as a argument, which are present in given type "
name: "@cascade only accepts those fields as a argument, which are present in given type"
gqlrequest: |
query {
queryAuthor @cascade(fields:["title"]){
Expand All @@ -112,7 +112,8 @@
gqlvariables: |
{ }
errors:
[ { "message": "Field `title` is not present in type `Author`. You can only use fields which are in type `Author`",
[ { "message": "Field `title` is not present in type `Author`. You can only use fields in cascade which are in type `Author`",
"locations": [{ "line": 2, "column": 16}]
} ]

-
Expand Down Expand Up @@ -168,7 +169,8 @@
gqlvariables: |
{ }
errors:
[ { "message": "Field `name` is not present in type `AddAuthorPayload`. You can only use fields which are in type `AddAuthorPayload`",
[ { "message": "Field `name` is not present in type `AddAuthorPayload`. You can only use fields in cascade which are in type `AddAuthorPayload`",
"locations": [{ "line": 2, "column": 38}]
} ]

-
Expand Down Expand Up @@ -362,4 +364,78 @@
{ }
errors:
[ { "message": "Int64Filter filter expects only one filter function, got: 2",
"locations": [ { "line": 2, "column": 29 } ] } ]
"locations": [ { "line": 2, "column": 29 } ] } ]

-
name: "@cascade only accepts those fields as a argument, which are present in given type at both root and deep levels"
gqlrequest: |
query {
queryAuthor @cascade(fields: ["dob","reputation"]) {
dob
reputation
posts @cascade(fields: ["text1"]) {
text
title
}
}
}
errors:
[ { "message": "Field `text1` is not present in type `Post`. You can only use fields in cascade which are in type `Post`",
"locations": [{ "line": 5, "column": 10}]
} ]

-
name: "@cascade only accepts those fields as a argument, which are present in given type at deep level using variables"
gqlrequest: |
query($fieldsRoot: [String], $fieldsDeep: [String]) {
queryAuthor @cascade(fields: $fieldsRoot) {
dob
reputation
posts @cascade(fields: $fieldsDeep) {
text
title
}
}
}
gqlvariables: |
{
"fieldsRoot": [
"dob",
"reputation"
],
"fieldsDeep": [
"text1"
]
}
errors:
[ { "message": "input: variables.fieldsDeep.text1 Field `text1` is not present in type `Post`. You can only use fields in cascade which are in type `Post`",
"locations": [{ "line": 5, "column": 10}]
} ]

-
name: "@cascade only accepts those fields as a argument, which are present in given type at root level using variables"
gqlrequest: |
query($fieldsRoot: [String], $fieldsDeep: [String]) {
queryAuthor @cascade(fields: $fieldsRoot) {
dob
reputation
posts @cascade(fields: $fieldsDeep) {
text
title
}
}
}
gqlvariables: |
{
"fieldsRoot": [
"dob",
"reputation1"
],
"fieldsDeep": [
"text"
]
}
errors:
[ { "message": "input: variables.fieldsRoot.reputation1 Field `reputation1` is not present in type `Author`. You can only use fields in cascade which are in type `Author`",
"locations": [{ "line": 2, "column": 15}]
} ]
36 changes: 36 additions & 0 deletions graphql/e2e/common/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -2460,6 +2460,42 @@ func queryWithCascade(t *testing.T) {
]
}`,
},
{
name: "parameterized cascade at all levels using variables",
query: `query ($ids: [ID!],$fieldsRoot: [String], $fieldsDeep: [String]) {
queryAuthor(filter: {id: $ids}) @cascade(fields: $fieldsRoot) {
reputation
name
dob
posts @cascade(fields: $fieldsDeep) {
title
text
}
}
}`,
variables: map[string]interface{}{"ids": authorIds, "fieldsRoot": []string{"reputation", "name"}, "fieldsDeep": []string{"text"}},
respData: `{
"queryAuthor": [
{
"reputation": 4.5,
"name": "George",
"dob": null,
"posts": [
{
"title": "A show about nothing",
"text": "Got ya!"
}
]
},
{
"dob": null,
"name": "Jerry",
"posts": [],
"reputation": 4.6
}
]
}`,
},
{
name: "parameterized cascade on ID type ",
query: `query ($ids: [ID!]) {
Expand Down
8 changes: 5 additions & 3 deletions graphql/resolve/mutation_query_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,6 @@ ADD_UPDATE_MUTATION:
-
name: "can work with skip and filter"
variables:
skip: true
include: false
gqlquery: |
mutation ($skip: Boolean!, $include: Boolean!) {
ADD_UPDATE_MUTATION {
Expand All @@ -142,6 +139,11 @@ ADD_UPDATE_MUTATION:
}
}
}
gqlvariables: |
{
"skip": true,
"include": false
}
dgquery: |-
query {
PAYLOAD_TYPE.post(func: uid(0x4)) {
Expand Down
7 changes: 6 additions & 1 deletion graphql/resolve/mutation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,15 @@ func TestMutationQueryRewriting(t *testing.T) {
gqlMutationStr := strings.Replace(tcase.GQLQuery, testType, tt.mut, 1)
tcase.DGQuery = strings.Replace(tcase.DGQuery, "PAYLOAD_TYPE",
tt.payloadType, 1)
var vars map[string]interface{}
if tcase.GQLVariables != "" {
err := json.Unmarshal([]byte(tcase.GQLVariables), &vars)
require.NoError(t, err)
}
op, err := gqlSchema.Operation(
&schema.Request{
Query: gqlMutationStr,
Variables: tcase.Variables,
Variables: vars,
})
require.NoError(t, err)
gqlMutation := test.GetMutation(t, op)
Expand Down
15 changes: 10 additions & 5 deletions graphql/resolve/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ import (
// Tests showing that the query rewriter produces the expected Dgraph queries

type QueryRewritingCase struct {
Name string
GQLQuery string
Variables map[string]interface{}
DGQuery string
Name string
GQLQuery string
GQLVariables string
DGQuery string
}

func TestQueryRewriting(t *testing.T) {
Expand All @@ -56,10 +56,15 @@ func TestQueryRewriting(t *testing.T) {

for _, tcase := range tests {
t.Run(tcase.Name, func(t *testing.T) {
var vars map[string]interface{}
if tcase.GQLVariables != "" {
err := json.Unmarshal([]byte(tcase.GQLVariables), &vars)
require.NoError(t, err)
}
op, err := gqlSchema.Operation(
&schema.Request{
Query: tcase.GQLQuery,
Variables: tcase.Variables,
Variables: vars,
})
require.NoError(t, err)
gqlQuery := test.GetQuery(t, op)
Expand Down
61 changes: 55 additions & 6 deletions graphql/resolve/query_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1574,9 +1574,6 @@
-
name: "Skip directive"
variables:
skipTrue: true
skipFalse: false
gqlquery: |
query ($skipTrue: Boolean!, $skipFalse: Boolean!) {
getAuthor(id: "0x1") {
Expand All @@ -1587,6 +1584,11 @@
}
}
}
gqlvariables: |
{
"skipTrue": true,
"skipFalse": false
}
dgquery: |-
query {
getAuthor(func: uid(0x1)) @filter(type(Author)) {
Expand All @@ -1597,9 +1599,6 @@
-
name: "Include directive"
variables:
includeTrue: true
includeFalse: false
gqlquery: |
query ($includeTrue: Boolean!, $includeFalse: Boolean!) {
queryAuthor {
Expand All @@ -1609,6 +1608,12 @@
}
}
}
gqlvariables: |
{
"includeTrue": true,
"includeFalse": false
}
dgquery: |-
query {
queryAuthor(func: type(Author)) {
Expand Down Expand Up @@ -1638,6 +1643,13 @@
}
}
}
gqlvariables: |
{
"includeTrue": true,
"includeFalse": false,
"skipTrue": true,
"skipFalse": false
}
dgquery: |-
query {
queryAuthor(func: type(Author)) {
Expand Down Expand Up @@ -1935,6 +1947,43 @@
}
}
-
name: "Parameterized Cascade directive on root and nested field using variables"
gqlquery: |
query($fieldsRoot:[String],$fieldsDeep:[String]) {
queryAuthor @cascade(fields: $fieldsRoot) {
dob
reputation
posts @cascade(fields: $fieldsDeep) {
text
title
}
}
}
gqlvariables: |
{
"fieldsRoot": [
"dob",
"reputation"
],
"fieldsDeep": [
"text"
]
}
dgquery: |-
query {
queryAuthor(func: type(Author)) @cascade(Author.dob, Author.reputation) {
Author.dob : Author.dob
Author.reputation : Author.reputation
Author.posts : Author.posts @cascade(Post.text) {
Post.text : Post.text
Post.title : Post.title
dgraph.uid : uid
}
dgraph.uid : uid
}
}
-
name: "getHuman which implements an interface"
gqlquery: |
Expand Down
Loading

0 comments on commit 97f280f

Please sign in to comment.