diff --git a/graphql/e2e/common/query.go b/graphql/e2e/common/query.go index eb18a7d8b8f..1bf07fa50ec 100644 --- a/graphql/e2e/common/query.go +++ b/graphql/e2e/common/query.go @@ -1465,6 +1465,38 @@ func queryWithAlias(t *testing.T) { string(gqlResponse.Data)) } +func DgraphDirectiveWithSpecialCharacters(t *testing.T) { + mutation := &GraphQLParams{ + Query: ` + mutation { + addMessage(input : [{content : "content1", author: "author1"}]) { + message { + content + author + } + } + }`, + } + result := `{"addMessage":{"message":[{"content":"content1","author":"author1"}]}}` + gqlResponse := mutation.ExecuteAsPost(t, graphqlURL) + RequireNoGQLErrors(t, gqlResponse) + require.JSONEq(t, result, string(gqlResponse.Data)) + + queryParams := &GraphQLParams{ + Query: ` + query { + queryMessage { + content + author + } + }`, + } + result = `{"queryMessage":[{"content":"content1","author":"author1"}]}` + gqlResponse = queryParams.ExecuteAsPost(t, graphqlURL) + RequireNoGQLErrors(t, gqlResponse) + require.JSONEq(t, result, string(gqlResponse.Data)) +} + func queryWithCascade(t *testing.T) { // for testing @cascade with get by ID and filter queries, also for testing @cascade on field authors := addMultipleAuthorFromRef(t, []*author{ diff --git a/graphql/e2e/directives/dgraph_directives_test.go b/graphql/e2e/directives/dgraph_directives_test.go index 5099756be70..ce53792936f 100644 --- a/graphql/e2e/directives/dgraph_directives_test.go +++ b/graphql/e2e/directives/dgraph_directives_test.go @@ -27,6 +27,8 @@ import ( func TestRunAll_WithDgraphDirectives(t *testing.T) { common.RunAll(t) + t.Run("dgraph predicate with special characters", + common.DgraphDirectiveWithSpecialCharacters) } func TestSchema_WithDgraphDirectives(t *testing.T) { @@ -200,6 +202,12 @@ func TestSchema_WithDgraphDirectives(t *testing.T) { "index": true, "tokenizer": ["hash"], "upsert": true + }, { + "predicate": "post", + "type": "string" + },{ + "predicate": "职业", + "type": "string" }, { "predicate": "People.name", "type": "string" @@ -297,6 +305,13 @@ func TestSchema_WithDgraphDirectives(t *testing.T) { "name": "dgraph.graphql.xid" }], "name": "dgraph.graphql" + }, { + "fields": [{ + "name": "post" + }, { + "name": "职业" + }], + "name": "Message" }, { "fields": [{ "name": "myPost.title" diff --git a/graphql/e2e/directives/schema.graphql b/graphql/e2e/directives/schema.graphql index d6d0a76dbf3..69baa37569c 100644 --- a/graphql/e2e/directives/schema.graphql +++ b/graphql/e2e/directives/schema.graphql @@ -138,3 +138,8 @@ type Teacher implements People { type Student implements People { taughtBy: [Teacher] } + +type Message { + content: String! @dgraph(pred: "post") + author: String @dgraph(pred: "<职业>") +} diff --git a/graphql/e2e/directives/test_data.json b/graphql/e2e/directives/test_data.json index 7eef3f0a3af..e7a60c4fa9b 100644 --- a/graphql/e2e/directives/test_data.json +++ b/graphql/e2e/directives/test_data.json @@ -100,4 +100,4 @@ "State.name": "Nusa", "State.xcode": "nusa" } -] \ No newline at end of file +] diff --git a/graphql/resolve/add_mutation_test.yaml b/graphql/resolve/add_mutation_test.yaml index 62d74b397f1..26be00bde9c 100644 --- a/graphql/resolve/add_mutation_test.yaml +++ b/graphql/resolve/add_mutation_test.yaml @@ -26,6 +26,26 @@ "Author.posts":[] } +- + name: "Add mutation for predicates with special characters having @dgraph directive." + gqlmutation: | + mutation { + addMessage(input : [{content : "content1", author: "author1"}]) { + message { + content + author + } + } + } + dgmutations: + - setjson: | + { + "uid":"_:Message1", + "dgraph.type":["Message"], + "职业":"author1", + "post":"content1" + } + - name: "Add multiple mutation with variables" gqlmutation: | diff --git a/graphql/resolve/mutation_rewriter.go b/graphql/resolve/mutation_rewriter.go index f0f1244eb2a..73c9b256f24 100644 --- a/graphql/resolve/mutation_rewriter.go +++ b/graphql/resolve/mutation_rewriter.go @@ -773,8 +773,7 @@ func deleteAuthSelector(t schema.Type) *schema.RuleNode { func mutationsFromFragments( frags []*mutationFragment, - setBuilder mutationBuilder, - delBuilder mutationBuilder) ([]*dgoapi.Mutation, error) { + setBuilder, delBuilder mutationBuilder) ([]*dgoapi.Mutation, error) { mutations := make([]*dgoapi.Mutation, 0, len(frags)) var errs x.GqlErrorList @@ -1009,6 +1008,10 @@ func rewriteObject( fieldDef := typ.Field(field) fieldName := typ.DgraphPredicate(field) + // This fixes mutation when dgraph predicate has special characters. PR #5526 + if strings.HasPrefix(fieldName, "<") && strings.HasSuffix(fieldName, ">") { + fieldName = fieldName[1 : len(fieldName)-1] + } switch val := val.(type) { case map[string]interface{}: @@ -1110,8 +1113,7 @@ func asIDReference( ctx context.Context, val interface{}, srcField schema.FieldDefinition, - srcUID string, - variable string, + srcUID, variable string, withAdditionalDeletes bool, varGen *VariableGenerator) *mutationFragment { diff --git a/graphql/resolve/schema.graphql b/graphql/resolve/schema.graphql index 5a895591259..c677d34d9db 100644 --- a/graphql/resolve/schema.graphql +++ b/graphql/resolve/schema.graphql @@ -208,6 +208,11 @@ type Mutation { }) } +type Message { + content: String! @dgraph(pred: "post") + author: String @dgraph(pred: "<职业>") +} + interface X { id: ID! username: String! @id diff --git a/graphql/schema/dgraph_schemagen_test.yml b/graphql/schema/dgraph_schemagen_test.yml index cd6c6d6cc4c..e7ce3765c64 100644 --- a/graphql/schema/dgraph_schemagen_test.yml +++ b/graphql/schema/dgraph_schemagen_test.yml @@ -522,6 +522,20 @@ schemas: name } + - name: "fields with @dgraph(pred: ...) contain different language." + input: | + type A { + content: String! @dgraph(pred: "post") @search(by: [exact, term]) + author: String @dgraph(pred: "<公司>") @search(by: [exact, term]) + } + output: | + type A { + post + <公司> + } + post: string @index(exact, term) . + <公司>: string @index(exact, term) . + - name: "custom types shouldn't be part of Dgraph schema" input: | diff --git a/graphql/schema/gqlschema_test.yml b/graphql/schema/gqlschema_test.yml index d24b44ef4f2..e3f74a1942b 100644 --- a/graphql/schema/gqlschema_test.yml +++ b/graphql/schema/gqlschema_test.yml @@ -2032,6 +2032,7 @@ valid_schemas: f3: [String!] @dgraph(pred: "f3") f4: [String]! @dgraph(pred: "f4") f5: String + f6: String @dgraph(pred: "<职业>") } type Y { f1: String! @dgraph(pred: "f1") @@ -2039,6 +2040,7 @@ valid_schemas: f3: [String]! @dgraph(pred: "f3") f4: [String!]! @dgraph(pred: "f4") f5: String @dgraph(pred: "X.f5") + f6: String @dgraph(pred: "<职业>") } - @@ -2106,23 +2108,6 @@ valid_schemas: }) } - - name: "@dgraph predicate type validation gives no errors with non-null variations" - input: | - type X { - f1: String @dgraph(pred: "f1") - f2: [String] @dgraph(pred: "f2") - f3: [String!] @dgraph(pred: "f3") - f4: [String]! @dgraph(pred: "f4") - f5: String - } - type Y { - f1: String! @dgraph(pred: "f1") - f2: [String!] @dgraph(pred: "f2") - f3: [String]! @dgraph(pred: "f3") - f4: [String!]! @dgraph(pred: "f4") - f5: String @dgraph(pred: "X.f5") - } - - name: "@custom directive with variable definitions in operation in graphql" input: |