Skip to content

Commit

Permalink
Improve RdbmsResult by implementing SeekableIterator when possible
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Jan 18, 2025
1 parent bd59e16 commit 45c4618
Showing 1 changed file with 31 additions and 9 deletions.
40 changes: 31 additions & 9 deletions src/RdbmsResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
use ArrayIterator;
use Iterator;
use mysqli_result;
use OutOfBoundsException;
use PDO;
use PDOStatement;
use PgSql\Result;
use RuntimeException;
use SeekableIterator;
use SQLite3Result;
use Throwable;
use ValueError;
Expand Down Expand Up @@ -80,17 +82,17 @@ public static function from(object $result): self
}

/**
* @throws RuntimeException If the DB result is unknown or unsupported or no column names information is found.
* @throws RuntimeException If no column names information is found.
*
* @return array<string>
*/
public static function columnNames(object $result): array
{
return match (true) {
$result instanceof PDOStatement => array_map(
function (int $i) use ($result): string {
$metadata = $result->getColumnMeta($i);
false !== $metadata || throw new RuntimeException('Unable to get metadata for column '.$i);
function (int $index) use ($result): string {
$metadata = $result->getColumnMeta($index);
false !== $metadata || throw new RuntimeException('Unable to get metadata for column '.$index);

return $metadata['name'];
},
Expand Down Expand Up @@ -145,17 +147,24 @@ public function valid(): bool
return false !== $this->current;
}
},
$result instanceof mysqli_result => new class ($result) implements Iterator {
$result instanceof mysqli_result => new class ($result) implements SeekableIterator {
private array|false|null $current;
private int $key = 0;

public function __construct(private readonly mysqli_result $result)
{
}

public function seek(int $offset): void
{
if (!$this->result->data_seek($offset)) {
throw new OutOfBoundsException('Unable to seek to offset '.$offset);
}
}

public function rewind(): void
{
$this->result->data_seek(0);
$this->seek(0);
$this->current = $this->result->fetch_assoc();
$this->key = 0;
}
Expand All @@ -182,17 +191,24 @@ public function valid(): bool
&& null !== $this->current;
}
},
$result instanceof Result => new class ($result) implements Iterator {
$result instanceof Result => new class ($result) implements SeekableIterator {
private array|false|null $current;
private int $key = 0;

public function __construct(private readonly Result $result)
{
}

public function seek(int $offset): void
{
if (!pg_result_seek($this->result, $offset)) {
throw new OutOfBoundsException('Unable to seek to offset '.$offset);
}
}

public function rewind(): void
{
pg_result_seek($this->result, 0);
$this->seek(0);
$this->current = pg_fetch_assoc($this->result);
$this->key = 0;
}
Expand All @@ -219,13 +235,19 @@ public function valid(): bool
&& null !== $this->current;
}
},
$result instanceof PDOStatement => new class ($result) implements Iterator {
$result instanceof PDOStatement => new class ($result) implements SeekableIterator {
private ?ArrayIterator $cacheIterator;

public function __construct(private readonly PDOStatement $result)
{
}

public function seek(int $offset): void
{
$this->cacheIterator ??= new ArrayIterator($this->result->fetchAll(PDO::FETCH_ASSOC));
$this->cacheIterator->seek($offset);
}

public function rewind(): void
{
$this->cacheIterator ??= new ArrayIterator($this->result->fetchAll(PDO::FETCH_ASSOC));
Expand Down

0 comments on commit 45c4618

Please sign in to comment.