Test Failed
Pull Request — master (#83)
by Wilmer
16:31 queued 13:03
created

QueryBuilderPDOSqlite::build()   B

Complexity

Conditions 10
Paths 32

Size

Total Lines 47
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 26
dl 0
loc 47
rs 7.6666
c 1
b 0
f 0
cc 10
nc 32
nop 2

How to fix   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\PDO;
6
7
use Generator;
8
use Yiisoft\Db\Command\CommandInterface;
9
use Yiisoft\Db\Exception\NotSupportedException;
10
use Yiisoft\Db\Expression\Expression;
11
use Yiisoft\Db\Expression\ExpressionBuilder;
12
use Yiisoft\Db\Expression\ExpressionInterface;
13
use Yiisoft\Db\Query\Conditions\InCondition;
14
use Yiisoft\Db\Query\Conditions\LikeCondition;
15
use Yiisoft\Db\Query\Query;
16
use Yiisoft\Db\Query\QueryBuilder;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\QueryBuilder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Yiisoft\Db\Schema\QuoterInterface;
18
use Yiisoft\Db\Schema\Schema;
19
use Yiisoft\Db\Schema\SchemaInterface;
20
use Yiisoft\Db\Sqlite\Condition\InConditionBuilder;
21
use Yiisoft\Db\Sqlite\Condition\LikeConditionBuilder;
22
use Yiisoft\Db\Sqlite\DDLQueryBuilder;
23
use Yiisoft\Db\Sqlite\DMLQueryBuilder;
24
25
use function array_filter;
26
use function array_merge;
27
use function implode;
28
use function trim;
29
30
final class QueryBuilderPDOSqlite extends QueryBuilder
31
{
32
    /**
33
     * @var array mapping from abstract column types (keys) to physical column types (values).
34
     *
35
     * @psalm-var string[] $typeMap
36
     */
37
    protected array $typeMap = [
38
        Schema::TYPE_PK => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL',
39
        Schema::TYPE_UPK => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL',
40
        Schema::TYPE_BIGPK => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL',
41
        Schema::TYPE_UBIGPK => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL',
42
        Schema::TYPE_CHAR => 'char(1)',
43
        Schema::TYPE_STRING => 'varchar(255)',
44
        Schema::TYPE_TEXT => 'text',
45
        Schema::TYPE_TINYINT => 'tinyint',
46
        Schema::TYPE_SMALLINT => 'smallint',
47
        Schema::TYPE_INTEGER => 'integer',
48
        Schema::TYPE_BIGINT => 'bigint',
49
        Schema::TYPE_FLOAT => 'float',
50
        Schema::TYPE_DOUBLE => 'double',
51
        Schema::TYPE_DECIMAL => 'decimal(10,0)',
52
        Schema::TYPE_DATETIME => 'datetime',
53
        Schema::TYPE_TIMESTAMP => 'timestamp',
54
        Schema::TYPE_TIME => 'time',
55
        Schema::TYPE_DATE => 'date',
56
        Schema::TYPE_BINARY => 'blob',
57
        Schema::TYPE_BOOLEAN => 'boolean',
58
        Schema::TYPE_MONEY => 'decimal(19,4)',
59
    ];
60
61
    public function __construct(
62
        private CommandInterface $command,
63
        private QuoterInterface $quoter,
64
        private SchemaInterface $schema
65
    ) {
66
        $this->ddlBuilder = new DDLQueryBuilder($this);
0 ignored issues
show
Bug Best Practice introduced by
The property ddlBuilder does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
67
        $this->dmlBuilder = new DMLQueryBuilder($this);
0 ignored issues
show
Bug Best Practice introduced by
The property dmlBuilder does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
68
        parent::__construct($quoter, $schema);
69
    }
70
71
    public function addForeignKey(
72
        string $name,
73
        string $table,
74
        array|string $columns,
75
        string $refTable,
76
        array|string $refColumns,
77
        ?string $delete = null,
78
        ?string $update = null
79
    ): string {
80
        return $this->ddlBuilder->addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete, $update);
81
    }
82
83
    /**
84
     * @throws NotSupportedException
85
     */
86
    public function addPrimaryKey(string $name, string $table, array|string $columns): string
87
    {
88
        return $this->ddlBuilder->addPrimaryKey($name, $table, $columns);
89
    }
90
91
    /**
92
     * @throws NotSupportedException
93
     */
94
    public function addUnique(string $name, string $table, array|string $columns): string
95
    {
96
        return $this->ddlBuilder->addUnique($name, $table, $columns);
97
    }
98
99
    /**
100
     * @throws NotSupportedException
101
     */
102
    public function alterColumn(string $table, string $column, string $type): string
103
    {
104
        return $this->ddlBuilder->alterColumn($table, $column, $type);
105
    }
106
107
    public function batchInsert(string $table, array $columns, iterable|Generator $rows, array &$params = []): string
108
    {
109
        return $this->dmlBuilder->batchInsert($table, $columns, $rows, $params);
110
    }
111
112
    public function build(Query $query, array $params = []): array
113
    {
114
        $query = $query->prepare($this);
115
116
        $params = empty($params) ? $query->getParams() : array_merge($params, $query->getParams());
117
118
        $clauses = [
119
            $this->buildSelect($query->getSelect(), $params, $query->getDistinct(), $query->getSelectOption()),
120
            $this->buildFrom($query->getFrom(), $params),
121
            $this->buildJoin($query->getJoin(), $params),
122
            $this->buildWhere($query->getWhere(), $params),
123
            $this->buildGroupBy($query->getGroupBy()),
124
            $this->buildHaving($query->getHaving(), $params),
125
        ];
126
127
        $sql = implode($this->separator, array_filter($clauses));
128
        $sql = $this->buildOrderByAndLimit($sql, $query->getOrderBy(), $query->getLimit(), $query->getOffset());
129
130
        if (!empty($query->getOrderBy())) {
131
            foreach ($query->getOrderBy() as $expression) {
132
                if ($expression instanceof ExpressionInterface) {
133
                    $this->buildExpression($expression, $params);
134
                }
135
            }
136
        }
137
138
        if (!empty($query->getGroupBy())) {
139
            foreach ($query->getGroupBy() as $expression) {
140
                if ($expression instanceof ExpressionInterface) {
141
                    $this->buildExpression($expression, $params);
142
                }
143
            }
144
        }
145
146
        $union = $this->buildUnion($query->getUnion(), $params);
147
148
        if ($union !== '') {
149
            $sql = "$sql$this->separator$union";
150
        }
151
152
        $with = $this->buildWithQueries($query->getWithQueries(), $params);
153
154
        if ($with !== '') {
155
            $sql = "$with$this->separator$sql";
156
        }
157
158
        return [$sql, $params];
159
    }
160
161
    public function buildLimit(Expression|int|null $limit, Expression|int|null $offset): string
162
    {
163
        $sql = '';
164
165
        if ($this->hasLimit($limit)) {
166
            $sql = "LIMIT $limit";
167
            if ($this->hasOffset($offset)) {
168
                $sql .= " OFFSET $offset";
169
            }
170
        } elseif ($this->hasOffset($offset)) {
171
            /**
172
             * limit is not optional in SQLite.
173
             *
174
             * {@see http://www.sqlite.org/syntaxdiagrams.html#select-stmt}
175
             */
176
            $sql = "LIMIT 9223372036854775807 OFFSET $offset"; // 2^63-1
177
        }
178
179
        return $sql;
180
    }
181
182
    public function buildUnion(array $unions, array &$params = []): string
183
    {
184
        if (empty($unions)) {
185
            return '';
186
        }
187
188
        $result = '';
189
190
        foreach ($unions as $i => $union) {
191
            $query = $union['query'];
192
            if ($query instanceof Query) {
193
                [$unions[$i]['query'], $params] = $this->build($query, $params);
194
            }
195
196
            $result .= ' UNION ' . ($union['all'] ? 'ALL ' : '') . ' ' . $unions[$i]['query'];
197
        }
198
199
        return trim($result);
200
    }
201
202
    public function checkIntegrity(string $schema = '', string $table = '', bool $check = true): string
203
    {
204
        return $this->ddlBuilder->checkIntegrity($schema, $table, $check);
205
    }
206
207
    public function createIndex(string $name, string $table, $columns, bool $unique = false): string
208
    {
209
        return $this->ddlBuilder->createIndex($name, $table, $columns, $unique);
210
    }
211
212
    public function command(): CommandInterface
213
    {
214
        return $this->command;
215
    }
216
217
    /**
218
     * @throws NotSupportedException
219
     */
220
    public function dropColumn(string $table, string $column): string
221
    {
222
        return $this->ddlBuilder->dropColumn($table, $column);
223
    }
224
225
    /**
226
     * @throws NotSupportedException
227
     */
228
    public function dropForeignKey(string $name, string $table): string
229
    {
230
        return $this->ddlBuilder->dropForeignKey($name, $table);
231
    }
232
233
    public function dropIndex(string $name, string $table): string
234
    {
235
        return $this->ddlBuilder->dropIndex($name, $table);
236
    }
237
238
    /**
239
     * @throws NotSupportedException
240
     */
241
    public function dropPrimaryKey(string $name, string $table): string
242
    {
243
        return $this->ddlBuilder->dropPrimaryKey($name, $table);
244
    }
245
246
    /**
247
     * @throws NotSupportedException
248
     */
249
    public function dropUnique(string $name, string $table): string
250
    {
251
        return $this->ddlBuilder->dropUnique($name, $table);
252
    }
253
254
    public function quoter(): QuoterInterface
255
    {
256
        return $this->quoter;
257
    }
258
259
    public function schema(): SchemaInterface
260
    {
261
        return $this->schema;
262
    }
263
264
    /**
265
     * @throws NotSupportedException
266
     */
267
    public function renameColumn(string $table, string $oldName, string $newName): string
268
    {
269
        return $this->ddlBuilder->renameColumn($table, $oldName, $newName);
270
    }
271
272
    public function renameTable(string $oldName, string $newName): string
273
    {
274
        return $this->ddlBuilder->renameTable($oldName, $newName);
275
    }
276
277
    public function truncateTable(string $table): string
278
    {
279
        return $this->ddlBuilder->truncateTable($table);
280
    }
281
282
    /**
283
     * Contains array of default expression builders. Extend this method and override it, if you want to change default
284
     * expression builders for this query builder.
285
     *
286
     * @return array
287
     *
288
     * See {@see ExpressionBuilder} docs for details.
289
     */
290
    protected function defaultExpressionBuilders(): array
291
    {
292
        return array_merge(parent::defaultExpressionBuilders(), [
293
            LikeCondition::class => LikeConditionBuilder::class,
294
            InCondition::class => InConditionBuilder::class,
295
        ]);
296
    }
297
}
298