Skip to content

Conversation

@dereuromark
Copy link
Member

With the last PRs being merged in we can soon prepare the release.

markstory and others added 30 commits August 3, 2025 00:20
Remove the commands that wrap the phinx commands. This has resulted
in more code being removed as well.

I also uncovered a bug in `BaseSeed` where it would fail to invoke
seeds that were in a non-default `source`.
I'm trying to keep the diff small but stan builds are finding all the
runtime links to deleted code.
* Remove commands that are entry points to phinx

Remove the commands that wrap the phinx commands. This has resulted
in more code being removed as well.

I also uncovered a bug in `BaseSeed` where it would fail to invoke
seeds that were in a non-default `source`.

* Remove more code that supported phinx.

* Remove commented out code

* Fix phpcs and stan builds

* More fixes

* Fix postgres tests.

* Comment out code that will be deleted soon.

I'm trying to keep the diff small but stan builds are finding all the
runtime links to deleted code.

* Appease typing gods

* Fix phpcs

* Make pattern work across more php versions
* Refactor to fully remove phinx dependency.

* Fix tests.

* Fix tests.

* Fix URL.

* Fix tests

* Fix more tests.

* Fix phpcs

* Fix constraint action generation

---------

Co-authored-by: Mark Story <mark@mark-story.com>
* Remove now unused code from imported phinx code

Slim down `ConfigInterface` to only be what we are using.

* Fix phpcs

* Remove a backend condition in a template
* Fix risky tests

* 5.x Remove adapter getPhinxType

This was a method inherited from phinx and maintained for backwards
compatibility.

* Update baseline file
Remove getSqlType(). This method is now unused and has been replaced by
cakephp/database features.
Remove getSqlType(). This method is now unused and has been replaced by
cakephp/database features.
More follow up on the column type cleanup.
5.x - Remove some attributes that are no longer used
* Remove usage of deprecated constants. 
   Remove usage of column type constants that are no longer supported.
* Fix mysql tests
* Update baseline file
* Fix phpcs
Use the dev branch as 5.3 release hasn't started yet, but I'd like to
validate the new reflection API by integrating it into migrations.

* Remove remaining references to symfony classes.
* Fix failing tests.
* Remove unused cake_version block and update php version
  cakephp 5.3 requires 8.2
* Update deps to align with cakephp version
* Don't ignore php versions
* Fix expected SQL
* Fix regression with postgres schema generation
* Fix deprecation warnings from plugin classes
* Restore jsonb column constant and update windows php version
* Fix failing identity column tests
  cakephp/database does not support `identity => true, generated => null`
  as a way to remove identity clauses on columns, as `generated => null`
  is the default value which for identity columns ~= 'by default'.
  Fix and re-enable the identity column tests as cakephp 5.3 will have
  identity column support.
* Remove more phinx references
* Fix tests
* Correct constant value.
* Fix phpcs
Use all the new methods that were added to simplify migrations.

* Get postgres adapter tests passing
* Update tests for mysql adapter

- column names are case-sensitive.
- ordering matters.

* Move hasColumn() up to AbstractAdapter
* Update sqlite has methods

- columns are case-sensitive
- order matters

* Partially update sqlserver adapter tests

- order and casing matter now.

* Clean up some TODOs

* Fix type error in stubfile
* Fix tests

- Column names are case-sensitive
- Required fixes in cakephp/database to implement included columns
* Add support for timestampfractional type. This type should
   have support in migrations now that we are on
   cakephp/database.
* Address a few TODOs
* sqlserver now uses datetimefractional by default for columns 
   generated by cakephp, datetime and timestamp columns use
   fractional versions.
* Fix more sqlserver tests
* Fix mistake
* Remove brittle mock test. getVersionLog() is called in enough places that we 
   can rely on integration tests from the rest of the library.
* Replace string queries with querybuilder. This removes a bunch of potential sql 
   injection as we weren't safely
   escaping parameters before.
* Cleanup
Having both `Migrations\Db\Table` and `Migrations\Db\Table\Table` can
make reading migrations code confusing to read. Renaming one of the
classes to TableMetadata avoids confusion.
dereuromark and others added 16 commits November 23, 2025 00:31
# Conflicts:
#	src/Command/BakeMigrationCommand.php
#	templates/bake/config/skeleton.twig
#	tests/TestCase/Command/BakeMigrationCommandTest.php
* Fix deprecations and postgres CI

- Rename Plugin classes to {PluginName}Plugin convention
- Fix bootstrap.php to use correct plugin classes
- Add missing cakephp_comparisons database for postgres CI
- Add DB_URL_COMPARE for postgres tests

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix deprecations and pgsql comparison file

- Rename Plugin classes to {PluginName}Plugin convention
- Fix bootstrap.php to use correct plugin classes
- Update timestamp columns to timestampfractional in pgsql comparison

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix sqlserver comparison file timestamp types

