Passed
Push — master ( 2d706d...f38e4f )
by Wilmer
32:52 queued 29:57
created

DQLQueryBuilder::buildLimit()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

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