Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f789a1b
Refactor data readers
Tigrov Apr 17, 2024
b9f7eab
Apply fixes from StyleCI
StyleCIBot Apr 17, 2024
884e9c7
Fix psalm issue
Tigrov Apr 17, 2024
0e9afd6
Merge branch 'refs/heads/master' into refactor-data-readers
Tigrov Jan 27, 2025
2446c58
Merge branch 'master' into refactor-data-readers
vjik Apr 3, 2025
8529e81
Merge branch 'refs/heads/master' into refactor-data-readers
Tigrov Apr 3, 2025
2e131d8
Merge remote-tracking branch 'origin/refactor-data-readers' into refa…
Tigrov Apr 3, 2025
2c2e10d
Merge branch 'master' into refactor-data-readers
Tigrov Apr 4, 2025
c0c6505
Remove `populateMethod`
Tigrov Apr 5, 2025
30d5ef5
Merge branch 'master' into refactor-data-readers
Tigrov Apr 6, 2025
7605e50
Update
Tigrov Apr 6, 2025
60b0180
Apply fixes from StyleCI
StyleCIBot Apr 6, 2025
06187e7
Merge branch 'master' into refactor-data-readers
samdark Apr 8, 2025
a31a953
Update
Tigrov Apr 13, 2025
ee20ab0
Update type annotations
Tigrov Apr 13, 2025
4043713
Update type annotations
Tigrov Apr 13, 2025
abe793f
Update and improve test coverage
Tigrov Apr 14, 2025
bbede61
Apply fixes from StyleCI
StyleCIBot Apr 14, 2025
2e00a92
Fix psalm
Tigrov Apr 14, 2025
b402d50
Merge remote-tracking branch 'origin/refactor-data-readers' into refa…
Tigrov Apr 14, 2025
7d00ab8
Fix test
Tigrov Apr 14, 2025
deb81b2
Change `DataReaderInterface::resultCallback` accept one item
Tigrov Apr 14, 2025
1098597
Improve, add lines to UPGRADE.md and CHANGELOG.md
Tigrov Apr 14, 2025
1441b31
Merge branch 'master' into refactor-data-readers
Tigrov Apr 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
- Enh #925, #951: Add callback to `Query::all()` and `Query::one()` methods (@Tigrov, @vjik)
- New #954: Add `DbArrayHelper::arrange()` method (@Tigrov)
- Chg #956: Remove nullable from `PdoConnectionInterface::getActivePdo()` result (@vjik)
- Enh #822: Refactor data readers (@Tigrov)

## 1.3.0 March 21, 2024

Expand Down
16 changes: 16 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ Each table column has its own class in the `Yiisoft\Db\Schema\Column` namespace
- `DbStringHelper::pascalCaseToId()`;
- `AbstractDQLQueryBuilder::hasLimit()` - use `$limit !== null` instead;
- `AbstractDQLQueryBuilder::hasOffset()` - use `!empty($offset)` instead;
- `BatchQueryResultInterface::reset()` - use `BatchQueryResultInterface::rewind()` instead;
- `BatchQueryResult::reset()` - use `BatchQueryResult::rewind()` instead;

### Remove deprecated parameters

