From 6b8f60dd180538c36fa43402d91c5038990a75ab Mon Sep 17 00:00:00 2001 From: mscherer Date: Thu, 12 Mar 2026 10:59:21 +0100 Subject: [PATCH] Fix LONGTEXT columns becoming TEXT in generated migrations The issue was a mismatch between CakePHP's LENGTH_LONG constant (4294967295) and migrations' TEXT_LONG constant (2147483647). When using `bake migration_diff`, CakePHP's schema reflection returns LENGTH_LONG for LONGTEXT columns, but MysqlAdapter expected TEXT_LONG. This fix: 1. MigrationHelper: Convert LENGTH_LONG to TEXT_LONG when generating migrations 2. MysqlAdapter: Accept both constants for backward compatibility with existing migrations that have the wrong value Fixes #1029 --- src/Db/Adapter/MysqlAdapter.php | 4 +- src/View/Helper/MigrationHelper.php | 9 +++++ .../TestCase/Db/Adapter/MysqlAdapterTest.php | 4 ++ .../View/Helper/MigrationHelperTest.php | 38 +++++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/Db/Adapter/MysqlAdapter.php b/src/Db/Adapter/MysqlAdapter.php index 694f821b..dabf3a95 100644 --- a/src/Db/Adapter/MysqlAdapter.php +++ b/src/Db/Adapter/MysqlAdapter.php @@ -374,8 +374,10 @@ public function createTable(TableMetadata $table, array $columns = [], array $in protected function mapColumnData(array $data): array { if ($data['type'] == self::TYPE_TEXT && $data['length'] !== null) { + // Accept both migrations TEXT_LONG and CakePHP LENGTH_LONG for backward compatibility + // with migrations generated before the fix (LENGTH_TINY/MEDIUM are already equal to TEXT_TINY/MEDIUM) $data['length'] = match ($data['length']) { - self::TEXT_LONG => TableSchema::LENGTH_LONG, + self::TEXT_LONG, TableSchema::LENGTH_LONG => TableSchema::LENGTH_LONG, self::TEXT_MEDIUM => TableSchema::LENGTH_MEDIUM, self::TEXT_REGULAR => null, self::TEXT_TINY => TableSchema::LENGTH_TINY, diff --git a/src/View/Helper/MigrationHelper.php b/src/View/Helper/MigrationHelper.php index b0014f7c..9aec4dae 100644 --- a/src/View/Helper/MigrationHelper.php +++ b/src/View/Helper/MigrationHelper.php @@ -18,11 +18,13 @@ use Cake\Database\Connection; use Cake\Database\Driver\Mysql; use Cake\Database\Schema\CollectionInterface; +use Cake\Database\Schema\TableSchema; use Cake\Database\Schema\TableSchemaInterface; use Cake\Utility\Hash; use Cake\Utility\Inflector; use Cake\View\Helper; use Cake\View\View; +use Migrations\Db\Adapter\MysqlAdapter; use Migrations\Db\Table\ForeignKey; /** @@ -445,6 +447,13 @@ public function getColumnOption(array $options): array } } + // Convert CakePHP's LENGTH_LONG to migrations TEXT_LONG for text columns + // CakePHP uses LENGTH_LONG = 4294967295, but migrations expects TEXT_LONG = 2147483647 + // (LENGTH_TINY and LENGTH_MEDIUM have the same values as TEXT_TINY and TEXT_MEDIUM) + if (isset($columnOptions['limit']) && $columnOptions['limit'] === TableSchema::LENGTH_LONG) { + $columnOptions['limit'] = MysqlAdapter::TEXT_LONG; + } + return $columnOptions; } diff --git a/tests/TestCase/Db/Adapter/MysqlAdapterTest.php b/tests/TestCase/Db/Adapter/MysqlAdapterTest.php index 1ab36b5c..94202d83 100644 --- a/tests/TestCase/Db/Adapter/MysqlAdapterTest.php +++ b/tests/TestCase/Db/Adapter/MysqlAdapterTest.php @@ -9,6 +9,7 @@ use Cake\Core\Configure; use Cake\Database\Connection; use Cake\Database\Driver\Mysql; +use Cake\Database\Schema\TableSchema; use Cake\Datasource\ConnectionManager; use InvalidArgumentException; use Migrations\Db\Adapter\MysqlAdapter; @@ -1377,6 +1378,9 @@ public static function textRoundTripData() ['text', MysqlAdapter::TEXT_TINY, 'text', MysqlAdapter::TEXT_TINY], ['text', MysqlAdapter::TEXT_MEDIUM, 'text', MysqlAdapter::TEXT_MEDIUM], ['text', MysqlAdapter::TEXT_LONG, 'text', MysqlAdapter::TEXT_LONG], + // Test backward compatibility: CakePHP's LENGTH_LONG (4294967295) should also work + // This ensures migrations generated before the fix still create LONGTEXT correctly + ['text', TableSchema::LENGTH_LONG, 'text', MysqlAdapter::TEXT_LONG], ]; } diff --git a/tests/TestCase/View/Helper/MigrationHelperTest.php b/tests/TestCase/View/Helper/MigrationHelperTest.php index fd2dfe91..0f64e4dd 100644 --- a/tests/TestCase/View/Helper/MigrationHelperTest.php +++ b/tests/TestCase/View/Helper/MigrationHelperTest.php @@ -16,9 +16,11 @@ use Cake\Database\Driver\Mysql; use Cake\Database\Driver\Sqlserver; use Cake\Database\Schema\Collection; +use Cake\Database\Schema\TableSchema; use Cake\Datasource\ConnectionManager; use Cake\TestSuite\TestCase; use Cake\View\View; +use Migrations\Db\Adapter\MysqlAdapter; use Migrations\View\Helper\MigrationHelper; use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses; @@ -490,4 +492,40 @@ public function testGetColumnOptionExcludesFixedWhenNotSet(): void $this->assertArrayNotHasKey('fixed', $result); } + + /** + * Test that getColumnOption converts CakePHP's LENGTH_LONG to migrations TEXT_LONG + * + * CakePHP uses LENGTH_LONG = 4294967295 for LONGTEXT, but migrations expects + * TEXT_LONG = 2147483647. This ensures generated migrations use the correct value. + */ + public function testGetColumnOptionConvertsLengthLongToTextLong(): void + { + $options = [ + 'limit' => TableSchema::LENGTH_LONG, // 4294967295 + 'null' => true, + 'default' => null, + ]; + + $result = $this->helper->getColumnOption($options); + + $this->assertArrayHasKey('limit', $result); + $this->assertSame(MysqlAdapter::TEXT_LONG, $result['limit']); // 2147483647 + } + + /** + * Test that getColumnOption preserves other limit values unchanged + */ + public function testGetColumnOptionPreservesOtherLimits(): void + { + $options = [ + 'limit' => 255, // TEXT_TINY / LENGTH_TINY - same value + 'null' => true, + 'default' => null, + ]; + + $result = $this->helper->getColumnOption($options); + + $this->assertSame(255, $result['limit']); + } }