From ba8ecfef2e1cfe015aab5483dddff7de59f29c10 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sat, 27 Nov 2021 02:12:31 +0100 Subject: [PATCH 1/3] Provide abstract middleware classes --- .../AbstractConnectionMiddleware.php | 97 +++++++++++++++++++ .../Middleware/AbstractDriverMiddleware.php | 61 ++++++++++++ .../Middleware/AbstractResultMiddleware.php | 79 +++++++++++++++ .../AbstractStatementMiddleware.php | 42 ++++++++ src/Logging/Connection.php | 63 +++--------- src/Logging/Driver.php | 48 +-------- src/Logging/Statement.php | 19 ++-- src/Portability/Connection.php | 84 ++-------------- src/Portability/Driver.php | 39 ++------ src/Portability/Result.php | 36 ++----- src/Portability/Statement.php | 28 +----- .../AbstractConnectionMiddlewareTest.php | 77 +++++++++++++++ .../AbstractDriverMiddlewareTest.php | 54 +++++++++++ .../AbstractResultMiddlewareTest.php | 27 ++++++ .../AbstractStatementMiddlewareTest.php | 29 ++++++ 15 files changed, 520 insertions(+), 263 deletions(-) create mode 100644 src/Driver/Middleware/AbstractConnectionMiddleware.php create mode 100644 src/Driver/Middleware/AbstractDriverMiddleware.php create mode 100644 src/Driver/Middleware/AbstractResultMiddleware.php create mode 100644 src/Driver/Middleware/AbstractStatementMiddleware.php create mode 100644 tests/Driver/Middleware/AbstractConnectionMiddlewareTest.php create mode 100644 tests/Driver/Middleware/AbstractDriverMiddlewareTest.php create mode 100644 tests/Driver/Middleware/AbstractResultMiddlewareTest.php create mode 100644 tests/Driver/Middleware/AbstractStatementMiddlewareTest.php diff --git a/src/Driver/Middleware/AbstractConnectionMiddleware.php b/src/Driver/Middleware/AbstractConnectionMiddleware.php new file mode 100644 index 00000000000..951e5f53adf --- /dev/null +++ b/src/Driver/Middleware/AbstractConnectionMiddleware.php @@ -0,0 +1,97 @@ +wrappedConnection = $wrappedConnection; + } + + public function prepare(string $sql): Statement + { + return $this->wrappedConnection->prepare($sql); + } + + public function query(string $sql): Result + { + return $this->wrappedConnection->query($sql); + } + + /** + * {@inheritdoc} + */ + public function quote($value, $type = ParameterType::STRING) + { + return $this->wrappedConnection->quote($value, $type); + } + + public function exec(string $sql): int + { + return $this->wrappedConnection->exec($sql); + } + + /** + * {@inheritdoc} + */ + public function lastInsertId($name = null) + { + if ($name !== null) { + Deprecation::triggerIfCalledFromOutside( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/issues/4687', + 'The usage of Connection::lastInsertId() with a sequence name is deprecated.' + ); + } + + return $this->wrappedConnection->lastInsertId($name); + } + + /** + * {@inheritdoc} + */ + public function beginTransaction() + { + return $this->wrappedConnection->beginTransaction(); + } + + /** + * {@inheritdoc} + */ + public function commit() + { + return $this->wrappedConnection->commit(); + } + + /** + * {@inheritdoc} + */ + public function rollBack() + { + return $this->wrappedConnection->rollBack(); + } + + /** + * {@inheritdoc} + */ + public function getServerVersion() + { + if (! $this->wrappedConnection instanceof ServerInfoAwareConnection) { + throw new LogicException('The underlying connection is not a ServerInfoAwareConnection'); + } + + return $this->wrappedConnection->getServerVersion(); + } +} diff --git a/src/Driver/Middleware/AbstractDriverMiddleware.php b/src/Driver/Middleware/AbstractDriverMiddleware.php new file mode 100644 index 00000000000..ab1f508f7ee --- /dev/null +++ b/src/Driver/Middleware/AbstractDriverMiddleware.php @@ -0,0 +1,61 @@ +wrappedDriver = $wrappedDriver; + } + + /** + * {@inheritdoc} + */ + public function connect(array $params) + { + return $this->wrappedDriver->connect($params); + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return $this->wrappedDriver->getDatabasePlatform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(Connection $conn, AbstractPlatform $platform) + { + return $this->wrappedDriver->getSchemaManager($conn, $platform); + } + + public function getExceptionConverter(): ExceptionConverter + { + return $this->wrappedDriver->getExceptionConverter(); + } + + /** + * {@inheritdoc} + */ + public function createDatabasePlatformForVersion($version) + { + if ($this->wrappedDriver instanceof VersionAwarePlatformDriver) { + return $this->wrappedDriver->createDatabasePlatformForVersion($version); + } + + return $this->wrappedDriver->getDatabasePlatform(); + } +} diff --git a/src/Driver/Middleware/AbstractResultMiddleware.php b/src/Driver/Middleware/AbstractResultMiddleware.php new file mode 100644 index 00000000000..ebc63c57078 --- /dev/null +++ b/src/Driver/Middleware/AbstractResultMiddleware.php @@ -0,0 +1,79 @@ +wrappedResult = $result; + } + + /** + * {@inheritdoc} + */ + public function fetchNumeric() + { + return $this->wrappedResult->fetchNumeric(); + } + + /** + * {@inheritdoc} + */ + public function fetchAssociative() + { + return $this->wrappedResult->fetchAssociative(); + } + + /** + * {@inheritdoc} + */ + public function fetchOne() + { + return $this->wrappedResult->fetchOne(); + } + + /** + * {@inheritdoc} + */ + public function fetchAllNumeric(): array + { + return $this->wrappedResult->fetchAllNumeric(); + } + + /** + * {@inheritdoc} + */ + public function fetchAllAssociative(): array + { + return $this->wrappedResult->fetchAllAssociative(); + } + + /** + * {@inheritdoc} + */ + public function fetchFirstColumn(): array + { + return $this->wrappedResult->fetchFirstColumn(); + } + + public function rowCount(): int + { + return $this->wrappedResult->rowCount(); + } + + public function columnCount(): int + { + return $this->wrappedResult->columnCount(); + } + + public function free(): void + { + $this->wrappedResult->free(); + } +} diff --git a/src/Driver/Middleware/AbstractStatementMiddleware.php b/src/Driver/Middleware/AbstractStatementMiddleware.php new file mode 100644 index 00000000000..a646cd30cb2 --- /dev/null +++ b/src/Driver/Middleware/AbstractStatementMiddleware.php @@ -0,0 +1,42 @@ +wrappedStatement = $wrappedStatement; + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = ParameterType::STRING) + { + return $this->wrappedStatement->bindValue($param, $value, $type); + } + + /** + * {@inheritdoc} + */ + public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null) + { + return $this->wrappedStatement->bindParam($param, $variable, $type, $length); + } + + /** + * {@inheritdoc} + */ + public function execute($params = null): Result + { + return $this->wrappedStatement->execute($params); + } +} diff --git a/src/Logging/Connection.php b/src/Logging/Connection.php index 9bb11ac0593..2175dc467df 100644 --- a/src/Logging/Connection.php +++ b/src/Logging/Connection.php @@ -5,19 +5,13 @@ namespace Doctrine\DBAL\Logging; use Doctrine\DBAL\Driver\Connection as ConnectionInterface; +use Doctrine\DBAL\Driver\Middleware\AbstractConnectionMiddleware; use Doctrine\DBAL\Driver\Result; -use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Driver\Statement as DriverStatement; -use Doctrine\DBAL\ParameterType; -use Doctrine\Deprecations\Deprecation; -use LogicException; use Psr\Log\LoggerInterface; -final class Connection implements ServerInfoAwareConnection +final class Connection extends AbstractConnectionMiddleware { - /** @var ConnectionInterface */ - private $connection; - /** @var LoggerInterface */ private $logger; @@ -26,8 +20,9 @@ final class Connection implements ServerInfoAwareConnection */ public function __construct(ConnectionInterface $connection, LoggerInterface $logger) { - $this->connection = $connection; - $this->logger = $logger; + parent::__construct($connection); + + $this->logger = $logger; } public function __destruct() @@ -38,7 +33,7 @@ public function __destruct() public function prepare(string $sql): DriverStatement { return new Statement( - $this->connection->prepare($sql), + parent::prepare($sql), $this->logger, $sql ); @@ -48,38 +43,14 @@ public function query(string $sql): Result { $this->logger->debug('Executing query: {sql}', ['sql' => $sql]); - return $this->connection->query($sql); - } - - /** - * {@inheritDoc} - */ - public function quote($value, $type = ParameterType::STRING) - { - return $this->connection->quote($value, $type); + return parent::query($sql); } public function exec(string $sql): int { $this->logger->debug('Executing statement: {sql}', ['sql' => $sql]); - return $this->connection->exec($sql); - } - - /** - * {@inheritDoc} - */ - public function lastInsertId($name = null) - { - if ($name !== null) { - Deprecation::triggerIfCalledFromOutside( - 'doctrine/dbal', - 'https://github.com/doctrine/dbal/issues/4687', - 'The usage of Connection::lastInsertId() with a sequence name is deprecated.' - ); - } - - return $this->connection->lastInsertId($name); + return parent::exec($sql); } /** @@ -89,7 +60,7 @@ public function beginTransaction() { $this->logger->debug('Beginning transaction'); - return $this->connection->beginTransaction(); + return parent::beginTransaction(); } /** @@ -99,7 +70,7 @@ public function commit() { $this->logger->debug('Committing transaction'); - return $this->connection->commit(); + return parent::commit(); } /** @@ -109,18 +80,6 @@ public function rollBack() { $this->logger->debug('Rolling back transaction'); - return $this->connection->rollBack(); - } - - /** - * {@inheritDoc} - */ - public function getServerVersion() - { - if (! $this->connection instanceof ServerInfoAwareConnection) { - throw new LogicException('The underlying connection is not a ServerInfoAwareConnection'); - } - - return $this->connection->getServerVersion(); + return parent::rollBack(); } } diff --git a/src/Logging/Driver.php b/src/Logging/Driver.php index 5ee12b4312a..12c8cffc6c5 100644 --- a/src/Logging/Driver.php +++ b/src/Logging/Driver.php @@ -4,18 +4,12 @@ namespace Doctrine\DBAL\Logging; -use Doctrine\DBAL\Connection as DBALConnection; use Doctrine\DBAL\Driver as DriverInterface; -use Doctrine\DBAL\Driver\API\ExceptionConverter; -use Doctrine\DBAL\Platforms\AbstractPlatform; -use Doctrine\DBAL\VersionAwarePlatformDriver; +use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware; use Psr\Log\LoggerInterface; -final class Driver implements VersionAwarePlatformDriver +final class Driver extends AbstractDriverMiddleware { - /** @var DriverInterface */ - private $driver; - /** @var LoggerInterface */ private $logger; @@ -24,7 +18,8 @@ final class Driver implements VersionAwarePlatformDriver */ public function __construct(DriverInterface $driver, LoggerInterface $logger) { - $this->driver = $driver; + parent::__construct($driver); + $this->logger = $logger; } @@ -36,44 +31,11 @@ public function connect(array $params) $this->logger->info('Connecting with parameters {params}', ['params' => $this->maskPassword($params)]); return new Connection( - $this->driver->connect($params), + parent::connect($params), $this->logger ); } - /** - * {@inheritDoc} - */ - public function getDatabasePlatform() - { - return $this->driver->getDatabasePlatform(); - } - - /** - * {@inheritDoc} - */ - public function getSchemaManager(DBALConnection $conn, AbstractPlatform $platform) - { - return $this->driver->getSchemaManager($conn, $platform); - } - - public function getExceptionConverter(): ExceptionConverter - { - return $this->driver->getExceptionConverter(); - } - - /** - * {@inheritDoc} - */ - public function createDatabasePlatformForVersion($version) - { - if ($this->driver instanceof VersionAwarePlatformDriver) { - return $this->driver->createDatabasePlatformForVersion($version); - } - - return $this->driver->getDatabasePlatform(); - } - /** * @param array $params Connection parameters * diff --git a/src/Logging/Statement.php b/src/Logging/Statement.php index 37ebf343da9..e993767aa08 100644 --- a/src/Logging/Statement.php +++ b/src/Logging/Statement.php @@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Logging; +use Doctrine\DBAL\Driver\Middleware\AbstractStatementMiddleware; use Doctrine\DBAL\Driver\Result as ResultInterface; use Doctrine\DBAL\Driver\Statement as StatementInterface; use Doctrine\DBAL\ParameterType; @@ -12,11 +13,8 @@ use function array_slice; use function func_get_args; -final class Statement implements StatementInterface +final class Statement extends AbstractStatementMiddleware { - /** @var StatementInterface */ - private $statement; - /** @var LoggerInterface */ private $logger; @@ -34,9 +32,10 @@ final class Statement implements StatementInterface */ public function __construct(StatementInterface $statement, LoggerInterface $logger, string $sql) { - $this->statement = $statement; - $this->logger = $logger; - $this->sql = $sql; + parent::__construct($statement); + + $this->logger = $logger; + $this->sql = $sql; } /** @@ -47,7 +46,7 @@ public function bindParam($param, &$variable, $type = ParameterType::STRING, $le $this->params[$param] = &$variable; $this->types[$param] = $type; - return $this->statement->bindParam($param, $variable, $type, ...array_slice(func_get_args(), 3)); + return parent::bindParam($param, $variable, $type, ...array_slice(func_get_args(), 3)); } /** @@ -58,7 +57,7 @@ public function bindValue($param, $value, $type = ParameterType::STRING) $this->params[$param] = $value; $this->types[$param] = $type; - return $this->statement->bindValue($param, $value, $type); + return parent::bindValue($param, $value, $type); } /** @@ -72,6 +71,6 @@ public function execute($params = null): ResultInterface 'types' => $this->types, ]); - return $this->statement->execute($params); + return parent::execute($params); } } diff --git a/src/Portability/Connection.php b/src/Portability/Connection.php index 9b9d8d09b6e..a22ab92ffc0 100644 --- a/src/Portability/Connection.php +++ b/src/Portability/Connection.php @@ -3,17 +3,14 @@ namespace Doctrine\DBAL\Portability; use Doctrine\DBAL\Driver\Connection as ConnectionInterface; +use Doctrine\DBAL\Driver\Middleware\AbstractConnectionMiddleware; use Doctrine\DBAL\Driver\Result as DriverResult; -use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Driver\Statement as DriverStatement; -use Doctrine\DBAL\ParameterType; -use Doctrine\Deprecations\Deprecation; -use LogicException; /** * Portability wrapper for a Connection. */ -final class Connection implements ServerInfoAwareConnection +final class Connection extends AbstractConnectionMiddleware { public const PORTABILITY_ALL = 255; public const PORTABILITY_NONE = 0; @@ -21,22 +18,20 @@ final class Connection implements ServerInfoAwareConnection public const PORTABILITY_EMPTY_TO_NULL = 4; public const PORTABILITY_FIX_CASE = 8; - /** @var ConnectionInterface */ - private $connection; - /** @var Converter */ private $converter; public function __construct(ConnectionInterface $connection, Converter $converter) { - $this->connection = $connection; - $this->converter = $converter; + parent::__construct($connection); + + $this->converter = $converter; } public function prepare(string $sql): DriverStatement { return new Statement( - $this->connection->prepare($sql), + parent::prepare($sql), $this->converter ); } @@ -44,73 +39,8 @@ public function prepare(string $sql): DriverStatement public function query(string $sql): DriverResult { return new Result( - $this->connection->query($sql), + parent::query($sql), $this->converter ); } - - /** - * {@inheritDoc} - */ - public function quote($value, $type = ParameterType::STRING) - { - return $this->connection->quote($value, $type); - } - - public function exec(string $sql): int - { - return $this->connection->exec($sql); - } - - /** - * {@inheritDoc} - */ - public function lastInsertId($name = null) - { - if ($name !== null) { - Deprecation::triggerIfCalledFromOutside( - 'doctrine/dbal', - 'https://github.com/doctrine/dbal/issues/4687', - 'The usage of Connection::lastInsertId() with a sequence name is deprecated.' - ); - } - - return $this->connection->lastInsertId($name); - } - - /** - * {@inheritDoc} - */ - public function beginTransaction() - { - return $this->connection->beginTransaction(); - } - - /** - * {@inheritDoc} - */ - public function commit() - { - return $this->connection->commit(); - } - - /** - * {@inheritDoc} - */ - public function rollBack() - { - return $this->connection->rollBack(); - } - - /** - * {@inheritDoc} - */ - public function getServerVersion() - { - if (! $this->connection instanceof ServerInfoAwareConnection) { - throw new LogicException('The underlying connection is not a ServerInfoAwareConnection'); - } - - return $this->connection->getServerVersion(); - } } diff --git a/src/Portability/Driver.php b/src/Portability/Driver.php index 5ae410cd005..7ea0a5aaed8 100644 --- a/src/Portability/Driver.php +++ b/src/Portability/Driver.php @@ -3,20 +3,15 @@ namespace Doctrine\DBAL\Portability; use Doctrine\DBAL\ColumnCase; -use Doctrine\DBAL\Connection as DBALConnection; use Doctrine\DBAL\Driver as DriverInterface; -use Doctrine\DBAL\Driver\API\ExceptionConverter; +use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware; use Doctrine\DBAL\Driver\PDO; -use Doctrine\DBAL\Platforms\AbstractPlatform; use const CASE_LOWER; use const CASE_UPPER; -final class Driver implements DriverInterface +final class Driver extends AbstractDriverMiddleware { - /** @var DriverInterface */ - private $driver; - /** @var int */ private $mode; @@ -25,9 +20,10 @@ final class Driver implements DriverInterface public function __construct(DriverInterface $driver, int $mode, int $case) { - $this->driver = $driver; - $this->mode = $mode; - $this->case = $case; + parent::__construct($driver); + + $this->mode = $mode; + $this->case = $case; } /** @@ -35,7 +31,7 @@ public function __construct(DriverInterface $driver, int $mode, int $case) */ public function connect(array $params) { - $connection = $this->driver->connect($params); + $connection = parent::connect($params); $portability = (new OptimizeFlags())( $this->getDatabasePlatform(), @@ -66,25 +62,4 @@ public function connect(array $params) new Converter($convertEmptyStringToNull, $rightTrimString, $case) ); } - - /** - * {@inheritDoc} - */ - public function getDatabasePlatform() - { - return $this->driver->getDatabasePlatform(); - } - - /** - * {@inheritDoc} - */ - public function getSchemaManager(DBALConnection $conn, AbstractPlatform $platform) - { - return $this->driver->getSchemaManager($conn, $platform); - } - - public function getExceptionConverter(): ExceptionConverter - { - return $this->driver->getExceptionConverter(); - } } diff --git a/src/Portability/Result.php b/src/Portability/Result.php index 1fa91ab4813..d8440b66318 100644 --- a/src/Portability/Result.php +++ b/src/Portability/Result.php @@ -4,13 +4,11 @@ namespace Doctrine\DBAL\Portability; +use Doctrine\DBAL\Driver\Middleware\AbstractResultMiddleware; use Doctrine\DBAL\Driver\Result as ResultInterface; -final class Result implements ResultInterface +final class Result extends AbstractResultMiddleware { - /** @var ResultInterface */ - private $result; - /** @var Converter */ private $converter; @@ -19,7 +17,8 @@ final class Result implements ResultInterface */ public function __construct(ResultInterface $result, Converter $converter) { - $this->result = $result; + parent::__construct($result); + $this->converter = $converter; } @@ -29,7 +28,7 @@ public function __construct(ResultInterface $result, Converter $converter) public function fetchNumeric() { return $this->converter->convertNumeric( - $this->result->fetchNumeric() + parent::fetchNumeric() ); } @@ -39,7 +38,7 @@ public function fetchNumeric() public function fetchAssociative() { return $this->converter->convertAssociative( - $this->result->fetchAssociative() + parent::fetchAssociative() ); } @@ -49,7 +48,7 @@ public function fetchAssociative() public function fetchOne() { return $this->converter->convertOne( - $this->result->fetchOne() + parent::fetchOne() ); } @@ -59,7 +58,7 @@ public function fetchOne() public function fetchAllNumeric(): array { return $this->converter->convertAllNumeric( - $this->result->fetchAllNumeric() + parent::fetchAllNumeric() ); } @@ -69,7 +68,7 @@ public function fetchAllNumeric(): array public function fetchAllAssociative(): array { return $this->converter->convertAllAssociative( - $this->result->fetchAllAssociative() + parent::fetchAllAssociative() ); } @@ -79,22 +78,7 @@ public function fetchAllAssociative(): array public function fetchFirstColumn(): array { return $this->converter->convertFirstColumn( - $this->result->fetchFirstColumn() + parent::fetchFirstColumn() ); } - - public function rowCount(): int - { - return $this->result->rowCount(); - } - - public function columnCount(): int - { - return $this->result->columnCount(); - } - - public function free(): void - { - $this->result->free(); - } } diff --git a/src/Portability/Statement.php b/src/Portability/Statement.php index f3f94e413e5..b104cf78af2 100644 --- a/src/Portability/Statement.php +++ b/src/Portability/Statement.php @@ -2,18 +2,15 @@ namespace Doctrine\DBAL\Portability; +use Doctrine\DBAL\Driver\Middleware\AbstractStatementMiddleware; use Doctrine\DBAL\Driver\Result as ResultInterface; use Doctrine\DBAL\Driver\Statement as DriverStatement; -use Doctrine\DBAL\ParameterType; /** * Portability wrapper for a Statement. */ -final class Statement implements DriverStatement +final class Statement extends AbstractStatementMiddleware { - /** @var DriverStatement */ - private $stmt; - /** @var Converter */ private $converter; @@ -22,24 +19,9 @@ final class Statement implements DriverStatement */ public function __construct(DriverStatement $stmt, Converter $converter) { - $this->stmt = $stmt; - $this->converter = $converter; - } - - /** - * {@inheritdoc} - */ - public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null) - { - return $this->stmt->bindParam($param, $variable, $type, $length); - } + parent::__construct($stmt); - /** - * {@inheritdoc} - */ - public function bindValue($param, $value, $type = ParameterType::STRING) - { - return $this->stmt->bindValue($param, $value, $type); + $this->converter = $converter; } /** @@ -48,7 +30,7 @@ public function bindValue($param, $value, $type = ParameterType::STRING) public function execute($params = null): ResultInterface { return new Result( - $this->stmt->execute($params), + parent::execute($params), $this->converter ); } diff --git a/tests/Driver/Middleware/AbstractConnectionMiddlewareTest.php b/tests/Driver/Middleware/AbstractConnectionMiddlewareTest.php new file mode 100644 index 00000000000..5f3b924c2e2 --- /dev/null +++ b/tests/Driver/Middleware/AbstractConnectionMiddlewareTest.php @@ -0,0 +1,77 @@ +createMock(Statement::class); + $connection = $this->createMock(Connection::class); + $connection->expects(self::once()) + ->method('prepare') + ->with('SELECT 1') + ->willReturn($statement); + + self::assertSame($statement, $this->createMiddleware($connection)->prepare('SELECT 1')); + } + + public function testQuery(): void + { + $result = $this->createMock(Result::class); + $connection = $this->createMock(Connection::class); + $connection->expects(self::once()) + ->method('query') + ->with('SELECT 1') + ->willReturn($result); + + self::assertSame($result, $this->createMiddleware($connection)->query('SELECT 1')); + } + + public function testExec(): void + { + $connection = $this->createMock(Connection::class); + $connection->expects(self::once()) + ->method('exec') + ->with('UPDATE foo SET bar=\'baz\' WHERE some_field > 0') + ->willReturn(42); + + self::assertSame( + 42, + $this->createMiddleware($connection)->exec('UPDATE foo SET bar=\'baz\' WHERE some_field > 0') + ); + } + + public function testGetServerVersion(): void + { + $connection = $this->createMock(ServerInfoAwareConnection::class); + $connection->expects(self::once()) + ->method('getServerVersion') + ->willReturn('1.2.3'); + + self::assertSame('1.2.3', $this->createMiddleware($connection)->getServerVersion()); + } + + public function testGetServerVersionFailsOnLegacyConnections(): void + { + $connection = $this->createMock(Connection::class); + $middleware = $this->createMiddleware($connection); + + $this->expectException(LogicException::class); + $middleware->getServerVersion(); + } + + private function createMiddleware(Connection $connection): AbstractConnectionMiddleware + { + return new class ($connection) extends AbstractConnectionMiddleware { + }; + } +} diff --git a/tests/Driver/Middleware/AbstractDriverMiddlewareTest.php b/tests/Driver/Middleware/AbstractDriverMiddlewareTest.php new file mode 100644 index 00000000000..600cdfd0e83 --- /dev/null +++ b/tests/Driver/Middleware/AbstractDriverMiddlewareTest.php @@ -0,0 +1,54 @@ +createMock(Connection::class); + $driver = $this->createMock(Driver::class); + $driver->expects(self::once()) + ->method('connect') + ->with(['foo' => 'bar']) + ->willReturn($connection); + + self::assertSame($connection, $this->createMiddleware($driver)->connect(['foo' => 'bar'])); + } + + public function testCreateDatabasePlatformForVersion(): void + { + $platform = $this->createMock(AbstractPlatform::class); + $driver = $this->createMock(VersionAwarePlatformDriver::class); + $driver->expects(self::once()) + ->method('createDatabasePlatformForVersion') + ->with('1.2.3') + ->willReturn($platform); + + self::assertSame($platform, $this->createMiddleware($driver)->createDatabasePlatformForVersion('1.2.3')); + } + + public function testCreateDatabasePlatformForVersionWithLegacyDriver(): void + { + $platform = $this->createMock(AbstractPlatform::class); + $driver = $this->createMock(Driver::class); + $driver->expects(self::once()) + ->method('getDatabasePlatform') + ->willReturn($platform); + + self::assertSame($platform, $this->createMiddleware($driver)->createDatabasePlatformForVersion('1.2.3')); + } + + private function createMiddleware(Driver $driver): AbstractDriverMiddleware + { + return new class ($driver) extends AbstractDriverMiddleware { + }; + } +} diff --git a/tests/Driver/Middleware/AbstractResultMiddlewareTest.php b/tests/Driver/Middleware/AbstractResultMiddlewareTest.php new file mode 100644 index 00000000000..dfa10cc3f2a --- /dev/null +++ b/tests/Driver/Middleware/AbstractResultMiddlewareTest.php @@ -0,0 +1,27 @@ + 'value', 'another_field' => 42]; + $result = $this->createMock(Result::class); + $result->expects(self::once()) + ->method('fetchAssociative') + ->willReturn($row); + + self::assertSame($row, $this->createMiddleware($result)->fetchAssociative()); + } + + private function createMiddleware(Result $result): AbstractResultMiddleware + { + return new class ($result) extends AbstractResultMiddleware { + }; + } +} diff --git a/tests/Driver/Middleware/AbstractStatementMiddlewareTest.php b/tests/Driver/Middleware/AbstractStatementMiddlewareTest.php new file mode 100644 index 00000000000..2aeb15cbbd1 --- /dev/null +++ b/tests/Driver/Middleware/AbstractStatementMiddlewareTest.php @@ -0,0 +1,29 @@ +createMock(Result::class); + $statement = $this->createMock(Statement::class); + $statement->expects(self::once()) + ->method('execute') + ->with(['foo' => 'bar']) + ->willReturn($result); + + self::assertSame($result, $this->createMiddleware($statement)->execute(['foo' => 'bar'])); + } + + private function createMiddleware(Statement $statement): AbstractStatementMiddleware + { + return new class ($statement) extends AbstractStatementMiddleware { + }; + } +} From d9f969b366fcd4c7def89372b9c198edb2cc9fe5 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sat, 27 Nov 2021 15:34:38 +0100 Subject: [PATCH 2/3] Add Connection::getNativeConnection() --- UPGRADE.md | 17 +++++++ phpstan.neon.dist | 4 ++ psalm.xml.dist | 4 ++ src/Connection.php | 21 +++++++++ src/Driver/Connection.php | 2 + src/Driver/IBMDB2/Connection.php | 8 ++++ .../AbstractConnectionMiddleware.php | 19 ++++++++ src/Driver/Mysqli/Connection.php | 16 ++++++- src/Driver/OCI8/Connection.php | 8 ++++ src/Driver/PDO/Connection.php | 17 ++++++- src/Driver/PDO/SQLSrv/Connection.php | 15 ++++++ src/Driver/SQLSrv/Connection.php | 10 +++- src/Portability/Driver.php | 18 ++++++-- .../AbstractConnectionMiddlewareTest.php | 29 ++++++++++++ tests/Driver/PDO/PgSQL/DriverTest.php | 6 +-- tests/Functional/ConnectionTest.php | 2 +- .../Functional/Driver/AbstractDriverTest.php | 11 +++++ .../Driver/PDO/SQLSrv/DriverTest.php | 2 +- tests/Portability/ConnectionTest.php | 46 +++++++++++++++++++ 19 files changed, 243 insertions(+), 12 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index e51562bd0ab..a2a12be1caf 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -6,6 +6,23 @@ awareness about deprecated code. - Use of our low-overhead runtime deprecation API, details: https://github.com/doctrine/deprecations/ +# Upgrade to 3.3 + +## Add `Connection::getNativeConnection()` + +Driver and middleware connections need to implement a new method `getNativeConnection()` that gives access to the +native database connection. Not doing so is deprecated. + +## Deprecate accessors for the native connection in favor of `getNativeConnection()` + +The following methods have been deprecated: + +* `Doctrine\DBAL\Driver\PDO\Connection::getWrappedConnection()` +* `Doctrine\DBAL\Driver\PDO\SQLSrv\Connection::getWrappedConnection()` +* `Doctrine\DBAL\Driver\Mysqli\Connection::getWrappedResourceHandle()` + +Call `getNativeConnection()` to access the underlying PDO or MySQLi connection. + # Upgrade to 3.2 ## Deprecated `SQLLogger` and its implementations. diff --git a/phpstan.neon.dist b/phpstan.neon.dist index eacfb26a4ea..90ce2f50d66 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -141,5 +141,9 @@ parameters: message: '~Method Doctrine\\DBAL\\Driver\\Mysqli\\Result::rowCount\(\) should return int but returns int\|string\.~' paths: - src/Driver/Mysqli/Result.php + + # Type check for legacy implementations of the Connection interface + # TODO: remove in 4.0.0 + - "~Call to function method_exists\\(\\) with Doctrine\\\\DBAL\\\\Driver\\\\Connection and 'getNativeConnection' will always evaluate to true\\.~" includes: - vendor/phpstan/phpstan-strict-rules/rules.neon diff --git a/psalm.xml.dist b/psalm.xml.dist index 4b194dda9f3..b12b1af3446 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -194,6 +194,9 @@ See https://github.com/doctrine/dbal/pull/4897 --> + + + @@ -376,6 +379,7 @@ or breaking API changes. --> + diff --git a/src/Connection.php b/src/Connection.php index 32ed3aa1d89..1a32d12fded 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -24,6 +24,7 @@ use Doctrine\DBAL\SQL\Parser; use Doctrine\DBAL\Types\Type; use Doctrine\Deprecations\Deprecation; +use LogicException; use Throwable; use Traversable; @@ -34,6 +35,8 @@ use function is_int; use function is_string; use function key; +use function method_exists; +use function sprintf; /** * A database abstraction-level connection that implements features like events, transaction isolation levels, @@ -1511,6 +1514,24 @@ public function getWrappedConnection() return $this->_conn; } + /** + * @return resource|object + */ + public function getNativeConnection() + { + $this->connect(); + + assert($this->_conn !== null); + if (! method_exists($this->_conn, 'getNativeConnection')) { + throw new LogicException(sprintf( + 'The driver connection %s does not support accessing the native connection.', + get_class($this->_conn) + )); + } + + return $this->_conn->getNativeConnection(); + } + /** * Creates a SchemaManager that can be used to inspect or change the * database schema through the connection. diff --git a/src/Driver/Connection.php b/src/Driver/Connection.php index 3ececce156e..a129a7c8b6a 100644 --- a/src/Driver/Connection.php +++ b/src/Driver/Connection.php @@ -7,6 +7,8 @@ /** * Connection interface. * Driver connections must implement this interface. + * + * @method resource|object getNativeConnection() */ interface Connection { diff --git a/src/Driver/IBMDB2/Connection.php b/src/Driver/IBMDB2/Connection.php index fe7906e95f4..4f2a2926696 100644 --- a/src/Driver/IBMDB2/Connection.php +++ b/src/Driver/IBMDB2/Connection.php @@ -142,4 +142,12 @@ public function rollBack(): bool return $result; } + + /** + * @return resource + */ + public function getNativeConnection() + { + return $this->connection; + } } diff --git a/src/Driver/Middleware/AbstractConnectionMiddleware.php b/src/Driver/Middleware/AbstractConnectionMiddleware.php index 951e5f53adf..a0e69a5e779 100644 --- a/src/Driver/Middleware/AbstractConnectionMiddleware.php +++ b/src/Driver/Middleware/AbstractConnectionMiddleware.php @@ -10,6 +10,10 @@ use Doctrine\Deprecations\Deprecation; use LogicException; +use function get_class; +use function method_exists; +use function sprintf; + abstract class AbstractConnectionMiddleware implements ServerInfoAwareConnection { /** @var Connection */ @@ -94,4 +98,19 @@ public function getServerVersion() return $this->wrappedConnection->getServerVersion(); } + + /** + * @return resource|object + */ + public function getNativeConnection() + { + if (! method_exists($this->wrappedConnection, 'getNativeConnection')) { + throw new LogicException(sprintf( + 'The driver connection %s does not support accessing the native connection.', + get_class($this->wrappedConnection) + )); + } + + return $this->wrappedConnection->getNativeConnection(); + } } diff --git a/src/Driver/Mysqli/Connection.php b/src/Driver/Mysqli/Connection.php index fce300a8870..df2729be9dc 100644 --- a/src/Driver/Mysqli/Connection.php +++ b/src/Driver/Mysqli/Connection.php @@ -36,10 +36,19 @@ public function __construct(mysqli $connection) * Retrieves mysqli native resource handle. * * Could be used if part of your application is not using DBAL. + * + * @deprecated Call {@see getNativeConnection()} instead. */ public function getWrappedResourceHandle(): mysqli { - return $this->connection; + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/5037', + '%s is deprecated, call getNativeConnection() instead.', + __METHOD__ + ); + + return $this->getNativeConnection(); } /** @@ -147,4 +156,9 @@ public function rollBack(): bool return false; } } + + public function getNativeConnection(): mysqli + { + return $this->connection; + } } diff --git a/src/Driver/OCI8/Connection.php b/src/Driver/OCI8/Connection.php index 72bcec4ac6f..46ff4186691 100644 --- a/src/Driver/OCI8/Connection.php +++ b/src/Driver/OCI8/Connection.php @@ -166,4 +166,12 @@ public function rollBack(): bool return true; } + + /** + * @return resource + */ + public function getNativeConnection() + { + return $this->connection; + } } diff --git a/src/Driver/PDO/Connection.php b/src/Driver/PDO/Connection.php index 8165799caf4..505acba5f0b 100644 --- a/src/Driver/PDO/Connection.php +++ b/src/Driver/PDO/Connection.php @@ -123,8 +123,23 @@ public function rollBack(): bool return $this->connection->rollBack(); } - public function getWrappedConnection(): PDO + public function getNativeConnection(): PDO { return $this->connection; } + + /** + * @deprecated Call {@see getNativeConnection()} instead. + */ + public function getWrappedConnection(): PDO + { + Deprecation::triggerIfCalledFromOutside( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/5037', + '%s is deprecated, call getNativeConnection() instead.', + __METHOD__ + ); + + return $this->getNativeConnection(); + } } diff --git a/src/Driver/PDO/SQLSrv/Connection.php b/src/Driver/PDO/SQLSrv/Connection.php index c08b236c2ac..1ab904bdbf9 100644 --- a/src/Driver/PDO/SQLSrv/Connection.php +++ b/src/Driver/PDO/SQLSrv/Connection.php @@ -88,8 +88,23 @@ public function getServerVersion() return $this->connection->getServerVersion(); } + public function getNativeConnection(): PDO + { + return $this->connection->getNativeConnection(); + } + + /** + * @deprecated Call {@see getNativeConnection()} instead. + */ public function getWrappedConnection(): PDO { + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/5037', + '%s is deprecated, call getNativeConnection() instead.', + __METHOD__ + ); + return $this->connection->getWrappedConnection(); } } diff --git a/src/Driver/SQLSrv/Connection.php b/src/Driver/SQLSrv/Connection.php index 62a65379750..0295db7e5b0 100644 --- a/src/Driver/SQLSrv/Connection.php +++ b/src/Driver/SQLSrv/Connection.php @@ -23,7 +23,7 @@ final class Connection implements ServerInfoAwareConnection { /** @var resource */ - protected $connection; + private $connection; /** * @internal The connection can be only instantiated by its driver. @@ -135,4 +135,12 @@ public function rollBack(): bool return true; } + + /** + * @return resource + */ + public function getNativeConnection() + { + return $this->connection; + } } diff --git a/src/Portability/Driver.php b/src/Portability/Driver.php index 7ea0a5aaed8..65cd056e71b 100644 --- a/src/Portability/Driver.php +++ b/src/Portability/Driver.php @@ -5,7 +5,10 @@ use Doctrine\DBAL\ColumnCase; use Doctrine\DBAL\Driver as DriverInterface; use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware; -use Doctrine\DBAL\Driver\PDO; +use LogicException; +use PDO; + +use function method_exists; use const CASE_LOWER; use const CASE_UPPER; @@ -41,10 +44,17 @@ public function connect(array $params) $case = 0; if ($this->case !== 0 && ($portability & Connection::PORTABILITY_FIX_CASE) !== 0) { - if ($connection instanceof PDO\Connection) { - // make use of c-level support for case handling + $nativeConnection = null; + if (method_exists($connection, 'getNativeConnection')) { + try { + $nativeConnection = $connection->getNativeConnection(); + } catch (LogicException $e) { + } + } + + if ($nativeConnection instanceof PDO) { $portability &= ~Connection::PORTABILITY_FIX_CASE; - $connection->getWrappedConnection()->setAttribute(\PDO::ATTR_CASE, $this->case); + $nativeConnection->setAttribute(PDO::ATTR_CASE, $this->case); } else { $case = $this->case === ColumnCase::LOWER ? CASE_LOWER : CASE_UPPER; } diff --git a/tests/Driver/Middleware/AbstractConnectionMiddlewareTest.php b/tests/Driver/Middleware/AbstractConnectionMiddlewareTest.php index 5f3b924c2e2..80e1e34a777 100644 --- a/tests/Driver/Middleware/AbstractConnectionMiddlewareTest.php +++ b/tests/Driver/Middleware/AbstractConnectionMiddlewareTest.php @@ -69,9 +69,38 @@ public function testGetServerVersionFailsOnLegacyConnections(): void $middleware->getServerVersion(); } + public function testGetNativeConnection(): void + { + $nativeConnection = new class () { + }; + + $connection = $this->createMock(NativeDriverConnection::class); + $connection->method('getNativeConnection') + ->willReturn($nativeConnection); + + self::assertSame($nativeConnection, $this->createMiddleware($connection)->getNativeConnection()); + } + + public function testGetNativeConnectionFailsWithLegacyConnection(): void + { + $connection = $this->createMock(Connection::class); + $middleware = $this->createMiddleware($connection); + + $this->expectException(LogicException::class); + $middleware->getNativeConnection(); + } + private function createMiddleware(Connection $connection): AbstractConnectionMiddleware { return new class ($connection) extends AbstractConnectionMiddleware { }; } } + +interface NativeDriverConnection extends ServerInfoAwareConnection +{ + /** + * @return object|resource + */ + public function getNativeConnection(); +} diff --git a/tests/Driver/PDO/PgSQL/DriverTest.php b/tests/Driver/PDO/PgSQL/DriverTest.php index 50e9fc08696..2dfb3fa1609 100644 --- a/tests/Driver/PDO/PgSQL/DriverTest.php +++ b/tests/Driver/PDO/PgSQL/DriverTest.php @@ -30,7 +30,7 @@ public function testConnectionDisablesPrepares(): void self::assertInstanceOf(PDO\Connection::class, $connection); self::assertTrue( - $connection->getWrappedConnection()->getAttribute(\PDO::PGSQL_ATTR_DISABLE_PREPARES) + $connection->getNativeConnection()->getAttribute(\PDO::PGSQL_ATTR_DISABLE_PREPARES) ); } @@ -42,7 +42,7 @@ public function testConnectionDoesNotDisablePreparesWhenAttributeDefined(): void self::assertInstanceOf(PDO\Connection::class, $connection); self::assertNotTrue( - $connection->getWrappedConnection()->getAttribute(\PDO::PGSQL_ATTR_DISABLE_PREPARES) + $connection->getNativeConnection()->getAttribute(\PDO::PGSQL_ATTR_DISABLE_PREPARES) ); } @@ -54,7 +54,7 @@ public function testConnectionDisablePreparesWhenDisablePreparesIsExplicitlyDefi self::assertInstanceOf(PDO\Connection::class, $connection); self::assertTrue( - $connection->getWrappedConnection()->getAttribute(\PDO::PGSQL_ATTR_DISABLE_PREPARES) + $connection->getNativeConnection()->getAttribute(\PDO::PGSQL_ATTR_DISABLE_PREPARES) ); } diff --git a/tests/Functional/ConnectionTest.php b/tests/Functional/ConnectionTest.php index 68e13d50966..226c1aca592 100644 --- a/tests/Functional/ConnectionTest.php +++ b/tests/Functional/ConnectionTest.php @@ -386,7 +386,7 @@ public function testPersistentConnection(): void self::markTestSkipped('Unable to test if the connection is persistent'); } - $pdo = $driverConnection->getWrappedConnection(); + $pdo = $driverConnection->getNativeConnection(); self::assertTrue($pdo->getAttribute(PDO::ATTR_PERSISTENT)); } diff --git a/tests/Functional/Driver/AbstractDriverTest.php b/tests/Functional/Driver/AbstractDriverTest.php index 25d5d5e4c8a..43836564607 100644 --- a/tests/Functional/Driver/AbstractDriverTest.php +++ b/tests/Functional/Driver/AbstractDriverTest.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\Driver; use Doctrine\DBAL\Driver\Connection as DriverConnection; use Doctrine\DBAL\Tests\FunctionalTestCase; +use PHPUnit\Framework\Constraint\IsType; abstract class AbstractDriverTest extends FunctionalTestCase { @@ -49,6 +50,16 @@ public function testReturnsDatabaseNameWithoutDatabaseNameParameter(): void ); } + public function testProvidesAccessToTheNativeConnection(): void + { + $nativeConnection = $this->connection->getNativeConnection(); + + self::assertThat($nativeConnection, self::logicalOr( + new IsType(IsType::TYPE_OBJECT), + new IsType(IsType::TYPE_RESOURCE) + )); + } + abstract protected function createDriver(): Driver; protected static function getDatabaseNameForConnectionWithoutDatabaseNameParameter(): ?string diff --git a/tests/Functional/Driver/PDO/SQLSrv/DriverTest.php b/tests/Functional/Driver/PDO/SQLSrv/DriverTest.php index 2603ca0bd60..3736f99808b 100644 --- a/tests/Functional/Driver/PDO/SQLSrv/DriverTest.php +++ b/tests/Functional/Driver/PDO/SQLSrv/DriverTest.php @@ -71,7 +71,7 @@ public function testDriverOptions(): void self::assertSame( PDO::CASE_UPPER, $connection - ->getWrappedConnection() + ->getNativeConnection() ->getAttribute(PDO::ATTR_CASE) ); } diff --git a/tests/Portability/ConnectionTest.php b/tests/Portability/ConnectionTest.php index 1255805f704..3077edd2b94 100644 --- a/tests/Portability/ConnectionTest.php +++ b/tests/Portability/ConnectionTest.php @@ -2,9 +2,11 @@ namespace Doctrine\DBAL\Tests\Portability; +use Doctrine\DBAL\Driver\Connection as DriverConnection; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Portability\Connection; use Doctrine\DBAL\Portability\Converter; +use LogicException; use PHPUnit\Framework\TestCase; class ConnectionTest extends TestCase @@ -20,4 +22,48 @@ public function testGetServerVersion(): void self::assertSame('1.2.3', $connection->getServerVersion()); } + + public function testGetServerVersionFailsWithLegacyConnection(): void + { + $connection = new Connection( + $this->createMock(DriverConnection::class), + new Converter(false, false, 0) + ); + + $this->expectException(LogicException::class); + $connection->getServerVersion(); + } + + public function testGetNativeConnection(): void + { + $nativeConnection = new class () { + }; + + $driverConnection = $this->createMock(NativeDriverConnection::class); + $driverConnection->method('getNativeConnection') + ->willReturn($nativeConnection); + + $connection = new Connection($driverConnection, new Converter(false, false, 0)); + + self::assertSame($nativeConnection, $connection->getNativeConnection()); + } + + public function testGetNativeConnectionFailsWithLegacyConnection(): void + { + $connection = new Connection( + $this->createMock(DriverConnection::class), + new Converter(false, false, 0) + ); + + $this->expectException(LogicException::class); + $connection->getNativeConnection(); + } +} + +interface NativeDriverConnection extends ServerInfoAwareConnection +{ + /** + * @return object|resource + */ + public function getNativeConnection(); } From dcee3b5a10539ee94ab757b9e69f5c0584b61154 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Sun, 7 Nov 2021 11:34:40 -0800 Subject: [PATCH 3/3] Deprecate Connection::getWrappedConnection(), mark Connection::connect() internal --- UPGRADE.md | 7 +++++++ psalm.xml.dist | 5 +++++ src/Connection.php | 17 +++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/UPGRADE.md b/UPGRADE.md index a2a12be1caf..675f97a68ed 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -8,6 +8,13 @@ awareness about deprecated code. # Upgrade to 3.3 +## Deprecated `Connection::getWrappedConnection()`, `Connection::connect()` made `@internal`. + +The wrapper-level `Connection::getWrappedConnection()` method has been deprecated. +Use `Connection::getNativeConnection()` to access the native connection. + +The `Connection::connect()` method has been marked internal. It will be marked `protected` in DBAL 4.0. + ## Add `Connection::getNativeConnection()` Driver and middleware connections need to implement a new method `getNativeConnection()` that gives access to the diff --git a/psalm.xml.dist b/psalm.xml.dist index b12b1af3446..78022833c54 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -197,6 +197,11 @@ + + diff --git a/src/Connection.php b/src/Connection.php index 1a32d12fded..5b905912d30 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -313,6 +313,8 @@ public function getExpressionBuilder() /** * Establishes the connection with the database. * + * @internal This method will be made protected in DBAL 4.0. + * * @return bool TRUE if the connection was successfully established, FALSE if * the connection is already open. * @@ -320,6 +322,12 @@ public function getExpressionBuilder() */ public function connect() { + Deprecation::triggerIfCalledFromOutside( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/issues/4966', + 'Public access to Connection::connect() is deprecated.' + ); + if ($this->_conn !== null) { return false; } @@ -1501,12 +1509,21 @@ public function rollbackSavepoint($savepoint) /** * Gets the wrapped driver connection. * + * @deprecated Use {@link getNativeConnection()} to access the native connection. + * * @return DriverConnection * * @throws Exception */ public function getWrappedConnection() { + Deprecation::triggerIfCalledFromOutside( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/issues/4966', + 'Connection::getWrappedConnection() is deprecated.' + . ' Use Connection::getNativeConnection() to access the native connection.' + ); + $this->connect(); assert($this->_conn !== null);