[DBAL-3079] Reworked the usage of PDO inPDOConnection from inheritance to composition

parent d71824e4
......@@ -985,25 +985,19 @@ class Connection implements DriverConnection
}
/**
* Executes an SQL statement, returning a result set as a Statement object.
*
* @return \Doctrine\DBAL\Driver\Statement
*
* @throws DBALException
* {@inheritDoc}
*/
public function query()
public function query(string $sql)
{
$this->connect();
$args = func_get_args();
$logger = $this->_config->getSQLLogger();
$logger->startQuery($args[0]);
$logger->startQuery($sql);
try {
$statement = $this->_conn->query(...$args);
$statement = $this->_conn->query($sql);
} catch (Throwable $ex) {
throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $args[0]);
throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $sql);
}
$statement->setFetchMode($this->defaultFetchMode);
......
......@@ -341,16 +341,14 @@ class MasterSlaveConnection extends Connection
/**
* {@inheritDoc}
*/
public function query()
public function query(string $sql)
{
$this->connect('master');
$args = func_get_args();
$logger = $this->getConfiguration()->getSQLLogger();
$logger->startQuery($args[0]);
$logger->startQuery($sql);
$statement = $this->_conn->query(...$args);
$statement = $this->_conn->query($sql);
$logger->stopQuery();
......
......@@ -2,6 +2,7 @@
namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\ParameterType;
/**
......@@ -25,8 +26,10 @@ interface Connection
* Executes an SQL statement, returning a result set as a Statement object.
*
* @return Statement
*
* @throws DBALException
*/
public function query();
public function query(string $sql);
/**
* Quotes a string for use in a query.
......
......@@ -86,10 +86,8 @@ class DB2Connection implements Connection, ServerInfoAwareConnection
/**
* {@inheritdoc}
*/
public function query()
public function query(string $sql)
{
$args = func_get_args();
$sql = $args[0];
$stmt = $this->prepare($sql);
$stmt->execute();
......
......@@ -134,10 +134,8 @@ class MysqliConnection implements Connection, PingableConnection, ServerInfoAwar
/**
* {@inheritdoc}
*/
public function query()
public function query(string $sql)
{
$args = func_get_args();
$sql = $args[0];
$stmt = $this->prepare($sql);
$stmt->execute();
......
......@@ -103,11 +103,8 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection
/**
* {@inheritdoc}
*/
public function query()
public function query(string $sql)
{
$args = func_get_args();
$sql = $args[0];
//$fetchMode = $args[1];
$stmt = $this->prepare($sql);
$stmt->execute();
......
......@@ -4,14 +4,17 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\ParameterType;
use PDO;
use function func_get_args;
/**
* PDO implementation of the Connection interface.
*
* Used by all PDO-based drivers.
*/
class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
class PDOConnection implements Connection, ServerInfoAwareConnection
{
/** @var PDO */
private $connection;
/**
* @param string $dsn
* @param string|null $user
......@@ -23,8 +26,8 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
public function __construct($dsn, $user = null, $password = null, ?array $options = null)
{
try {
parent::__construct($dsn, $user, $password, $options);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->connection = new PDO($dsn, $user, $password, $options);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
......@@ -36,7 +39,7 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
public function exec($statement)
{
try {
return parent::exec($statement);
return $this->connection->exec($statement);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
......@@ -47,17 +50,17 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
*/
public function getServerVersion()
{
return PDO::getAttribute(PDO::ATTR_SERVER_VERSION);
return $this->connection->getAttribute(PDO::ATTR_SERVER_VERSION);
}
/**
* {@inheritdoc}
*/
public function prepare($prepareString, $driverOptions = [])
public function prepare($prepareString)
{
try {
return $this->createStatement(
parent::prepare($prepareString, $driverOptions)
$this->connection->prepare($prepareString)
);
} catch (\PDOException $exception) {
throw new PDOException($exception);
......@@ -67,13 +70,11 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
/**
* {@inheritdoc}
*/
public function query()
public function query(string $sql)
{
$args = func_get_args();
try {
return $this->createStatement(
parent::query(...$args)
$this->connection->query($sql)
);
} catch (\PDOException $exception) {
throw new PDOException($exception);
......@@ -85,7 +86,7 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
*/
public function quote($input, $type = ParameterType::STRING)
{
return parent::quote($input, $type);
return $this->connection->quote($input, $type);
}
/**
......@@ -93,7 +94,7 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
*/
public function lastInsertId($name = null)
{
return parent::lastInsertId($name);
return $this->connection->lastInsertId($name);
}
/**
......@@ -111,4 +112,49 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
{
return new PDOStatement($stmt);
}
/**
* {@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 errorCode()
{
return $this->connection->errorCode();
}
/**
* {@inheritDoc}
*/
public function errorInfo()
{
return $this->connection->errorInfo();
}
public function getWrappedConnection() : PDO
{
return $this->connection;
}
}
......@@ -20,7 +20,7 @@ class Driver extends AbstractPostgreSQLDriver
public function connect(array $params, $username = null, $password = null, array $driverOptions = [])
{
try {
$pdo = new PDOConnection(
$connection = new PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
......@@ -32,7 +32,7 @@ class Driver extends AbstractPostgreSQLDriver
|| $driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES] === true
)
) {
$pdo->setAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES, true);
$connection->getWrappedConnection()->setAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES, true);
}
/* defining client_encoding via SET NAMES to avoid inconsistent DSN support
......@@ -40,10 +40,10 @@ class Driver extends AbstractPostgreSQLDriver
* - passing client_encoding via the 'options' param breaks pgbouncer support
*/
if (isset($params['charset'])) {
$pdo->exec('SET NAMES \'' . $params['charset'] . '\'');
$connection->exec('SET NAMES \'' . $params['charset'] . '\'');
}
return $pdo;
return $connection;
} catch (PDOException $e) {
throw DBALException::driverException($this, $e);
}
......
......@@ -35,7 +35,7 @@ class Driver extends AbstractSQLiteDriver
}
try {
$pdo = new PDOConnection(
$connection = new PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
......@@ -45,11 +45,13 @@ class Driver extends AbstractSQLiteDriver
throw DBALException::driverException($this, $ex);
}
$pdo = $connection->getWrappedConnection();
foreach ($this->_userDefinedFunctions as $fn => $data) {
$pdo->sqliteCreateFunction($fn, $data['callback'], $data['numArgs']);
}
return $pdo;
return $connection;
}
/**
......
......@@ -156,11 +156,9 @@ class SQLAnywhereConnection implements Connection, ServerInfoAwareConnection
/**
* {@inheritdoc}
*/
public function query()
public function query(string $sql)
{
$args = func_get_args();
$stmt = $this->prepare($args[0]);
$stmt = $this->prepare($sql);
$stmt->execute();
return $stmt;
......
......@@ -6,7 +6,6 @@ use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ParameterType;
use const SQLSRV_ERR_ERRORS;
use function func_get_args;
use function is_float;
use function is_int;
use function sprintf;
......@@ -80,10 +79,8 @@ class SQLSrvConnection implements Connection, ServerInfoAwareConnection
/**
* {@inheritDoc}
*/
public function query()
public function query(string $sql)
{
$args = func_get_args();
$sql = $args[0];
$stmt = $this->prepare($sql);
$stmt->execute();
......
......@@ -8,7 +8,6 @@ use Doctrine\DBAL\Driver\PDOConnection;
use PDO;
use const CASE_LOWER;
use const CASE_UPPER;
use function func_get_args;
/**
* Portability wrapper for a Connection.
......@@ -65,7 +64,7 @@ class Connection extends \Doctrine\DBAL\Connection
if (isset($params['fetch_case']) && $this->portability & self::PORTABILITY_FIX_CASE) {
if ($this->_conn instanceof PDOConnection) {
// make use of c-level support for case handling
$this->_conn->setAttribute(PDO::ATTR_CASE, $params['fetch_case']);
$this->_conn->getWrappedConnection()->setAttribute(PDO::ATTR_CASE, $params['fetch_case']);
} else {
$this->case = $params['fetch_case'] === ColumnCase::LOWER ? CASE_LOWER : CASE_UPPER;
}
......@@ -116,11 +115,11 @@ class Connection extends \Doctrine\DBAL\Connection
/**
* {@inheritdoc}
*/
public function query()
public function query(string $sql)
{
$this->connect();
$stmt = $this->_conn->query(...func_get_args());
$stmt = $this->_conn->query($sql);
$stmt = new Statement($stmt, $this);
$stmt->setFetchMode($this->defaultFetchMode);
......
......@@ -36,7 +36,7 @@ class DriverTest extends AbstractPostgreSQLDriverTest
self::assertInstanceOf(PDOConnection::class, $connection);
try {
self::assertTrue($connection->getAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES));
self::assertTrue($connection->getWrappedConnection()->getAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES));
} catch (PDOException $ignored) {
/** @link https://bugs.php.net/bug.php?id=68371 */
$this->markTestIncomplete('See https://bugs.php.net/bug.php?id=68371');
......@@ -63,7 +63,10 @@ class DriverTest extends AbstractPostgreSQLDriverTest
self::assertInstanceOf(PDOConnection::class, $connection);
try {
self::assertNotSame(true, $connection->getAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES));
self::assertNotSame(
true,
$connection->getWrappedConnection()->getAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES)
);
} catch (PDOException $ignored) {
/** @link https://bugs.php.net/bug.php?id=68371 */
$this->markTestIncomplete('See https://bugs.php.net/bug.php?id=68371');
......@@ -90,7 +93,7 @@ class DriverTest extends AbstractPostgreSQLDriverTest
self::assertInstanceOf(PDOConnection::class, $connection);
try {
self::assertTrue($connection->getAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES));
self::assertTrue($connection->getWrappedConnection()->getAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES));
} catch (PDOException $ignored) {
/** @link https://bugs.php.net/bug.php?id=68371 */
$this->markTestIncomplete('See https://bugs.php.net/bug.php?id=68371');
......
......@@ -74,7 +74,9 @@ class PDOConnectionTest extends DbalFunctionalTestCase
// Emulated prepared statements have to be disabled for this test
// so that PDO actually communicates with the database server to check the query.
$this->driverConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->driverConnection
->getWrappedConnection()
->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->driverConnection->prepare('foo');
......
......@@ -3,9 +3,11 @@
namespace Doctrine\Tests\DBAL\Functional\Driver\PDOSqlsrv;
use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDOSqlsrv\Driver;
use Doctrine\Tests\DBAL\Functional\Driver\AbstractDriverTest;
use PDO;
use function assert;
use function extension_loaded;
class DriverTest extends AbstractDriverTest
......@@ -69,6 +71,13 @@ class DriverTest extends AbstractDriverTest
{
$connection = $this->getConnection([PDO::ATTR_CASE => PDO::CASE_UPPER]);
self::assertSame(PDO::CASE_UPPER, $connection->getAttribute(PDO::ATTR_CASE));
assert($connection instanceof PDOConnection);
self::assertSame(
PDO::CASE_UPPER,
$connection
->getWrappedConnection()
->getAttribute(PDO::ATTR_CASE)
);
}
}
......@@ -37,7 +37,9 @@ class DBAL630Test extends DbalFunctionalTestCase
protected function tearDown()
{
if ($this->running) {
$this->connection->getWrappedConnection()->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->connection->getWrappedConnection()
->getWrappedConnection()
->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
parent::tearDown();
......@@ -71,7 +73,9 @@ class DBAL630Test extends DbalFunctionalTestCase
public function testBooleanConversionBoolParamEmulatedPrepares()
{
$this->connection->getWrappedConnection()->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$this->connection->getWrappedConnection()
->getWrappedConnection()
->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$platform = $this->connection->getDatabasePlatform();
......@@ -95,7 +99,9 @@ class DBAL630Test extends DbalFunctionalTestCase
$statementValue,
$databaseConvertedValue
) {
$this->connection->getWrappedConnection()->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$this->connection->getWrappedConnection()
->getWrappedConnection()
->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$platform = $this->connection->getDatabasePlatform();
......@@ -119,7 +125,9 @@ class DBAL630Test extends DbalFunctionalTestCase
$statementValue,
$databaseConvertedValue
) {
$this->connection->getWrappedConnection()->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$this->connection->getWrappedConnection()
->getWrappedConnection()
->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$platform = $this->connection->getDatabasePlatform();
......
......@@ -8,9 +8,10 @@ use Doctrine\DBAL\ParameterType;
class DriverConnectionMock implements Connection
{
public function prepare($prepareString)
{
{
}
public function query()
public function query(string $sql)
{
}
......
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