From 9433a34d3bcd8e7fd38ae42d561c2b337a984f41 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Mon, 7 Oct 2024 12:48:04 +0700 Subject: [PATCH 1/6] Add `ColumnDefinitionBuilder` --- src/Column/ColumnDefinitionBuilder.php | 104 ++++++++++++++++++++++++ src/Column/ColumnFactory.php | 2 +- src/Connection.php | 7 -- src/QueryBuilder.php | 5 +- src/Schema.php | 11 ++- tests/ConnectionTest.php | 8 -- tests/Provider/QueryBuilderProvider.php | 39 +++++++++ tests/QueryBuilderTest.php | 7 ++ tests/SchemaTest.php | 8 ++ 9 files changed, 173 insertions(+), 18 deletions(-) create mode 100644 src/Column/ColumnDefinitionBuilder.php diff --git a/src/Column/ColumnDefinitionBuilder.php b/src/Column/ColumnDefinitionBuilder.php new file mode 100644 index 00000000..e8d73f1d --- /dev/null +++ b/src/Column/ColumnDefinitionBuilder.php @@ -0,0 +1,104 @@ +getComment(); + + return $comment === null ? '' : ' COMMENT ' . (string) $this->queryBuilder->quoter()->quoteValue($comment); + } + + protected function getDbType(ColumnSchemaInterface $column): string + { + /** @psalm-suppress DocblockTypeContradiction */ + return match ($column->getType()) { + ColumnType::BOOLEAN => 'bit(1)', + ColumnType::BIT => 'bit', + ColumnType::TINYINT => 'tinyint', + ColumnType::SMALLINT => 'smallint', + ColumnType::INTEGER => 'int', + ColumnType::BIGINT => 'bigint', + ColumnType::FLOAT => 'float', + ColumnType::DOUBLE => 'double', + ColumnType::DECIMAL => 'decimal', + ColumnType::MONEY => 'decimal', + ColumnType::CHAR => 'char', + ColumnType::STRING => 'varchar', + ColumnType::TEXT => 'text', + ColumnType::BINARY => 'blob', + ColumnType::UUID => 'binary(16)', + ColumnType::DATETIME => 'datetime', + ColumnType::TIMESTAMP => 'timestamp', + ColumnType::DATE => 'date', + ColumnType::TIME => 'time', + ColumnType::ARRAY => 'json', + ColumnType::STRUCTURED => 'json', + ColumnType::JSON => 'json', + default => 'varchar', + }; + } +} diff --git a/src/Column/ColumnFactory.php b/src/Column/ColumnFactory.php index 087201e4..a4044fa5 100644 --- a/src/Column/ColumnFactory.php +++ b/src/Column/ColumnFactory.php @@ -31,12 +31,12 @@ final class ColumnFactory extends AbstractColumnFactory 'numeric' => ColumnType::DECIMAL, 'char' => ColumnType::CHAR, 'varchar' => ColumnType::STRING, - 'string' => ColumnType::STRING, 'enum' => ColumnType::STRING, 'tinytext' => ColumnType::TEXT, 'mediumtext' => ColumnType::TEXT, 'longtext' => ColumnType::TEXT, 'text' => ColumnType::TEXT, + 'binary' => ColumnType::BINARY, 'varbinary' => ColumnType::BINARY, 'blob' => ColumnType::BINARY, 'longblob' => ColumnType::BINARY, diff --git a/src/Connection.php b/src/Connection.php index 5a744781..380ba8f4 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -8,9 +8,7 @@ use Throwable; use Yiisoft\Db\Driver\Pdo\AbstractPdoConnection; use Yiisoft\Db\Driver\Pdo\PdoCommandInterface; -use Yiisoft\Db\Mysql\Column\ColumnFactory; use Yiisoft\Db\QueryBuilder\QueryBuilderInterface; -use Yiisoft\Db\Schema\Column\ColumnFactoryInterface; use Yiisoft\Db\Schema\QuoterInterface; use Yiisoft\Db\Schema\SchemaInterface; use Yiisoft\Db\Transaction\TransactionInterface; @@ -65,11 +63,6 @@ public function createTransaction(): TransactionInterface return new Transaction($this); } - public function getColumnFactory(): ColumnFactoryInterface - { - return new ColumnFactory(); - } - public function getQueryBuilder(): QueryBuilderInterface { if ($this->queryBuilder === null) { diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index 0176b966..95a2d20f 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -6,6 +6,7 @@ use Yiisoft\Db\Constant\ColumnType; use Yiisoft\Db\Constant\PseudoType; +use Yiisoft\Db\Mysql\Column\ColumnDefinitionBuilder; use Yiisoft\Db\QueryBuilder\AbstractQueryBuilder; use Yiisoft\Db\Schema\QuoterInterface; use Yiisoft\Db\Schema\SchemaInterface; @@ -52,6 +53,8 @@ public function __construct( $ddlBuilder = new DDLQueryBuilder($this, $quoter, $schema); $dmlBuilder = new DMLQueryBuilder($this, $quoter, $schema); $dqlBuilder = new DQLQueryBuilder($this, $quoter); - parent::__construct($quoter, $schema, $ddlBuilder, $dmlBuilder, $dqlBuilder); + $columnDefinitionBuilder = new ColumnDefinitionBuilder($this); + + parent::__construct($quoter, $schema, $ddlBuilder, $dmlBuilder, $dqlBuilder, $columnDefinitionBuilder); } } diff --git a/src/Schema.php b/src/Schema.php index 2a7c1a28..eac4de34 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -15,7 +15,10 @@ use Yiisoft\Db\Exception\NotSupportedException; use Yiisoft\Db\Expression\Expression; use Yiisoft\Db\Helper\DbArrayHelper; +use Yiisoft\Db\Mysql\Column\ColumnBuilder; +use Yiisoft\Db\Mysql\Column\ColumnFactory; use Yiisoft\Db\Schema\Builder\ColumnInterface; +use Yiisoft\Db\Schema\Column\ColumnFactoryInterface; use Yiisoft\Db\Schema\Column\ColumnSchemaInterface; use Yiisoft\Db\Schema\TableSchemaInterface; @@ -75,11 +78,17 @@ */ final class Schema extends AbstractPdoSchema { + /** @deprecated Use {@see ColumnBuilder} instead. Will be removed in 2.0. */ public function createColumn(string $type, array|int|string $length = null): ColumnInterface { return new Column($type, $length); } + public function getColumnFactory(): ColumnFactoryInterface + { + return new ColumnFactory(); + } + /** * Returns all unique indexes for the given table. * @@ -410,7 +419,7 @@ protected function getCreateTableSql(TableSchemaInterface $table): string */ private function loadColumnSchema(array $info): ColumnSchemaInterface { - $columnFactory = $this->db->getColumnFactory(); + $columnFactory = $this->getColumnFactory(); $dbType = $info['type']; /** @psalm-var ColumnInfoArray $info */ diff --git a/tests/ConnectionTest.php b/tests/ConnectionTest.php index e6792971..e8baa4ac 100644 --- a/tests/ConnectionTest.php +++ b/tests/ConnectionTest.php @@ -11,7 +11,6 @@ use Yiisoft\Db\Exception\IntegrityException; use Yiisoft\Db\Exception\InvalidConfigException; use Yiisoft\Db\Exception\NotSupportedException; -use Yiisoft\Db\Mysql\Column\ColumnFactory; use Yiisoft\Db\Mysql\Tests\Support\TestTrait; use Yiisoft\Db\Tests\Common\CommonConnectionTest; use Yiisoft\Db\Transaction\TransactionInterface; @@ -157,11 +156,4 @@ public function testNotRestartConnectionOnTimeoutInTransaction(): void $db->createCommand('SELECT 1')->queryScalar(); } - - public function testGetColumnFactory(): void - { - $db = $this->getConnection(); - - $this->assertInstanceOf(ColumnFactory::class, $db->getColumnFactory()); - } } diff --git a/tests/Provider/QueryBuilderProvider.php b/tests/Provider/QueryBuilderProvider.php index 0e5d6ee6..4ff3a4f4 100644 --- a/tests/Provider/QueryBuilderProvider.php +++ b/tests/Provider/QueryBuilderProvider.php @@ -4,8 +4,10 @@ namespace Yiisoft\Db\Mysql\Tests\Provider; +use Yiisoft\Db\Constant\PseudoType; use Yiisoft\Db\Expression\Expression; use Yiisoft\Db\Expression\JsonExpression; +use Yiisoft\Db\Mysql\Column\ColumnBuilder; use Yiisoft\Db\Mysql\Tests\Support\TestTrait; use Yiisoft\Db\Query\Query; @@ -174,4 +176,41 @@ public static function upsert(): array return $upsert; } + + public static function buildColumnDefinition(): array + { + $values = parent::buildColumnDefinition(); + + $values[PseudoType::PK][0] = 'int PRIMARY KEY AUTO_INCREMENT'; + $values[PseudoType::UPK][0] = 'int UNSIGNED PRIMARY KEY AUTO_INCREMENT'; + $values[PseudoType::BIGPK][0] = 'bigint PRIMARY KEY AUTO_INCREMENT'; + $values[PseudoType::UBIGPK][0] = 'bigint UNSIGNED PRIMARY KEY AUTO_INCREMENT'; + $values[PseudoType::UUID_PK][0] = 'binary(16) PRIMARY KEY DEFAULT uuid_to_bin(uuid())'; + $values[PseudoType::UUID_PK_SEQ][0] = 'binary(16) PRIMARY KEY DEFAULT uuid_to_bin(uuid())'; + $values['primaryKey()'][0] = 'int PRIMARY KEY AUTO_INCREMENT'; + $values['primaryKey(false)'][0] = 'int PRIMARY KEY'; + $values['smallPrimaryKey()'][0] = 'smallint PRIMARY KEY AUTO_INCREMENT'; + $values['bigPrimaryKey()'][0] = 'bigint PRIMARY KEY AUTO_INCREMENT'; + $values['uuidPrimaryKey()'][0] = 'binary(16) PRIMARY KEY DEFAULT uuid_to_bin(uuid())'; + $values['uuidPrimaryKey(false)'][0] = 'binary(16) PRIMARY KEY'; + $values['boolean()'][0] = 'bit(1)'; + $values['boolean(100)'][0] = 'bit(1)'; + $values['integer()'][0] = 'int'; + $values['integer(8)'][0] = 'int(8)'; + $values['money()'][0] = 'decimal(19,4)'; + $values['money(10)'][0] = 'decimal(10,4)'; + $values['money(10,2)'][0] = 'decimal(10,2)'; + $values['money(null)'][0] = 'decimal'; + $values['binary()'][0] = 'blob'; + $values['binary(1000)'][0] = 'blob(1000)'; + $values['uuid()'][0] = 'binary(16)'; + $values["comment('comment')"][0] = "varchar(255) COMMENT 'comment'"; + $values["comment('')"][0] = "varchar(255) COMMENT ''"; + $values['integer()->primaryKey()'][0] = 'int PRIMARY KEY'; + $values['unsigned()'][0] = 'int UNSIGNED'; + $values['integer(8)->scale(2)'][0] = 'int(8)'; + $values['reference($reference)'][0] = 'int REFERENCES `ref_table` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'; + + return $values; + } } diff --git a/tests/QueryBuilderTest.php b/tests/QueryBuilderTest.php index d15bca20..fe53917e 100644 --- a/tests/QueryBuilderTest.php +++ b/tests/QueryBuilderTest.php @@ -15,6 +15,7 @@ use Yiisoft\Db\Query\Query; use Yiisoft\Db\Query\QueryInterface; use Yiisoft\Db\QueryBuilder\Condition\JsonOverlapsCondition; +use Yiisoft\Db\Schema\Column\ColumnSchemaInterface; use Yiisoft\Db\Tests\Common\CommonQueryBuilderTest; use function str_contains; @@ -731,4 +732,10 @@ public function testJsonOverlapsConditionOperator(iterable|ExpressionInterface $ $db->close(); } + + /** @dataProvider \Yiisoft\Db\Mysql\Tests\Provider\QueryBuilderProvider::buildColumnDefinition() */ + public function testBuildColumnDefinition(string $expected, ColumnSchemaInterface|string $column): void + { + parent::testBuildColumnDefinition($expected, $column); + } } diff --git a/tests/SchemaTest.php b/tests/SchemaTest.php index 6b59c32e..538460b3 100644 --- a/tests/SchemaTest.php +++ b/tests/SchemaTest.php @@ -17,6 +17,7 @@ use Yiisoft\Db\Exception\NotSupportedException; use Yiisoft\Db\Expression\Expression; use Yiisoft\Db\Mysql\Column; +use Yiisoft\Db\Mysql\Column\ColumnFactory; use Yiisoft\Db\Mysql\Schema; use Yiisoft\Db\Mysql\Tests\Support\TestTrait; use Yiisoft\Db\Query\Query; @@ -573,4 +574,11 @@ public function testInsertDefaultValues() 'numeric_col' => '-33.22', ], $row); } + + public function testGetColumnFactory(): void + { + $db = $this->getConnection(); + + $this->assertInstanceOf(ColumnFactory::class, $db->getSchema()->getColumnFactory()); + } } From e8250bcb04993e58cf7cd72064a4831048795595 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Wed, 9 Oct 2024 09:35:59 +0700 Subject: [PATCH 2/6] Remove code comments --- src/Column/ColumnDefinitionBuilder.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Column/ColumnDefinitionBuilder.php b/src/Column/ColumnDefinitionBuilder.php index e8d73f1d..ea4293e4 100644 --- a/src/Column/ColumnDefinitionBuilder.php +++ b/src/Column/ColumnDefinitionBuilder.php @@ -47,11 +47,6 @@ final class ColumnDefinitionBuilder extends AbstractColumnDefinitionBuilder 'time', 'datetime', 'timestamp', - -// 'bool', -// 'boolean', -// 'date', -// 'json' ]; protected const TYPES_WITH_SCALE = [ From f8b550dfcd9595dca1ee59e69358c0fdd1707026 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Wed, 9 Oct 2024 02:37:33 +0000 Subject: [PATCH 3/6] Apply fixes from StyleCI --- tests/Provider/QueryBuilderProvider.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Provider/QueryBuilderProvider.php b/tests/Provider/QueryBuilderProvider.php index 4ff3a4f4..6e119d7d 100644 --- a/tests/Provider/QueryBuilderProvider.php +++ b/tests/Provider/QueryBuilderProvider.php @@ -7,7 +7,6 @@ use Yiisoft\Db\Constant\PseudoType; use Yiisoft\Db\Expression\Expression; use Yiisoft\Db\Expression\JsonExpression; -use Yiisoft\Db\Mysql\Column\ColumnBuilder; use Yiisoft\Db\Mysql\Tests\Support\TestTrait; use Yiisoft\Db\Query\Query; From ce46c37013de2111ccd91325884c32245e63a214 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Wed, 9 Oct 2024 10:17:56 +0700 Subject: [PATCH 4/6] Update according changes in main PR --- tests/Provider/QueryBuilderProvider.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Provider/QueryBuilderProvider.php b/tests/Provider/QueryBuilderProvider.php index 6e119d7d..1a9f7248 100644 --- a/tests/Provider/QueryBuilderProvider.php +++ b/tests/Provider/QueryBuilderProvider.php @@ -206,6 +206,7 @@ public static function buildColumnDefinition(): array $values["comment('comment')"][0] = "varchar(255) COMMENT 'comment'"; $values["comment('')"][0] = "varchar(255) COMMENT ''"; $values['integer()->primaryKey()'][0] = 'int PRIMARY KEY'; + $values["integer()->defaultValue('')"][0] = 'int'; $values['unsigned()'][0] = 'int UNSIGNED'; $values['integer(8)->scale(2)'][0] = 'int(8)'; $values['reference($reference)'][0] = 'int REFERENCES `ref_table` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'; From 720c95c11aca6dd9f4107537e21c0474e0c36ac6 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Wed, 9 Oct 2024 11:13:55 +0700 Subject: [PATCH 5/6] Update according changes in main PR --- tests/Provider/QueryBuilderProvider.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Provider/QueryBuilderProvider.php b/tests/Provider/QueryBuilderProvider.php index 1a9f7248..9e0b1f3d 100644 --- a/tests/Provider/QueryBuilderProvider.php +++ b/tests/Provider/QueryBuilderProvider.php @@ -210,6 +210,7 @@ public static function buildColumnDefinition(): array $values['unsigned()'][0] = 'int UNSIGNED'; $values['integer(8)->scale(2)'][0] = 'int(8)'; $values['reference($reference)'][0] = 'int REFERENCES `ref_table` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'; + $values['reference($referenceWithSchema)'][0] = 'int REFERENCES `ref_schema`.`ref_table` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'; return $values; } From b05652af4e90d4c54403970c1db979897da14505 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Fri, 11 Oct 2024 09:48:23 +0700 Subject: [PATCH 6/6] Add line to CHANGELOG.md [skip ci] --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 036aa95d..13e2edc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,14 +6,15 @@ - Bug #320: Change visibility of `DDLQueryBuilder::getColumnDefinition()` method to `private` (@Tigrov) - Enh #321: Implement `SqlParser` and `ExpressionBuilder` driver classes (@Tigrov) - Chg #339: Replace call of `SchemaInterface::getRawTableName()` to `QuoterInterface::getRawTableName()` (@Tigrov) -- Enh #342: Add JSON overlaps condition builder (@Tigrov) +- New #342: Add JSON overlaps condition builder (@Tigrov) - Enh #344: Update `bit` type according to main PR yiisoft/db#860 (@Tigrov) -- Enh #346: Implement `ColumnFactory` class (@Tigrov) +- New #346: Implement `ColumnFactory` class (@Tigrov) - Enh #347, #353: Raise minimum PHP version to `^8.1` with minor refactoring (@Tigrov) - Bug #349, #352: Restore connection if closed by connection timeout (@Tigrov) - Enh #354: Separate column type constants (@Tigrov) -- Enh #355: Realize `ColumnBuilder` class (@Tigrov) +- New #355: Realize `ColumnBuilder` class (@Tigrov) - Enh #357: Update according changes in `ColumnSchemaInterface` (@Tigrov) +- New #358: Add `ColumnDefinitionBuilder` class (@Tigrov) ## 1.2.0 March 21, 2024