Reworking driver exceptions

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