Test Failed
Pull Request — dev (#106)
by Def
23:40 queued 20:10
created

DMLQueryBuilder::truncateTable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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