Skip to content

Commit 9d74ef7

Browse files
authored
Add fixed option for binary column type (#1014)
Add support for the `fixed` attribute on binary columns to distinguish between fixed-length BINARY and variable-length VARBINARY types. This mirrors cakephp/cakephp#19207. * Add test cases for fixed option on binary columns Tests cover: - Column class getter/setter for fixed option - Column::toArray() including fixed in output - Column::setOptions() accepting fixed option - MigrationHelper::getColumnOption() including/excluding fixed - MysqlAdapter creating BINARY vs VARBINARY based on fixed option * Add column type assertions to binary fixed test
1 parent d6720e1 commit 9d74ef7

6 files changed

Lines changed: 172 additions & 1 deletion

File tree

src/Db/Adapter/MysqlAdapter.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,9 @@ public function getColumns(string $tableName): array
651651
if ($record['onUpdate'] ?? false) {
652652
$column->setUpdate($record['onUpdate']);
653653
}
654+
if ($record['fixed'] ?? false) {
655+
$column->setFixed(true);
656+
}
654657

655658
$columns[] = $column;
656659
}

src/Db/Table/Column.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ class Column extends DatabaseColumn
117117
*/
118118
protected ?string $lock = null;
119119

120+
/**
121+
* @var bool|null
122+
*/
123+
protected ?bool $fixed = null;
124+
120125
/**
121126
* Column constructor
122127
*
@@ -772,6 +777,31 @@ public function getLock(): ?string
772777
return $this->lock;
773778
}
774779

780+
/**
781+
* Sets whether field should use fixed-length storage (for binary columns).
782+
*
783+
* When true, binary columns will use BINARY(n) instead of VARBINARY(n).
784+
*
785+
* @param bool $fixed Fixed
786+
* @return $this
787+
*/
788+
public function setFixed(bool $fixed)
789+
{
790+
$this->fixed = $fixed;
791+
792+
return $this;
793+
}
794+
795+
/**
796+
* Gets whether field should use fixed-length storage.
797+
*
798+
* @return bool|null
799+
*/
800+
public function getFixed(): ?bool
801+
{
802+
return $this->fixed;
803+
}
804+
775805
/**
776806
* Gets all allowed options. Each option must have a corresponding `setFoo` method.
777807
*
@@ -802,6 +832,7 @@ protected function getValidOptions(): array
802832
'generated',
803833
'algorithm',
804834
'lock',
835+
'fixed',
805836
];
806837
}
807838

@@ -894,6 +925,7 @@ public function toArray(): array
894925
'default' => $default,
895926
'generated' => $this->getGenerated(),
896927
'unsigned' => $this->getUnsigned(),
928+
'fixed' => $this->getFixed(),
897929
'onUpdate' => $this->getUpdate(),
898930
'collate' => $this->getCollation(),
899931
'precision' => $precision,

src/View/Helper/MigrationHelper.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ public function getColumnOption(array $options): array
389389
'scale',
390390
'after',
391391
'collate',
392+
'fixed',
392393
]);
393394
$columnOptions = array_intersect_key($options, $wantedOptions);
394395
if (empty($columnOptions['comment'])) {
@@ -495,7 +496,7 @@ public function attributes(TableSchemaInterface|string $table, string $column):
495496
'comment', 'unsigned',
496497
'signed', 'properties',
497498
'autoIncrement', 'unique',
498-
'collate',
499+
'collate', 'fixed',
499500
];
500501

501502
$attributes = [];

tests/TestCase/Db/Adapter/MysqlAdapterTest.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3541,4 +3541,53 @@ public function testCombinedPartitionAndColumnOperations(): void
35413541
$this->assertCount(1, $rows);
35423542
$this->assertEquals('A description', $rows[0]['description']);
35433543
}
3544+
3545+
public function testBinaryColumnWithFixedOption(): void
3546+
{
3547+
$table = new Table('binary_fixed_test', [], $this->adapter);
3548+
$table->addColumn('hash', 'binary', ['limit' => 20, 'fixed' => true])
3549+
->addColumn('data', 'binary', ['limit' => 20])
3550+
->save();
3551+
3552+
$this->assertTrue($this->adapter->hasColumn('binary_fixed_test', 'hash'));
3553+
$this->assertTrue($this->adapter->hasColumn('binary_fixed_test', 'data'));
3554+
3555+
// Check that the fixed column is created as BINARY and the non-fixed as VARBINARY
3556+
$rows = $this->adapter->fetchAll('SHOW COLUMNS FROM binary_fixed_test');
3557+
$hashColumn = null;
3558+
$dataColumn = null;
3559+
foreach ($rows as $row) {
3560+
if ($row['Field'] === 'hash') {
3561+
$hashColumn = $row;
3562+
}
3563+
if ($row['Field'] === 'data') {
3564+
$dataColumn = $row;
3565+
}
3566+
}
3567+
3568+
$this->assertNotNull($hashColumn);
3569+
$this->assertNotNull($dataColumn);
3570+
$this->assertSame('binary(20)', $hashColumn['Type']);
3571+
$this->assertSame('varbinary(20)', $dataColumn['Type']);
3572+
3573+
// Verify the fixed attribute is reflected back
3574+
$columns = $this->adapter->getColumns('binary_fixed_test');
3575+
$hashCol = null;
3576+
$dataCol = null;
3577+
foreach ($columns as $col) {
3578+
if ($col->getName() === 'hash') {
3579+
$hashCol = $col;
3580+
}
3581+
if ($col->getName() === 'data') {
3582+
$dataCol = $col;
3583+
}
3584+
}
3585+
3586+
$this->assertNotNull($hashCol);
3587+
$this->assertNotNull($dataCol);
3588+
$this->assertSame('binary', $hashCol->getType());
3589+
$this->assertSame('binary', $dataCol->getType());
3590+
$this->assertTrue($hashCol->getFixed());
3591+
$this->assertNull($dataCol->getFixed());
3592+
}
35443593
}

tests/TestCase/Db/Table/ColumnTest.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,4 +275,56 @@ public function testUnsignedConfigurationDoesNotAffectNonIntegerTypes(): void
275275
$decimalColumn->setName('price')->setType('decimal');
276276
$this->assertFalse($decimalColumn->isUnsigned());
277277
}
278+
279+
public function testFixedOptionDefaultsToNull(): void
280+
{
281+
$column = new Column();
282+
$column->setName('data')->setType('binary');
283+
284+
$this->assertNull($column->getFixed());
285+
}
286+
287+
public function testSetFixedTrue(): void
288+
{
289+
$column = new Column();
290+
$column->setName('hash')->setType('binary')->setFixed(true);
291+
292+
$this->assertTrue($column->getFixed());
293+
}
294+
295+
public function testSetFixedFalse(): void
296+
{
297+
$column = new Column();
298+
$column->setName('data')->setType('binary')->setFixed(false);
299+
300+
$this->assertFalse($column->getFixed());
301+
}
302+
303+
public function testSetOptionsWithFixed(): void
304+
{
305+
$column = new Column();
306+
$column->setName('hash')->setType('binary');
307+
$column->setOptions(['fixed' => true, 'limit' => 20]);
308+
309+
$this->assertTrue($column->getFixed());
310+
$this->assertSame(20, $column->getLimit());
311+
}
312+
313+
public function testToArrayIncludesFixed(): void
314+
{
315+
$column = new Column();
316+
$column->setName('hash')->setType('binary')->setFixed(true)->setLimit(20);
317+
318+
$result = $column->toArray();
319+
$this->assertTrue($result['fixed']);
320+
}
321+
322+
public function testToArrayFixedNullByDefault(): void
323+
{
324+
$column = new Column();
325+
$column->setName('data')->setType('binary')->setLimit(20);
326+
327+
$result = $column->toArray();
328+
$this->assertNull($result['fixed']);
329+
}
278330
}

tests/TestCase/View/Helper/MigrationHelperTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,4 +456,38 @@ public function testGetColumnOptionConvertsCollateToCollation(): void
456456
$this->assertArrayHasKey('collation', $result, 'collation should be set from collate value');
457457
$this->assertSame('en_US.UTF-8', $result['collation']);
458458
}
459+
460+
/**
461+
* Test that getColumnOption includes the fixed option for binary columns
462+
*/
463+
public function testGetColumnOptionIncludesFixed(): void
464+
{
465+
$options = [
466+
'length' => 20,
467+
'null' => true,
468+
'default' => null,
469+
'fixed' => true,
470+
];
471+
472+
$result = $this->helper->getColumnOption($options);
473+
474+
$this->assertArrayHasKey('fixed', $result);
475+
$this->assertTrue($result['fixed']);
476+
}
477+
478+
/**
479+
* Test that getColumnOption excludes fixed when not set
480+
*/
481+
public function testGetColumnOptionExcludesFixedWhenNotSet(): void
482+
{
483+
$options = [
484+
'length' => 20,
485+
'null' => true,
486+
'default' => null,
487+
];
488+
489+
$result = $this->helper->getColumnOption($options);
490+
491+
$this->assertArrayNotHasKey('fixed', $result);
492+
}
459493
}

0 commit comments

Comments
 (0)