Test Failed
Pull Request — master (#229)
by Wilmer
23:59 queued 19:53
created

DMLQueryBuilder::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 6
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Sqlite;
6
7
use Yiisoft\Db\Constraint\Constraint;
8
use Yiisoft\Db\Exception\InvalidArgumentException;
9
use Yiisoft\Db\Exception\NotSupportedException;
10
use Yiisoft\Db\Expression\Expression;
11
use Yiisoft\Db\Expression\ExpressionInterface;
12
use Yiisoft\Db\Query\QueryInterface;
13
use Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder;
14
15
use function implode;
16
use function ltrim;
17
use function reset;
18
19
/**
20
 * Implements a DML (Data Manipulation Language) SQL statements for SQLite Server.
21
 */
22
final class DMLQueryBuilder extends AbstractDMLQueryBuilder
23
{
24
    public function insertWithReturningPks(string $table, QueryInterface|array $columns, array &$params = []): string
25
    {
26
        throw new NotSupportedException(__METHOD__ . '() is not supported by SQLite.');
27 507
    }
28
29
    public function resetSequence(string $tableName, int|string $value = null): string
30
    {
31
        $table = $this->schema->getTableSchema($tableName);
0 ignored issues
show
Bug introduced by
The property schema is declared private in Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder and cannot be accessed from this context.
Loading history...
32 507
33
        if ($table === null) {
34
            throw new InvalidArgumentException("Table not found: '$tableName'.");
35 1
        }
36
37 1
        $sequenceName = $table->getSequenceName();
38
39
        if ($sequenceName === null) {
40 5
            throw new InvalidArgumentException("There is not sequence associated with table '$tableName'.'");
41
        }
42 5
43
        $tableName = $this->quoter->quoteTableName($tableName);
0 ignored issues
show
Bug introduced by
The property quoter is declared private in Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder and cannot be accessed from this context.
Loading history...
44 5
45 1
        if ($value !== null) {
46
            $value = "'" . ((int) $value - 1) . "'";
47
        } else {
48 4
            $pk = $table->getPrimaryKey();
49
            $key = $this->quoter->quoteColumnName(reset($pk));
50 4
            $value = '(SELECT MAX(' . $key . ') FROM ' . $tableName . ')';
51 1
        }
52
53
        return 'UPDATE sqlite_sequence SET seq=' . $value . " WHERE name='" . $table->getName() . "'";
54 3
    }
55
56 3
    public function upsert(
57 2
        string $table,
58
        QueryInterface|array $insertColumns,
59 3
        bool|array $updateColumns,
60 3
        array &$params
61 3
    ): string {
62
        /** @psalm-var Constraint[] $constraints */
63
        $constraints = [];
64 3
65
        /**
66
         * @psalm-var string[] $insertNames
67 34
         * @psalm-var string[] $updateNames
68
         * @psalm-var array<string, ExpressionInterface|string>|bool $updateColumns
69
         */
70
        [$uniqueNames, $insertNames, $updateNames] = $this->prepareUpsertColumns(
71
            $table,
72
            $insertColumns,
73
            $updateColumns,
74 34
            $constraints
75
        );
76
77
        if (empty($uniqueNames)) {
78
            return $this->insert($table, $insertColumns, $params);
79
        }
80
81 34
        /** @psalm-var string[] $placeholders */
82 34
        [, $placeholders, $values, $params] = $this->prepareInsertValues($table, $insertColumns, $params);
83 34
84 34
        $insertSql = 'INSERT OR IGNORE INTO '
85 34
            . $this->quoter->quoteTableName($table)
0 ignored issues
show
Bug introduced by
The property quoter is declared private in Yiisoft\Db\QueryBuilder\AbstractDMLQueryBuilder and cannot be accessed from this context.
Loading history...
86 34
            . (!empty($insertNames) ? ' (' . implode(', ', $insertNames) . ')' : '')
87
            . (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : "$values");
88 34
89 2
        if ($updateColumns === false) {
0 ignored issues
show
introduced by
The condition $updateColumns === false is always false.
Loading history...
90
            return $insertSql;
91
        }
92
93 32
        $updateCondition = ['or'];
94
        $quotedTableName = $this->quoter->quoteTableName($table);
95 32
96 32
        foreach ($constraints as $constraint) {
97 32
            $constraintCondition = ['and'];
98 32
            /** @psalm-var string[] $columnNames */
99
            $columnNames = $constraint->getColumnNames();
100 32
            foreach ($columnNames as $name) {
101 12
                $quotedName = $this->quoter->quoteColumnName($name);
102
                $constraintCondition[] = "$quotedTableName.$quotedName=(SELECT $quotedName FROM `EXCLUDED`)";
103
            }
104 20
            $updateCondition[] = $constraintCondition;
105 20
        }
106
107 20
        if ($updateColumns === true) {
0 ignored issues
show
introduced by
The condition $updateColumns === true is always false.
Loading history...
108 20
            $updateColumns = [];
109
            foreach ($updateNames as $name) {
110 20
                $quotedName = $this->quoter->quoteColumnName($name);
111 20
112 20
                if (strrpos($quotedName, '.') === false) {
113 20
                    $quotedName = "(SELECT $quotedName FROM `EXCLUDED`)";
114
                }
115 20
                $updateColumns[$name] = new Expression($quotedName);
116
            }
117
        }
118 20
119 10
        if ($updateColumns === []) {
120 10
            return $insertSql;
121 8
        }
122
123 8
        /** @psalm-var array $params */
124 8
        $updateSql = 'WITH "EXCLUDED" ('
125
            . implode(', ', $insertNames)
126 8
            . ') AS (' . (!empty($placeholders)
127
                ? 'VALUES (' . implode(', ', $placeholders) . ')'
128
                : ltrim("$values", ' ')) . ') ' .
129
                $this->update($table, $updateColumns, $updateCondition, $params);
130 20
131 2
        return "$updateSql; $insertSql;";
132
    }
133
}
134