diff --git a/CHANGELOG.md b/CHANGELOG.md index 4631dece9..b1923affd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ - Enh #433: Support column's collation (@Tigrov) - New #440: Add `Connection::getColumnBuilderClass()` method (@Tigrov) - New #439: Implement `ArrayMergeBuilder` class (@Tigrov) +- Enh #442: Refactor `DMLQueryBuilder::upsert()` method (@Tigrov) ## 1.3.0 March 21, 2024 diff --git a/src/DMLQueryBuilder.php b/src/DMLQueryBuilder.php index 243523fd9..0b5bee0b5 100644 --- a/src/DMLQueryBuilder.php +++ b/src/DMLQueryBuilder.php @@ -5,7 +5,6 @@ namespace Yiisoft\Db\Pgsql; use InvalidArgumentException; -use Yiisoft\Db\Expression\Expression; use Yiisoft\Db\Query\QueryInterface; use Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder; @@ -75,24 +74,13 @@ public function upsert( return $insertSql; } - if ($updateColumns === false || $updateNames === []) { + if (empty($updateColumns) || $updateNames === []) { /** there are no columns to update */ return "$insertSql ON CONFLICT DO NOTHING"; } - if ($updateColumns === true) { - $updateColumns = []; - - /** @psalm-var string[] $updateNames */ - foreach ($updateNames as $name) { - $updateColumns[$name] = new Expression( - 'EXCLUDED.' . $this->quoter->quoteColumnName($name) - ); - } - } - $quotedUniqueNames = array_map($this->quoter->quoteColumnName(...), $uniqueNames); - $updates = $this->prepareUpdateSets($table, $updateColumns, $params); + $updates = $this->prepareUpsertSets($table, $updateColumns, $updateNames, $params); return $insertSql . ' ON CONFLICT (' . implode(', ', $quotedUniqueNames) . ')' diff --git a/tests/Provider/QueryBuilderProvider.php b/tests/Provider/QueryBuilderProvider.php index 4aa1367e2..58366b128 100644 --- a/tests/Provider/QueryBuilderProvider.php +++ b/tests/Provider/QueryBuilderProvider.php @@ -236,7 +236,7 @@ public static function upsert(): array 2 => ['address' => 'foo {{city}}', 'status' => 2, 'orders' => new Expression('"T_upsert"."orders" + 1')], 3 => 'INSERT INTO "T_upsert" ("email", "address", "status", "profile_id") ' . 'VALUES (:qp0, :qp1, :qp2, :qp3) ON CONFLICT ("email") ' . - 'DO UPDATE SET "address"=:qp4, "status"=:qp5, "orders"="T_upsert"."orders" + 1', + 'DO UPDATE SET "address"=:qp4, "status"=2, "orders"="T_upsert"."orders" + 1', ], 'regular values without update part' => [ 3 => 'INSERT INTO "T_upsert" ("email", "address", "status", "profile_id") ' . @@ -249,7 +249,7 @@ public static function upsert(): array 'query with update part' => [ 2 => ['address' => 'foo {{city}}', 'status' => 2, 'orders' => new Expression('"T_upsert"."orders" + 1')], 3 => 'INSERT INTO "T_upsert" ("email", "status") SELECT "email", 2 AS "status" FROM "customer" ' . - 'WHERE "name" = :qp0 LIMIT 1 ON CONFLICT ("email") DO UPDATE SET "address"=:qp1, "status"=:qp2, "orders"="T_upsert"."orders" + 1', + 'WHERE "name" = :qp0 LIMIT 1 ON CONFLICT ("email") DO UPDATE SET "address"=:qp1, "status"=2, "orders"="T_upsert"."orders" + 1', ], 'query without update part' => [ 3 => 'INSERT INTO "T_upsert" ("email", "status") SELECT "email", 2 AS "status" FROM "customer" ' . @@ -280,7 +280,7 @@ public static function upsert(): array ), 2 => ['ts' => 0, '[[orders]]' => new Expression('EXCLUDED.orders + 1')], 3 => 'INSERT INTO {{%T_upsert}} ("email", [[ts]]) SELECT :phEmail AS "email", extract(epoch from now()) * 1000 AS [[ts]] ' . - 'ON CONFLICT ("email") DO UPDATE SET "ts"=:qp1, "orders"=EXCLUDED.orders + 1', + 'ON CONFLICT ("email") DO UPDATE SET "ts"=0, "orders"=EXCLUDED.orders + 1', ], 'query, values and expressions without update part' => [ 1 => (new Query(self::getDb())) diff --git a/tests/QueryBuilderTest.php b/tests/QueryBuilderTest.php index 782fe5b16..b601d6b0d 100644 --- a/tests/QueryBuilderTest.php +++ b/tests/QueryBuilderTest.php @@ -429,7 +429,7 @@ public function testUpdate( array|string $condition, array $params, string $expectedSql, - array $expectedParams, + array $expectedParams = [], ): void { parent::testUpdate($table, $columns, $condition, $params, $expectedSql, $expectedParams); }