Update remaining timestamp columns to datetimefractional for sqlserver.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Adds support for specifying default column values in the bake migration
command using the syntax: `column:type:default[value]`

Examples:
- `active:boolean:default[true]`
- `count:integer:default[0]`
- `status:string:default['pending']`

Supports booleans, integers, floats, strings (quoted), null, and SQL
expressions like CURRENT_TIMESTAMP.

* Fix empty string handling in parseDefaultValue

Return null when default value is an empty string (no default specified)
instead of returning the empty string itself.

* Fix PHPStan type errors in ColumnParser

- Fix return type annotation for getTypeAndLength() using tuple syntax
- Convert string lengths to integers for proper type safety
- Add null coalescing operator for columnType parameter
* Add tests for integer type conversion in getTypeAndLength

Verify that lengths are returned as integers (not strings) and that
precision/scale arrays contain integers for proper type safety.

* Fix CS.
* Add documentation for default value syntax

- Update column pattern to include default[value]
- Document supported value types (boolean, int, float, string, null, SQL)
- Add practical examples showing default values in action
- Show how to combine defaults with other options
…IMESTAMP (#963)

Add DEFAULT support for CURRENT_DATE, CURRENT_TIME, LOCALTIME, LOCALTIMESTAMP

Expand automatic SQL function handling in getDefaultValueDefinition() to
support more standard SQL datetime functions without requiring Literal::from():

- CURRENT_DATE for date columns
- CURRENT_TIME for time columns
- LOCALTIME for time columns
- LOCALTIMESTAMP for datetime/timestamp columns

Each function is only unquoted when used with appropriate column types.
Using them with incompatible types (e.g., CURRENT_DATE on a string column)
will quote the value as a literal string.
* Add unified cake_migrations table support with BC autodetect

This change introduces a consolidated migration tracking approach for v5.0:

**New Features:**
- `cake_migrations` table: Single table with `plugin` column to track all migrations
- `UnifiedMigrationsTableStorage`: New storage class for unified table operations
- `migrations upgrade` command: Migrates data from legacy phinxlog tables

**Backward Compatibility:**
- Autodetect mode (default): If any `phinxlog` or `*_phinxlog` table exists,
  legacy mode is used automatically - no breaking changes on upgrade
- Fresh installations automatically use the new `cake_migrations` table

**Configuration:**
- `Migrations.legacyTables = null` (default): Autodetect
- `Migrations.legacyTables = false`: Force unified table
- `Migrations.legacyTables = true`: Force legacy phinxlog tables

**Upgrade workflow:**
1. Upgrade to v5.0 (existing apps continue working with phinxlog)
2. Run `bin/cake migrations upgrade` to migrate data
3. Set `Migrations.legacyTables = false` in config
4. Application now uses unified `cake_migrations` table

Refs #822

- Address PR feedback for unified migrations table
- Simplify NULL handling using 'plugin IS' => $this->plugin pattern
- Remove cache complexity from UtilTrait
- Replace empty() with explicit === [] check
- Simplify upgradeTable() to no-op for new table format
- Use in_array for phinxlog detection (simpler than loop)
- Use hasTable() for phinxlog detection. Uses the new hasTable() method from
  CakePHP 5.3 as suggested in the PR feedback.
- Add CI matrix, tests, docs for unified migrations table
- Add LEGACY_TABLES CI matrix option to test both modes
- Use schemaDialect()->hasTable() for phinxlog detection
- Add documentation for unified table upgrade process
- Add basic test for UnifiedMigrationsTableStorage
- Update bootstrap to read LEGACY_TABLES from environment
- Remove development notes
- Hide upgrade command when legacyTables is false. When
  `Migrations.legacyTables` is set to `false`, the upgrade command is not
  needed since the user has already opted into the unified table. Only show it
  when in autodetect mode (null) or legacy mode (true).
- Remove LEGACY_TABLES CI matrix, partial test fixes. The unified table feature
  works, but tests have extensive hardcoded phinxlog assumptions (99 failures).
  Removing CI matrix for now.
- Partial fixes to BakeMigrationDiffCommandTest to show the pattern:
- Add UtilTrait to get correct schema table name
- Update table cleanup to include both table types
- Update queries to use dynamic table name
- Update tests to support unified migrations table mode
- Add helper methods to TestCase for migration table operations:
  - getMigrationsTableName() - gets correct table name based on mode
  - clearMigrationRecords() - clears records with plugin filtering
  - getMigrationRecordCount() - counts records with plugin filtering
  - insertMigrationRecord() - inserts with correct structure
  - isUsingUnifiedTable() - checks current mode

- Update command tests to use new helper methods:
  - MigrateCommandTest
  - RollbackCommandTest
  - StatusCommandTest
  - MarkMigratedTest
  - DumpCommandTest
  - BakeMigrationDiffCommandTest

- Add cleanup for both phinxlog and cake_migrations tables
- Re-add LEGACY_TABLES=false CI matrix option
- Fix test suite for LEGACY_TABLES=false CI build
- Update Util::tableName() to return cake_migrations when unified table mode is enabled
- Update Manager::cleanupMissingMigrations() to use correct table name and filter by plugin
- Skip cake_migrations table in bake snapshot/diff commands (like phinxlog tables)
- Update TableFinder to skip cake_migrations table
- Update Migrator to not drop cake_migrations during table cleanup
- Update tests to use helper methods for migration record operations
- Add mode-aware assertions in adapter tests
- Skip some Migrator tests in unified mode that test legacy-specific behavior
- Feedback and fixes. I thought the conditional logic in Manager, and
  unwrapping decorators pointed to a missing abstraction method. Since we're in
  a major anyways, I could extend the interface and have better layering as
  well.
- Add more tests.
- Fix diff baking tests to delete migration file after running migrate. The
  checkSync() method compares the last migration file version against the last
  migrated version. After the test deletes the migration record from the
  phinxlog table, the migration file still exists, causing checkSync() to fail
  because it sees an unmigrated file.

  The fix deletes the migration file after running migrate and before baking
  the diff, so checkSync() passes correctly.
- Remove file.
- Auto create folder. ensures a more stable setup.

---------

Co-authored-by: Mark Story <mark@mark-story.com>
Display which migration tracking table is being used (cake_migrations
or phinxlog) in the status command output. This helps users understand
which table format they are using during upgrades.

Also updates help text to use generic 'migration tracking table'
instead of 'phinxlog' since the table name varies based on configuration.
The console help output format changed from "Available Commands" to
category-based grouping like "migrations:". Updated test assertion
to match the new format.
…982)

