-
Notifications
You must be signed in to change notification settings - Fork 108
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
Support upsert with empty updates #301
base: master
Are you sure you want to change the base?
Conversation
Ah, dang. In the event that we do an So the most proper type of At least, as a default. Playing around locally, the following form works: WITH inserted AS (
INSERT INTO "OneUnique" (name, value)
VALUES ("asdf", 0)
ON CONFLICT (value)
DO NOTHING
RETURNING id, name, value
)
SELECT id, name, value
FROM inserted
UNION
SELECT id, name, value
FROM "OneUnique"
WHERE value = 0 But I have no idea what sorts of performance this has. This StackOverflow question/answer has some details and it looks to be somewhat complicated. Maybe the type of coolUpsert entity updates =
case NonEmpty.nonEmpty updates of
Just nonEmptyUpdates ->
Just <$> upsert entity nonEmptyUpdates
Nothing ->
insertOnConflictDoNothing entity It might be tempting to write:
But this only means that the uniqueness key is the same, not the rest of the values. |
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.
Dang, this is more complicated than I thought.
@@ -51,6 +51,34 @@ import Common.Test | |||
import Common.Test.Import hiding (from, on) | |||
import PostgreSQL.MigrateJSON | |||
|
|||
spec :: Spec |
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.
this is just moved up to the top
test/PostgreSQL/Test.hs
Outdated
@@ -1038,18 +1066,20 @@ testInsertUniqueViolation = | |||
sqlErrorHint = ""} | |||
|
|||
testUpsert :: SpecDb | |||
testUpsert = | |||
describe "Upsert test" $ do | |||
testUpsert = describe "Upsert test" $ do |
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.
fixed formatting to be 4 space indent
test/PostgreSQL/Test.hs
Outdated
itDb "Works with no updates" $ do | ||
_ <- EP.upsert u1 [] | ||
pure () |
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.
New test case here
itDb "Works with no updates" $ do | ||
_ <- EP.upsert u1 [] | ||
pure () |
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.
Well, this passes. Hooray.
itDb "Works with no updates, twice" $ do | ||
Entity u1Key u1' <- EP.upsert u1 [] | ||
Entity u1Key_ u1'' <- EP.upsert u1 { oneUniqueName = "Something Else" } [] | ||
pure () |
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.
Unfortunately, this fails with ErrorCall "head: empty list"
.
The reason is that:
INSERT INTO "OneUnique" (name, value)
VALUES (?, ?)
ON CONFLICT DO NOTHING
RETURNING id, name, value
does not return anything if we don't perform an INSERT
- so the return is []
which he head
on and it goes boom.
DO UPDATE
always does something. But we really don't want to do something silly like DO UPDATE SET blah = EXCLUDED.blah
because this does unnecessary writes and triggers.
Fixes #300
Before submitting your PR, check that you've:
@since
declarations to the Haddock.stylish-haskell
and otherwise adhered to the style guide.After submitting your PR: