From fa3f9a1a8204d570bd538d8c38e12178caf98d01 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Thu, 26 Oct 2023 20:52:03 +0700 Subject: [PATCH] Allow `ColumnInterface` as column type --- src/Command/AbstractCommand.php | 2 +- src/Command/CommandInterface.php | 7 ++++--- src/Debug/CommandInterfaceProxy.php | 2 +- src/QueryBuilder/AbstractDDLQueryBuilder.php | 4 ++-- src/QueryBuilder/AbstractQueryBuilder.php | 2 +- src/QueryBuilder/DDLQueryBuilderInterface.php | 5 +++-- tests/AbstractQueryBuilderTest.php | 15 +++++++++------ tests/Common/CommonCommandTest.php | 16 ++++++++++++---- tests/Db/Command/CommandTest.php | 19 +++++++++++++------ tests/Db/QueryBuilder/QueryBuilderTest.php | 3 ++- tests/Provider/CommandProvider.php | 9 +++++++++ tests/Provider/QueryBuilderProvider.php | 9 +++++++++ 12 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/Command/AbstractCommand.php b/src/Command/AbstractCommand.php index 479c1052e..6d573bdf0 100644 --- a/src/Command/AbstractCommand.php +++ b/src/Command/AbstractCommand.php @@ -132,7 +132,7 @@ public function addCheck(string $table, string $name, string $expression): stati return $this->setSql($sql)->requireTableSchemaRefresh($table); } - public function addColumn(string $table, string $column, string $type): static + public function addColumn(string $table, string $column, ColumnInterface|string $type): static { $sql = $this->getQueryBuilder()->addColumn($table, $column, $type); return $this->setSql($sql)->requireTableSchemaRefresh($table); diff --git a/src/Command/CommandInterface.php b/src/Command/CommandInterface.php index 955e28c3b..2ef67e7a0 100644 --- a/src/Command/CommandInterface.php +++ b/src/Command/CommandInterface.php @@ -39,13 +39,13 @@ public function addCheck(string $table, string $name, string $expression): stati * * @param string $table The name of the table to add new column to. * @param string $column The name of the new column. - * @param string $type The column type. {@see QueryBuilder::getColumnType()} will be called to convert the given - * column type to the database one. + * @param ColumnInterface|string $type The column type. {@see QueryBuilder::getColumnType()} will be called + * to convert the given column type to the database one. * For example, `string` will be converted to `varchar(255)`, and `string not null` becomes `varchar(255) not null`. * * Note: The method will quote the `table` and `column` parameters before using them in the generated SQL. */ - public function addColumn(string $table, string $column, string $type): static; + public function addColumn(string $table, string $column, ColumnInterface|string $type): static; /** * Builds an SQL command for adding a comment to a column. @@ -304,6 +304,7 @@ public function createIndex( * * @param string $table The name of the table to create. * @param array $columns The columns (name => definition) in the new table. + * The definition can be `string` or {@see ColumnInterface} instance. * @param string|null $options More SQL fragments to append to the generated SQL. * * @throws Exception diff --git a/src/Debug/CommandInterfaceProxy.php b/src/Debug/CommandInterfaceProxy.php index 2ca7773c7..6e95a0c85 100644 --- a/src/Debug/CommandInterfaceProxy.php +++ b/src/Debug/CommandInterfaceProxy.php @@ -30,7 +30,7 @@ public function addCheck(string $table, string $name, string $expression): stati /** * @psalm-suppress MixedArgument */ - public function addColumn(string $table, string $column, string $type): static + public function addColumn(string $table, string $column, ColumnInterface|string $type): static { return new self($this->decorated->{__FUNCTION__}(...func_get_args()), $this->collector); } diff --git a/src/QueryBuilder/AbstractDDLQueryBuilder.php b/src/QueryBuilder/AbstractDDLQueryBuilder.php index d73f57853..7aed605f0 100644 --- a/src/QueryBuilder/AbstractDDLQueryBuilder.php +++ b/src/QueryBuilder/AbstractDDLQueryBuilder.php @@ -39,7 +39,7 @@ public function addCheck(string $table, string $name, string $expression): strin . ' CHECK (' . $this->quoter->quoteSql($expression) . ')'; } - public function addColumn(string $table, string $column, string $type): string + public function addColumn(string $table, string $column, ColumnInterface|string $type): string { return 'ALTER TABLE ' . $this->quoter->quoteTableName($table) @@ -169,7 +169,7 @@ public function createTable(string $table, array $columns, string $options = nul { $cols = []; - /** @psalm-var string[] $columns */ + /** @psalm-var array|string[] $columns */ foreach ($columns as $name => $type) { if (is_string($name)) { $cols[] = "\t" diff --git a/src/QueryBuilder/AbstractQueryBuilder.php b/src/QueryBuilder/AbstractQueryBuilder.php index f93c13bc9..14945345b 100644 --- a/src/QueryBuilder/AbstractQueryBuilder.php +++ b/src/QueryBuilder/AbstractQueryBuilder.php @@ -54,7 +54,7 @@ public function addCheck(string $table, string $name, string $expression): strin return $this->ddlBuilder->addCheck($table, $name, $expression); } - public function addColumn(string $table, string $column, string $type): string + public function addColumn(string $table, string $column, ColumnInterface|string $type): string { return $this->ddlBuilder->addColumn($table, $column, $type); } diff --git a/src/QueryBuilder/DDLQueryBuilderInterface.php b/src/QueryBuilder/DDLQueryBuilderInterface.php index 3018b5964..c5b9e5498 100644 --- a/src/QueryBuilder/DDLQueryBuilderInterface.php +++ b/src/QueryBuilder/DDLQueryBuilderInterface.php @@ -36,7 +36,7 @@ public function addCheck(string $table, string $name, string $expression): strin * * @param string $table The table to add the new column will to. * @param string $column The name of the new column. - * @param string $type The column type. + * @param ColumnInterface|string $type The column type. * {@see getColumnType()} Method will be invoked to convert an abstract column type (if any) into the physical one. * Anything that isn't recognized as an abstract type will be kept in the generated SQL. * For example, 'string' will be turned into 'varchar(255)', while 'string not null' will become @@ -46,7 +46,7 @@ public function addCheck(string $table, string $name, string $expression): strin * * Note: The method will quote the `table` and `column` parameters before using them in the generated SQL. */ - public function addColumn(string $table, string $column, string $type): string; + public function addColumn(string $table, string $column, ColumnInterface|string $type): string; /** * Builds an SQL command for adding comment to column. @@ -233,6 +233,7 @@ public function createIndex( * * @param string $table The name of the table to create. * @param array $columns The columns (name => definition) in the new table. + * The definition can be `string` or {@see ColumnInterface} instance. * @param string|null $options More SQL fragments to append to the generated SQL. * * @return string The SQL statement for creating a new DB table. diff --git a/tests/AbstractQueryBuilderTest.php b/tests/AbstractQueryBuilderTest.php index 31de64c71..0f1263cf0 100644 --- a/tests/AbstractQueryBuilderTest.php +++ b/tests/AbstractQueryBuilderTest.php @@ -22,6 +22,7 @@ use Yiisoft\Db\Query\Query; use Yiisoft\Db\Query\QueryInterface; use Yiisoft\Db\QueryBuilder\Condition\SimpleCondition; +use Yiisoft\Db\Schema\Builder\ColumnInterface; use Yiisoft\Db\Schema\QuoterInterface; use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Tests\Support\Assert; @@ -53,18 +54,19 @@ public function testAddCheck(): void ); } - public function testAddColumn(): void + /** @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::columnTypes */ + public function testAddColumn(ColumnInterface|string $type): void { $db = $this->getConnection(); $qb = $db->getQueryBuilder(); - $sql = $qb->addColumn('table', 'column', SchemaInterface::TYPE_STRING); + $sql = $qb->addColumn('table', 'column', $type); $this->assertSame( DbHelper::replaceQuotes( <<getColumnType(SchemaInterface::TYPE_STRING), + SQL . ' ' . $qb->getColumnType($type), $db->getDriverName(), ), $sql, @@ -185,18 +187,19 @@ public function testAddUnique(string $name, string $table, array|string $columns $this->assertSame($expected, $sql); } - public function testAlterColumn(): void + /** @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::columnTypes */ + public function testAlterColumn(ColumnInterface|string $type): void { $db = $this->getConnection(); $qb = $db->getQueryBuilder(); - $sql = $qb->alterColumn('customer', 'email', SchemaInterface::TYPE_STRING); + $sql = $qb->alterColumn('customer', 'email', $type); $this->assertSame( DbHelper::replaceQuotes( <<getColumnType(SchemaInterface::TYPE_STRING), + SQL . ' ' . $qb->getColumnType($type), $db->getDriverName(), ), $sql, diff --git a/tests/Common/CommonCommandTest.php b/tests/Common/CommonCommandTest.php index 220b60786..06372ddba 100644 --- a/tests/Common/CommonCommandTest.php +++ b/tests/Common/CommonCommandTest.php @@ -24,6 +24,7 @@ use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Tests\AbstractCommandTest; use Yiisoft\Db\Tests\Support\Assert; +use Yiisoft\Db\Tests\Support\Stub\Column; use Yiisoft\Db\Transaction\TransactionInterface; use function call_user_func_array; @@ -544,16 +545,23 @@ public function testCreateTable(): void $command->createTable( '{{testCreateTable}}', - ['[[id]]' => SchemaInterface::TYPE_PK, '[[bar]]' => SchemaInterface::TYPE_INTEGER], + [ + '[[id]]' => SchemaInterface::TYPE_PK, + '[[bar]]' => SchemaInterface::TYPE_INTEGER, + '[[name]]' => (new Column('string(100)'))->notNull(), + ], )->execute(); - $command->insert('{{testCreateTable}}', ['[[bar]]' => 1])->execute(); + $command->insert('{{testCreateTable}}', ['[[bar]]' => 1, '[[name]]' => 'Lilo'])->execute(); $records = $command->setSql( <<queryAll(); - $this->assertEquals([['id' => 1, 'bar' => 1]], $records); + $nameCol = $schema->getTableSchema('{{testCreateTable}}', true)->getColumn('name'); + + $this->assertFalse($nameCol->isAllowNull()); + $this->assertEquals([['id' => 1, 'bar' => 1, 'name' => 'Lilo']], $records); $db->close(); } diff --git a/tests/Db/Command/CommandTest.php b/tests/Db/Command/CommandTest.php index d361a9ab8..bbe23a985 100644 --- a/tests/Db/Command/CommandTest.php +++ b/tests/Db/Command/CommandTest.php @@ -5,6 +5,7 @@ namespace Yiisoft\Db\Tests\Db\Command; use Yiisoft\Db\Exception\NotSupportedException; +use Yiisoft\Db\Schema\Builder\ColumnInterface; use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Tests\AbstractCommandTest; use Yiisoft\Db\Tests\Support\Assert; @@ -39,17 +40,20 @@ public function testAddCheck(): void ); } - public function testAddColumn(): void + /** @dataProvider \Yiisoft\Db\Tests\Provider\CommandProvider::columnTypes */ + public function testAddColumn(ColumnInterface|string $type): void { $db = $this->getConnection(); $command = $db->createCommand(); - $sql = $command->addColumn('table', 'column', SchemaInterface::TYPE_INTEGER)->getSql(); + $sql = $command->addColumn('table', 'column', $type)->getSql(); + + $type = $db->getQueryBuilder()->getColumnType($type); $this->assertSame( DbHelper::replaceQuotes( <<getDriverName(), ), @@ -154,17 +158,20 @@ public function testAddUniqueSql(string $name, string $tableName, array|string $ $this->assertSame($expected, $sql); } - public function testAlterColumn(): void + /** @dataProvider \Yiisoft\Db\Tests\Provider\CommandProvider::columnTypes */ + public function testAlterColumn(ColumnInterface|string $type): void { $db = $this->getConnection(); $command = $db->createCommand(); - $sql = $command->alterColumn('table', 'column', SchemaInterface::TYPE_INTEGER)->getSql(); + $sql = $command->alterColumn('table', 'column', $type)->getSql(); + + $type = $db->getQueryBuilder()->getColumnType($type); $this->assertSame( DbHelper::replaceQuotes( <<getDriverName(), ), diff --git a/tests/Db/QueryBuilder/QueryBuilderTest.php b/tests/Db/QueryBuilder/QueryBuilderTest.php index 79a1e382b..ffd91fdfa 100644 --- a/tests/Db/QueryBuilder/QueryBuilderTest.php +++ b/tests/Db/QueryBuilder/QueryBuilderTest.php @@ -15,6 +15,7 @@ use Yiisoft\Db\Query\QueryInterface; use Yiisoft\Db\Tests\AbstractQueryBuilderTest; use Yiisoft\Db\Tests\Support\DbHelper; +use Yiisoft\Db\Tests\Support\Stub\Column; use Yiisoft\Db\Tests\Support\Stub\QueryBuilder; use Yiisoft\Db\Tests\Support\Stub\Schema; use Yiisoft\Db\Tests\Support\TestTrait; @@ -116,7 +117,7 @@ public function testCreateTable(): void [ 'id' => 'pk', 'name' => 'string(255) NOT NULL', - 'email' => 'string(255) NOT NULL', + 'email' => (new Column('string(255)'))->notNull(), 'status' => 'integer NOT NULL', 'created_at' => 'datetime NOT NULL', 'UNIQUE test_email_unique (email)', diff --git a/tests/Provider/CommandProvider.php b/tests/Provider/CommandProvider.php index 7f6999d80..3297ea2ac 100644 --- a/tests/Provider/CommandProvider.php +++ b/tests/Provider/CommandProvider.php @@ -8,6 +8,7 @@ use Yiisoft\Db\Query\Query; use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Tests\Support\DbHelper; +use Yiisoft\Db\Tests\Support\Stub\Column; use Yiisoft\Db\Tests\Support\TestTrait; class CommandProvider @@ -763,4 +764,12 @@ public static function upsert(): array ], ]; } + + public static function columnTypes(): array + { + return [ + [SchemaInterface::TYPE_INTEGER], + [new Column('string(100)')], + ]; + } } diff --git a/tests/Provider/QueryBuilderProvider.php b/tests/Provider/QueryBuilderProvider.php index 0871a113b..9db09bdfd 100644 --- a/tests/Provider/QueryBuilderProvider.php +++ b/tests/Provider/QueryBuilderProvider.php @@ -12,6 +12,7 @@ use Yiisoft\Db\QueryBuilder\QueryBuilderInterface; use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Tests\Support\DbHelper; +use Yiisoft\Db\Tests\Support\Stub\Column; use Yiisoft\Db\Tests\Support\TestTrait; use Yiisoft\Db\Tests\Support\TraversableObject; @@ -1242,4 +1243,12 @@ public static function cteAliases(): array 'expression' => [new Expression('a(b,c,d)'), 'a(b,c,d)'], ]; } + + public static function columnTypes(): array + { + return [ + [SchemaInterface::TYPE_STRING], + [new Column('string(100)')], + ]; + } }