From 5ca70c9babbb9ea939cf5c097c5e816892a77292 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Thu, 2 Jul 2020 18:32:28 -0700 Subject: [PATCH] PDO connection and statement classes made final --- UPGRADE.md | 5 ++ src/Driver/PDO/Connection.php | 5 +- src/Driver/PDO/Statement.php | 2 +- src/Driver/PDOSqlsrv/Connection.php | 90 +++++++++++++++---- src/Driver/PDOSqlsrv/Driver.php | 11 ++- src/Driver/PDOSqlsrv/Statement.php | 29 +++++- .../Driver/PDOSqlsrv/DriverTest.php | 2 +- 7 files changed, 117 insertions(+), 27 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index d47516fbefd..d37ba991e13 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,10 @@ # Upgrade to 3.0 +## BC BREAK: Changes in PDO driver classes + +1. The `PDO\Connection` and `PDO\Statement` classes have been made final. +2. The `PDOSqlsrv\Connection` and `PDOSqlsrv\Statement` classes have been made final and no longer extend the corresponding PDO classes. + ## BC BREAK: Changes in driver-level exception handling 1. The `convertException()` method has been removed from the `Driver` interface. The logic of exception conversion has been moved to the `ExceptionConverter` interface. The drivers now must implement the `getExceptionConverter()` method. diff --git a/src/Driver/PDO/Connection.php b/src/Driver/PDO/Connection.php index affa0ec345c..c643f3ce534 100644 --- a/src/Driver/PDO/Connection.php +++ b/src/Driver/PDO/Connection.php @@ -13,7 +13,7 @@ use function assert; -class Connection implements ServerInfoAwareConnection +final class Connection implements ServerInfoAwareConnection { /** @var PDO */ private $connection; @@ -57,6 +57,9 @@ public function getServerVersion() return $this->connection->getAttribute(PDO::ATTR_SERVER_VERSION); } + /** + * @return Statement + */ public function prepare(string $sql): StatementInterface { try { diff --git a/src/Driver/PDO/Statement.php b/src/Driver/PDO/Statement.php index 2751158da81..2de99d0b462 100644 --- a/src/Driver/PDO/Statement.php +++ b/src/Driver/PDO/Statement.php @@ -14,7 +14,7 @@ use function array_slice; use function func_get_args; -class Statement implements StatementInterface +final class Statement implements StatementInterface { private const PARAM_TYPE_MAP = [ ParameterType::NULL => PDO::PARAM_NULL, diff --git a/src/Driver/PDOSqlsrv/Connection.php b/src/Driver/PDOSqlsrv/Connection.php index fb3cacacbde..12585179153 100644 --- a/src/Driver/PDOSqlsrv/Connection.php +++ b/src/Driver/PDOSqlsrv/Connection.php @@ -2,27 +2,66 @@ namespace Doctrine\DBAL\Driver\PDOSqlsrv; -use Doctrine\DBAL\Driver\PDO\Connection as BaseConnection; -use Doctrine\DBAL\Driver\PDO\Statement as BaseStatement; +use Doctrine\DBAL\Driver\PDO\Connection as PDOConnection; +use Doctrine\DBAL\Driver\Result; +use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\Driver\Statement as StatementInterface; use Doctrine\DBAL\ParameterType; -use PDOStatement; +use PDO; use function is_string; use function strpos; use function substr; -/** - * Sqlsrv Connection implementation. - */ -class Connection extends BaseConnection +final class Connection implements ServerInfoAwareConnection { + /** @var PDOConnection */ + private $connection; + + public function __construct(PDOConnection $connection) + { + $this->connection = $connection; + } + + public function prepare(string $sql): StatementInterface + { + return new Statement( + $this->connection->prepare($sql) + ); + } + + public function query(string $sql): Result + { + return $this->connection->query($sql); + } + + /** + * {@inheritDoc} + */ + public function quote($value, $type = ParameterType::STRING) + { + $val = $this->connection->quote($value, $type); + + // Fix for a driver version terminating all values with null byte + if (is_string($val) && strpos($val, "\0") !== false) { + $val = substr($val, 0, -1); + } + + return $val; + } + + public function exec(string $statement): int + { + return $this->connection->exec($statement); + } + /** * {@inheritDoc} */ public function lastInsertId($name = null) { if ($name === null) { - return parent::lastInsertId($name); + return $this->connection->lastInsertId($name); } return $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?') @@ -33,20 +72,37 @@ public function lastInsertId($name = null) /** * {@inheritDoc} */ - public function quote($value, $type = ParameterType::STRING) + public function beginTransaction() { - $val = parent::quote($value, $type); + return $this->connection->beginTransaction(); + } - // Fix for a driver version terminating all values with null byte - if (is_string($val) && strpos($val, "\0") !== false) { - $val = substr($val, 0, -1); - } + /** + * {@inheritDoc} + */ + public function commit() + { + return $this->connection->commit(); + } - return $val; + /** + * {@inheritDoc} + */ + public function rollBack() + { + return $this->connection->rollBack(); + } + + /** + * {@inheritDoc} + */ + public function getServerVersion() + { + return $this->connection->getServerVersion(); } - protected function createStatement(PDOStatement $stmt): BaseStatement + public function getWrappedConnection(): PDO { - return new Statement($stmt); + return $this->connection->getWrappedConnection(); } } diff --git a/src/Driver/PDOSqlsrv/Driver.php b/src/Driver/PDOSqlsrv/Driver.php index 0bf15f39608..a74d2763d69 100644 --- a/src/Driver/PDOSqlsrv/Driver.php +++ b/src/Driver/PDOSqlsrv/Driver.php @@ -5,6 +5,7 @@ use Doctrine\DBAL\Driver\AbstractSQLServerDriver; use Doctrine\DBAL\Driver\AbstractSQLServerDriver\Exception\PortWithoutHost; use Doctrine\DBAL\Driver\Exception; +use Doctrine\DBAL\Driver\PDO\Connection as PDOConnection; use PDO; use function is_int; @@ -37,10 +38,12 @@ public function connect(array $params) } return new Connection( - $this->_constructPdoDsn($params, $dsnOptions), - $params['user'] ?? '', - $params['password'] ?? '', - $pdoOptions + new PDOConnection( + $this->_constructPdoDsn($params, $dsnOptions), + $params['user'] ?? '', + $params['password'] ?? '', + $pdoOptions + ) ); } diff --git a/src/Driver/PDOSqlsrv/Statement.php b/src/Driver/PDOSqlsrv/Statement.php index 7091eb375a3..e1a277dcf6f 100644 --- a/src/Driver/PDOSqlsrv/Statement.php +++ b/src/Driver/PDOSqlsrv/Statement.php @@ -2,17 +2,32 @@ namespace Doctrine\DBAL\Driver\PDOSqlsrv; -use Doctrine\DBAL\Driver\PDO\Statement as BaseStatement; +use Doctrine\DBAL\Driver\PDO\Statement as PDOStatement; +use Doctrine\DBAL\Driver\Result; +use Doctrine\DBAL\Driver\Statement as StatementInterface; use Doctrine\DBAL\ParameterType; use PDO; /** * PDO SQL Server Statement */ -class Statement extends BaseStatement +final class Statement implements StatementInterface { + /** @var PDOStatement */ + private $statement; + + /** + * @internal The statement can be only instantiated by its driver connection. + */ + public function __construct(PDOStatement $statement) + { + $this->statement = $statement; + } + /** * {@inheritdoc} + * + * @param mixed $driverOptions */ public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null) { @@ -23,7 +38,7 @@ public function bindParam($column, &$variable, $type = ParameterType::STRING, $l $driverOptions = PDO::SQLSRV_ENCODING_BINARY; } - return parent::bindParam($column, $variable, $type, $length, $driverOptions); + return $this->statement->bindParam($column, $variable, $type, $length, $driverOptions); } /** @@ -33,4 +48,12 @@ public function bindValue($param, $value, $type = ParameterType::STRING) { return $this->bindParam($param, $value, $type); } + + /** + * {@inheritdoc} + */ + public function execute($params = null): Result + { + return $this->statement->execute($params); + } } diff --git a/tests/Functional/Driver/PDOSqlsrv/DriverTest.php b/tests/Functional/Driver/PDOSqlsrv/DriverTest.php index db82f8e8a81..3bfb68e497f 100644 --- a/tests/Functional/Driver/PDOSqlsrv/DriverTest.php +++ b/tests/Functional/Driver/PDOSqlsrv/DriverTest.php @@ -3,7 +3,7 @@ namespace Doctrine\DBAL\Tests\Functional\Driver\PDOSqlsrv; use Doctrine\DBAL\Driver as DriverInterface; -use Doctrine\DBAL\Driver\PDO\Connection; +use Doctrine\DBAL\Driver\PDOSqlsrv\Connection; use Doctrine\DBAL\Driver\PDOSqlsrv\Driver; use Doctrine\DBAL\Tests\Functional\Driver\AbstractDriverTest; use Doctrine\DBAL\Tests\TestUtil;