Passed
Push — master ( 8ec0f7...57cda1 )
by Wilmer
03:52
created

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