Passed
Pull Request — master (#223)
by Def
03:40
created

DQLQueryBuilder::buildLimit()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 23
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 7

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 7
eloc 10
c 2
b 0
f 0
nc 9
nop 2
dl 0
loc 23
ccs 11
cts 11
cp 1
crap 7
rs 8.8333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Mysql;
6
7
use Yiisoft\Db\Expression\ExpressionBuilder;
8
use Yiisoft\Db\Expression\ExpressionInterface;
9
use Yiisoft\Db\Expression\JsonExpression;
10
use Yiisoft\Db\Mysql\Builder\JsonExpressionBuilder;
11
use Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder;
12
13
use function array_merge;
14
use function ctype_digit;
15
16
final class DQLQueryBuilder extends AbstractDQLQueryBuilder
17
{
18 238
    public function buildLimit(ExpressionInterface|int|null $limit, ExpressionInterface|int|null $offset): string
19
    {
20 238
        $sql = '';
21
22 238
        if ($this->hasLimit($limit)) {
23 16
            $sql = 'LIMIT ' . ($limit instanceof ExpressionInterface ? $this->buildExpression($limit) : (string)$limit);
24
25 16
            if ($this->hasOffset($offset)) {
26 16
                $sql .= ' OFFSET ' . ($offset instanceof ExpressionInterface ? $this->buildExpression($offset) : (string)$offset);
27
            }
28 228
        } elseif ($this->hasOffset($offset)) {
29
            /**
30
             * limit is not optional in MySQL.
31
             *
32
             * http://stackoverflow.com/a/271650/1106908
33
             * http://dev.mysql.com/doc/refman/5.0/en/select.html#idm47619502796240
34
             */
35 1
            $sql = 'LIMIT ' .
36 1
                ($offset instanceof ExpressionInterface ? $this->buildExpression($offset) : (string)$offset) .
37 1
                ', 18446744073709551615'; // 2^64-1
38
        }
39
40 238
        return $sql;
41
    }
42
43
    /**
44
     * Checks to see if the given limit is effective.
45
     *
46
     * @param mixed $limit The given limit.
47
     *
48
     * @return bool Whether the limit is effective.
49
     */
50 238
    protected function hasLimit(mixed $limit): bool
51
    {
52
        /** In MySQL limit argument must be non-negative integer constant */
53 238
        return ctype_digit((string) $limit);
54
    }
55
56
    /**
57
     * Checks to see if the given offset is effective.
58
     *
59
     * @param mixed $offset The given offset.
60
     *
61
     * @return bool Whether the offset is effective.
62
     */
63 238
    protected function hasOffset(mixed $offset): bool
64
    {
65
        /** In MySQL offset argument must be non-negative integer constant */
66 238
        $offset = (string) $offset;
67 238
        return ctype_digit($offset) && $offset !== '0';
68
    }
69
70
    /**
71
     * Contains array of default expression builders. Extend this method and override it, if you want to change default
72
     * expression builders for this query builder.
73
     *
74
     * See {@see ExpressionBuilder} docs for details.
75
     */
76 507
    protected function defaultExpressionBuilders(): array
77
    {
78 507
        return array_merge(
79 507
            parent::defaultExpressionBuilders(),
80 507
            [
81 507
                JsonExpression::class => JsonExpressionBuilder::class,
82 507
            ]
83 507
        );
84
    }
85
}
86