Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix(GraphQL): Ignore redundant references to inverse object in mutation rewriting #7469

Merged
merged 1 commit into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 153 additions & 1 deletion graphql/resolve/add_mutation_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4015,4 +4015,156 @@
"Person1"
],
"uid": "_:Person12"
}
}
- name: "Reference to inverse field should be ignored and not throw an error"
gqlmutation: |
mutation addDistrict($input: [AddDistrictInput!]!) {
addDistrict(input: $input) {
district {
name
code
cities {
name
}
}
}
}
gqlvariables: |
{
"input": [
{
"name": "Dist1",
"code": "D1",
"cities": [{"name": "Bengaluru", "district": { "code": "non-existing" } }]
},
{
"name": "Dist2",
"code": "D2",
"cities": [{"name": "Pune", "district": { "code": "D2" } }]
}
]
}
explanation: "As district is inverse of city. There is no need to supply district to
the city. In case it is supplied, it is simply ignored. The city is linked to D1 and
district with code non-existing is ignored. Not even its existence query is generated."
dgquery: |-
query {
District1(func: eq(District.code, "D1")) @filter(type(District)) {
uid
}
District2(func: eq(District.code, "D2")) @filter(type(District)) {
uid
}
}
dgmutations:
- setjson: |
{
"District.cities":
[
{
"City.name":"Bengaluru",
"dgraph.type":["City"],
"City.district": {
"uid": "_:District1"
},
"uid":"_:City3"
}
],
"District.code":"D1",
"District.name":"Dist1",
"dgraph.type":["District"],
"uid":"_:District1"
}
- setjson: |
{
"District.cities":
[
{
"City.name":"Pune",
"dgraph.type":["City"],
"City.district": {
"uid": "_:District2"
},
"uid":"_:City4"
}
],
"District.code":"D2",
"District.name":"Dist2",
"dgraph.type":["District"],
"uid":"_:District2"
}
- name: "Reference to inverse field should be ignored and not throw an error 2"
gqlmutation: |
mutation addFoo($input: [AddFooInput!]!) {
addFoo(input: $input) {
foo {
id
bar {
id
}
}
}
}
gqlvariables: |
{
"input": [
{
"id": "123",
"bar": {"id": "1234", "foo": { "id": "123" } }
},
{
"id": "1",
"bar": {"id": "2", "foo": { "id": "3" } }
}
]
}
explanation: "As foo is inverse of bar. There is no need to supply bar to
foo. In case it is supplied, it is simply ignored."
dgquery: |-
query {
Foo1(func: eq(Foo.id, "123")) @filter(type(Foo)) {
uid
}
Bar2(func: eq(Bar.id, "1234")) @filter(type(Bar)) {
uid
}
Foo3(func: eq(Foo.id, "1")) @filter(type(Foo)) {
uid
}
Bar4(func: eq(Bar.id, "2")) @filter(type(Bar)) {
uid
}
}
dgmutations:
- setjson: |
{
"Foo.bar":
{
"Bar.id":"1234",
"dgraph.type":["Bar"],
"Bar.foo": {
"uid": "_:Foo1"
},
"uid":"_:Bar2"
},
"Foo.id":"123",
"dgraph.type":["Foo"],
"uid":"_:Foo1"
}
- setjson: |
{
"Foo.bar":
{
"Bar.id":"2",
"dgraph.type":["Bar"],
"Bar.foo": {
"uid": "_:Foo3"
},
"uid":"_:Bar4"
},
"Foo.id":"1",
"dgraph.type":["Foo"],
"uid":"_:Foo3"
}
8 changes: 8 additions & 0 deletions graphql/resolve/mutation_rewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,14 @@ func existenceQueries(
var ret []*gql.GraphQuery
var retErrors []error

// Inverse Object field is deleted. This is to ensure that we don't refer any conflicting
// inverse node as inverse of a field.
// Example: For the given mutation,
// addAuthor (input: [{name: ..., posts: [ {author: { id: "some id"}} ]} ] ),
// the part, author: { id: "some id"} is removed. This ensures that the author
// for the post is not set to something different but is set to the real author.
deleteInverseObject(obj, srcField)

id := typ.IDField()
if id != nil {
// Check if the ID field is referenced in the mutation
Expand Down
12 changes: 11 additions & 1 deletion graphql/resolve/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -415,4 +415,14 @@ type Astronaut @key(fields: "id") @extends {
type SpaceShip @key(fields: "id") @extends {
id: String! @id @external
missions: [Mission]
}
}

type Foo {
id: String! @id
bar: Bar! @hasInverse(field: foo)
}

type Bar {
id: String! @id
foo: Foo!
}