Select::getLimit()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 6
c 1
b 0
f 0
nc 3
nop 0
dl 0
loc 10
rs 10
ccs 7
cts 7
cp 1
crap 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace QB\MySQL\Statement;
6
7
use QB\Generic\IQueryPart;
8
use QB\Generic\Statement\Select as GenericSelect;
9
use QB\MySQL\Clause\CombiningQuery;
10
use QB\MySQL\Clause\Lock;
11
12
/**
13
 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
14
 */
15
class Select extends GenericSelect
16
{
17
    public const DISTINCTROW         = 'DISTINCTROW';
18
    public const HIGH_PRIORITY       = 'HIGH_PRIORITY';
19
    public const STRAIGHT_JOIN       = 'STRAIGHT_JOIN';
20
    public const SQL_SMALL_RESULT    = 'SQL_SMALL_RESULT';
21
    public const SQL_BIG_RESULT      = 'SQL_BIG_RESULT';
22
    public const SQL_BUFFER_RESULT   = 'SQL_BUFFER_RESULT';
23
    public const SQL_NO_CACHE        = 'SQL_NO_CACHE';
24
    public const SQL_CALC_FOUND_ROWS = 'SQL_CALC_FOUND_ROWS';
25
26
    protected const GROUP_WITH_ROLLUP = 'WITH ROLLUP';
27
28
    protected bool $groupWithRollup = false;
29
30
    /** @var CombiningQuery[] */
31
    protected array $combiningQueries = [];
32
33
    protected ?Lock $lock = null;
34
35
    protected ?int $outerOffset = null;
36
37
    protected ?int $outerLimit = null;
38
39
    /** @var array<string,string> */
40
    protected array $outerOrderBy = [];
41
42
    protected ?Lock $outerLock = null;
43
44
    /**
45
     * @SuppressWarnings("complexity")
46
     *
47
     * @param string ...$modifiers
48
     *
49
     * @return $this
50
     */
51 2
    public function modifier(string ...$modifiers): static
52
    {
53 2
        foreach ($modifiers as $modifier) {
54
            switch ($modifier) {
55 2
                case static::ALL:
56 2
                case static::DISTINCT:
57 1
                case static::DISTINCTROW:
58 2
                    $this->modifiers[0] = $modifier;
59 2
                    break;
60 1
                case static::HIGH_PRIORITY:
61 1
                    $this->modifiers[1] = $modifier;
62 1
                    break;
63 1
                case static::STRAIGHT_JOIN:
64 1
                    $this->modifiers[2] = $modifier;
65 1
                    break;
66 1
                case static::SQL_SMALL_RESULT:
67 1
                    $this->modifiers[3] = $modifier;
68 1
                    break;
69 1
                case static::SQL_BIG_RESULT:
70 1
                    $this->modifiers[4] = $modifier;
71 1
                    break;
72 1
                case static::SQL_BUFFER_RESULT:
73 1
                    $this->modifiers[5] = $modifier;
74 1
                    break;
75 1
                case static::SQL_NO_CACHE:
76 1
                    $this->modifiers[6] = $modifier;
77 1
                    break;
78 1
                case static::SQL_CALC_FOUND_ROWS:
79 1
                    $this->modifiers[7] = $modifier;
80 1
                    break;
81
            }
82
        }
83
84 2
        ksort($this->modifiers);
85
86 2
        return $this;
87
    }
88
89
    /**
90
     * @return $this
91
     */
92 1
    public function groupWithRollup(): static
93
    {
94 1
        $this->groupWithRollup = true;
95
96 1
        return $this;
97
    }
98
99
    /**
100
     * @param int|null $offset
101
     *
102
     * @return $this
103
     */
104 1
    public function outerOffset(?int $offset): static
105
    {
106 1
        $this->outerOffset = $offset;
107
108 1
        return $this;
109
    }
110
111
    /**
112
     * @param int|null $limit
113
     *
114
     * @return $this
115
     */
116 3
    public function outerLimit(?int $limit): static
117
    {
118 3
        $this->outerLimit = $limit;
119
120 3
        return $this;
121
    }
122
123
    /**
124
     * @param string $column
125
     * @param string $direction
126
     *
127
     * @return $this
128
     */
129 1
    public function outerOrderBy(string $column, string $direction = 'ASC'): static
130
    {
131 1
        $this->outerOrderBy[$column] = $direction;
132
133 1
        return $this;
134
    }
135
136
    /**
137
     * @param Lock $lock
138
     *
139
     * @return $this
140
     */
141 1
    public function lock(Lock $lock): static
142
    {
143 1
        $this->lock = $lock;
144
145 1
        return $this;
146
    }
147
148
    /**
149
     * @param IQueryPart  $select
150
     * @param string|null $modifier
151
     *
152
     * @return $this
153
     */
154 5
    public function union(IQueryPart $select, ?string $modifier = null): static
155
    {
156 5
        $this->combiningQueries[] = new CombiningQuery(CombiningQuery::TYPE_UNION, $select, $modifier);
157
158 5
        return $this;
159
    }
160
161
    /**
162
     * @param Lock $lock
163
     *
164
     * @return $this
165
     */
166 2
    public function outerLock(Lock $lock): static
167
    {
168 2
        $this->outerLock = $lock;
169
170 2
        return $this;
171
    }
172
173
    /**
174
     * @return string
175
     */
176 22
    public function __toString(): string
177
    {
178 22
        $parts = array_merge(
179 22
            [parent::__toString()],
180 21
            $this->getLock(),
181 21
            $this->getUnion()
182
        );
183
184 21
        $parts = array_filter($parts);
185
186 21
        $sql = implode(PHP_EOL, $parts);
187
188
        if (
189 21
            $this->outerLimit === null && $this->outerOffset === null && count($this->outerOrderBy) === 0 &&
190 21
            $this->outerLock === null
191
        ) {
192 21
            return $sql;
193
        }
194
195 5
        $parts = array_merge(
196 5
            ['(' . $sql . ')'],
197 5
            $this->getOuterOrderBy(),
198 5
            $this->getOuterLimit(),
199 5
            $this->getOuterLocks()
200
        );
201
202 5
        $parts = array_filter($parts);
203
204 5
        return implode(PHP_EOL, $parts);
205
    }
206
207
    /**
208
     * @return string[]
209
     */
210 15
    protected function getGroupBy(): array
211
    {
212 15
        $groupBy = parent::getGroupBy();
213
214 15
        if ($this->groupWithRollup && count($groupBy) > 0) {
215 1
            $groupBy[0] = sprintf('%s %s', $groupBy[0], static::GROUP_WITH_ROLLUP);
216
        }
217
218 15
        return $groupBy;
219
    }
220
221
    /**
222
     * @return string[]
223
     */
224 15
    protected function getLimit(): array
225
    {
226 15
        $parts = [];
227 15
        if ($this->limit !== null && $this->offset !== null) {
228 1
            $parts[] = 'LIMIT ' . $this->offset . ', ' . $this->limit;
229 15
        } elseif ($this->limit !== null) {
230 1
            $parts[] = 'LIMIT ' . $this->limit;
231
        }
232
233 15
        return $parts;
234
    }
235
236
    /**
237
     * @return string[]
238
     */
239 21
    protected function getLock(): array
240
    {
241 21
        if ($this->lock === null) {
242 21
            return [];
243
        }
244
245 1
        return [(string)$this->lock];
246
    }
247
248
    /**
249
     * @return string[]
250
     */
251 21
    protected function getUnion(): array
252
    {
253 21
        $parts = [];
254 21
        foreach ($this->combiningQueries as $query) {
255 5
            $parts[] = (string)$query;
256
        }
257
258 21
        return $parts;
259
    }
260
261
    /**
262
     * @return string[]
263
     */
264 5
    protected function getOuterOrderBy(): array
265
    {
266 5
        if (count($this->outerOrderBy) === 0) {
267 4
            return [];
268
        }
269
270 1
        $parts = [];
271 1
        foreach ($this->outerOrderBy as $column => $direction) {
272 1
            $parts[] = "$column $direction";
273
        }
274
275 1
        return ['ORDER BY ' . implode(', ', $parts)];
276
    }
277
278
    /**
279
     * @return string[]
280
     */
281 5
    protected function getOuterLimit(): array
282
    {
283 5
        $parts = [];
284 5
        if ($this->outerLimit !== null && $this->outerOffset !== null) {
285 1
            $parts[] = 'LIMIT ' . $this->outerOffset . ', ' . $this->outerLimit;
286 4
        } elseif ($this->outerLimit !== null) {
287 2
            $parts[] = 'LIMIT ' . $this->outerLimit;
288
        }
289
290 5
        return $parts;
291
    }
292
293
    /**
294
     * @return string[]
295
     */
296 5
    protected function getOuterLocks(): array
297
    {
298 5
        if ($this->outerLock === null) {
299 3
            return [];
300
        }
301
302 2
        return [(string)$this->outerLock];
303
    }
304
}
305