Skip to content

Commit 3dadbef

Browse files
committed
try/catch checking and converting of PDOException moved to drivers
1 parent bb7bd16 commit 3dadbef

22 files changed

+169
-157
lines changed

src/Bridges/DatabaseTracy/ConnectionPanel.php

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
use Nette;
1313
use Nette\Database\Connection;
14+
use Nette\Database\DriverException;
1415
use Nette\Database\Helpers;
1516
use Nette\Database\Result;
1617
use Tracy;
@@ -72,7 +73,7 @@ private function logQuery(Connection $connection, $result): void
7273

7374
$this->count++;
7475

75-
$trace = $result instanceof \PDOException
76+
$trace = $result instanceof DriverException
7677
? array_map(fn($row) => array_diff_key($row, ['args' => null]), $result->getTrace())
7778
: debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
7879

@@ -88,26 +89,20 @@ private function logQuery(Connection $connection, $result): void
8889
if ($this->count < $this->maxQueries) {
8990
$this->events[] = [$connection, $result->getQueryString(), $result->getParameters(), $trace, $result->getTime(), $result->getRowCount(), null];
9091
}
91-
} elseif ($result instanceof \PDOException && $this->count < $this->maxQueries) {
92-
$this->events[] = [$connection, $result->queryString, null, $trace, null, null, $result->getMessage()];
92+
} elseif ($result instanceof DriverException && $this->count < $this->maxQueries) {
93+
$this->events[] = [$connection, $result->getQueryString(), null, $trace, null, null, $result->getMessage()];
9394
}
9495
}
9596

9697

9798
public static function renderException(?\Throwable $e): ?array
9899
{
99-
if (!$e instanceof \PDOException) {
100+
if (!$e instanceof DriverException) {
100101
return null;
101102
}
102103

103-
if (isset($e->queryString)) {
104-
$sql = $e->queryString;
105-
106-
} elseif ($item = Tracy\Helpers::findTrace($e->getTrace(), 'PDO::prepare')) {
107-
$sql = $item['args'][0];
108-
}
109-
110-
return isset($sql) ? [
104+
$sql = $e->getQueryString();
105+
return $sql ? [
111106
'tab' => 'SQL',
112107
'panel' => Helpers::dumpSql($sql, $e->params ?? []),
113108
] : null;
@@ -145,7 +140,7 @@ public function getPanel(): ?string
145140
: 'EXPLAIN';
146141
$rows = $connection->getConnection()->query("$cmd $sql", $params);
147142
for ($explain = []; $row = $rows->fetch(); $explain[] = $row);
148-
} catch (\PDOException) {
143+
} catch (DriverException) {
149144
}
150145
}
151146

src/Database/Connection.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use JetBrains\PhpStorm\Language;
1313
use Nette;
1414
use Nette\Utils\Arrays;
15-
use PDOException;
1615
use function func_get_args, str_replace, ucfirst;
1716

1817

@@ -83,7 +82,7 @@ public function connect(): void
8382

8483
try {
8584
$this->connection = $this->driver->connect();
86-
} catch (PDOException $e) {
85+
} catch (DriverException $e) {
8786
throw ConnectionException::from($e);
8887
}
8988

@@ -177,8 +176,8 @@ public function getInsertId(?string $sequence = null): string
177176
{
178177
try {
179178
return $this->getConnection()->getInsertId($sequence);
180-
} catch (PDOException $e) {
181-
throw $this->getDatabaseEngine()->convertException($e);
179+
} catch (DriverException $e) {
180+
throw $this->convertException($e);
182181
}
183182
}
184183

@@ -273,7 +272,7 @@ public function query(#[Language('SQL')] string $sql, #[Language('GenericSQL')]
273272
[$this->sql, $params] = $this->preprocess($sql, ...$params);
274273
try {
275274
$result = new Result($this, $this->sql, $params);
276-
} catch (PDOException $e) {
275+
} catch (DriverException $e) {
277276
Arrays::invoke($this->onQuery, $this, $e);
278277
throw $e;
279278
}
@@ -311,6 +310,13 @@ public function getLastQueryString(): ?string
311310
}
312311

313312

313+
public function convertException(DriverException $e): DriverException
314+
{
315+
$class = $this->getDatabaseEngine()->classifyException($e);
316+
return $class ? $class::from($e) : $e;
317+
}
318+
319+
314320
/********************* shortcuts ****************d*g**/
315321

316322

src/Database/DriverException.php

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,51 +15,46 @@
1515
/**
1616
* Base class for all errors in the driver or SQL server.
1717
*/
18-
class DriverException extends \PDOException
18+
class DriverException extends \Exception
1919
{
20-
public ?string $queryString = null;
21-
public ?array $params = null;
20+
public static function from(self $e): static
21+
{
22+
return new static($e->getMessage(), $e->sqlState, $e->getDriverCode() ?? 0, $e->query, $e);
23+
}
2224

2325

24-
public static function from(\PDOException $src): static
25-
{
26-
$e = new static($src->message, 0, $src);
27-
$e->file = $src->file;
28-
$e->line = $src->line;
29-
if (!$src->errorInfo && preg_match('#SQLSTATE\[(.*?)\] \[(.*?)\] (.*)#A', $src->message, $m)) {
30-
$m[2] = (int) $m[2];
31-
$e->errorInfo = array_slice($m, 1);
32-
$e->code = $m[1];
33-
} else {
34-
$e->errorInfo = $src->errorInfo;
35-
$e->code = $src->code;
36-
$e->code = $e->errorInfo[0] ?? $src->code;
37-
}
38-
39-
return $e;
26+
public function __construct(
27+
string $message,
28+
private readonly ?string $sqlState = null,
29+
private int $driverCode = 0,
30+
private readonly ?SqlLiteral $query = null,
31+
?\Throwable $previous = null,
32+
) {
33+
parent::__construct($message, 0, $previous);
34+
$this->code = $sqlState ?: null;
4035
}
4136

4237

4338
public function getDriverCode(): int|string|null
4439
{
45-
return $this->errorInfo[1] ?? null;
40+
return $this->driverCode ?: null;
4641
}
4742

4843

4944
public function getSqlState(): ?string
5045
{
51-
return $this->errorInfo[0] ?? null;
46+
return $this->sqlState;
5247
}
5348

5449

5550
public function getQueryString(): ?string
5651
{
57-
return $this->queryString;
52+
return $this->query?->getSql();
5853
}
5954

6055

6156
public function getParameters(): ?array
6257
{
63-
return $this->params;
58+
return $this->query?->getParameters();
6459
}
6560
}

src/Database/Drivers/Engine.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace Nette\Database\Drivers;
1111

12-
use Nette\Database;
12+
use Nette\Database\DriverException;
1313
use Nette\Database\TypeConverter;
1414

1515

@@ -31,10 +31,8 @@ interface Engine
3131
*/
3232
function isSupported(string $feature): bool;
3333

34-
/**
35-
* Converts PDOException to DriverException or its descendant.
36-
*/
37-
function convertException(\PDOException $e): Database\DriverException;
34+
/** Maps a driver exception to an appropriate exception class. */
35+
function classifyException(DriverException $e): ?string;
3836

3937
/** Converts a value from the database to a PHP value. */
4038
function convertToPhp(mixed $value, array $meta, TypeConverter $converter): mixed;

src/Database/Drivers/Engines/MSSQLEngine.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ public function isSupported(string $feature): bool
3333
}
3434

3535

36-
public function convertException(\PDOException $e): Nette\Database\DriverException
36+
public function classifyException(Nette\Database\DriverException $e): ?string
3737
{
38-
return Nette\Database\DriverException::from($e);
38+
return null;
3939
}
4040

4141

src/Database/Drivers/Engines/MySQLEngine.php

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,16 @@ public function isSupported(string $feature): bool
3737
}
3838

3939

40-
public function convertException(\PDOException $e): Nette\Database\DriverException
40+
public function classifyException(Nette\Database\DriverException $e): ?string
4141
{
42-
$code = $e->errorInfo[1] ?? null;
43-
if (in_array($code, [1216, 1217, 1451, 1452, 1701], strict: true)) {
44-
return Nette\Database\ForeignKeyConstraintViolationException::from($e);
45-
46-
} elseif (in_array($code, [1062, 1557, 1569, 1586], strict: true)) {
47-
return Nette\Database\UniqueConstraintViolationException::from($e);
48-
49-
} elseif ($code >= 2001 && $code <= 2028) {
50-
return Nette\Database\ConnectionException::from($e);
51-
52-
} elseif (in_array($code, [1048, 1121, 1138, 1171, 1252, 1263, 1566], strict: true)) {
53-
return Nette\Database\NotNullConstraintViolationException::from($e);
54-
55-
} else {
56-
return Nette\Database\DriverException::from($e);
57-
}
42+
$code = $e->getDriverCode();
43+
return match (true) {
44+
in_array($code, [1216, 1217, 1451, 1452, 1701], strict: true) => Nette\Database\ForeignKeyConstraintViolationException::class,
45+
in_array($code, [1062, 1557, 1569, 1586], strict: true) => Nette\Database\UniqueConstraintViolationException::class,
46+
$code >= 2001 && $code <= 2028 => Nette\Database\ConnectionException::class,
47+
in_array($code, [1048, 1121, 1138, 1171, 1252, 1263, 1566], strict: true) => Nette\Database\NotNullConstraintViolationException::class,
48+
default => null,
49+
};
5850
}
5951

6052

src/Database/Drivers/Engines/ODBCEngine.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ public function isSupported(string $feature): bool
2626
}
2727

2828

29-
public function convertException(\PDOException $e): Nette\Database\DriverException
29+
public function classifyException(Nette\Database\DriverException $e): ?string
3030
{
31-
return Nette\Database\DriverException::from($e);
31+
return null;
3232
}
3333

3434

src/Database/Drivers/Engines/OracleEngine.php

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,15 @@ public function isSupported(string $feature): bool
3636
}
3737

3838

39-
public function convertException(\PDOException $e): Nette\Database\DriverException
39+
public function classifyException(Nette\Database\DriverException $e): ?string
4040
{
41-
$code = $e->errorInfo[1] ?? null;
42-
if (in_array($code, [1, 2299, 38911], strict: true)) {
43-
return Nette\Database\UniqueConstraintViolationException::from($e);
44-
45-
} elseif (in_array($code, [1400], strict: true)) {
46-
return Nette\Database\NotNullConstraintViolationException::from($e);
47-
48-
} elseif (in_array($code, [2266, 2291, 2292], strict: true)) {
49-
return Nette\Database\ForeignKeyConstraintViolationException::from($e);
50-
51-
} else {
52-
return Nette\Database\DriverException::from($e);
53-
}
41+
$code = $e->getDriverCode();
42+
return match (true) {
43+
in_array($code, [1, 2299, 38911], strict: true) => Nette\Database\UniqueConstraintViolationException::class,
44+
in_array($code, [1400], strict: true) => Nette\Database\NotNullConstraintViolationException::class,
45+
in_array($code, [2266, 2291, 2292], strict: true) => Nette\Database\ForeignKeyConstraintViolationException::class,
46+
default => null,
47+
};
5448
}
5549

5650

src/Database/Drivers/Engines/PostgreSQLEngine.php

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,27 +33,16 @@ public function isSupported(string $feature): bool
3333
}
3434

3535

36-
public function convertException(\PDOException $e): Nette\Database\DriverException
36+
public function classifyException(Nette\Database\DriverException $e): ?string
3737
{
38-
$code = $e->errorInfo[0] ?? null;
39-
if ($code === '0A000' && str_contains($e->getMessage(), 'truncate')) {
40-
return Nette\Database\ForeignKeyConstraintViolationException::from($e);
41-
42-
} elseif ($code === '23502') {
43-
return Nette\Database\NotNullConstraintViolationException::from($e);
44-
45-
} elseif ($code === '23503') {
46-
return Nette\Database\ForeignKeyConstraintViolationException::from($e);
47-
48-
} elseif ($code === '23505') {
49-
return Nette\Database\UniqueConstraintViolationException::from($e);
50-
51-
} elseif ($code === '08006') {
52-
return Nette\Database\ConnectionException::from($e);
53-
54-
} else {
55-
return Nette\Database\DriverException::from($e);
56-
}
38+
return match ($e->getSqlState()) {
39+
'0A000' => str_contains($e->getMessage(), 'truncate') ? Nette\Database\ForeignKeyConstraintViolationException::class : null,
40+
'23502' => Nette\Database\NotNullConstraintViolationException::class,
41+
'23503' => Nette\Database\ForeignKeyConstraintViolationException::class,
42+
'23505' => Nette\Database\UniqueConstraintViolationException::class,
43+
'08006' => Nette\Database\ConnectionException::class,
44+
default => null,
45+
};
5746
}
5847

5948

src/Database/Drivers/Engines/SQLServerEngine.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ public function isSupported(string $feature): bool
3333
}
3434

3535

36-
public function convertException(\PDOException $e): Nette\Database\DriverException
36+
public function classifyException(Nette\Database\DriverException $e): ?string
3737
{
38-
return Nette\Database\DriverException::from($e);
38+
return null;
3939
}
4040

4141

0 commit comments

Comments
 (0)