From 8f07c53de36a4cc2a727d233aa47625ecfbae797 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sat, 17 Jan 2026 23:19:55 -0500 Subject: [PATCH] Fix small binary column creation When migrations switched to cakephp/database we didn't have adequate test coverage for small non-standard sized blobs. This broke migrations that created small binary columns with indexes on them. By preserving the specific length for columns that are smaller than tinyblob we can preserve compatiblity with existing migrations. Fixes #999 --- src/Db/Adapter/MysqlAdapter.php | 6 +++- .../TestCase/Db/Adapter/MysqlAdapterTest.php | 32 +++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/Db/Adapter/MysqlAdapter.php b/src/Db/Adapter/MysqlAdapter.php index 76b71f4dc..4351d3c7e 100644 --- a/src/Db/Adapter/MysqlAdapter.php +++ b/src/Db/Adapter/MysqlAdapter.php @@ -305,7 +305,11 @@ protected function mapColumnData(array $data): array $data['length'] = null; } $standardLengths = [TableSchema::LENGTH_TINY, TableSchema::LENGTH_MEDIUM, TableSchema::LENGTH_LONG]; - if ($data['length'] !== null && !in_array($data['length'], $standardLengths, true)) { + if ( + $data['length'] !== null && + $data['length'] > TableSchema::LENGTH_TINY && + !in_array($data['length'], $standardLengths, true) + ) { foreach ($standardLengths as $bucket) { if ($bucket < $data['length']) { continue; diff --git a/tests/TestCase/Db/Adapter/MysqlAdapterTest.php b/tests/TestCase/Db/Adapter/MysqlAdapterTest.php index a12e765a6..f0d3a3bcc 100644 --- a/tests/TestCase/Db/Adapter/MysqlAdapterTest.php +++ b/tests/TestCase/Db/Adapter/MysqlAdapterTest.php @@ -17,6 +17,7 @@ use Migrations\Db\Table; use Migrations\Db\Table\Column; use Migrations\Db\Table\ForeignKey; +use Migrations\Db\Table\Index; use PDO; use PDOException; use PHPUnit\Framework\Attributes\DataProvider; @@ -337,6 +338,27 @@ public function testCreateTableWithPrimaryKeyAsBinaryUuid() $this->assertTrue($this->adapter->hasColumn('ztable', 'user_id')); } + public function testCreateTableBinaryLengthWithIndex() + { + $table = new Table('ntable', [], $this->adapter); + $table + ->addColumn('file', 'binary', [ + 'default' => null, + 'length' => 20, + 'null' => true, + ]) + ->addIndex( + (new Index()) + ->setColumns(['file']) + ->setName('file_idx') + ->setType('unique'), + ) + ->create(); + $this->assertTrue($this->adapter->hasColumn('ntable', 'id')); + $this->assertTrue($this->adapter->hasColumn('ntable', 'file')); + $this->assertTrue($this->adapter->hasIndex('ntable', 'file')); + } + /** * @return void */ @@ -1071,8 +1093,11 @@ public static function binaryToBlobAutomaticConversionData() return [ // When creating binary with limit > 255, MySQL auto-converts to BLOB // input limit, expected SQL type name, expected column limit after round-trip + // For values smaller than 255, we preserve the length. [null, 'blob', MysqlAdapter::BLOB_REGULAR], // binary(null) becomes BLOB - [64, 'tinyblob', MysqlAdapter::BLOB_TINY], // binary(64) becomes TINYBLOB + [64, 'binary', 64], // binary(64) becomes binary(64) + [254, 'binary', 254], // binary(254) becomes binary(254) + [255, 'tinyblob', MysqlAdapter::BLOB_TINY], // binary(255) becomes TINYBLOB [MysqlAdapter::BLOB_REGULAR - 20, 'mediumblob', MysqlAdapter::BLOB_MEDIUM], [MysqlAdapter::BLOB_REGULAR, 'blob', MysqlAdapter::BLOB_REGULAR], [MysqlAdapter::BLOB_REGULAR + 20, 'mediumblob', MysqlAdapter::BLOB_MEDIUM], @@ -1099,8 +1124,11 @@ public static function varbinaryToBlobAutomaticConversionData() return [ // When creating varbinary with limit > 255, MySQL auto-converts to BLOB // input limit, expected SQL type name, expected column limit after round-trip + // For values smaller than 255, we preserve the length. [null, 'blob', MysqlAdapter::BLOB_REGULAR], // varbinary(null) becomes BLOB - [64, 'tinyblob', MysqlAdapter::BLOB_TINY], // varbinary(64) becomes TINYBLOB + [64, 'binary', 64], // varbinary(64) becomes binary(64) + [254, 'binary', 254], // varbinary(254) becomes binary(254) + [255, 'tinyblob', MysqlAdapter::BLOB_TINY], // varbinary(255) becomes TINYBLOB [MysqlAdapter::BLOB_REGULAR - 20, 'mediumblob', MysqlAdapter::BLOB_MEDIUM], [MysqlAdapter::BLOB_REGULAR, 'blob', MysqlAdapter::BLOB_REGULAR], [MysqlAdapter::BLOB_REGULAR + 20, 'mediumblob', MysqlAdapter::BLOB_MEDIUM],