Passed
Push — remove-test-schema-trait ( 2f86f9...0a3cc3 )
by Wilmer
35:59
created

InConditionBuilder::splitCondition()   A

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\Builder\InConditionBuilder as AbstractInConditionBuilder;
13
use Yiisoft\Db\QueryBuilder\Condition\InCondition;
14
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
15
16
use function array_slice;
17
use function array_unshift;
18
use function count;
19
use function is_array;
20
21
final class InConditionBuilder extends AbstractInConditionBuilder
22
{
23 34
    public function __construct(private QueryBuilderInterface $queryBuilder)
24
    {
25 34
        parent::__construct($queryBuilder);
26
    }
27
28
    /**
29
     * Method builds the raw SQL from the $expression that will not be additionally
30
     * escaped or quoted.
31
     *
32
     * @param ExpressionInterface $expression the expression to be built.
33
     * @param array $params the binding parameters.
34
     *
35
     * @throws Exception|InvalidArgumentException|InvalidConfigException|NotSupportedException
36
     *
37
     * @return string the raw SQL that will not be additionally escaped or quoted.
38
     */
39 34
    public function build(ExpressionInterface $expression, array &$params = []): string
40
    {
41
        /** @var Incondition $expression */
42 34
        $splitCondition = $this->splitCondition($expression, $params);
43
44 34
        if ($splitCondition !== null) {
45
            return $splitCondition;
46
        }
47
48 34
        return parent::build($expression, $params);
49
    }
50
51
    /**
52
     * Oracle DBMS does not support more than 1000 parameters in `IN` condition.
53
     * This method splits long `IN` condition into series of smaller ones.
54
     *
55
     * @param array $params the binding parameters.
56
     *
57
     * @throws Exception|InvalidArgumentException|InvalidConfigException|NotSupportedException
58
     *
59
     * @return string|null null when split is not required. Otherwise - built SQL condition.
60
     */
61 34
    protected function splitCondition(InCondition $condition, array &$params): string|null
62
    {
63 34
        $operator = $condition->getOperator();
64 34
        $values = $condition->getValues();
65 34
        $column = $condition->getColumn();
66
67 34
        if (!is_array($values)) {
68 18
            return null;
69
        }
70
71 16
        $maxParameters = 1000;
72 16
        $count = count($values);
73
74 16
        if ($count <= $maxParameters) {
75 16
            return null;
76
        }
77
78
        $slices = [];
79
80
        for ($i = 0; $i < $count; $i += $maxParameters) {
81
            $slices[] = $this->queryBuilder->createConditionFromArray(
82
                [$operator, $column, array_slice($values, $i, $maxParameters)]
83
            );
84
        }
85
86
        array_unshift($slices, ($operator === 'IN') ? 'OR' : 'AND');
87
88
        return $this->queryBuilder->buildCondition($slices, $params);
89
    }
90
}
91