Skip to content

Commit e94059b

Browse files
authored
Update according changes in db package (#423)
1 parent 320fe4e commit e94059b

File tree

4 files changed

+14
-34
lines changed

4 files changed

+14
-34
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
- Enh #415: Support column's collation (@Tigrov)
5252
- New #421: Add `Connection::getColumnBuilderClass()` method (@Tigrov)
5353
- New #420: Implement `ArrayMergeBuilder`, `LongestBuilder` and `ShortestBuilder` classes (@Tigrov)
54+
- Enh #423: Refactor `DMLQueryBuilder::upsert()` method (@Tigrov)
5455

5556
## 1.2.0 March 21, 2024
5657

src/DMLQueryBuilder.php

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66

77
use InvalidArgumentException;
88
use Yiisoft\Db\Exception\NotSupportedException;
9-
use Yiisoft\Db\Expression\Expression;
109
use Yiisoft\Db\Expression\ExpressionInterface;
1110
use Yiisoft\Db\Query\QueryInterface;
1211
use Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder;
1312
use Yiisoft\Db\Schema\TableSchema;
1413

1514
use function array_combine;
1615
use function array_diff;
16+
use function array_fill_keys;
1717
use function array_intersect;
18+
use function array_intersect_key;
1819
use function array_key_exists;
1920
use function array_keys;
2021
use function array_map;
@@ -74,15 +75,8 @@ public function upsert(
7475
return $this->insert($table, $insertColumns, $params);
7576
}
7677

77-
if ($updateColumns === true) {
78-
$updateColumns = [];
79-
/** @psalm-var string[] $updateNames */
80-
foreach ($updateNames as $name) {
81-
$updateColumns[$name] = new Expression('EXCLUDED.' . $this->quoter->quoteSimpleColumnName($name));
82-
}
83-
}
84-
85-
if (empty($updateColumns)) {
78+
if (empty($updateColumns) || $updateNames === []) {
79+
/** there are no columns to update */
8680
$insertSql = $this->insert($table, $insertColumns, $params);
8781
return 'INSERT IGNORE' . substr($insertSql, 6);
8882
}
@@ -92,21 +86,15 @@ public function upsert(
9286
$quotedNames = array_map($this->quoter->quoteColumnName(...), $names);
9387

9488
if (!empty($placeholders)) {
95-
$selectValues = [];
96-
97-
foreach ($placeholders as $i => $placeholder) {
98-
$selectValues[] = "$placeholder AS $quotedNames[$i]";
99-
}
100-
101-
$values = 'SELECT ' . implode(', ', $selectValues);
89+
$values = $this->buildSimpleSelect(array_combine($names, $placeholders));
10290
}
10391

10492
$fields = implode(', ', $quotedNames);
10593

10694
$insertSql = 'INSERT INTO ' . $this->quoter->quoteTableName($table)
10795
. " ($fields) SELECT $fields FROM ($values) AS EXCLUDED";
10896

109-
$updates = $this->prepareUpdateSets($table, $updateColumns, $params);
97+
$updates = $this->prepareUpsertSets($table, $updateColumns, $updateNames, $params);
11098

11199
return $insertSql . ' ON DUPLICATE KEY UPDATE ' . implode(', ', $updates);
112100
}
@@ -140,13 +128,8 @@ public function upsertReturning(
140128

141129
if (empty($uniqueColumns)) {
142130
$returnValues = $this->prepareColumnValues($tableSchema, $returnColumns, $insertColumns, $params);
143-
$selectValues = [];
144-
145-
foreach ($returnValues as $name => $value) {
146-
$selectValues[] = $value . ' AS ' . $quoter->quoteSimpleColumnName($name);
147-
}
148131

149-
return $upsertSql . ';SELECT ' . implode(', ', $selectValues);
132+
return $upsertSql . ';' . $this->buildSimpleSelect($returnValues);
150133
}
151134

152135
if (is_array($updateColumns) && !empty(array_intersect($uniqueColumns, array_keys($updateColumns)))) {
@@ -172,13 +155,9 @@ public function upsertReturning(
172155
$uniqueValues = $this->prepareColumnValues($tableSchema, $uniqueColumns, $insertColumns, $params);
173156

174157
if (empty(array_diff($returnColumns, array_keys($uniqueValues)))) {
175-
$selectValues = [];
176-
177-
foreach ($returnColumns as $name) {
178-
$selectValues[] = $uniqueValues[$name] . ' AS ' . $quoter->quoteSimpleColumnName($name);
179-
}
158+
$selectValues = array_intersect_key($uniqueValues, array_fill_keys($returnColumns, null));
180159

181-
return $upsertSql . ';SELECT ' . implode(', ', $selectValues);
160+
return $upsertSql . ';' . $this->buildSimpleSelect($selectValues);
182161
}
183162

184163
$conditions = [];

tests/Provider/QueryBuilderProvider.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public static function upsert(): array
6363
3 => 'INSERT INTO `T_upsert` (`email`, `address`, `status`, `profile_id`)'
6464
. ' SELECT `email`, `address`, `status`, `profile_id`'
6565
. ' FROM (SELECT :qp0 AS `email`, :qp1 AS `address`, :qp2 AS `status`, :qp3 AS `profile_id`) AS EXCLUDED'
66-
. ' ON DUPLICATE KEY UPDATE `address`=:qp4, `status`=:qp5, `orders`=T_upsert.orders + 1',
66+
. ' ON DUPLICATE KEY UPDATE `address`=:qp4, `status`=2, `orders`=T_upsert.orders + 1',
6767
],
6868
'regular values without update part' => [
6969
3 => 'INSERT IGNORE INTO `T_upsert` (`email`, `address`, `status`, `profile_id`) VALUES (:qp0, :qp1, :qp2, :qp3)',
@@ -76,7 +76,7 @@ public static function upsert(): array
7676
'query with update part' => [
7777
3 => 'INSERT INTO `T_upsert` (`email`, `status`) SELECT `email`, `status`'
7878
. ' FROM (SELECT `email`, 2 AS `status` FROM `customer` WHERE `name` = :qp0 LIMIT 1) AS EXCLUDED'
79-
. ' ON DUPLICATE KEY UPDATE `address`=:qp1, `status`=:qp2, `orders`=T_upsert.orders + 1',
79+
. ' ON DUPLICATE KEY UPDATE `address`=:qp1, `status`=2, `orders`=T_upsert.orders + 1',
8080
],
8181
'query without update part' => [
8282
3 => 'INSERT IGNORE INTO `T_upsert` (`email`, `status`) SELECT `email`, 2 AS `status` FROM `customer`'
@@ -98,7 +98,7 @@ public static function upsert(): array
9898
'query, values and expressions with update part' => [
9999
3 => 'INSERT INTO {{%T_upsert}} (`email`, [[ts]]) SELECT `email`, [[ts]]'
100100
. ' FROM (SELECT :phEmail AS `email`, CURRENT_TIMESTAMP AS [[ts]]) AS EXCLUDED'
101-
. ' ON DUPLICATE KEY UPDATE `ts`=:qp1, `orders`=T_upsert.orders + 1',
101+
. ' ON DUPLICATE KEY UPDATE `ts`=0, `orders`=T_upsert.orders + 1',
102102
],
103103
'query, values and expressions without update part' => [
104104
3 => 'INSERT IGNORE INTO `T_upsert` (`email`, [[ts]]) SELECT :phEmail AS `email`, CURRENT_TIMESTAMP AS [[ts]]',

tests/QueryBuilderTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ public function testUpdate(
573573
array|string $condition,
574574
array $params,
575575
string $expectedSql,
576-
array $expectedParams,
576+
array $expectedParams = [],
577577
): void {
578578
parent::testUpdate($table, $columns, $condition, $params, $expectedSql, $expectedParams);
579579
}

0 commit comments

Comments
 (0)