Skip to content

Commit

Permalink
cherry-pick v20.07: fix(GraphQL): Link xids properly if there are dup…
Browse files Browse the repository at this point in the history
…licate xids within t… (#6521)

Fixes GRAPHQL-641

See https://discuss.dgraph.io/t/residual-issue-linking-grandchild-in-mutation-with-custom-ids/9613 for the issue details.

If the same nested xid was used as a leaf node within an addType mutation, it was only linked the first time that it was used and not subsequently for later objects. This change fixes that by adding the linkage mutations and only removing the mutation which was creating the object with the xid again.

(cherry picked from commit 12b2716)

# Conflicts:
#	graphql/e2e/directives/dgraph_directives_test.go
#	graphql/e2e/normal/normal_test.go
#	graphql/resolve/add_mutation_test.yaml
  • Loading branch information
abhimanyusinghgaur authored Sep 21, 2020
1 parent 27837c8 commit e07f17d
Show file tree
Hide file tree
Showing 10 changed files with 1,643 additions and 797 deletions.
1 change: 1 addition & 0 deletions graphql/e2e/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ func RunAll(t *testing.T) {
t.Run("deep mutations", deepMutations)
t.Run("add multiple mutations", testMultipleMutations)
t.Run("deep XID mutations", deepXIDMutations)
t.Run("three level xid", testThreeLevelXID)
t.Run("error in multiple mutations", addMultipleMutationWithOneError)
t.Run("dgraph directive with reverse edge adds data correctly",
addMutationWithReverseDgraphEdge)
Expand Down
254 changes: 254 additions & 0 deletions graphql/e2e/common/mutation.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,260 @@ func deepXIDMutations(t *testing.T) {
deepXIDTest(t, postExecutor)
}

func addComments(t *testing.T, ids []string) {
input := []map[string]interface{}{}
for _, id := range ids {
input = append(input, map[string]interface{}{"id": id})
}

params := &GraphQLParams{
Query: `mutation($input: [AddComment1Input!]!) {
addComment1(input: $input) {
comment1 {
id
}
}
}`,
Variables: map[string]interface{}{
"input": input,
},
}

gqlResponse := postExecutor(t, graphqlURL, params)
RequireNoGQLErrors(t, gqlResponse)
}

func testThreeLevelXID(t *testing.T) {

input := `{
"input": [
{
"id": "post1",
"comments": [
{
"id": "comment1",
"replies": [
{
"id": "reply1"
}
]
}
]
},
{
"id": "post2",
"comments": [
{
"id": "comment2",
"replies": [
{
"id": "reply1"
}
]
}
]
}
]
}`

qinput := make(map[string]interface{})
err := json.Unmarshal([]byte(input), &qinput)
require.NoError(t, err)

addPostParams := &GraphQLParams{
Query: ` mutation($input: [AddPost1Input!]!) {
addPost1(input: $input) {
post1(order: { asc: id }) {
id
comments {
id
replies {
id
}
}
}
}
}`,
Variables: qinput,
}

bothCommentsLinkedToReply := `{
"addPost1": {
"post1": [
{
"id": "post1",
"comments": [
{
"id": "comment1",
"replies": [
{
"id": "reply1"
}
]
}
]
},
{
"id": "post2",
"comments": [
{
"id": "comment2",
"replies": [
{
"id": "reply1"
}
]
}
]
}
]
}
}`

firstCommentLinkedToReply := `{
"addPost1": {
"post1": [
{
"id": "post1",
"comments": [
{
"id": "comment1",
"replies": [
{
"id": "reply1"
}
]
}
]
},
{
"id": "post2",
"comments": [
{
"id": "comment2",
"replies": []
}
]
}
]
}
}`

secondCommentLinkedToReply := `{
"addPost1": {
"post1": [
{
"id": "post1",
"comments": [
{
"id": "comment1",
"replies": []
}
]
},
{
"id": "post2",
"comments": [
{
"id": "comment2",
"replies": [
{
"id": "reply1"
}
]
}
]
}
]
}
}`

noCommentsLinkedToReply := `{
"addPost1": {
"post1": [
{
"id": "post1",
"comments": [
{
"id": "comment1",
"replies": []
}
]
},
{
"id": "post2",
"comments": [
{
"id": "comment2",
"replies": []
}
]
}
]
}
}`

cases := map[string]struct {
Comments []string
Expected string
ExpectedNumDeletedComments int
}{
"2nd level nodes don't exist but third level does": {
[]string{"reply1"},
bothCommentsLinkedToReply,
3,
},
"2nd level and third level nodes don't exist": {
[]string{},
bothCommentsLinkedToReply,
3,
},
"2nd level node exists but third level doesn't": {
[]string{"comment1", "comment2"},
noCommentsLinkedToReply,
2,
},
"2nd level and third level nodes exist": {
[]string{"comment1", "comment2", "reply1"},
noCommentsLinkedToReply,
3,
},
"one 2nd level node exists and third level node exists": {
[]string{"comment1", "reply1"},
secondCommentLinkedToReply,
3,
},
"the other 2nd level node exists and third level node exists": {
[]string{"comment2", "reply1"},
firstCommentLinkedToReply,
3,
},
"one 2nd level node exists and third level node doesn't exist": {
[]string{"comment1"},
secondCommentLinkedToReply,
3,
},
"other 2nd level node exists and third level node doesn't exist": {
[]string{"comment2", "reply1"},
firstCommentLinkedToReply,
3,
},
}

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
addComments(t, tc.Comments)
gqlResponse := postExecutor(t, graphqlURL, addPostParams)
RequireNoGQLErrors(t, gqlResponse)
testutil.CompareJSON(t, tc.Expected, string(gqlResponse.Data))

deleteGqlType(t, "Post1", map[string]interface{}{}, 2, nil)
deleteGqlType(t, "Comment1", map[string]interface{}{}, tc.ExpectedNumDeletedComments,
nil)
})
}
}

func deepXIDTest(t *testing.T, executeRequest requestExecutor) {
newCountry := &country{
Name: "A Country",
Expand Down
Loading

0 comments on commit e07f17d

Please sign in to comment.