Passed
Pull Request — dev (#107)
by Def
06:03 queued 01:55
created

DQLQueryBuilder::defaultExpressionBuilders()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 5
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Sqlite;
6
7
use Yiisoft\Db\Expression\Expression;
8
use Yiisoft\Db\Expression\ExpressionBuilderInterface;
9
use Yiisoft\Db\Expression\ExpressionInterface;
10
use Yiisoft\Db\Query\Conditions\InCondition;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\Conditions\InCondition 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...
11
use Yiisoft\Db\Query\Conditions\LikeCondition;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\Conditions\LikeCondition 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...
12
use Yiisoft\Db\Query\DQLQueryBuilder as AbstractDQLQueryBuilder;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\DQLQueryBuilder 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...
13
use Yiisoft\Db\Query\Query;
14
use Yiisoft\Db\Query\QueryBuilderInterface;
15
use Yiisoft\Db\Query\QueryInterface;
16
use Yiisoft\Db\Schema\QuoterInterface;
17
use Yiisoft\Db\Schema\SchemaInterface;
18
use Yiisoft\Db\Sqlite\Builder\InConditionBuilder;
19
use Yiisoft\Db\Sqlite\Builder\LikeConditionBuilder;
20
21
use function array_filter;
22
use function array_merge;
23
use function implode;
24
use function trim;
25
26
final class DQLQueryBuilder extends AbstractDQLQueryBuilder
27
{
28 336
    public function __construct(
29
        private QueryBuilderInterface $queryBuilder,
30
        QuoterInterface $quoter,
31
        SchemaInterface $schema
32
    ) {
33 336
        parent::__construct($queryBuilder, $quoter, $schema);
34
    }
35
36 163
    public function build(QueryInterface $query, array $params = []): array
37
    {
38 163
        $query = $query->prepare($this->queryBuilder);
39
40 163
        $params = empty($params) ? $query->getParams() : array_merge($params, $query->getParams());
41
42 163
        $clauses = [
43 163
            $this->buildSelect($query->getSelect(), $params, $query->getDistinct(), $query->getSelectOption()),
44 163
            $this->buildFrom($query->getFrom(), $params),
45 163
            $this->buildJoin($query->getJoin(), $params),
46 163
            $this->buildWhere($query->getWhere(), $params),
47 163
            $this->buildGroupBy($query->getGroupBy()),
48 163
            $this->buildHaving($query->getHaving(), $params),
49
        ];
50
51 163
        $orderBy = $query->getOrderBy();
52 163
        $sql = implode($this->separator, array_filter($clauses));
53 163
        $sql = $this->buildOrderByAndLimit($sql, $orderBy, $query->getLimit(), $query->getOffset());
54
55 163
        if (!empty($orderBy)) {
56
            /** @psalm-var array<string|ExpressionInterface> $orderBy */
57 6
            foreach ($orderBy as $expression) {
58 6
                if ($expression instanceof ExpressionInterface) {
59 1
                    $this->buildExpression($expression, $params);
60
                }
61
            }
62
        }
63
64 163
        $groupBy = $query->getGroupBy();
65
66 163
        if (!empty($groupBy)) {
67
            /** @psalm-var array<string|ExpressionInterface> $groupBy */
68 2
            foreach ($groupBy as $expression) {
69 2
                if ($expression instanceof ExpressionInterface) {
70 1
                    $this->buildExpression($expression, $params);
71
                }
72
            }
73
        }
74
75 163
        $union = $this->buildUnion($query->getUnion(), $params);
76
77 163
        if ($union !== '') {
78 3
            $sql = "$sql$this->separator$union";
79
        }
80
81 163
        $with = $this->buildWithQueries($query->getWithQueries(), $params);
82
83 163
        if ($with !== '') {
84 2
            $sql = "$with$this->separator$sql";
85
        }
86
87 163
        return [$sql, $params];
88
    }
89
90 163
    public function buildLimit(Expression|int|null $limit, Expression|int|null $offset): string
91
    {
92 163
        $sql = '';
93
94 163
        if ($this->hasLimit($limit)) {
95 9
            $sql = "LIMIT $limit";
96 9
            if ($this->hasOffset($offset)) {
97 9
                $sql .= " OFFSET $offset";
98
            }
99 157
        } elseif ($this->hasOffset($offset)) {
100
            /**
101
             * limit is not optional in SQLite.
102
             *
103
             * {@see http://www.sqlite.org/syntaxdiagrams.html#select-stmt}
104
             */
105
            $sql = "LIMIT 9223372036854775807 OFFSET $offset"; // 2^63-1
106
        }
107
108 163
        return $sql;
109
    }
110
111 163
    public function buildUnion(array $unions, array &$params = []): string
112
    {
113 163
        if (empty($unions)) {
114 163
            return '';
115
        }
116
117 3
        $result = '';
118
119
        /** @psalm-var array<array-key, array{query: Query|null, all: bool}> $unions */
120 3
        foreach ($unions as $i => $union) {
121 3
            $query = $union['query'];
122 3
            if ($query instanceof Query) {
123 3
                [$unions[$i]['query'], $params] = $this->build($query, $params);
124
            }
125
126 3
            $result .= ' UNION ' . ($union['all'] ? 'ALL ' : '') . ' ' . (string) $unions[$i]['query'];
127
        }
128
129 3
        return trim($result);
130
    }
131
132
    /**
133
     * Contains array of default expression builders. Extend this method and override it, if you want to change default
134
     * expression builders for this query builder.
135
     *
136
     * @return array
137
     *
138
     * See {@see ExpressionBuilder} docs for details.
139
     *
140
     * @psalm-return array<string, class-string<ExpressionBuilderInterface>>
141
     */
142 336
    protected function defaultExpressionBuilders(): array
143
    {
144 336
        return array_merge(parent::defaultExpressionBuilders(), [
145
            LikeCondition::class => LikeConditionBuilder::class,
146
            InCondition::class => InConditionBuilder::class,
147
        ]);
148
    }
149
}
150