Skip to content

Commit f15ac48

Browse files
authored
Allow Expression for column definitions when create table. (#979)
1 parent e88f5d8 commit f15ac48

7 files changed

Lines changed: 39 additions & 32 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
- New #973: Add `upsertWithReturningPks()` method to `CommandInterface` and `DMLQueryBuilderInterface` (@Tigrov)
9292
- New #968: Add `DateTimeColumn` column class (@Tigrov)
9393
- Bug #978: Fix memory leaking in `Command::exists()` method (@Tigrov)
94+
- Enh #979: Allow `ExpressionInterface` for column definitions when create table (@Tigrov)
9495

9596
## 1.3.0 March 21, 2024
9697

docs/guide/pt-BR/command/ddl.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@ Para criar uma tabela, você pode usar o método `Yiisoft\Db\Command\CommandInte
1313

1414
```php
1515
use Yiisoft\Db\Connection\ConnectionInterface;
16+
use Yiisoft\Db\Schema\Column\ColumnBuilder;
1617

1718
/** @var ConnectionInterface $db */
1819
$db->createCommand()->createTable(
1920
'{{%customer}}',
2021
[
21-
'id' => 'pk',
22-
'name' => 'string(255) NOT NULL',
23-
'email' => 'string(255) NOT NULL',
24-
'status' => 'integer NOT NULL',
25-
'created_at' => 'datetime NOT NULL',
22+
'id' => ColumnBuilder::primaryKey(),
23+
'name' => ColumnBuilder::string()->notNull(),
24+
'email' => ColumnBuilder::string()->notNull(),
25+
'status' => ColumnBuilder::integer()->notNull(),
26+
'created_at' => ColumnBuilder::datetime()->notNull(),
2627
],
2728
)->execute();
2829
```

src/Command/CommandInterface.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Yiisoft\Db\Exception\InvalidCallException;
1919
use Yiisoft\Db\Exception\InvalidConfigException;
2020
use Yiisoft\Db\Exception\NotSupportedException;
21+
use Yiisoft\Db\Expression\ExpressionInterface;
2122
use Yiisoft\Db\Query\DataReaderInterface;
2223
use Yiisoft\Db\Query\QueryInterface;
2324
use Yiisoft\Db\QueryBuilder\DMLQueryBuilderInterface;
@@ -349,18 +350,16 @@ public function createIndex(
349350
* If a column is specified with definition only (e.g. 'PRIMARY KEY (name, type)'), it will be directly put into the
350351
* generated SQL.
351352
*
353+
* The method will quote the `table` and `columns` parameter before using it in the generated SQL.
354+
*
352355
* @param string $table The name of the table to create.
353-
* @param (ColumnInterface|string)[] $columns The columns (name => definition) in the new table.
354-
* The definition can be `string` or {@see ColumnInterface} instance.
356+
* @param (ColumnInterface|ExpressionInterface|string)[] $columns The columns (name => definition) in the new table.
357+
* The definition can be `string`, or {@see ColumnInterface} or {@see ExpressionInterface} instance.
355358
* @param string|null $options More SQL fragments to append to the generated SQL.
356359
*
357360
* @throws Exception
358361
* @throws InvalidConfigException
359362
* @throws NotSupportedException
360-
*
361-
* Note: The method will quote the `table` and `columns` parameter before using it in the generated SQL.
362-
*
363-
* @psalm-param array<string, ColumnInterface>|string[] $columns
364363
*/
365364
public function createTable(string $table, array $columns, ?string $options = null): static;
366365

src/QueryBuilder/AbstractDDLQueryBuilder.php

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Yiisoft\Db\QueryBuilder;
66

77
use Yiisoft\Db\Exception\NotSupportedException;
8+
use Yiisoft\Db\Expression\ExpressionInterface;
89
use Yiisoft\Db\Query\QueryInterface;
910
use Yiisoft\Db\Schema\Column\ColumnInterface;
1011
use Yiisoft\Db\Schema\QuoterInterface;
@@ -166,25 +167,27 @@ public function createIndex(
166167
public function createTable(string $table, array $columns, ?string $options = null): string
167168
{
168169
$cols = [];
170+
$quoter = $this->quoter;
171+
$queryBuilder = $this->queryBuilder;
169172

170173
foreach ($columns as $name => $type) {
171174
if (is_string($name)) {
172-
$cols[] = "\t"
173-
. $this->quoter->quoteColumnName($name)
174-
. ' '
175-
. $this->queryBuilder->buildColumnDefinition(
176-
$type instanceof ColumnInterface
177-
? $type->withName($name)
178-
: $type
179-
);
175+
$columnDefinition = match (true) {
176+
$type instanceof ColumnInterface => $queryBuilder->buildColumnDefinition($type->withName($name)),
177+
$type instanceof ExpressionInterface => $queryBuilder->buildExpression($type),
178+
default => $queryBuilder->buildColumnDefinition($type),
179+
};
180+
181+
$cols[] = "{$quoter->quoteColumnName($name)} $columnDefinition";
180182
} else {
181183
/** @var string $type */
182-
$cols[] = "\t" . $type;
184+
$cols[] = $type;
183185
}
184186
}
185187

186-
$sql = 'CREATE TABLE '
187-
. $this->quoter->quoteTableName($table) . " (\n" . implode(",\n", $cols) . "\n)";
188+
$sql = "CREATE TABLE {$quoter->quoteTableName($table)} (\n\t"
189+
. implode(",\n\t", $cols)
190+
. "\n)";
188191

189192
return $options === null ? $sql : $sql . ' ' . $options;
190193
}

src/QueryBuilder/DDLQueryBuilderInterface.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Yiisoft\Db\Exception\InvalidArgumentException;
1111
use Yiisoft\Db\Exception\InvalidConfigException;
1212
use Yiisoft\Db\Exception\NotSupportedException;
13+
use Yiisoft\Db\Expression\ExpressionInterface;
1314
use Yiisoft\Db\Query\QueryInterface;
1415
use Yiisoft\Db\Schema\Column\ColumnInterface;
1516

@@ -263,15 +264,13 @@ public function createIndex(
263264
* generated SQL.
264265
*
265266
* @param string $table The name of the table to create.
266-
* @param array $columns The columns (name => definition) in the new table.
267-
* The definition can be `string` or {@see ColumnInterface} instance.
267+
* @param (ColumnInterface|ExpressionInterface|string)[] $columns The columns (name => definition) in the new table.
268+
* The definition can be `string`, or {@see ColumnInterface} or {@see ExpressionInterface} instance.
268269
* @param string|null $options More SQL fragments to append to the generated SQL.
269270
*
270271
* @return string The SQL statement for creating a new DB table.
271272
*
272273
* Note: The method will quote the `table` and `columns` parameter before using it in the generated SQL.
273-
*
274-
* @psalm-param array<string, ColumnInterface>|string[] $columns
275274
*/
276275
public function createTable(string $table, array $columns, ?string $options = null): string;
277276

tests/Db/Command/CommandTest.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
use Yiisoft\Db\Constant\ColumnType;
99
use Yiisoft\Db\Constant\PseudoType;
1010
use Yiisoft\Db\Exception\NotSupportedException;
11+
use Yiisoft\Db\Expression\Expression;
1112
use Yiisoft\Db\Schema\Column\ColumnBuilder;
1213
use Yiisoft\Db\Schema\Column\ColumnInterface;
14+
use Yiisoft\Db\Schema\Column\IntegerColumn;
1315
use Yiisoft\Db\Tests\AbstractCommandTest;
1416
use Yiisoft\Db\Tests\Provider\CommandProvider;
1517
use Yiisoft\Db\Tests\Support\Assert;
@@ -257,9 +259,9 @@ public function testCreateTable(): void
257259
$columns = [
258260
'id' => PseudoType::PK,
259261
'name' => ColumnType::STRING . '(255) NOT NULL',
260-
'email' => ColumnType::STRING . '(255) NOT NULL',
261-
'address' => ColumnType::STRING . '(255) NOT NULL',
262-
'status' => ColumnType::INTEGER . ' NOT NULL',
262+
'email' => new Expression('varchar(255) NOT NULL'),
263+
'address' => ColumnBuilder::string()->notNull(),
264+
'status' => new IntegerColumn(notNull: true),
263265
'profile_id' => ColumnType::INTEGER . ' NOT NULL',
264266
'data' => ColumnBuilder::json(),
265267
'created_at' => ColumnType::TIMESTAMP . ' NOT NULL',

tests/Db/QueryBuilder/QueryBuilderTest.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
use Yiisoft\Db\Exception\Exception;
1010
use Yiisoft\Db\Exception\InvalidArgumentException;
1111
use Yiisoft\Db\Exception\NotSupportedException;
12+
use Yiisoft\Db\Expression\Expression;
1213
use Yiisoft\Db\Expression\ExpressionInterface;
1314
use Yiisoft\Db\Query\Query;
1415
use Yiisoft\Db\Query\QueryInterface;
1516
use Yiisoft\Db\Schema\Column\ColumnBuilder;
17+
use Yiisoft\Db\Schema\Column\IntegerColumn;
1618
use Yiisoft\Db\Tests\AbstractQueryBuilderTest;
1719
use Yiisoft\Db\Tests\Provider\QueryBuilderProvider;
1820
use Yiisoft\Db\Tests\Support\Assert;
@@ -102,7 +104,7 @@ public function testCreateTable(): void
102104
<<<SQL
103105
CREATE TABLE [[test]] (
104106
\t[[id]] integer PRIMARY KEY AUTOINCREMENT,
105-
\t[[name]] varchar(255) NOT NULL,
107+
\t[[name]] string(255) NOT NULL,
106108
\t[[email]] varchar(255) NOT NULL,
107109
\t[[status]] integer NOT NULL,
108110
\t[[created_at]] datetime NOT NULL,
@@ -115,9 +117,9 @@ public function testCreateTable(): void
115117
'test',
116118
[
117119
'id' => 'pk',
118-
'name' => 'string(255) NOT NULL',
120+
'name' => new Expression('string(255) NOT NULL'),
119121
'email' => ColumnBuilder::string()->notNull(),
120-
'status' => 'integer NOT NULL',
122+
'status' => new IntegerColumn(notNull: true),
121123
'created_at' => 'datetime NOT NULL',
122124
'UNIQUE test_email_unique (email)',
123125
],

0 commit comments

Comments
 (0)