-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
fix: HTTP status responses for upserts #2926
fix: HTTP status responses for upserts #2926
Conversation
479f924
to
6619350
Compare
postgrest/src/PostgREST/Query.hs Lines 234 to 236 in 0703f27
Edit: NVM, @steve-chavez confirmed that it may be kinda costly, it's better to keep it as it is right now. |
6619350
to
319b416
Compare
With this change, the cost of single upsert becomes:
@laurenceisla @steve-chavez Is it still worth it? |
@taimoorzaeem To be extra sure, we would need to test upserts with more than one single row. These are done with resolution=merge-duplicates. If the extra cost is constant, then it would be worth it, I think. So how about adding some more tests below here: postgrest/test/spec/Feature/Query/PlanSpec.hs Lines 183 to 195 in a9d6c31
I'm thinking: it "outputs the total cost for an upsert with 10 rows" $ do
it "outputs the total cost for an upsert with 100 rows" $ do
it "outputs the total cost for an upsert with 1000 rows" $ do There should be a helper function that generates the payload. Rough idea:
And maybe using Aeson.toJSONList to convert to JSON. These tests can be added in another PR. In fact that would be better to see the resulting costs there to compare. Sometimes we do commits that only add tests, like add10bd |
319b416
to
23619ff
Compare
Alright. I'll open another PR to add these tests. |
23619ff
to
2281e87
Compare
As far as I can see, there were no existing tests for Adding this test to the beginning of it "UPDATEs rows and returns 200 on pk conflict on all the items" $
request methodPost "/tiobe_pls" [("Prefer", "return=representation"), ("Prefer", "resolution=merge-duplicates")]
[json| [
{ "name": "Python", "rank": 6 },
{ "name": "Java", "rank": 2 },
{ "name": "C", "rank": 1 }
]|] `shouldRespondWith` [json| [
{ "name": "Python", "rank": 6 },
{ "name": "Java", "rank": 2 },
{ "name": "C", "rank": 1 }
]|]
{ matchStatus = 200
, matchHeaders = ["Preference-Applied" <:> "resolution=merge-duplicates, return=representation", matchContentTypeJson]
} All of those already exist in the database, so a So far so good, we're almost there! This wasn't a simple issue by any means. |
2281e87
to
acebd4e
Compare
Lastly, what's missing from the original issue is to verify that:
|
Hmm, for mutatePlanToQuery :: Maybe PreferResolution -> MutatePlan -> SQL.Snippet
mutatePlanToQuery resolution (Insert mainQi iCols body onConflct putConditions returnings _ applyDefaults) =
"INSERT INTO " <> fromQi mainQi <> (if null iCols then " " else "(" <> cols <> ") ") <>
fromJsonBodyF body iCols True False applyDefaults <>
-- Only used for PUT
(if null putConditions then mempty else "WHERE " <> addConfigPgrstInserted True <> " AND " <> intercalateSnippet " AND " (pgFmtLogicTree (QualifiedIdentifier mempty "pgrst_body") <$> putConditions)) <>
(if null putConditions && isJust resolution then "WHERE " <> addConfigPgrstInserted True else mempty) <>
maybe mempty (\(oncDo, oncCols) ->
if null oncCols then
mempty
else
" ON CONFLICT(" <> intercalateSnippet ", " (pgFmtIdent <$> oncCols) <> ") " <> case oncDo of
IgnoreDuplicates ->
"DO NOTHING"
MergeDuplicates ->
if null iCols
then "DO NOTHING"
else "DO UPDATE SET " <> intercalateSnippet ", " ((pgFmtIdent . cfName) <> const " = EXCLUDED." <> (pgFmtIdent . cfName) <$> iCols) <> (if null putConditions && isNothing resolution then mempty else "WHERE " <> addConfigPgrstInserted False)
) onConflct <> " " <>
returningF mainQi returnings I first add 1 when row is inserted, but if there is IgnoreDuplicates ->
"DO NOTHING" <> " WHERE " <> addConfigPgrstInserted False -- not possible i guess |
True that. I noticed that PostgreSQL allows We could leave that outside of this PR to check for a better solution later on, it won't close the issue completely but it's good progress. |
d68b098
to
c27e54e
Compare
c27e54e
to
7a868f6
Compare
c7c65c3
to
8c9213d
Compare
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.
Good job! I clarified a message and rebased against the changes made in main to be ready to merge.
This might fix #1070.
Fixed
PUT
returns201
instead of200
when rows are insertedPOST
withPrefer: resolution=merge-duplicates
returns200
instead of201
when no rows are inserted