Unverified Commit 55f9382d authored by Sergei Morozov's avatar Sergei Morozov

Merge branch '2.11.x' into 3.0.x

parents 4509f271 a7c431c0
......@@ -232,6 +232,38 @@ Please use other database client applications for import, e.g.:
# Upgrade to 2.11
## Inconsistently and ambiguously named driver-level classes are deprecated
The following classes under the `Driver` namespace have been deprecated in favor of their consistently named counterparts:
- `DriverException``Exception`
- `AbstractDriverException``AbstractException`
- `IBMDB2\DB2Driver``IBMDB2\Driver`
- `IBMDB2\DB2Connection``IBMDB2\Connection`
- `IBMDB2\DB2Statement``IBMDB2\Statement`
- `Mysqli\MysqliConnection``Mysqli\Connection`
- `Mysqli\MysqliStatement``Mysqli\Statement`
- `OCI8\OCI8Connection``OCI8\Connection`
- `OCI8\OCI8Statement``OCI8\Statement`
- `SQLSrv\SQLSrvConnection``SQLSrv\Connection`
- `SQLSrv\SQLSrvStatement``SQLSrv\Statement`
- `PDOConnection``PDO\Connection`
- `PDOStatement``PDO\Statement`
All driver-specific exception classes have been deprecated:
- `IBMDB2\DB2Exception`
- `Mysqli\MysqliException`
- `OCI8\OCI8Exception`
- `PDOException`
- `SQLSrv\SQLSrvException`
A driver-level exception should be only identified as a subtype of `Driver\Exception`.
Internal driver-level exception implementations may use `Driver\AbstractException` as the base class.
Driver-specific exception handling has to be implemented either in the driver or based on the type of the `Driver` implementation.
The `Driver\AbstractException` class has been marked internal.
## `Connection::getParams()` has been marked internal
Consumers of the Connection class should not rely on connection parameters stored in the connection object. If needed, they should be obtained from a different source, e.g. application configuration.
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ce60bfb3c7214de480c0b859a69fe820",
"content-hash": "f61efbf7b6070380da835ef52ec3b8f0",
"packages": [
{
"name": "composer/package-versions-deprecated",
......@@ -1358,21 +1358,24 @@
},
{
"name": "phpstan/phpstan",
"version": "0.12.18",
"version": "0.12.30",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "1ce27fe29c8660a27926127d350d53d80c4d4286"
"reference": "1f2c16d3fbb5eec6e55fbe2358e32570cefa20e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/1ce27fe29c8660a27926127d350d53d80c4d4286",
"reference": "1ce27fe29c8660a27926127d350d53d80c4d4286",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/1f2c16d3fbb5eec6e55fbe2358e32570cefa20e5",
"reference": "1f2c16d3fbb5eec6e55fbe2358e32570cefa20e5",
"shasum": ""
},
"require": {
"php": "^7.1"
},
"conflict": {
"phpstan/phpstan-shim": "*"
},
"bin": [
"phpstan",
"phpstan.phar"
......@@ -1393,7 +1396,21 @@
"MIT"
],
"description": "PHPStan - PHP Static Analysis Tool",
"time": "2020-03-22T16:51:47+00:00"
"funding": [
{
"url": "https://github.com/ondrejmirtes",
"type": "github"
},
{
"url": "https://www.patreon.com/phpstan",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
"type": "tidelift"
}
],
"time": "2020-06-21T14:08:19+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
......
......@@ -88,6 +88,7 @@
https://github.com/squizlabs/PHP_CodeSniffer/issues/2950
-->
<exclude-pattern>src/Driver/IBMDB2/DB2Connection.php</exclude-pattern>
<exclude-pattern>src/Driver/Mysqli/Exception/ConnectionFailed.php</exclude-pattern>
<exclude-pattern>src/Driver/Mysqli/MysqliConnection.php</exclude-pattern>
<!-- See https://github.com/squizlabs/PHP_CodeSniffer/issues/2837 -->
<exclude-pattern>src/SQLParserUtils.php</exclude-pattern>
......@@ -103,7 +104,7 @@
<!-- See https://github.com/slevomat/coding-standard/issues/1038 -->
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses">
<exclude-pattern>tests/Functional/Driver/IBMDB2/DB2StatementTest.php</exclude-pattern>
<exclude-pattern>tests/Functional/Driver/IBMDB2/StatementTest.php</exclude-pattern>
</rule>
<!-- see https://github.com/doctrine/dbal/issues/3377 -->
......
......@@ -2,7 +2,7 @@ parameters:
level: 7
paths:
- %currentWorkingDirectory%/src
autoload_files:
scanFiles:
- %currentWorkingDirectory%/tests/phpstan-polyfill.php
treatPhpDocTypesAsCertain: false
reportUnmatchedIgnoredErrors: false
......@@ -15,30 +15,26 @@ parameters:
# removing it would be BC break
- '~^Constructor of class Doctrine\\DBAL\\Schema\\Table has an unused parameter \$idGeneratorType\.\z~'
# declaring $tableName in AbstractSchemaManager::_getPortableTableIndexesList() non-optional will be a BC break
- '~^Parameter #2 \$table of class Doctrine\\DBAL\\Event\\SchemaIndexDefinitionEventArgs constructor expects string, string\|null given\.\z~'
# changing these would be a BC break, to be done in next major
- "~^Casting to bool something that's already bool.~"
- "~^Casting to int something that's already int.~"
- '~^Method Doctrine\\DBAL\\Driver\\IBMDB2\\DB2Connection::exec\(\) should return int but returns bool\.\z~'
- '~^Property Doctrine\\DBAL\\Schema\\Table::\$_primaryKeyName \(string\) does not accept (default value of type )?false\.\z~'
- '~^Property Doctrine\\DBAL\\Schema\\Schema::\$_schemaConfig \(Doctrine\\DBAL\\Schema\\SchemaConfig\) does not accept default value of type false\.\z~'
- '~^Method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint::onEvent\(\) should return string\|null but returns false\.\z~'
- '~^Method Doctrine\\DBAL\\Schema\\(Oracle|PostgreSql|SQLServer)SchemaManager::_getPortableTableDefinition\(\) should return array but returns string\.\z~'
- '~^Method Doctrine\\DBAL\\Driver\\OCI8\\OCI8Connection::lastInsertId\(\) should return string but returns (int|false)\.\z~'
- '~^Return type \(int\|false\) of method Doctrine\\DBAL\\Driver\\OCI8\\OCI8Connection\:\:lastInsertId\(\) should be compatible with return type \(string\) of method Doctrine\\DBAL\\Driver\\Connection::lastInsertId\(\)~'
# https://bugs.php.net/bug.php?id=78126
- '~^Call to an undefined method PDO::sqliteCreateFunction\(\)\.\z~'
# https://github.com/phpstan/phpstan/issues/3527
-
message: '~^Call to private method sqliteCreateFunction\(\) of parent class PDO\.$~'
path: %currentWorkingDirectory%/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php
# https://github.com/phpstan/phpstan/issues/1847
- '~^Parameter #2 \$registeredAliases of static method Doctrine\\DBAL\\Query\\QueryException::unknownAlias\(\) expects array<string>, array<int, int\|string> given\.\z~'
# https://github.com/phpstan/phpstan/issues/2857
# TODO: remove in 4.0.0
- '~^Parameter #2 \$registeredAliases of static method Doctrine\\DBAL\\Query\\QueryException::nonUniqueAlias\(\) expects array<string>, array<int, int\|string> given\.\z~'
# PHPStan is too strict about preg_replace(): https://phpstan.org/r/993dc99f-0d43-4b51-868b-d01f982c1463
- '~^Method Doctrine\\DBAL\\Platforms\\AbstractPlatform::escapeStringForLike\(\) should return string but returns string\|null\.\z~'
# legacy variadic-like signature
# TODO: remove in 3.0.0
- '~^Method Doctrine\\DBAL(\\.*)?Connection::query\(\) invoked with \d+ parameters?, 0 required\.\z~'
# some drivers actually do accept 2nd parameter...
......@@ -48,16 +44,10 @@ parameters:
- '~^Class Doctrine\\Common\\(Collections\\Collection|Persistence\\Proxy) not found\.\z~'
- '~^.+ on an unknown class Doctrine\\Common\\(Collections\\Collection|Persistence\\Proxy)\.\z~'
# inheritance variance inference issue
- '~^Method Doctrine\\DBAL\\Driver\\PDOConnection::\w+\(\) should return Doctrine\\DBAL\\Driver\\Statement but returns PDOStatement\.\z~'
# may not exist when pdo_sqlsrv is not loaded but PDO is
- '~^Access to undefined constant PDO::SQLSRV_ENCODING_BINARY\.\z~'
# weird class name, represented in stubs as OCI_(Lob|Collection)
- '~unknown class OCI-(Lob|Collection)~'
# https://github.com/JetBrains/phpstorm-stubs/pull/766
# https://github.com/phpstan/phpstan-src/pull/255
-
message: '~^Strict comparison using === between true and null will always evaluate to false\.$~'
path: %currentWorkingDirectory%/src/Driver/Mysqli/Result.php
......@@ -85,17 +75,61 @@ parameters:
message: '~^Strict comparison using !== between int and false will always evaluate to true\.$~'
path: %currentWorkingDirectory%/src/Driver/PDOConnection.php
# Requires a release of https://github.com/JetBrains/phpstorm-stubs/pull/732
-
message: '~^Access to undefined constant PDO::PGSQL_ATTR_DISABLE_PREPARES\.$~'
path: %currentWorkingDirectory%/src/Driver/PDOPgSql/Driver.php
# False Positive
- '~Strict comparison using === between 1 and 2 will always evaluate to false~'
# Needs Generics
- '~Method Doctrine\\DBAL\\Schema\\SchemaDiff::getNewTablesSortedByDependencies\(\) should return array<Doctrine\\DBAL\\Schema\\Table> but returns array<object>.~'
# This is deprecated code. Fixing the issue may cause a BC break.
# TODO: remove in 3.0.0
-
message: '~^Return type \(Doctrine\\DBAL\\Platforms\\DrizzlePlatform\) of method Doctrine\\DBAL\\Driver\\DrizzlePDOMySql\\Driver::getDatabasePlatform\(\) should be compatible with return type \(Doctrine\\DBAL\\Platforms\\MySqlPlatform\) of method Doctrine\\DBAL\\Driver\\AbstractMySQLDriver::getDatabasePlatform\(\)$~'
paths:
- %currentWorkingDirectory%/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php
# This is deprecated code. Fixing the issue may cause a BC break.
# TODO: remove in 3.0.0
-
message: '~^Return type \(Doctrine\\DBAL\\Schema\\DrizzleSchemaManager\) of method Doctrine\\DBAL\\Driver\\DrizzlePDOMySql\\Driver::getSchemaManager\(\) should be compatible with return type \(Doctrine\\DBAL\\Schema\\MySqlSchemaManager\) of method Doctrine\\DBAL\\Driver\\AbstractMySQLDriver::getSchemaManager\(\)$~'
paths:
- %currentWorkingDirectory%/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php
# This is deprecated code. Fixing the issue may cause a BC break.
# TODO: remove in 3.0.0
-
message: '~^Return type \(int\) of method Doctrine\\DBAL\\Driver\\Mysqli\\MysqliConnection::errorCode\(\) should be compatible with return type \(string\|null\) of method Doctrine\\DBAL\\Driver\\Connection::errorCode\(\)$~'
paths:
- %currentWorkingDirectory%/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php
# This is deprecated code. Fixing the issue may cause a BC break.
# TODO: remove in 3.0.0
-
message: '~^Return type \(string\) of method Doctrine\\DBAL\\Driver\\Mysqli\\MysqliConnection::errorInfo\(\) should be compatible with return type \(array\) of method Doctrine\\DBAL\\Driver\\Connection::errorInfo\(\)$~'
paths:
- %currentWorkingDirectory%/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php
# Fixing the issue may cause a BC break.
# TODO: fix in 3.0.0
-
message: '~^Parameter \#2 \$sqlState of class Doctrine\\DBAL\\Driver\\Mysqli\\MysqliException constructor expects string\|null, int given\.$~'
paths:
- %currentWorkingDirectory%/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php
# This is deprecated code. Fixing the issue may cause a BC break.
# TODO: remove in 3.0.0
-
message: '~^Return type \(string\) of method Doctrine\\DBAL\\Driver\\Mysqli\\MysqliStatement::errorInfo\(\) should be compatible with return type \(array\) of method Doctrine\\DBAL\\Driver\\Statement::errorInfo\(\)$~'
paths:
- %currentWorkingDirectory%/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php
# This is poorly typed deprecated code. The issue doesn't have practical implication and can be suppressed.
# TODO: remove in 3.0.0
-
message: '~^Parameter \#1 \$how of method PDOStatement\:\:fetchAll\(\) expects int, array\|int\|null given\.$~'
paths:
- %currentWorkingDirectory%/lib/Doctrine/DBAL/Driver/PDOStatement.php
# https://github.com/phpstan/phpstan/issues/3134
-
message: '~^Call to static method PHPUnit\\Framework\\Assert::assertSame\(\) with Doctrine\\DBAL\\Types\\Type and Doctrine\\DBAL\\Types\\Type will always evaluate to true\.$~'
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Cache;
use Doctrine\Common\Cache\Cache;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Result;
......@@ -133,7 +133,7 @@ class CachingResult implements Result
/**
* @return array<string,mixed>|false
*
* @throws DriverException
* @throws Exception
*/
private function fetch()
{
......
......@@ -2,7 +2,7 @@
namespace Doctrine\DBAL;
use Doctrine\DBAL\Driver\DriverException as DriverExceptionInterface;
use Doctrine\DBAL\Driver\DriverException as DeprecatedDriverException;
use Doctrine\DBAL\Driver\ExceptionConverterDriver;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\Platforms\AbstractPlatform;
......@@ -169,7 +169,7 @@ class DBALException extends Exception
return $driverEx;
}
if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof DriverExceptionInterface) {
if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof DeprecatedDriverException) {
return $driver->convertException($msg, $driverEx);
}
......
......@@ -2,55 +2,11 @@
namespace Doctrine\DBAL\Driver;
use Exception;
/**
* Abstract base implementation of the {@link DriverException} interface.
* @deprecated
*
* @psalm-immutable
*/
abstract class AbstractDriverException extends Exception implements DriverException
abstract class AbstractDriverException extends AbstractException
{
/**
* The driver specific error code.
*
* @var int|string|null
*/
private $errorCode;
/**
* The SQLSTATE of the driver.
*
* @var string|null
*/
private $sqlState;
/**
* @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.
*/
public function __construct($message, $sqlState = null, $errorCode = null)
{
parent::__construct($message);
$this->errorCode = $errorCode;
$this->sqlState = $sqlState;
}
/**
* {@inheritdoc}
*/
public function getErrorCode()
{
return $this->errorCode;
}
/**
* {@inheritdoc}
*/
public function getSQLState()
{
return $this->sqlState;
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver;
use Exception as BaseException;
/**
* Base implementation of the {@link Exception} interface.
*
* @internal
*
* @psalm-immutable
*/
abstract class AbstractException extends BaseException implements DriverException
{
/**
* The driver specific error code.
*
* @var int|string|null
*/
private $errorCode;
/**
* The SQLSTATE of the driver.
*
* @var string|null
*/
private $sqlState;
/**
* @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.
*/
public function __construct($message, $sqlState = null, $errorCode = null)
{
parent::__construct($message);
$this->errorCode = $errorCode;
$this->sqlState = $sqlState;
}
/**
* {@inheritdoc}
*/
public function getErrorCode()
{
return $this->errorCode;
}
/**
* {@inheritdoc}
*/
public function getSQLState()
{
return $this->sqlState;
}
}
......@@ -4,7 +4,19 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Driver\DriverException as DeprecatedDriverException;
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\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\Platforms\MariaDb1027Platform;
use Doctrine\DBAL\Platforms\MySQL57Platform;
use Doctrine\DBAL\Platforms\MySQL80Platform;
......@@ -17,7 +29,7 @@ use function stripos;
use function version_compare;
/**
* Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for MySQL based drivers.
* Abstract base implementation of the {@link Driver} interface for MySQL based drivers.
*/
abstract class AbstractMySQLDriver implements ExceptionConverterDriver, VersionAwarePlatformDriver
{
......@@ -27,44 +39,44 @@ abstract class AbstractMySQLDriver implements ExceptionConverterDriver, VersionA
* @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, DriverException $exception)
public function convertException($message, DeprecatedDriverException $exception)
{
switch ($exception->getErrorCode()) {
case '1213':
return new Exception\DeadlockException($message, $exception);
return new DeadlockException($message, $exception);
case '1205':
return new Exception\LockWaitTimeoutException($message, $exception);
return new LockWaitTimeoutException($message, $exception);
case '1050':
return new Exception\TableExistsException($message, $exception);
return new TableExistsException($message, $exception);
case '1051':
case '1146':
return new Exception\TableNotFoundException($message, $exception);
return new TableNotFoundException($message, $exception);
case '1216':
case '1217':
case '1451':
case '1452':
case '1701':
return new Exception\ForeignKeyConstraintViolationException($message, $exception);
return new ForeignKeyConstraintViolationException($message, $exception);
case '1062':
case '1557':
case '1569':
case '1586':
return new Exception\UniqueConstraintViolationException($message, $exception);
return new UniqueConstraintViolationException($message, $exception);
case '1054':
case '1166':
case '1611':
return new Exception\InvalidFieldNameException($message, $exception);
return new InvalidFieldNameException($message, $exception);
case '1052':
case '1060':
case '1110':
return new Exception\NonUniqueFieldNameException($message, $exception);
return new NonUniqueFieldNameException($message, $exception);
case '1064':
case '1149':
......@@ -78,7 +90,7 @@ abstract class AbstractMySQLDriver implements ExceptionConverterDriver, VersionA
case '1541':
case '1554':
case '1626':
return new Exception\SyntaxErrorException($message, $exception);
return new SyntaxErrorException($message, $exception);
case '1044':
case '1045':
......@@ -92,7 +104,7 @@ abstract class AbstractMySQLDriver implements ExceptionConverterDriver, VersionA
case '1429':
case '2002':
case '2005':
return new Exception\ConnectionException($message, $exception);
return new ConnectionException($message, $exception);
case '1048':
case '1121':
......@@ -102,10 +114,10 @@ abstract class AbstractMySQLDriver implements ExceptionConverterDriver, VersionA
case '1263':
case '1364':
case '1566':
return new Exception\NotNullConstraintViolationException($message, $exception);
return new NotNullConstraintViolationException($message, $exception);
}
return new Exception\DriverException($message, $exception);
return new DriverException($message, $exception);
}
/**
......
......@@ -5,56 +5,66 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\AbstractOracleDriver\EasyConnectString;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Driver\DriverException as DeprecatedDriverException;
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\Platforms\OraclePlatform;
use Doctrine\DBAL\Schema\OracleSchemaManager;
/**
* Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for Oracle based drivers.
* Abstract base implementation of the {@link Driver} interface for Oracle based drivers.
*/
abstract class AbstractOracleDriver implements Driver, ExceptionConverterDriver
{
/**
* {@inheritdoc}
*/
public function convertException($message, DriverException $exception)
public function convertException($message, DeprecatedDriverException $exception)
{
switch ($exception->getErrorCode()) {
case '1':
case '2299':
case '38911':
return new Exception\UniqueConstraintViolationException($message, $exception);
return new UniqueConstraintViolationException($message, $exception);
case '904':
return new Exception\InvalidFieldNameException($message, $exception);
return new InvalidFieldNameException($message, $exception);
case '918':
case '960':
return new Exception\NonUniqueFieldNameException($message, $exception);
return new NonUniqueFieldNameException($message, $exception);
case '923':
return new Exception\SyntaxErrorException($message, $exception);
return new SyntaxErrorException($message, $exception);
case '942':
return new Exception\TableNotFoundException($message, $exception);
return new TableNotFoundException($message, $exception);
case '955':
return new Exception\TableExistsException($message, $exception);
return new TableExistsException($message, $exception);
case '1017':
case '12545':
return new Exception\ConnectionException($message, $exception);
return new ConnectionException($message, $exception);
case '1400':
return new Exception\NotNullConstraintViolationException($message, $exception);
return new NotNullConstraintViolationException($message, $exception);
case '2266':
case '2291':
case '2292':
return new Exception\ForeignKeyConstraintViolationException($message, $exception);
return new ForeignKeyConstraintViolationException($message, $exception);
}
return new Exception\DriverException($message, $exception);
return new DriverException($message, $exception);
}
/**
......
......@@ -4,7 +4,18 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Driver\DriverException as DeprecatedDriverException;
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\Platforms\PostgreSQL100Platform;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use Doctrine\DBAL\Schema\PostgreSqlSchemaManager;
......@@ -15,7 +26,7 @@ use function strpos;
use function version_compare;
/**
* Abstract base implementation of the {@link Doctrine\DBAL\Driver} interface for PostgreSQL based drivers.
* Abstract base implementation of the {@link Driver} interface for PostgreSQL based drivers.
*/
abstract class AbstractPostgreSQLDriver implements ExceptionConverterDriver, VersionAwarePlatformDriver
{
......@@ -24,58 +35,58 @@ abstract class AbstractPostgreSQLDriver implements ExceptionConverterDriver, Ver
*
* @link http://www.postgresql.org/docs/9.4/static/errcodes-appendix.html
*/
public function convertException($message, DriverException $exception)
public function convertException($message, DeprecatedDriverException $exception)
{
switch ($exception->getSQLState()) {
case '40001':
case '40P01':
return new Exception\DeadlockException($message, $exception);
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 Exception\ForeignKeyConstraintViolationException($message, $exception);
return new ForeignKeyConstraintViolationException($message, $exception);
}
break;
case '23502':
return new Exception\NotNullConstraintViolationException($message, $exception);
return new NotNullConstraintViolationException($message, $exception);
case '23503':
return new Exception\ForeignKeyConstraintViolationException($message, $exception);
return new ForeignKeyConstraintViolationException($message, $exception);
case '23505':
return new Exception\UniqueConstraintViolationException($message, $exception);
return new UniqueConstraintViolationException($message, $exception);
case '42601':
return new Exception\SyntaxErrorException($message, $exception);
return new SyntaxErrorException($message, $exception);
case '42702':
return new Exception\NonUniqueFieldNameException($message, $exception);
return new NonUniqueFieldNameException($message, $exception);
case '42703':
return new Exception\InvalidFieldNameException($message, $exception);
return new InvalidFieldNameException($message, $exception);
case '42P01':
return new Exception\TableNotFoundException($message, $exception);
return new TableNotFoundException($message, $exception);
case '42P07':
return new Exception\TableExistsException($message, $exception);
return new 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) {
return new Exception\ConnectionException($message, $exception);
return new ConnectionException($message, $exception);
}
break;
}
return new Exception\DriverException($message, $exception);
return new DriverException($message, $exception);
}
/**
......
......@@ -2,16 +2,16 @@
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\AbstractSQLServerDriver;
namespace Doctrine\DBAL\Driver\AbstractSQLServerDriver\Exception;
use Doctrine\DBAL\Driver\AbstractDriverException;
use Doctrine\DBAL\Driver\AbstractException;
/**
* @internal
*
* @psalm-immutable
*/
final class PortWithoutHost extends AbstractDriverException
final class PortWithoutHost extends AbstractException
{
public static function new(): self
{
......
......@@ -4,7 +4,19 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Driver\DriverException as DeprecatedDriverException;
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\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\SqliteSchemaManager;
......@@ -20,10 +32,10 @@ abstract class AbstractSQLiteDriver implements Driver, ExceptionConverterDriver
*
* @link http://www.sqlite.org/c3ref/c_abort.html
*/
public function convertException($message, DriverException $exception)
public function convertException($message, DeprecatedDriverException $exception)
{
if (strpos($exception->getMessage(), 'database is locked') !== false) {
return new Exception\LockWaitTimeoutException($message, $exception);
return new LockWaitTimeoutException($message, $exception);
}
if (
......@@ -32,49 +44,49 @@ abstract class AbstractSQLiteDriver implements Driver, ExceptionConverterDriver
strpos($exception->getMessage(), 'are not unique') !== false ||
strpos($exception->getMessage(), 'UNIQUE constraint failed') !== false
) {
return new Exception\UniqueConstraintViolationException($message, $exception);
return new UniqueConstraintViolationException($message, $exception);
}
if (
strpos($exception->getMessage(), 'may not be NULL') !== false ||
strpos($exception->getMessage(), 'NOT NULL constraint failed') !== false
) {
return new Exception\NotNullConstraintViolationException($message, $exception);
return new NotNullConstraintViolationException($message, $exception);
}
if (strpos($exception->getMessage(), 'no such table:') !== false) {
return new Exception\TableNotFoundException($message, $exception);
return new TableNotFoundException($message, $exception);
}
if (strpos($exception->getMessage(), 'already exists') !== false) {
return new Exception\TableExistsException($message, $exception);
return new TableExistsException($message, $exception);
}
if (strpos($exception->getMessage(), 'has no column named') !== false) {
return new Exception\InvalidFieldNameException($message, $exception);
return new InvalidFieldNameException($message, $exception);
}
if (strpos($exception->getMessage(), 'ambiguous column name') !== false) {
return new Exception\NonUniqueFieldNameException($message, $exception);
return new NonUniqueFieldNameException($message, $exception);
}
if (strpos($exception->getMessage(), 'syntax error') !== false) {
return new Exception\SyntaxErrorException($message, $exception);
return new SyntaxErrorException($message, $exception);
}
if (strpos($exception->getMessage(), 'attempt to write a readonly database') !== false) {
return new Exception\ReadOnlyException($message, $exception);
return new ReadOnlyException($message, $exception);
}
if (strpos($exception->getMessage(), 'unable to open database file') !== false) {
return new Exception\ConnectionException($message, $exception);
return new ConnectionException($message, $exception);
}
if (strpos($exception->getMessage(), 'FOREIGN KEY constraint failed') !== false) {
return new Exception\ForeignKeyConstraintViolationException($message, $exception);
return new ForeignKeyConstraintViolationException($message, $exception);
}
return new Exception\DriverException($message, $exception);
return new DriverException($message, $exception);
}
/**
......
......@@ -2,34 +2,11 @@
namespace Doctrine\DBAL\Driver;
use Throwable;
/**
* Contract for a driver exception.
*
* Driver exceptions provide the SQLSTATE of the driver
* and the driver specific error code at the time the error occurred.
* @deprecated Use {@link Exception} instead
*
* @psalm-immutable
*/
interface DriverException extends Throwable
interface DriverException extends Exception
{
/**
* 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 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();
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver;
use Throwable;
/**
* @psalm-immutable
*/
interface Exception 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 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();
}
......@@ -2,6 +2,9 @@
namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\DriverException as TheDriverException;
use Doctrine\DBAL\Exception\DriverException;
/**
* Contract for a driver that is capable of converting DBAL driver exceptions into standardized DBAL driver exceptions.
*/
......@@ -11,12 +14,12 @@ interface ExceptionConverterDriver
* Converts a given DBAL driver exception into a standardized DBAL driver exception.
*
* It evaluates the vendor specific error code and SQLSTATE and transforms
* it into a unified {@link Doctrine\DBAL\Exception\DriverException} subclass.
* it into a unified {@link DriverException} subclass.
*
* @param string $message The DBAL exception message to use.
* @param DriverException $exception The DBAL driver exception to convert.
* @param string $message The DBAL exception message to use.
* @param TheDriverException $exception The DBAL driver exception to convert.
*
* @return \Doctrine\DBAL\Exception\DriverException An instance of one of the DriverException subclasses.
* @return DriverException An instance of one of the DriverException subclasses.
*/
public function convertException($message, DriverException $exception);
public function convertException($message, TheDriverException $exception);
}
......@@ -12,7 +12,7 @@ final class FetchUtils
/**
* @return mixed|false
*
* @throws DriverException
* @throws Exception
*/
public static function fetchOne(Result $result)
{
......@@ -28,7 +28,7 @@ final class FetchUtils
/**
* @return array<int,array<int,mixed>>
*
* @throws DriverException
* @throws Exception
*/
public static function fetchAllNumeric(Result $result): array
{
......@@ -44,7 +44,7 @@ final class FetchUtils
/**
* @return array<int,array<string,mixed>>
*
* @throws DriverException
* @throws Exception
*/
public static function fetchAllAssociative(Result $result): array
{
......@@ -60,7 +60,7 @@ final class FetchUtils
/**
* @return array<int,mixed>
*
* @throws DriverException
* @throws Exception
*/
public static function fetchFirstColumn(Result $result): array
{
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2;
final class Connection extends DB2Connection
{
}
......@@ -29,6 +29,9 @@ use function is_bool;
use const DB2_AUTOCOMMIT_OFF;
use const DB2_AUTOCOMMIT_ON;
/**
* @deprecated Use {@link Connection} instead
*/
class DB2Connection implements ServerInfoAwareConnection
{
/** @var resource */
......@@ -86,7 +89,7 @@ class DB2Connection implements ServerInfoAwareConnection
throw PrepareFailed::new(error_get_last()['message']);
}
return new DB2Statement($stmt);
return new Statement($stmt);
}
public function query(string $sql): ResultInterface
......
......@@ -6,6 +6,8 @@ use Doctrine\DBAL\Driver\AbstractDB2Driver;
/**
* IBM DB2 Driver.
*
* @deprecated Use {@link Driver} instead
*/
class DB2Driver extends AbstractDB2Driver
{
......@@ -14,7 +16,7 @@ class DB2Driver extends AbstractDB2Driver
*/
public function connect(array $params)
{
return new DB2Connection(
return new Connection(
DataSourceName::fromConnectionParameters($params)->toString(),
isset($params['persistent']) && $params['persistent'] === true,
$params['user'] ?? '',
......
......@@ -5,6 +5,8 @@ namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\AbstractDriverException;
/**
* @deprecated Use {@link Exception} instead
*
* @psalm-immutable
*/
class DB2Exception extends AbstractDriverException
......
......@@ -2,9 +2,12 @@
namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\IBMDB2\Exception\CannotCopyStreamToStream;
use Doctrine\DBAL\Driver\IBMDB2\Exception\CannotCreateTemporaryFile;
use Doctrine\DBAL\Driver\IBMDB2\Exception\CannotWriteToTemporaryFile;
use Doctrine\DBAL\Driver\IBMDB2\Exception\StatementError;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\ParameterType;
use function assert;
......@@ -26,7 +29,10 @@ use const DB2_LONG;
use const DB2_PARAM_FILE;
use const DB2_PARAM_IN;
class DB2Statement implements Statement
/**
* @deprecated Use {@link Statement} instead
*/
class DB2Statement implements StatementInterface
{
/** @var resource */
private $stmt;
......@@ -159,7 +165,7 @@ class DB2Statement implements Statement
$handle = @tmpfile();
if ($handle === false) {
throw new DB2Exception('Could not create temporary file: ' . error_get_last()['message']);
throw CannotCreateTemporaryFile::new(error_get_last()['message']);
}
return $handle;
......@@ -174,7 +180,7 @@ class DB2Statement implements Statement
private function copyStreamToStream($source, $target): void
{
if (@stream_copy_to_stream($source, $target) === false) {
throw new DB2Exception('Could not copy source stream to temporary file: ' . error_get_last()['message']);
throw CannotCopyStreamToStream::new(error_get_last()['message']);
}
}
......@@ -186,7 +192,7 @@ class DB2Statement implements Statement
private function writeStringToStream(string $string, $target): void
{
if (@fwrite($target, $string) === false) {
throw new DB2Exception('Could not write string to temporary file: ' . error_get_last()['message']);
throw CannotWriteToTemporaryFile::new(error_get_last()['message']);
}
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2;
final class Driver extends DB2Driver
{
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;
/**
* @internal
*
* @psalm-immutable
*/
final class CannotCopyStreamToStream extends DB2Exception
{
public static function new(string $message): self
{
return new self('Could not copy source stream to temporary file: ' . $message);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;
/**
* @internal
*
* @psalm-immutable
*/
final class CannotCreateTemporaryFile extends DB2Exception
{
public static function new(string $message): self
{
return new self('Could not create temporary file: ' . $message);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;
/**
* @internal
*
* @psalm-immutable
*/
final class CannotWriteToTemporaryFile extends DB2Exception
{
public static function new(string $message): self
{
return new self('Could not write string to temporary file: ' . $message);
}
}
......@@ -4,15 +4,17 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;
use Doctrine\DBAL\Driver\AbstractException;
use function db2_conn_error;
use function db2_conn_errormsg;
/**
* @internal
*
* @psalm-immutable
*/
final class ConnectionError extends DB2Exception
final class ConnectionError extends AbstractException
{
/**
* @param resource $connection
......
......@@ -4,15 +4,17 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;
use Doctrine\DBAL\Driver\AbstractException;
use function db2_conn_error;
use function db2_conn_errormsg;
/**
* @internal
*
* @psalm-immutable
*/
final class ConnectionFailed extends DB2Exception
final class ConnectionFailed extends AbstractException
{
public static function new(): self
{
......
......@@ -4,12 +4,14 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;
use Doctrine\DBAL\Driver\AbstractException;
/**
* @internal
*
* @psalm-immutable
*/
final class PrepareFailed extends DB2Exception
final class PrepareFailed extends AbstractException
{
public static function new(string $message): self
{
......
......@@ -4,15 +4,17 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2\Exception;
use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;
use Doctrine\DBAL\Driver\AbstractException;
use function db2_stmt_error;
use function db2_stmt_errormsg;
/**
* @internal
*
* @psalm-immutable
*/
final class StatementError extends DB2Exception
final class StatementError extends AbstractException
{
/**
* @param resource $statement
......
......@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\IBMDB2\Exception\StatementError;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use function db2_fetch_array;
......@@ -13,7 +14,6 @@ use function db2_free_result;
use function db2_num_fields;
use function db2_num_rows;
use function db2_stmt_error;
use function db2_stmt_errormsg;
final class Result implements ResultInterface
{
......@@ -36,7 +36,7 @@ final class Result implements ResultInterface
$row = @db2_fetch_array($this->statement);
if ($row === false && db2_stmt_error($this->statement) !== '02000') {
throw new DB2Exception(db2_stmt_errormsg($this->statement));
throw StatementError::new($this->statement);
}
return $row;
......@@ -50,7 +50,7 @@ final class Result implements ResultInterface
$row = @db2_fetch_assoc($this->statement);
if ($row === false && db2_stmt_error($this->statement) !== '02000') {
throw new DB2Exception(db2_stmt_errormsg($this->statement));
throw StatementError::new($this->statement);
}
return $row;
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2;
final class Statement extends DB2Statement
{
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli;
final class Connection extends MysqliConnection
{
}
......@@ -44,7 +44,7 @@ class Driver extends AbstractMySQLDriver
$preInitializers = $this->withSecure($preInitializers, $params);
$postInitializers = $this->withCharset($postInitializers, $params);
return new MysqliConnection(
return new Connection(
$host,
$params['user'] ?? null,
$params['password'] ?? null,
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use mysqli;
/**
* @internal
*
* @psalm-immutable
*/
final class ConnectionError extends MysqliException
{
public static function new(mysqli $connection): self
{
return new self($connection->error, $connection->sqlstate, $connection->errno);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use mysqli;
/**
* @internal
*
* @psalm-immutable
*/
final class ConnectionFailed extends MysqliException
{
public static function new(mysqli $connection): self
{
return new self($connection->connect_error, 'HY000', $connection->connect_errno);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use function sprintf;
/**
* @internal
*
* @psalm-immutable
*/
final class FailedReadingStreamOffset extends MysqliException
{
public static function new(int $offset): self
{
return new self(sprintf('Failed reading the stream resource for parameter offset %d.', $offset));
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use mysqli_stmt;
/**
* @internal
*
* @psalm-immutable
*/
final class StatementError extends MysqliException
{
public static function new(mysqli_stmt $statement): self
{
return new self($statement->error, $statement->sqlstate, $statement->errno);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli\Exception;
use Doctrine\DBAL\Driver\Mysqli\MysqliException;
use function sprintf;
/**
* @internal
*
* @psalm-immutable
*/
final class UnknownType extends MysqliException
{
/**
* @param mixed $type
*/
public static function new($type): self
{
return new self(sprintf('Unknown type, %d given.', $type));
}
}
......@@ -2,6 +2,8 @@
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionError;
use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionFailed;
use Doctrine\DBAL\Driver\PingableConnection;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
......@@ -13,6 +15,9 @@ use function floor;
use function mysqli_init;
use function stripos;
/**
* @deprecated Use {@link Connection} instead
*/
class MysqliConnection implements PingableConnection, ServerInfoAwareConnection
{
/**
......@@ -47,11 +52,7 @@ class MysqliConnection implements PingableConnection, ServerInfoAwareConnection
}
if (! @$connection->real_connect($host, $username, $password, $database, $port, $socket, $flags)) {
throw new MysqliException(
$connection->connect_error,
'HY000',
$connection->connect_errno
);
throw ConnectionFailed::new($connection);
}
foreach ($postInitializers as $initializer) {
......@@ -105,7 +106,7 @@ class MysqliConnection implements PingableConnection, ServerInfoAwareConnection
public function prepare(string $sql): DriverStatement
{
return new MysqliStatement($this->conn, $sql);
return new Statement($this->conn, $sql);
}
public function query(string $sql): ResultInterface
......@@ -124,7 +125,7 @@ class MysqliConnection implements PingableConnection, ServerInfoAwareConnection
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 ConnectionError::new($this->conn);
}
return $this->conn->affected_rows;
......
......@@ -5,7 +5,7 @@ namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\AbstractDriverException;
/**
* Exception thrown in case the mysqli driver errors.
* @deprecated Use {@link Exception} instead
*
* @psalm-immutable
*/
......
......@@ -2,8 +2,12 @@
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionError;
use Doctrine\DBAL\Driver\Mysqli\Exception\FailedReadingStreamOffset;
use Doctrine\DBAL\Driver\Mysqli\Exception\StatementError;
use Doctrine\DBAL\Driver\Mysqli\Exception\UnknownType;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\DBAL\ParameterType;
use mysqli;
......@@ -17,10 +21,12 @@ use function fread;
use function get_resource_type;
use function is_int;
use function is_resource;
use function sprintf;
use function str_repeat;
class MysqliStatement implements Statement
/**
* @deprecated Use {@link Statement} instead
*/
class MysqliStatement implements StatementInterface
{
/** @var string[] */
protected static $_paramTypeMap = [
......@@ -63,7 +69,7 @@ class MysqliStatement implements Statement
$stmt = $conn->prepare($prepareString);
if ($stmt === false) {
throw new MysqliException($this->_conn->error, $this->_conn->sqlstate, $this->_conn->errno);
throw ConnectionError::new($this->_conn);
}
$this->_stmt = $stmt;
......@@ -85,7 +91,7 @@ class MysqliStatement implements Statement
assert(is_int($column));
if (! isset(self::$_paramTypeMap[$type])) {
throw new MysqliException(sprintf("Unknown type: '%s'", $type));
throw UnknownType::new($type);
}
$this->_bindedValues[$column] =& $variable;
......@@ -102,7 +108,7 @@ class MysqliStatement implements Statement
assert(is_int($param));
if (! isset(self::$_paramTypeMap[$type])) {
throw new MysqliException(sprintf("Unknown type: '%s'", $type));
throw UnknownType::new($type);
}
$this->_values[$param] = $value;
......@@ -120,7 +126,7 @@ class MysqliStatement implements Statement
if ($this->_bindedValues !== null) {
if ($params !== null) {
if (! $this->bindUntypedValues($params)) {
throw new MysqliException($this->_stmt->error, $this->_stmt->errno);
throw StatementError::new($this->_stmt);
}
} else {
$this->bindTypedParameters();
......@@ -128,7 +134,7 @@ class MysqliStatement implements Statement
}
if (! $this->_stmt->execute()) {
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
throw StatementError::new($this->_stmt);
}
return new Result($this->_stmt);
......@@ -167,7 +173,7 @@ class MysqliStatement implements Statement
}
if (! $this->_stmt->bind_param($types, ...$values)) {
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
throw StatementError::new($this->_stmt);
}
$this->sendLongData($streams);
......@@ -187,11 +193,11 @@ class MysqliStatement implements Statement
$chunk = fread($stream, 8192);
if ($chunk === false) {
throw new MysqliException("Failed reading the stream resource for parameter offset ${paramNr}.");
throw FailedReadingStreamOffset::new($paramNr);
}
if (! $this->_stmt->send_long_data($paramNr - 1, $chunk)) {
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
throw StatementError::new($this->_stmt);
}
}
}
......
......@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Mysqli\Exception\StatementError;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use mysqli_stmt;
use stdClass;
......@@ -88,7 +89,7 @@ final class Result implements ResultInterface
}
if (! $this->statement->bind_result(...$refs)) {
throw new MysqliException($this->statement->error, $this->statement->sqlstate, $this->statement->errno);
throw StatementError::new($this->statement);
}
}
......@@ -100,7 +101,7 @@ final class Result implements ResultInterface
$ret = $this->statement->fetch();
if ($ret === false) {
throw new MysqliException($this->statement->error, $this->statement->sqlstate, $this->statement->errno);
throw StatementError::new($this->statement);
}
if ($ret === null) {
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli;
final class Statement extends MysqliStatement
{
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\OCI8;
final class Connection extends OCI8Connection
{
}
......@@ -16,7 +16,7 @@ class Driver extends AbstractOracleDriver
*/
public function connect(array $params)
{
return new OCI8Connection(
return new Connection(
$params['user'] ?? '',
$params['password'] ?? '',
$this->_constructDsn($params),
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\OCI8\Exception;
use Doctrine\DBAL\Driver\OCI8\OCI8Exception;
use function sprintf;
/**
* @internal
*
* @psalm-immutable
*/
final class NonTerminatedStringLiteral extends OCI8Exception
{
public static function new(int $offset): self
{
return new self(
sprintf(
'The statement contains non-terminated string literal starting at offset %d.',
$offset
)
);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\OCI8\Exception;
use Doctrine\DBAL\Driver\OCI8\OCI8Exception;
/**
* @internal
*
* @psalm-immutable
*/
final class SequenceDoesNotExist extends OCI8Exception
{
public static function new(): self
{
return new self('lastInsertId failed: Query was executed but no result was returned.');
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\OCI8\Exception;
use Doctrine\DBAL\Driver\OCI8\OCI8Exception;
use function sprintf;
/**
* @internal
*
* @psalm-immutable
*/
final class UnknownParameterIndex extends OCI8Exception
{
public static function new(int $index): self
{
return new self(
sprintf('Could not find variable mapping with index %d, in the SQL statement', $index)
);
}
}
......@@ -2,7 +2,8 @@
namespace Doctrine\DBAL\Driver\OCI8;
use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\Connection as ConnectionInterface;
use Doctrine\DBAL\Driver\OCI8\Exception\SequenceDoesNotExist;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
......@@ -27,8 +28,10 @@ use const OCI_NO_AUTO_COMMIT;
/**
* OCI8 implementation of the Connection interface.
*
* @deprecated Use {@link Connection} instead
*/
class OCI8Connection implements Connection, ServerInfoAwareConnection
class OCI8Connection implements ConnectionInterface, ServerInfoAwareConnection
{
/** @var resource */
protected $dbh;
......@@ -104,7 +107,7 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection
public function prepare(string $sql): DriverStatement
{
return new OCI8Statement($this->dbh, $sql, $this);
return new Statement($this->dbh, $sql, $this);
}
public function query(string $sql): ResultInterface
......@@ -145,7 +148,7 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection
$result = $this->query('SELECT ' . $name . '.CURRVAL FROM DUAL')->fetchOne();
if ($result === false) {
throw new OCI8Exception('lastInsertId failed: Query was executed but no result was returned.');
throw SequenceDoesNotExist::new();
}
return (int) $result;
......
......@@ -5,6 +5,8 @@ namespace Doctrine\DBAL\Driver\OCI8;
use Doctrine\DBAL\Driver\AbstractDriverException;
/**
* @deprecated Use {@link Exception} instead
*
* @psalm-immutable
*/
class OCI8Exception extends AbstractDriverException
......
......@@ -2,8 +2,10 @@
namespace Doctrine\DBAL\Driver\OCI8;
use Doctrine\DBAL\Driver\OCI8\Exception\NonTerminatedStringLiteral;
use Doctrine\DBAL\Driver\OCI8\Exception\UnknownParameterIndex;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\ParameterType;
use function assert;
......@@ -18,7 +20,6 @@ use function oci_new_descriptor;
use function oci_parse;
use function preg_match;
use function preg_quote;
use function sprintf;
use function substr;
use const OCI_B_BIN;
......@@ -30,8 +31,10 @@ use const SQLT_CHR;
/**
* The OCI8 implementation of the Statement interface.
*
* @deprecated Use {@link Statement} instead
*/
class OCI8Statement implements Statement
class OCI8Statement implements StatementInterface
{
/** @var resource */
protected $_dbh;
......@@ -116,10 +119,7 @@ class OCI8Statement implements Statement
} while ($result);
if ($currentLiteralDelimiter) {
throw new OCI8Exception(sprintf(
'The statement contains non-terminated string literal starting at offset %d',
$tokenOffset - 1
));
throw NonTerminatedStringLiteral::new($tokenOffset - 1);
}
$fragments[] = substr($statement, $fragmentOffset);
......@@ -239,7 +239,7 @@ class OCI8Statement implements Statement
{
if (is_int($param)) {
if (! isset($this->_paramMap[$param])) {
throw new OCI8Exception(sprintf('Could not find variable mapping with index %d, in the SQL statement', $param));
throw UnknownParameterIndex::new($param);
}
$param = $this->_paramMap[$param];
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\OCI8;
final class Statement extends OCI8Statement
{
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\PDO;
use Doctrine\DBAL\Driver\PDOConnection;
class Connection extends PDOConnection
{
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\PDO;
use Doctrine\DBAL\Driver\PDOException;
/**
* @internal
*
* @psalm-immutable
*/
final class Exception extends PDOException
{
public static function new(\PDOException $exception): self
{
return new self($exception);
}
}
......@@ -4,9 +4,9 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\PDO;
use Doctrine\DBAL\Driver\PDOException;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use PDO;
use PDOException;
use PDOStatement;
use function assert;
......@@ -74,8 +74,8 @@ final class Result implements ResultInterface
{
try {
return $this->statement->rowCount();
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
......@@ -83,8 +83,8 @@ final class Result implements ResultInterface
{
try {
return $this->statement->columnCount();
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
......@@ -92,36 +92,36 @@ final class Result implements ResultInterface
{
try {
$this->statement->closeCursor();
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
/**
* @return mixed|false
*
* @throws PDOException
* @throws Exception
*/
private function fetch(int $mode)
{
try {
return $this->statement->fetch($mode);
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
/**
* @return array<int,mixed>
*
* @throws PDOException
* @throws Exception
*/
private function fetchAll(int $mode): array
{
try {
$data = $this->statement->fetchAll($mode);
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
assert(is_array($data));
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\PDO;
use Doctrine\DBAL\Driver\PDOStatement;
class Statement extends PDOStatement
{
}
......@@ -2,10 +2,15 @@
namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\PDO\Exception;
use Doctrine\DBAL\Driver\PDO\Result;
use Doctrine\DBAL\Driver\PDO\Statement;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\ParameterType;
use PDO;
use PDOException;
use PDOStatement;
use function assert;
......@@ -13,6 +18,8 @@ use function assert;
* PDO implementation of the Connection interface.
*
* Used by all PDO-based drivers.
*
* @deprecated Use {@link Connection} instead
*/
class PDOConnection implements ServerInfoAwareConnection
{
......@@ -32,8 +39,8 @@ class PDOConnection implements ServerInfoAwareConnection
try {
$this->connection = new PDO($dsn, (string) $user, (string) $password, (array) $options);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
......@@ -45,8 +52,8 @@ class PDOConnection implements ServerInfoAwareConnection
assert($result !== false);
return $result;
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
......@@ -58,14 +65,14 @@ class PDOConnection implements ServerInfoAwareConnection
return $this->connection->getAttribute(PDO::ATTR_SERVER_VERSION);
}
public function prepare(string $sql): Statement
public function prepare(string $sql): StatementInterface
{
try {
return $this->createStatement(
$this->connection->prepare($sql)
);
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
......@@ -73,11 +80,11 @@ class PDOConnection implements ServerInfoAwareConnection
{
try {
$stmt = $this->connection->query($sql);
assert($stmt instanceof \PDOStatement);
assert($stmt instanceof PDOStatement);
return new Result($stmt);
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
......@@ -100,8 +107,8 @@ class PDOConnection implements ServerInfoAwareConnection
}
return $this->connection->lastInsertId($name);
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
......@@ -116,9 +123,9 @@ class PDOConnection implements ServerInfoAwareConnection
/**
* Creates a wrapped statement
*/
protected function createStatement(\PDOStatement $stmt): PDOStatement
protected function createStatement(PDOStatement $stmt): Statement
{
return new PDOStatement($stmt);
return new Statement($stmt);
}
/**
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Driver;
/**
* Tiny wrapper for PDOException instances to implement the {@link DriverException} interface.
* @deprecated Use {@link Exception} instead
*
* @psalm-immutable
*/
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Driver\PDOMySql;
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDO\Connection;
use PDO;
/**
......@@ -22,7 +22,7 @@ class Driver extends AbstractMySQLDriver
$driverOptions[PDO::ATTR_PERSISTENT] = true;
}
return new PDOConnection(
return new Connection(
$this->constructPdoDsn($params),
$params['user'] ?? '',
$params['password'] ?? '',
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Driver\PDOOracle;
use Doctrine\DBAL\Driver\AbstractOracleDriver;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDO\Connection;
use PDO;
/**
......@@ -27,7 +27,7 @@ class Driver extends AbstractOracleDriver
$driverOptions[PDO::ATTR_PERSISTENT] = true;
}
return new PDOConnection(
return new Connection(
$this->constructPdoDsn($params),
$params['user'] ?? '',
$params['password'] ?? '',
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Driver\PDOPgSql;
use Doctrine\DBAL\Driver\AbstractPostgreSQLDriver;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDO\Connection;
use PDO;
use function defined;
......@@ -24,7 +24,7 @@ class Driver extends AbstractPostgreSQLDriver
$driverOptions[PDO::ATTR_PERSISTENT] = true;
}
$connection = new PDOConnection(
$connection = new Connection(
$this->_constructPdoDsn($params),
$params['user'] ?? '',
$params['password'] ?? '',
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Driver\PDOSqlite;
use Doctrine\DBAL\Driver\AbstractSQLiteDriver;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDO\Connection;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use function array_merge;
......@@ -35,7 +35,7 @@ class Driver extends AbstractSQLiteDriver
unset($driverOptions['userDefinedFunctions']);
}
$connection = new PDOConnection(
$connection = new Connection(
$this->_constructPdoDsn($params),
$params['user'] ?? '',
$params['password'] ?? '',
......
......@@ -2,17 +2,19 @@
namespace Doctrine\DBAL\Driver\PDOSqlsrv;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDOStatement;
use Doctrine\DBAL\Driver\PDO\Connection as BaseConnection;
use Doctrine\DBAL\Driver\PDO\Statement as BaseStatement;
use Doctrine\DBAL\ParameterType;
use PDOStatement;
use function is_string;
use function strpos;
use function substr;
/**
* Sqlsrv Connection implementation.
*/
class Connection extends PDOConnection
class Connection extends BaseConnection
{
/**
* {@inheritDoc}
......@@ -36,14 +38,14 @@ class Connection extends PDOConnection
$val = parent::quote($value, $type);
// Fix for a driver version terminating all values with null byte
if (strpos($val, "\0") !== false) {
if (is_string($val) && strpos($val, "\0") !== false) {
$val = substr($val, 0, -1);
}
return $val;
}
protected function createStatement(\PDOStatement $stmt): PDOStatement
protected function createStatement(PDOStatement $stmt): BaseStatement
{
return new Statement($stmt);
}
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Driver\PDOSqlsrv;
use Doctrine\DBAL\Driver\AbstractSQLServerDriver;
use Doctrine\DBAL\Driver\AbstractSQLServerDriver\PortWithoutHost;
use Doctrine\DBAL\Driver\AbstractSQLServerDriver\Exception\PortWithoutHost;
use PDO;
use function is_int;
......
......@@ -2,14 +2,14 @@
namespace Doctrine\DBAL\Driver\PDOSqlsrv;
use Doctrine\DBAL\Driver\PDOStatement;
use Doctrine\DBAL\Driver\PDO\Statement as BaseStatement;
use Doctrine\DBAL\ParameterType;
use PDO;
/**
* PDO SQL Server Statement
*/
class Statement extends PDOStatement
class Statement extends BaseStatement
{
/**
* {@inheritdoc}
......
......@@ -2,11 +2,14 @@
namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\PDO\Exception;
use Doctrine\DBAL\Driver\PDO\Result;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\ParameterType;
use InvalidArgumentException;
use PDO;
use PDOException;
use function array_slice;
use function func_get_args;
......@@ -14,8 +17,10 @@ use function func_get_args;
/**
* The PDO implementation of the Statement interface.
* Used by all PDO-based drivers.
*
* @deprecated Use {@link Statement} instead
*/
class PDOStatement implements Statement
class PDOStatement implements StatementInterface
{
private const PARAM_TYPE_MAP = [
ParameterType::NULL => PDO::PARAM_NULL,
......@@ -43,8 +48,8 @@ class PDOStatement implements Statement
try {
return $this->stmt->bindValue($param, $value, $type);
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
......@@ -63,8 +68,8 @@ class PDOStatement implements Statement
try {
return $this->stmt->bindParam($column, $variable, $type, ...array_slice(func_get_args(), 3));
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}
......@@ -75,8 +80,8 @@ class PDOStatement implements Statement
{
try {
$this->stmt->execute($params);
} catch (\PDOException $exception) {
throw new PDOException($exception);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
return new Result($this->stmt);
......
......@@ -14,7 +14,7 @@ interface Result
*
* @return array<int,mixed>|false
*
* @throws DriverException
* @throws Exception
*/
public function fetchNumeric();
......@@ -23,7 +23,7 @@ interface Result
*
* @return array<string,mixed>|false
*
* @throws DriverException
* @throws Exception
*/
public function fetchAssociative();
......@@ -32,7 +32,7 @@ interface Result
*
* @return mixed|false
*
* @throws DriverException
* @throws Exception
*/
public function fetchOne();
......@@ -41,7 +41,7 @@ interface Result
*
* @return array<int,array<int,mixed>>
*
* @throws DriverException
* @throws Exception
*/
public function fetchAllNumeric(): array;
......@@ -50,7 +50,7 @@ interface Result
*
* @return array<int,array<string,mixed>>
*
* @throws DriverException
* @throws Exception
*/
public function fetchAllAssociative(): array;
......@@ -59,7 +59,7 @@ interface Result
*
* @return array<int,mixed>
*
* @throws DriverException
* @throws Exception
*/
public function fetchFirstColumn(): array;
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\SQLSrv;
final class Connection extends SQLSrvConnection
{
}
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\AbstractSQLServerDriver;
use Doctrine\DBAL\Driver\AbstractSQLServerDriver\PortWithoutHost;
use Doctrine\DBAL\Driver\AbstractSQLServerDriver\Exception\PortWithoutHost;
/**
* Driver for ext/sqlsrv.
......@@ -49,6 +49,6 @@ class Driver extends AbstractSQLServerDriver
$driverOptions['ReturnDatesAsStrings'] = 1;
}
return new SQLSrvConnection($serverName, $driverOptions);
return new Connection($serverName, $driverOptions);
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\SQLSrv\Exception;
use Doctrine\DBAL\Driver\SQLSrv\SQLSrvException;
use function rtrim;
use function sqlsrv_errors;
use const SQLSRV_ERR_ERRORS;
/**
* @internal
*
* @psalm-immutable
*/
final class Error extends SQLSrvException
{
public static function new(): self
{
$message = '';
$sqlState = null;
$errorCode = null;
foreach ((array) sqlsrv_errors(SQLSRV_ERR_ERRORS) as $error) {
$message .= 'SQLSTATE [' . $error['SQLSTATE'] . ', ' . $error['code'] . ']: ' . $error['message'] . "\n";
if ($sqlState === null) {
$sqlState = $error['SQLSTATE'];
}
if ($errorCode !== null) {
continue;
}
$errorCode = $error['code'];
}
if ($message === '') {
$message = 'SQL Server error occurred but no error message was retrieved from driver.';
}
return new self(rtrim($message), $sqlState, $errorCode);
}
}
......@@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\SQLSrv\Exception\Error;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\DBAL\ParameterType;
......@@ -22,6 +23,8 @@ use function str_replace;
/**
* SQL Server implementation for the Connection interface.
*
* @deprecated Use {@link Connection} instead
*/
class SQLSrvConnection implements ServerInfoAwareConnection
{
......@@ -40,13 +43,13 @@ class SQLSrvConnection implements ServerInfoAwareConnection
public function __construct($serverName, $connectionOptions)
{
if (! sqlsrv_configure('WarningsReturnAsErrors', 0)) {
throw SQLSrvException::fromSqlSrvErrors();
throw Error::new();
}
$conn = sqlsrv_connect($serverName, $connectionOptions);
if ($conn === false) {
throw SQLSrvException::fromSqlSrvErrors();
throw Error::new();
}
$this->conn = $conn;
......@@ -73,7 +76,7 @@ class SQLSrvConnection implements ServerInfoAwareConnection
public function prepare(string $sql): DriverStatement
{
return new SQLSrvStatement($this->conn, $sql, $this->lastInsertId);
return new Statement($this->conn, $sql, $this->lastInsertId);
}
public function query(string $sql): ResultInterface
......@@ -102,13 +105,13 @@ class SQLSrvConnection implements ServerInfoAwareConnection
$stmt = sqlsrv_query($this->conn, $statement);
if ($stmt === false) {
throw SQLSrvException::fromSqlSrvErrors();
throw Error::new();
}
$rowsAffected = sqlsrv_rows_affected($stmt);
if ($rowsAffected === false) {
throw SQLSrvException::fromSqlSrvErrors();
throw Error::new();
}
return $rowsAffected;
......@@ -135,7 +138,7 @@ class SQLSrvConnection implements ServerInfoAwareConnection
public function beginTransaction()
{
if (! sqlsrv_begin_transaction($this->conn)) {
throw SQLSrvException::fromSqlSrvErrors();
throw Error::new();
}
return true;
......@@ -147,7 +150,7 @@ class SQLSrvConnection implements ServerInfoAwareConnection
public function commit()
{
if (! sqlsrv_commit($this->conn)) {
throw SQLSrvException::fromSqlSrvErrors();
throw Error::new();
}
return true;
......@@ -159,7 +162,7 @@ class SQLSrvConnection implements ServerInfoAwareConnection
public function rollBack()
{
if (! sqlsrv_rollback($this->conn)) {
throw SQLSrvException::fromSqlSrvErrors();
throw Error::new();
}
return true;
......
......@@ -3,13 +3,11 @@
namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\AbstractDriverException;
use function rtrim;
use function sqlsrv_errors;
use const SQLSRV_ERR_ERRORS;
use Doctrine\DBAL\Driver\SQLSrv\Exception\Error;
/**
* @deprecated Use {@link Exception} instead
*
* @psalm-immutable
*/
class SQLSrvException extends AbstractDriverException
......@@ -21,28 +19,6 @@ class SQLSrvException extends AbstractDriverException
*/
public static function fromSqlSrvErrors()
{
$message = '';
$sqlState = null;
$errorCode = null;
foreach ((array) sqlsrv_errors(SQLSRV_ERR_ERRORS) as $error) {
$message .= 'SQLSTATE [' . $error['SQLSTATE'] . ', ' . $error['code'] . ']: ' . $error['message'] . "\n";
if ($sqlState === null) {
$sqlState = $error['SQLSTATE'];
}
if ($errorCode !== null) {
continue;
}
$errorCode = $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 Error::new();
}
}
......@@ -3,11 +3,12 @@
namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\SQLSrv\Exception\Error;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\ParameterType;
use function assert;
use function is_int;
use function is_numeric;
use function sqlsrv_execute;
use function sqlsrv_fetch;
use function sqlsrv_get_field;
......@@ -23,8 +24,10 @@ use const SQLSRV_PARAM_IN;
/**
* SQL Server Statement.
*
* @deprecated Use {@link Statement} instead
*/
final class SQLSrvStatement implements Statement
class SQLSrvStatement implements StatementInterface
{
/**
* The SQLSRV Resource.
......@@ -95,11 +98,7 @@ final class SQLSrvStatement implements Statement
*/
public function bindValue($param, $value, $type = ParameterType::STRING)
{
if (! is_numeric($param)) {
throw new SQLSrvException(
'sqlsrv does not support named parameters to queries, use question mark (?) placeholders instead.'
);
}
assert(is_int($param));
$this->variables[$param] = $value;
$this->types[$param] = $type;
......@@ -112,9 +111,7 @@ final class SQLSrvStatement implements Statement
*/
public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null)
{
if (! is_numeric($column)) {
throw new SQLSrvException('sqlsrv does not support named parameters to queries, use question mark (?) placeholders instead.');
}
assert(is_int($column));
$this->variables[$column] =& $variable;
$this->types[$column] = $type;
......@@ -145,7 +142,7 @@ final class SQLSrvStatement implements Statement
}
if (! sqlsrv_execute($this->stmt)) {
throw SQLSrvException::fromSqlSrvErrors();
throw Error::new();
}
if ($this->lastInsertId !== null) {
......@@ -196,7 +193,7 @@ final class SQLSrvStatement implements Statement
$stmt = sqlsrv_prepare($this->conn, $this->sql, $params);
if ($stmt === false) {
throw SQLSrvException::fromSqlSrvErrors();
throw Error::new();
}
return $stmt;
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver\SQLSrv;
class Statement extends SQLSrvStatement
{
}
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Driver\IBMDB2\DB2Driver;
use Doctrine\DBAL\Driver\IBMDB2\Driver as IBMDB2Driver;
use Doctrine\DBAL\Driver\Mysqli\Driver as MySQLiDriver;
use Doctrine\DBAL\Driver\OCI8\Driver as OCI8Driver;
use Doctrine\DBAL\Driver\PDOMySql\Driver as PDOMySQLDriver;
......@@ -47,7 +47,7 @@ final class DriverManager
'pdo_pgsql' => PDOPgSQLDriver::class,
'pdo_oci' => PDOOCIDriver::class,
'oci8' => OCI8Driver::class,
'ibm_db2' => DB2Driver::class,
'ibm_db2' => IBMDB2Driver::class,
'pdo_sqlsrv' => PDOSQLSrvDriver::class,
'mysqli' => MySQLiDriver::class,
'sqlsrv' => SQLSrvDriver::class,
......
......@@ -3,6 +3,7 @@
namespace Doctrine\DBAL\Exception;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\DriverException as DeprecatedDriverException;
use Exception;
/**
......@@ -15,15 +16,15 @@ class DriverException extends DBALException
/**
* The previous DBAL driver exception.
*
* @var \Doctrine\DBAL\Driver\DriverException
* @var DeprecatedDriverException
*/
private $driverException;
/**
* @param string $message The exception message.
* @param \Doctrine\DBAL\Driver\DriverException $driverException The DBAL driver exception to chain.
* @param string $message The exception message.
* @param DeprecatedDriverException $driverException The DBAL driver exception to chain.
*/
public function __construct($message, \Doctrine\DBAL\Driver\DriverException $driverException)
public function __construct($message, DeprecatedDriverException $driverException)
{
$exception = null;
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Types\Type;
use Throwable;
......@@ -37,7 +37,7 @@ class OracleSchemaManager extends AbstractSchemaManager
$exception = $exception->getPrevious();
assert($exception instanceof Throwable);
if (! $exception instanceof DriverException) {
if (! $exception instanceof Exception) {
throw $exception;
}
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Platforms\SQLServer2012Platform;
use Doctrine\DBAL\Types\Type;
use PDOException;
......@@ -34,7 +34,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager
$exception = $exception->getPrevious();
assert($exception instanceof Throwable);
if (! $exception instanceof DriverException) {
if (! $exception instanceof Exception) {
throw $exception;
}
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Tests\Driver;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\AbstractSQLServerDriver\PortWithoutHost;
use Doctrine\DBAL\Driver\AbstractSQLServerDriver\Exception\PortWithoutHost;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\SQLServer2012Platform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
......
......@@ -3,13 +3,13 @@
namespace Doctrine\DBAL\Tests\Driver\IBMDB2;
use Doctrine\DBAL\Driver as DriverInterface;
use Doctrine\DBAL\Driver\IBMDB2\DB2Driver;
use Doctrine\DBAL\Driver\IBMDB2\Driver;
use Doctrine\DBAL\Tests\Driver\AbstractDB2DriverTest;
class DB2DriverTest extends AbstractDB2DriverTest
{
protected function createDriver(): DriverInterface
{
return new DB2Driver();
return new Driver();
}
}
<?php
namespace Doctrine\DBAL\Tests\Driver;
namespace Doctrine\DBAL\Tests\Driver\PDO;
use Doctrine\DBAL\Driver\PDOException;
use Doctrine\DBAL\Driver\PDO\Exception;
use PDOException;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
/**
* @requires extension pdo
*/
class PDOExceptionTest extends TestCase
class ExceptionTest extends TestCase
{
public const ERROR_CODE = 666;
......@@ -20,14 +21,14 @@ class PDOExceptionTest extends TestCase
/**
* The PDO exception wrapper under test.
*
* @var PDOException
* @var Exception
*/
private $exception;
/**
* The wrapped PDO exception mock.
*
* @var \PDOException|MockObject
* @var PDOException|MockObject
*/
private $wrappedException;
......@@ -35,11 +36,11 @@ class PDOExceptionTest extends TestCase
{
parent::setUp();
$this->wrappedException = new \PDOException(self::MESSAGE, self::SQLSTATE);
$this->wrappedException = new PDOException(self::MESSAGE, self::SQLSTATE);
$this->wrappedException->errorInfo = [self::SQLSTATE, self::ERROR_CODE];
$this->exception = new PDOException($this->wrappedException);
$this->exception = new Exception($this->wrappedException);
}
public function testReturnsCode(): void
......
......@@ -5,7 +5,7 @@ namespace Doctrine\DBAL\Tests\Functional;
use DateTime;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\IBMDB2\DB2Driver;
use Doctrine\DBAL\Driver\IBMDB2\Driver as IBMDB2Driver;
use Doctrine\DBAL\Driver\Mysqli\Driver as MySQLiDriver;
use Doctrine\DBAL\Driver\SQLSrv\Driver as SQLSrvDriver;
use Doctrine\DBAL\ParameterType;
......@@ -204,7 +204,7 @@ class DataAccessTest extends FunctionalTestCase
}
if (
$this->connection->getDriver() instanceof DB2Driver
$this->connection->getDriver() instanceof IBMDB2Driver
) {
$this->markTestSkipped(
'ibm_ibm2 may or may not report the error depending on the PHP version and the connection state'
......
......@@ -2,8 +2,8 @@
namespace Doctrine\DBAL\Tests\Functional\Driver\IBMDB2;
use Doctrine\DBAL\Driver\IBMDB2\DB2Connection;
use Doctrine\DBAL\Driver\IBMDB2\DB2Driver;
use Doctrine\DBAL\Driver\IBMDB2\Connection;
use Doctrine\DBAL\Driver\IBMDB2\Driver;
use Doctrine\DBAL\Driver\IBMDB2\Exception\ConnectionFailed;
use Doctrine\DBAL\Driver\IBMDB2\Exception\PrepareFailed;
use Doctrine\DBAL\Tests\FunctionalTestCase;
......@@ -11,6 +11,7 @@ use ReflectionProperty;
use function db2_close;
use function extension_loaded;
use function get_parent_class;
class ConnectionTest extends FunctionalTestCase
{
......@@ -22,7 +23,7 @@ class ConnectionTest extends FunctionalTestCase
parent::setUp();
if ($this->connection->getDriver() instanceof DB2Driver) {
if ($this->connection->getDriver() instanceof Driver) {
return;
}
......@@ -37,14 +38,14 @@ class ConnectionTest extends FunctionalTestCase
public function testConnectionFailure(): void
{
$this->expectException(ConnectionFailed::class);
new DB2Connection('garbage', false, '', '');
new Connection('garbage', false, '', '');
}
public function testPrepareFailure(): void
{
$driverConnection = $this->connection->getWrappedConnection();
$re = new ReflectionProperty($driverConnection, 'conn');
$re = new ReflectionProperty(get_parent_class($driverConnection), 'conn');
$re->setAccessible(true);
$conn = $re->getValue($driverConnection);
db2_close($conn);
......
......@@ -8,7 +8,7 @@ use Doctrine\DBAL\Tests\Functional\Driver\AbstractDriverTest;
use function extension_loaded;
class DB2DriverTest extends AbstractDriverTest
class DriverTest extends AbstractDriverTest
{
protected function setUp(): void
{
......
......@@ -14,7 +14,7 @@ use const E_ALL;
use const E_NOTICE;
use const E_WARNING;
class DB2StatementTest extends FunctionalTestCase
class StatementTest extends FunctionalTestCase
{
protected function setUp(): void
{
......
......@@ -9,7 +9,7 @@ use Doctrine\DBAL\Tests\FunctionalTestCase;
use function extension_loaded;
class OCI8ConnectionTest extends FunctionalTestCase
class ConnectionTest extends FunctionalTestCase
{
/** @var OCI8Connection */
protected $driverConnection;
......
<?php
namespace Doctrine\DBAL\Tests\Functional\Driver;
namespace Doctrine\DBAL\Tests\Functional\Driver\PDO;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDOException;
use Doctrine\DBAL\Driver\PDO\Connection;
use Doctrine\DBAL\Driver\PDO\Exception;
use Doctrine\DBAL\Driver\PDOOracle\Driver as PDOOracleDriver;
use Doctrine\DBAL\Driver\PDOPgSql\Driver as PDOPgSQLDriver;
use Doctrine\DBAL\Driver\PDOSqlsrv\Driver as PDOSQLSRVDriver;
......@@ -16,12 +16,12 @@ use function sprintf;
/**
* @requires extension pdo
*/
class PDOConnectionTest extends FunctionalTestCase
class ConnectionTest extends FunctionalTestCase
{
/**
* The PDO driver connection under test.
*
* @var PDOConnection
* @var Connection
*/
protected $driverConnection;
......@@ -31,7 +31,7 @@ class PDOConnectionTest extends FunctionalTestCase
$this->driverConnection = $this->connection->getWrappedConnection();
if ($this->driverConnection instanceof PDOConnection) {
if ($this->driverConnection instanceof Connection) {
return;
}
......@@ -52,9 +52,9 @@ class PDOConnectionTest extends FunctionalTestCase
public function testThrowsWrappedExceptionOnConstruct(): void
{
$this->expectException(PDOException::class);
$this->expectException(Exception::class);
new PDOConnection('foo');
new Connection('foo');
}
/**
......@@ -62,7 +62,7 @@ class PDOConnectionTest extends FunctionalTestCase
*/
public function testThrowsWrappedExceptionOnExec(): void
{
$this->expectException(PDOException::class);
$this->expectException(Exception::class);
$this->driverConnection->exec('foo');
}
......@@ -94,14 +94,14 @@ class PDOConnectionTest extends FunctionalTestCase
->getWrappedConnection()
->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->expectException(PDOException::class);
$this->expectException(Exception::class);
$this->driverConnection->prepare('foo');
}
public function testThrowsWrappedExceptionOnQuery(): void
{
$this->expectException(PDOException::class);
$this->expectException(Exception::class);
$this->driverConnection->query('foo');
}
......
<?php
namespace Doctrine\DBAL\Tests\Functional\Driver;
namespace Doctrine\DBAL\Tests\Functional\Driver\PDOPgSql;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
......@@ -8,7 +8,7 @@ use Doctrine\DBAL\Tests\FunctionalTestCase;
use function extension_loaded;
class PDOPgsqlConnectionTest extends FunctionalTestCase
class ConnectionTest extends FunctionalTestCase
{
protected function setUp(): void
{
......
......@@ -3,14 +3,13 @@
namespace Doctrine\DBAL\Tests\Functional\Driver\PDOSqlsrv;
use Doctrine\DBAL\Driver as DriverInterface;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDO\Connection;
use Doctrine\DBAL\Driver\PDOSqlsrv\Driver;
use Doctrine\DBAL\Tests\Functional\Driver\AbstractDriverTest;
use Doctrine\DBAL\Tests\TestUtil;
use PDO;
use function array_merge;
use function assert;
use function extension_loaded;
class DriverTest extends AbstractDriverTest
......@@ -43,7 +42,7 @@ class DriverTest extends AbstractDriverTest
/**
* @param int[]|string[] $driverOptions
*/
private function getConnection(array $driverOptions): PDOConnection
private function getConnection(array $driverOptions): Connection
{
return $this->connection->getDriver()->connect(
array_merge(
......@@ -65,8 +64,6 @@ class DriverTest extends AbstractDriverTest
{
$connection = $this->getConnection([PDO::ATTR_CASE => PDO::CASE_UPPER]);
assert($connection instanceof PDOConnection);
self::assertSame(
PDO::CASE_UPPER,
$connection
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Tests\Functional\Ticket;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDO\Connection;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use Doctrine\DBAL\Tests\FunctionalTestCase;
......@@ -178,10 +178,10 @@ class DBAL630Test extends FunctionalTestCase
];
}
private function getWrappedConnection(): PDOConnection
private function getWrappedConnection(): Connection
{
$connection = $this->connection->getWrappedConnection();
self::assertInstanceOf(PDOConnection::class, $connection);
self::assertInstanceOf(Connection::class, $connection);
return $connection;
}
......
......@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Tests\Functional\Types;
use Doctrine\DBAL\Driver\IBMDB2\DB2Driver;
use Doctrine\DBAL\Driver\IBMDB2\Driver;
use Doctrine\DBAL\Driver\PDOOracle\Driver as PDOOracleDriver;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Table;
......@@ -46,7 +46,7 @@ class BinaryTest extends FunctionalTestCase
$value2 = random_bytes(64);
/** @see https://bugs.php.net/bug.php?id=76322 */
if ($this->connection->getDriver() instanceof DB2Driver) {
if ($this->connection->getDriver() instanceof Driver) {
$value1 = str_replace("\x00", "\xFF", $value1);
$value2 = str_replace("\x00", "\xFF", $value2);
}
......
......@@ -3,7 +3,7 @@
namespace Doctrine\DBAL\Tests\Functional;
use DateTime;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Table;
......@@ -343,13 +343,13 @@ class WriteTest extends FunctionalTestCase
*
* @return string|false
*
* @throws DriverException
* @throws Exception
*/
private function lastInsertId(?string $name = null)
{
try {
return $this->connection->lastInsertId($name);
} catch (DriverException $e) {
} catch (Exception $e) {
if ($e->getCode() === 'IM001') {
self::markTestSkipped($e->getMessage());
}
......
......@@ -2,7 +2,7 @@
namespace Doctrine\DBAL\Tests;
use Doctrine\DBAL\Driver\OCI8\OCI8Statement;
use Doctrine\DBAL\Driver\OCI8\Statement;
use PHPUnit\Framework\TestCase;
class UtilTest extends TestCase
......@@ -73,7 +73,7 @@ class UtilTest extends TestCase
*/
public function testConvertPositionalToNamedParameters(string $inputSQL, string $expectedOutputSQL, array $expectedOutputParamsMap): void
{
[$statement, $params] = OCI8Statement::convertPositionalToNamedPlaceholders($inputSQL);
[$statement, $params] = Statement::convertPositionalToNamedPlaceholders($inputSQL);
self::assertEquals($expectedOutputSQL, $statement);
self::assertEquals($expectedOutputParamsMap, $params);
......
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