From 63f31ac40948046f06c8db3c275e6085b5ea902d Mon Sep 17 00:00:00 2001 From: Adam Dyson Date: Sun, 13 Jul 2025 16:45:41 +1000 Subject: [PATCH 1/2] Added bigInteger handling within RegistryModifier --- src/Schema/RegistryModifier.php | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/Schema/RegistryModifier.php b/src/Schema/RegistryModifier.php index 9744f81..1bff41e 100644 --- a/src/Schema/RegistryModifier.php +++ b/src/Schema/RegistryModifier.php @@ -32,9 +32,14 @@ class RegistryModifier 'smallInteger', 'bigInteger', ]; + protected const BIG_INTEGER_TYPES = [ + 'bigint', + 'bigInteger', + ]; protected const DATETIME_TYPES = ['datetime', 'datetime2']; protected const INT_COLUMN = AbstractColumn::INT; protected const STRING_COLUMN = AbstractColumn::STRING; + protected const BIG_INTEGER_COLUMN = 'bigInteger'; protected const DATETIME_COLUMN = 'datetime'; protected const UUID_COLUMN = 'uuid'; @@ -58,6 +63,13 @@ public static function isIntegerType(string $type): bool return \in_array($matches['type'], self::INTEGER_TYPES, true); } + public static function isBigIntegerType(string $type): bool + { + \preg_match(self::DEFINITION, $type, $matches); + + return \in_array($matches['type'], self::BIG_INTEGER_TYPES, true); + } + public static function isDatetimeType(string $type): bool { \preg_match(self::DEFINITION, $type, $matches); @@ -123,6 +135,32 @@ public function addIntegerColumn(string $columnName, string $fieldName, int|null return $this->table->column($columnName)->type(self::INT_COLUMN); } + public function addBigIntegerColumn( + string $columnName, + string $fieldName, + int|null $generated = null, + ): AbstractColumn { + if ($this->fields->has($fieldName)) { + if (! static::isBigIntegerType($this->fields->get($fieldName)->getType())) { + throw new BehaviorCompilationException(\sprintf('Field %s must be of type big integer.', $fieldName)); + } + $this->validateColumnName($fieldName, $columnName); + $this->fields->get($fieldName)->setGenerated($generated); + + return $this->table->column($columnName); + } + + $field = (new Field()) + ->setColumn($columnName) + ->setType(self::BIG_INTEGER_COLUMN) + ->setTypecast('int') + ->setGenerated($generated); + + $this->fields->set($fieldName, $field); + + return $this->table->column($columnName)->type(self::BIG_INTEGER_COLUMN); + } + public function addStringColumn(string $columnName, string $fieldName, int|null $generated = null): AbstractColumn { if ($this->fields->has($fieldName)) { From 690aa102fe3879880c3debb9ac5fefdb41493ef9 Mon Sep 17 00:00:00 2001 From: Adam Dyson Date: Sun, 13 Jul 2025 16:45:58 +1000 Subject: [PATCH 2/2] Added test coverage for bigInteger handling within RegistryModifier --- psalm-baseline.xml | 5 +++- .../Common/Schema/RegistryModifierTest.php | 27 +++++++++++++++++++ .../Unit/Schema/RegistryModifierTest.php | 24 +++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 8798835..06a83b4 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + @@ -113,6 +113,9 @@ + + + diff --git a/tests/Behavior/Functional/Driver/Common/Schema/RegistryModifierTest.php b/tests/Behavior/Functional/Driver/Common/Schema/RegistryModifierTest.php index c1f9427..6e16118 100644 --- a/tests/Behavior/Functional/Driver/Common/Schema/RegistryModifierTest.php +++ b/tests/Behavior/Functional/Driver/Common/Schema/RegistryModifierTest.php @@ -5,6 +5,7 @@ namespace Cycle\ORM\Entity\Behavior\Tests\Functional\Driver\Common\Schema; use Cycle\Database\ColumnInterface; +use Cycle\ORM\Entity\Behavior\Exception\BehaviorCompilationException; use Cycle\ORM\Entity\Behavior\Schema\RegistryModifier; use Cycle\ORM\Entity\Behavior\Tests\Fixtures\CustomTypecast; use Cycle\ORM\Entity\Behavior\Tests\Functional\Driver\Common\BaseTest; @@ -57,6 +58,28 @@ public function testAddIntegerField(): void $this->assertSame('version_int', $fields->get('version')->getColumn()); } + public function testAddBigIntegerField(): void + { + $this->modifier->addBigIntegerColumn('snowflake_column', 'snowflake'); + + $entity = $this->registry->getEntity(self::ROLE_TEST); + $fields = $entity->getFields(); + + $this->assertTrue($fields->has('snowflake')); + $this->assertSame('bigInteger', $fields->get('snowflake')->getType()); + $this->assertSame('snowflake_column', $fields->get('snowflake')->getColumn()); + } + + public function testAddBigIntegerFieldThrowsException(): void + { + $this->modifier->addIntegerColumn('snowflake_column', 'snowflake'); + + $this->expectException(BehaviorCompilationException::class); + $this->expectExceptionMessage('Field snowflake must be of type big integer.'); + + $this->modifier->addBigIntegerColumn('snowflake_column', 'snowflake'); + } + public function testAddUuidField(): void { $this->modifier->addUuidColumn('uuid_column', 'uuid'); @@ -73,15 +96,19 @@ public function testAddTypecast(): void { $this->modifier->addUuidColumn('uuid_column', 'uuid'); $this->modifier->addIntegerColumn('counter_column', 'counter'); + $this->modifier->addBigIntegerColumn('snowflake_column', 'snowflake'); $field1 = $this->registry->getEntity(self::ROLE_TEST)->getFields()->get('uuid'); $field2 = $this->registry->getEntity(self::ROLE_TEST)->getFields()->get('counter'); + $field3 = $this->registry->getEntity(self::ROLE_TEST)->getFields()->get('snowflake'); $this->modifier->setTypecast($field1, [Uuid::class, 'fromString']); $this->modifier->setTypecast($field2, 'int', CustomTypecast::class); + $this->modifier->setTypecast($field3, 'int', CustomTypecast::class); // field has custom UUID typecast $this->assertSame([Uuid::class, 'fromString'], $field1->getTypecast()); $this->assertSame('int', $field2->getTypecast()); + $this->assertSame('int', $field3->getTypecast()); // entity has default typecast $this->assertSame( diff --git a/tests/Behavior/Unit/Schema/RegistryModifierTest.php b/tests/Behavior/Unit/Schema/RegistryModifierTest.php index d5ef5f4..d93fe5c 100644 --- a/tests/Behavior/Unit/Schema/RegistryModifierTest.php +++ b/tests/Behavior/Unit/Schema/RegistryModifierTest.php @@ -22,6 +22,12 @@ public static function integerDataProvider(): \Traversable yield ['integer(4)']; } + public static function bigIntegerDataProvider(): \Traversable + { + yield ['bigint']; + yield ['bigInteger']; + } + public static function datetimeDataProvider(): \Traversable { yield ['datetime']; @@ -61,6 +67,24 @@ public function testIsIntegerTypeFalse(mixed $type): void $this->assertFalse(RegistryModifier::isIntegerType($type)); } + /** + * @dataProvider bigIntegerDataProvider + */ + public function testIsBigIntegerTypeTrue(mixed $type): void + { + $this->assertTrue(RegistryModifier::isBigIntegerType($type)); + } + + /** + * @dataProvider datetimeDataProvider + * @dataProvider stringDataProvider + * @dataProvider invalidDataProvider + */ + public function testIsBigIntegerTypeFalse(mixed $type): void + { + $this->assertFalse(RegistryModifier::isBigIntegerType($type)); + } + /** * @dataProvider datetimeDataProvider */