When a table was created via the API (e.g. $this->table()->create()) and
then dropped via execute() (raw SQL), hasTable() would incorrectly return
true because it checked an internal cache before querying the database.

This fix limits the cache usage to dry-run mode only, where it's necessary
to track what tables "would" exist. In normal mode, hasTable() now always
queries the database to ensure accurate results.

Also fixes SqlserverAdapter to pass the table name without schema prefix
to the dialect, which was a latent bug hidden by the cache.
This adds support for PARTITION BY (RANGE, LIST, HASH, KEY) clauses
when creating tables and managing partitions on existing tables.

Features:
- RANGE, RANGE COLUMNS, LIST, LIST COLUMNS, HASH, KEY partitioning
- Composite partition keys
- Add/drop partitions on existing tables
- PostgreSQL declarative partitioning with auto-generated table names
- Expression-based partitioning via Literal class

New classes:
- Partition: Value object for partition configuration
- PartitionDefinition: Value object for individual partition definitions
- AddPartition: Action for adding partitions to existing tables
- DropPartition: Action for dropping partitions

New Table methods:
- partitionBy(): Define partitioning on new tables
- addPartition(): Add partition definitions when creating tables
- addPartitionToExisting(): Add partition to existing partitioned tables
- dropPartition(): Remove partition from existing tables


* Fix PHPStan and PHPCS errors in partition implementation

- Remove redundant is_array() check in MysqlAdapter (is_scalar already excludes arrays)
- Remove redundant ?? operator in PostgresAdapter (from key always exists)
- Remove : static return type from Partition::addDefinition() per CakePHP coding standards
Implements upsert functionality that inserts new rows and updates existing
rows on duplicate key conflicts.

Database support:
- MySQL: ON DUPLICATE KEY UPDATE
- PostgreSQL: ON CONFLICT (...) DO UPDATE SET
- SQLite: ON CONFLICT (...) DO UPDATE SET

Usage:
$table->insertOrUpdate($data, $updateColumns, $conflictColumns);
$this->insertOrUpdate($tableName, $data, $updateColumns, $conflictColumns);

Refs #950

* Remove redundant comment

---------

Co-authored-by: Mark Story <mark@mark-story.com>
* Strip 'Seed' suffix from seed names in all command output

Makes seed name display consistent across all commands by removing the
'Seed' suffix. The run command confirmation was already doing this, but
status, reset, and execution output still showed the full class name.

* Add ' seed' suffix to display names for clarity

Changes output from "Users" to "Users seed" to make it clearer
that seeds are being displayed, not other entities.

* Refactor seed display name logic to utility method

Move the seed name suffix stripping logic to Util::getSeedDisplayName()
to avoid code duplication across SeedCommand, SeedResetCommand,
SeedStatusCommand, and Manager.
* Make unsigned the default for int columns.

* Opt-in for unsigned column defaults

Use tearDown() to restore Configure defaults instead of running
tests in separate processes. This improves test performance.

