-
-
Notifications
You must be signed in to change notification settings - Fork 15
/
DQLQueryBuilder.php
91 lines (80 loc) · 2.98 KB
/
DQLQueryBuilder.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?php
declare(strict_types=1);
namespace Yiisoft\Db\Mysql;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Expression\JsonExpression;
use Yiisoft\Db\Mysql\Builder\ExpressionBuilder;
use Yiisoft\Db\Mysql\Builder\JsonExpressionBuilder;
use Yiisoft\Db\Mysql\Builder\JsonOverlapsConditionBuilder;
use Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder;
use Yiisoft\Db\QueryBuilder\Condition\JsonOverlapsCondition;
use function ctype_digit;
/**
* Implements a DQL (Data Query Language) SQL statements for MySQL, MariaDB.
*/
final class DQLQueryBuilder extends AbstractDQLQueryBuilder
{
public function buildLimit(ExpressionInterface|int|null $limit, ExpressionInterface|int|null $offset): string
{
$sql = '';
if ($this->hasLimit($limit)) {
$sql = 'LIMIT ' . ($limit instanceof ExpressionInterface ? $this->buildExpression($limit) : (string)$limit);
if ($this->hasOffset($offset)) {
$sql .= ' OFFSET ' . ($offset instanceof ExpressionInterface ? $this->buildExpression($offset) : (string)$offset);
}
} elseif ($this->hasOffset($offset)) {
/**
* Limit isn't optional in MySQL.
*
* @link https://stackoverflow.com/a/271650/1106908
* @link https://dev.mysql.com/doc/refman/5.0/en/select.html#idm47619502796240
*/
$sql = 'LIMIT ' .
($offset instanceof ExpressionInterface ? $this->buildExpression($offset) : (string)$offset) .
', 18446744073709551615'; // 2^64-1
}
return $sql;
}
/**
* Checks to see if the given limit is effective.
*
* @param mixed $limit The given limit.
*
* @return bool Whether the limit is effective.
*/
protected function hasLimit(mixed $limit): bool
{
/** In MySQL limit argument must be a non-negative integer constant */
return ctype_digit((string) $limit);
}
/**
* Checks to see if the given offset is effective.
*
* @param mixed $offset The given offset.
*
* @return bool Whether the offset is effective.
*/
protected function hasOffset(mixed $offset): bool
{
/** In MySQL offset argument must be a non-negative integer constant */
$offset = (string) $offset;
return ctype_digit($offset) && $offset !== '0';
}
/**
* Has an array of default expression builders.
*
* Extend this method and override it if you want to change default expression builders for this query builder.
*
* {@see ExpressionBuilder} docs for details.
*/
protected function defaultExpressionBuilders(): array
{
return [
...parent::defaultExpressionBuilders(),
JsonExpression::class => JsonExpressionBuilder::class,
JsonOverlapsCondition::class => JsonOverlapsConditionBuilder::class,
Expression::class => ExpressionBuilder::class,
];
}
}