Skip to content

Commit 50aa657

Browse files
committed
added ResultDriver
1 parent 2aa30e7 commit 50aa657

8 files changed

Lines changed: 143 additions & 25 deletions

File tree

src/Database/Connection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ public function query(string $sql, ...$params): ResultSet
200200
[$this->sql, $params] = $this->preprocess($sql, ...$params);
201201
try {
202202
$result = new ResultSet($this, $this->sql, $params, $this->rowNormalizer);
203-
} catch (\PDOException $e) {
203+
} catch (DriverException $e) {
204204
Arrays::invoke($this->onQuery, $this, $e);
205205
throw $e;
206206
}

src/Database/Driver.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function connect(string $dsn, string $user = null, string $password = null, arra
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

@@ -102,11 +102,6 @@ function getIndexes(string $table): array;
102102
*/
103103
function getForeignKeys(string $table): array;
104104

105-
/**
106-
* Returns associative array of detected types (IStructure::FIELD_*) in result set.
107-
*/
108-
function getColumnTypes(\PDOStatement $statement): array;
109-
110105
/**
111106
* Cheks if driver supports specific property
112107
* @param string $item self::SUPPORT_* property

src/Database/Drivers/PDODriver.php

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

5353

54-
public function query(string $queryString, array $params)
54+
public function query(string $queryString, array $params): PDOResultDriver
5555
{
5656
try {
5757
static $types = ['boolean' => PDO::PARAM_BOOL, 'integer' => PDO::PARAM_INT,
@@ -64,7 +64,7 @@ public function query(string $queryString, array $params)
6464
}
6565
$statement->setFetchMode(PDO::FETCH_ASSOC);
6666
@$statement->execute(); // @ PHP generates warning when ATTR_ERRMODE = ERRMODE_EXCEPTION bug #73878
67-
return $statement;
67+
return new PDOResultDriver($statement, $this);
6868

6969
} catch (PDOException $e) {
7070
$e = $this->convertException($e);
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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+
use Nette\Database;
14+
15+
16+
/**
17+
* PDO-based result-set driver.
18+
*/
19+
class PDOResultDriver implements Nette\Database\ResultDriver
20+
{
21+
use Nette\SmartObject;
22+
23+
private \PDOStatement $result;
24+
25+
private PDODriver $driver;
26+
27+
28+
public function __construct(\PDOStatement $result, Database\Drivers\PDODriver $driver)
29+
{
30+
$this->result = $result;
31+
$this->driver = $driver;
32+
}
33+
34+
35+
public function fetch(): ?array
36+
{
37+
$data = $this->result->fetch();
38+
if (!$data) {
39+
$this->result->closeCursor();
40+
return null;
41+
}
42+
return $data;
43+
}
44+
45+
46+
public function getColumnCount(): int
47+
{
48+
return $this->result->columnCount();
49+
}
50+
51+
52+
public function getRowCount(): int
53+
{
54+
return $this->result->rowCount();
55+
}
56+
57+
58+
public function getColumnTypes(): array
59+
{
60+
return $this->driver->getColumnTypes($this->result);
61+
}
62+
63+
64+
public function getColumnMeta(int $col): array
65+
{
66+
return $this->result->getColumnMeta($col);
67+
}
68+
69+
70+
public function getPDOStatement(): \PDOStatement
71+
{
72+
return $this->result;
73+
}
74+
}

src/Database/Helpers.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,11 +355,11 @@ public static function toPairs(array $rows, $key = null, $value = null): array
355355
/**
356356
* Finds duplicate columns in select statement
357357
*/
358-
public static function findDuplicates(\PDOStatement $statement): string
358+
public static function findDuplicates(ResultDriver $result): string
359359
{
360360
$cols = [];
361-
for ($i = 0; $i < $statement->columnCount(); $i++) {
362-
$meta = $statement->getColumnMeta($i);
361+
for ($i = 0; $i < $result->getColumnCount(); $i++) {
362+
$meta = $result->getColumnMeta($i);
363363
$cols[$meta['name']][] = $meta['table'] ?? '';
364364
}
365365
$duplicates = [];

src/Database/ResultDriver.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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 (IStructure::FIELD_*) in result set.
35+
*/
36+
function getColumnTypes(): array;
37+
38+
/**
39+
* Returns associative array of original table names.
40+
*/
41+
function getColumnMeta(int $col): array;
42+
}

src/Database/ResultSet.php

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

1212
use Nette;
13-
use PDO;
1413

1514

1615
/**
@@ -22,7 +21,7 @@ class ResultSet implements \Iterator, IRowContainer
2221

2322
private Connection $connection;
2423

25-
private ?\PDOStatement $pdoStatement;
24+
private ?ResultDriver $result;
2625

2726
/** @var callable(array, ResultSet): array */
2827
private $normalizer;
@@ -55,7 +54,7 @@ public function __construct(Connection $connection, string $queryString, array $
5554
if (str_starts_with($queryString, '::')) {
5655
$driver->{substr($queryString, 2)}();
5756
} elseif ($queryString !== null) {
58-
$this->pdoStatement = $driver->query($queryString, $params);
57+
$this->result = $driver->query($queryString, $params);
5958
}
6059
$this->time = microtime(true) - $time;
6160
}
@@ -64,7 +63,7 @@ public function __construct(Connection $connection, string $queryString, array $
6463
/** @deprecated */
6564
public function getPdoStatement(): ?\PDOStatement
6665
{
67-
return $this->pdoStatement;
66+
return $this->result->getPDOStatement();
6867
}
6968

7069

@@ -82,20 +81,20 @@ public function getParameters(): array
8281

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

8887

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

9493

9594
public function getColumnTypes(): array
9695
{
9796
if (!isset($this->types)) {
98-
$this->types = $this->connection->getDriver()->getColumnTypes($this->pdoStatement);
97+
$this->types = $this->result->getColumnTypes();
9998
}
10099
return $this->types;
101100
}
@@ -172,13 +171,12 @@ public function valid(): bool
172171
*/
173172
public function fetch(): ?Row
174173
{
175-
$data = $this->pdoStatement ? $this->pdoStatement->fetch() : null;
176-
if (!$data) {
177-
$this->pdoStatement->closeCursor();
174+
$data = $this->result?->fetch();
175+
if ($data === null) {
178176
return null;
179177

180-
} elseif (!isset($this->lastRow) && count($data) !== $this->pdoStatement->columnCount()) {
181-
$duplicates = Helpers::findDuplicates($this->pdoStatement);
178+
} elseif (!isset($this->lastRow) && count($data) !== $this->result->getColumnCount()) {
179+
$duplicates = Helpers::findDuplicates($this->result);
182180
trigger_error("Found duplicate columns in database result set: $duplicates.", E_USER_NOTICE);
183181
}
184182

@@ -194,6 +192,13 @@ public function fetch(): ?Row
194192
}
195193

196194

195+
/** @internal */
196+
public function fetchArray(): ?array
197+
{
198+
return $this->result?->fetch();
199+
}
200+
201+
197202
/**
198203
* Fetches single field.
199204
*/

src/Database/Table/Selection.php

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

528528
$this->rows = [];
529529
$usedPrimary = true;
530-
foreach ($result->getPdoStatement() as $key => $row) {
530+
$key = 0;
531+
while ($row = $result->fetchArray()) {
531532
$row = $this->createRow($result->normalizeRow($row));
532533
$primary = $row->getSignature(false);
533534
$usedPrimary = $usedPrimary && $primary !== '';
534535
$this->rows[$usedPrimary ? $primary : $key] = $row;
536+
$key++;
535537
}
536538
$this->data = $this->rows;
537539

0 commit comments

Comments
 (0)