Skip to content

Commit

Permalink
Refactor DMLQueryBuilder (#302)
Browse files Browse the repository at this point in the history
* Refactor DMLQueryBuilder

* Add line to CHANGELOG.md

* Fix after merge

* Revert "Apply Rector changes (CI)"

This reverts commit a127e1f.

* Remove `Generator` from tests
  • Loading branch information
Tigrov authored Nov 1, 2023
1 parent d48ca3a commit dcb2370
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Chg #297: Remove `QueryBuilder::getColumnType()` child method as legacy code (@Tigrov)
- Enh #300: Refactor insert default values (@Tigrov)
- Bug #302: Refactor `DMLQueryBuilder`, related with yiisoft/db#746 (@Tigrov)

## 1.0.1 July 24, 2023

Expand Down
30 changes: 9 additions & 21 deletions src/DMLQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@
use Yiisoft\Db\Exception\InvalidConfigException;
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Query\Query;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder;

use function implode;
use function reset;
use function str_replace;

/**
* Implements a DML (Data Manipulation Language) SQL statements for MySQL, MariaDB.
Expand Down Expand Up @@ -50,8 +49,7 @@ public function resetSequence(string $table, int|string $value = null): string
return 'ALTER TABLE ' . $tableName . ' AUTO_INCREMENT=' . $value . ';';
}

$pk = $tableSchema->getPrimaryKey();
$key = (string) reset($pk);
$key = $tableSchema->getPrimaryKey()[0];

return "SET @new_autoincrement_value := (SELECT MAX(`$key`) + 1 FROM $tableName);
SET @sql = CONCAT('ALTER TABLE $tableName AUTO_INCREMENT =', @new_autoincrement_value);
Expand All @@ -67,35 +65,24 @@ public function upsert(
): string {
$insertSql = $this->insert($table, $insertColumns, $params);

/** @psalm-var array $uniqueNames */
[$uniqueNames, , $updateNames] = $this->prepareUpsertColumns(
$table,
$insertColumns,
$updateColumns,
);
[$uniqueNames, , $updateNames] = $this->prepareUpsertColumns($table, $insertColumns, $updateColumns);

if (empty($uniqueNames)) {
return $insertSql;
}

if ($updateColumns === true) {
$updateColumns = [];
/** @psalm-var string $name */
foreach ($updateNames as $name) {
$updateColumns[$name] = new Expression(
'VALUES(' . $this->quoter->quoteColumnName($name) . ')'
);
/** @psalm-var string[] $updateNames */
foreach ($updateNames as $quotedName) {
$updateColumns[$quotedName] = new Expression('VALUES(' . $quotedName . ')');
}
}

if (empty($updateColumns)) {
return str_replace('INSERT INTO', 'INSERT IGNORE INTO', $insertSql);
}

/**
* @psalm-var array<array-key, string> $updates
* @psalm-var array<string, ExpressionInterface|string> $updateColumns
*/
[$updates, $params] = $this->prepareUpdateSets($table, $updateColumns, $params);

return $insertSql . ' ON DUPLICATE KEY UPDATE ' . implode(', ', $updates);
Expand All @@ -115,12 +102,13 @@ public function upsert(
* @throws InvalidConfigException
* @throws NotSupportedException
*
* @return array Array of column names, placeholders, values, and params.
* @return array Array of quoted column names, placeholders, values, and params.
* @psalm-return array{0: string[], 1: string[], 2: string, 3: array}
*/
protected function prepareInsertValues(string $table, QueryInterface|array $columns, array $params = []): array
{
if (empty($columns)) {
return [[], [], ' VALUES ()', []];
return [[], [], 'VALUES ()', []];
}

return parent::prepareInsertValues($table, $columns, $params);
Expand Down
4 changes: 4 additions & 0 deletions tests/Provider/QueryBuilderProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ public static function upsert(): array
3 => 'INSERT INTO `T_upsert` (`email`, `address`, `status`, `profile_id`) VALUES (:qp0, :qp1, :qp2, :qp3) ' .
'ON DUPLICATE KEY UPDATE `address`=VALUES(`address`), `status`=VALUES(`status`), `profile_id`=VALUES(`profile_id`)',
],
'regular values with unique at not the first position' => [
3 => 'INSERT INTO `T_upsert` (`address`, `email`, `status`, `profile_id`) VALUES (:qp0, :qp1, :qp2, :qp3) ' .
'ON DUPLICATE KEY UPDATE `address`=VALUES(`address`), `status`=VALUES(`status`), `profile_id`=VALUES(`profile_id`)',
],
'regular values with update part' => [
3 => 'INSERT INTO `T_upsert` (`email`, `address`, `status`, `profile_id`) VALUES (:qp0, :qp1, :qp2, :qp3) ' .
'ON DUPLICATE KEY UPDATE `address`=:qp4, `status`=:qp5, `orders`=T_upsert.orders + 1',
Expand Down
3 changes: 1 addition & 2 deletions tests/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace Yiisoft\Db\Mysql\Tests;

use Generator;
use Throwable;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidArgumentException;
Expand Down Expand Up @@ -143,7 +142,7 @@ public function testAddUnique(string $name, string $table, array|string $columns
* @throws InvalidArgumentException
* @throws NotSupportedException
*/
public function testBatchInsert(string $table, array $columns, iterable|Generator $rows, string $expected): void
public function testBatchInsert(string $table, array $columns, iterable $rows, string $expected): void
{
parent::testBatchInsert($table, $columns, $rows, $expected);
}
Expand Down

0 comments on commit dcb2370

Please sign in to comment.