Move the exception conversion logic under a separate interface

parent 5bca2b72
# Upgrade to 3.0
## BC BREAK: Changes in driver-level exception handling
1. The `convertException()` method has been removed from the `Driver` interface. The logic of exception conversion has been moved to the `ExceptionConverter` interface. The drivers now must implement the `getExceptionConverter()` method.
2. The `driverException()` and `driverExceptionDuringQuery()` factory methods have been removed from the `DBALException` class.
## BC BREAK: More driver-level methods are allowed to throw a Driver\Exception.
The following driver-level methods are allowed to throw a Driver\Exception:
......
......@@ -169,7 +169,7 @@ class DBALException extends Exception
}
if ($driverEx instanceof TheDriverException) {
return $driver->convertException($msg, $driverEx);
return $driver->getExceptionConverter()->convert($msg, $driverEx);
}
return new self($msg, 0, $driverEx);
......
......@@ -2,9 +2,9 @@
namespace Doctrine\DBAL;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Driver\Connection as DriverConnection;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
......@@ -42,15 +42,7 @@ interface Driver
public function getSchemaManager(Connection $conn);
/**
* Converts a given driver-level exception into a DBAL-level driver exception.
*
* Implementors should use the vendor-specific error code and SQLSTATE of the exception
* and instantiate the most appropriate specialized {@link DriverException} subclass.
*
* @param string $message The exception message to use.
* @param Exception $exception The driver exception to convert.
*
* @return DriverException An instance of {@link DriverException} or one of its subclasses.
* Gets the ExceptionConverter that can be used to convert driver-level exceptions into DBAL exceptions.
*/
public function convertException($message, Exception $exception);
public function getExceptionConverter(): ExceptionConverter;
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\API;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception\DriverException;
final class DefaultExceptionConverter implements ExceptionConverter
{
public function convert(string $message, Exception $exception): DriverException
{
return new DriverException($message, $exception);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\API;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception\DriverException;
interface ExceptionConverter
{
/**
* Converts a given driver-level exception into a DBAL-level driver exception.
*
* Implementors should use the vendor-specific error code and SQLSTATE of the exception
* and instantiate the most appropriate specialized {@link DriverException} subclass.
*
* @param string $message The exception message to use.
* @param Exception $exception The driver exception to convert.
*
* @return DriverException An instance of {@link DriverException} or one of its subclasses.
*/
public function convert(string $message, Exception $exception): DriverException;
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\API\MySQL;
use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception\ConnectionLost;
use Doctrine\DBAL\Exception\DeadlockException;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\InvalidFieldNameException;
use Doctrine\DBAL\Exception\LockWaitTimeoutException;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
final class ExceptionConverter implements ExceptionConverterInterface
{
/**
* @link https://dev.mysql.com/doc/refman/8.0/en/client-error-reference.html
* @link https://dev.mysql.com/doc/refman/8.0/en/server-error-reference.html
*/
public function convert(string $message, Exception $exception): DriverException
{
switch ($exception->getCode()) {
case 1213:
return new DeadlockException($message, $exception);
case 1205:
return new LockWaitTimeoutException($message, $exception);
case 1050:
return new TableExistsException($message, $exception);
case 1051:
case 1146:
return new TableNotFoundException($message, $exception);
case 1216:
case 1217:
case 1451:
case 1452:
case 1701:
return new ForeignKeyConstraintViolationException($message, $exception);
case 1062:
case 1557:
case 1569:
case 1586:
return new UniqueConstraintViolationException($message, $exception);
case 1054:
case 1166:
case 1611:
return new InvalidFieldNameException($message, $exception);
case 1052:
case 1060:
case 1110:
return new NonUniqueFieldNameException($message, $exception);
case 1064:
case 1149:
case 1287:
case 1341:
case 1342:
case 1343:
case 1344:
case 1382:
case 1479:
case 1541:
case 1554:
case 1626:
return new SyntaxErrorException($message, $exception);
case 1044:
case 1045:
case 1046:
case 1049:
case 1095:
case 1142:
case 1143:
case 1227:
case 1370:
case 1429:
case 2002:
case 2005:
return new ConnectionException($message, $exception);
case 2006:
return new ConnectionLost($message, $exception);
case 1048:
case 1121:
case 1138:
case 1171:
case 1252:
case 1263:
case 1364:
case 1566:
return new NotNullConstraintViolationException($message, $exception);
}
return new DriverException($message, $exception);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\API\OCI;
use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\InvalidFieldNameException;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
final class ExceptionConverter implements ExceptionConverterInterface
{
/**
* @link http://www.dba-oracle.com/t_error_code_list.htm
*/
public function convert(string $message, Exception $exception): DriverException
{
switch ($exception->getCode()) {
case 1:
case 2299:
case 38911:
return new UniqueConstraintViolationException($message, $exception);
case 904:
return new InvalidFieldNameException($message, $exception);
case 918:
case 960:
return new NonUniqueFieldNameException($message, $exception);
case 923:
return new SyntaxErrorException($message, $exception);
case 942:
return new TableNotFoundException($message, $exception);
case 955:
return new TableExistsException($message, $exception);
case 1017:
case 12545:
return new ConnectionException($message, $exception);
case 1400:
return new NotNullConstraintViolationException($message, $exception);
case 2266:
case 2291:
case 2292:
return new ForeignKeyConstraintViolationException($message, $exception);
}
return new DriverException($message, $exception);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\API\PostgreSQL;
use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception\DeadlockException;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\InvalidFieldNameException;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use function strpos;
final class ExceptionConverter implements ExceptionConverterInterface
{
/**
* @link http://www.postgresql.org/docs/9.4/static/errcodes-appendix.html
*/
public function convert(string $message, Exception $exception): DriverException
{
switch ($exception->getSQLState()) {
case '40001':
case '40P01':
return new DeadlockException($message, $exception);
case '0A000':
// Foreign key constraint violations during a TRUNCATE operation
// are considered "feature not supported" in PostgreSQL.
if (strpos($exception->getMessage(), 'truncate') !== false) {
return new ForeignKeyConstraintViolationException($message, $exception);
}
break;
case '23502':
return new NotNullConstraintViolationException($message, $exception);
case '23503':
return new ForeignKeyConstraintViolationException($message, $exception);
case '23505':
return new UniqueConstraintViolationException($message, $exception);
case '42601':
return new SyntaxErrorException($message, $exception);
case '42702':
return new NonUniqueFieldNameException($message, $exception);
case '42703':
return new InvalidFieldNameException($message, $exception);
case '42P01':
return new TableNotFoundException($message, $exception);
case '42P07':
return new TableExistsException($message, $exception);
}
// In some case (mainly connection errors) the PDO exception does not provide a SQLSTATE via its code.
// The exception code is always set to 7 here.
// We have to match against the SQLSTATE in the error message in these cases.
if ($exception->getCode() === 7 && strpos($exception->getMessage(), 'SQLSTATE[08006]') !== false) {
return new ConnectionException($message, $exception);
}
return new DriverException($message, $exception);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\API\SQLite;
use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\InvalidFieldNameException;
use Doctrine\DBAL\Exception\LockWaitTimeoutException;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
use Doctrine\DBAL\Exception\ReadOnlyException;
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use function strpos;
final class ExceptionConverter implements ExceptionConverterInterface
{
/**
* @link http://www.sqlite.org/c3ref/c_abort.html
*/
public function convert(string $message, Exception $exception): DriverException
{
if (strpos($exception->getMessage(), 'database is locked') !== false) {
return new LockWaitTimeoutException($message, $exception);
}
if (
strpos($exception->getMessage(), 'must be unique') !== false ||
strpos($exception->getMessage(), 'is not unique') !== false ||
strpos($exception->getMessage(), 'are not unique') !== false ||
strpos($exception->getMessage(), 'UNIQUE constraint failed') !== false
) {
return new UniqueConstraintViolationException($message, $exception);
}
if (
strpos($exception->getMessage(), 'may not be NULL') !== false ||
strpos($exception->getMessage(), 'NOT NULL constraint failed') !== false
) {
return new NotNullConstraintViolationException($message, $exception);
}
if (strpos($exception->getMessage(), 'no such table:') !== false) {
return new TableNotFoundException($message, $exception);
}
if (strpos($exception->getMessage(), 'already exists') !== false) {
return new TableExistsException($message, $exception);
}
if (strpos($exception->getMessage(), 'has no column named') !== false) {
return new InvalidFieldNameException($message, $exception);
}
if (strpos($exception->getMessage(), 'ambiguous column name') !== false) {
return new NonUniqueFieldNameException($message, $exception);
}
if (strpos($exception->getMessage(), 'syntax error') !== false) {
return new SyntaxErrorException($message, $exception);
}
if (strpos($exception->getMessage(), 'attempt to write a readonly database') !== false) {
return new ReadOnlyException($message, $exception);
}
if (strpos($exception->getMessage(), 'unable to open database file') !== false) {
return new ConnectionException($message, $exception);
}
if (strpos($exception->getMessage(), 'FOREIGN KEY constraint failed') !== false) {
return new ForeignKeyConstraintViolationException($message, $exception);
}
return new DriverException($message, $exception);
}
}
......@@ -4,7 +4,8 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Driver\API\DefaultExceptionConverter;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Platforms\DB2Platform;
use Doctrine\DBAL\Schema\DB2SchemaManager;
......@@ -29,13 +30,8 @@ abstract class AbstractDB2Driver implements Driver
return new DB2SchemaManager($conn);
}
/**
* @param string $message
*
* @return DriverException
*/
public function convertException($message, Exception $exception)
public function getExceptionConverter(): ExceptionConverter
{
return new DriverException($message, $exception);
return new DefaultExceptionConverter();
}
}
......@@ -4,19 +4,8 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception\ConnectionLost;
use Doctrine\DBAL\Exception\DeadlockException;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\InvalidFieldNameException;
use Doctrine\DBAL\Exception\LockWaitTimeoutException;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Driver\API\MySQL;
use Doctrine\DBAL\Platforms\MariaDb1027Platform;
use Doctrine\DBAL\Platforms\MySQL57Platform;
use Doctrine\DBAL\Platforms\MySQL80Platform;
......@@ -33,96 +22,6 @@ use function version_compare;
*/
abstract class AbstractMySQLDriver implements VersionAwarePlatformDriver
{
/**
* {@inheritdoc}
*
* @link https://dev.mysql.com/doc/refman/8.0/en/client-error-reference.html
* @link https://dev.mysql.com/doc/refman/8.0/en/server-error-reference.html
*/
public function convertException($message, Exception $exception)
{
switch ($exception->getCode()) {
case 1213:
return new DeadlockException($message, $exception);
case 1205:
return new LockWaitTimeoutException($message, $exception);
case 1050:
return new TableExistsException($message, $exception);
case 1051:
case 1146:
return new TableNotFoundException($message, $exception);
case 1216:
case 1217:
case 1451:
case 1452:
case 1701:
return new ForeignKeyConstraintViolationException($message, $exception);
case 1062:
case 1557:
case 1569:
case 1586:
return new UniqueConstraintViolationException($message, $exception);
case 1054:
case 1166:
case 1611:
return new InvalidFieldNameException($message, $exception);
case 1052:
case 1060:
case 1110:
return new NonUniqueFieldNameException($message, $exception);
case 1064:
case 1149:
case 1287:
case 1341:
case 1342:
case 1343:
case 1344:
case 1382:
case 1479:
case 1541:
case 1554:
case 1626:
return new SyntaxErrorException($message, $exception);
case 1044:
case 1045:
case 1046:
case 1049:
case 1095:
case 1142:
case 1143:
case 1227:
case 1370:
case 1429:
case 2002:
case 2005:
return new ConnectionException($message, $exception);
case 2006:
return new ConnectionLost($message, $exception);
case 1048:
case 1121:
case 1138:
case 1171:
case 1252:
case 1263:
case 1364:
case 1566:
return new NotNullConstraintViolationException($message, $exception);
}
return new DriverException($message, $exception);
}
/**
* {@inheritdoc}
*
......@@ -228,4 +127,9 @@ abstract class AbstractMySQLDriver implements VersionAwarePlatformDriver
{
return new MySqlSchemaManager($conn);
}
public function getExceptionConverter(): ExceptionConverter
{
return new MySQL\ExceptionConverter();
}
}
......@@ -5,16 +5,8 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\AbstractOracleDriver\EasyConnectString;
use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\InvalidFieldNameException;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Driver\API\OCI;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Schema\OracleSchemaManager;
......@@ -23,49 +15,6 @@ use Doctrine\DBAL\Schema\OracleSchemaManager;
*/
abstract class AbstractOracleDriver implements Driver
{
/**
* {@inheritdoc}
*/
public function convertException($message, Exception $exception)
{
switch ($exception->getCode()) {
case 1:
case 2299:
case 38911:
return new UniqueConstraintViolationException($message, $exception);
case 904:
return new InvalidFieldNameException($message, $exception);
case 918:
case 960:
return new NonUniqueFieldNameException($message, $exception);
case 923:
return new SyntaxErrorException($message, $exception);
case 942:
return new TableNotFoundException($message, $exception);
case 955:
return new TableExistsException($message, $exception);
case 1017:
case 12545:
return new ConnectionException($message, $exception);
case 1400:
return new NotNullConstraintViolationException($message, $exception);
case 2266:
case 2291:
case 2292:
return new ForeignKeyConstraintViolationException($message, $exception);
}
return new DriverException($message, $exception);
}
/**
* {@inheritdoc}
*/
......@@ -82,6 +31,11 @@ abstract class AbstractOracleDriver implements Driver
return new OracleSchemaManager($conn);
}
public function getExceptionConverter(): ExceptionConverter
{
return new OCI\ExceptionConverter();
}
/**
* Returns an appropriate Easy Connect String for the given parameters.
*
......
......@@ -4,24 +4,14 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception\DeadlockException;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\InvalidFieldNameException;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Driver\API\PostgreSQL;
use Doctrine\DBAL\Platforms\PostgreSQL100Platform;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use Doctrine\DBAL\Schema\PostgreSqlSchemaManager;
use Doctrine\DBAL\VersionAwarePlatformDriver;
use function preg_match;
use function strpos;
use function version_compare;
/**
......@@ -29,62 +19,6 @@ use function version_compare;
*/
abstract class AbstractPostgreSQLDriver implements VersionAwarePlatformDriver
{
/**
* {@inheritdoc}
*
* @link http://www.postgresql.org/docs/9.4/static/errcodes-appendix.html
*/
public function convertException($message, Exception $exception)
{
switch ($exception->getSQLState()) {
case '40001':
case '40P01':
return new DeadlockException($message, $exception);
case '0A000':
// Foreign key constraint violations during a TRUNCATE operation
// are considered "feature not supported" in PostgreSQL.
if (strpos($exception->getMessage(), 'truncate') !== false) {
return new ForeignKeyConstraintViolationException($message, $exception);
}
break;
case '23502':
return new NotNullConstraintViolationException($message, $exception);
case '23503':
return new ForeignKeyConstraintViolationException($message, $exception);
case '23505':
return new UniqueConstraintViolationException($message, $exception);
case '42601':
return new SyntaxErrorException($message, $exception);
case '42702':
return new NonUniqueFieldNameException($message, $exception);
case '42703':
return new InvalidFieldNameException($message, $exception);
case '42P01':
return new TableNotFoundException($message, $exception);
case '42P07':
return new TableExistsException($message, $exception);
}
// In some case (mainly connection errors) the PDO exception does not provide a SQLSTATE via its code.
// The exception code is always set to 7 here.
// We have to match against the SQLSTATE in the error message in these cases.
if ($exception->getCode() === 7 && strpos($exception->getMessage(), 'SQLSTATE[08006]') !== false) {
return new ConnectionException($message, $exception);
}
return new DriverException($message, $exception);
}
/**
* {@inheritdoc}
*/
......@@ -124,4 +58,9 @@ abstract class AbstractPostgreSQLDriver implements VersionAwarePlatformDriver
{
return new PostgreSqlSchemaManager($conn);
}
public function getExceptionConverter(): ExceptionConverter
{
return new PostgreSQL\ExceptionConverter();
}
}
......@@ -4,7 +4,8 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Driver\API\DefaultExceptionConverter;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Platforms\SQLServer2012Platform;
use Doctrine\DBAL\Schema\SQLServerSchemaManager;
......@@ -29,13 +30,8 @@ abstract class AbstractSQLServerDriver implements Driver
return new SQLServerSchemaManager($conn);
}
/**
* @param string $message
*
* @return DriverException
*/
public function convertException($message, Exception $exception)
public function getExceptionConverter(): ExceptionConverter
{
return new DriverException($message, $exception);
return new DefaultExceptionConverter();
}
}
......@@ -4,90 +4,16 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Exception\ConnectionException;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Exception\InvalidFieldNameException;
use Doctrine\DBAL\Exception\LockWaitTimeoutException;
use Doctrine\DBAL\Exception\NonUniqueFieldNameException;
use Doctrine\DBAL\Exception\NotNullConstraintViolationException;
use Doctrine\DBAL\Exception\ReadOnlyException;
use Doctrine\DBAL\Exception\SyntaxErrorException;
use Doctrine\DBAL\Exception\TableExistsException;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Driver\API\SQLite;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\SqliteSchemaManager;
use function strpos;
/**
* Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for SQLite based drivers.
*/
abstract class AbstractSQLiteDriver implements Driver
{
/**
* {@inheritdoc}
*
* @link http://www.sqlite.org/c3ref/c_abort.html
*/
public function convertException($message, Exception $exception)
{
if (strpos($exception->getMessage(), 'database is locked') !== false) {
return new LockWaitTimeoutException($message, $exception);
}
if (
strpos($exception->getMessage(), 'must be unique') !== false ||
strpos($exception->getMessage(), 'is not unique') !== false ||
strpos($exception->getMessage(), 'are not unique') !== false ||
strpos($exception->getMessage(), 'UNIQUE constraint failed') !== false
) {
return new UniqueConstraintViolationException($message, $exception);
}
if (
strpos($exception->getMessage(), 'may not be NULL') !== false ||
strpos($exception->getMessage(), 'NOT NULL constraint failed') !== false
) {
return new NotNullConstraintViolationException($message, $exception);
}
if (strpos($exception->getMessage(), 'no such table:') !== false) {
return new TableNotFoundException($message, $exception);
}
if (strpos($exception->getMessage(), 'already exists') !== false) {
return new TableExistsException($message, $exception);
}
if (strpos($exception->getMessage(), 'has no column named') !== false) {
return new InvalidFieldNameException($message, $exception);
}
if (strpos($exception->getMessage(), 'ambiguous column name') !== false) {
return new NonUniqueFieldNameException($message, $exception);
}
if (strpos($exception->getMessage(), 'syntax error') !== false) {
return new SyntaxErrorException($message, $exception);
}
if (strpos($exception->getMessage(), 'attempt to write a readonly database') !== false) {
return new ReadOnlyException($message, $exception);
}
if (strpos($exception->getMessage(), 'unable to open database file') !== false) {
return new ConnectionException($message, $exception);
}
if (strpos($exception->getMessage(), 'FOREIGN KEY constraint failed') !== false) {
return new ForeignKeyConstraintViolationException($message, $exception);
}
return new DriverException($message, $exception);
}
/**
* {@inheritdoc}
*/
......@@ -103,4 +29,9 @@ abstract class AbstractSQLiteDriver implements Driver
{
return new SqliteSchemaManager($conn);
}
public function getExceptionConverter(): ExceptionConverter
{
return new SQLite\ExceptionConverter();
}
}
......@@ -93,7 +93,7 @@ abstract class AbstractDriverTest extends TestCase
);
$dbalMessage = 'DBAL exception message';
$dbalException = $this->driver->convertException($dbalMessage, $driverException);
$dbalException = $this->driver->getExceptionConverter()->convert($dbalMessage, $driverException);
self::assertInstanceOf($expectedClass, $dbalException);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment