Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
- Enh #806: Build `Expression` instances inside `Expression::$params` when build a query using `QueryBuilder` (@Tigrov)
- Enh #766: Allow `ColumnInterface` as column type. (@Tigrov)
- Bug #828: Fix `float` type when use `AbstractCommand::getRawSql()` method (@Tigrov)
- Enh #829: Rename `batchInsert()` to `insertBatch()` in `DMLQueryBuilderInterface` and `CommandInterface`
and change parameters from `$table, $columns, $rows` to `$table, $rows, $columns = []` (@Tigrov)

## 1.3.0 March 21, 2024

Expand Down
19 changes: 19 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,22 @@ Add support any scalar values for `$columns` parameter of these methods in your
`Expression::$params` can contain:
- non-unique placeholder names, they will be replaced with unique names.
- `Expression` instances, they will be built when building a query using `QueryBuilder`.

### Rename `batchInsert()` to `insertBatch()`

`batchInsert()` method is renamed to `insertBatch()` in `DMLQueryBuilderInterface` and `CommandInterface`.
The parameters are changed from `$table, $columns, $rows` to `$table, $rows, $columns = []`.
It allows to use the method without columns, for example:

```php
use Yiisoft\Db\Connection\ConnectionInterface;

$values = [
['name' => 'Tom', 'age' => 30],
['name' => 'Jane', 'age' => 20],
['name' => 'Linda', 'age' => 25],
];

/** @var ConnectionInterface $db */
$db->createCommand()->insertBatch('user', $values)->execute();
```
24 changes: 20 additions & 4 deletions docs/guide/en/command/dml.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,36 @@ You can use the DML to perform the following operations:

## Batch insert

To insert multiple rows into a table, you can use the `Yiisoft\Db\Command\CommandInterface::batchInsert()` method:
To insert multiple rows into a table, you can use the `Yiisoft\Db\Command\CommandInterface::insertBatch()` method:

```php
use Yiisoft\Db\Connection\ConnectionInterface;

/** @var ConnectionInterface $db */
$db->createCommand()->batchInsert(
$db->createCommand()->insertBatch(
'{{%customer}}',
['name', 'email'],
[
['user1', 'email1@email.com'],
['user2', 'email2@email.com'],
['user3', 'email3@email.com'],
]
],
['name', 'email'],
)->execute();
```

It is possible to insert rows as associative arrays, where the keys are column names.

```php
use Yiisoft\Db\Connection\ConnectionInterface;

/** @var ConnectionInterface $db */
$db->createCommand()->insertBatch(
'{{%customer}}',
[
['name' => 'user1', 'email' => 'email1@email.com'],
['name' => 'user2', 'email' => 'email2@email.com'],
['name' => 'user3', 'email' => 'email3@email.com'],
],
)->execute();
```

Expand Down
20 changes: 18 additions & 2 deletions docs/guide/pt-BR/command/dml.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ Você pode usar o DML para realizar as seguintes operações:

## Inserção em lote

Para inserir múltiplas linhas em uma tabela, você pode usar o método `Yiisoft\Db\Command\CommandInterface::batchInsert()`:
Para inserir múltiplas linhas em uma tabela, você pode usar o método `Yiisoft\Db\Command\CommandInterface::insertBatch()`:

```php
use Yiisoft\Db\Connection\ConnectionInterface;

/** @var ConnectionInterface $db */
$db->createCommand()->batchInsert(
$db->createCommand()->insertBatch(
'{{%customer}}',
['name', 'email'],
[
Expand All @@ -30,6 +30,22 @@ $db->createCommand()->batchInsert(
)->execute();
```

It is possible to insert rows as associative arrays, where the keys are column names.

```php
use Yiisoft\Db\Connection\ConnectionInterface;

/** @var ConnectionInterface $db */
$db->createCommand()->insertBatch(
'{{%customer}}',
[
['name' => 'user1', 'email' => 'email1@email.com'],
['name' => 'user2', 'email' => 'email2@email.com'],
['name' => 'user3', 'email' => 'email3@email.com'],
],
)->execute();
```

## Excluir linhas

