From f5633230b55ccde46e4691ed18b8353abb6a2e9a Mon Sep 17 00:00:00 2001 From: mscherer Date: Wed, 3 Dec 2025 14:30:41 +0100 Subject: [PATCH] Remove null collate option and convert collate to collation When baking migration diffs, the collate option was included in column options even when null. This caused "collate is not a valid column option" errors when running migrations on PostgreSQL. Additionally, the collate to collation conversion was only done for MySQL and SQL Server. This caused the same error for PostgreSQL and SQLite columns with non-default collation. Fixes #974 --- src/View/Helper/MigrationHelper.php | 10 ++-- .../View/Helper/MigrationHelperTest.php | 48 +++++++++++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/View/Helper/MigrationHelper.php b/src/View/Helper/MigrationHelper.php index f61f26f26..017be4a98 100644 --- a/src/View/Helper/MigrationHelper.php +++ b/src/View/Helper/MigrationHelper.php @@ -17,7 +17,6 @@ use Cake\Core\Configure; use Cake\Database\Connection; use Cake\Database\Driver\Mysql; -use Cake\Database\Driver\Sqlserver; use Cake\Database\Schema\CollectionInterface; use Cake\Database\Schema\TableSchemaInterface; use Cake\Utility\Hash; @@ -401,18 +400,19 @@ public function getColumnOption(array $options): array if (empty($columnOptions['autoIncrement'])) { unset($columnOptions['autoIncrement']); } + if (empty($columnOptions['collate'])) { + unset($columnOptions['collate']); + } // currently only MySQL supports the signed option $driver = $connection->getDriver(); $isMysql = $driver instanceof Mysql; - $isSqlserver = $driver instanceof Sqlserver; - if (!$isMysql) { unset($columnOptions['signed']); } - if (($isMysql || $isSqlserver) && !empty($columnOptions['collate'])) { - // due to Phinx using different naming for the collation + if (!empty($columnOptions['collate'])) { + // Phinx uses 'collation' not 'collate' $columnOptions['collation'] = $columnOptions['collate']; unset($columnOptions['collate']); } diff --git a/tests/TestCase/View/Helper/MigrationHelperTest.php b/tests/TestCase/View/Helper/MigrationHelperTest.php index 79aa3554e..3dc73d92c 100644 --- a/tests/TestCase/View/Helper/MigrationHelperTest.php +++ b/tests/TestCase/View/Helper/MigrationHelperTest.php @@ -397,4 +397,52 @@ public function testStringifyList() ], ])); } + + /** + * Test that getColumnOption removes null collate for all databases + * + * @see https://github.com/cakephp/migrations/issues/974 + */ + public function testGetColumnOptionRemovesNullCollate(): void + { + $options = [ + 'length' => 255, + 'null' => true, + 'default' => null, + 'collate' => null, + ]; + + $result = $this->helper->getColumnOption($options); + + // collate => null should NOT be in the output for any database + // because it causes "collate is not a valid column option" error + $this->assertArrayNotHasKey('collate', $result, 'collate => null should be removed'); + $this->assertArrayNotHasKey('collation', $result, 'collation should not be set when collate is null'); + } + + /** + * Test that getColumnOption converts collate to collation for all databases + * + * Phinx uses 'collation' not 'collate', so this must be converted for any database + * that supports per-column collation (MySQL, SQL Server, PostgreSQL, SQLite). + * + * @see https://github.com/cakephp/migrations/issues/974 + */ + public function testGetColumnOptionConvertsCollateToCollation(): void + { + $options = [ + 'length' => 255, + 'null' => true, + 'default' => null, + 'collate' => 'en_US.UTF-8', + ]; + + $result = $this->helper->getColumnOption($options); + + // collate should be converted to collation for Phinx compatibility + // This is a bug: currently only MySQL/SQLServer convert this + $this->assertArrayNotHasKey('collate', $result, 'collate should be converted to collation'); + $this->assertArrayHasKey('collation', $result, 'collation should be set from collate value'); + $this->assertSame('en_US.UTF-8', $result['collation']); + } }