From db8cba8267edc4fe1f8355d711049ff64d93eb38 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Fri, 21 Nov 2025 17:45:22 +0300 Subject: [PATCH 01/22] start --- src/Column/ColumnDefinitionBuilder.php | 1 + src/Column/ColumnFactory.php | 2 +- tests/Provider/ColumnFactoryProvider.php | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Column/ColumnDefinitionBuilder.php b/src/Column/ColumnDefinitionBuilder.php index 81dea0d1..02ab0617 100644 --- a/src/Column/ColumnDefinitionBuilder.php +++ b/src/Column/ColumnDefinitionBuilder.php @@ -104,6 +104,7 @@ protected function getDbType(ColumnInterface $column): string ColumnType::ARRAY => 'json', ColumnType::STRUCTURED => 'json', ColumnType::JSON => 'json', + ColumnType::ENUM => 'varchar', default => 'varchar', }; } diff --git a/src/Column/ColumnFactory.php b/src/Column/ColumnFactory.php index 14ffe8d3..50b64ac7 100644 --- a/src/Column/ColumnFactory.php +++ b/src/Column/ColumnFactory.php @@ -36,7 +36,7 @@ final class ColumnFactory extends AbstractColumnFactory 'numeric' => ColumnType::DECIMAL, 'char' => ColumnType::CHAR, 'varchar' => ColumnType::STRING, - 'enum' => ColumnType::STRING, + 'enum' => ColumnType::ENUM, 'tinytext' => ColumnType::TEXT, 'mediumtext' => ColumnType::TEXT, 'longtext' => ColumnType::TEXT, diff --git a/tests/Provider/ColumnFactoryProvider.php b/tests/Provider/ColumnFactoryProvider.php index d2036512..efdab383 100644 --- a/tests/Provider/ColumnFactoryProvider.php +++ b/tests/Provider/ColumnFactoryProvider.php @@ -11,6 +11,7 @@ use Yiisoft\Db\Schema\Column\BooleanColumn; use Yiisoft\Db\Schema\Column\DatetimeColumn; use Yiisoft\Db\Schema\Column\DoubleColumn; +use Yiisoft\Db\Schema\Column\EnumColumn; use Yiisoft\Db\Schema\Column\IntegerColumn; use Yiisoft\Db\Schema\Column\JsonColumn; use Yiisoft\Db\Schema\Column\StringColumn; @@ -38,7 +39,7 @@ public static function dbTypes(): array ['char', ColumnType::CHAR, StringColumn::class], ['varchar', ColumnType::STRING, StringColumn::class], ['string', ColumnType::STRING, StringColumn::class], - ['enum', ColumnType::STRING, StringColumn::class], + ['enum', ColumnType::ENUM, EnumColumn::class], ['tinytext', ColumnType::TEXT, StringColumn::class], ['mediumtext', ColumnType::TEXT, StringColumn::class], ['longtext', ColumnType::TEXT, StringColumn::class], From bca039513ad37930157fa9133ebb6d48fe327c7f Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 25 Nov 2025 11:59:22 +0300 Subject: [PATCH 02/22] improve --- src/Column/ColumnFactory.php | 1 - src/Schema.php | 44 ++++++++++++++++++- tests/Column/EnumColumnTest.php | 55 ++++++++++++++++++++++++ tests/Provider/ColumnFactoryProvider.php | 1 - 4 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 tests/Column/EnumColumnTest.php diff --git a/src/Column/ColumnFactory.php b/src/Column/ColumnFactory.php index 50b64ac7..b93203f6 100644 --- a/src/Column/ColumnFactory.php +++ b/src/Column/ColumnFactory.php @@ -36,7 +36,6 @@ final class ColumnFactory extends AbstractColumnFactory 'numeric' => ColumnType::DECIMAL, 'char' => ColumnType::CHAR, 'varchar' => ColumnType::STRING, - 'enum' => ColumnType::ENUM, 'tinytext' => ColumnType::TEXT, 'mediumtext' => ColumnType::TEXT, 'longtext' => ColumnType::TEXT, diff --git a/src/Schema.php b/src/Schema.php index b018339c..0a345930 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -243,6 +243,7 @@ protected function findColumns(TableSchemaInterface $table): bool { $columns = $this->loadTableColumnsInfo($table->getName()); $jsonColumns = $this->getJsonColumns($table); + $checks = $this->loadTableChecks($table->getName()); foreach ($columns as $info) { if (in_array($info['name'], $jsonColumns, true)) { @@ -252,7 +253,7 @@ protected function findColumns(TableSchemaInterface $table): bool $info['schema'] = $table->getSchemaName(); $info['table'] = $table->getName(); - $column = $this->loadColumn($info); + $column = $this->loadColumn($info, $checks); $table->column($info['name'], $column); } @@ -314,12 +315,13 @@ protected function findViewNames(string $schema = ''): array * Loads the column information into a {@see ColumnInterface} object. * * @param array $info The column information. + * @param Check[] $checks * * @return ColumnInterface The column object. * * @psalm-param ColumnInfo $info */ - private function loadColumn(array $info): ColumnInterface + private function loadColumn(array $info, array $checks): ColumnInterface { return $this->db->getColumnFactory()->fromDefinition($info['type'], [ 'defaultValueRaw' => $info['dflt_value'], @@ -328,6 +330,7 @@ private function loadColumn(array $info): ColumnInterface 'primaryKey' => (bool) $info['pk'], 'schema' => $info['schema'], 'table' => $info['table'], + 'values' => $this->tryGetEnumValuesFromCheck($info['name'], $checks), ]); } @@ -397,4 +400,41 @@ private function getJsonColumns(TableSchemaInterface $table): array return $result; } + + /** + * @param Check[] $checks + * + * @psalm-return list|null + */ + private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array + { + if (empty($checks)) { + return null; + } + + foreach ($checks as $check) { + if (!str_starts_with($check->expression, "$name ")) { + continue; + } + + preg_match_all( + "~ IN\s*\(\s*(?:'(?:[^']+|'(?:''|[^']))*')+~i", + $check->expression, + $block, + ); + + if (empty($block[0][0])) { + continue; + } + + preg_match_all("~'((?:''|[^'])*)'~", $block[0][0], $matches); + + return array_map( + static fn($v) => str_replace("''", "'", $v), + $matches[1] ?? [], + ); + } + + return null; + } } diff --git a/tests/Column/EnumColumnTest.php b/tests/Column/EnumColumnTest.php new file mode 100644 index 00000000..bd528c44 --- /dev/null +++ b/tests/Column/EnumColumnTest.php @@ -0,0 +1,55 @@ +dropTable('test_enum_table'); + $this->executeStatements( + <<getSharedConnection(); + $column = $db->getTableSchema('test_enum_table')->getColumn('status'); + + $this->assertNotInstanceOf(EnumColumn::class, $column); + + $this->dropTable('test_enum_table'); + } + + protected function createDatabaseObjectsStatements(): array + { + return [ + << Date: Tue, 25 Nov 2025 09:00:52 +0000 Subject: [PATCH 03/22] Apply PHP CS Fixer and Rector changes (CI) --- tests/Provider/ColumnFactoryProvider.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Provider/ColumnFactoryProvider.php b/tests/Provider/ColumnFactoryProvider.php index d9854408..cc09a3fb 100644 --- a/tests/Provider/ColumnFactoryProvider.php +++ b/tests/Provider/ColumnFactoryProvider.php @@ -11,7 +11,6 @@ use Yiisoft\Db\Schema\Column\BooleanColumn; use Yiisoft\Db\Schema\Column\DatetimeColumn; use Yiisoft\Db\Schema\Column\DoubleColumn; -use Yiisoft\Db\Schema\Column\EnumColumn; use Yiisoft\Db\Schema\Column\IntegerColumn; use Yiisoft\Db\Schema\Column\JsonColumn; use Yiisoft\Db\Schema\Column\StringColumn; From e10df710202e20383c60e7a25842d1e1036fae7e Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Tue, 25 Nov 2025 13:19:11 +0300 Subject: [PATCH 04/22] test --- tests/Column/EnumColumnTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Column/EnumColumnTest.php b/tests/Column/EnumColumnTest.php index bd528c44..38347a40 100644 --- a/tests/Column/EnumColumnTest.php +++ b/tests/Column/EnumColumnTest.php @@ -14,6 +14,7 @@ final class EnumColumnTest extends CommonEnumColumnTest use IntegrationTestTrait; #[TestWith(['INTEGER CHECK (status IN (1, 2, 3))'])] + #[TestWith(["TEXT CHECK (status != 'abc')"])] public function testNonEnumCheck(string $columnDefinition): void { $this->dropTable('test_enum_table'); From f75475d1bef90041ca116d48c60067b79cce1d4a Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 27 Nov 2025 14:41:16 +0300 Subject: [PATCH 05/22] fix --- src/Schema.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Schema.php b/src/Schema.php index 0a345930..58e59e1e 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -413,7 +413,9 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array } foreach ($checks as $check) { - if (!str_starts_with($check->expression, "$name ")) { + if (!str_starts_with($check->expression, "$name ") && + !str_starts_with($check->expression, "\"$name\" ") + ) { continue; } From 6a5bf047ee55a9fc970d4159eb84b2f3d5391c85 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 27 Nov 2025 14:42:02 +0300 Subject: [PATCH 06/22] fix --- src/Schema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Schema.php b/src/Schema.php index 58e59e1e..a4934d11 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -243,7 +243,7 @@ protected function findColumns(TableSchemaInterface $table): bool { $columns = $this->loadTableColumnsInfo($table->getName()); $jsonColumns = $this->getJsonColumns($table); - $checks = $this->loadTableChecks($table->getName()); + $checks = $this->getTableChecks($table->getName()); foreach ($columns as $info) { if (in_array($info['name'], $jsonColumns, true)) { From 9dd9b6ea5e3a888820036bf85b0db75e080f226e Mon Sep 17 00:00:00 2001 From: vjik <525501+vjik@users.noreply.github.com> Date: Thu, 27 Nov 2025 11:44:55 +0000 Subject: [PATCH 07/22] Apply PHP CS Fixer and Rector changes (CI) --- src/Schema.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Schema.php b/src/Schema.php index a4934d11..a9db4e9b 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -413,8 +413,8 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array } foreach ($checks as $check) { - if (!str_starts_with($check->expression, "$name ") && - !str_starts_with($check->expression, "\"$name\" ") + if (!str_starts_with($check->expression, "$name ") + && !str_starts_with($check->expression, "\"$name\" ") ) { continue; } From 938501dbbaf4b4d89e145a22b4a03820c42123a2 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Thu, 27 Nov 2025 14:46:03 +0300 Subject: [PATCH 08/22] improve --- src/Schema.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Schema.php b/src/Schema.php index a9db4e9b..5e5750d7 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -21,6 +21,7 @@ use function array_column; use function array_map; use function count; +use function in_array; use function strncasecmp; /** From 6a60f4af79abbb09b55dee8feeced68150ffc84f Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 10:13:56 +0300 Subject: [PATCH 09/22] improve --- src/Schema.php | 2 +- tests/Column/EnumColumnTest.php | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Schema.php b/src/Schema.php index 5e5750d7..81361663 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -421,7 +421,7 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array } preg_match_all( - "~ IN\s*\(\s*(?:'(?:[^']+|'(?:''|[^']))*')+~i", + "~(?expression, $block, ); diff --git a/tests/Column/EnumColumnTest.php b/tests/Column/EnumColumnTest.php index 38347a40..98cd8d9d 100644 --- a/tests/Column/EnumColumnTest.php +++ b/tests/Column/EnumColumnTest.php @@ -15,6 +15,8 @@ final class EnumColumnTest extends CommonEnumColumnTest #[TestWith(['INTEGER CHECK (status IN (1, 2, 3))'])] #[TestWith(["TEXT CHECK (status != 'abc')"])] + #[TestWith(["TEXT CHECK (status NOT IN ('a', 'b', 'c'))"])] + #[TestWith(["TEXT CHECK (status not IN ('a', 'b', 'c'))"])] public function testNonEnumCheck(string $columnDefinition): void { $this->dropTable('test_enum_table'); @@ -35,6 +37,34 @@ public function testNonEnumCheck(string $columnDefinition): void $this->dropTable('test_enum_table'); } + #[TestWith([ + 'knot', + "TEXT CHECK (knot IN ('a', 'b'))", + ['a', 'b'], + ])] + public function testEnumCheck(string $columnName, string $columnDefinition, array $expectedValues): void + { + $this->dropTable('test_enum_table'); + + $quotedColumnName = $this->getSharedConnection()->getQuoter()->quoteColumnName($columnName); + $this->executeStatements( + <<getSharedConnection(); + $column = $db->getTableSchema('test_enum_table')->getColumn($columnName); + + $this->assertInstanceOf(EnumColumn::class, $column, $column::class); + $this->assertEqualsCanonicalizing($expectedValues, $column->getValues()); + + $this->dropTable('test_enum_table'); + } + protected function createDatabaseObjectsStatements(): array { return [ From d39eb9541661357f75564ae0bd0ed3295de2f089 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 10:25:40 +0300 Subject: [PATCH 10/22] improve --- src/Schema.php | 10 +++++++--- tests/Column/EnumColumnTest.php | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/Schema.php b/src/Schema.php index 81361663..24380d4a 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -414,9 +414,7 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array } foreach ($checks as $check) { - if (!str_starts_with($check->expression, "$name ") - && !str_starts_with($check->expression, "\"$name\" ") - ) { + if ($this->isCheckNotStartsFromColumnName($check->expression, $name)) { continue; } @@ -440,4 +438,10 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array return null; } + + private function isCheckNotStartsFromColumnName(string $check, string $columnName): bool + { + $quotedColumnName = preg_quote($columnName, '~'); + return preg_match("~^(|\"|`|'|\[)$quotedColumnName(|\"|`|'|\])\s~", $check) !== 1; + } } diff --git a/tests/Column/EnumColumnTest.php b/tests/Column/EnumColumnTest.php index 98cd8d9d..ae46b42e 100644 --- a/tests/Column/EnumColumnTest.php +++ b/tests/Column/EnumColumnTest.php @@ -42,6 +42,26 @@ public function testNonEnumCheck(string $columnDefinition): void "TEXT CHECK (knot IN ('a', 'b'))", ['a', 'b'], ])] + #[TestWith([ + 'letter', + "TEXT CHECK ('letter' IN ('a', 'b'))", + ['a', 'b'], + ])] + #[TestWith([ + 'letter', + "TEXT CHECK (`letter` IN ('a', 'b'))", + ['a', 'b'], + ])] + #[TestWith([ + 'letter', + "TEXT CHECK ([letter] IN ('a', 'b'))", + ['a', 'b'], + ])] + #[TestWith([ + 'letter', + "TEXT CHECK (\"letter\" IN ('a', 'b'))", + ['a', 'b'], + ])] public function testEnumCheck(string $columnName, string $columnDefinition, array $expectedValues): void { $this->dropTable('test_enum_table'); From 3925bcfdb8b16e30ca5402d3aa11ee1bfe723c64 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 11:35:07 +0300 Subject: [PATCH 11/22] improve regexp --- src/Schema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Schema.php b/src/Schema.php index 24380d4a..59ad78be 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -419,7 +419,7 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array } preg_match_all( - "~(?expression, $block, ); From 3e6755f17a3903a4170c5b419e4207b032cd7a84 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 13:00:16 +0300 Subject: [PATCH 12/22] more tests --- tests/Column/EnumColumnTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Column/EnumColumnTest.php b/tests/Column/EnumColumnTest.php index ae46b42e..211cf882 100644 --- a/tests/Column/EnumColumnTest.php +++ b/tests/Column/EnumColumnTest.php @@ -42,6 +42,11 @@ public function testNonEnumCheck(string $columnDefinition): void "TEXT CHECK (knot IN ('a', 'b'))", ['a', 'b'], ])] + #[TestWith([ + 'status', + "TEXT CHECK (status in ('a', 'b'))", + ['a', 'b'], + ])] #[TestWith([ 'letter', "TEXT CHECK ('letter' IN ('a', 'b'))", From 41a0f8a4bdeebea94cb5102aad82f1ad30930b71 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 13:13:03 +0300 Subject: [PATCH 13/22] improve --- src/Schema.php | 3 ++- tests/Column/EnumColumnTest.php | 27 ++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Schema.php b/src/Schema.php index 59ad78be..9dd72d1b 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -442,6 +442,7 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array private function isCheckNotStartsFromColumnName(string $check, string $columnName): bool { $quotedColumnName = preg_quote($columnName, '~'); - return preg_match("~^(|\"|`|'|\[)$quotedColumnName(|\"|`|'|\])\s~", $check) !== 1; + return preg_match("~^\"$quotedColumnName\"\s~", $check) !== 1 + && preg_match("~^(|`|'|\[)$quotedColumnName(|`|'|\])\s~i", $check) !== 1; } } diff --git a/tests/Column/EnumColumnTest.php b/tests/Column/EnumColumnTest.php index 211cf882..f80ec892 100644 --- a/tests/Column/EnumColumnTest.php +++ b/tests/Column/EnumColumnTest.php @@ -16,7 +16,7 @@ final class EnumColumnTest extends CommonEnumColumnTest #[TestWith(['INTEGER CHECK (status IN (1, 2, 3))'])] #[TestWith(["TEXT CHECK (status != 'abc')"])] #[TestWith(["TEXT CHECK (status NOT IN ('a', 'b', 'c'))"])] - #[TestWith(["TEXT CHECK (status not IN ('a', 'b', 'c'))"])] + #[TestWith(["TEXT CHECK (\"Status\" not IN ('a', 'b', 'c'))"])] public function testNonEnumCheck(string $columnDefinition): void { $this->dropTable('test_enum_table'); @@ -47,21 +47,46 @@ public function testNonEnumCheck(string $columnDefinition): void "TEXT CHECK (status in ('a', 'b'))", ['a', 'b'], ])] + #[TestWith([ + 'letter', + "TEXT CHECK (letter IN ('a', 'b'))", + ['a', 'b'], + ])] + #[TestWith([ + 'letter', + "TEXT CHECK (LETTER IN ('a', 'b'))", + ['a', 'b'], + ])] #[TestWith([ 'letter', "TEXT CHECK ('letter' IN ('a', 'b'))", ['a', 'b'], ])] + #[TestWith([ + 'letter', + "TEXT CHECK ('LETTER' IN ('a', 'b'))", + ['a', 'b'], + ])] #[TestWith([ 'letter', "TEXT CHECK (`letter` IN ('a', 'b'))", ['a', 'b'], ])] + #[TestWith([ + 'letter', + "TEXT CHECK (`LETTER` IN ('a', 'b'))", + ['a', 'b'], + ])] #[TestWith([ 'letter', "TEXT CHECK ([letter] IN ('a', 'b'))", ['a', 'b'], ])] + #[TestWith([ + 'letter', + "TEXT CHECK ([LETTER] IN ('a', 'b'))", + ['a', 'b'], + ])] #[TestWith([ 'letter', "TEXT CHECK (\"letter\" IN ('a', 'b'))", From c11c61a2a0e795fd8cddb64041a5ff1d9061e86e Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 13:26:19 +0300 Subject: [PATCH 14/22] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa617d4d..54f40d4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ - Enh #387: Refactor `DMLQueryBuilder::upsert()` method (@Tigrov) - Chg #391: Update expression namespaces according to changes in `yiisoft/db` package (@Tigrov) - Chg #402: Throw exception on "unsigned" column usage (@vjik) +- New #404: Add enumeration column type support (@vjik) ## 1.2.0 March 21, 2024 From 21a1b984dd43e52a32bb422b343baef597d3a787 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 17:26:04 +0300 Subject: [PATCH 15/22] fix --- src/Schema.php | 2 +- tests/Column/EnumColumnTest.php | 11 +---------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Schema.php b/src/Schema.php index 9dd72d1b..cb29df57 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -443,6 +443,6 @@ private function isCheckNotStartsFromColumnName(string $check, string $columnNam { $quotedColumnName = preg_quote($columnName, '~'); return preg_match("~^\"$quotedColumnName\"\s~", $check) !== 1 - && preg_match("~^(|`|'|\[)$quotedColumnName(|`|'|\])\s~i", $check) !== 1; + && preg_match("~^(|`|\[)$quotedColumnName(|`|\])\s~i", $check) !== 1; } } diff --git a/tests/Column/EnumColumnTest.php b/tests/Column/EnumColumnTest.php index f80ec892..154eb563 100644 --- a/tests/Column/EnumColumnTest.php +++ b/tests/Column/EnumColumnTest.php @@ -17,6 +17,7 @@ final class EnumColumnTest extends CommonEnumColumnTest #[TestWith(["TEXT CHECK (status != 'abc')"])] #[TestWith(["TEXT CHECK (status NOT IN ('a', 'b', 'c'))"])] #[TestWith(["TEXT CHECK (\"Status\" not IN ('a', 'b', 'c'))"])] + #[TestWith(["TEXT CHECK ('status' not IN ('a', 'b', 'c'))"])] public function testNonEnumCheck(string $columnDefinition): void { $this->dropTable('test_enum_table'); @@ -57,16 +58,6 @@ public function testNonEnumCheck(string $columnDefinition): void "TEXT CHECK (LETTER IN ('a', 'b'))", ['a', 'b'], ])] - #[TestWith([ - 'letter', - "TEXT CHECK ('letter' IN ('a', 'b'))", - ['a', 'b'], - ])] - #[TestWith([ - 'letter', - "TEXT CHECK ('LETTER' IN ('a', 'b'))", - ['a', 'b'], - ])] #[TestWith([ 'letter', "TEXT CHECK (`letter` IN ('a', 'b'))", From 2eccd9f77ad212e90bd5e0a20d3dd16592fbbc54 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 17:27:59 +0300 Subject: [PATCH 16/22] improve --- src/Schema.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Schema.php b/src/Schema.php index cb29df57..a3026e86 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -242,9 +242,10 @@ protected function loadTableDefaultValues(string $tableName): array */ protected function findColumns(TableSchemaInterface $table): bool { - $columns = $this->loadTableColumnsInfo($table->getName()); + $tableName = $table->getName(); + $columns = $this->loadTableColumnsInfo($tableName); $jsonColumns = $this->getJsonColumns($table); - $checks = $this->getTableChecks($table->getName()); + $checks = $this->getTableChecks($tableName); foreach ($columns as $info) { if (in_array($info['name'], $jsonColumns, true)) { @@ -252,7 +253,7 @@ protected function findColumns(TableSchemaInterface $table): bool } $info['schema'] = $table->getSchemaName(); - $info['table'] = $table->getName(); + $info['table'] = $tableName; $column = $this->loadColumn($info, $checks); $table->column($info['name'], $column); From 36d47a40637073676a9f27e13762ebeb71fa95a9 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 17:48:30 +0300 Subject: [PATCH 17/22] fix --- src/Schema.php | 4 ++-- tests/Column/EnumColumnTest.php | 14 +++----------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/Schema.php b/src/Schema.php index a3026e86..f85a0b43 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -443,7 +443,7 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array private function isCheckNotStartsFromColumnName(string $check, string $columnName): bool { $quotedColumnName = preg_quote($columnName, '~'); - return preg_match("~^\"$quotedColumnName\"\s~", $check) !== 1 - && preg_match("~^(|`|\[)$quotedColumnName(|`|\])\s~i", $check) !== 1; + return preg_match("~^$quotedColumnName\s~i", $check) !== 1 + && preg_match("~^(\"|`|\[)$quotedColumnName(\"|`|\])\s~", $check) !== 1; } } diff --git a/tests/Column/EnumColumnTest.php b/tests/Column/EnumColumnTest.php index 154eb563..e444bb2b 100644 --- a/tests/Column/EnumColumnTest.php +++ b/tests/Column/EnumColumnTest.php @@ -16,8 +16,10 @@ final class EnumColumnTest extends CommonEnumColumnTest #[TestWith(['INTEGER CHECK (status IN (1, 2, 3))'])] #[TestWith(["TEXT CHECK (status != 'abc')"])] #[TestWith(["TEXT CHECK (status NOT IN ('a', 'b', 'c'))"])] - #[TestWith(["TEXT CHECK (\"Status\" not IN ('a', 'b', 'c'))"])] #[TestWith(["TEXT CHECK ('status' not IN ('a', 'b', 'c'))"])] + #[TestWith(["TEXT CHECK (\"Status\" IN ('a', 'b', 'c'))"])] + #[TestWith(["TEXT CHECK ('Status' IN ('a', 'b', 'c'))"])] + #[TestWith(["TEXT CHECK ([Status] IN ('a', 'b', 'c'))"])] public function testNonEnumCheck(string $columnDefinition): void { $this->dropTable('test_enum_table'); @@ -63,21 +65,11 @@ public function testNonEnumCheck(string $columnDefinition): void "TEXT CHECK (`letter` IN ('a', 'b'))", ['a', 'b'], ])] - #[TestWith([ - 'letter', - "TEXT CHECK (`LETTER` IN ('a', 'b'))", - ['a', 'b'], - ])] #[TestWith([ 'letter', "TEXT CHECK ([letter] IN ('a', 'b'))", ['a', 'b'], ])] - #[TestWith([ - 'letter', - "TEXT CHECK ([LETTER] IN ('a', 'b'))", - ['a', 'b'], - ])] #[TestWith([ 'letter', "TEXT CHECK (\"letter\" IN ('a', 'b'))", From 0a6a1b32e8afcfdefe1a98fd567be5ee1bf1d487 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 17:50:56 +0300 Subject: [PATCH 18/22] more tests --- tests/Column/EnumColumnTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Column/EnumColumnTest.php b/tests/Column/EnumColumnTest.php index e444bb2b..0bc5b74a 100644 --- a/tests/Column/EnumColumnTest.php +++ b/tests/Column/EnumColumnTest.php @@ -75,6 +75,11 @@ public function testNonEnumCheck(string $columnDefinition): void "TEXT CHECK (\"letter\" IN ('a', 'b'))", ['a', 'b'], ])] + #[TestWith([ + 'status', + "TEXT CHECK (status IN\n(\n'a',\n'b'\n))", + ['a', 'b'], + ])] public function testEnumCheck(string $columnName, string $columnDefinition, array $expectedValues): void { $this->dropTable('test_enum_table'); From 16bab24be5f08a2e05055172b2c01aa6cf1ab701 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 18:35:05 +0300 Subject: [PATCH 19/22] Update src/Schema.php Co-authored-by: Sergei Tigrov --- src/Schema.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Schema.php b/src/Schema.php index f85a0b43..6b7f21fc 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -443,7 +443,6 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array private function isCheckNotStartsFromColumnName(string $check, string $columnName): bool { $quotedColumnName = preg_quote($columnName, '~'); - return preg_match("~^$quotedColumnName\s~i", $check) !== 1 - && preg_match("~^(\"|`|\[)$quotedColumnName(\"|`|\])\s~", $check) !== 1; + return preg_match("~^(?:(?i:$quotedColumnName)|(?:\"|`|\[)$quotedColumnName(?:\"|`|\]))\s~", $check) !== 1; } } From 11bafb0846b14cf94de51ca1307c32f63dbd7e5a Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 18:43:42 +0300 Subject: [PATCH 20/22] Update src/Schema.php Co-authored-by: Sergei Tigrov --- src/Schema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Schema.php b/src/Schema.php index 6b7f21fc..85d0b966 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -443,6 +443,6 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array private function isCheckNotStartsFromColumnName(string $check, string $columnName): bool { $quotedColumnName = preg_quote($columnName, '~'); - return preg_match("~^(?:(?i:$quotedColumnName)|(?:\"|`|\[)$quotedColumnName(?:\"|`|\]))\s~", $check) !== 1; + return preg_match("~^(?:(?i:$quotedColumnName)|[\"`[]$quotedColumnName[\"`\]])\s~", $check) !== 1; } } From 9ffc8ccf15bc9bff99f25316a82470f69f808832 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 18:45:05 +0300 Subject: [PATCH 21/22] fix --- src/Schema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Schema.php b/src/Schema.php index 85d0b966..16ebbe26 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -443,6 +443,6 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array private function isCheckNotStartsFromColumnName(string $check, string $columnName): bool { $quotedColumnName = preg_quote($columnName, '~'); - return preg_match("~^(?:(?i:$quotedColumnName)|[\"`[]$quotedColumnName[\"`\]])\s~", $check) !== 1; + return preg_match("~^(?:(?i:$quotedColumnName)|[\"`[]{$quotedColumnName}[\"`\]])\s~", $check) !== 1; } } From 339c90dc721834b91d9a9bba911edff654a40294 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sat, 29 Nov 2025 18:46:36 +0300 Subject: [PATCH 22/22] fix --- src/Schema.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Schema.php b/src/Schema.php index 16ebbe26..aa355d72 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -443,6 +443,6 @@ private function tryGetEnumValuesFromCheck(string $name, array $checks): ?array private function isCheckNotStartsFromColumnName(string $check, string $columnName): bool { $quotedColumnName = preg_quote($columnName, '~'); - return preg_match("~^(?:(?i:$quotedColumnName)|[\"`[]{$quotedColumnName}[\"`\]])\s~", $check) !== 1; + return preg_match("~^(?:(?i:$quotedColumnName)|[\"`\[]{$quotedColumnName}[\"`\]])\s~", $check) !== 1; } }