diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d955acb..f322f100 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ - Enh #319: Separate column type constants (@Tigrov) - New #320: Realize `ColumnBuilder` class (@Tigrov) - Enh #321: Update according changes in `ColumnSchemaInterface` (@Tigrov) -- New #322: Add `ColumnDefinitionBuilder` class (@Tigrov) +- New #322, #330: Add `ColumnDefinitionBuilder` class (@Tigrov) - Enh #323: Refactor `Dsn` class (@Tigrov) - Enh #324: Use constructor to create columns and initialize properties (@Tigrov) - Enh #327: Refactor `Schema::findColumns()` method (@Tigrov) diff --git a/src/Column/ColumnDefinitionBuilder.php b/src/Column/ColumnDefinitionBuilder.php index d0f40d09..82698f69 100644 --- a/src/Column/ColumnDefinitionBuilder.php +++ b/src/Column/ColumnDefinitionBuilder.php @@ -51,11 +51,13 @@ public function build(ColumnSchemaInterface $column): string protected function getDbType(ColumnSchemaInterface $column): string { + $size = $column->getSize(); + /** @psalm-suppress DocblockTypeContradiction */ - return match ($column->getType()) { + $dbType = $column->getDbType() ?? match ($column->getType()) { ColumnType::BOOLEAN => 'bit', ColumnType::BIT => match (true) { - ($size = $column->getSize()) === null => 'bigint', + $size === null => 'bigint', $size === 1 => 'bit', $size <= 8 => 'tinyint', $size <= 16 => 'smallint', @@ -72,7 +74,7 @@ protected function getDbType(ColumnSchemaInterface $column): string ColumnType::DECIMAL => 'decimal', ColumnType::MONEY => 'money', ColumnType::CHAR => 'nchar', - ColumnType::STRING => 'nvarchar', + ColumnType::STRING => 'nvarchar(' . (($size ?? '255') ?: 'max') . ')', ColumnType::TEXT => 'nvarchar(max)', ColumnType::BINARY => 'varbinary(max)', ColumnType::UUID => 'uniqueidentifier', @@ -80,10 +82,18 @@ protected function getDbType(ColumnSchemaInterface $column): string ColumnType::TIMESTAMP => 'datetime2', ColumnType::DATE => 'date', ColumnType::TIME => 'time', - ColumnType::ARRAY => 'json', - ColumnType::STRUCTURED => 'json', - ColumnType::JSON => 'json', - default => 'varchar', + ColumnType::ARRAY => 'nvarchar(max)', + ColumnType::STRUCTURED => 'nvarchar(max)', + ColumnType::JSON => 'nvarchar(max)', + default => 'nvarchar', + }; + + return match ($dbType) { + 'timestamp' => 'datetime2', + 'varchar' => 'varchar(' . ($size ?: 'max') . ')', + 'nvarchar' => 'nvarchar(' . ($size ?: 'max') . ')', + 'varbinary' => 'varbinary(' . ($size ?: 'max') . ')', + default => $dbType, }; } } diff --git a/tests/Provider/QueryBuilderProvider.php b/tests/Provider/QueryBuilderProvider.php index d71c7f8f..3e3c931d 100644 --- a/tests/Provider/QueryBuilderProvider.php +++ b/tests/Provider/QueryBuilderProvider.php @@ -6,6 +6,7 @@ use Yiisoft\Db\Constant\PseudoType; use Yiisoft\Db\Expression\Expression; +use Yiisoft\Db\Mssql\Column\ColumnBuilder; use Yiisoft\Db\Mssql\Tests\Support\TestTrait; use Yiisoft\Db\Query\Query; use Yiisoft\Db\QueryBuilder\Condition\InCondition; @@ -349,7 +350,7 @@ public static function buildColumnDefinition(): array $values[PseudoType::UBIGPK][0] = 'bigint IDENTITY PRIMARY KEY'; $values[PseudoType::UUID_PK][0] = 'uniqueidentifier PRIMARY KEY DEFAULT newid()'; $values[PseudoType::UUID_PK_SEQ][0] = 'uniqueidentifier PRIMARY KEY DEFAULT newsequentialid()'; - $values['STRING'][0] = 'nvarchar'; + $values['STRING'][0] = 'nvarchar(255)'; $values['STRING(100)'][0] = 'nvarchar(100)'; $values['primaryKey()'][0] = 'int IDENTITY PRIMARY KEY'; $values['primaryKey(false)'][0] = 'int PRIMARY KEY'; @@ -364,7 +365,7 @@ public static function buildColumnDefinition(): array $values['bit()'][0] = 'bigint'; $values['bit(1)'][0] = 'bit'; $values['bit(8)'][0] = 'tinyint'; - $values['bit(1000)'][0] = 'varbinary(125)'; + $values['bit(64)'][0] = 'bigint'; $values['tinyint(2)'][0] = 'tinyint'; $values['smallint(4)'][0] = 'smallint'; $values['integer()'][0] = 'int'; @@ -381,7 +382,7 @@ public static function buildColumnDefinition(): array $values['char(null)'][0] = 'nchar'; $values['string()'][0] = 'nvarchar(255)'; $values['string(100)'][0] = 'nvarchar(100)'; - $values['string(null)'][0] = 'nvarchar'; + $values['string(null)'][0] = 'nvarchar(255)'; $values['text()'][0] = 'nvarchar(max)'; $values['text(1000)'][0] = 'nvarchar(max)'; $values['binary()'][0] = 'varbinary(max)'; @@ -393,18 +394,23 @@ public static function buildColumnDefinition(): array $values['timestamp(6)'][0] = 'datetime2(6)'; $values['timestamp(null)'][0] = 'datetime2'; $values['uuid()'][0] = 'uniqueidentifier'; - $values["extra('bar')"][0] = 'nvarchar(255) bar'; + $values['array()'][0] = 'nvarchar(max)'; + $values['structured()'][0] = 'nvarchar(max)'; + $values["structured('json')"] = ['varbinary(max)', ColumnBuilder::structured('varbinary(max)')]; + $values['json()'][0] = 'nvarchar(max)'; + $values['json(100)'][0] = 'nvarchar(max)'; + $values["extra('NOT NULL')"][0] = 'nvarchar(255) NOT NULL'; $values["extra('')"][0] = 'nvarchar(255)'; - $values["check('value > 5')"][0] = 'nvarchar(255) CHECK (value > 5)'; - $values["check('')"][0] = 'nvarchar(255)'; - $values['check(null)'][0] = 'nvarchar(255)'; + $values["check('value > 5')"][0] = 'int CHECK ([col_59] > 5)'; + $values["check('')"][0] = 'int'; + $values['check(null)'][0] = 'int'; $values["comment('comment')"][0] = 'nvarchar(255)'; $values["comment('')"][0] = 'nvarchar(255)'; $values['comment(null)'][0] = 'nvarchar(255)'; $values["defaultValue('value')"][0] = "nvarchar(255) DEFAULT 'value'"; $values["defaultValue('')"][0] = "nvarchar(255) DEFAULT ''"; $values['defaultValue(null)'][0] = 'nvarchar(255) DEFAULT NULL'; - $values['defaultValue($expression)'][0] = 'nvarchar(255) DEFAULT expression'; + $values['defaultValue($expression)'][0] = 'int DEFAULT (1 + 2)'; $values['notNull()->defaultValue(null)'][0] = 'nvarchar(255) NOT NULL'; $values["integer()->defaultValue('')"][0] = 'int DEFAULT NULL'; $values['notNull()'][0] = 'nvarchar(255) NOT NULL';