Passed
Pull Request — master (#822)
by Sergei
02:51
created

BatchQueryResult   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 34
c 1
b 0
f 0
dl 0
loc 113
rs 10
ccs 29
cts 29
cp 1
wmc 16

12 Methods

Rating   Name   Duplication   Size   Complexity  
A next() 0 4 1
A batchSize() 0 5 1
A setPopulatedMethod() 0 5 1
A __construct() 0 2 1
A valid() 0 3 1
A fetchData() 0 9 2
A getQuery() 0 3 1
A getRows() 0 15 3
A current() 0 3 1
A key() 0 3 1
A getBatchSize() 0 3 1
A rewind() 0 9 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Query;
6
7
use Closure;
8
use Throwable;
9
use Yiisoft\Db\Exception\Exception;
10
use Yiisoft\Db\Exception\InvalidConfigException;
11
12
/**
13
 * Represents the result of a batch query execution.
14
 *
15
 * A batch query is a group of many SQL statements that are executed together as a single unit.
16
 */
17
final class BatchQueryResult implements BatchQueryResultInterface
18
{
19
    private int $batchSize = 100;
20
    private int $index = -1;
21
    /**
22
     * @var array The data retrieved in the current batch.
23
     */
24
    private array $batch = [];
25
    /**
26
     * @var DataReaderInterface|null The data reader associated with this batch query.
27
     */
28
    private DataReaderInterface|null $dataReader = null;
29
30
    private Closure|null $populateMethod = null;
31
32
    public function __construct(private QueryInterface $query)
33
    {
34
    }
35
36
    public function rewind(): void
37
    {
38
        if ($this->index === 0) {
39
            return;
40
        }
41
42
        $this->dataReader = null;
43
        $this->batch = $this->fetchData();
44
        $this->index = 0;
45
    }
46
47
    public function next(): void
48
    {
49
        $this->batch = $this->fetchData();
50
        ++$this->index;
51
    }
52
53
    /**
54
     * Fetches the next batch of data.
55
     *
56
     * @throws Exception
57
     * @throws InvalidConfigException
58
     * @throws Throwable
59
     *
60
     * @return array The data fetched.
61
     */
62
    private function fetchData(): array
63
    {
64
        $rows = $this->getRows();
65
66
        if ($this->populateMethod !== null) {
67
            return (array) ($this->populateMethod)($rows, $this->query->getIndexBy());
68 30
        }
69
70 30
        return $rows;
71 30
    }
72
73
    /**
74
     * Reads and collects rows for batch.
75
     */
76
    private function getRows(): array
77
    {
78 30
        $rows = [];
79
80 30
        $this->dataReader ??= $this->query->createCommand()->query();
81 30
82
        for (
83
            $leftCount = $this->batchSize;
84 30
            $leftCount > 0 && $this->dataReader->valid();
85 30
            --$leftCount, $this->dataReader->next()
86 30
        ) {
87 30
            $rows[] = $this->dataReader->current();
88 30
        }
89
90
        return $rows;
91
    }
92
93
    public function key(): int
94
    {
95 30
        return $this->index;
96
    }
97 30
98 30
    public function current(): array
99 30
    {
100
        return $this->batch;
101
    }
102
103
    public function valid(): bool
104
    {
105
        return !empty($this->batch);
106 30
    }
107
108 30
    public function getQuery(): QueryInterface
109 30
    {
110 30
        return $this->query;
111
    }
112
113 30
    public function getBatchSize(): int
114 10
    {
115 10
        return $this->batchSize;
116 10
    }
117 10
118 10
    public function batchSize(int $value): static
119
    {
120 10
        $this->batchSize = $value;
121
122
        return $this;
123 30
    }
124 30
125
    public function setPopulatedMethod(Closure|null $populateMethod = null): static
126 30
    {
127
        $this->populateMethod = $populateMethod;
128
129
        return $this;
130
    }
131
}
132