Skip to content

[#190]: Add upsert support via onConflict argument - #622

Closed
matt-metivier wants to merge 6 commits into
supabase:masterfrom
matt-metivier:feat/on-conflict-upsert
Closed

matt-metivier wants to merge 6 commits into
supabase:masterfrom
matt-metivier:feat/on-conflict-upsert

Conversation

@matt-metivier

@matt-metivier matt-metivier commented Jan 26, 2026 •

Copy link
Copy Markdown

Adds an onConflict argument to insert mutations so INSERT ... ON CONFLICT DO UPDATE is reachable through the API. Closes #190.

Each table with a usable unique index gains a {Table}OnConflict input taking constraint, updateColumns and filter, backed by a {Table}Constraint enum of index names and a {Table}UpdateColumn enum of updatable columns. Index names come from pg_class. The argument is only exposed on tables that have a valid constraint, so serial and generated primary keys do not get it, since constraint columns have to be insertable. An empty updateColumns transpiles to DO NOTHING.

Tests in test/sql/mutation_insert_on_conflict.sql.

Based on #503, reimplemented on current master without the unrelated changes.

@matt-metivier matt-metivier changed the title feat: Add upsert support via onConflict argument [#190]: Add upsert support via onConflict argument Jan 26, 2026
@matt-metivier

Copy link
Copy Markdown
Author

Whenever you've time @olirice, I tried to match & build on what you had in #503

matt-metivier and others added 5 commits January 25, 2026 20:07
- Rename updateColumns to updateFields
- Rename {Table}UpdateColumn enum to {Table}Field
- Rename {Table}Constraint enum to {Table}OnConflictConstraint
- Keep DO NOTHING improvement for empty updateFields
- Make graphql_column_field_name method public
- Add OnConflictInput to all __Type match arms (kind, name, description, fields, interfaces, enum_values, input_fields)
- Add TableColumns and OnConflictTarget to EnumSource match in parser_util.rs
- Fix string comparison in builder.rs using as_str()
Move where_clause computation inside the else branch in on_conflict_clause
so param_context is not mutated when update_fields is empty (do nothing path).

Also apply rustfmt to builder.rs lines that exceeded the line length limit.
78 commits of master, one real conflict in src/graphql.rs: master added
introspection_enabled and is_schema_introspection_enabled next to
graphql_column_field_name, while this branch had widened that method to pub.
Kept both, since builder.rs resolves onConflict updateColumns names through it.

cargo fmt reflowed three spots in builder.rs and transpile.rs where master's
changes met ours.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@matt-metivier

Copy link
Copy Markdown
Author

Closing. This has been open since January with no reviewer, and it no longer builds against master. If someone wants to review it I'll rebase and reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upsert support

1 participant