Para excluir linhas de uma tabela, você pode usar o método `Yiisoft\Db\Command\CommandInterface::delete()`:
Expand Down
17 changes: 16 additions & 1 deletion src/Command/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Query\Data\DataReaderInterface;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\QueryBuilder\DMLQueryBuilderInterface;
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
use Yiisoft\Db\Schema\Builder\ColumnInterface;
use Yiisoft\Db\Schema\SchemaInterface;
Expand Down Expand Up @@ -65,6 +66,8 @@
* ```
*
* To build `SELECT` SQL statements, please use {@see QueryInterface} and its implementations instead.
*
* @psalm-import-type BatchValues from DMLQueryBuilderInterface
*/
abstract class AbstractCommand implements CommandInterface
{
Expand Down Expand Up @@ -195,7 +198,19 @@ public function alterColumn(string $table, string $column, ColumnInterface|strin
return $this->setSql($sql)->requireTableSchemaRefresh($table);
}

/**
* @param string[] $columns
*
* @psalm-param BatchValues $rows
*
* @deprecated Use {@see insertBatch()} instead. It will be removed in version 3.0.0.
*/
public function batchInsert(string $table, array $columns, iterable $rows): static
{
return $this->insertBatch($table, $rows, $columns);
}

public function insertBatch(string $table, iterable $rows, array $columns = []): static
{
$table = $this->getQueryBuilder()->quoter()->quoteSql($table);

Expand All @@ -207,7 +222,7 @@ public function batchInsert(string $table, array $columns, iterable $rows): stat
unset($column);

$params = [];
$sql = $this->getQueryBuilder()->batchInsert($table, $columns, $rows, $params);
$sql = $this->getQueryBuilder()->insertBatch($table, $rows, $columns, $params);

$this->setRawSql($sql);
$this->bindValues($params);
Expand Down
25 changes: 20 additions & 5 deletions src/Command/CommandInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Query\Data\DataReaderInterface;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\QueryBuilder\DMLQueryBuilderInterface;
use Yiisoft\Db\Schema\Builder\ColumnInterface;

/**
Expand All @@ -23,6 +24,7 @@
* A command instance is usually created by calling {@see ConnectionInterface::createCommand}.
*
* @psalm-import-type ParamsType from ConnectionInterface
* @psalm-import-type BatchValues from DMLQueryBuilderInterface
*/
interface CommandInterface
{
Expand Down Expand Up @@ -156,13 +158,26 @@ public function alterColumn(string $table, string $column, ColumnInterface|strin
* For example,
*
* ```php
* $connectionInterface->createCommand()->batchInsert(
* $connectionInterface->createCommand()->insertBatch(
* 'user',
* ['name', 'age'],
* [
* ['Tom', 30],
* ['Jane', 20],
* ['Linda', 25],
* ],
* ['name', 'age']
* )->execute();
* ```
*
* or as associative arrays where the keys are column names
*
* ```php
* $connectionInterface->createCommand()->insertBatch(
* 'user',
* [
* ['name' => 'Tom', 'age' => 30],
* ['name' => 'Jane', 'age' => 20],
* ['name' => 'Linda', 'age' => 25],
* ]
* )->execute();
* ```
Expand All @@ -174,17 +189,17 @@ public function alterColumn(string $table, string $column, ColumnInterface|strin
* Also note that the created command isn't executed until {@see execute()} is called.
*
* @param string $table The name of the table to insert new rows into.
* @param array $columns The column names.
* @param iterable $rows The rows to be batch inserted into the table.
* @param string[] $columns The column names.
*
* @throws Exception
* @throws InvalidArgumentException
*
* @psalm-param iterable<array-key, array<array-key, mixed>> $rows
* @psalm-param BatchValues $rows
*
* Note: The method will quote the `table` and `column` parameters before using them in the generated SQL.
*/
public function batchInsert(string $table, array $columns, iterable $rows): static;
public function insertBatch(string $table, iterable $rows, array $columns = []): static;

/**
* Binds a parameter to the SQL statement to be executed.
Expand Down
2 changes: 1 addition & 1 deletion src/Debug/CommandInterfaceProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public function alterColumn(string $table, string $column, ColumnInterface|strin
/**
* @psalm-suppress MixedArgument
*/
public function batchInsert(string $table, array $columns, iterable $rows): static
public function insertBatch(string $table, iterable $rows, array $columns = []): static
{
return new self($this->decorated->{__FUNCTION__}(...func_get_args()), $this->collector);
}
Expand Down
25 changes: 20 additions & 5 deletions src/QueryBuilder/AbstractDMLQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@
use function array_values;
use function count;
use function get_object_vars;
use function gettype;
use function implode;
use function in_array;
use function is_array;
use function is_object;
use function is_string;
use function iterator_to_array;
use function json_encode;
Expand All @@ -52,6 +52,7 @@
* @link https://en.wikipedia.org/wiki/Data_manipulation_language
*
* @psalm-import-type ParamsType from ConnectionInterface
* @psalm-import-type BatchValues from DMLQueryBuilderInterface
*/
abstract class AbstractDMLQueryBuilder implements DMLQueryBuilderInterface
{
Expand All @@ -62,7 +63,20 @@ public function __construct(
) {
}

/**
* @param string[] $columns
*
* @psalm-param BatchValues $rows
* @psalm-param ParamsType $params
*
* @deprecated Use {@see insertBatch()} instead. It will be removed in version 3.0.0.
*/
public function batchInsert(string $table, array $columns, iterable $rows, array &$params = []): string
{
return $this->insertBatch($table, $rows, $columns, $params);
}

public function insertBatch(string $table, iterable $rows, array $columns = [], array &$params = []): string
{
if (!is_array($rows)) {
$rows = $this->prepareTraversable($rows);
Expand Down Expand Up @@ -226,10 +240,11 @@ protected function extractColumnNames(array|Iterator $rows, array $columns): arr
$row = reset($rows);
}

$row = match (true) {
is_array($row) => $row,
$row instanceof Traversable => iterator_to_array($row),
is_object($row) => get_object_vars($row),
$row = match (gettype($row)) {
'array' => $row,
'object' => $row instanceof Traversable
? iterator_to_array($row)
: get_object_vars($row),
default => [],
};

Expand Down
19 changes: 18 additions & 1 deletion src/QueryBuilder/AbstractQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Yiisoft\Db\QueryBuilder;

use Yiisoft\Db\Command\CommandInterface;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\QueryBuilder\Condition\Interface\ConditionInterface;
Expand All @@ -24,6 +25,9 @@
*
* AbstractQueryBuilder is also used by {@see CommandInterface} to build SQL statements such as {@see insert()},
* {@see update()}, {@see delete()} and {@see createTable()}.
*
* @psalm-import-type ParamsType from ConnectionInterface
* @psalm-import-type BatchValues from DMLQueryBuilderInterface
*/
abstract class AbstractQueryBuilder implements QueryBuilderInterface
{
Expand Down Expand Up @@ -108,9 +112,22 @@ public function alterColumn(string $table, string $column, ColumnInterface|strin
return $this->ddlBuilder->alterColumn($table, $column, $type);
}

/**
* @param string[] $columns
*
* @psalm-param BatchValues $rows
* @psalm-param ParamsType $params
*
* @deprecated Use {@see insertBatch()} instead. It will be removed in version 3.0.0.
*/
public function batchInsert(string $table, array $columns, iterable $rows, array &$params = []): string
{
return $this->dmlBuilder->batchInsert($table, $columns, $rows, $params);
return $this->dmlBuilder->insertBatch($table, $rows, $columns, $params);
}

public function insertBatch(string $table, iterable $rows, array $columns = [], array &$params = []): string
{
return $this->dmlBuilder->insertBatch($table, $rows, $columns, $params);
}

public function bindParam(mixed $value, array &$params = []): string
Expand Down
20 changes: 15 additions & 5 deletions src/QueryBuilder/DMLQueryBuilderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @link https://en.wikipedia.org/wiki/Data_manipulation_language
*
* @psalm-import-type ParamsType from ConnectionInterface
* @psalm-type BatchValues = iterable<iterable<array-key, mixed>>
*/
interface DMLQueryBuilderInterface
{
Expand All @@ -27,32 +28,41 @@ interface DMLQueryBuilderInterface
* For example,
*
* ```php
* $sql = $queryBuilder->batchInsert('user', ['name', 'age'], [
* $sql = $queryBuilder->insertBatch('user', [
* ['Tom', 30],
* ['Jane', 20],
* ['Linda', 25],
* ], ['name', 'age']);
* ```
*
* or as associative arrays where the keys are column names
*
* ```php
* $queryBuilder->insertBatch('user', [
* ['name' => 'Tom', 'age' => 30],
* ['name' => 'Jane', 'age' => 20],
* ['name' => 'Linda', 'age' => 25],
* ]);
* ```
*
* @param string $table The table to insert new rows into.
* @param string[] $columns The column names of the table.
* @param iterable $rows The rows to batch-insert into the table.
* @param string[] $columns The column names of the table.
* @param array $params The binding parameters. This parameter exists.
*
* @throws Exception
* @throws InvalidArgumentException
*
* @return string The batch INSERT SQL statement.
*
* @psalm-param string[] $columns
* @psalm-param iterable<iterable<array-key, mixed>> $rows
* @psalm-param BatchValues $rows
* @psalm-param ParamsType $params
*
* Note:
* - That the values in each row must match the corresponding column names.
* - The method will escape the column names, and quote the values to insert.
*/
public function batchInsert(string $table, array $columns, iterable $rows, array &$params = []): string;
public function insertBatch(string $table, iterable $rows, array $columns = [], array &$params = []): string;

/**
* Creates a `DELETE` SQL statement.
Expand Down
Loading