Passed
Pull Request — dev (#52)
by Wilmer
09:35
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.3183

Importance

Changes 0
Metric Value
cc 5
eloc 15
c 0
b 0
f 0
nc 4
nop 2
dl 0
loc 28
ccs 10
cts 16
cp 0.625
crap 6.3183
rs 9.4555
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\Query\Conditions\Builder\InConditionBuilder as AbstractInConditionBuilder;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\Conditi...lder\InConditionBuilder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Yiisoft\Db\Query\Conditions\InCondition;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\Conditions\InCondition was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use Yiisoft\Db\Query\QueryBuilderInterface;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\QueryBuilderInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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 31
    public function __construct(private QueryBuilderInterface $queryBuilder)
24
    {
25 31
        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 31
    public function build(ExpressionInterface $expression, array &$params = []): string
40
    {
41
        /** @var Incondition $expression */
42 31
        $splitCondition = $this->splitCondition($expression, $params);
43
44 31
        if ($splitCondition !== null) {
45
            return $splitCondition;
46
        }
47
48 31
        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 InCondition $condition
56
     * @param array $params the binding parameters.
57
     *
58
     * @throws Exception|InvalidArgumentException|InvalidConfigException|NotSupportedException
59
     *
60
     * @return string|null null when split is not required. Otherwise - built SQL condition.
61
     */
62 31
    protected function splitCondition(InCondition $condition, array &$params): ?string
63
    {
64 31
        $operator = $condition->getOperator();
65 31
        $values = $condition->getValues();
66 31
        $column = $condition->getColumn();
67
68 31
        if (!is_array($values)) {
69 18
            return null;
70
        }
71
72 13
        $maxParameters = 1000;
73 13
        $count = count($values);
74
75 13
        if ($count <= $maxParameters) {
76 13
            return null;
77
        }
78
79
        $slices = [];
80
81
        for ($i = 0; $i < $count; $i += $maxParameters) {
82
            $slices[] = $this->queryBuilder->createConditionFromArray(
83
                [$operator, $column, array_slice($values, $i, $maxParameters)]
84
            );
85
        }
86
87
        array_unshift($slices, ($operator === 'IN') ? 'OR' : 'AND');
88
89
        return $this->queryBuilder->buildCondition($slices, $params);
90
    }
91
}
92