Skip to content

Commit c66a771

Browse files
committed
added ResultDriver
1 parent 4de1a69 commit c66a771

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
@@ -202,7 +202,7 @@ public function query(string $sql, ...$params): ResultSet
202202
[$this->sql, $params] = $this->preprocess($sql, ...$params);
203203
try {
204204
$result = new ResultSet($this, $this->sql, $params, $this->rowNormalizer);
205-
} catch (\PDOException $e) {
205+
} catch (DriverException $e) {
206206
Arrays::invoke($this->onQuery, $this, $e);
207207
throw $e;
208208
}

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
/**
@@ -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
}
@@ -73,7 +72,7 @@ public function getConnection(): Connection
7372
*/
7473
public function getPdoStatement(): ?\PDOStatement
7574
{
76-
return $this->pdoStatement;
75+
return $this->result->getPDOStatement();
7776
}
7877

7978

@@ -91,20 +90,20 @@ public function getParameters(): array
9190

9291
public function getColumnCount(): ?int
9392
{
94-
return $this->pdoStatement ? $this->pdoStatement->columnCount() : null;
93+
return $this->result?->getColumnCount();
9594
}
9695

9796

9897
public function getRowCount(): ?int
9998
{
100-
return $this->pdoStatement ? $this->pdoStatement->rowCount() : null;
99+
return $this->result?->getRowCount();
101100
}
102101

103102

104103
public function getColumnTypes(): array
105104
{
106105
if (!isset($this->types)) {
107-
$this->types = $this->connection->getDriver()->getColumnTypes($this->pdoStatement);
106+
$this->types = $this->result->getColumnTypes();
108107
}
109108
return $this->types;
110109
}
@@ -181,13 +180,12 @@ public function valid(): bool
181180
*/
182181
public function fetch(): ?Row
183182
{
184-
$data = $this->pdoStatement ? $this->pdoStatement->fetch() : null;
185-
if (!$data) {
186-
$this->pdoStatement->closeCursor();
183+
$data = $this->result?->fetch();
184+
if ($data === null) {
187185
return null;
188186

189-
} elseif (!isset($this->lastRow) && count($data) !== $this->pdoStatement->columnCount()) {
190-
$duplicates = Helpers::findDuplicates($this->pdoStatement);
187+
} elseif (!isset($this->lastRow) && count($data) !== $this->result->getColumnCount()) {
188+
$duplicates = Helpers::findDuplicates($this->result);
191189
trigger_error("Found duplicate columns in database result set: $duplicates.", E_USER_NOTICE);
192190
}
193191

@@ -203,6 +201,13 @@ public function fetch(): ?Row
203201
}
204202

205203

204+
/** @internal */
205+
public function fetchArray(): ?array
206+
{
207+
return $this->result?->fetch();
208+
}
209+
210+
206211
/**
207212
* Fetches single field.
208213
*/

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)