-
-
Notifications
You must be signed in to change notification settings - Fork 46
Fix #1142: upsert to use first matching unique constraint #1144
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
base: master
Are you sure you want to change the base?
Fix #1142: upsert to use first matching unique constraint #1144
Conversation
e3af930 to
45fcfa9
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1144 +/- ##
=============================================
- Coverage 98.79% 66.55% -32.24%
- Complexity 1654 1655 +1
=============================================
Files 120 120
Lines 4301 4273 -28
=============================================
- Hits 4249 2844 -1405
- Misses 52 1429 +1377 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Looks this will not work correct for some cases. Better to generate expression for each unique index Instead of |
I checked the PostgreeSQL docs and unfortunately, multiple ON CONFLICT clauses are not allowed in a single INSERT statement The syntax only allows ONE ON CONFLICT clause per INSERT |
Seems this works for SQLite but not for PostgreSQL. Then we should add an extra parameter to the |
dad38d5 to
13c13c3
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.
Pull request overview
This PR fixes a bug where tables with multiple separate unique constraints would generate invalid SQL by merging all unique column names into a single ON CONFLICT clause. The fix changes getTableUniqueColumnNames() to return columns from only the first matching constraint instead of merging all constraints.
Key Changes:
- Modified
getTableUniqueColumnNames()to return the first matching unique constraint instead of merging all matching constraints - Added optional
$constraintColumnsparameter toupsert(),upsertReturning(), andupsertReturningPks()methods to allow explicit constraint specification - Removed unused imports (
array_filter,array_merge,array_unique) that were only needed for the old merging logic
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/QueryBuilder/DMLQueryBuilderInterface.php |
Added $constraintColumns parameter to interface method signatures with documentation |
src/QueryBuilder/AbstractQueryBuilder.php |
Updated wrapper methods to pass through the new $constraintColumns parameter |
src/QueryBuilder/AbstractDMLQueryBuilder.php |
Core logic changes: simplified getTableUniqueColumnNames() to return first match only, added support for explicit constraint columns, removed unused imports |
src/Debug/CommandInterfaceProxy.php |
Added $constraintColumns parameter to proxy methods |
src/Command/CommandInterface.php |
Added $constraintColumns parameter to command interface method signatures with documentation |
src/Command/AbstractCommand.php |
Updated command methods to accept and pass through the new $constraintColumns parameter |
CHANGELOG.md |
Documented the change and bug fix |
Comments suppressed due to low confidence (1)
src/QueryBuilder/AbstractDMLQueryBuilder.php:483
- The PHPDoc is missing @param documentation for parameters
$table,$insertColumns, and$updateColumns. Only$constraintsand$constraintColumnsare documented. For consistency and completeness, all parameters should be documented.
/**
* Prepare column names and constraints for "upsert" operation.
*
* @param Index[] $constraints
* @param string[]|null $constraintColumns The column names to use for the conflict clause. If `null`,
* the primary key or the first matching unique constraint will be used.
*
* @psalm-param array<string, mixed>|QueryInterface $insertColumns
*
* @return array Array of unique, insert and update column names.
* @psalm-return array{0: string[], 1: string[], 2: string[]|null}
*/
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Tigrov
left a comment
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.
Dependent packages also need to be fixed (see test results)
| * @return string[] The column names. | ||
| * @return string[] The column names of the first matching constraint. | ||
| */ | ||
| private function getTableUniqueColumnNames(string $name, array $columns, array &$indexes = []): array |
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.
| private function getTableUniqueColumnNames(string $name, array $columns, array &$indexes = []): array | |
| private function getTableUniqueColumnNames(string $name, array $columns, ?Index &$index = null): array |
array can be changed to ?Index with corresponding fixes of code
|
These changes break BC. So I suggest split this PR on two:
And one more idea... Configure globally default upsert constraint columns in connection. This is doesn't break BC and this will be enough in most cases. |
This probably doesn't solve the problem; see the issue #1142. This solution will select
This may also break BC if configure them via an additional method or parameter. |
If we implement this via new optional parameter, it doesn't break BC. Also it may solve issue #1142. |
|
you're right, adding params to interface methods does break BC for custom implementations. How if I split this into two PRs:
|
Bugfix needs to be made. New feature requires a discussion. Parameter adding is OK, but maybe it's worth to add global per table defaults for constraint in upsert. |
|
Separate PR with bugfix only - OK
I think it's better to add an additional parameter to the method that breaks BC (as it done in the PR) and wait for the next major update. |
When a table has multiple separate unique constraints (e.g., primary key on
idand unique index onslug), theupsertmethod incorrectly merged all unique column names, generating invalid SQL like:This failed because there's no composite unique constraint on
(id, slug).The fix: Changed
getTableUniqueColumnNames()to return columns from only the first matching constraint, instead of merging columns from all constraints.