Expand Down Expand Up @@ -191,3 +193,17 @@ Each table column has its own class in the `Yiisoft\Db\Schema\Column` namespace
- Rename `QueryBuilderInterface::quoter()` method to `QueryBuilderInterface::getQuoter()`;
- Change constructor parameters in `AbstractQueryBuilder` class;
- Remove nullable from `PdoConnectionInterface::getActivePdo()` result;
- Move `Yiisoft\Db\Query\Data\DataReaderInterface` interface to `Yiisoft\Db\Query` namespace;
- Move `Yiisoft\Db\Query\Data\DataReader` class to `Yiisoft\Db\Driver\Pdo` namespace and rename it to `PdoDataReader`;
- Add `indexBy()` and `resultCallback()` methods to `DataReaderInterface` and `PdoDataReader` class;
- Change return type of `DataReaderInterface::key()` method to `int|string|null`;
- Change return type of `DataReaderInterface::current()` method to `array|object|false`;
- Change `PdoDataReader` a constructor parameter;
- Remove the second parameter `$each` from `ConnectionInterface::createBatchQueryResult()`
and `AbstractConnection::createBatchQueryResult()` methods;
- Rename `setPopulatedMethod()` to `resultCallback()` in `BatchQueryResultInterface` and `BatchQueryResult` class;
- Change return type of `key()` method to `int` in `BatchQueryResultInterface` and `BatchQueryResult` class;
- Change return type of `current()` method to `array` in `BatchQueryResultInterface` and `BatchQueryResult` class;
- Remove `null` from return type of `getQuery()` method in `BatchQueryResultInterface` and `BatchQueryResult` class;
- Remove parameters from `each()` method in `QueryInterface` and `Query` class;
- Change return type of `each()` method to `DataReaderInterface` in `QueryInterface` and `Query` class;
2 changes: 1 addition & 1 deletion src/Command/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Closure;
use Throwable;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Query\Data\DataReaderInterface;
use Yiisoft\Db\Query\DataReaderInterface;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\QueryBuilder\DMLQueryBuilderInterface;
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
Expand Down
2 changes: 1 addition & 1 deletion src/Command/CommandInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use Yiisoft\Db\Exception\InvalidCallException;
use Yiisoft\Db\Exception\InvalidConfigException;
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Query\Data\DataReaderInterface;
use Yiisoft\Db\Query\DataReaderInterface;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\QueryBuilder\DMLQueryBuilderInterface;
use Yiisoft\Db\Schema\Column\ColumnInterface;
Expand Down
4 changes: 2 additions & 2 deletions src/Connection/AbstractConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public function beginTransaction(?string $isolationLevel = null): TransactionInt
return $this->transaction;
}

public function createBatchQueryResult(QueryInterface $query, bool $each = false): BatchQueryResultInterface
public function createBatchQueryResult(QueryInterface $query): BatchQueryResultInterface
{
return new BatchQueryResult($query, $each);
return new BatchQueryResult($query);
}

public function getTablePrefix(): string
Expand Down
3 changes: 1 addition & 2 deletions src/Connection/ConnectionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,10 @@ public function beginTransaction(?string $isolationLevel = null): TransactionInt
* Create a batch query result instance.
*
* @param QueryInterface $query The query to execute.
* @param bool $each Whether to return each row of the result set one at a time.
*
* @return BatchQueryResultInterface The batch query result instance.
*/
public function createBatchQueryResult(QueryInterface $query, bool $each = false): BatchQueryResultInterface;
public function createBatchQueryResult(QueryInterface $query): BatchQueryResultInterface;

/**
* Creates a command for execution.
Expand Down
2 changes: 1 addition & 1 deletion src/Debug/CommandInterfaceProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Closure;
use Throwable;
use Yiisoft\Db\Command\CommandInterface;
use Yiisoft\Db\Query\Data\DataReaderInterface;
use Yiisoft\Db\Query\DataReaderInterface;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\Schema\Column\ColumnInterface;

Expand Down
4 changes: 2 additions & 2 deletions src/Debug/ConnectionInterfaceProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public function beginTransaction(?string $isolationLevel = null): TransactionInt
return new TransactionInterfaceDecorator($result, $this->collector);
}

public function createBatchQueryResult(QueryInterface $query, bool $each = false): BatchQueryResultInterface
public function createBatchQueryResult(QueryInterface $query): BatchQueryResultInterface
{
return $this->connection->createBatchQueryResult($query, $each);
return $this->connection->createBatchQueryResult($query);
}

public function createCommand(?string $sql = null, array $params = []): CommandInterface
Expand Down
4 changes: 2 additions & 2 deletions src/Driver/Pdo/AbstractPdoCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
use Yiisoft\Db\Profiler\Context\CommandContext;
use Yiisoft\Db\Profiler\ProfilerAwareInterface;
use Yiisoft\Db\Profiler\ProfilerAwareTrait;
use Yiisoft\Db\Query\Data\DataReader;
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;

use function restore_error_handler;
Expand Down Expand Up @@ -238,7 +237,8 @@ protected function internalExecute(): void
protected function internalGetQueryResult(int $queryMode): mixed
{
if ($queryMode === self::QUERY_MODE_CURSOR) {
return new DataReader($this);
/** @psalm-suppress PossiblyNullArgument */
return new PdoDataReader($this->pdoStatement);
}

