From 801f62fa491952254d2926d6eed489b6f8fd4c9e Mon Sep 17 00:00:00 2001 From: Aman Mangal Date: Tue, 23 May 2023 03:31:28 -0400 Subject: [PATCH] feat(graphql): adds @default directive to graphql (#8017) --- .../schema/apollo_service_response.graphql | 5 + graphql/e2e/schema/generatedSchema.graphql | 5 + graphql/resolve/add_mutation_test.yaml | 513 ++++++++++++++++ graphql/resolve/mutation_rewriter.go | 15 + graphql/resolve/schema.graphql | 26 + graphql/resolve/update_mutation_test.yaml | 553 ++++++++++++++++++ graphql/schema/gqlschema.go | 23 +- graphql/schema/gqlschema_test.yml | 122 +++- graphql/schema/rules.go | 82 +++ .../output/auth-directive.graphql | 5 + .../output/custom-directive.graphql | 5 + .../output/extended-types.graphql | 5 + .../output/generate-directive.graphql | 5 + .../output/single-extended-type.graphql | 5 + .../input/created-updated-directives.graphql | 13 + .../output/apollo-federation.graphql | 5 + .../output/auth-on-interfaces.graphql | 5 + .../schemagen/output/authorization.graphql | 5 + .../output/comments-and-descriptions.graphql | 5 + .../output/created-updated-directives.graphql | 483 +++++++++++++++ ...custom-dql-query-with-subscription.graphql | 5 + .../schemagen/output/custom-mutation.graphql | 5 + .../output/custom-nested-types.graphql | 5 + .../output/custom-query-mixed-types.graphql | 5 + .../custom-query-not-dgraph-type.graphql | 5 + .../custom-query-with-dgraph-type.graphql | 5 + .../schemagen/output/deprecated.graphql | 5 + ...e-on-concrete-type-with-interfaces.graphql | 5 + ...-reverse-directive-with-interfaces.graphql | 5 + .../output/field-with-id-directive.graphql | 5 + .../field-with-multiple-@id-fields.graphql | 5 + ...erse-predicate-in-dgraph-directive.graphql | 5 + .../filter-cleanSchema-all-empty.graphql | 5 + .../filter-cleanSchema-circular.graphql | 5 + ...filter-cleanSchema-custom-mutation.graphql | 5 + .../filter-cleanSchema-directLink.graphql | 5 + .../output/generate-directive.graphql | 5 + .../schemagen/output/geo-type.graphql | 5 + ...se-with-interface-having-directive.graphql | 5 + .../output/hasInverse-with-interface.graphql | 5 + ...Inverse-with-type-having-directive.graphql | 5 + .../schemagen/output/hasInverse.graphql | 5 + .../hasInverse_withSubscription.graphql | 5 + .../schemagen/output/hasfilter.graphql | 5 + .../ignore-unsupported-directive.graphql | 5 + .../output/interface-with-dgraph-pred.graphql | 5 + .../interface-with-id-directive.graphql | 5 + .../output/interface-with-no-ids.graphql | 5 + ...interfaces-with-types-and-password.graphql | 5 + .../output/interfaces-with-types.graphql | 5 + .../schemagen/output/lambda-directive.graphql | 5 + .../schemagen/output/language-tags.graphql | 6 + .../no-id-field-with-searchables.graphql | 5 + .../schemagen/output/no-id-field.graphql | 5 + .../schemagen/output/password-type.graphql | 5 + .../testdata/schemagen/output/random.graphql | 5 + .../output/searchables-references.graphql | 5 + .../schemagen/output/searchables.graphql | 5 + .../output/single-type-with-enum.graphql | 5 + .../schemagen/output/single-type.graphql | 5 + ...ype-implements-multiple-interfaces.graphql | 5 + .../schemagen/output/type-reference.graphql | 5 + .../type-with-arguments-on-field.graphql | 5 + ...e-with-custom-field-on-dgraph-type.graphql | 5 + ...-with-custom-fields-on-remote-type.graphql | 5 + .../output/type-without-orderables.graphql | 5 + .../testdata/schemagen/output/union.graphql | 5 + graphql/schema/wrappers.go | 39 +- 68 files changed, 2154 insertions(+), 6 deletions(-) create mode 100644 graphql/schema/testdata/schemagen/input/created-updated-directives.graphql create mode 100644 graphql/schema/testdata/schemagen/output/created-updated-directives.graphql diff --git a/graphql/e2e/schema/apollo_service_response.graphql b/graphql/e2e/schema/apollo_service_response.graphql index c0383cdeec5..fa8f1a6300e 100644 --- a/graphql/e2e/schema/apollo_service_response.graphql +++ b/graphql/e2e/schema/apollo_service_response.graphql @@ -117,6 +117,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -199,6 +203,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM diff --git a/graphql/e2e/schema/generatedSchema.graphql b/graphql/e2e/schema/generatedSchema.graphql index 6b9c37d5f31..7effc173194 100644 --- a/graphql/e2e/schema/generatedSchema.graphql +++ b/graphql/e2e/schema/generatedSchema.graphql @@ -98,6 +98,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -180,6 +184,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/resolve/add_mutation_test.yaml b/graphql/resolve/add_mutation_test.yaml index 1f85a553e98..5883be087a1 100644 --- a/graphql/resolve/add_mutation_test.yaml +++ b/graphql/resolve/add_mutation_test.yaml @@ -5204,3 +5204,516 @@ "dgraph.type": ["Person"], "uid": "_:Person_1" } + +- + name: "2-level add mutation with nullable @id fields " + explaination: "bookId in Book and PenName in author are @id and nullable field, + we can skip them while doing add mutation. Nested object author doesn't exist, so we + add it and link it to book" + gqlmutation: | + mutation addBook($input: [AddBookInput!]!) { + addBook(input: $input, upsert: false) { + book { + title + } + } + } + gqlvariables: | + { "input": + [ + { + "title": "Sapiens", + "ISBN": "B02", + "publisher": "penguin", + "author": { + "name": "Alice", + "authorId": "A02" + } + } + ] + } + dgquery: |- + query { + Book_1(func: eq(Book.ISBN, "B02")) { + uid + dgraph.type + } + Book_2(func: eq(Book.title, "Sapiens")) { + uid + dgraph.type + } + author_3(func: eq(author.authorId, "A02")) { + uid + dgraph.type + } + } + dgmutations: + - setjson: | + { + "Book.title": "Sapiens", + "Book.ISBN": "B02", + "Book.publisher": "penguin", + "dgraph.type": [ + "Book" + ], + "Book.author": { + "author.authorId":"A02", + "author.book": [ + { + "uid": "_:Book_2" + } + ], + "author.name": "Alice", + "dgraph.type": [ + "author" + ], + "uid": "_:author_3" + }, + "uid": "_:Book_2" + } + +- + name: "2- level add mutation with upsert and nullable @id fields " + explaination: "bookId in @id,penName in author are nullable @id fields and we can skip them. + title,ISBN in Book are @id fields,so also added in set Json, because @id fields will also be updated by upserts. + Both book and author already exist so we just link new author to book and delete old reference from book to author, + if there is any" + gqlmutation: | + mutation addBook($input: [AddBookInput!]!) { + addBook(input: $input, upsert: true) { + book { + title + } + } + } + gqlvariables: | + { "input": + [ + { + "title": "Sapiens", + "ISBN": "B01", + "publisher": "penguin", + "author": { + "name": "Alice", + "authorId": "A01" + } + } + ] + } + dgquery: |- + query { + Book_1(func: eq(Book.ISBN, "B01")) { + uid + dgraph.type + } + Book_2(func: eq(Book.title, "Sapiens")) { + uid + dgraph.type + } + author_3(func: eq(author.authorId, "A01")) { + uid + dgraph.type + } + } + qnametouid: | + { + "Book_2":"0x11", + "author_3": "0x12" + } + dgquerysec: |- + query { + Book_2 as Book_2(func: uid(0x11)) @filter(type(Book)) { + uid + } + var(func: uid(Book_2)) { + author_4 as Book.author @filter(NOT (uid(0x12))) + } + } + dgmutations: + - setjson: | + { + "Book.ISBN": "B01", + "Book.author": { + "author.book": [ + { + "uid": "uid(Book_2)" + } + ], + "uid": "0x12" + }, + "Book.publisher": "penguin", + "Book.title": "Sapiens", + "uid": "uid(Book_2)" + } + deletejson: | + [{ + "author.book": [ + { + "uid": "uid(Book_2)" + } + ], + "uid": "uid(author_4)" + }] + cond: "@if(gt(len(Book_2), 0))" + +- + name: "add mutation with upsert gives error when multiple nodes are found for existence queries" + explaination: "Two different books exist for title and Sapiens @id fields, We can't do upsert mutation " + gqlmutation: | + mutation addBook($input: [AddBookInput!]!) { + addBook(input: $input, upsert: true) { + book { + title + } + } + } + gqlvariables: | + { "input": + [ + { + "title": "Sapiens", + "ISBN": "B01", + "publisher": "penguin" + } + ] + } + dgquery: |- + query { + Book_1(func: eq(Book.ISBN, "B01")) { + uid + dgraph.type + } + Book_2(func: eq(Book.title, "Sapiens")) { + uid + dgraph.type + } + } + qnametouid: | + { + "Book_1":"0x11", + "Book_2": "0x12" + } + error2: + { + "message": "failed to rewrite mutation payload because multiple nodes found + for given xid values, updation not possible" + } + +- + name: "add mutation with upsert at nested level gives error when multiple nodes are found + for existence queries" + explaination: "Two different author exist for penName and authorId @id fields inside author, + We can't link author to both books " + gqlmutation: | + mutation addBook($input: [AddBookInput!]!) { + addBook(input: $input, upsert: true) { + book { + title + } + } + } + gqlvariables: | + { "input": + [ + { + "title": "Sapiens", + "ISBN": "B01", + "publisher": "penguin", + "author": { + "penName": "Alice", + "authorId": "A01" + } + } + ] + } + dgquery: |- + query { + Book_1(func: eq(Book.ISBN, "B01")) { + uid + dgraph.type + } + Book_2(func: eq(Book.title, "Sapiens")) { + uid + dgraph.type + } + author_3(func: eq(author.authorId, "A01")) { + uid + dgraph.type + } + author_4(func: eq(author.penName, "Alice")) { + uid + dgraph.type + } + } + qnametouid: | + { + "author_3":"0x11", + "author_4": "0x12" + } + error2: + { + "message": "failed to rewrite mutation payload because multiple nodes + found for given xid values, updation not possible" + } + +- + name: "No xid present for add mutation with upsert" + explaination: "If none of the xid field is given in upsert mutation then there will be no existence queries, + and it will behave as simple add mutation,i.e. create new node with all the given fields" + gqlmutation: | + mutation addBook($input: [AddBookInput!]!) { + addBook(input: $input, upsert: true) { + book { + title + } + } + } + gqlvariables: | + { "input": + [ + { + "publisher": "penguin" + } + ] + } + dgmutations: + - setjson: | + { + "Book.publisher": "penguin", + "dgraph.type": [ + "Book" + ], + "uid":"_:Book_1" + } + +- + name: "Non-nullable xid should be present in add Mutation for nested field" + explaination: "non-nullable @id field id in comment1 type not provided. As no reference is + provided for comment, we treat it as new node, and return error for missing xid." + gqlmutation: | + mutation addPost1($input: [AddPost1Input!]!) { + addPost1(input: $input, upsert: false) { + post1 { + content + } + } + } + gqlvariables: | + { "input": + [ + { + "id": "P01", + "content":"Intro to GraphQL", + "comments":[{ + "message":"Nice Intro! Love GraphQl" + }] + } + ] + } + dgquery: |- + query { + Post1_1(func: eq(Post1.id, "P01")) { + uid + dgraph.type + } + } + error2: + { + "message": "failed to rewrite mutation payload because field id cannot be empty" + } + +- + name: "Add Mutation referencing same XID in different types" + gqlmutation: | + mutation($input: [AddT1Input!]!) { + addT1(input: $input) { + t1 { + name + name1 + name2 + link { + name + name1 + name3 + } + } + } + } + gqlvariables: | + { + "input": [ + { + "name": "Bob", + "name1": "Bob11", + "name2": "Bob2", + "link": { + "name": "Bob" + } + } + ] + } + explanation: "As the link and top level object contain the same XID, Bob, this should throw an error" + error: + { + "message": + "failed to rewrite mutation payload because using duplicate XID value: Bob for XID: name for two different + implementing types of same interfaces: T1 and T2" + } + +- + name: "Add mutation with @default directive" + gqlmutation: | + mutation($input: [AddBookingInput!]!) { + addBooking(input: $input) { + booking { + name + created + updated + } + } + } + gqlvariables: | + { + "input": [ + { + "name": "Holiday to Bermuda" + } + ] + } + explanation: "As booking has @default fields and is being added, these should be set to the default add value" + dgmutations: + - setjson: | + { + "Booking.created": "2000-01-01T00:00:00.00Z", + "Booking.active": "false", + "Booking.count": "1", + "Booking.hotel": "add", + "Booking.length": "1.1", + "Booking.status": "ACTIVE", + "Booking.name": "Holiday to Bermuda", + "Booking.updated": "2000-01-01T00:00:00.00Z", + "dgraph.type": [ + "Booking" + ], + "uid":"_:Booking_1" + } + +- + name: "Add mutation with @default directive uses provided values" + gqlmutation: | + mutation($input: [AddBookingInput!]!) { + addBooking(input: $input) { + booking { + name + created + updated + } + } + } + gqlvariables: | + { + "input": [ + { + "name": "Holiday to Bermuda", + "created": "2022-10-12T07:20:50.52Z", + "updated": "2023-10-12T07:20:50.52Z", + "active": false, + "length": 12.3, + "status": "INACTIVE", + "hotel": "provided" + } + ] + } + explanation: "Fields with @default(add) should use input values if provided (note that count is still using default)" + dgmutations: + - setjson: | + { + "Booking.name": "Holiday to Bermuda", + "Booking.created": "2022-10-12T07:20:50.52Z", + "Booking.updated": "2023-10-12T07:20:50.52Z", + "Booking.active": false, + "Booking.count": "1", + "Booking.hotel": "provided", + "Booking.length": 12.3, + "Booking.status": "INACTIVE", + "dgraph.type": [ + "Booking" + ], + "uid":"_:Booking_1" + } + +- + name: "Upsert mutation with @default directives where only one of the nodes exists" + explanation: "Booking1 should only have updated timestamp as it exists, Booking2 should have created and updated timestamps" + gqlmutation: | + mutation addBookingXID($input: [AddBookingXIDInput!]!) { + addBookingXID(input: $input, upsert: true) { + bookingXID { + name + } + } + } + gqlvariables: | + { "input": + [ + { + "id": "Booking1", + "name": "Trip to Bermuda" + }, + { + "id": "Booking2", + "name": "Trip to Antigua" + } + ] + } + dgquery: |- + query { + BookingXID_1(func: eq(BookingXID.id, "Booking1")) { + uid + dgraph.type + } + BookingXID_2(func: eq(BookingXID.id, "Booking2")) { + uid + dgraph.type + } + } + qnametouid: |- + { + "BookingXID_1": "0x11" + } + dgquerysec: |- + query { + BookingXID_1 as BookingXID_1(func: uid(0x11)) @filter(type(BookingXID)) { + uid + } + } + dgmutations: + - setjson: | + { + "uid" : "uid(BookingXID_1)", + "BookingXID.id": "Booking1", + "BookingXID.name": "Trip to Bermuda", + "BookingXID.updated": "2000-01-01T00:00:00.00Z", + "BookingXID.active": "true", + "BookingXID.count": "2", + "BookingXID.length": "1.2", + "BookingXID.status": "INACTIVE", + "BookingXID.hotel": "update" + } + cond: "@if(gt(len(BookingXID_1), 0))" + - setjson: | + { + "uid": "_:BookingXID_2", + "BookingXID.id": "Booking2", + "BookingXID.name": "Trip to Antigua", + "BookingXID.created": "2000-01-01T00:00:00.00Z", + "BookingXID.updated": "2000-01-01T00:00:00.00Z", + "BookingXID.active": "false", + "BookingXID.count": "1", + "BookingXID.length": "1.1", + "BookingXID.status": "ACTIVE", + "BookingXID.hotel": "add", + "dgraph.type": [ + "BookingXID" + ] + } diff --git a/graphql/resolve/mutation_rewriter.go b/graphql/resolve/mutation_rewriter.go index deb00d61e40..084cb523fbc 100644 --- a/graphql/resolve/mutation_rewriter.go +++ b/graphql/resolve/mutation_rewriter.go @@ -1570,6 +1570,8 @@ func rewriteObject( } } + action := "update" + // This is not an XID reference. This is also not a UID reference. // This is definitely a new node. // Create new node @@ -1618,6 +1620,19 @@ func rewriteObject( // "_:Project2" . myUID will store the variable generated to reference this node. newObj["dgraph.type"] = dgraphTypes newObj["uid"] = myUID + action = "add" + } + + // Now we know whether this is a new node or not, we can set @default(add/update) fields + for _, field := range typ.Fields() { + var pred = field.DgraphPredicate() + if newObj[pred] != nil { + continue + } + var value = field.GetDefaultValue(action) + if value != nil { + newObj[pred] = value + } } // Add Inverse Link if necessary diff --git a/graphql/resolve/schema.graphql b/graphql/resolve/schema.graphql index fe94fd0cbef..ba1e3347e08 100644 --- a/graphql/resolve/schema.graphql +++ b/graphql/resolve/schema.graphql @@ -175,6 +175,32 @@ type Student implements People { taughtBy: [Teacher] @hasInverse(field: "teaches") } +# For testing default values +type Booking { + id: ID! + name: String! + created: DateTime! @default(add: {value: "$now"}) + updated: DateTime! @default(add: {value: "$now"}, update: {value: "$now"}) + count: Int! @default(add: {value: "1"}, update: {value: "2"}) + length: Float! @default(add: {value: "1.1"}, update: {value: "1.2"}) + hotel: String! @default(add: {value: "add"}, update: {value: "update"}) + active: Boolean! @default(add: {value: "false"}, update: {value: "true"}) + status: Status! @default(add: {value: "ACTIVE"}, update: {value: "INACTIVE"}) +} + +# For testing default values with upserts +type BookingXID { + id: String! @id + name: String! + created: DateTime! @default(add: {value: "$now"}) + updated: DateTime! @default(add: {value: "$now"}, update: {value: "$now"}) + count: Int! @default(add: {value: "1"}, update: {value: "2"}) + length: Float! @default(add: {value: "1.1"}, update: {value: "1.2"}) + hotel: String! @default(add: {value: "add"}, update: {value: "update"}) + active: Boolean! @default(add: {value: "false"}, update: {value: "true"}) + status: Status! @default(add: {value: "ACTIVE"}, update: {value: "INACTIVE"}) +} + type Comment { id: ID! author: String! diff --git a/graphql/resolve/update_mutation_test.yaml b/graphql/resolve/update_mutation_test.yaml index d4335ceebaa..bf434c04f7f 100644 --- a/graphql/resolve/update_mutation_test.yaml +++ b/graphql/resolve/update_mutation_test.yaml @@ -1979,3 +1979,556 @@ "Author.name": "Alice" } cond: "@if(gt(len(x), 0))" + +- + name: "Updating @id field when given values for @id fields doesn't exists" + explaination: "We are giving two @id fields title and ISBN in set part of update mutation, + and will generate two existence queries for both of them. As none of the @id field is present,we + update the values successfully " + gqlmutation: | + mutation update($patch: UpdateBookInput!) { + updateBook(input: $patch) { + book { + title + ISBN + publisher + } + } + } + gqlvariables: | + { + "patch": { + "filter": { + "or": [ + { + "title": { + "in": "Sapiens" + } + }, + { + "ISBN": { + "in": "2QSAT" + } + } + ] + }, + "set": { + "title": "History of Humans", + "ISBN": "I001", + "publisher": "penguin" + } + } + } + dgquery: |- + query { + Book_1(func: eq(Book.ISBN, "I001")) { + uid + dgraph.type + } + Book_2(func: eq(Book.title, "History of Humans")) { + uid + dgraph.type + } + } + dgquerysec: |- + query { + x as updateBook(func: type(Book)) @filter((eq(Book.title, "Sapiens") OR eq(Book.ISBN, "2QSAT"))) { + uid + } + } + dgmutations: + - setjson: | + { "uid" : "uid(x)", + "Book.ISBN": "I001", + "Book.publisher": "penguin", + "Book.title": "History of Humans" + } + cond: "@if(gt(len(x), 0))" +- + name: "Updating @id field when given value for @id fields exist in some node" + explaination: "We are giving two @id fields title and ISBN in set part of update mutation, + and will generate two existence queries for both of them.As we already have node with title + Sapiens, we will return error in this case " + gqlmutation: | + mutation update($patch: UpdateBookInput!) { + updateBook(input: $patch) { + book { + title + ISBN + publisher + } + } + } + gqlvariables: | + { + "patch": { + "filter": { + "or": [ + { + "title": { + "in": "Sapiens" + } + }, + { + "ISBN": { + "in": "2QSAT" + } + } + ] + }, + "set": { + "title": "History of Humans", + "ISBN": "I001", + "publisher": "penguin" + } + } + } + dgquery: |- + query { + Book_1(func: eq(Book.ISBN, "I001")) { + uid + dgraph.type + } + Book_2(func: eq(Book.title, "History of Humans")) { + uid + dgraph.type + } + } + qnametouid: |- + { + "Book_2": "0x123" + } + error2: + { "message": + "failed to rewrite mutation payload because id History of Humans already exists for field title inside type Book" + } + +- + name: "skipping nullable @id values while Updating link to non-existent nested object" + explaination: "when we update link to nested field, we check if that node already exists or not, + In this case nested object doesn't exists and update mutation create it and link it to root object. + while creating nested object it skip @id nullable fields which don't exists in nested object, in this case + it skips commentId in nested type Comment1" + gqlmutation: | + mutation update($patch: UpdatePost1Input!) { + updatePost1(input: $patch) { + post1 { + id + } + } + } + gqlvariables: | + { + "patch": { + "filter": { + "id": { + "in": "P02" + } + }, + "set": { + "id": "P01", + "content": "intro to graphql", + "comments": { + "id": "C01", + "message": "nice intro!" + } + } + } + } + dgquery: |- + query { + Post1_1(func: eq(Post1.id, "P01")) { + uid + dgraph.type + } + Comment1_2(func: eq(Comment1.id, "C01")) { + uid + dgraph.type + } + } + dgquerysec: |- + query { + x as updatePost1(func: type(Post1)) @filter(eq(Post1.id, "P02")) { + uid + } + } + dgmutations: + - setjson: | + { + "Post1.comments": [ + { + "Comment1.id": "C01", + "Comment1.message": "nice intro!", + "dgraph.type": [ + "Comment1" + ], + "uid": "_:Comment1_2" + } + ], + "Post1.content": "intro to graphql", + "Post1.id": "P01", + "uid": "uid(x)" + } + cond: "@if(gt(len(x), 0))" + +- + name: "Updating link to nested field require all the non-null id's to be present in nested field" + explaination: "when we update link to nested field then we check if that already exist or not, + In this case since @id field is not present in nested field, so we assume it to be a new node. + update mutation tries to create it but failed because non-nullable id field is required to add new + node." + gqlmutation: | + mutation update($patch: UpdatePost1Input!) { + updatePost1(input: $patch) { + post1 { + id + } + } + } + gqlvariables: | + { + "patch": { + "filter": { + "id": { + "in": "P02" + } + }, + "set": { + "id": "P01", + "content": "intro to graphql", + "comments":{ + "message":"nice intro!" + } + } + } + } + dgquery: |- + query { + Post1_1(func: eq(Post1.id, "P01")) { + uid + dgraph.type + } + } + error2: + { "message": + "failed to rewrite mutation payload because field id cannot be empty" + } + +- + name: "Updating inherited @id field with interface arg -1 " + explaination: "For this case we will generate one more existence query for inherited @id field refID which have + interface arg set. No node with given refID exist in same or other implementing type of interface so we will + successfully update node in this case" + gqlmutation: | + mutation update($patch: UpdateLibraryMemberInput!) { + updateLibraryMember(input: $patch) { + libraryMember { + refID + } + } + } + gqlvariables: | + { + "patch": { + "filter": { + "refID": { + "in": "101" + } + }, + "set": { + "refID": "102", + "name": "Alice", + "readHours": "3d2hr" + } + } + } + + dgquery: |- + query { + LibraryMember_1(func: eq(Member.name, "Alice")) { + uid + dgraph.type + } + LibraryMember_2(func: eq(Member.refID, "102")) { + uid + dgraph.type + } + LibraryMember_3(func: eq(Member.refID, "102")) { + uid + dgraph.type + } + } + dgquerysec: |- + query { + x as updateLibraryMember(func: type(LibraryMember)) @filter(eq(Member.refID, "101")) { + uid + } + } + dgmutations: + - setjson: | + { + "LibraryMember.readHours":"3d2hr", + "Member.name":"Alice", + "Member.refID":"102", + "uid":"uid(x)" + } + cond: "@if(gt(len(x), 0))" + +- + name: "Updating inherited @id field with interface arg -2 " + explaination: "For this case we will generate one more existence query for inherited @id field refID. + There already exist node with refID in other implementing type of interface so we will generate error for this case" + gqlmutation: | + mutation update($patch: UpdateLibraryMemberInput!) { + updateLibraryMember(input: $patch) { + libraryMember { + refID + } + } + } + gqlvariables: | + { + "patch": { + "filter": { + "refID": { + "in": "101" + } + }, + "set": { + "refID": "102", + "name": "Alice", + "readHours": "3d2hr" + } + } + } + dgquery: |- + query { + LibraryMember_1(func: eq(Member.name, "Alice")) { + uid + dgraph.type + } + LibraryMember_2(func: eq(Member.refID, "102")) { + uid + dgraph.type + } + LibraryMember_3(func: eq(Member.refID, "102")) { + uid + dgraph.type + } + } + qnametouid: |- + { + "LibraryMember_3": "0x123" + } + error2: + { + "message": "failed to rewrite mutation payload because id 102 already exists for field refID + in some other implementing type of interface Member" + } + +- + name: "Updating link to nested object inheriting @id field with interface argument-1" + explaination: "If nested object have inherited @id field which have interface argument set, and that + field already exist in some other implementing type than we returns error.In below mutation manages + is of type LibraryMember but node with given refID already exist in some other + type than than LibraryMember" + gqlmutation: | + mutation update($patch: UpdateLibraryManagerInput!) { + updateLibraryManager(input: $patch) { + libraryManager { + name + } + } + } + gqlvariables: | + { + "patch": { + "filter": { + "name": { + "in": "Alice" + } + }, + "set": { + "name": "Bob", + "manages": { + "refID":"101" + } + } + } + } + dgquery: |- + query { + LibraryManager_1(func: eq(LibraryManager.name, "Bob")) { + uid + dgraph.type + } + LibraryMember_2(func: eq(Member.refID, "101")) { + uid + dgraph.type + } + LibraryMember_3(func: eq(Member.refID, "101")) { + uid + dgraph.type + } + } + qnametouid: |- + { + "LibraryMember_3": "0x123" + } + error2: + { + "message": "failed to rewrite mutation payload because id 101 already exists for field refID + in some other implementing type of interface Member" + } + +- + name: "Updating link to nested object inheriting @id field with interface argument-2" + explaination: "In below mutation manages is of type LibraryMember and node of type LibraryMember already + existed with given refID, so we link that correctly" + gqlmutation: | + mutation update($patch: UpdateLibraryManagerInput!) { + updateLibraryManager(input: $patch) { + libraryManager { + name + } + } + } + gqlvariables: | + { + "patch": { + "filter": { + "name": { + "in": "Alice" + } + }, + "set": { + "name": "Bob", + "manages": { + "refID":"101" + } + } + } + } + dgquery: |- + query { + LibraryManager_1(func: eq(LibraryManager.name, "Bob")) { + uid + dgraph.type + } + LibraryMember_2(func: eq(Member.refID, "101")) { + uid + dgraph.type + } + LibraryMember_3(func: eq(Member.refID, "101")) { + uid + dgraph.type + } + } + qnametouid: |- + { + "LibraryMember_2": "0x123", + "LibraryMember_3": "0x124" + } + dgquerysec: |- + query { + x as updateLibraryManager(func: type(LibraryManager)) @filter(eq(LibraryManager.name, "Alice")) { + uid + } + } + dgmutations: + - setjson: | + { + "LibraryManager.manages": [ + { + "uid": "0x123" + } + ], + "LibraryManager.name": "Bob", + "uid": "uid(x)" + } + cond: "@if(gt(len(x), 0))" + +- + name: "Update with @default directive" + gqlmutation: | + mutation updateBooking($patch: UpdateBookingInput!) { + updateBooking(input: $patch) { + booking { + id + } + } + } + gqlvariables: | + { "patch": + { "filter": { + "id": ["0x123", "0x124"] + }, + "set": { + "name": "Flight to Antigua" + } + } + } + explanation: "The update patch should include default values on the fields with the @default(update:) directive" + dgquerysec: |- + query { + x as updateBooking(func: uid(0x123, 0x124)) @filter(type(Booking)) { + uid + } + } + dgmutations: + - setjson: | + { "uid" : "uid(x)", + "Booking.name": "Flight to Antigua", + "Booking.updated": "2000-01-01T00:00:00.00Z", + "Booking.active": "true", + "Booking.count": "2", + "Booking.length": "1.2", + "Booking.status": "INACTIVE", + "Booking.hotel": "update" + } + cond: "@if(gt(len(x), 0))" + +- + name: "Update with @default directive uses provided values" + gqlmutation: | + mutation updateBooking($patch: UpdateBookingInput!) { + updateBooking(input: $patch) { + booking { + id + } + } + } + gqlvariables: | + { "patch": + { "filter": { + "id": ["0x123", "0x124"] + }, + "set": { + "name": "Flight to Antigua", + "updated": "2022-10-12T07:20:50.52Z", + "active": false, + "length": 12.3, + "status": "ACTIVE", + "hotel": "provided" + } + } + } + explanation: "Fields with @default(update) should use input values if provided (note that count is still using default)" + dgquerysec: |- + query { + x as updateBooking(func: uid(0x123, 0x124)) @filter(type(Booking)) { + uid + } + } + dgmutations: + - setjson: | + { "uid" : "uid(x)", + "Booking.name": "Flight to Antigua", + "Booking.updated": "2022-10-12T07:20:50.52Z", + "Booking.active": false, + "Booking.count": "2", + "Booking.length": 12.3, + "Booking.status": "ACTIVE", + "Booking.hotel": "provided" + } + cond: "@if(gt(len(x), 0))" diff --git a/graphql/schema/gqlschema.go b/graphql/schema/gqlschema.go index 185611e50be..d4bc3bc734b 100644 --- a/graphql/schema/gqlschema.go +++ b/graphql/schema/gqlschema.go @@ -48,6 +48,7 @@ const ( remoteResponseDirective = "remoteResponse" lambdaDirective = "lambda" lambdaOnMutateDirective = "lambdaOnMutate" + defaultDirective = "default" generateDirective = "generate" generateQueryArg = "query" @@ -195,6 +196,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -278,6 +283,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( @@ -309,6 +315,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM @@ -570,6 +577,7 @@ var directiveValidators = map[string]directiveValidator{ remoteDirective: ValidatorNoOp, deprecatedDirective: ValidatorNoOp, lambdaDirective: lambdaDirectiveValidation, + defaultDirective: defaultDirectiveValidation, lambdaOnMutateDirective: ValidatorNoOp, generateDirective: ValidatorNoOp, apolloKeyDirective: ValidatorNoOp, @@ -1289,7 +1297,7 @@ func addPatchType(schema *ast.Schema, defn *ast.Definition, providesTypeMap map[ return } - nonIDFields := getNonIDFields(schema, defn, providesTypeMap) + nonIDFields := getPatchFields(schema, defn, providesTypeMap) if len(nonIDFields) == 0 { // The user might just have an external id field and nothing else. We don't generate patch // type in that case. @@ -2233,7 +2241,7 @@ func createField(schema *ast.Schema, fld *ast.FieldDefinition) *ast.FieldDefinit return &newFld } -func getNonIDFields(schema *ast.Schema, defn *ast.Definition, providesTypeMap map[string]bool) ast.FieldList { +func getPatchFields(schema *ast.Schema, defn *ast.Definition, providesTypeMap map[string]bool) ast.FieldList { fldList := make([]*ast.FieldDefinition, 0) for _, fld := range defn.Fields { if isIDField(defn, fld) || hasIDDirective(fld) { @@ -2315,12 +2323,19 @@ func getFieldsWithoutIDType(schema *ast.Schema, defn *ast.Definition, continue } - // see also comment in getNonIDFields + // see also comment in getPatchFields if schema.Types[fld.Type.Name()].Kind == ast.Interface && (!hasID(schema.Types[fld.Type.Name()]) && !hasXID(schema.Types[fld.Type.Name()])) { continue } - fldList = append(fldList, createField(schema, fld)) + + // if the field has a @default(add) value it is optional in add input + var field = createField(schema, fld) + if getDefaultValue(fld, "add") != nil { + field.Type.NonNull = false + } + + fldList = append(fldList, field) } pd := getPasswordField(defn) diff --git a/graphql/schema/gqlschema_test.yml b/graphql/schema/gqlschema_test.yml index b31b6e86705..dd36ca09cb5 100644 --- a/graphql/schema/gqlschema_test.yml +++ b/graphql/schema/gqlschema_test.yml @@ -2743,7 +2743,7 @@ invalid_schemas: review: String! } errlist: [ - {"message": "Type Product; @remote directive cannot be defined with @key directive", "locations": [ { "line": 174, "column": 12} ] }, + {"message": "Type Product; @remote directive cannot be defined with @key directive", "locations": [ { "line": 179, "column": 12} ] }, ] - name: "directives defined on @external fields that are not @key." @@ -2944,6 +2944,7 @@ invalid_schemas: { "message": "Type Person; Field nameHi: `*` language tag not supported in GraphQL", "locations": [ { "line": 3, "column": 19 } ] }, ] + - name: "@id field can't have interface argument when it's defined inside a type" input: | type Person { @@ -2956,6 +2957,125 @@ invalid_schemas: "locations": [ { "line": 2, "column": 18 } ] }, ] + - name: "@default validates field type for value $now" + input: | + type X { + field: String @default(add:{value:"$now"}) + } + errlist: [ + {"message": "Type X; Field field: @default directive provides value \"$now\" which cannot be used with String", + "locations":[{"line":2, "column":18}]} + ] + + - name: "@default validates value for Int" + input: | + type X { + field: Int @default(add:{value:"apple"}) + } + errlist: [ + {"message": "Type X; Field field: @default directive provides value \"apple\" which cannot be used with Int", + "locations":[{"line":2, "column":15}]} + ] + + - name: "@default validates value for Float" + input: | + type X { + field: Float @default(add:{value:"apple"}) + } + errlist: [ + {"message": "Type X; Field field: @default directive provides value \"apple\" which cannot be used with Float", + "locations":[{"line":2, "column":17}]} + ] + + - name: "@default validates value for Boolean" + input: | + type X { + field: Boolean @default(add:{value:"apple"}) + } + errlist: [ + {"message": "Type X; Field field: @default directive provides value \"apple\" which cannot be used with Boolean", + "locations":[{"line":2, "column":19}]} + ] + + - name: "@default validates type is not @remote" + input: | + type X @remote { + field: Int @default(add:{value:"1"}) + } + errlist: [ + {"message": "Type X; Field field: cannot use @default directive on a @remote type", + "locations":[{"line":2, "column":15}]} + ] + + - name: "@default validates field type is scalar" + input: | + type X { + field: Y @default(add:{value:"1"}) + } + type Y { + field: String + } + errlist: [ + {"message": "Type X; Field field: cannot use @default directive on field with non-scalar type Y", + "locations":[{"line":2, "column":13}]} + ] + + - name: "@default validates field type is not list" + input: | + type X { + field: [String] @default(add:{value:"1"}) + } + errlist: [ + {"message": "Type X; Field field: cannot use @default directive on field with list type [String]", + "locations":[{"line":2, "column":20}]} + ] + + - name: "@default validates field type is not @id" + input: | + type X { + field: String! @id @default(add:{value:"foo"}) + } + errlist: [ + {"message": "Type X; Field field: cannot use @default directive on field with @id directive", + "locations":[{"line":2, "column":23}]} + ] + + - name: "@default validates field type is not ID" + input: | + type X { + id: ID! @default(add:{value:"foo"}) + field: String + } + errlist: [ + {"message": "Type X; Field id: cannot use @default directive on field with type ID", + "locations":[{"line":2, "column":12}]} + ] + + - name: "@default validates field type is not @custom" + input: | + type X { + id: String! @id + field: String! @default(add:{value:"foo"}) @custom(http: { + url: "http://blah.com", + method: "GET" + }) + } + errlist: [ + {"message": "Type X; Field field: cannot use @default directive on field with @custom directive", + "locations":[{"line":3, "column":19}]} + ] + + - name: "@default validates field type is not @lambda" + input: | + type X { + id: String! @id + field: String! @default(add:{value:"foo"}) @lambda + } + errlist: [ + {"message": "Type X; Field field: cannot use @default directive on field with @lambda directive", + "locations":[{"line":3, "column":19}]} + ] + valid_schemas: - name: "Multiple fields with @id directive should be allowed" input: | diff --git a/graphql/schema/rules.go b/graphql/schema/rules.go index 1647911ba65..175b14e4fb9 100644 --- a/graphql/schema/rules.go +++ b/graphql/schema/rules.go @@ -1301,6 +1301,88 @@ func lambdaDirectiveValidation(sch *ast.Schema, return errs } +func defaultDirectiveValidation(sch *ast.Schema, + typ *ast.Definition, + field *ast.FieldDefinition, + dir *ast.Directive, + secrets map[string]x.Sensitive) gqlerror.List { + if typ.Directives.ForName(remoteDirective) != nil { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: cannot use @default directive on a @remote type", + typ.Name, field.Name)} + } + if !isScalar(field.Type.Name()) && sch.Types[field.Type.Name()].Kind != ast.Enum { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: cannot use @default directive on field with non-scalar type %s", + typ.Name, field.Name, field.Type.Name())} + } + if field.Type.Elem != nil { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: cannot use @default directive on field with list type [%s]", + typ.Name, field.Name, field.Type.Name())} + } + if field.Directives.ForName(idDirective) != nil { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: cannot use @default directive on field with @id directive", + typ.Name, field.Name)} + } + if isID(field) { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: cannot use @default directive on field with type ID", + typ.Name, field.Name)} + } + if field.Directives.ForName(customDirective) != nil { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: cannot use @default directive on field with @custom directive", + typ.Name, field.Name)} + } + if field.Directives.ForName(lambdaDirective) != nil { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: cannot use @default directive on field with @lambda directive", + typ.Name, field.Name)} + } + for _, arg := range dir.Arguments { + fieldType := field.Type.Name() + value := arg.Value.Children.ForName("value").Raw + if value == "$now" && fieldType != "DateTime" { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: @default directive provides value \"%s\" which cannot be used with %s", + typ.Name, field.Name, value, fieldType)} + } + if fieldType == "Int" { + if _, err := strconv.ParseInt(value, 10, 64); err != nil { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: @default directive provides value \"%s\" which cannot be used with %s", + typ.Name, field.Name, value, fieldType)} + } + } + if fieldType == "Float" { + if _, err := strconv.ParseFloat(value, 64); err != nil { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: @default directive provides value \"%s\" which cannot be used with %s", + typ.Name, field.Name, value, fieldType)} + } + } + if fieldType == "Boolean" && value != "true" && value != "false" { + return []*gqlerror.Error{gqlerror.ErrorPosf( + dir.Position, + "Type %s; Field %s: @default directive provides value \"%s\" which cannot be used with %s", + typ.Name, field.Name, value, fieldType)} + } + } + return nil +} + func lambdaOnMutateValidation(sch *ast.Schema, typ *ast.Definition) gqlerror.List { dir := typ.Directives.ForName(lambdaOnMutateDirective) if dir == nil { diff --git a/graphql/schema/testdata/apolloservice/output/auth-directive.graphql b/graphql/schema/testdata/apolloservice/output/auth-directive.graphql index 1d3488c0b27..c91fb7c1471 100644 --- a/graphql/schema/testdata/apolloservice/output/auth-directive.graphql +++ b/graphql/schema/testdata/apolloservice/output/auth-directive.graphql @@ -111,6 +111,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -193,6 +197,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM diff --git a/graphql/schema/testdata/apolloservice/output/custom-directive.graphql b/graphql/schema/testdata/apolloservice/output/custom-directive.graphql index 0ffe521b151..a39876c07d4 100644 --- a/graphql/schema/testdata/apolloservice/output/custom-directive.graphql +++ b/graphql/schema/testdata/apolloservice/output/custom-directive.graphql @@ -103,6 +103,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -185,6 +189,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM diff --git a/graphql/schema/testdata/apolloservice/output/extended-types.graphql b/graphql/schema/testdata/apolloservice/output/extended-types.graphql index 31024cd9323..c1295d8a145 100644 --- a/graphql/schema/testdata/apolloservice/output/extended-types.graphql +++ b/graphql/schema/testdata/apolloservice/output/extended-types.graphql @@ -117,6 +117,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -199,6 +203,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM diff --git a/graphql/schema/testdata/apolloservice/output/generate-directive.graphql b/graphql/schema/testdata/apolloservice/output/generate-directive.graphql index fd38dab07b9..069a312e111 100644 --- a/graphql/schema/testdata/apolloservice/output/generate-directive.graphql +++ b/graphql/schema/testdata/apolloservice/output/generate-directive.graphql @@ -113,6 +113,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -195,6 +199,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM diff --git a/graphql/schema/testdata/apolloservice/output/single-extended-type.graphql b/graphql/schema/testdata/apolloservice/output/single-extended-type.graphql index 0704e8fd6f3..07081021b4f 100644 --- a/graphql/schema/testdata/apolloservice/output/single-extended-type.graphql +++ b/graphql/schema/testdata/apolloservice/output/single-extended-type.graphql @@ -98,6 +98,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -180,6 +184,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM diff --git a/graphql/schema/testdata/schemagen/input/created-updated-directives.graphql b/graphql/schema/testdata/schemagen/input/created-updated-directives.graphql new file mode 100644 index 00000000000..a25ed3a9228 --- /dev/null +++ b/graphql/schema/testdata/schemagen/input/created-updated-directives.graphql @@ -0,0 +1,13 @@ +type Booking { + id: ID! + name: String! + created: DateTime! @default(add: {value:"$now"}) + updated: DateTime! @default(add: {value:"$now"}, update: {value:"$now"}) +} + +type BookingXID { + id: String! @id + name: String! + created: DateTime! @default(add: {value:"$now"}) + updated: DateTime! @default(add: {value:"$now"}, update: {value:"$now"}) +} diff --git a/graphql/schema/testdata/schemagen/output/apollo-federation.graphql b/graphql/schema/testdata/schemagen/output/apollo-federation.graphql index 91642aebb01..80c9cb5be09 100644 --- a/graphql/schema/testdata/schemagen/output/apollo-federation.graphql +++ b/graphql/schema/testdata/schemagen/output/apollo-federation.graphql @@ -133,6 +133,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -215,6 +219,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/auth-on-interfaces.graphql b/graphql/schema/testdata/schemagen/output/auth-on-interfaces.graphql index ea87104b74f..ce7c9f93a6c 100644 --- a/graphql/schema/testdata/schemagen/output/auth-on-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/auth-on-interfaces.graphql @@ -115,6 +115,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -197,6 +201,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/authorization.graphql b/graphql/schema/testdata/schemagen/output/authorization.graphql index 8d8a2da3d46..b75d733d116 100644 --- a/graphql/schema/testdata/schemagen/output/authorization.graphql +++ b/graphql/schema/testdata/schemagen/output/authorization.graphql @@ -111,6 +111,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -193,6 +197,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql b/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql index cf11ecc3856..7e8823dcb3f 100755 --- a/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql +++ b/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql @@ -124,6 +124,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -206,6 +210,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/created-updated-directives.graphql b/graphql/schema/testdata/schemagen/output/created-updated-directives.graphql new file mode 100644 index 00000000000..e54a114aa5e --- /dev/null +++ b/graphql/schema/testdata/schemagen/output/created-updated-directives.graphql @@ -0,0 +1,483 @@ +####################### +# Input Schema +####################### + +type Booking { + id: ID! + name: String! + created: DateTime! @default(add: {value:"$now"}) + updated: DateTime! @default(add: {value:"$now"}, update: {value:"$now"}) +} + +type BookingXID { + id: String! @id + name: String! + created: DateTime! @default(add: {value:"$now"}) + updated: DateTime! @default(add: {value:"$now"}, update: {value:"$now"}) +} + +####################### +# Extended Definitions +####################### + +""" +The Int64 scalar type represents a signed 64‐bit numeric non‐fractional value. +Int64 can represent values in range [-(2^63),(2^63 - 1)]. +""" +scalar Int64 + +""" +The DateTime scalar type represents date and time as a string in RFC3339 format. +For example: "1985-04-12T23:20:50.52Z" represents 20 minutes and 50.52 seconds after the 23rd hour of April 12th, 1985 in UTC. +""" +scalar DateTime + +input IntRange{ + min: Int! + max: Int! +} + +input FloatRange{ + min: Float! + max: Float! +} + +input Int64Range{ + min: Int64! + max: Int64! +} + +input DateTimeRange{ + min: DateTime! + max: DateTime! +} + +input StringRange{ + min: String! + max: String! +} + +enum DgraphIndex { + int + int64 + float + bool + hash + exact + term + fulltext + trigram + regexp + year + month + day + hour + geo +} + +input AuthRule { + and: [AuthRule] + or: [AuthRule] + not: AuthRule + rule: String +} + +enum HTTPMethod { + GET + POST + PUT + PATCH + DELETE +} + +enum Mode { + BATCH + SINGLE +} + +input CustomHTTP { + url: String! + method: HTTPMethod! + body: String + graphql: String + mode: Mode + forwardHeaders: [String!] + secretHeaders: [String!] + introspectionHeaders: [String!] + skipIntrospection: Boolean +} + +input DgraphDefault { + value: String +} + +type Point { + longitude: Float! + latitude: Float! +} + +input PointRef { + longitude: Float! + latitude: Float! +} + +input NearFilter { + distance: Float! + coordinate: PointRef! +} + +input PointGeoFilter { + near: NearFilter + within: WithinFilter +} + +type PointList { + points: [Point!]! +} + +input PointListRef { + points: [PointRef!]! +} + +type Polygon { + coordinates: [PointList!]! +} + +input PolygonRef { + coordinates: [PointListRef!]! +} + +type MultiPolygon { + polygons: [Polygon!]! +} + +input MultiPolygonRef { + polygons: [PolygonRef!]! +} + +input WithinFilter { + polygon: PolygonRef! +} + +input ContainsFilter { + point: PointRef + polygon: PolygonRef +} + +input IntersectsFilter { + polygon: PolygonRef + multiPolygon: MultiPolygonRef +} + +input PolygonGeoFilter { + near: NearFilter + within: WithinFilter + contains: ContainsFilter + intersects: IntersectsFilter +} + +input GenerateQueryParams { + get: Boolean + query: Boolean + password: Boolean + aggregate: Boolean +} + +input GenerateMutationParams { + add: Boolean + update: Boolean + delete: Boolean +} + +directive @hasInverse(field: String!) on FIELD_DEFINITION +directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION +directive @id on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION +directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION +directive @secret(field: String!, pred: String) on OBJECT | INTERFACE +directive @auth( + password: AuthRule + query: AuthRule, + add: AuthRule, + update: AuthRule, + delete: AuthRule) on OBJECT | INTERFACE +directive @custom(http: CustomHTTP, dql: String) on FIELD_DEFINITION +directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM +directive @remoteResponse(name: String) on FIELD_DEFINITION +directive @cascade(fields: [String]) on FIELD +directive @lambda on FIELD_DEFINITION +directive @lambdaOnMutate(add: Boolean, update: Boolean, delete: Boolean) on OBJECT | INTERFACE +directive @cacheControl(maxAge: Int!) on QUERY +directive @generate( + query: GenerateQueryParams, + mutation: GenerateMutationParams, + subscription: Boolean) on OBJECT | INTERFACE + +input IntFilter { + eq: Int + in: [Int] + le: Int + lt: Int + ge: Int + gt: Int + between: IntRange +} + +input Int64Filter { + eq: Int64 + in: [Int64] + le: Int64 + lt: Int64 + ge: Int64 + gt: Int64 + between: Int64Range +} + +input FloatFilter { + eq: Float + in: [Float] + le: Float + lt: Float + ge: Float + gt: Float + between: FloatRange +} + +input DateTimeFilter { + eq: DateTime + in: [DateTime] + le: DateTime + lt: DateTime + ge: DateTime + gt: DateTime + between: DateTimeRange +} + +input StringTermFilter { + allofterms: String + anyofterms: String +} + +input StringRegExpFilter { + regexp: String +} + +input StringFullTextFilter { + alloftext: String + anyoftext: String +} + +input StringExactFilter { + eq: String + in: [String] + le: String + lt: String + ge: String + gt: String + between: StringRange +} + +input StringHashFilter { + eq: String + in: [String] +} + +####################### +# Generated Types +####################### + +type AddBookingPayload { + booking(filter: BookingFilter, order: BookingOrder, first: Int, offset: Int): [Booking] + numUids: Int +} + +type AddBookingXIDPayload { + bookingXID(filter: BookingXIDFilter, order: BookingXIDOrder, first: Int, offset: Int): [BookingXID] + numUids: Int +} + +type BookingAggregateResult { + count: Int + nameMin: String + nameMax: String + createdMin: DateTime + createdMax: DateTime + updatedMin: DateTime + updatedMax: DateTime +} + +type BookingXIDAggregateResult { + count: Int + idMin: String + idMax: String + nameMin: String + nameMax: String + createdMin: DateTime + createdMax: DateTime + updatedMin: DateTime + updatedMax: DateTime +} + +type DeleteBookingPayload { + booking(filter: BookingFilter, order: BookingOrder, first: Int, offset: Int): [Booking] + msg: String + numUids: Int +} + +type DeleteBookingXIDPayload { + bookingXID(filter: BookingXIDFilter, order: BookingXIDOrder, first: Int, offset: Int): [BookingXID] + msg: String + numUids: Int +} + +type UpdateBookingPayload { + booking(filter: BookingFilter, order: BookingOrder, first: Int, offset: Int): [Booking] + numUids: Int +} + +type UpdateBookingXIDPayload { + bookingXID(filter: BookingXIDFilter, order: BookingXIDOrder, first: Int, offset: Int): [BookingXID] + numUids: Int +} + +####################### +# Generated Enums +####################### + +enum BookingHasFilter { + name + created + updated +} + +enum BookingOrderable { + name + created + updated +} + +enum BookingXIDHasFilter { + id + name + created + updated +} + +enum BookingXIDOrderable { + id + name + created + updated +} + +####################### +# Generated Inputs +####################### + +input AddBookingInput { + name: String! + created: DateTime + updated: DateTime +} + +input AddBookingXIDInput { + id: String! + name: String! + created: DateTime + updated: DateTime +} + +input BookingFilter { + id: [ID!] + has: [BookingHasFilter] + and: [BookingFilter] + or: [BookingFilter] + not: BookingFilter +} + +input BookingOrder { + asc: BookingOrderable + desc: BookingOrderable + then: BookingOrder +} + +input BookingPatch { + name: String + created: DateTime + updated: DateTime +} + +input BookingRef { + id: ID + name: String + created: DateTime + updated: DateTime +} + +input BookingXIDFilter { + id: StringHashFilter + has: [BookingXIDHasFilter] + and: [BookingXIDFilter] + or: [BookingXIDFilter] + not: BookingXIDFilter +} + +input BookingXIDOrder { + asc: BookingXIDOrderable + desc: BookingXIDOrderable + then: BookingXIDOrder +} + +input BookingXIDPatch { + id: String + name: String + created: DateTime + updated: DateTime +} + +input BookingXIDRef { + id: String + name: String + created: DateTime + updated: DateTime +} + +input UpdateBookingInput { + filter: BookingFilter! + set: BookingPatch + remove: BookingPatch +} + +input UpdateBookingXIDInput { + filter: BookingXIDFilter! + set: BookingXIDPatch + remove: BookingXIDPatch +} + +####################### +# Generated Query +####################### + +type Query { + getBooking(id: ID!): Booking + queryBooking(filter: BookingFilter, order: BookingOrder, first: Int, offset: Int): [Booking] + aggregateBooking(filter: BookingFilter): BookingAggregateResult + getBookingXID(id: String!): BookingXID + queryBookingXID(filter: BookingXIDFilter, order: BookingXIDOrder, first: Int, offset: Int): [BookingXID] + aggregateBookingXID(filter: BookingXIDFilter): BookingXIDAggregateResult +} + +####################### +# Generated Mutations +####################### + +type Mutation { + addBooking(input: [AddBookingInput!]!): AddBookingPayload + updateBooking(input: UpdateBookingInput!): UpdateBookingPayload + deleteBooking(filter: BookingFilter!): DeleteBookingPayload + addBookingXID(input: [AddBookingXIDInput!]!, upsert: Boolean): AddBookingXIDPayload + updateBookingXID(input: UpdateBookingXIDInput!): UpdateBookingXIDPayload + deleteBookingXID(filter: BookingXIDFilter!): DeleteBookingXIDPayload +} + diff --git a/graphql/schema/testdata/schemagen/output/custom-dql-query-with-subscription.graphql b/graphql/schema/testdata/schemagen/output/custom-dql-query-with-subscription.graphql index a6c89246ef5..1a9ea6d0433 100755 --- a/graphql/schema/testdata/schemagen/output/custom-dql-query-with-subscription.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-dql-query-with-subscription.graphql @@ -112,6 +112,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -194,6 +198,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/custom-mutation.graphql b/graphql/schema/testdata/schemagen/output/custom-mutation.graphql index 1b48735de16..b1491d50143 100644 --- a/graphql/schema/testdata/schemagen/output/custom-mutation.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-mutation.graphql @@ -102,6 +102,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -184,6 +188,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql b/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql index 7184d90e5a8..e5ef0f6ce6c 100755 --- a/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql @@ -119,6 +119,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -201,6 +205,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql b/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql index d441721cf27..56869daf11e 100644 --- a/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql @@ -103,6 +103,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -185,6 +189,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql b/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql index bbc666a87e1..88be19f9679 100755 --- a/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql @@ -102,6 +102,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -184,6 +188,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql b/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql index a38c50561d8..cafa431e847 100755 --- a/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql @@ -98,6 +98,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -180,6 +184,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/deprecated.graphql b/graphql/schema/testdata/schemagen/output/deprecated.graphql index 52cb4ea15d4..d7c47708cf2 100755 --- a/graphql/schema/testdata/schemagen/output/deprecated.graphql +++ b/graphql/schema/testdata/schemagen/output/deprecated.graphql @@ -98,6 +98,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -180,6 +184,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql index b1af0955121..c701b754382 100755 --- a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql @@ -115,6 +115,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -197,6 +201,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql index 44da4eec782..ce781cc3796 100755 --- a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql @@ -115,6 +115,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -197,6 +201,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql b/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql index 47653c74222..96fc5b69fde 100755 --- a/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql @@ -112,6 +112,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -194,6 +198,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/field-with-multiple-@id-fields.graphql b/graphql/schema/testdata/schemagen/output/field-with-multiple-@id-fields.graphql index d8b93ef7b08..9747d771ad2 100755 --- a/graphql/schema/testdata/schemagen/output/field-with-multiple-@id-fields.graphql +++ b/graphql/schema/testdata/schemagen/output/field-with-multiple-@id-fields.graphql @@ -112,6 +112,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -194,6 +198,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql b/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql index f2145184ee6..a3c7b81057e 100755 --- a/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql @@ -107,6 +107,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -189,6 +193,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql index 64d88e15dd9..0990e50ec03 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql @@ -110,6 +110,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -192,6 +196,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql index fd2ae029d78..f8c12e3718e 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql @@ -114,6 +114,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -196,6 +200,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql index 480d42cc906..b945880374b 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql @@ -102,6 +102,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -184,6 +188,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql index ce22f674d5a..eb34687aeef 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql @@ -112,6 +112,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -194,6 +198,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/generate-directive.graphql b/graphql/schema/testdata/schemagen/output/generate-directive.graphql index 046c376fd08..1a4e9a7a725 100644 --- a/graphql/schema/testdata/schemagen/output/generate-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/generate-directive.graphql @@ -113,6 +113,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -195,6 +199,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/geo-type.graphql b/graphql/schema/testdata/schemagen/output/geo-type.graphql index 7b007dbea08..071120217c4 100644 --- a/graphql/schema/testdata/schemagen/output/geo-type.graphql +++ b/graphql/schema/testdata/schemagen/output/geo-type.graphql @@ -104,6 +104,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -186,6 +190,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql index 2a6e74d672c..5529d051f3a 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql @@ -123,6 +123,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -205,6 +209,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql index 7262833b462..07d3a978165 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql @@ -125,6 +125,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -207,6 +211,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql b/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql index 2a6e74d672c..5529d051f3a 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql @@ -123,6 +123,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -205,6 +209,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/hasInverse.graphql b/graphql/schema/testdata/schemagen/output/hasInverse.graphql index e550998e55a..2e1b4087111 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse.graphql @@ -104,6 +104,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -186,6 +190,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql b/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql index 08cebd56299..177f12530f2 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql @@ -104,6 +104,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -186,6 +190,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/hasfilter.graphql b/graphql/schema/testdata/schemagen/output/hasfilter.graphql index e5adcc1acc6..69bfb06206a 100644 --- a/graphql/schema/testdata/schemagen/output/hasfilter.graphql +++ b/graphql/schema/testdata/schemagen/output/hasfilter.graphql @@ -106,6 +106,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -188,6 +192,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql b/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql index 0d50f4fcb38..c1ab841a763 100755 --- a/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql @@ -105,6 +105,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -187,6 +191,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql b/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql index a604dd070c5..46511cf0a48 100644 --- a/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql +++ b/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql @@ -114,6 +114,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -196,6 +200,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql b/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql index db2e3d3be50..0f11c74abee 100755 --- a/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql @@ -110,6 +110,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -192,6 +196,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql b/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql index 90161b27860..95bf2aed056 100755 --- a/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql +++ b/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql @@ -108,6 +108,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -190,6 +194,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql b/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql index 2314846daa9..baee5257b8f 100755 --- a/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql +++ b/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql @@ -133,6 +133,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -215,6 +219,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql b/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql index 53da87263b2..0b6f623356c 100755 --- a/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql +++ b/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql @@ -133,6 +133,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -215,6 +219,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/lambda-directive.graphql b/graphql/schema/testdata/schemagen/output/lambda-directive.graphql index 8df251f64a7..13dc614cc54 100644 --- a/graphql/schema/testdata/schemagen/output/lambda-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/lambda-directive.graphql @@ -100,6 +100,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -182,6 +186,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/language-tags.graphql b/graphql/schema/testdata/schemagen/output/language-tags.graphql index 09bbce78f52..b67526feee5 100755 --- a/graphql/schema/testdata/schemagen/output/language-tags.graphql +++ b/graphql/schema/testdata/schemagen/output/language-tags.graphql @@ -113,6 +113,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -195,6 +199,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( @@ -447,6 +452,7 @@ input PersonPatch { f1Hi: String f2: String f3: String + name: String nameHi: String nameEn: String address: String diff --git a/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql b/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql index 5430dbf9e17..5c976fe960e 100755 --- a/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql +++ b/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql @@ -97,6 +97,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -179,6 +183,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/no-id-field.graphql b/graphql/schema/testdata/schemagen/output/no-id-field.graphql index 1976d50b845..bc720948cbf 100755 --- a/graphql/schema/testdata/schemagen/output/no-id-field.graphql +++ b/graphql/schema/testdata/schemagen/output/no-id-field.graphql @@ -110,6 +110,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -192,6 +196,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/password-type.graphql b/graphql/schema/testdata/schemagen/output/password-type.graphql index cba6c170459..ffcd13110cd 100755 --- a/graphql/schema/testdata/schemagen/output/password-type.graphql +++ b/graphql/schema/testdata/schemagen/output/password-type.graphql @@ -98,6 +98,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -180,6 +184,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/random.graphql b/graphql/schema/testdata/schemagen/output/random.graphql index 117b334faef..77a1cbc61ec 100644 --- a/graphql/schema/testdata/schemagen/output/random.graphql +++ b/graphql/schema/testdata/schemagen/output/random.graphql @@ -116,6 +116,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -198,6 +202,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @remote on OBJECT | INTERFACE | UNION | INPUT_OBJECT | ENUM diff --git a/graphql/schema/testdata/schemagen/output/searchables-references.graphql b/graphql/schema/testdata/schemagen/output/searchables-references.graphql index a1d33610f5a..405e5facd32 100755 --- a/graphql/schema/testdata/schemagen/output/searchables-references.graphql +++ b/graphql/schema/testdata/schemagen/output/searchables-references.graphql @@ -108,6 +108,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -190,6 +194,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/searchables.graphql b/graphql/schema/testdata/schemagen/output/searchables.graphql index 8e21af2ddcd..21bb0df8902 100755 --- a/graphql/schema/testdata/schemagen/output/searchables.graphql +++ b/graphql/schema/testdata/schemagen/output/searchables.graphql @@ -128,6 +128,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -210,6 +214,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql b/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql index dc67bd55967..20445ad0497 100755 --- a/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql +++ b/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql @@ -106,6 +106,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -188,6 +192,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/single-type.graphql b/graphql/schema/testdata/schemagen/output/single-type.graphql index ffd93575abf..524aaa18295 100755 --- a/graphql/schema/testdata/schemagen/output/single-type.graphql +++ b/graphql/schema/testdata/schemagen/output/single-type.graphql @@ -101,6 +101,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -183,6 +187,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql b/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql index b789d8551f7..ecbd5db1b2c 100755 --- a/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql @@ -115,6 +115,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -197,6 +201,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/type-reference.graphql b/graphql/schema/testdata/schemagen/output/type-reference.graphql index 721497a18fd..20811f0a341 100755 --- a/graphql/schema/testdata/schemagen/output/type-reference.graphql +++ b/graphql/schema/testdata/schemagen/output/type-reference.graphql @@ -105,6 +105,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -187,6 +191,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql b/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql index 192482c12fa..b98d068a640 100644 --- a/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql +++ b/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql @@ -106,6 +106,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -188,6 +192,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql b/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql index 7e4c71914f7..d3336134634 100644 --- a/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql +++ b/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql @@ -105,6 +105,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -187,6 +191,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql b/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql index e85ea68b041..6db0f218446 100644 --- a/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql +++ b/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql @@ -105,6 +105,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -187,6 +191,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql b/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql index ff78a20fbb1..fac1447b75d 100644 --- a/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql +++ b/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql @@ -100,6 +100,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -182,6 +186,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/testdata/schemagen/output/union.graphql b/graphql/schema/testdata/schemagen/output/union.graphql index 33eaa4c6c54..7d8d32ed3ad 100644 --- a/graphql/schema/testdata/schemagen/output/union.graphql +++ b/graphql/schema/testdata/schemagen/output/union.graphql @@ -147,6 +147,10 @@ input CustomHTTP { skipIntrospection: Boolean } +input DgraphDefault { + value: String +} + type Point { longitude: Float! latitude: Float! @@ -229,6 +233,7 @@ directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION +directive @default(add: DgraphDefault, update: DgraphDefault) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION directive @secret(field: String!, pred: String) on OBJECT | INTERFACE directive @auth( diff --git a/graphql/schema/wrappers.go b/graphql/schema/wrappers.go index 40239982a55..056f5e12d1b 100644 --- a/graphql/schema/wrappers.go +++ b/graphql/schema/wrappers.go @@ -19,12 +19,14 @@ package schema import ( "bytes" "encoding/json" + "flag" "fmt" "net/http" "net/url" "sort" "strconv" "strings" + "time" "github.com/pkg/errors" @@ -270,6 +272,7 @@ type FieldDefinition interface { IsExternal() bool HasIDDirective() bool HasInterfaceArg() bool + GetDefaultValue(action string) interface{} Inverse() FieldDefinition WithMemberType(string) FieldDefinition // TODO - It might be possible to get rid of ForwardEdge and just use Inverse() always. @@ -2313,6 +2316,36 @@ func (fd *fieldDefinition) IsID() bool { return isID(fd.fieldDef) } +func (fd *fieldDefinition) GetDefaultValue(action string) interface{} { + if fd.fieldDef == nil { + return nil + } + return getDefaultValue(fd.fieldDef, action) +} + +func getDefaultValue(fd *ast.FieldDefinition, action string) interface{} { + dir := fd.Directives.ForName(defaultDirective) + if dir == nil { + return nil + } + arg := dir.Arguments.ForName(action) + if arg == nil { + return nil + } + value := arg.Value.Children.ForName("value") + if value == nil { + return nil + } + if value.Raw == "$now" { + if flag.Lookup("test.v") == nil { + return time.Now().Format(time.RFC3339) + } else { + return "2000-01-01T00:00:00.00Z" + } + } + return value.Raw +} + func (fd *fieldDefinition) HasIDDirective() bool { if fd.fieldDef == nil { return false @@ -2353,6 +2386,10 @@ func isID(fd *ast.FieldDefinition) bool { return fd.Type.Name() == "ID" } +func hasDefault(fd *ast.FieldDefinition) bool { + return fd.Directives.ForName(defaultDirective) != nil +} + func (fd *fieldDefinition) Type() Type { return &astType{ typ: fd.fieldDef.Type, @@ -2717,7 +2754,7 @@ func (t *astType) ImplementingTypes() []Type { // satisfy a valid post. func (t *astType) EnsureNonNulls(obj map[string]interface{}, exclusion string) error { for _, fld := range t.inSchema.schema.Types[t.Name()].Fields { - if fld.Type.NonNull && !isID(fld) && fld.Name != exclusion && + if fld.Type.NonNull && !isID(fld) && !hasDefault(fld) && fld.Name != exclusion && t.inSchema.customDirectives[t.Name()][fld.Name] == nil { if val, ok := obj[fld.Name]; !ok || val == nil { return errors.Errorf(