Test Failed
Push — master ( 6bf147...11f981 )
by Sergei
14:04 queued 09:48
created

DMLQueryBuilder::upsert()   B

Complexity

Conditions 11
Paths 77

Size

Total Lines 62
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 11

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 33
c 3
b 0
f 0
dl 0
loc 62
ccs 33
cts 33
cp 1
rs 7.3166
cc 11
nc 77
nop 4
crap 11

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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