if ($queryMode === self::QUERY_MODE_EXECUTE) {
Expand Down
142 changes: 142 additions & 0 deletions src/Driver/Pdo/PdoDataReader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Driver\Pdo;

use Closure;
use Countable;
use Iterator;
use PDO;
use PDOStatement;
use Yiisoft\Db\Exception\InvalidCallException;
use Yiisoft\Db\Query\DataReaderInterface;
use Yiisoft\Db\Query\QueryInterface;

use function is_string;

/**
* Provides an abstract way to read data from a database.
*
* A data reader is an object that can be used to read a forward-only stream of rows from a database.
*
* It's typically used in combination with a command object, such as a {@see \Yiisoft\Db\Command\AbstractCommand},
* to execute a SELECT statement and read the results.
*
* The class provides methods for accessing the data returned by the query.
*
* @psalm-import-type IndexBy from QueryInterface
* @psalm-import-type ResultCallbackOne from QueryInterface
*/
final class PdoDataReader implements DataReaderInterface
{
/** @psalm-var IndexBy|null $indexBy */
private Closure|string|null $indexBy = null;
private int $index = 0;
/** @psalm-var ResultCallbackOne|null $resultCallback */
private Closure|null $resultCallback = null;
private array|false $row;

/**
* @param PDOStatement $statement The PDO statement object that contains the result of the query.
*/
public function __construct(private readonly PDOStatement $statement)
{
/** @var array|false */
$this->row = $statement->fetch(PDO::FETCH_ASSOC);
}

public function __destruct()
{
$this->statement->closeCursor();
}

/**
* Returns the number of rows in the result set.
*
* This method is required by the interface {@see Countable}.
*
* Note, most DBMS mayn't give a meaningful count. In this case, use "SELECT COUNT(*) FROM tableName" to obtain the
* number of rows.
*/
public function count(): int
{
return $this->statement->rowCount();
}

/**
* Resets the iterator to the initial state.
*
* This method is required by the interface {@see Iterator}.
*
* @throws InvalidCallException If the data reader isn't at the beginning.
*/
public function rewind(): void
{
if ($this->index === 0) {
return;
}

throw new InvalidCallException('DataReader cannot rewind. It is a forward-only reader.');
}

public function key(): int|string|null
{
if ($this->indexBy === null) {
return $this->index;
}

if ($this->row === false) {
return null;
}

if (is_string($this->indexBy)) {
return (string) $this->row[$this->indexBy];
}

return ($this->indexBy)($this->row);
}

public function current(): array|object|false
{
if ($this->resultCallback === null || $this->row === false) {
return $this->row;
}

return ($this->resultCallback)($this->row);
}

/**
* Moves the internal pointer to the next row.
*
* This method is required by the interface {@see Iterator}.
*/
public function next(): void
{
/** @var array|false */
$this->row = $this->statement->fetch(PDO::FETCH_ASSOC);
$this->index++;
}

/**
* Returns whether there is a row of data at current position.
*
* This method is required by the interface {@see Iterator}.
*/
public function valid(): bool
{
return $this->row !== false;
}

public function indexBy(Closure|string|null $indexBy): static
{
$this->indexBy = $indexBy;
return $this;
}

public function resultCallback(Closure|null $resultCallback): static
{
$this->resultCallback = $resultCallback;
return $this;
}
}
6 changes: 3 additions & 3 deletions src/Helper/DbArrayHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ final class DbArrayHelper
* @param Closure|null $resultCallback The callback function that will be called with the result array. This can be
* used to modify the result before returning it.
*
* @return (array|object)[] The arranged array.
* @return array[]|object[] The arranged array.
*
* @psalm-param list<array> $rows
* @psalm-param IndexBy|null $indexBy
Expand Down Expand Up @@ -169,7 +169,7 @@ public static function arrange(
* @param Closure|null $resultCallback The callback function that will be called with the result array. This can be
* used to modify the result before returning it.
*
* @return (array|object)[] The indexed array.
* @return array[]|object[] The indexed array.
*
* @psalm-param list<array> $rows
* @psalm-param IndexBy|null $indexBy
Expand Down Expand Up @@ -290,7 +290,7 @@ public static function toArray(array|object $object): array
/**
* Recursively indexes the arranged array.
*
* @psalm-assert (array|object)[] $arranged
* @psalm-assert array[]|object[] $arranged
* @psalm-param IndexBy|null $indexBy
* @psalm-param ResultCallback|null $resultCallback
*/
Expand Down
Loading