From 9e3d461f71ea587745552e1641fa5631c2938919 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Fri, 8 Nov 2024 08:23:53 +0700 Subject: [PATCH] Use new column definition builder --- psalm.xml | 1 + src/Column.php | 5 + src/Column/ColumnDefinitionBuilder.php | 7 + src/DDLQueryBuilder.php | 66 ++--- src/Schema.php | 6 +- tests/ColumnSchemaBuilderTest.php | 8 - .../Provider/ColumnSchemaBuilderProvider.php | 29 -- tests/Provider/QueryBuilderProvider.php | 194 +++++++++++++ tests/QueryBuilderTest.php | 259 ++---------------- 9 files changed, 262 insertions(+), 313 deletions(-) delete mode 100644 tests/Provider/ColumnSchemaBuilderProvider.php diff --git a/psalm.xml b/psalm.xml index 5001d0a76..fc5771199 100644 --- a/psalm.xml +++ b/psalm.xml @@ -15,6 +15,7 @@ + diff --git a/src/Column.php b/src/Column.php index 1ce3b73ef..d408ec7e3 100644 --- a/src/Column.php +++ b/src/Column.php @@ -6,6 +6,7 @@ use Yiisoft\Db\Expression\Expression; use Yiisoft\Db\Schema\Builder\AbstractColumn; +use Yiisoft\Db\Schema\Column\StringColumnSchema; /** * Provides a convenient way to create column schema for use with {@see Schema} for MSSQL Server. @@ -21,6 +22,10 @@ * * Provides a fluent interface, which means that the methods can be chained together to create a column schema with * many properties in a single line of code. + * + * @psalm-suppress DeprecatedClass + * + * @deprecated Use {@see StringColumnSchema} or other column classes instead. Will be removed in 2.0.0. */ final class Column extends AbstractColumn { diff --git a/src/Column/ColumnDefinitionBuilder.php b/src/Column/ColumnDefinitionBuilder.php index 82698f69b..737bc1613 100644 --- a/src/Column/ColumnDefinitionBuilder.php +++ b/src/Column/ColumnDefinitionBuilder.php @@ -49,6 +49,13 @@ public function build(ColumnSchemaInterface $column): string . $this->buildExtra($column); } + public function buildAlter(ColumnSchemaInterface $column): string + { + return $this->buildType($column) + . $this->buildNotNull($column) + . $this->buildExtra($column); + } + protected function getDbType(ColumnSchemaInterface $column): string { $size = $column->getSize(); diff --git a/src/DDLQueryBuilder.php b/src/DDLQueryBuilder.php index a9f2685fb..87b9ee3af 100644 --- a/src/DDLQueryBuilder.php +++ b/src/DDLQueryBuilder.php @@ -8,11 +8,13 @@ use Throwable; use Yiisoft\Db\Exception\InvalidArgumentException; use Yiisoft\Db\Exception\NotSupportedException; -use Yiisoft\Db\Expression\Expression; use Yiisoft\Db\QueryBuilder\AbstractDDLQueryBuilder; use Yiisoft\Db\Schema\Builder\ColumnInterface; +use Yiisoft\Db\Schema\Column\ColumnSchemaInterface; use function array_diff; +use function implode; +use function preg_replace; /** * Implements a (Data Definition Language) SQL statements for MSSQL Server. @@ -51,45 +53,45 @@ public function addDefaultValue(string $table, string $name, string $column, mix /** * @throws Exception */ - public function alterColumn(string $table, string $column, ColumnInterface|string $type): string + public function alterColumn(string $table, string $column, ColumnInterface|ColumnSchemaInterface|string $type): string { - $sqlAfter = []; $columnName = $this->quoter->quoteColumnName($column); $tableName = $this->quoter->quoteTableName($table); - $constraintBase = preg_replace('/[^a-z0-9_]/i', '', $table . '_' . $column); + $constraintBase = preg_replace('/\W/', '', $table . '_' . $column); if ($type instanceof ColumnInterface) { - $type->setFormat('{type}{length}{notnull}{append}'); - - /** @psalm-var mixed $defaultValue */ - $defaultValue = $type->getDefault(); - if ($defaultValue !== null || $type->isNotNull() === false) { - $sqlAfter[] = $this->addDefaultValue( - $table, - "DF_{$constraintBase}", - $column, - $defaultValue instanceof Expression ? $defaultValue : new Expression((string)$defaultValue) - ); - } - - $checkValue = $type->getCheck(); - if ($checkValue !== null) { - $sqlAfter[] = "ALTER TABLE {$tableName} ADD CONSTRAINT " . - $this->quoter->quoteColumnName("CK_{$constraintBase}") . - ' CHECK (' . ($defaultValue instanceof Expression ? $checkValue : new Expression($checkValue)) . ')'; - } - - if ($type->isUnique()) { - $sqlAfter[] = "ALTER TABLE {$tableName} ADD CONSTRAINT " . $this->quoter->quoteColumnName("UQ_{$constraintBase}") . " UNIQUE ({$columnName})"; - } + $type = $type->asString(); } - /** @psalm-suppress DeprecatedMethod */ - return implode("\n", [ + if (is_string($type)) { + $type = $this->schema->getColumnFactory()->fromDefinition($type); + } + + $columnDefinitionBuilder = $this->queryBuilder->getColumnDefinitionBuilder(); + $statements = [ $this->dropConstraintsForColumn($table, $column, 'D'), - "ALTER TABLE $tableName ALTER COLUMN $columnName {$this->queryBuilder->getColumnType($type)}", - ...$sqlAfter, - ]); + "ALTER TABLE $tableName ALTER COLUMN $columnName " . $columnDefinitionBuilder->buildAlter($type), + ]; + + if ($type->hasDefaultValue()) { + $defaultValue = $type->dbTypecast($type->getDefaultValue()); + $statements[] = $this->addDefaultValue($table, "DF_$constraintBase", $column, $defaultValue); + } + + $checkValue = $type->getCheck(); + if (!empty($checkValue)) { + $statements[] = "ALTER TABLE $tableName ADD CONSTRAINT " + . $this->quoter->quoteColumnName("CK_$constraintBase") + . " CHECK ($checkValue)"; + } + + if ($type->isUnique()) { + $statements[] = "ALTER TABLE $tableName ADD CONSTRAINT " + . $this->quoter->quoteColumnName("UQ_$constraintBase") + . " UNIQUE ($columnName)"; + } + + return implode("\n", $statements); } /** diff --git a/src/Schema.php b/src/Schema.php index 06bc0686a..53e1e77a1 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -71,6 +71,7 @@ final class Schema extends AbstractPdoSchema /** @deprecated Use {@see ColumnBuilder} instead. Will be removed in 2.0. */ public function createColumn(string $type, array|int|string|null $length = null): ColumnInterface { + /** @psalm-suppress DeprecatedClass */ return new Column($type, $length); } @@ -229,7 +230,6 @@ protected function loadTableSchema(string $name): TableSchemaInterface|null */ protected function loadTablePrimaryKey(string $tableName): Constraint|null { - /** @psalm-var mixed $tablePrimaryKey */ $tablePrimaryKey = $this->loadTableConstraints($tableName, self::PRIMARY_KEY); return $tablePrimaryKey instanceof Constraint ? $tablePrimaryKey : null; } @@ -247,7 +247,6 @@ protected function loadTablePrimaryKey(string $tableName): Constraint|null */ protected function loadTableForeignKeys(string $tableName): array { - /** @psalm-var mixed $tableForeignKeys */ $tableForeignKeys = $this->loadTableConstraints($tableName, self::FOREIGN_KEYS); return is_array($tableForeignKeys) ? $tableForeignKeys : []; } @@ -320,7 +319,6 @@ protected function loadTableIndexes(string $tableName): array */ protected function loadTableUniques(string $tableName): array { - /** @psalm-var mixed $tableUniques */ $tableUniques = $this->loadTableConstraints($tableName, self::UNIQUES); return is_array($tableUniques) ? $tableUniques : []; } @@ -338,7 +336,6 @@ protected function loadTableUniques(string $tableName): array */ protected function loadTableChecks(string $tableName): array { - /** @psalm-var mixed $tableCheck */ $tableCheck = $this->loadTableConstraints($tableName, self::CHECKS); return is_array($tableCheck) ? $tableCheck : []; } @@ -356,7 +353,6 @@ protected function loadTableChecks(string $tableName): array */ protected function loadTableDefaultValues(string $tableName): array { - /** @psalm-var mixed $tableDefault */ $tableDefault = $this->loadTableConstraints($tableName, self::DEFAULTS); return is_array($tableDefault) ? $tableDefault : []; } diff --git a/tests/ColumnSchemaBuilderTest.php b/tests/ColumnSchemaBuilderTest.php index fe1c5a0ea..da490b0d7 100644 --- a/tests/ColumnSchemaBuilderTest.php +++ b/tests/ColumnSchemaBuilderTest.php @@ -15,12 +15,4 @@ final class ColumnSchemaBuilderTest extends CommonColumnSchemaBuilderTest { use TestTrait; - - /** - * @dataProvider \Yiisoft\Db\Mssql\Tests\Provider\ColumnSchemaBuilderProvider::createColumnTypes() - */ - public function testCreateColumnTypes(string $expected, string $type, ?int $length, array $calls): void - { - parent::testCreateColumnTypes($expected, $type, $length, $calls); - } } diff --git a/tests/Provider/ColumnSchemaBuilderProvider.php b/tests/Provider/ColumnSchemaBuilderProvider.php deleted file mode 100644 index 5f7b2d184..000000000 --- a/tests/Provider/ColumnSchemaBuilderProvider.php +++ /dev/null @@ -1,29 +0,0 @@ - '[\\]', ]; + public static function alterColumn(): array + { + return [ + [ + 'varchar(255)', + <<notNull(), + <<check('LEN(bar) > 5'), + << 5) + SQL, + ], [ + ColumnBuilder::string()->defaultValue(''), + <<defaultValue('AbCdE'), + <<defaultValue(new Expression('CURRENT_TIMESTAMP')), + <<unique(), + <<assertSame($testData, $resultData['blob_col']); } - /** - * @throws Exception - * @throws InvalidConfigException - */ - public function testAlterColumn(): void + #[DataProviderExternal(QueryBuilderProvider::class, 'alterColumn')] + public function testAlterColumn(string|ColumnSchemaInterface $type, string $expected): void { - $db = $this->getConnection(true); - - $qb = $db->getQueryBuilder(); - - $expected = <<alterColumn('foo1', 'bar', 'varchar(255)'); - $this->assertEquals($expected, $sql); - - $expected = <<alterColumn( - 'foo1', - 'bar', - (new Column(ColumnType::STRING, 255))->notNull() - ); - $this->assertEquals($expected, $sql); - - $expected = << 5) - SQL; - $sql = $qb->alterColumn( - 'foo1', - 'bar', - (new Column(ColumnType::STRING, 255))->check('LEN(bar) > 5') - ); - $this->assertEquals($expected, $sql); - - $expected = <<alterColumn( - 'foo1', - 'bar', - (new Column(ColumnType::STRING, 255))->defaultValue('') - ); - $this->assertEquals($expected, $sql); - - $expected = <<alterColumn( - 'foo1', - 'bar', - (new Column(ColumnType::STRING, 255))->defaultValue('AbCdE') - ); - $this->assertEquals($expected, $sql); - - $expected = <<alterColumn( - 'foo1', - 'bar', - (new Column(ColumnType::TIMESTAMP))->defaultExpression('CURRENT_TIMESTAMP') - ); - $this->assertEquals($expected, $sql); - - $expected = <<alterColumn( - 'foo1', - 'bar', - (new Column(ColumnType::STRING, 30))->unique() - ); - $this->assertEquals($expected, $sql); + parent::testAlterColumn($type, $expected); } /** @@ -856,7 +637,7 @@ public function testAlterColumnOnDb(): void $sql = $db->getQueryBuilder()->alterColumn( 'foo1', 'bar', - (new Column(ColumnType::STRING, 128))->notNull() + ColumnBuilder::string(128)->notNull() ); $db->createCommand($sql)->execute(); $schema = $db->getTableSchema('[foo1]', true); @@ -868,11 +649,11 @@ public function testAlterColumnOnDb(): void $sql = $db->getQueryBuilder()->alterColumn( 'foo1', 'bar', - (new Column(ColumnType::TIMESTAMP))->defaultExpression('CURRENT_TIMESTAMP') + ColumnBuilder::timestamp()->defaultValue(new Expression('CURRENT_TIMESTAMP')) ); $db->createCommand($sql)->execute(); $schema = $db->getTableSchema('[foo1]', true); - $this->assertSame(ColumnType::DATETIME, $schema?->getColumn('bar')->getDbType()); + $this->assertSame('datetime2', $schema?->getColumn('bar')->getDbType()); $this->assertEquals(new Expression('getdate()'), $schema?->getColumn('bar')->getDefaultValue()); } @@ -888,7 +669,7 @@ public function testAlterColumnWithCheckConstraintOnDb(): void $sql = $db->getQueryBuilder()->alterColumn( 'foo1', 'bar', - (new Column(ColumnType::STRING, 128))->null()->check('LEN(bar) > 5') + ColumnBuilder::string(128)->null()->check('LEN(bar) > 5') ); $db->createCommand($sql)->execute(); $schema = $db->getTableSchema('[foo1]', true); @@ -912,7 +693,7 @@ public function testAlterColumnWithCheckConstraintOnDbWithException(): void $sql = $db->getQueryBuilder()->alterColumn( 'foo1', 'bar', - (new Column(ColumnType::STRING, 64))->check('LEN(bar) > 5') + ColumnBuilder::string(64)->check('LEN(bar) > 5') ); $db->createCommand($sql)->execute(); @@ -933,7 +714,7 @@ public function testAlterColumnWithUniqueConstraintOnDbWithException(): void $sql = $db->getQueryBuilder()->alterColumn( 'foo1', 'bar', - (new Column(ColumnType::STRING, 64))->unique() + ColumnBuilder::string(64)->unique() ); $db->createCommand($sql)->execute(); @@ -1017,7 +798,7 @@ public function testDropColumnOnDb(): void $sql = $db->getQueryBuilder()->alterColumn( 'foo1', 'bar', - (new Column(ColumnType::STRING, 64)) + ColumnBuilder::string(64) ->defaultValue('') ->check('LEN(bar) < 5') ->unique() @@ -1067,7 +848,7 @@ public function testAlterColumnWithNull(): void $sql = $qb->alterColumn( 'foo1', 'bar', - (new Column(ColumnType::INTEGER))->null()->defaultValue(null) + ColumnBuilder::integer()->null()->defaultValue(null) ); $this->assertEquals($expected, $sql); @@ -1093,13 +874,13 @@ public function testAlterColumnWithNull(): void IF @constraintName IS NULL BREAK EXEC (N'ALTER TABLE ' + @tableName + ' DROP CONSTRAINT [' + @constraintName + ']') END - ALTER TABLE [foo1] ALTER COLUMN [bar] int NULL + ALTER TABLE [foo1] ALTER COLUMN [bar] int ALTER TABLE [foo1] ADD CONSTRAINT [DF_foo1_bar] DEFAULT NULL FOR [bar] SQL; $sql = $qb->alterColumn( 'foo1', 'bar', - (new Column(ColumnType::INTEGER))->defaultValue(null) + ColumnBuilder::integer()->defaultValue(null) ); $this->assertEquals($expected, $sql); } @@ -1140,7 +921,7 @@ public function testAlterColumnWithExpression(): void $sql = $qb->alterColumn( 'foo1', 'bar', - (new Column(ColumnType::INTEGER)) + ColumnBuilder::integer() ->null() ->defaultValue(new Expression('CAST(GETDATE() AS INT)')) );