Test Failed
Pull Request — master (#278)
by Sergei
25:00 queued 09:01
created

DQLQueryBuilder::defaultExpressionBuilders()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Mssql;
6
7
use Yiisoft\Db\Exception\Exception;
8
use Yiisoft\Db\Exception\InvalidArgumentException;
9
use Yiisoft\Db\Expression\ExpressionInterface;
10
use Yiisoft\Db\Mssql\Builder\InConditionBuilder;
11
use Yiisoft\Db\Mssql\Builder\LikeConditionBuilder;
12
use Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder;
13
use Yiisoft\Db\QueryBuilder\Condition\InCondition;
14
use Yiisoft\Db\QueryBuilder\Condition\LikeCondition;
15
16
use function array_merge;
17
use function preg_match;
18
19
/**
20
 * Implements a DQL (Data Query Language) SQL statements for MSSQL Server.
21
 */
22
final class DQLQueryBuilder extends AbstractDQLQueryBuilder
23
{
24 223
    public function buildOrderByAndLimit(
25
        string $sql,
26
        array $orderBy,
27
        ExpressionInterface|int|null $limit,
28
        ExpressionInterface|int|null $offset,
29
        array &$params = []
30
    ): string {
31 223
        if (!$this->hasOffset($offset) && !$this->hasLimit($limit)) {
32 214
            $orderByString = $this->buildOrderBy($orderBy, $params);
33
34 214
            return $orderByString === '' ? $sql : $sql . $this->separator . $orderByString;
35
        }
36
37 16
        return $this->newBuildOrderByAndLimit($sql, $orderBy, $limit, $offset, $params);
38
    }
39
40 1
    public function selectExists(string $rawSql): string
41
    {
42 1
        return 'SELECT CASE WHEN EXISTS(' . $rawSql . ') THEN 1 ELSE 0 END';
43
    }
44
45 881
    protected function defaultExpressionBuilders(): array
46
    {
47 881
        return array_merge(parent::defaultExpressionBuilders(), [
48 881
            InCondition::class => InConditionBuilder::class,
49 881
            LikeCondition::class => LikeConditionBuilder::class,
50 881
        ]);
51
    }
52
53
    /**
54
     * Builds the `ORDER BY`/`LIMIT`/`OFFSET` clauses for SQL SERVER 2012 or newer.
55
     *
56
     * @param string $sql The existing SQL (without `ORDER BY`/`LIMIT`/`OFFSET`).
57
     * @param array $orderBy The order by columns. See {@see Query::orderBy} for more details on how to specify
58
     * this parameter.
59
     * @param ExpressionInterface|int|null $limit The limit number. See {@see Query::limit} for more details.
60
     * @param ExpressionInterface|int|null $offset The offset number. See {@see Query::offset} for more details.
61
     * @param array $params The binding parameters to populate.
62
     *
63
     * @throws Exception
64
     * @throws InvalidArgumentException
65
     *
66
     * @return string The SQL completed with `ORDER BY`/`LIMIT`/`OFFSET` (if any).
67
     */
68 16
    protected function newBuildOrderByAndLimit(
69
        string $sql,
70
        array $orderBy,
71
        ExpressionInterface|int|null $limit,
72
        ExpressionInterface|int|null $offset,
73
        array &$params = []
74
    ): string {
75 16
        $orderByString = $this->buildOrderBy($orderBy, $params);
76
77 16
        if ($orderByString === '') {
78
            /** `ORDER BY` clause is required when `FETCH` and `OFFSET` are in the SQL */
79 12
            $orderByString = 'ORDER BY (SELECT NULL)';
80
        }
81
82 16
        $sql .= $this->separator . $orderByString;
83
84
        /**
85
         * @link http://technet.microsoft.com/en-us/library/gg699618.aspx
86
         */
87 16
        $offsetString = $this->hasOffset($offset) ?
88 16
            ($offset instanceof ExpressionInterface ? $this->buildExpression($offset) : (string)$offset) : '0';
89 16
        $sql .= $this->separator . 'OFFSET ' . $offsetString . ' ROWS';
90
91 16
        if ($this->hasLimit($limit)) {
92 15
            $sql .= $this->separator . 'FETCH NEXT ' .
93 15
                ($limit instanceof ExpressionInterface ? $this->buildExpression($limit) : (string)$limit) . ' ROWS ONLY';
94
        }
95
96 16
        return $sql;
97
    }
98
99
    /**
100
     * Extracts table alias if there is one or returns `false`.
101
     *
102
     * @psalm-return string[]|bool
103
     */
104 89
    protected function extractAlias(string $table): array|bool
105
    {
106 89
        if (preg_match('/^\[.*]$/', $table)) {
107 1
            return false;
108
        }
109
110 89
        return parent::extractAlias($table);
111
    }
112
113
    public function buildWithQueries(array $withs, array &$params): string
114
    {
115
        foreach ($withs as &$with) {
116
            $with['recursive'] = false;
117
        }
118
119
        return parent::buildWithQueries($withs, $params);
120
    }
121
}
122