Skip to content

Commit c8cfb93

Browse files
authored
Fix LONGTEXT columns becoming TEXT in generated migrations (#1050)
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
1 parent 6f57c07 commit c8cfb93

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

src/Db/Adapter/MysqlAdapter.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,10 @@ public function createTable(TableMetadata $table, array $columns = [], array $in
374374
protected function mapColumnData(array $data): array
375375
{
376376
if ($data['type'] == self::TYPE_TEXT && $data['length'] !== null) {
377+
// Accept both migrations TEXT_LONG and CakePHP LENGTH_LONG for backward compatibility
378+
// with migrations generated before the fix (LENGTH_TINY/MEDIUM are already equal to TEXT_TINY/MEDIUM)
377379
$data['length'] = match ($data['length']) {
378-
self::TEXT_LONG => TableSchema::LENGTH_LONG,
380+
self::TEXT_LONG, TableSchema::LENGTH_LONG => TableSchema::LENGTH_LONG,
379381
self::TEXT_MEDIUM => TableSchema::LENGTH_MEDIUM,
380382
self::TEXT_REGULAR => null,
381383
self::TEXT_TINY => TableSchema::LENGTH_TINY,

src/View/Helper/MigrationHelper.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
use Cake\Database\Connection;
1919
use Cake\Database\Driver\Mysql;
2020
use Cake\Database\Schema\CollectionInterface;
21+
use Cake\Database\Schema\TableSchema;
2122
use Cake\Database\Schema\TableSchemaInterface;
2223
use Cake\Utility\Hash;
2324
use Cake\Utility\Inflector;
2425
use Cake\View\Helper;
2526
use Cake\View\View;
27+
use Migrations\Db\Adapter\MysqlAdapter;
2628
use Migrations\Db\Table\ForeignKey;
2729

2830
/**
@@ -445,6 +447,13 @@ public function getColumnOption(array $options): array
445447
}
446448
}
447449

450+
// Convert CakePHP's LENGTH_LONG to migrations TEXT_LONG for text columns
451+
// CakePHP uses LENGTH_LONG = 4294967295, but migrations expects TEXT_LONG = 2147483647
452+
// (LENGTH_TINY and LENGTH_MEDIUM have the same values as TEXT_TINY and TEXT_MEDIUM)
453+
if (isset($columnOptions['limit']) && $columnOptions['limit'] === TableSchema::LENGTH_LONG) {
454+
$columnOptions['limit'] = MysqlAdapter::TEXT_LONG;
455+
}
456+
448457
return $columnOptions;
449458
}
450459

tests/TestCase/Db/Adapter/MysqlAdapterTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Cake\Core\Configure;
1010
use Cake\Database\Connection;
1111
use Cake\Database\Driver\Mysql;
12+
use Cake\Database\Schema\TableSchema;
1213
use Cake\Datasource\ConnectionManager;
1314
use InvalidArgumentException;
1415
use Migrations\Db\Adapter\MysqlAdapter;
@@ -1377,6 +1378,9 @@ public static function textRoundTripData()
13771378
['text', MysqlAdapter::TEXT_TINY, 'text', MysqlAdapter::TEXT_TINY],
13781379
['text', MysqlAdapter::TEXT_MEDIUM, 'text', MysqlAdapter::TEXT_MEDIUM],
13791380
['text', MysqlAdapter::TEXT_LONG, 'text', MysqlAdapter::TEXT_LONG],
1381+
// Test backward compatibility: CakePHP's LENGTH_LONG (4294967295) should also work
1382+
// This ensures migrations generated before the fix still create LONGTEXT correctly
1383+
['text', TableSchema::LENGTH_LONG, 'text', MysqlAdapter::TEXT_LONG],
13801384
];
13811385
}
13821386

tests/TestCase/View/Helper/MigrationHelperTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
use Cake\Database\Driver\Mysql;
1717
use Cake\Database\Driver\Sqlserver;
1818
use Cake\Database\Schema\Collection;
19+
use Cake\Database\Schema\TableSchema;
1920
use Cake\Datasource\ConnectionManager;
2021
use Cake\TestSuite\TestCase;
2122
use Cake\View\View;
23+
use Migrations\Db\Adapter\MysqlAdapter;
2224
use Migrations\View\Helper\MigrationHelper;
2325
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
2426

@@ -490,4 +492,40 @@ public function testGetColumnOptionExcludesFixedWhenNotSet(): void
490492

491493
$this->assertArrayNotHasKey('fixed', $result);
492494
}
495+
496+
/**
497+
* Test that getColumnOption converts CakePHP's LENGTH_LONG to migrations TEXT_LONG
498+
*
499+
* CakePHP uses LENGTH_LONG = 4294967295 for LONGTEXT, but migrations expects
500+
* TEXT_LONG = 2147483647. This ensures generated migrations use the correct value.
501+
*/
502+
public function testGetColumnOptionConvertsLengthLongToTextLong(): void
503+
{
504+
$options = [
505+
'limit' => TableSchema::LENGTH_LONG, // 4294967295
506+
'null' => true,
507+
'default' => null,
508+
];
509+
510+
$result = $this->helper->getColumnOption($options);
511+
512+
$this->assertArrayHasKey('limit', $result);
513+
$this->assertSame(MysqlAdapter::TEXT_LONG, $result['limit']); // 2147483647
514+
}
515+
516+
/**
517+
* Test that getColumnOption preserves other limit values unchanged
518+
*/
519+
public function testGetColumnOptionPreservesOtherLimits(): void
520+
{
521+
$options = [
522+
'limit' => 255, // TEXT_TINY / LENGTH_TINY - same value
523+
'null' => true,
524+
'default' => null,
525+
];
526+
527+
$result = $this->helper->getColumnOption($options);
528+
529+
$this->assertSame(255, $result['limit']);
530+
}
493531
}

0 commit comments

Comments
 (0)