Skip to content

Conversation

@dereuromark
Copy link
Member

Summary

Addresses API consistency issues with insertOrUpdate() across different database adapters:

  • MySQL: The $conflictColumns parameter is ignored because MySQL's ON DUPLICATE KEY UPDATE automatically applies to all unique constraints. Now triggers a deprecation warning when passed.

  • PostgreSQL/SQLite: The $conflictColumns parameter is required. Now throws a RuntimeException with a clear message if missing or empty.

  • Documentation: Added comprehensive docblocks explaining the database-specific behavior in Table.php and SeedInterface.php.

Changes

  • Add deprecation warning in AbstractAdapter::getUpsertClause() when $conflictColumns is passed (MySQL)
  • Add RuntimeException in PostgresAdapter::getConflictClause() when $conflictColumns is missing
  • Add RuntimeException in SqliteAdapter::getUpsertClause() when $conflictColumns is missing
  • Update documentation for Table::insertOrUpdate() and SeedInterface::insertOrUpdate()
  • Add tests for conflict column validation in PostgreSQL and SQLite adapters

Test plan

  • Run SQLite adapter test for conflict column validation
  • Run PostgreSQL adapter test for conflict column validation
  • Run MySQL adapter tests to verify deprecation doesn't break existing functionality
  • Run phpcs and phpstan checks

@dereuromark dereuromark marked this pull request as ready for review January 11, 2026 08:15
Comment on lines 811 to 819
* - **MySQL**: Uses `ON DUPLICATE KEY UPDATE`. The `$conflictColumns` parameter is
* ignored because MySQL automatically applies the update to all unique constraint
* violations. Passing `$conflictColumns` will trigger a deprecation warning.
*
* - **PostgreSQL/SQLite**: Uses `ON CONFLICT (...) DO UPDATE SET`. The `$conflictColumns`
* parameter is required and must specify the columns that have a unique constraint.
* A RuntimeException will be thrown if this parameter is empty.
*
* - **SQL Server**: Not currently supported. Use separate insert/update logic.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also be in the docs? There are a lot of caveats to using this method.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added docs for insertOrSkip() and insertOrUpdate() in docs/en/seeding.rst with the database-specific caveats in a warning block.

@dereuromark
Copy link
Member Author

Changed deprecationWarning() to trigger_error(..., E_USER_WARNING) - you're right, deprecation doesn't make sense for a new feature.

- Add deprecation warning for MySQL when conflictColumns is passed (ignored)
- Add RuntimeException for PostgreSQL/SQLite when conflictColumns is missing
- Document database-specific behavior in Table.php and SeedInterface.php
- Add tests for PostgreSQL and SQLite conflict column validation
Since insertOrUpdate is a new feature, using deprecationWarning()
doesn't make semantic sense. Switch to trigger_error() with
E_USER_WARNING to alert developers that the parameter is ignored
on MySQL without implying the feature will be removed.
Documents the insert modes with database-specific behavior caveats,
particularly the MySQL vs PostgreSQL/SQLite differences for upsert.
@dereuromark dereuromark force-pushed the fix-insertorupdate-consistency branch from 69f50b5 to ca4a1d4 Compare January 13, 2026 02:52
@markstory markstory merged commit dee5b42 into 5.x Jan 13, 2026
14 checks passed
@markstory markstory deleted the fix-insertorupdate-consistency branch January 13, 2026 04:42
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.

3 participants