InConditionBuilder::splitCondition()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 6.7458

Importance

Changes 0
Metric Value
cc 5
eloc 15
nc 4
nop 2
dl 0
loc 28
ccs 10
cts 17
cp 0.5881
crap 6.7458
rs 9.4555
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Oracle\Builder;
6
7
use Yiisoft\Db\Exception\Exception;
8
use Yiisoft\Db\Exception\InvalidArgumentException;
9
use Yiisoft\Db\Exception\InvalidConfigException;
10
use Yiisoft\Db\Exception\NotSupportedException;
11
use Yiisoft\Db\Expression\ExpressionInterface;
12
use Yiisoft\Db\QueryBuilder\Condition\Interface\InConditionInterface;
13
14
use function array_slice;
15
use function array_unshift;
16
use function count;
17
use function is_array;
18
19
/**
20
 * Build an object of {@see \Yiisoft\Db\QueryBuilder\Condition\InCondition} into SQL expressions for Oracle Server.
21
 */
22
final class InConditionBuilder extends \Yiisoft\Db\QueryBuilder\Condition\Builder\InConditionBuilder
23
{
24
    /**
25
     * The Method builds the raw SQL from the $expression that won't be additionally escaped or quoted.
26
     *
27
     * @param ExpressionInterface $expression The expression to build.
28
     * @param array $params The binding parameters.
29
     *
30
     * @throws Exception
31
     * @throws InvalidArgumentException
32
     * @throws InvalidConfigException
33
     * @throws NotSupportedException
34
     *
35
     * @return string The raw SQL that won't be additionally escaped or quoted.
36
     *
37
     * @psalm-param InConditionInterface $expression
38
     */
39 37
    public function build(ExpressionInterface $expression, array &$params = []): string
40
    {
41 37
        $splitCondition = $this->splitCondition($expression, $params);
42
43 37
        return $splitCondition ?? parent::build($expression, $params);
44
    }
45
46
    /**
47
     * Oracle DBMS doesn't support more than 1000 parameters in `IN` condition.
48
     *
49
     * This method splits long `IN` condition into series of smaller ones.
50
     *
51
     * @param array $params The binding parameters.
52
     *
53
     * @throws Exception
54
     * @throws InvalidArgumentException
55
     * @throws InvalidConfigException
56
     * @throws NotSupportedException
57
     *
58
     * @return string|null `null` when split isn't required. Otherwise - built SQL condition.
59
     */
60 37
    protected function splitCondition(InConditionInterface $condition, array &$params): string|null
61
    {
62 37
        $operator = $condition->getOperator();
63 37
        $values = $condition->getValues();
64 37
        $column = $condition->getColumn();
65
66 37
        if (!is_array($values)) {
67 20
            return null;
68
        }
69
70 17
        $maxParameters = 1000;
71 17
        $count = count($values);
72
73 17
        if ($count <= $maxParameters) {
74 17
            return null;
75
        }
76
77
        $slices = [];
78
79
        for ($i = 0; $i < $count; $i += $maxParameters) {
80
            $slices[] = $this->queryBuilder->createConditionFromArray(
81
                [$operator, $column, array_slice($values, $i, $maxParameters)]
82
            );
83
        }
84
85
        array_unshift($slices, ($operator === 'IN') ? 'OR' : 'AND');
86
87
        return $this->queryBuilder->buildCondition($slices, $params);
88
    }
89
}
90