Reworking driver exceptions

parent 2ac43e20
# Upgrade to 3.0
## BC BREAK Changes in driver exceptions
1. The `Doctrine\DBAL\Driver\DriverException::getErrorCode()` method is removed. In order to obtain the driver error code, please use `::getCode()`.
2. `Doctrine\DBAL\Driver\PDOException` no longer extends `PDOException`.
3. The value returned by `Doctrine\DBAL\Driver\PDOException::getSQLState()` no longer falls back to the driver error code.
The method was used internally and is no longer needed.
## BC BREAK `DB2SchemaManager::_getPortableForeignKeyRuleDef()` removed
The method was used internally and is no longer needed.
......
......@@ -5,19 +5,13 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver;
use Exception;
use Throwable;
/**
* Abstract base implementation of the {@link DriverException} interface.
*/
abstract class AbstractDriverException extends Exception implements DriverException
{
/**
* The driver specific error code.
*
* @var int|string|null
*/
private $errorCode;
/**
* The SQLSTATE of the driver.
*
......@@ -28,28 +22,20 @@ abstract class AbstractDriverException extends Exception implements DriverExcept
/**
* @param string $message The driver error message.
* @param string|null $sqlState The SQLSTATE the driver is in at the time the error occurred, if any.
* @param int|string|null $errorCode The driver specific error code if any.
* @param int $code The driver specific error code if any.
* @param Throwable|null $previous The previous throwable used for the exception chaining.
*/
public function __construct($message, $sqlState = null, $errorCode = null)
public function __construct(string $message, ?string $sqlState = null, int $code = 0, ?Throwable $previous = null)
{
parent::__construct($message);
parent::__construct($message, $code, $previous);
$this->errorCode = $errorCode;
$this->sqlState = $sqlState;
}
/**
* {@inheritdoc}
*/
public function getErrorCode()
{
return $this->errorCode;
}
/**
* {@inheritdoc}
*/
public function getSQLState()
public function getSQLState() : ?string
{
return $this->sqlState;
}
......
......@@ -31,77 +31,77 @@ abstract class AbstractMySQLDriver implements Driver, ExceptionConverterDriver,
*/
public function convertException($message, DriverException $exception)
{
switch ($exception->getErrorCode()) {
case '1213':
switch ($exception->getCode()) {
case 1213:
return new Exception\DeadlockException($message, $exception);
case '1205':
case 1205:
return new Exception\LockWaitTimeoutException($message, $exception);
case '1050':
case 1050:
return new Exception\TableExistsException($message, $exception);
case '1051':
case '1146':
case 1051:
case 1146:
return new Exception\TableNotFoundException($message, $exception);
case '1216':
case '1217':
case '1451':
case '1452':
case '1701':
case 1216:
case 1217:
case 1451:
case 1452:
case 1701:
return new Exception\ForeignKeyConstraintViolationException($message, $exception);
case '1062':
case '1557':
case '1569':
case '1586':
case 1062:
case 1557:
case 1569:
case 1586:
return new Exception\UniqueConstraintViolationException($message, $exception);
case '1054':
case '1166':
case '1611':
case 1054:
case 1166:
case 1611:
return new Exception\InvalidFieldNameException($message, $exception);
case '1052':
case '1060':
case '1110':
case 1052:
case 1060:
case 1110:
return new Exception\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':
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 Exception\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':
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 Exception\ConnectionException($message, $exception);
case '1048':
case '1121':
case '1138':
case '1171':
case '1252':
case '1263':
case '1364':
case '1566':
case 1048:
case 1121:
case 1138:
case 1171:
case 1252:
case 1263:
case 1364:
case 1566:
return new Exception\NotNullConstraintViolationException($message, $exception);
}
......
......@@ -21,38 +21,38 @@ abstract class AbstractOracleDriver implements Driver, ExceptionConverterDriver
*/
public function convertException($message, DriverException $exception)
{
switch ($exception->getErrorCode()) {
case '1':
case '2299':
case '38911':
switch ($exception->getCode()) {
case 1:
case 2299:
case 38911:
return new Exception\UniqueConstraintViolationException($message, $exception);
case '904':
case 904:
return new Exception\InvalidFieldNameException($message, $exception);
case '918':
case '960':
case 918:
case 960:
return new Exception\NonUniqueFieldNameException($message, $exception);
case '923':
case 923:
return new Exception\SyntaxErrorException($message, $exception);
case '942':
case 942:
return new Exception\TableNotFoundException($message, $exception);
case '955':
case 955:
return new Exception\TableExistsException($message, $exception);
case '1017':
case '12545':
case 1017:
case 12545:
return new Exception\ConnectionException($message, $exception);
case '1400':
case 1400:
return new Exception\NotNullConstraintViolationException($message, $exception);
case '2266':
case '2291':
case '2292':
case 2266:
case 2291:
case 2292:
return new Exception\ForeignKeyConstraintViolationException($message, $exception);
}
......
......@@ -64,18 +64,15 @@ abstract class AbstractPostgreSQLDriver implements Driver, ExceptionConverterDri
case '42P07':
return new Exception\TableExistsException($message, $exception);
}
case '7':
// 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 (strpos($exception->getMessage(), 'SQLSTATE[08006]') !== false) {
if ($exception->getCode() === 7 && strpos($exception->getMessage(), 'SQLSTATE[08006]') !== false) {
return new Exception\ConnectionException($message, $exception);
}
break;
}
return new Exception\DriverException($message, $exception);
}
......
......@@ -25,38 +25,38 @@ abstract class AbstractSQLAnywhereDriver implements Driver, ExceptionConverterDr
*/
public function convertException($message, DriverException $exception)
{
switch ($exception->getErrorCode()) {
case '-306':
case '-307':
case '-684':
switch ($exception->getCode()) {
case -306:
case -307:
case -684:
return new Exception\DeadlockException($message, $exception);
case '-210':
case '-1175':
case '-1281':
case -210:
case -1175:
case -1281:
return new Exception\LockWaitTimeoutException($message, $exception);
case '-100':
case '-103':
case '-832':
case -100:
case -103:
case -832:
return new Exception\ConnectionException($message, $exception);
case '-143':
case -143:
return new Exception\InvalidFieldNameException($message, $exception);
case '-193':
case '-196':
case -193:
case -196:
return new Exception\UniqueConstraintViolationException($message, $exception);
case '-194':
case '-198':
case -194:
case -198:
return new Exception\ForeignKeyConstraintViolationException($message, $exception);
case '-144':
case -144:
return new Exception\NonUniqueFieldNameException($message, $exception);
case '-184':
case '-195':
case -184:
case -195:
return new Exception\NotNullConstraintViolationException($message, $exception);
case '-131':
case -131:
return new Exception\SyntaxErrorException($message, $exception);
case '-110':
case -110:
return new Exception\TableExistsException($message, $exception);
case '-141':
case '-1041':
case -141:
case -1041:
return new Exception\TableNotFoundException($message, $exception);
}
......
......@@ -14,29 +14,10 @@ use Throwable;
*/
interface DriverException extends Throwable
{
/**
* Returns the driver specific error code if available.
*
* Returns null if no driver specific error code is available
* for the error raised by the driver.
*
* @return int|string|null
*/
public function getErrorCode();
/**
* Returns the driver error message.
*
* @return string
*/
public function getMessage();
/**
* Returns the SQLSTATE the driver was in at the time the error occurred.
*
* Returns null if the driver does not provide a SQLSTATE for the error occurred.
*
* @return string|null
*/
public function getSQLState();
public function getSQLState() : ?string;
}
......@@ -24,7 +24,6 @@ use function db2_pconnect;
use function db2_prepare;
use function db2_rollback;
use function db2_server_info;
use function db2_stmt_errormsg;
class DB2Connection implements Connection, ServerInfoAwareConnection
{
......@@ -50,7 +49,7 @@ class DB2Connection implements Connection, ServerInfoAwareConnection
}
if ($conn === false) {
throw new DB2Exception(db2_conn_errormsg());
throw DB2Exception::fromConnectionError();
}
$this->conn = $conn;
......@@ -82,7 +81,7 @@ class DB2Connection implements Connection, ServerInfoAwareConnection
{
$stmt = @db2_prepare($this->conn, $sql);
if (! $stmt) {
throw new DB2Exception(db2_stmt_errormsg());
throw DB2Exception::fromStatementError();
}
return new DB2Statement($stmt);
......@@ -115,7 +114,7 @@ class DB2Connection implements Connection, ServerInfoAwareConnection
$stmt = @db2_exec($this->conn, $statement);
if ($stmt === false) {
throw new DB2Exception(db2_stmt_errormsg());
throw DB2Exception::fromStatementError();
}
return db2_num_rows($stmt);
......@@ -135,7 +134,7 @@ class DB2Connection implements Connection, ServerInfoAwareConnection
public function beginTransaction() : void
{
if (! db2_autocommit($this->conn, DB2_AUTOCOMMIT_OFF)) {
throw new DB2Exception(db2_conn_errormsg($this->conn));
throw DB2Exception::fromConnectionError($this->conn);
}
}
......@@ -145,11 +144,11 @@ class DB2Connection implements Connection, ServerInfoAwareConnection
public function commit() : void
{
if (! db2_commit($this->conn)) {
throw new DB2Exception(db2_conn_errormsg($this->conn));
throw DB2Exception::fromConnectionError($this->conn);
}
if (! db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON)) {
throw new DB2Exception(db2_conn_errormsg($this->conn));
throw DB2Exception::fromConnectionError($this->conn);
}
}
......@@ -159,11 +158,11 @@ class DB2Connection implements Connection, ServerInfoAwareConnection
public function rollBack() : void
{
if (! db2_rollback($this->conn)) {
throw new DB2Exception(db2_conn_errormsg($this->conn));
throw DB2Exception::fromConnectionError($this->conn);
}
if (! db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON)) {
throw new DB2Exception(db2_conn_errormsg($this->conn));
throw DB2Exception::fromConnectionError($this->conn);
}
}
......
......@@ -5,7 +5,34 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\AbstractDriverException;
use function db2_conn_error;
use function db2_conn_errormsg;
use function db2_stmt_error;
use function db2_stmt_errormsg;
class DB2Exception extends AbstractDriverException
{
/**
* @param resource|null $connection
*/
public static function fromConnectionError($connection = null) : self
{
if ($connection !== null) {
return new self(db2_conn_errormsg($connection), db2_conn_error($connection));
}
return new self(db2_conn_errormsg(), db2_conn_error());
}
/**
* @param resource|null $statement
*/
public static function fromStatementError($statement = null) : self
{
if ($statement !== null) {
return new self(db2_stmt_errormsg($statement), db2_stmt_error($statement));
}
return new self(db2_stmt_errormsg(), db2_stmt_error());
}
}
......@@ -137,7 +137,7 @@ class DB2Statement implements IteratorAggregate, Statement
$this->bindParam[$position] =& $variable;
if (! db2_bind_param($this->stmt, $position, 'variable', $parameterType, $dataType)) {
throw new DB2Exception(db2_stmt_errormsg());
throw DB2Exception::fromStatementError($this->stmt);
}
}
......@@ -218,7 +218,7 @@ class DB2Statement implements IteratorAggregate, Statement
$this->lobs = [];
if ($retval === false) {
throw new DB2Exception(db2_stmt_errormsg());
throw DB2Exception::fromStatementError($this->stmt);
}
$this->result = true;
......
......@@ -20,8 +20,6 @@ use function defined;
use function floor;
use function in_array;
use function ini_get;
use function mysqli_errno;
use function mysqli_error;
use function mysqli_init;
use function mysqli_options;
use function restore_error_handler;
......@@ -70,7 +68,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
});
try {
if (! $this->conn->real_connect($params['host'], $username, $password, $dbname, $port, $socket, $flags)) {
throw new MysqliException($this->conn->connect_error, $this->conn->sqlstate ?? 'HY000', $this->conn->connect_errno);
throw MysqliException::fromConnectionError($this->conn);
}
} finally {
restore_error_handler();
......@@ -158,7 +156,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
public function exec(string $statement) : int
{
if ($this->conn->query($statement) === false) {
throw new MysqliException($this->conn->error, $this->conn->sqlstate, $this->conn->errno);
throw MysqliException::fromConnectionError($this->conn);
}
return $this->conn->affected_rows;
......@@ -186,7 +184,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
public function commit() : void
{
if (! $this->conn->commit()) {
throw new MysqliException($this->conn->error, $this->conn->sqlstate, $this->conn->errno);
throw MysqliException::fromConnectionError($this->conn);
}
}
......@@ -196,7 +194,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
public function rollBack() : void
{
if (! $this->conn->rollback()) {
throw new MysqliException($this->conn->error, $this->conn->sqlstate, $this->conn->errno);
throw MysqliException::fromConnectionError($this->conn);
}
}
......@@ -255,14 +253,7 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
continue;
}
$msg = sprintf($exceptionMsg, 'Failed to set', $option, $value);
$msg .= sprintf(', error: %s (%d)', mysqli_error($this->conn), mysqli_errno($this->conn));
throw new MysqliException(
$msg,
$this->conn->sqlstate,
$this->conn->errno
);
throw MysqliException::fromConnectionError($this->conn);
}
}
......
......@@ -5,10 +5,21 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\AbstractDriverException;
use mysqli;
use mysqli_stmt;
/**
* Exception thrown in case the mysqli driver errors.
*/
class MysqliException extends AbstractDriverException
{
public static function fromConnectionError(mysqli $connection) : self
{
return new self($connection->error, $connection->sqlstate ?: null, $connection->errno);
}
public static function fromStatementError(mysqli_stmt $statement) : self
{
return new self($statement->error, $statement->sqlstate ?: null, $statement->errno);
}
}
......@@ -87,7 +87,7 @@ class MysqliStatement implements IteratorAggregate, Statement
$stmt = $conn->prepare($prepareString);
if ($stmt === false) {
throw new MysqliException($this->_conn->error, $this->_conn->sqlstate, $this->_conn->errno);
throw MysqliException::fromConnectionError($this->_conn);
}
$this->_stmt = $stmt;
......@@ -139,14 +139,14 @@ class MysqliStatement implements IteratorAggregate, Statement
{
if ($params !== null && count($params) > 0) {
if (! $this->bindUntypedValues($params)) {
throw new MysqliException($this->_stmt->error, $this->_stmt->errno);
throw MysqliException::fromStatementError($this->_stmt);
}
} else {
$this->bindTypedParameters();
}
if (! $this->_stmt->execute()) {
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
throw MysqliException::fromStatementError($this->_stmt);
}
if ($this->_columnNames === null) {
......@@ -193,7 +193,7 @@ class MysqliStatement implements IteratorAggregate, Statement
}
if (! $this->_stmt->bind_result(...$refs)) {
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
throw MysqliException::fromStatementError($this->_stmt);
}
}
......@@ -232,7 +232,7 @@ class MysqliStatement implements IteratorAggregate, Statement
}
if (count($values) > 0 && ! $this->_stmt->bind_param($types, ...$values)) {
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
throw MysqliException::fromStatementError($this->_stmt);
}
$this->sendLongData($streams);
......@@ -254,7 +254,7 @@ class MysqliStatement implements IteratorAggregate, Statement
}
if (! $this->_stmt->send_long_data($paramNr - 1, $chunk)) {
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
throw MysqliException::fromStatementError($this->_stmt);
}
}
}
......@@ -322,7 +322,7 @@ class MysqliStatement implements IteratorAggregate, Statement
}
if ($values === false) {
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
throw MysqliException::fromStatementError($this->_stmt);
}
if ($fetchMode === FetchMode::NUMERIC) {
......
......@@ -10,10 +10,8 @@ class OCI8Exception extends AbstractDriverException
{
/**
* @param mixed[]|false $error
*
* @return \Doctrine\DBAL\Driver\OCI8\OCI8Exception
*/
public static function fromErrorInfo($error)
public static function fromErrorInfo($error) : self
{
if ($error === false) {
return new self('Database error occurred but no error information was retrieved from the driver.');
......
......@@ -7,48 +7,20 @@ namespace Doctrine\DBAL\Driver;
/**
* Tiny wrapper for PDOException instances to implement the {@link DriverException} interface.
*/
class PDOException extends \PDOException implements DriverException
class PDOException extends AbstractDriverException
{
/**
* The driver specific error code.
*
* @var int|string|null
*/
private $errorCode;
/**
* The SQLSTATE of the driver.
*
* @var string|null
*/
private $sqlState;
/**
* @param \PDOException $exception The PDO exception to wrap.
*/
public function __construct(\PDOException $exception)
{
parent::__construct($exception->getMessage(), 0, $exception);
$this->code = $exception->getCode();
$this->errorInfo = $exception->errorInfo;
$this->errorCode = $exception->errorInfo[1] ?? $exception->getCode();
$this->sqlState = $exception->errorInfo[0] ?? $exception->getCode();
if ($exception->errorInfo !== null) {
[$sqlState, $code] = $exception->errorInfo;
} else {
$code = $exception->getCode();
$sqlState = null;
}
/**
* {@inheritdoc}
*/
public function getErrorCode()
{
return $this->errorCode;
}
/**
* {@inheritdoc}
*/
public function getSQLState()
{
return $this->sqlState;
parent::__construct($exception->getMessage(), $sqlState, $code, $exception);
}
}
......@@ -7,7 +7,7 @@ namespace Doctrine\DBAL\Driver\PDOMySql;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
use Doctrine\DBAL\Driver\PDOConnection;
use PDOException;
use Doctrine\DBAL\Driver\PDOException;
/**
* PDO MySql driver.
......
......@@ -7,7 +7,7 @@ namespace Doctrine\DBAL\Driver\PDOOracle;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\AbstractOracleDriver;
use Doctrine\DBAL\Driver\PDOConnection;
use PDOException;
use Doctrine\DBAL\Driver\PDOException;
/**
* PDO Oracle driver.
......
......@@ -7,8 +7,8 @@ namespace Doctrine\DBAL\Driver\PDOPgSql;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\AbstractPostgreSQLDriver;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDOException;
use PDO;
use PDOException;
use function defined;
/**
......
......@@ -7,8 +7,8 @@ namespace Doctrine\DBAL\Driver\PDOSqlite;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\AbstractSQLiteDriver;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDOException;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use PDOException;
use function array_merge;
/**
......
......@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\AbstractDriverException;
use InvalidArgumentException;
use function sasql_error;
use function sasql_errorcode;
use function sasql_sqlstate;
......@@ -22,12 +21,8 @@ class SQLAnywhereException extends AbstractDriverException
*
* @param resource|null $conn The SQL Anywhere connection resource to retrieve the last error from.
* @param resource|null $stmt The SQL Anywhere statement resource to retrieve the last error from.
*
* @return SQLAnywhereException
*
* @throws InvalidArgumentException
*/
public static function fromSQLAnywhereError($conn = null, $stmt = null)
public static function fromSQLAnywhereError($conn = null, $stmt = null) : self
{
$state = $conn ? sasql_sqlstate($conn) : sasql_sqlstate();
$code = null;
......
......@@ -13,14 +13,12 @@ class SQLSrvException extends AbstractDriverException
{
/**
* Helper method to turn sql server errors into exception.
*
* @return \Doctrine\DBAL\Driver\SQLSrv\SQLSrvException
*/
public static function fromSqlSrvErrors()
public static function fromSqlSrvErrors() : self
{
$message = '';
$sqlState = null;
$errorCode = null;
$code = null;
foreach ((array) sqlsrv_errors(SQLSRV_ERR_ERRORS) as $error) {
$message .= 'SQLSTATE [' . $error['SQLSTATE'] . ', ' . $error['code'] . ']: ' . $error['message'] . "\n";
......@@ -29,17 +27,17 @@ class SQLSrvException extends AbstractDriverException
$sqlState = $error['SQLSTATE'];
}
if ($errorCode !== null) {
if ($code !== null) {
continue;
}
$errorCode = $error['code'];
$code = $error['code'];
}
if (! $message) {
$message = 'SQL Server error occurred but no error message was retrieved from driver.';
}
return new self(rtrim($message), $sqlState, $errorCode);
return new self(rtrim($message), $sqlState, $code);
}
}
......@@ -5,58 +5,31 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Exception;
use Doctrine\DBAL\DBALException;
use Exception;
use Doctrine\DBAL\Driver\DriverException as DriverExceptionInterface;
use function assert;
/**
* Base class for all errors detected in the driver.
*/
class DriverException extends DBALException
class DriverException extends DBALException implements DriverExceptionInterface
{
/**
* The previous DBAL driver exception.
*
* @var \Doctrine\DBAL\Driver\DriverException
*/
private $driverException;
/**
* @param string $message The exception message.
* @param \Doctrine\DBAL\Driver\DriverException $driverException The DBAL driver exception to chain.
* @param DriverExceptionInterface $driverException The DBAL driver exception to chain.
*/
public function __construct($message, \Doctrine\DBAL\Driver\DriverException $driverException)
public function __construct(string $message, DriverExceptionInterface $driverException)
{
$exception = null;
if ($driverException instanceof Exception) {
$exception = $driverException;
}
parent::__construct($message, 0, $exception);
$this->driverException = $driverException;
parent::__construct($message, $driverException->getCode(), $driverException);
}
/**
* Returns the driver specific error code if given.
*
* Returns null if no error code was given by the driver.
*
* @return int|string|null
* {@inheritDoc}
*/
public function getErrorCode()
public function getSQLState() : ?string
{
return $this->driverException->getErrorCode();
}
$previous = $this->getPrevious();
assert($previous instanceof DriverExceptionInterface);
/**
* Returns the SQLSTATE the driver was in at the time the error occurred, if given.
*
* Returns null if no SQLSTATE was given by the driver.
*
* @return string|null
*/
public function getSQLState()
{
return $this->driverException->getSQLState();
return $previous->getSQLState();
}
}
......@@ -45,7 +45,7 @@ class OracleSchemaManager extends AbstractSchemaManager
// because of active connections on the database.
// To force dropping the database, we first have to close all active connections
// on that database and issue the drop database operation again.
if ($exception->getErrorCode() !== 1940) {
if ($exception->getCode() !== 1940) {
throw $exception;
}
......
......@@ -44,7 +44,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager
// because of active connections on the database.
// To force dropping the database, we first have to close all active connections
// on that database and issue the drop database operation again.
if ($exception->getErrorCode() !== 3702) {
if ($exception->getCode() !== 3702) {
throw $exception;
}
......
......@@ -71,11 +71,9 @@ abstract class AbstractDriverTest extends DbalTestCase
}
/**
* @param int|string $errorCode
*
* @dataProvider exceptionConversionProvider
*/
public function testConvertsException($errorCode, ?string $sqlState, ?string $message, string $expectedClass) : void
public function testConvertsException(string $expectedClass, int $errorCode, ?string $sqlState = null, string $message = '') : void
{
if (! $this->driver instanceof ExceptionConverterDriver) {
$this->markTestSkipped('This test is only intended for exception converter drivers.');
......@@ -83,10 +81,8 @@ abstract class AbstractDriverTest extends DbalTestCase
/** @var DriverExceptionInterface|MockObject $driverException */
$driverException = $this->getMockBuilder(DriverExceptionInterface::class)
->setConstructorArgs([$message])
->setConstructorArgs([$message, $errorCode])
->getMock();
$driverException->method('getErrorCode')
->willReturn($errorCode);
$driverException->method('getSQLState')
->willReturn($sqlState);
......@@ -95,7 +91,7 @@ abstract class AbstractDriverTest extends DbalTestCase
self::assertInstanceOf($expectedClass, $dbalException);
self::assertSame($driverException->getErrorCode(), $dbalException->getErrorCode());
self::assertSame($driverException->getCode(), $dbalException->getCode());
self::assertSame($driverException->getSQLState(), $dbalException->getSQLState());
self::assertSame($driverException, $dbalException->getPrevious());
self::assertSame($dbalMessage, $dbalException->getMessage());
......@@ -224,11 +220,11 @@ abstract class AbstractDriverTest extends DbalTestCase
{
foreach (static::getExceptionConversionData() as $expectedClass => $items) {
foreach ($items as $item) {
yield array_merge($item, [$expectedClass]);
yield array_merge([$expectedClass], $item);
}
}
yield ['foo', 'bar', 'baz', self::EXCEPTION_DRIVER];
yield [self::EXCEPTION_DRIVER, 1, 'HY000', 'The message'];
}
/**
......
......@@ -95,76 +95,76 @@ class AbstractMySQLDriverTest extends AbstractDriverTest
{
return [
self::EXCEPTION_CONNECTION => [
['1044', null, null],
['1045', null, null],
['1046', null, null],
['1049', null, null],
['1095', null, null],
['1142', null, null],
['1143', null, null],
['1227', null, null],
['1370', null, null],
['2002', null, null],
['2005', null, null],
[1044],
[1045],
[1046],
[1049],
[1095],
[1142],
[1143],
[1227],
[1370],
[2002],
[2005],
],
self::EXCEPTION_FOREIGN_KEY_CONSTRAINT_VIOLATION => [
['1216', null, null],
['1217', null, null],
['1451', null, null],
['1452', null, null],
[1216],
[1217],
[1451],
[1452],
],
self::EXCEPTION_INVALID_FIELD_NAME => [
['1054', null, null],
['1166', null, null],
['1611', null, null],
[1054],
[1166],
[1611],
],
self::EXCEPTION_NON_UNIQUE_FIELD_NAME => [
['1052', null, null],
['1060', null, null],
['1110', null, null],
[1052],
[1060],
[1110],
],
self::EXCEPTION_NOT_NULL_CONSTRAINT_VIOLATION => [
['1048', null, null],
['1121', null, null],
['1138', null, null],
['1171', null, null],
['1252', null, null],
['1263', null, null],
['1364', null, null],
['1566', null, null],
[1048],
[1121],
[1138],
[1171],
[1252],
[1263],
[1364],
[1566],
],
self::EXCEPTION_SYNTAX_ERROR => [
['1064', null, null],
['1149', null, null],
['1287', null, null],
['1341', null, null],
['1342', null, null],
['1343', null, null],
['1344', null, null],
['1382', null, null],
['1479', null, null],
['1541', null, null],
['1554', null, null],
['1626', null, null],
[1064],
[1149],
[1287],
[1341],
[1342],
[1343],
[1344],
[1382],
[1479],
[1541],
[1554],
[1626],
],
self::EXCEPTION_TABLE_EXISTS => [
['1050', null, null],
[1050],
],
self::EXCEPTION_TABLE_NOT_FOUND => [
['1051', null, null],
['1146', null, null],
[1051],
[1146],
],
self::EXCEPTION_UNIQUE_CONSTRAINT_VIOLATION => [
['1062', null, null],
['1557', null, null],
['1569', null, null],
['1586', null, null],
[1062],
[1557],
[1569],
[1586],
],
self::EXCEPTION_DEADLOCK => [
['1213', null, null],
[1213],
],
self::EXCEPTION_LOCK_WAIT_TIMEOUT => [
['1205', null, null],
[1205],
],
];
}
......
......@@ -72,35 +72,35 @@ class AbstractOracleDriverTest extends AbstractDriverTest
{
return [
self::EXCEPTION_CONNECTION => [
['1017', null, null],
['12545', null, null],
[1017],
[12545],
],
self::EXCEPTION_FOREIGN_KEY_CONSTRAINT_VIOLATION => [
['2292', null, null],
[2292],
],
self::EXCEPTION_INVALID_FIELD_NAME => [
['904', null, null],
[904],
],
self::EXCEPTION_NON_UNIQUE_FIELD_NAME => [
['918', null, null],
['960', null, null],
[918],
[960],
],
self::EXCEPTION_NOT_NULL_CONSTRAINT_VIOLATION => [
['1400', null, null],
[1400],
],
self::EXCEPTION_SYNTAX_ERROR => [
['923', null, null],
[923],
],
self::EXCEPTION_TABLE_EXISTS => [
['955', null, null],
[955],
],
self::EXCEPTION_TABLE_NOT_FOUND => [
['942', null, null],
[942],
],
self::EXCEPTION_UNIQUE_CONSTRAINT_VIOLATION => [
['1', null, null],
['2299', null, null],
['38911', null, null],
[1],
[2299],
[38911],
],
];
}
......
......@@ -84,35 +84,35 @@ class AbstractPostgreSQLDriverTest extends AbstractDriverTest
{
return [
self::EXCEPTION_CONNECTION => [
[null, '7', 'SQLSTATE[08006]'],
[7, null, 'SQLSTATE[08006]'],
],
self::EXCEPTION_FOREIGN_KEY_CONSTRAINT_VIOLATION => [
[null, '23503', null],
[0, '23503'],
],
self::EXCEPTION_INVALID_FIELD_NAME => [
[null, '42703', null],
[0, '42703'],
],
self::EXCEPTION_NON_UNIQUE_FIELD_NAME => [
[null, '42702', null],
[0, '42702'],
],
self::EXCEPTION_NOT_NULL_CONSTRAINT_VIOLATION => [
[null, '23502', null],
[0, '23502'],
],
self::EXCEPTION_SYNTAX_ERROR => [
[null, '42601', null],
[0, '42601'],
],
self::EXCEPTION_TABLE_EXISTS => [
[null, '42P07', null],
[0, '42P07'],
],
self::EXCEPTION_TABLE_NOT_FOUND => [
[null, '42P01', null],
[0, '42P01'],
],
self::EXCEPTION_UNIQUE_CONSTRAINT_VIOLATION => [
[null, '23505', null],
[0, '23505'],
],
self::EXCEPTION_DEADLOCK => [
[null, '40001', null],
[null, '40P01', null],
[0, '40001'],
[0, '40P01'],
],
];
}
......
......@@ -52,46 +52,46 @@ class AbstractSQLAnywhereDriverTest extends AbstractDriverTest
{
return [
self::EXCEPTION_CONNECTION => [
['-100', null, null],
['-103', null, null],
['-832', null, null],
[-100],
[-103],
[-832],
],
self::EXCEPTION_FOREIGN_KEY_CONSTRAINT_VIOLATION => [
['-198', null, null],
[-198],
],
self::EXCEPTION_INVALID_FIELD_NAME => [
['-143', null, null],
[-143],
],
self::EXCEPTION_NON_UNIQUE_FIELD_NAME => [
['-144', null, null],
[-144],
],
self::EXCEPTION_NOT_NULL_CONSTRAINT_VIOLATION => [
['-184', null, null],
['-195', null, null],
[-184],
[-195],
],
self::EXCEPTION_SYNTAX_ERROR => [
['-131', null, null],
[-131],
],
self::EXCEPTION_TABLE_EXISTS => [
['-110', null, null],
[-110],
],
self::EXCEPTION_TABLE_NOT_FOUND => [
['-141', null, null],
['-1041', null, null],
[-141],
[-1041],
],
self::EXCEPTION_UNIQUE_CONSTRAINT_VIOLATION => [
['-193', null, null],
['-196', null, null],
[-193],
[-196],
],
self::EXCEPTION_DEADLOCK => [
['-306', null, null],
['-307', null, null],
['-684', null, null],
[-306],
[-307],
[-684],
],
self::EXCEPTION_LOCK_WAIT_TIMEOUT => [
['-210', null, null],
['-1175', null, null],
['-1281', null, null],
[-210],
[-1175],
[-1281],
],
];
}
......
......@@ -54,36 +54,36 @@ class AbstractSQLiteDriverTest extends AbstractDriverTest
{
return [
self::EXCEPTION_CONNECTION => [
[null, null, 'unable to open database file'],
[0, null, 'unable to open database file'],
],
self::EXCEPTION_INVALID_FIELD_NAME => [
[null, null, 'has no column named'],
[0, null, 'has no column named'],
],
self::EXCEPTION_NON_UNIQUE_FIELD_NAME => [
[null, null, 'ambiguous column name'],
[0, null, 'ambiguous column name'],
],
self::EXCEPTION_NOT_NULL_CONSTRAINT_VIOLATION => [
[null, null, 'may not be NULL'],
[0, null, 'may not be NULL'],
],
self::EXCEPTION_READ_ONLY => [
[null, null, 'attempt to write a readonly database'],
[0, null, 'attempt to write a readonly database'],
],
self::EXCEPTION_SYNTAX_ERROR => [
[null, null, 'syntax error'],
[0, null, 'syntax error'],
],
self::EXCEPTION_TABLE_EXISTS => [
[null, null, 'already exists'],
[0, null, 'already exists'],
],
self::EXCEPTION_TABLE_NOT_FOUND => [
[null, null, 'no such table:'],
[0, null, 'no such table:'],
],
self::EXCEPTION_UNIQUE_CONSTRAINT_VIOLATION => [
[null, null, 'must be unique'],
[null, null, 'is not unique'],
[null, null, 'are not unique'],
[0, null, 'must be unique'],
[0, null, 'is not unique'],
[0, null, 'are not unique'],
],
self::EXCEPTION_LOCK_WAIT_TIMEOUT => [
[null, null, 'database is locked'],
[0, null, 'database is locked'],
],
];
}
......
......@@ -15,7 +15,7 @@ class PDOExceptionTest extends DbalTestCase
public const MESSAGE = 'PDO Exception';
public const SQLSTATE = 28000;
public const SQLSTATE = 'HY000';
/**
* The PDO exception wrapper under test.
......@@ -39,7 +39,7 @@ class PDOExceptionTest extends DbalTestCase
parent::setUp();
$this->wrappedException = new \PDOException(self::MESSAGE, self::SQLSTATE);
$this->wrappedException = new \PDOException(self::MESSAGE);
$this->wrappedException->errorInfo = [self::SQLSTATE, self::ERROR_CODE];
......@@ -48,12 +48,7 @@ class PDOExceptionTest extends DbalTestCase
public function testReturnsCode() : void
{
self::assertSame(self::SQLSTATE, $this->exception->getCode());
}
public function testReturnsErrorCode() : void
{
self::assertSame(self::ERROR_CODE, $this->exception->getErrorCode());
self::assertSame(self::ERROR_CODE, $this->exception->getCode());
}
public function testReturnsMessage() : void
......
......@@ -351,7 +351,7 @@ class WriteTest extends DbalFunctionalTestCase
try {
return $this->connection->lastInsertId($name);
} catch (DriverException $e) {
if ($e->getCode() === 'IM001') {
if ($e->getSQLState() === 'IM001') {
$this->markTestSkipped($e->getMessage());
}
......
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