Skip to content

Commit

Permalink
Use new column definition builder (yiisoft#905)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov authored Dec 23, 2024
1 parent 7afd5d8 commit 5502bc2
Show file tree
Hide file tree
Showing 23 changed files with 291 additions and 240 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
- New #902: Add `QueryBuilderInterface::prepareParam()` and `QueryBuilderInterface::prepareValue()` methods (@Tigrov)
- Enh #902: Refactor `Quoter::quoteValue()` method (@Tigrov)
- New #906: Add `ServerInfoInterface` and its implementation (@Tigrov)
- Enh #905: Use `AbstractColumnDefinitionBuilder` to generate table column SQL representation (@Tigrov)

## 1.3.0 March 21, 2024

Expand Down
15 changes: 8 additions & 7 deletions docs/guide/en/command/ddl.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@ To create a table, you can use the `Yiisoft\Db\Command\CommandInterface::createT

```php
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Schema\Column\ColumnBuilder;

/** @var ConnectionInterface $db */
$db->createCommand()->createTable(
'{{%customer}}',
[
'id' => 'pk',
'name' => 'string(255) NOT NULL',
'email' => 'string(255) NOT NULL',
'status' => 'integer NOT NULL',
'created_at' => 'datetime NOT NULL',
'id' => ColumnBuilder::primaryKey(),
'name' => ColumnBuilder::string()->notNull(),
'email' => ColumnBuilder::string()->notNull(),
'status' => ColumnBuilder::integer()->notNull(),
'created_at' => ColumnBuilder::datetime()->notNull(),
],
)->execute();
```
Expand All @@ -44,10 +45,10 @@ And the following SQL will be executed in MySQL/MariaDB:

```sql
CREATE TABLE `customer` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id` int PRIMARY KEY AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`status` int(11) NOT NULL,
`status` int NOT NULL,
`created_at` datetime(0) NOT NULL
)
```
Expand Down
5 changes: 3 additions & 2 deletions src/Command/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Yiisoft\Db\QueryBuilder\DMLQueryBuilderInterface;
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
use Yiisoft\Db\Schema\Builder\ColumnInterface;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;

use function explode;
use function get_resource_type;
Expand Down Expand Up @@ -131,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, ColumnInterface|string $type): static
public function addColumn(string $table, string $column, ColumnInterface|ColumnSchemaInterface|string $type): static
{
$sql = $this->getQueryBuilder()->addColumn($table, $column, $type);
return $this->setSql($sql)->requireTableSchemaRefresh($table);
Expand Down Expand Up @@ -188,7 +189,7 @@ public function addUnique(string $table, string $name, array|string $columns): s
return $this->setSql($sql)->requireTableSchemaRefresh($table);
}

public function alterColumn(string $table, string $column, ColumnInterface|string $type): static
public function alterColumn(string $table, string $column, ColumnInterface|ColumnSchemaInterface|string $type): static
{
$sql = $this->getQueryBuilder()->alterColumn($table, $column, $type);
return $this->setSql($sql)->requireTableSchemaRefresh($table);
Expand Down
60 changes: 41 additions & 19 deletions src/Command/CommandInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use JsonException;
use Throwable;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Constant\ColumnType;
use Yiisoft\Db\Constant\PseudoType;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
use Yiisoft\Db\Exception\InvalidCallException;
Expand All @@ -17,6 +19,7 @@
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\QueryBuilder\DMLQueryBuilderInterface;
use Yiisoft\Db\Schema\Builder\ColumnInterface;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;

/**
* This interface represents a database command, such as a `SELECT`, `INSERT`, `UPDATE`, or `DELETE` statement.
Expand Down Expand Up @@ -44,13 +47,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 ColumnInterface|string $type The column type. {@see QueryBuilder::getColumnType()} will be called
* to convert the given column type to the database one.
* @param ColumnInterface|ColumnSchemaInterface|string $type The column type.
* {@see QueryBuilder::buildColumnDefinition()} 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, ColumnInterface|string $type): static;
public function addColumn(string $table, string $column, ColumnInterface|ColumnSchemaInterface|string $type): static;

/**
* Builds an SQL command for adding a comment to a column.
Expand Down Expand Up @@ -144,13 +147,13 @@ public function addPrimaryKey(string $table, string $name, array|string $columns
*
* @param string $table The table whose column is to change.
* @param string $column The name of the column to change.
* @param ColumnInterface|string $type The column type. {@see QueryBuilder::getColumnType()} will be called to
* convert the give column type to the physical one. For example, `string` will be converted as `varchar(255)`, and
* `string not null` becomes `varchar(255) not null`.
* @param ColumnInterface|ColumnSchemaInterface|string $type The column type.
* {@see QueryBuilder::buildColumnDefinition()} will be called to convert the give column type to the physical one.
* For example, `string` will be converted as `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 alterColumn(string $table, string $column, ColumnInterface|string $type): static;
public function alterColumn(string $table, string $column, ColumnInterface|ColumnSchemaInterface|string $type): static;

/**
* Creates a batch INSERT command.
Expand Down Expand Up @@ -314,21 +317,40 @@ public function createIndex(
/**
* Creates an SQL command for creating a new DB table.
*
* Specify the columns in the new table as name-definition pairs ('name' => 'string'), where name
* stands for a column name which will be quoted by the method, and definition stands for the column type
* which can contain an abstract DB type.
* The columns in the new table should be specified as name-definition pairs (e.g. 'name' => 'string'), where name
* is the name of the column which will be properly quoted by the method, and definition is the type of the column
* which can contain a native database column type, {@see ColumnType abstract} or {@see PseudoType pseudo} type,
* or can be represented as instance of {@see ColumnSchemaInterface}.
*
* The method {@see QueryBuilder::getColumnType()} will be called to convert the abstract column types to physical
* ones.
* For example, it will convert `string` to `varchar(255)`, and `string not null` to
* `varchar(255) not null`.
* The {@see QueryBuilderInterface::buildColumnDefinition()} method will be invoked to convert column definitions
* into SQL representation. For example, it will convert `string not null` to `varchar(255) not null`
* and `pk` to `int PRIMARY KEY AUTO_INCREMENT` (for MySQL).
*
* If you specify a column with definition only (`PRIMARY KEY (name, type)`), it will be directly inserted
* into the generated SQL.
* The preferred method is to use {@see ColumnBuilder} to generate column definitions as instances of
* {@see ColumnSchemaInterface}.
*
* ```php
* $this->createTable(
* 'example_table',
* [
* 'id' => ColumnBuilder::primaryKey(),
* 'name' => ColumnBuilder::string(64)->notNull(),
* 'type' => ColumnBuilder::integer()->notNull()->defaultValue(10),
* 'description' => ColumnBuilder::text(),
* 'rule_name' => ColumnBuilder::string(64),
* 'data' => ColumnBuilder::text(),
* 'created_at' => ColumnBuilder::datetime()->notNull(),
* 'updated_at' => ColumnBuilder::datetime(),
* ],
* );
* ```
*
* If a column is specified with definition only (e.g. 'PRIMARY KEY (name, type)'), it will be directly put into the
* generated SQL.
*
* @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 (ColumnSchemaInterface|string)[] $columns The columns (name => definition) in the new table.
* The definition can be `string` or {@see ColumnSchemaInterface} instance.
* @param string|null $options More SQL fragments to append to the generated SQL.
*
* @throws Exception
Expand All @@ -337,7 +359,7 @@ public function createIndex(
*
* Note: The method will quote the `table` and `columns` parameter before using it in the generated SQL.
*
* @psalm-param array<string, ColumnInterface>|string[] $columns
* @psalm-param array<string, ColumnSchemaInterface>|string[] $columns
*/
public function createTable(string $table, array $columns, string $options = null): static;

Expand Down
5 changes: 3 additions & 2 deletions src/Debug/CommandInterfaceProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Yiisoft\Db\Query\Data\DataReaderInterface;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\Schema\Builder\ColumnInterface;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;

final class CommandInterfaceProxy implements CommandInterface
{
Expand All @@ -30,7 +31,7 @@ public function addCheck(string $table, string $name, string $expression): stati
/**
* @psalm-suppress MixedArgument
*/
public function addColumn(string $table, string $column, ColumnInterface|string $type): static
public function addColumn(string $table, string $column, ColumnInterface|ColumnSchemaInterface|string $type): static
{
return new self($this->decorated->{__FUNCTION__}(...func_get_args()), $this->collector);
}
Expand Down Expand Up @@ -93,7 +94,7 @@ public function addUnique(string $table, string $name, array|string $columns): s
/**
* @psalm-suppress MixedArgument
*/
public function alterColumn(string $table, string $column, ColumnInterface|string $type): static
public function alterColumn(string $table, string $column, ColumnInterface|ColumnSchemaInterface|string $type): static
{
return new self($this->decorated->{__FUNCTION__}(...func_get_args()), $this->collector);
}
Expand Down
24 changes: 17 additions & 7 deletions src/QueryBuilder/AbstractColumnDefinitionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ abstract class AbstractColumnDefinitionBuilder implements ColumnDefinitionBuilde
*/
protected const AUTO_INCREMENT_KEYWORD = '';

/**
* @var string The expression used to generate a UUID value.
*/
protected const GENERATE_UUID_EXPRESSION = '';

/**
* @var string[] The list of database column types (in lower case) that allow size specification.
*/
Expand Down Expand Up @@ -65,6 +60,11 @@ public function build(ColumnSchemaInterface $column): string
. $this->buildExtra($column);
}

public function buildAlter(ColumnSchemaInterface $column): string
{
return $this->build($column);
}

/**
* Builds the auto increment clause for the column.
*
Expand Down Expand Up @@ -114,12 +114,14 @@ protected function buildComment(ColumnSchemaInterface $column): string
*/
protected function buildDefault(ColumnSchemaInterface $column): string
{
if (!empty(static::GENERATE_UUID_EXPRESSION)
$uuidExpression = $this->getDefaultUuidExpression();

if (!empty($uuidExpression)
&& $column->getType() === ColumnType::UUID
&& $column->isAutoIncrement()
&& $column->getDefaultValue() === null
) {
return ' DEFAULT ' . static::GENERATE_UUID_EXPRESSION;
return " DEFAULT $uuidExpression";
}

if ($column->isAutoIncrement() && $column->getType() !== ColumnType::UUID
Expand Down Expand Up @@ -298,4 +300,12 @@ protected function buildUnsigned(ColumnSchemaInterface $column): string
{
return $column->isUnsigned() ? ' UNSIGNED' : '';
}

/**
* Get the expression used to generate a UUID as a default value.
*/
protected function getDefaultUuidExpression(): string
{
return '';
}
}
14 changes: 6 additions & 8 deletions src/QueryBuilder/AbstractDDLQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\Schema\Builder\ColumnInterface;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
use Yiisoft\Db\Schema\QuoterInterface;
use Yiisoft\Db\Schema\SchemaInterface;

Expand Down Expand Up @@ -39,15 +40,14 @@ public function addCheck(string $table, string $name, string $expression): strin
. ' CHECK (' . $this->quoter->quoteSql($expression) . ')';
}

public function addColumn(string $table, string $column, ColumnInterface|string $type): string
public function addColumn(string $table, string $column, ColumnInterface|ColumnSchemaInterface|string $type): string
{
/** @psalm-suppress DeprecatedMethod */
return 'ALTER TABLE '
. $this->quoter->quoteTableName($table)
. ' ADD '
. $this->quoter->quoteColumnName($column)
. ' '
. $this->queryBuilder->getColumnType($type);
. $this->queryBuilder->buildColumnDefinition($type);
}

public function addCommentOnColumn(string $table, string $column, string $comment): string
Expand Down Expand Up @@ -137,16 +137,15 @@ public function addUnique(string $table, string $name, array|string $columns): s
public function alterColumn(
string $table,
string $column,
ColumnInterface|string $type
ColumnInterface|ColumnSchemaInterface|string $type
): string {
/** @psalm-suppress DeprecatedMethod */
return 'ALTER TABLE '
. $this->quoter->quoteTableName($table)
. ' CHANGE '
. $this->quoter->quoteColumnName($column)
. ' '
. $this->quoter->quoteColumnName($column) . ' '
. $this->queryBuilder->getColumnType($type);
. $this->queryBuilder->buildColumnDefinition($type);
}

public function checkIntegrity(string $schema = '', string $table = '', bool $check = true): string
Expand All @@ -173,11 +172,10 @@ public function createTable(string $table, array $columns, string $options = nul

foreach ($columns as $name => $type) {
if (is_string($name)) {
/** @psalm-suppress DeprecatedMethod */
$cols[] = "\t"
. $this->quoter->quoteColumnName($name)
. ' '
. $this->queryBuilder->getColumnType($type);
. $this->queryBuilder->buildColumnDefinition($type);
} else {
/** @psalm-var string $type */
$cols[] = "\t" . $type;
Expand Down
15 changes: 12 additions & 3 deletions src/QueryBuilder/AbstractQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,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, ColumnInterface|string $type): string
public function addColumn(string $table, string $column, ColumnInterface|ColumnSchemaInterface|string $type): string
{
return $this->ddlBuilder->addColumn($table, $column, $type);
}
Expand Down Expand Up @@ -131,7 +131,7 @@ public function addUnique(string $table, string $name, array|string $columns): s
return $this->ddlBuilder->addUnique($table, $name, $columns);
}

public function alterColumn(string $table, string $column, ColumnInterface|string $type): string
public function alterColumn(string $table, string $column, ColumnInterface|ColumnSchemaInterface|string $type): string
{
return $this->ddlBuilder->alterColumn($table, $column, $type);
}
Expand Down Expand Up @@ -175,8 +175,12 @@ public function build(QueryInterface $query, array $params = []): array
return $this->dqlBuilder->build($query, $params);
}

public function buildColumnDefinition(ColumnSchemaInterface|string $column): string
public function buildColumnDefinition(ColumnInterface|ColumnSchemaInterface|string $column): string
{
if ($column instanceof ColumnInterface) {
$column = $column->asString();
}

if (is_string($column)) {
$column = $this->schema->getColumnFactory()->fromDefinition($column);
}
Expand Down Expand Up @@ -355,6 +359,11 @@ public function dropView(string $viewName): string
return $this->ddlBuilder->dropView($viewName);
}

public function getColumnDefinitionBuilder(): ColumnDefinitionBuilderInterface
{
return $this->columnDefinitionBuilder;
}

/** @deprecated Use {@see buildColumnDefinition()}. Will be removed in version 2.0. */
public function getColumnType(ColumnInterface|string $type): string
{
Expand Down
5 changes: 5 additions & 0 deletions src/QueryBuilder/ColumnDefinitionBuilderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ interface ColumnDefinitionBuilderInterface
* @return string the column SQL definition.
*/
public function build(ColumnSchemaInterface $column): string;

/**
* Builds column definition for `ALTER` operation based on given column instance.
*/
public function buildAlter(ColumnSchemaInterface $column): string;
}
Loading

0 comments on commit 5502bc2

Please sign in to comment.