Skip to content

Commit c7c81ee

Browse files
committed
added ResultDriver
1 parent ccece35 commit c7c81ee

File tree

8 files changed

+142
-26
lines changed

8 files changed

+142
-26
lines changed

src/Database/Connection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ public function query(#[Language('SQL')] string $sql, #[Language('GenericSQL')]
205205
[$this->sql, $params] = $this->preprocess($sql, ...$params);
206206
try {
207207
$result = new ResultSet($this, $this->sql, $params, $this->rowNormalizer);
208-
} catch (\PDOException $e) {
208+
} catch (DriverException $e) {
209209
Arrays::invoke($this->onQuery, $this, $e);
210210
throw $e;
211211
}

src/Database/Driver.php

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function connect(string $dsn, ?string $user = null, ?string $password = null, ?a
3434
*/
3535
function convertException(\PDOException $e): DriverException;
3636

37-
function query(string $queryString, array $params);
37+
function query(string $queryString, array $params): ResultDriver;
3838

3939
function beginTransaction(): void;
4040

@@ -91,12 +91,6 @@ function getIndexes(string $table): array;
9191
/** @return list<array{name: string, local: string, table: string, foreign: string}> */
9292
function getForeignKeys(string $table): array;
9393

94-
/**
95-
* Returns associative array of detected types in result set.
96-
* @return array<string, Type::*>
97-
*/
98-
function getColumnTypes(\PDOStatement $statement): array;
99-
10094
/**
10195
* Cheks if driver supports specific property
10296
* @param self::Support* $item

src/Database/Drivers/PdoDriver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public function getPdo(): ?PDO
4646
}
4747

4848

49-
public function query(string $queryString, array $params)
49+
public function query(string $queryString, array $params): PdoResultDriver
5050
{
5151
try {
5252
$types = ['boolean' => PDO::PARAM_BOOL, 'integer' => PDO::PARAM_INT, 'resource' => PDO::PARAM_LOB, 'NULL' => PDO::PARAM_NULL];
@@ -59,7 +59,7 @@ public function query(string $queryString, array $params)
5959

6060
$statement->setFetchMode(PDO::FETCH_ASSOC);
6161
@$statement->execute(); // @ PHP generates warning when ATTR_ERRMODE = ERRMODE_EXCEPTION bug #73878
62-
return $statement;
62+
return new PdoResultDriver($statement, $this);
6363

6464
} catch (PDOException $e) {
6565
$e = $this->convertException($e);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the Nette Framework (https://nette.org)
5+
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Nette\Database\Drivers;
11+
12+
use Nette;
13+
14+
15+
/**
16+
* PDO-based result-set driver.
17+
*/
18+
class PdoResultDriver implements Nette\Database\ResultDriver
19+
{
20+
private \PDOStatement $result;
21+
22+
private PdoDriver $driver;
23+
24+
25+
public function __construct(\PDOStatement $result, PdoDriver $driver)
26+
{
27+
$this->result = $result;
28+
$this->driver = $driver;
29+
}
30+
31+
32+
public function fetch(): ?array
33+
{
34+
$data = $this->result->fetch();
35+
if (!$data) {
36+
$this->result->closeCursor();
37+
return null;
38+
}
39+
40+
return $data;
41+
}
42+
43+
44+
public function getColumnCount(): int
45+
{
46+
return $this->result->columnCount();
47+
}
48+
49+
50+
public function getRowCount(): int
51+
{
52+
return $this->result->rowCount();
53+
}
54+
55+
56+
public function getColumnTypes(): array
57+
{
58+
return $this->driver->getColumnTypes($this->result);
59+
}
60+
61+
62+
public function getColumnMeta(int $col): array
63+
{
64+
return $this->result->getColumnMeta($col);
65+
}
66+
67+
68+
public function getPdoStatement(): \PDOStatement
69+
{
70+
return $this->result;
71+
}
72+
}

src/Database/Helpers.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,11 @@ public static function toPairs(array $rows, string|int|null $key = null, string|
303303
/**
304304
* Finds duplicate columns in select statement
305305
*/
306-
public static function findDuplicates(\PDOStatement $statement): string
306+
public static function findDuplicates(ResultDriver $result): string
307307
{
308308
$cols = [];
309-
for ($i = 0; $i < $statement->columnCount(); $i++) {
310-
$meta = $statement->getColumnMeta($i);
309+
for ($i = 0; $i < $result->getColumnCount(); $i++) {
310+
$meta = $result->getColumnMeta($i);
311311
$cols[$meta['name']][] = $meta['table'] ?? '';
312312
}
313313

src/Database/ResultDriver.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
/**
4+
* This file is part of the Nette Framework (https://nette.org)
5+
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace Nette\Database;
11+
12+
13+
/**
14+
* Supplemental database driver for result-set.
15+
*/
16+
interface ResultDriver
17+
{
18+
/**
19+
* Fetches the row at current position and moves the internal cursor to the next position.
20+
*/
21+
function fetch(): ?array;
22+
23+
/**
24+
* Returns the number of columns in a result set.
25+
*/
26+
function getColumnCount(): int;
27+
28+
/**
29+
* Returns the number of rows in a result set.
30+
*/
31+
function getRowCount(): int;
32+
33+
/**
34+
* Returns associative array of detected types in result set.
35+
* @return array<string, Type::*>
36+
*/
37+
function getColumnTypes(): array;
38+
39+
/**
40+
* Returns associative array of original table names.
41+
*/
42+
function getColumnMeta(int $col): array;
43+
}

src/Database/ResultSet.php

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@
1010
namespace Nette\Database;
1111

1212
use Nette;
13-
use PDO;
1413

1514

1615
/**
1716
* Represents a result set.
1817
*/
1918
class ResultSet implements \Iterator, IRowContainer
2019
{
21-
private ?\PDOStatement $pdoStatement = null;
20+
private ?ResultDriver $result = null;
2221

2322
/** @var callable(array, ResultSet): array */
2423
private $normalizer;
@@ -44,7 +43,7 @@ public function __construct(
4443
if (str_starts_with($queryString, '::')) {
4544
$driver->{substr($queryString, 2)}();
4645
} else {
47-
$this->pdoStatement = $driver->query($queryString, $params);
46+
$this->result = $driver->query($queryString, $params);
4847
}
4948

5049
$this->time = microtime(true) - $time;
@@ -63,7 +62,7 @@ public function getConnection(): Connection
6362
*/
6463
public function getPdoStatement(): ?\PDOStatement
6564
{
66-
return $this->pdoStatement;
65+
return $this->result->getPDOStatement();
6766
}
6867

6968

@@ -81,19 +80,19 @@ public function getParameters(): array
8180

8281
public function getColumnCount(): ?int
8382
{
84-
return $this->pdoStatement ? $this->pdoStatement->columnCount() : null;
83+
return $this->result?->getColumnCount();
8584
}
8685

8786

8887
public function getRowCount(): ?int
8988
{
90-
return $this->pdoStatement ? $this->pdoStatement->rowCount() : null;
89+
return $this->result?->getRowCount();
9190
}
9291

9392

9493
public function getColumnTypes(): array
9594
{
96-
$this->types ??= $this->connection->getDriver()->getColumnTypes($this->pdoStatement);
95+
$this->types ??= $this->result->getColumnTypes();
9796
return $this->types;
9897
}
9998

@@ -169,13 +168,12 @@ public function valid(): bool
169168
*/
170169
public function fetch(): ?Row
171170
{
172-
$data = $this->pdoStatement ? $this->pdoStatement->fetch() : null;
173-
if (!$data) {
174-
$this->pdoStatement->closeCursor();
171+
$data = $this->result?->fetch();
172+
if ($data === null) {
175173
return null;
176174

177-
} elseif ($this->lastRow === null && count($data) !== $this->pdoStatement->columnCount()) {
178-
$duplicates = Helpers::findDuplicates($this->pdoStatement);
175+
} elseif ($this->lastRow === null && count($data) !== $this->result->getColumnCount()) {
176+
$duplicates = Helpers::findDuplicates($this->result);
179177
trigger_error("Found duplicate columns in database result set: $duplicates.");
180178
}
181179

@@ -191,6 +189,13 @@ public function fetch(): ?Row
191189
}
192190

193191

192+
/** @internal */
193+
public function fetchArray(): ?array
194+
{
195+
return $this->result?->fetch();
196+
}
197+
198+
194199
/**
195200
* Fetches single field.
196201
*/

src/Database/Table/Selection.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,11 +530,13 @@ protected function execute(): void
530530

531531
$this->rows = [];
532532
$usedPrimary = true;
533-
foreach ($result->getPdoStatement() as $key => $row) {
533+
$key = 0;
534+
while ($row = $result->fetchArray()) {
534535
$row = $this->createRow($result->normalizeRow($row));
535536
$primary = $row->getSignature(false);
536537
$usedPrimary = $usedPrimary && $primary !== '';
537538
$this->rows[$usedPrimary ? $primary : $key] = $row;
539+
$key++;
538540
}
539541

540542
$this->data = $this->rows;

0 commit comments

Comments
 (0)