Repository navigation
fix: honor ignoreDuplicates in upsert - #28
Merged
Merged
Conversation
An upsert with `ignoreDuplicates: true` sends `Prefer: resolution=ignore-duplicates`, which the request dispatch did not recognize, so it was classified as an insert and the conflicting row was added as a duplicate. Treat both resolutions as upserts and skip conflicting rows instead of merging them when `ignore-duplicates` is requested. Skipped rows are left out of the response, matching PostgREST. Fixes #26
grdsdev
approved these changes
Sep 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #26
Problem
PostgrestQueryBuilder.upsertsendsPrefer: resolution=ignore-duplicateswhen called withignoreDuplicates: true, andresolution=merge-duplicatesotherwise. The request dispatch only recognizedmerge-duplicates, so an upsert withignoreDuplicates: truewas classified asRequestType.insertand never reached_handleUpsert. The conflicting row was appended as a duplicate:Changes
POSTdispatch now treatsresolution=ignore-duplicatesas an upsert alongsideresolution=merge-duplicates. As a side effect,postgrestExceptionTriggernow receivesRequestType.upsertrather thanRequestType.insertfor these requests, which is what it should have been._handleUpsertreads the resolution from thePreferheader. Whenignore-duplicatesis requested, a row that matches the conflict target is left untouched and no new row is inserted. Rows that do not conflict are still inserted.INSERT ... ON CONFLICT DO NOTHING RETURNING.Tests
Three tests were added covering both reproductions from the issue (default
idconflict target and an explicitonConflictcolumn) plus a mixed batch where one row conflicts and one does not, asserting both the response body and the resulting table contents. The full suite passes, anddart formatanddart analyze --fatal-warnings --fatal-infosare clean.