Skip to content

feat: add conflict handling on create/Many/AndReturn (Upsert) and add support for composite PKs - #45

Merged
VoidClancy merged 1 commit into
masterfrom
codegen
Jul 16, 2026
Merged

feat: add conflict handling on create/Many/AndReturn (Upsert) and add support for composite PKs#45
VoidClancy merged 1 commit into
masterfrom
codegen

Conversation

@VoidClancy

Copy link
Copy Markdown
Owner
  1. model_create.gotpl:
  • Define OnConflict() on the create/Many/AndReturnBuilder that returns a model specific ConflictBuilder
  • Replace the single idCol with a pkCols []string, either generated from a scalar field marked as IsID or a composite PK (fixes the bug in categoryToPost id="" resulting in WHERE "" = ?)

2- relations_runtime.gotpl:

  • change the signature of buildBulkInsertSQL to accept pkCols, conflict Tagret/Action

3- model_predicate.gotpl:

  • Generate package-level instances of CompositeUniqueConstraint for all model compound indexes/unique constraints, and defined aliases for package Upsert and ConflictBuilder
  • Add helper for compound primary key, simmilar to compound unique constraint functionality-wise, but to differentiate between compound unique

4- client.gotpl:

  • Modify the Dialect interface to receive conflict targets and custom updates in ConflictClause and remove InsertPrefix, to support SQL-compliant ON CONFLICT clause generation for all dialects, replacing the older dialect-specific prefixes, without having to duplicate much
  • Implement UniqueColumns() (from UniqueConstraintTarget inteface) on UniqueField and StringUniqueField to allow standard unique fields generated on delegates to act directly as UniqueConstraintTarget params in the OnConflict() builder

5- builders_create.gotpl:

  • Replace the bool skipDuplicates func with conflictTarget to allow create builders to support generic conflict actions (ignore, UpdateNewValues and custom update func)
  • replace row.Scan in execute insert with a buffered query stream (next, scan, close) to prevent connection leaks and ensure rows are properly closed as it was erroring on conflict without properly returning nil for records but retruning sql.ErrNoRows
  • Update the fallback SQL generation to check all primary key columns to support dialects that don't have RETURNING when fetching with composite PKs

6- runtime.gotpl:

  • Implement computeNonConflictCols to determine non-identifying cols that should be automatically set when UpdateNewValues() is called avoiding updating the PK and the conflicting cols
  • Add buildConflictClause() to generate dialect-specific ON CONFLICT CLAUSE

(basically define a common interface to retrieve col names on conflict, have unique fields and constraints implement it, so it's easy to use in the OnConflict func, define OnConflict itself on create builders, define Ignore(), UpdateNewValues() and custom Update()m handle the conflict logic in sql insertion, fix ID to slice instead of scalar resolving to scalar in case of scalar BUT, supporting composite ids now)

… support for composite primary keys

1. model_create.gotpl:
 - Define OnConflict() on the create/Many/AndReturnBuilder that returns a model specific ConflictBuilder
 - Replace the single idCol with a pkCols []string, either generated from a scalar field marked as IsID or a composite PK (fixes the bug in categoryToPost id="" resulting in WHERE "" = ?)

2- relations_runtime.gotpl:
 - change the signature of buildBulkInsertSQL to accept pkCols, conflict Tagret/Action

3- model_predicate.gotpl:
 - Generate package-level instances of CompositeUniqueConstraint for all model compound indexes/unique constraints, and defined aliases for package Upsert and ConflictBuilder
  - Add helper for compound primary key, simmilar to compound unique constraint functionality-wise, but to differentiate between compound unique

4- client.gotpl:
 -  Modify the Dialect interface to receive conflict targets and custom updates in ConflictClause and remove InsertPrefix, to support SQL-compliant ON CONFLICT clause generation for all dialects, replacing the older dialect-specific prefixes, without having to duplicate much
 - Implement UniqueColumns() (from UniqueConstraintTarget inteface) on UniqueField and StringUniqueField to allow standard unique fields generated on delegates to act directly as UniqueConstraintTarget params in the OnConflict() builder

5- builders_create.gotpl:
 - Replace the bool skipDuplicates func with conflictTarget to allow create builders to support generic conflict actions (ignore, UpdateNewValues and custom update func)
 - replace row.Scan in execute insert with a buffered query stream (next, scan, close) to prevent connection leaks and ensure rows are properly closed as it was erroring on conflict without properly returning nil for records but retruning sql.ErrNoRows
 - Update the fallback SQL generation to check all primary key columns to support dialects that don't have RETURNING when fetching with composite PKs

6- runtime.gotpl:
 - Implement computeNonConflictCols  to determine non-identifying cols that should be automatically set when UpdateNewValues() is called avoiding updating the PK and the conflicting cols
 - Add buildConflictClause() to generate dialect-specific ON CONFLICT CLAUSE

(define a common interface to retrieve col names on conflict, have unique fields and constraints implement it, so it's easy to use in the OnConflict func, define OnConflict itself on create builders, define Ignore(), UpdateNewValues() and custom Update()m handle the conflict logic in sql insertion, fix ID to slice instead of scalar resolving to scalar in case of scalar BUT, supporting composite ids now)
@VoidClancy VoidClancy self-assigned this Jul 16, 2026
@VoidClancy
VoidClancy merged commit 3bd5db4 into master Jul 16, 2026
5 checks passed
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.

1 participant