Skip to content

Commit

Permalink
fix(GRAPHQL): fix duplicate xid error for multiple xid fields. (#7546)
Browse files Browse the repository at this point in the history
We were getting duplicate xid error for the multiple xid fields if typeName+xidName+xidValue is same for those fields. The reason for this is that we need to generate unique query variables for the xids field while doing mutation rewriting and for that we use a map to variable names.
we were using below key for that map
key = typ.FieldOriginatedFrom(xidName) + xidName + xidVal
This was generating same key for different xid fields. For example in below type we have two fields with id fields

type ABC {
    ab: String! @id
    abc: String! @id
}
And below mutation try to set them such that key = typ.FieldOriginatedFrom(xidName) + xidName + xidVal will be same for both of them i.e. ABC+ab+cd=ABC+abc+d=ABCabcd

mutation {
		addABC(input: [{ ab: "cd", abc: "d" }]) {
		  aBC {
		        ab
		        abc
		       }
		  }
	 }
This error also occur in multiple types.
We now added "." between values to separate typename and xidname , and the xidValue.This will ensure unique keys for xid fields across types.
key = typ.FieldOriginatedFrom(xidName) + "." + xidName + "." + xidVal
  • Loading branch information
JatinDev543 authored Mar 11, 2021
1 parent 06922a1 commit 5c700d0
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 1 deletion.
167 changes: 167 additions & 0 deletions graphql/resolve/add_mutation_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3681,6 +3681,173 @@
"uid": "_:Book2"
}
-
name: "Add mutation with multiple Xid fields shouldn't give error if xidName+xidVal is equal for two different xid fields in a type"
gqlmutation: |
mutation($input: [AddABCInput!]!) {
addABC(input: $input) {
aBC {
ab
abc
}
}
}
gqlvariables: |
{
"input": [
{
"ab": "cd",
"abc": "d"
}
]
}
dgquery: |-
query {
ABC1(func: eq(ABC.ab, "cd")) @filter(type(ABC)) {
uid
}
ABC2(func: eq(ABC.abc, "d")) @filter(type(ABC)) {
uid
}
}
explanation: "We should generate different variables as ABC1 and ABC2 if xidName+xidValue is same as in above case
i.e. ab+cd and abc+d both equals to abcd"
dgmutations:
- setjson: |
{
"ABC.ab": "cd",
"ABC.abc": "d",
"dgraph.type": [
"ABC"
],
"uid":"_:ABC2"
}
-
name: "Add mutation with multiple Xid fields shouldn't give error if xidName+xidVal is equal for two different xid fields in different objects"
gqlmutation: |
mutation($input: [AddABCInput!]!) {
addABC(input: $input) {
aBC {
ab
abc
}
}
}
gqlvariables: |
{
"input": [
{
"ab": "cd",
"abc": "de"
},
{
"ab": "ef",
"abc": "d"
}
]
}
dgquery: |-
query {
ABC1(func: eq(ABC.ab, "cd")) @filter(type(ABC)) {
uid
}
ABC2(func: eq(ABC.abc, "de")) @filter(type(ABC)) {
uid
}
ABC3(func: eq(ABC.ab, "ef")) @filter(type(ABC)) {
uid
}
ABC4(func: eq(ABC.abc, "d")) @filter(type(ABC)) {
uid
}
}
explanation: "We should generate different variables as ABC1 and ABC4 if xidName+xidValue is same in two different objects as in above case
i.e. ab+cd and abc+d both equals to abcd"
dgmutations:
- setjson: |
{
"ABC.ab": "cd",
"ABC.abc": "de",
"dgraph.type": [
"ABC"
],
"uid":"_:ABC2"
}
- setjson: |
{
"ABC.ab": "ef",
"ABC.abc": "d",
"dgraph.type": [
"ABC"
],
"uid":"_:ABC4"
}
-
name: "Add mutation with multiple Xid fields shouldn't give error if typeName+xidName+xidVal is equal for two different xid fields in different types"
gqlmutation: |
mutation($input: [AddABCInput!]!) {
addABC(input: $input) {
aBC {
ab
abc
AB {
Cab
Cabc
}
}
}
}
gqlvariables: |
{
"input": [
{
"ab": "cd",
"abc": "de",
"AB": {
"Cab": "cde",
"Cabc":"d"
}
}
]
}
dgquery: |-
query {
ABC1(func: eq(ABC.ab, "cd")) @filter(type(ABC)) {
uid
}
ABC2(func: eq(ABC.abc, "de")) @filter(type(ABC)) {
uid
}
AB3(func: eq(AB.Cab, "cde")) @filter(type(AB)) {
uid
}
AB4(func: eq(AB.Cabc, "d")) @filter(type(AB)) {
uid
}
}
explanation: "We should generate different variables as ABC1 and AB3, or ABC2 and AB4 if typename+xidName+xidValue is same in two different types as in above case
i.e. ABC+ab+cd and AB+Cabc+d both equals to ABCabcd"
dgmutations:
- setjson: |
{
"ABC.AB": {
"AB.Cab": "cde",
"AB.Cabc": "d",
"dgraph.type": ["AB"],
"uid": "_:AB4"
},
"ABC.ab": "cd",
"ABC.abc": "de",
"dgraph.type": ["ABC"],
"uid": "_:ABC2"
}
-
name: "Add type with multiple Xid fields at deep level"
gqlmutation: |
Expand Down
15 changes: 14 additions & 1 deletion graphql/resolve/mutation_rewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,20 @@ func (v *VariableGenerator) Next(typ schema.Type, xidName, xidVal string, auth b
if xidName == "" || xidVal == "" {
key = typ.Name()
} else {
key = typ.FieldOriginatedFrom(xidName) + xidName + xidVal
// We add "." between values while generating key to removes duplicate xidError from below type of cases
// mutation {
// addABC(input: [{ ab: "cd", abc: "d" }]) {
// aBC {
// ab
// abc
// }
// }
// }
// The two generated keys for this case will be
// ABC.ab.cd and ABC.abc.d
// It also ensures that xids from different types gets different variable names
// here we are using the assertion that field name or type name can't have "." in them
key = typ.FieldOriginatedFrom(xidName) + "." + xidName + "." + xidVal
}
if varName, ok := v.xidVarNameMap[key]; ok {
return varName
Expand Down
12 changes: 12 additions & 0 deletions graphql/resolve/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -426,3 +426,15 @@ type Bar {
id: String! @id
foo: Foo!
}

type ABC {
ab: String! @id
abc: String! @id
AB: AB
}

type AB {
Cab: String! @id
Cabc: String! @id
}

0 comments on commit 5c700d0

Please sign in to comment.