-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: GraphQL upsert mutation #3075
feat: GraphQL upsert mutation #3075
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #3075 +/- ##
===========================================
- Coverage 79.50% 79.44% -0.06%
===========================================
Files 345 346 +1
Lines 26565 26705 +140
===========================================
+ Hits 21118 21214 +96
- Misses 3936 3963 +27
- Partials 1511 1528 +17
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 9 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wowza, super awesome stuff! Left some comments in first pass :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks nice for far! Very useful feature. I have most suggestions.
internal/planner/upsert.go
Outdated
@@ -0,0 +1,185 @@ | |||
// Copyright 2022 Democratized Data Foundation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: 2024
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
internal/planner/upsert.go
Outdated
updateInput map[string]any | ||
doc *client.Document | ||
isUpserting bool | ||
results planNode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: I find the name results
a bit confusing for planNode
. When reading methods' bodies I though it was a results objects of storage iterator.
I think a more common name would be source
or plan
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to source
internal/planner/upsert.go
Outdated
createInput map[string]any | ||
updateInput map[string]any | ||
doc *client.Document | ||
isUpserting bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: was also a bit puzzled why upsertNode
has isUpserting
prop. Maybe call it something like isInitialized
? As a bonus you wouldn't need to initialize it to true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied it from the update node which has an isUpdating
prop.
internal/planner/upsert.go
Outdated
switch next { | ||
case true: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: first time in my life I see this kind of switch :D
Maybe a classical if
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol +1 for making into if
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
internal/planner/upsert.go
Outdated
doc, err := client.NewDocFromMap(n.createInput, n.collection.Definition()) | ||
if err != nil { | ||
return err | ||
} | ||
n.doc = doc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: this part is not needed when upserting. Maybe move it to "create" branch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
|
||
// Next only returns once. | ||
func (n *upsertNode) Next() (bool, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: this upsertNode
looks (to some extend) as copy&paste of 2 nodes updateNode
and createNode
.
Did you consider making upsertNode
detect if it's update or create op and (on the fly?) use one of those?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did have that thought, but I think its worth the extra LOC to keep it separate incase we decide to extend or modify it.
testUtils.ExecuteTestCase(t, test) | ||
} | ||
|
||
func TestMutationUpsertSimple_WithUniqueCompositeIndexAndDuplicateUpdate_ReturnsError(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
praise: thanks for this test and for making clear test names.
testUtils.Request{ | ||
Request: `mutation { | ||
upsert_Users( | ||
filter: {name: {_eq: "Bob"}}, | ||
create: {name: "Bob", age: 40}, | ||
update: {age: 40} | ||
) { | ||
name | ||
age | ||
} | ||
}`, | ||
Results: map[string]any{ | ||
"upsert_Users": []map[string]any{ | ||
{ | ||
"name": "Bob", | ||
"age": int64(40), | ||
}, | ||
}, | ||
}, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: I think it also makes sense to run a follow up query request to make it really fetches them from storage and not just as a response.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Input = "input" | ||
CreateInput = "create" | ||
UpdateInput = "update" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: shouldn't "create" and "update" replace "input"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think keeping the input
label for create and update mutations is fine.
Changing it to create_User(create: {name: "Bob"})
doesn't read as nice imo.
return false, err | ||
} | ||
if next { | ||
return false, ErrUpsertMultipleDocuments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: is there an inherent problemt with upserting multiple docs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's nothing stopping us from supporting it in the future. It's there to stop users from doing something unexpected like updating all documents when they just wanted to upsert a single document.
If we do support it in the future we will want to add a variable to control the behavior: unique
or all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job, Keenan!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing the requested changes and answering all the comments =)
Relevant issue(s)
Resolves #783
Description
This PR adds a new upsert GraphQL mutation operation.
Tasks
How has this been tested?
Added integration tests.
Specify the platform(s) on which this was tested: