Skip to content

Commit c48afea

Browse files
committed
Move the logic of wrapping driver exceptions to the connection
1 parent aac506f commit c48afea

File tree

10 files changed

+136
-181
lines changed

10 files changed

+136
-181
lines changed

phpstan.neon.dist

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ parameters:
88
reportUnmatchedIgnoredErrors: false
99
checkMissingIterableValueType: false
1010
checkGenericClassInNonGenericObjectType: false
11-
earlyTerminatingMethodCalls:
12-
Doctrine\DBAL\Connection:
13-
- handleDriverException
14-
- handleExceptionDuringQuery
1511
ignoreErrors:
1612
# removing it would be BC break
1713
- '~^Constructor of class Doctrine\\DBAL\\Schema\\Table has an unused parameter \$idGeneratorType\.\z~'

src/Connection.php

Lines changed: 75 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Doctrine\DBAL\Cache\CacheException;
1010
use Doctrine\DBAL\Cache\CachingResult;
1111
use Doctrine\DBAL\Cache\QueryCacheProfile;
12+
use Doctrine\DBAL\Driver\API\ExceptionConverter;
1213
use Doctrine\DBAL\Driver\Connection as DriverConnection;
1314
use Doctrine\DBAL\Driver\Exception as DriverException;
1415
use Doctrine\DBAL\Driver\Result as DriverResult;
@@ -26,12 +27,18 @@
2627
use Traversable;
2728

2829
use function array_key_exists;
30+
use function array_map;
2931
use function assert;
32+
use function bin2hex;
3033
use function count;
3134
use function implode;
3235
use function is_int;
36+
use function is_resource;
3337
use function is_string;
38+
use function json_encode;
3439
use function key;
40+
use function preg_replace;
41+
use function sprintf;
3542

3643
/**
3744
* A wrapper around a Doctrine\DBAL\Driver\Connection that adds features like
@@ -114,6 +121,9 @@ class Connection implements DriverConnection
114121
*/
115122
private $platform;
116123

124+
/** @var ExceptionConverter|null */
125+
private $exceptionConverter;
126+
117127
/**
118128
* The schema manager.
119129
*
@@ -284,7 +294,7 @@ public function connect()
284294
try {
285295
$this->_conn = $this->_driver->connect($this->params);
286296
} catch (DriverException $e) {
287-
throw DBALException::driverException($this->_driver, $e);
297+
throw $this->convertException($e);
288298
}
289299

290300
$this->transactionNestingLevel = 0;
@@ -468,7 +478,7 @@ public function fetchAssociative(string $query, array $params = [], array $types
468478
try {
469479
return $this->executeQuery($query, $params, $types)->fetchAssociative();
470480
} catch (DriverException $e) {
471-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
481+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
472482
}
473483
}
474484

@@ -489,7 +499,7 @@ public function fetchNumeric(string $query, array $params = [], array $types = [
489499
try {
490500
return $this->executeQuery($query, $params, $types)->fetchNumeric();
491501
} catch (DriverException $e) {
492-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
502+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
493503
}
494504
}
495505

@@ -510,7 +520,7 @@ public function fetchOne(string $query, array $params = [], array $types = [])
510520
try {
511521
return $this->executeQuery($query, $params, $types)->fetchOne();
512522
} catch (DriverException $e) {
513-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
523+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
514524
}
515525
}
516526

@@ -772,7 +782,7 @@ public function fetchAllNumeric(string $query, array $params = [], array $types
772782
try {
773783
return $this->executeQuery($query, $params, $types)->fetchAllNumeric();
774784
} catch (DriverException $e) {
775-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
785+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
776786
}
777787
}
778788

@@ -792,7 +802,7 @@ public function fetchAllAssociative(string $query, array $params = [], array $ty
792802
try {
793803
return $this->executeQuery($query, $params, $types)->fetchAllAssociative();
794804
} catch (DriverException $e) {
795-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
805+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
796806
}
797807
}
798808

@@ -812,7 +822,7 @@ public function fetchFirstColumn(string $query, array $params = [], array $types
812822
try {
813823
return $this->executeQuery($query, $params, $types)->fetchFirstColumn();
814824
} catch (DriverException $e) {
815-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
825+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
816826
}
817827
}
818828

@@ -836,7 +846,7 @@ public function iterateNumeric(string $query, array $params = [], array $types =
836846
yield $row;
837847
}
838848
} catch (DriverException $e) {
839-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
849+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
840850
}
841851
}
842852

@@ -860,7 +870,7 @@ public function iterateAssociative(string $query, array $params = [], array $typ
860870
yield $row;
861871
}
862872
} catch (DriverException $e) {
863-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
873+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
864874
}
865875
}
866876

@@ -884,7 +894,7 @@ public function iterateColumn(string $query, array $params = [], array $types =
884894
yield $value;
885895
}
886896
} catch (DriverException $e) {
887-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
897+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
888898
}
889899
}
890900

@@ -949,7 +959,7 @@ public function executeQuery(
949959

950960
return new Result($result, $this);
951961
} catch (DriverException $e) {
952-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
962+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
953963
} finally {
954964
if ($logger !== null) {
955965
$logger->stopQuery();
@@ -1021,7 +1031,7 @@ public function query(string $sql): DriverResult
10211031
try {
10221032
return $connection->query($sql);
10231033
} catch (DriverException $e) {
1024-
$this->handleExceptionDuringQuery($e, $sql);
1034+
throw $this->convertExceptionDuringQuery($e, $sql);
10251035
} finally {
10261036
if ($logger !== null) {
10271037
$logger->stopQuery();
@@ -1069,7 +1079,7 @@ public function executeUpdate(string $query, array $params = [], array $types =
10691079

10701080
return $connection->exec($query);
10711081
} catch (DriverException $e) {
1072-
$this->handleExceptionDuringQuery($e, $query, $params, $types);
1082+
throw $this->convertExceptionDuringQuery($e, $query, $params, $types);
10731083
} finally {
10741084
if ($logger !== null) {
10751085
$logger->stopQuery();
@@ -1092,7 +1102,7 @@ public function exec(string $statement): int
10921102
try {
10931103
return $connection->exec($statement);
10941104
} catch (DriverException $e) {
1095-
$this->handleExceptionDuringQuery($e, $statement);
1105+
throw $this->convertExceptionDuringQuery($e, $statement);
10961106
} finally {
10971107
if ($logger !== null) {
10981108
$logger->stopQuery();
@@ -1580,15 +1590,12 @@ private function getBindingInfo($value, $type)
15801590
/**
15811591
* Resolves the parameters to a format which can be displayed.
15821592
*
1583-
* @internal This is a purely internal method. If you rely on this method, you are advised to
1584-
* copy/paste the code as this method may change, or be removed without prior notice.
1585-
*
15861593
* @param mixed[] $params
15871594
* @param array<int|string|null> $types
15881595
*
15891596
* @return mixed[]
15901597
*/
1591-
public function resolveParams(array $params, array $types)
1598+
private function resolveParams(array $params, array $types): array
15921599
{
15931600
$resolvedParams = [];
15941601

@@ -1640,53 +1647,73 @@ public function createQueryBuilder()
16401647
*
16411648
* @param array<mixed> $params
16421649
* @param array<int|string|null> $types
1643-
*
1644-
* @throws DBALException
1645-
*
1646-
* @psalm-return never-return
16471650
*/
1648-
public function handleExceptionDuringQuery(Throwable $e, string $sql, array $params = [], array $types = []): void
1649-
{
1650-
$this->throw(
1651-
DBALException::driverExceptionDuringQuery(
1652-
$this->_driver,
1653-
$e,
1654-
$sql,
1651+
final public function convertExceptionDuringQuery(
1652+
DriverException $e,
1653+
string $sql,
1654+
array $params = [],
1655+
array $types = []
1656+
): DBALException {
1657+
$message = "An exception occurred while executing '" . $sql . "'";
1658+
1659+
if (count($params) > 0) {
1660+
$message .= ' with params ' . $this->formatParameters(
16551661
$this->resolveParams($params, $types)
1656-
)
1657-
);
1662+
);
1663+
}
1664+
1665+
$message .= ":\n\n" . $e->getMessage();
1666+
1667+
return $this->handleDriverException($e, $message);
16581668
}
16591669

16601670
/**
16611671
* @internal
1662-
*
1663-
* @throws DBALException
1664-
*
1665-
* @psalm-return never-return
16661672
*/
1667-
public function handleDriverException(Throwable $e): void
1673+
final public function convertException(DriverException $e): DBALException
16681674
{
1669-
$this->throw(
1670-
DBALException::driverException(
1671-
$this->_driver,
1672-
$e
1673-
)
1675+
return $this->handleDriverException(
1676+
$e,
1677+
'An exception occurred in driver: ' . $e->getMessage()
16741678
);
16751679
}
16761680

16771681
/**
1678-
* @internal
1679-
*
1680-
* @throws DBALException
1682+
* Returns a human-readable representation of an array of parameters.
1683+
* This properly handles binary data by returning a hex representation.
16811684
*
1682-
* @psalm-return never-return
1685+
* @param mixed[] $params
16831686
*/
1684-
private function throw(DBALException $e): void
1687+
private function formatParameters(array $params): string
16851688
{
1686-
if ($e instanceof ConnectionLost) {
1689+
return '[' . implode(', ', array_map(static function ($param): string {
1690+
if (is_resource($param)) {
1691+
return (string) $param;
1692+
}
1693+
1694+
$json = @json_encode($param);
1695+
1696+
if (! is_string($json) || $json === 'null' && is_string($param)) {
1697+
// JSON encoding failed, this is not a UTF-8 string.
1698+
return sprintf('"%s"', preg_replace('/.{2}/', '\\x$0', bin2hex($param)));
1699+
}
1700+
1701+
return $json;
1702+
}, $params)) . ']';
1703+
}
1704+
1705+
private function handleDriverException(DriverException $driverException, string $message): DBALException
1706+
{
1707+
if ($this->exceptionConverter === null) {
1708+
$this->exceptionConverter = $this->_driver->getExceptionConverter();
1709+
}
1710+
1711+
$exception = $this->exceptionConverter->convert($message, $driverException);
1712+
1713+
if ($exception instanceof ConnectionLost) {
16871714
$this->close();
16881715
}
16891716

1690-
throw $e;
1717+
return $exception;
16911718
}
16921719
}

src/Connections/PrimaryReadReplicaConnection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ protected function connectTo($connectionName)
232232
try {
233233
return $this->_driver->connect($connectionParams);
234234
} catch (DriverException $e) {
235-
throw DBALException::driverException($this->_driver, $e);
235+
throw $this->convertException($e);
236236
}
237237
}
238238

0 commit comments

Comments
 (0)