Skip to content

Commit

Permalink
feat(graphql): adds @default directive to graphql (#8017)
Browse files Browse the repository at this point in the history
  • Loading branch information
mangalaman93 authored and shivaji-kharse committed Aug 26, 2024
1 parent 05bfcae commit 0a7816b
Show file tree
Hide file tree
Showing 68 changed files with 1,370 additions and 7 deletions.
5 changes: 5 additions & 0 deletions graphql/e2e/schema/apollo_service_response.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ input CustomHTTP {
skipIntrospection: Boolean
}

input DgraphDefault {
value: String
}

type Point {
longitude: Float!
latitude: Float!
Expand Down Expand Up @@ -201,6 +205,7 @@ directive @search(by: [String!]) on FIELD_DEFINITION
directive @embedding 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
Expand Down
5 changes: 5 additions & 0 deletions graphql/e2e/schema/generatedSchema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ input CustomHTTP {
skipIntrospection: Boolean
}

input DgraphDefault {
value: String
}

type Point {
longitude: Float!
latitude: Float!
Expand Down Expand Up @@ -182,6 +186,7 @@ directive @search(by: [String!]) on FIELD_DEFINITION
directive @embedding 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(
Expand Down
199 changes: 198 additions & 1 deletion graphql/resolve/add_mutation_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5499,4 +5499,201 @@
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"
]
}
15 changes: 15 additions & 0 deletions graphql/resolve/mutation_rewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -1587,6 +1587,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
Expand Down Expand Up @@ -1635,6 +1637,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
Expand Down
26 changes: 26 additions & 0 deletions graphql/resolve/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down
Loading

0 comments on commit 0a7816b

Please sign in to comment.