* Fix MigrationHelperTest failing when run with adapter tests

The adapter tests (MysqlAdapterTest, etc.) drop and recreate the database
in their setUp method, which destroys the schema tables created by
SchemaLoader. MigrationHelperTest then fails because the users and
special_tags tables no longer exist.

Use #[RunTestsInSeparateProcesses] to ensure MigrationHelperTest runs
in isolation with its own fresh schema.
* Fix multiple partition SQL syntax for MySQL

When adding multiple partitions to an existing table, MySQL requires:
ALTER TABLE foo ADD PARTITION (PARTITION p1 ..., PARTITION p2 ...)

Previously, each AddPartition action generated its own ADD PARTITION clause,
which when joined with commas resulted in invalid SQL:
ALTER TABLE foo ADD PARTITION (...), ADD PARTITION (...)

This fix:
- Batches AddPartition actions together in executeActions()
- Adds new getAddPartitionsInstructions() method to AbstractAdapter with
  a default implementation that calls the single partition method
- Overrides getAddPartitionsInstructions() in MysqlAdapter to generate
  correct batched SQL: ADD PARTITION (PARTITION p1, PARTITION p2)
- Similarly batches DropPartition actions for efficiency
- Adds gatherPartitions() to Plan.php to properly gather partition actions
- Includes extensive tests for single/multiple partition add/drop scenarios

Refs #986

* Fix coding standard - use single quotes

* Trigger CI re-run

* Add test for combined partition and column operations

* Add SetPartitioning action for partitionBy() + update()

Enables adding partitioning to existing non-partitioned tables using:

    $table->partitionBy(Partition::TYPE_RANGE_COLUMNS, 'created')
        ->addPartition('p2023', '2024-01-01')
        ->update();

Previously this generated no SQL. Now it properly generates:

    ALTER TABLE `table` PARTITION BY RANGE COLUMNS (created) (...)

Changes:
- Add SetPartitioning action class
- Update Plan to handle SetPartitioning in gatherPartitions()
- Add getSetPartitioningInstructions() to AbstractAdapter/MysqlAdapter
- Create SetPartitioning action in Table::executeActions() when updating

* Add test for composite partition keys

* Each adapter now only needs to implement the collection methods

* Remove unused import

---------

Co-authored-by: mscherer <dereuromark@web.de>
Co-authored-by: Jamison Bryant <jbryant@ticketsauce.com>
dereuromark and others added 5 commits January 11, 2026 08:58
- Remove redundant Exception catch when Throwable already covers it
- Use consistent error output formatting with <error> tags
- Add verbose trace output to SeedCommand for consistency
- Remove unused Exception imports
- Add --fake flag to mark seeds as executed without running them
- Add --seed option to seeds reset for selective seed reset
- Both features mirror similar functionality in migrations

* Show clear message when faking idempotent seeds

Idempotent seeds are not tracked, so faking them doesn't make sense.
Instead of showing misleading "faking"/"faked" messages, now shows
"skipped (idempotent)" to clarify what's happening.
* Remove phinx backend test from 5.x

The phinx backend was removed in 5.x, so the test for
MigrationsRollbackCommand is not applicable. This test was
incorrectly merged from 4.x where phinx backend still exists.

* Update PostgreSQL timestamp comparison file for 5.x

- Update documentation URL from phinx to migrations/5
- Update timestamp type to timestampfractional for columns with precision/scale
- Add insertOrUpdate() and insertOrSkip() documentation to seeding guide
- Document MySQL ALTER TABLE ALGORITHM/LOCK options
- Fix grammar issue in index.rst ("can has" -> "has")
- Update phinxlog references to generic "migrations tracking table"
Resolve conflicts:
- EntryCommandTest: Use minimal assertions without backend-specific text
- PostgresAdapterTest: Use flexible assertions for identity column syntax
- PendingMigrationsMiddlewareTest: Use assertInstanceOf for proper type checking
dereuromark and others added 4 commits January 12, 2026 23:40
- Fix README coverage badge pointing to 3.x instead of 5.x
- Update MigrationHelper comments (remove outdated phinx TODOs)
- Add database-specific limitations documentation
- Fix PHPStan issues by adding proper type hints for Bake event subjects
- Update PHPStan baseline to remove fixed errors
* Improve insertOrUpdate() API consistency across database adapters

- 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

* Fix use statement ordering in PostgresAdapterTest

* Change MySQL conflictColumns deprecationWarning to trigger_error

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.

* Add documentation for insertOrSkip and insertOrUpdate methods

Documents the insert modes with database-specific behavior caveats,
particularly the MySQL vs PostgreSQL/SQLite differences for upsert.
Accepted the 5.x branch's documentation for insertOrUpdate() and insertOrSkip()
which has the correct three-argument API signature.
Docs: Improve documentation for 5.x release
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants