Skip to content

Commit 292c352

Browse files
authored
Implement DMLQueryBuilder::upsertWithReturningPks() method (#408)
1 parent ae45569 commit 292c352

File tree

5 files changed

+84
-113
lines changed

5 files changed

+84
-113
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
- Enh #403, #404: Use `DbArrayHelper::arrange()` instead of `DbArrayHelper::index()` method (@Tigrov)
4141
- New #397: Realize `Schema::loadResultColumn()` method (@Tigrov)
4242
- New #407: Use `DateTimeColumn` class for datetime column types (@Tigrov)
43+
- New #408: Implement `DMLQueryBuilder::upsertWithReturningPks()` method (@Tigrov)
4344

4445
## 1.3.0 March 21, 2024
4546

src/DMLQueryBuilder.php

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,11 @@
1717
*/
1818
final class DMLQueryBuilder extends AbstractDMLQueryBuilder
1919
{
20-
public function insertWithReturningPks(string $table, QueryInterface|array $columns, array &$params = []): string
20+
public function insertWithReturningPks(string $table, array|QueryInterface $columns, array &$params = []): string
2121
{
2222
$sql = $this->insert($table, $columns, $params);
23-
$returnColumns = $this->schema->getTableSchema($table)?->getPrimaryKey();
24-
25-
if (!empty($returnColumns)) {
26-
$returnColumns = array_map($this->quoter->quoteColumnName(...), $returnColumns);
27-
28-
$sql .= ' RETURNING ' . implode(', ', $returnColumns);
29-
}
3023

31-
return $sql;
24+
return $this->appendReturningPksClause($sql, $table);
3225
}
3326

3427
public function resetSequence(string $table, int|string|null $value = null): string
@@ -60,9 +53,9 @@ public function resetSequence(string $table, int|string|null $value = null): str
6053

6154
public function upsert(
6255
string $table,
63-
QueryInterface|array $insertColumns,
64-
bool|array $updateColumns,
65-
array &$params = []
56+
array|QueryInterface $insertColumns,
57+
array|bool $updateColumns = true,
58+
array &$params = [],
6659
): string {
6760
$insertSql = $this->insert($table, $insertColumns, $params);
6861

@@ -93,4 +86,28 @@ public function upsert(
9386
return $insertSql
9487
. ' ON CONFLICT (' . implode(', ', $uniqueNames) . ') DO UPDATE SET ' . implode(', ', $updates);
9588
}
89+
90+
public function upsertWithReturningPks(
91+
string $table,
92+
array|QueryInterface $insertColumns,
93+
array|bool $updateColumns = true,
94+
array &$params = [],
95+
): string {
96+
$sql = $this->upsert($table, $insertColumns, $updateColumns, $params);
97+
98+
return $this->appendReturningPksClause($sql, $table);
99+
}
100+
101+
private function appendReturningPksClause(string $sql, string $table): string
102+
{
103+
$returnColumns = $this->schema->getTableSchema($table)?->getPrimaryKey();
104+
105+
if (!empty($returnColumns)) {
106+
$returnColumns = array_map($this->quoter->quoteColumnName(...), $returnColumns);
107+
108+
$sql .= ' RETURNING ' . implode(', ', $returnColumns);
109+
}
110+
111+
return $sql;
112+
}
96113
}

tests/Provider/QueryBuilderProvider.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,36 @@ public static function upsert(): array
317317
return $upsert;
318318
}
319319

320+
public static function upsertWithReturningPks(): array
321+
{
322+
$upsert = self::upsert();
323+
324+
foreach ($upsert as &$data) {
325+
$data[3] .= ' RETURNING "id"';
326+
}
327+
328+
$upsert['no columns to update'][3] = 'INSERT INTO "T_upsert_1" ("a") VALUES (:qp0) ON CONFLICT DO NOTHING RETURNING "a"';
329+
330+
return [
331+
...$upsert,
332+
'composite primary key' => [
333+
'notauto_pk',
334+
['id_1' => 1, 'id_2' => 2.5, 'type' => 'Test'],
335+
true,
336+
'INSERT INTO "notauto_pk" ("id_1", "id_2", "type") VALUES (:qp0, :qp1, :qp2)'
337+
. ' ON CONFLICT ("id_1", "id_2") DO UPDATE SET "type"=EXCLUDED."type" RETURNING "id_1", "id_2"',
338+
[':qp0' => 1, ':qp1' => 2.5, ':qp2' => 'Test'],
339+
],
340+
'no primary key' => [
341+
'type',
342+
['int_col' => 3, 'char_col' => 'a', 'float_col' => 1.2, 'bool_col' => true],
343+
true,
344+
'INSERT INTO "type" ("int_col", "char_col", "float_col", "bool_col") VALUES (:qp0, :qp1, :qp2, :qp3)',
345+
[':qp0' => 3, ':qp1' => 'a', ':qp2' => 1.2, ':qp3' => true],
346+
],
347+
];
348+
}
349+
320350
public static function overlapsCondition(): array
321351
{
322352
$data = parent::overlapsCondition();

0 commit comments

Comments
 (0)