Skip to content

Commit 87cbab8

Browse files
committed
added ResultDriver
1 parent c7fd4d8 commit 87cbab8

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
@@ -197,7 +197,7 @@ public function query(string $sql, ...$params): ResultSet
197197
[$this->sql, $params] = $this->preprocess($sql, ...$params);
198198
try {
199199
$result = new ResultSet($this, $this->sql, $params, $this->rowNormalizer);
200-
} catch (\PDOException $e) {
200+
} catch (DriverException $e) {
201201
Arrays::invoke($this->onQuery, $this, $e);
202202
throw $e;
203203
}

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
@@ -42,7 +42,7 @@ public function getPdo(): ?PDO
4242
}
4343

4444

45-
public function query(string $queryString, array $params)
45+
public function query(string $queryString, array $params): PdoResultDriver
4646
{
4747
try {
4848
static $types = ['boolean' => PDO::PARAM_BOOL, 'integer' => PDO::PARAM_INT,
@@ -55,7 +55,7 @@ public function query(string $queryString, array $params)
5555
}
5656
$statement->setFetchMode(PDO::FETCH_ASSOC);
5757
@$statement->execute(); // @ PHP generates warning when ATTR_ERRMODE = ERRMODE_EXCEPTION bug #73878
58-
return $statement;
58+
return new PdoResultDriver($statement, $this);
5959

6060
} catch (PDOException $e) {
6161
$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, 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
@@ -356,11 +356,11 @@ public static function toPairs(array $rows, $key = null, $value = null): array
356356
/**
357357
* Finds duplicate columns in select statement
358358
*/
359-
public static function findDuplicates(\PDOStatement $statement): string
359+
public static function findDuplicates(ResultDriver $result): string
360360
{
361361
$cols = [];
362-
for ($i = 0; $i < $statement->columnCount(); $i++) {
363-
$meta = $statement->getColumnMeta($i);
362+
for ($i = 0; $i < $result->getColumnCount(); $i++) {
363+
$meta = $result->getColumnMeta($i);
364364
$cols[$meta['name']][] = $meta['table'] ?? '';
365365
}
366366
$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
/**
@@ -21,7 +20,7 @@ class ResultSet implements \Iterator, IRowContainer
2120
use Nette\SmartObject;
2221

2322
private Connection $connection;
24-
private ?\PDOStatement $pdoStatement;
23+
private ?ResultDriver $result;
2524

2625
/** @var callable(array, ResultSet): array */
2726
private $normalizer;
@@ -50,7 +49,7 @@ public function __construct(Connection $connection, string $queryString, array $
5049
if (str_starts_with($queryString, '::')) {
5150
$driver->{substr($queryString, 2)}();
5251
} elseif ($queryString !== null) {
53-
$this->pdoStatement = $driver->query($queryString, $params);
52+
$this->result = $driver->query($queryString, $params);
5453
}
5554
$this->time = microtime(true) - $time;
5655
}
@@ -68,7 +67,7 @@ public function getConnection(): Connection
6867
*/
6968
public function getPdoStatement(): ?\PDOStatement
7069
{
71-
return $this->pdoStatement;
70+
return $this->result->getPDOStatement();
7271
}
7372

7473

@@ -86,20 +85,20 @@ public function getParameters(): array
8685

8786
public function getColumnCount(): ?int
8887
{
89-
return $this->pdoStatement ? $this->pdoStatement->columnCount() : null;
88+
return $this->result?->getColumnCount();
9089
}
9190

9291

9392
public function getRowCount(): ?int
9493
{
95-
return $this->pdoStatement ? $this->pdoStatement->rowCount() : null;
94+
return $this->result?->getRowCount();
9695
}
9796

9897

9998
public function getColumnTypes(): array
10099
{
101100
if (!isset($this->types)) {
102-
$this->types = $this->connection->getDriver()->getColumnTypes($this->pdoStatement);
101+
$this->types = $this->result->getColumnTypes();
103102
}
104103
return $this->types;
105104
}
@@ -176,13 +175,12 @@ public function valid(): bool
176175
*/
177176
public function fetch(): ?Row
178177
{
179-
$data = $this->pdoStatement ? $this->pdoStatement->fetch() : null;
180-
if (!$data) {
181-
$this->pdoStatement->closeCursor();
178+
$data = $this->result?->fetch();
179+
if ($data === null) {
182180
return null;
183181

184-
} elseif (!isset($this->lastRow) && count($data) !== $this->pdoStatement->columnCount()) {
185-
$duplicates = Helpers::findDuplicates($this->pdoStatement);
182+
} elseif (!isset($this->lastRow) && count($data) !== $this->result->getColumnCount()) {
183+
$duplicates = Helpers::findDuplicates($this->result);
186184
trigger_error("Found duplicate columns in database result set: $duplicates.", E_USER_NOTICE);
187185
}
188186

@@ -198,6 +196,13 @@ public function fetch(): ?Row
198196
}
199197

200198

199+
/** @internal */
200+
public function fetchArray(): ?array
201+
{
202+
return $this->result?->fetch();
203+
}
204+
205+
201206
/**
202207
* Fetches single field.
203208
*/

src/Database/Table/Selection.php

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

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

0 commit comments

Comments
 (0)