Issues (21)

src/DMLQueryBuilder.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Pgsql;
6
7
use Yiisoft\Db\Exception\InvalidArgumentException;
8
use Yiisoft\Db\Expression\Expression;
9
use Yiisoft\Db\Query\QueryInterface;
10
use Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder;
11
12
use function array_map;
13
use function implode;
14
15
/**
16
 * Implements a DML (Data Manipulation Language) SQL statements for PostgreSQL Server.
17
 */
18
final class DMLQueryBuilder extends AbstractDMLQueryBuilder
19
{
20 12
    public function insertWithReturningPks(string $table, QueryInterface|array $columns, array &$params = []): string
21
    {
22 12
        $sql = $this->insert($table, $columns, $params);
23 12
        $returnColumns = $this->schema->getTableSchema($table)?->getPrimaryKey();
24
25 12
        if (!empty($returnColumns)) {
26 11
            $returnColumns = array_map(
27 11
                [$this->quoter, 'quoteColumnName'],
28 11
                $returnColumns,
29 11
            );
30
31 11
            $sql .= ' RETURNING ' . implode(', ', $returnColumns);
32
        }
33
34 12
        return $sql;
35
    }
36
37 5
    public function resetSequence(string $table, int|string $value = null): string
38
    {
39 5
        $tableSchema = $this->schema->getTableSchema($table);
40
41 5
        if ($tableSchema === null) {
42 1
            throw new InvalidArgumentException("Table not found: '$table'.");
43
        }
44
45 4
        $sequence = $tableSchema->getSequenceName();
46
47 4
        if ($sequence === null) {
48 1
            throw new InvalidArgumentException("There is not sequence associated with table '$table'.");
49
        }
50
51
        /** @link https://www.postgresql.org/docs/8.1/static/functions-sequence.html */
52 3
        $sequence = $this->quoter->quoteTableName($sequence);
53
54 3
        if ($value === null) {
55 3
            $table = $this->quoter->quoteTableName($table);
56 3
            $key = $tableSchema->getPrimaryKey()[0];
57 3
            $key = $this->quoter->quoteColumnName($key);
58 3
            $value = "(SELECT COALESCE(MAX($key),0) FROM $table)+1";
59
        }
60
61 3
        return "SELECT SETVAL('$sequence',$value,false)";
62
    }
63
64 38
    public function upsert(
65
        string $table,
66
        QueryInterface|array $insertColumns,
67
        bool|array $updateColumns,
68
        array &$params = []
69
    ): string {
70 38
        $insertSql = $this->insert($table, $insertColumns, $params);
71
72 38
        [$uniqueNames, , $updateNames] = $this->prepareUpsertColumns($table, $insertColumns, $updateColumns);
73
74 38
        if (empty($uniqueNames)) {
75 2
            return $insertSql;
76
        }
77
78 36
        if ($updateColumns === false || $updateNames === []) {
79
            /** there are no columns to update */
80 14
            return "$insertSql ON CONFLICT DO NOTHING";
81
        }
82
83 22
        if ($updateColumns === true) {
0 ignored issues
show
The condition $updateColumns === true is always false.
Loading history...
84 12
            $updateColumns = [];
85
86
            /** @psalm-var string[] $updateNames */
87 12
            foreach ($updateNames as $name) {
88 12
                $updateColumns[$name] = new Expression(
89 12
                    'EXCLUDED.' . $this->quoter->quoteColumnName($name)
90 12
                );
91
            }
92
        }
93
94 22
        [$updates, $params] = $this->prepareUpdateSets($table, $updateColumns, $params);
95
96 22
        return $insertSql
97 22
            . ' ON CONFLICT (' . implode(', ', $uniqueNames) . ') DO UPDATE SET ' . implode(', ', $updates);
98
    }
99
}
100