-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
What version of Dgraph are you using?
latest:master
Have you tried reproducing the issue with the latest release?
Yes
What is the hardware spec (RAM, OS)?
doesn't matter
Steps to reproduce the issue (command/config used to run Dgraph).
- Run
dgraph zero - Run
dgraph alpha --acl_secret_file ee/acl/hmac-secret(ACL enabled, this is just to get the ACL Usergrootinserted into Dgraph) - Stop
alphainstance - Run
dgraph alpha(Without ACL this time, so that we can make queries and mutations without token) - Call
/admin/schemawith following POST body:
type Device {
uuid: String! @id @search(by: [hash])
owner: User! @hasInverse(field: devices)
}
type User {
uuid: String! @id @search(by: [hash])
devices: [Device] @hasInverse(field: owner)
}
- Perform following GraphQL mutation (call
graphqlwith given GraphQL body):
mutation {
addDevice(input: [{
uuid: "foo",
owner: {
uuid: "bar"
}
}]) {
device {
uuid
owner {
uuid
}
}
}
}
- Device gets added successfully, fine.
- Now, perform following GraphQL query:
query {
queryUser(filter: null) {
uuid
devices {
uuid
}
}
}
Expected behaviour and actual result.
- Expected Behaviour:
{
"data": {
"queryUser": [
{
"uuid": "bar",
"devices": [
{
"uuid": "foo"
}
]
}
]
}
}
- Actual Result:
{
"errors": [
{
"message": "Non-nullable field 'uuid' (type String!) was not present in result from Dgraph. GraphQL error propagation triggered.",
"locations": [
{
"line": 3,
"column": 5
}
],
"path": [
"queryUser",
1,
"uuid"
]
}
],
"data": {
"queryUser": [
{
"uuid": "bar",
"devices": [
{
"uuid": "foo"
}
]
},
null
]
}
}
Analysis
As a GraphQL user, I just declared some types, one of them (type User) happens to have same name as dgraph's internal type for ACL user. This causes a problem, as to how to identify which nodes are associated with user declared types and which ones with internal types. As a result, the actual results above contain errors, along with a null user in data.
If you call /query with following body, then you can see the reason why this happens:
query {
q1(func: eq(dgraph.type, "User")) {
uid
dgraph.xid
expand(_all_) {
expand(_all_)
}
}
}
following results are returned:
{
"data": {
"q1": [
{
"uid": "0x3",
"User.uuid": "bar",
"User.devices": [
{
"Device.uuid": "foo"
}
]
},
{
"uid": "0x5",
"dgraph.xid": "groot"
}
]
},
"extensions": {
"server_latency": {
"parsing_ns": 79899,
"processing_ns": 2018313,
"encoding_ns": 28383,
"assign_timestamp_ns": 547917,
"total_ns": 2755443
},
"txn": {
"start_ts": 25
},
"metrics": {
"num_uids": {
"Device.owner": 1,
"Device.uuid": 1,
"User.devices": 2,
"User.uuid": 2,
"dgraph.type": 0,
"dgraph.xid": 2,
"uid": 2
}
}
}
}
As groot is also a User, so it is also returned by dgraph in response to query, although, groot was never inserted by us, as it got inserted by ACL instance.
So, any types which are used by dgraph internally should be namespaced, in order to avoid collision with user declared types. For example, ACL User can be __User or dgraph.User, or something like that.