diff --git a/CHANGELOG.md b/CHANGELOG.md index b17e0bf6..2d955acb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Enh #323: Refactor `Dsn` class (@Tigrov) - Enh #324: Use constructor to create columns and initialize properties (@Tigrov) - Enh #327: Refactor `Schema::findColumns()` method (@Tigrov) +- Enh #328: Refactor `Schema::normalizeDefaultValue()` method and move it to `ColumnFactory` class (@Tigrov) ## 1.2.0 March 21, 2024 diff --git a/src/Column/ColumnFactory.php b/src/Column/ColumnFactory.php index 5b29029d..84e05220 100644 --- a/src/Column/ColumnFactory.php +++ b/src/Column/ColumnFactory.php @@ -86,4 +86,13 @@ protected function getColumnClass(string $type, array $info = []): string return parent::getColumnClass($type, $info); } + + protected function normalizeNotNullDefaultValue(string $defaultValue, ColumnSchemaInterface $column): mixed + { + if ($defaultValue[0] === '(' && $defaultValue[-1] === ')') { + $defaultValue = substr($defaultValue, 1, -1); + } + + return parent::normalizeNotNullDefaultValue($defaultValue, $column); + } } diff --git a/src/Schema.php b/src/Schema.php index 6fb9ab84..84193b1d 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -25,7 +25,6 @@ use function array_map; use function is_array; use function md5; -use function preg_match; use function serialize; use function str_replace; @@ -369,10 +368,11 @@ protected function loadTableDefaultValues(string $tableName): array */ private function loadColumnSchema(array $info): ColumnSchemaInterface { - $column = $this->getColumnFactory()->fromDbType($info['data_type'], [ + return $this->getColumnFactory()->fromDbType($info['data_type'], [ 'autoIncrement' => $info['is_identity'] === '1', 'comment' => $info['comment'], 'computed' => $info['is_computed'] === '1', + 'defaultValueRaw' => $info['column_default'], 'name' => $info['column_name'], 'notNull' => $info['is_nullable'] !== 'YES', 'primaryKey' => $info['primaryKey'], @@ -381,36 +381,6 @@ private function loadColumnSchema(array $info): ColumnSchemaInterface 'size' => $info['size'] !== null ? (int) $info['size'] : null, 'table' => $info['table'], ]); - - $column->defaultValue($this->normalizeDefaultValue($info['column_default'], $column)); - - return $column; - } - - /** - * Converts column's default value according to {@see ColumnSchema::phpType} after retrieval from the database. - * - * @param string|null $defaultValue The default value retrieved from the database. - * @param ColumnSchemaInterface $column The column schema object. - * - * @return mixed The normalized default value. - */ - private function normalizeDefaultValue(string|null $defaultValue, ColumnSchemaInterface $column): mixed - { - if ( - $defaultValue === null - || $defaultValue === '(NULL)' - || $column->isPrimaryKey() - || $column->isComputed() - ) { - return null; - } - - $value = $this->parseDefaultValue($defaultValue); - - return is_numeric($value) - ? $column->phpTypeCast($value) - : $value; } /** @@ -828,17 +798,4 @@ protected function getCacheTag(): string { return md5(serialize([self::class, ...$this->generateCacheKey()])); } - - private function parseDefaultValue(string $value): string - { - if (preg_match('/^\'(.*)\'$/', $value, $matches)) { - return $matches[1]; - } - - if (preg_match('/^\((.*)\)$/', $value, $matches)) { - return $this->parseDefaultValue($matches[1]); - } - - return $value; - } } diff --git a/tests/ColumnFactoryTest.php b/tests/ColumnFactoryTest.php index b409eae9..81f6069c 100644 --- a/tests/ColumnFactoryTest.php +++ b/tests/ColumnFactoryTest.php @@ -4,6 +4,8 @@ namespace Yiisoft\Db\Mssql\Tests; +use PHPUnit\Framework\Attributes\DataProviderExternal; +use Yiisoft\Db\Mssql\Tests\Provider\ColumnFactoryProvider; use Yiisoft\Db\Mssql\Tests\Support\TestTrait; use Yiisoft\Db\Tests\AbstractColumnFactoryTest; @@ -14,13 +16,13 @@ final class ColumnFactoryTest extends AbstractColumnFactoryTest { use TestTrait; - /** @dataProvider \Yiisoft\Db\Mssql\Tests\Provider\ColumnFactoryProvider::dbTypes */ + #[DataProviderExternal(ColumnFactoryProvider::class, 'dbTypes')] public function testFromDbType(string $dbType, string $expectedType, string $expectedInstanceOf): void { parent::testFromDbType($dbType, $expectedType, $expectedInstanceOf); } - /** @dataProvider \Yiisoft\Db\Mssql\Tests\Provider\ColumnFactoryProvider::definitions */ + #[DataProviderExternal(ColumnFactoryProvider::class, 'definitions')] public function testFromDefinition( string $definition, string $expectedType, @@ -30,7 +32,7 @@ public function testFromDefinition( parent::testFromDefinition($definition, $expectedType, $expectedInstanceOf, $expectedMethodResults); } - /** @dataProvider \Yiisoft\Db\Mssql\Tests\Provider\ColumnFactoryProvider::pseudoTypes */ + #[DataProviderExternal(ColumnFactoryProvider::class, 'pseudoTypes')] public function testFromPseudoType( string $pseudoType, string $expectedType, @@ -40,9 +42,15 @@ public function testFromPseudoType( parent::testFromPseudoType($pseudoType, $expectedType, $expectedInstanceOf, $expectedMethodResults); } - /** @dataProvider \Yiisoft\Db\Mssql\Tests\Provider\ColumnFactoryProvider::types */ + #[DataProviderExternal(ColumnFactoryProvider::class, 'types')] public function testFromType(string $type, string $expectedType, string $expectedInstanceOf): void { parent::testFromType($type, $expectedType, $expectedInstanceOf); } + + #[DataProviderExternal(ColumnFactoryProvider::class, 'defaultValueRaw')] + public function testFromTypeDefaultValueRaw(string $type, string|null $defaultValueRaw, mixed $expected): void + { + parent::testFromTypeDefaultValueRaw($type, $defaultValueRaw, $expected); + } } diff --git a/tests/Provider/ColumnFactoryProvider.php b/tests/Provider/ColumnFactoryProvider.php index b1326a31..a2a82005 100644 --- a/tests/Provider/ColumnFactoryProvider.php +++ b/tests/Provider/ColumnFactoryProvider.php @@ -62,4 +62,18 @@ public static function dbTypes(): array ['table', ColumnType::STRING, StringColumnSchema::class], ]; } + + public static function defaultValueRaw(): array + { + $defaultValueRaw = parent::defaultValueRaw(); + + $defaultValueRaw['(now())'][2] = new Expression('now()'); + + $defaultValueRaw[] = [ColumnType::TEXT, '(NULL)', null]; + $defaultValueRaw[] = [ColumnType::TEXT, "(('str''ing'))", "str'ing"]; + $defaultValueRaw[] = [ColumnType::INTEGER, '((-1))', -1]; + $defaultValueRaw[] = [ColumnType::TIMESTAMP, '((now()))', new Expression('(now())')]; + + return $defaultValueRaw; + } } diff --git a/tests/Provider/Type/BinaryProvider.php b/tests/Provider/Type/BinaryProvider.php index a0968ddd..56e966d1 100644 --- a/tests/Provider/Type/BinaryProvider.php +++ b/tests/Provider/Type/BinaryProvider.php @@ -4,13 +4,15 @@ namespace Yiisoft\Db\Mssql\Tests\Provider\Type; +use Yiisoft\Db\Expression\Expression; + final class BinaryProvider { public static function columns(): array { return [ - ['Mybinary1', 'binary', 'mixed', 10, 'CONVERT([binary](10),\'binary\')'], - ['Mybinary2', 'binary', 'mixed', 1, 'CONVERT([binary](1),\'b\')'], + ['Mybinary1', 'binary', 'mixed', 10, new Expression("CONVERT([binary](10),'binary')")], + ['Mybinary2', 'binary', 'mixed', 1, new Expression("CONVERT([binary](1),'b')")], ]; } } diff --git a/tests/Provider/Type/GeometryProvider.php b/tests/Provider/Type/GeometryProvider.php index dbd62169..fcc6da5d 100644 --- a/tests/Provider/Type/GeometryProvider.php +++ b/tests/Provider/Type/GeometryProvider.php @@ -4,12 +4,14 @@ namespace Yiisoft\Db\Mssql\Tests\Provider\Type; +use Yiisoft\Db\Expression\Expression; + final class GeometryProvider { public static function columns(): array { return [ - ['Mygeometry1', 'geometry', 'string', '[geometry]::STGeomFromText(\'POINT(0 0)\',(0))'], + ['Mygeometry1', 'geometry', 'string', new Expression("[geometry]::STGeomFromText('POINT(0 0)',(0))")], ['Mygeometry2', 'geometry', 'string', null], ]; } diff --git a/tests/Provider/Type/VarBinaryProvider.php b/tests/Provider/Type/VarBinaryProvider.php index 1b150926..7a7024d3 100644 --- a/tests/Provider/Type/VarBinaryProvider.php +++ b/tests/Provider/Type/VarBinaryProvider.php @@ -4,14 +4,16 @@ namespace Yiisoft\Db\Mssql\Tests\Provider\Type; +use Yiisoft\Db\Expression\Expression; + final class VarBinaryProvider { public static function columns(): array { return [ - ['Myvarbinary1', 'varbinary', 'mixed', 10, 'CONVERT([varbinary](10),\'varbinary\')'], - ['Myvarbinary2', 'varbinary', 'mixed', 100, 'CONVERT([varbinary](100),\'v\')'], - ['Myvarbinary3', 'varbinary', 'mixed', 20, 'hashbytes(\'MD5\',\'test string\')'], + ['Myvarbinary1', 'varbinary', 'mixed', 10, new Expression("CONVERT([varbinary](10),'varbinary')")], + ['Myvarbinary2', 'varbinary', 'mixed', 100, new Expression("CONVERT([varbinary](100),'v')")], + ['Myvarbinary3', 'varbinary', 'mixed', 20, new Expression("hashbytes('MD5','test string')")], ]; } } diff --git a/tests/Provider/Type/VarCharProvider.php b/tests/Provider/Type/VarCharProvider.php index 69238063..1ed0cf24 100644 --- a/tests/Provider/Type/VarCharProvider.php +++ b/tests/Provider/Type/VarCharProvider.php @@ -4,6 +4,8 @@ namespace Yiisoft\Db\Mssql\Tests\Provider\Type; +use Yiisoft\Db\Expression\Expression; + final class VarCharProvider { public static function columns(): array @@ -11,7 +13,7 @@ public static function columns(): array return [ ['Myvarchar1', 'varchar', 'string', 10, 'varchar'], ['Myvarchar2', 'varchar', 'string', 100, 'v'], - ['Myvarchar3', 'varchar', 'string', 20, 'TRY_CAST(datepart(year,getdate()) AS [varchar](20))'], + ['Myvarchar3', 'varchar', 'string', 20, new Expression('TRY_CAST(datepart(year,getdate()) AS [varchar](20))')], ]; } } diff --git a/tests/QueryBuilderTest.php b/tests/QueryBuilderTest.php index f079658a..273895e0 100644 --- a/tests/QueryBuilderTest.php +++ b/tests/QueryBuilderTest.php @@ -871,7 +871,7 @@ public function testAlterColumnOnDb(): void $db->createCommand($sql)->execute(); $schema = $db->getTableSchema('[foo1]', true); $this->assertSame(ColumnType::DATETIME, $schema?->getColumn('bar')->getDbType()); - $this->assertSame('getdate()', $schema?->getColumn('bar')->getDefaultValue()); + $this->assertEquals(new Expression('getdate()'), $schema?->getColumn('bar')->getDefaultValue()); } /** diff --git a/tests/Type/BinaryTest.php b/tests/Type/BinaryTest.php index 583112aa..b27bec73 100644 --- a/tests/Type/BinaryTest.php +++ b/tests/Type/BinaryTest.php @@ -39,7 +39,7 @@ public function testCreateTableWithDefaultValue( string $dbType, string $phpType, int $size, - string $defaultValue + Expression $defaultValue ): void { $db = $this->buildTable(); @@ -48,7 +48,7 @@ public function testCreateTableWithDefaultValue( $this->assertSame($dbType, $tableSchema?->getColumn($column)->getDbType()); $this->assertSame($phpType, $tableSchema?->getColumn($column)->getPhpType()); $this->assertSame($size, $tableSchema?->getColumn($column)->getSize()); - $this->assertSame($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); + $this->assertEquals($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); $db->createCommand()->dropTable('binary_default')->execute(); } @@ -93,7 +93,7 @@ public function testDefaultValue( string $dbType, string $phpType, int $size, - string $defaultValue + Expression $defaultValue ): void { $this->setFixture('Type/binary.sql'); @@ -103,7 +103,7 @@ public function testDefaultValue( $this->assertSame($dbType, $tableSchema?->getColumn($column)->getDbType()); $this->assertSame($phpType, $tableSchema?->getColumn($column)->getPhpType()); $this->assertSame($size, $tableSchema?->getColumn($column)->getSize()); - $this->assertSame($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); + $this->assertEquals($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); $db->createCommand()->dropTable('binary_default')->execute(); } diff --git a/tests/Type/GeometryTest.php b/tests/Type/GeometryTest.php index bd4bab11..1a8b1df6 100644 --- a/tests/Type/GeometryTest.php +++ b/tests/Type/GeometryTest.php @@ -38,7 +38,7 @@ public function testCreateTableWithDefaultValue( string $column, string $dbType, string $phpType, - string|null $defaultValue + Expression|null $defaultValue ): void { $db = $this->buildTable(); @@ -46,7 +46,7 @@ public function testCreateTableWithDefaultValue( $this->assertSame($dbType, $tableSchema?->getColumn($column)->getDbType()); $this->assertSame($phpType, $tableSchema?->getColumn($column)->getPhpType()); - $this->assertSame($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); + $this->assertEquals($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); $db->createCommand()->dropTable('geometry_default')->execute(); } @@ -90,7 +90,7 @@ public function testDefaultValue( string $column, string $dbType, string $phpType, - string|null $defaultValue + Expression|null $defaultValue ): void { $this->setFixture('Type/geometry.sql'); @@ -99,7 +99,7 @@ public function testDefaultValue( $this->assertSame($dbType, $tableSchema?->getColumn($column)->getDbType()); $this->assertSame($phpType, $tableSchema?->getColumn($column)->getPhpType()); - $this->assertSame($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); + $this->assertEquals($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); $db->createCommand()->dropTable('geometry_default')->execute(); } diff --git a/tests/Type/VarBinaryTest.php b/tests/Type/VarBinaryTest.php index a185badf..2390015e 100644 --- a/tests/Type/VarBinaryTest.php +++ b/tests/Type/VarBinaryTest.php @@ -41,7 +41,7 @@ public function testCreateTableWithDefaultValue( string $dbType, string $phpType, int $size, - string $defaultValue + Expression $defaultValue ): void { $db = $this->buildTable(); @@ -50,7 +50,7 @@ public function testCreateTableWithDefaultValue( $this->assertSame($dbType, $tableSchema?->getColumn($column)->getDbType()); $this->assertSame($phpType, $tableSchema?->getColumn($column)->getPhpType()); $this->assertSame($size, $tableSchema?->getColumn($column)->getSize()); - $this->assertSame($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); + $this->assertEquals($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); $db->createCommand()->dropTable('varbinary_default')->execute(); } @@ -95,7 +95,7 @@ public function testDefaultValue( string $dbType, string $phpType, int $size, - string $defaultValue + Expression $defaultValue ): void { $this->setFixture('Type/varbinary.sql'); @@ -105,7 +105,7 @@ public function testDefaultValue( $this->assertSame($dbType, $tableSchema?->getColumn($column)->getDbType()); $this->assertSame($phpType, $tableSchema?->getColumn($column)->getPhpType()); $this->assertSame($size, $tableSchema?->getColumn($column)->getSize()); - $this->assertSame($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); + $this->assertEquals($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); $db->createCommand()->dropTable('varbinary_default')->execute(); } diff --git a/tests/Type/VarCharTest.php b/tests/Type/VarCharTest.php index ff81fec8..78fc4dc2 100644 --- a/tests/Type/VarCharTest.php +++ b/tests/Type/VarCharTest.php @@ -11,6 +11,7 @@ use Yiisoft\Db\Exception\InvalidArgumentException; use Yiisoft\Db\Exception\InvalidConfigException; use Yiisoft\Db\Exception\NotSupportedException; +use Yiisoft\Db\Expression\Expression; use Yiisoft\Db\Mssql\Tests\Support\TestTrait; /** @@ -38,7 +39,7 @@ public function testCreateTableWithDefaultValue( string $dbType, string $phpType, int $size, - string $defaultValue + string|Expression $defaultValue ): void { $db = $this->buildTable(); @@ -47,7 +48,7 @@ public function testCreateTableWithDefaultValue( $this->assertSame($dbType, $tableSchema?->getColumn($column)->getDbType()); $this->assertSame($phpType, $tableSchema?->getColumn($column)->getPhpType()); $this->assertSame($size, $tableSchema?->getColumn($column)->getSize()); - $this->assertSame($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); + $this->assertEquals($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); $db->createCommand()->dropTable('varchar_default')->execute(); } @@ -92,7 +93,7 @@ public function testDefaultValue( string $dbType, string $phpType, int $size, - string $defaultValue + string|Expression $defaultValue ): void { $this->setFixture('Type/varchar.sql'); @@ -102,7 +103,7 @@ public function testDefaultValue( $this->assertSame($dbType, $tableSchema?->getColumn($column)->getDbType()); $this->assertSame($phpType, $tableSchema?->getColumn($column)->getPhpType()); $this->assertSame($size, $tableSchema?->getColumn($column)->getSize()); - $this->assertSame($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); + $this->assertEquals($defaultValue, $tableSchema?->getColumn($column)->getDefaultValue()); $db->createCommand()->dropTable('varchar_default')->execute(); }