From c2c05d191d5c4379fb9be58599012158ea3b9db6 Mon Sep 17 00:00:00 2001 From: Adam Dyson Date: Thu, 10 Jul 2025 00:14:37 +1000 Subject: [PATCH 1/3] test(MySQL): Added a test case proving bug with boolean columns --- .../MySQL/Connection/CustomOptionsTest.php | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/Database/Functional/Driver/MySQL/Connection/CustomOptionsTest.php b/tests/Database/Functional/Driver/MySQL/Connection/CustomOptionsTest.php index 0225ae43..59dc22c8 100644 --- a/tests/Database/Functional/Driver/MySQL/Connection/CustomOptionsTest.php +++ b/tests/Database/Functional/Driver/MySQL/Connection/CustomOptionsTest.php @@ -94,6 +94,33 @@ public function testNamedArgumentsToConfigureInteger(): void $this->assertTrue($foo->isNullable()); } + public function testNamedArgumentsToConfigureBoolean(): void + { + $schema = $this->schema('foo'); + $schema->boolean('bar')->defaultValue(false)->unsigned(true)->size(1); + $schema->boolean('baz', nullable: true, unsigned: true, size: 1); + $schema->save(); + + $this->assertInstanceOf(MySQLColumn::class, $bar = $this->fetchSchema($schema)->column('bar')); + $this->assertInstanceOf(MySQLColumn::class, $baz = $this->fetchSchema($schema)->column('baz')); + + \assert($bar instanceof MySQLColumn); + \assert($baz instanceof MySQLColumn); + $this->assertFalse($bar->isZerofill()); + $this->assertFalse($baz->isZerofill()); + $this->assertTrue($bar->isUnsigned()); + $this->assertTrue($baz->isUnsigned()); + + // Below assertion fails. We expect boolean to have a default size of 1 however we receive 4, + // even when explicitly declaring the column size. Likely due to MySQLColumn::createInstance + // not knowing the `userType` at this point, or that the default size should be 1. Instead, the + // size is resolved as 4, default value when resolving a tinyint (DBMS specific column type). + $this->assertSame(1, $bar->getSize()); + $this->assertSame(1, $baz->getSize()); + $this->assertFalse($bar->isNullable()); + $this->assertTrue($baz->isNullable()); + } + /** * The `text` have no the `unsigned` attribute. It will be stored in the additional attributes. */ From 0129e7f0c49e2cefb7d986b0ad0d311bdcdf7738 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 10 Jul 2025 10:07:40 +0400 Subject: [PATCH 2/3] test(MySQL): enhance boolean column configuration tests with zerofill and nullable checks --- .../MySQL/Connection/CustomOptionsTest.php | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/tests/Database/Functional/Driver/MySQL/Connection/CustomOptionsTest.php b/tests/Database/Functional/Driver/MySQL/Connection/CustomOptionsTest.php index 59dc22c8..a775df82 100644 --- a/tests/Database/Functional/Driver/MySQL/Connection/CustomOptionsTest.php +++ b/tests/Database/Functional/Driver/MySQL/Connection/CustomOptionsTest.php @@ -97,28 +97,40 @@ public function testNamedArgumentsToConfigureInteger(): void public function testNamedArgumentsToConfigureBoolean(): void { $schema = $this->schema('foo'); - $schema->boolean('bar')->defaultValue(false)->unsigned(true)->size(1); - $schema->boolean('baz', nullable: true, unsigned: true, size: 1); + $schema->boolean('bar')->defaultValue(false)->nullable(false)->unsigned(true)->size(1)->zerofill(true); + $schema->boolean('baz', nullable: true, unsigned: true, size: 1, zerofill: true); + $schema->boolean('qux', nullable: false, unsigned: true); + $schema->boolean('quux', nullable: false); $schema->save(); $this->assertInstanceOf(MySQLColumn::class, $bar = $this->fetchSchema($schema)->column('bar')); $this->assertInstanceOf(MySQLColumn::class, $baz = $this->fetchSchema($schema)->column('baz')); - - \assert($bar instanceof MySQLColumn); - \assert($baz instanceof MySQLColumn); - $this->assertFalse($bar->isZerofill()); - $this->assertFalse($baz->isZerofill()); + $this->assertInstanceOf(MySQLColumn::class, $qux = $this->fetchSchema($schema)->column('qux')); + $this->assertInstanceOf(MySQLColumn::class, $quux = $this->fetchSchema($schema)->column('quux')); + + self::assertInstanceOf(MySQLColumn::class, $bar); + self::assertInstanceOf(MySQLColumn::class, $baz); + self::assertInstanceOf(MySQLColumn::class, $qux); + self::assertInstanceOf(MySQLColumn::class, $quux); + $this->assertTrue($bar->isZerofill()); + $this->assertTrue($baz->isZerofill()); + $this->assertFalse($qux->isZerofill()); + $this->assertFalse($quux->isZerofill()); $this->assertTrue($bar->isUnsigned()); $this->assertTrue($baz->isUnsigned()); + $this->assertTrue($qux->isUnsigned()); + $this->assertFalse($quux->isUnsigned()); - // Below assertion fails. We expect boolean to have a default size of 1 however we receive 4, - // even when explicitly declaring the column size. Likely due to MySQLColumn::createInstance - // not knowing the `userType` at this point, or that the default size should be 1. Instead, the - // size is resolved as 4, default value when resolving a tinyint (DBMS specific column type). $this->assertSame(1, $bar->getSize()); $this->assertSame(1, $baz->getSize()); + // In case of zerofill=false and unsigned=true the size value might be resolved to 4 + $this->assertTrue(\in_array($qux->getSize(), [1, 4], true)); + $this->assertSame(1, $quux->getSize()); + $this->assertFalse($bar->isNullable()); $this->assertTrue($baz->isNullable()); + $this->assertFalse($qux->isNullable()); + $this->assertFalse($quux->isNullable()); } /** From 0e77852c54621dbc68b065d4f0bf030eebd9f6de Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Thu, 10 Jul 2025 10:08:14 +0400 Subject: [PATCH 3/3] chore: update method annotations in MySQLColumn for improved clarity --- src/Driver/MySQL/Schema/MySQLColumn.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Driver/MySQL/Schema/MySQLColumn.php b/src/Driver/MySQL/Schema/MySQLColumn.php index 6e34add4..c8cf6464 100644 --- a/src/Driver/MySQL/Schema/MySQLColumn.php +++ b/src/Driver/MySQL/Schema/MySQLColumn.php @@ -23,17 +23,17 @@ * Attention! You can use only one timestamp or datetime with DATETIME_NOW setting! Thought, it will * work on multiple fields with MySQL 5.6.6+ version. * - * @method $this|AbstractColumn primary(int $size, bool $unsigned = false, $zerofill = false) - * @method $this|AbstractColumn smallPrimary(int $size, bool $unsigned = false, $zerofill = false) - * @method $this|AbstractColumn bigPrimary(int $size, bool $unsigned = false, $zerofill = false) - * @method $this|AbstractColumn integer(int $size, bool $unsigned = false, $zerofill = false) - * @method $this|AbstractColumn tinyInteger(int $size, bool $unsigned = false, $zerofill = false) - * @method $this|AbstractColumn smallInteger(int $size, bool $unsigned = false, $zerofill = false) - * @method $this|AbstractColumn bigInteger(int $size, bool $unsigned = false, $zerofill = false) - * @method $this|AbstractColumn unsigned(bool $value) - * @method $this|AbstractColumn zerofill(bool $value) - * @method $this|AbstractColumn comment(string $value) - * @method $this|AbstractColumn after(string $column) + * @method $this primary(int $size, bool $unsigned = false, $zerofill = false) + * @method $this smallPrimary(int $size, bool $unsigned = false, $zerofill = false) + * @method $this bigPrimary(int $size, bool $unsigned = false, $zerofill = false) + * @method $this integer(int $size, bool $unsigned = false, $zerofill = false) + * @method $this tinyInteger(int $size, bool $unsigned = false, $zerofill = false) + * @method $this smallInteger(int $size, bool $unsigned = false, $zerofill = false) + * @method $this bigInteger(int $size, bool $unsigned = false, $zerofill = false) + * @method $this unsigned(bool $value) + * @method $this zerofill(bool $value) + * @method $this comment(string $value) + * @method $this after(string $column) */ class MySQLColumn extends AbstractColumn {