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

parent dc47f569
......@@ -23,7 +23,6 @@ use Exception;
use Throwable;
use function array_key_exists;
use function assert;
use function func_get_args;
use function implode;
use function is_int;
use function is_string;
......@@ -990,25 +989,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)
{
$connection = $this->getWrappedConnection();
$args = func_get_args();
$logger = $this->_config->getSQLLogger();
$logger->startQuery($args[0]);
$logger->startQuery($sql);
try {
$statement = $connection->query(...$args);
$statement = $connection->query($sql);
} catch (Throwable $ex) {
throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $args[0]);
throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $sql);
}
$statement->setFetchMode($this->defaultFetchMode);
......
......@@ -13,7 +13,6 @@ use InvalidArgumentException;
use function array_rand;
use function assert;
use function count;
use function func_get_args;
/**
* Master-Slave Connection
......@@ -342,17 +341,15 @@ class MasterSlaveConnection extends Connection
/**
* {@inheritDoc}
*/
public function query()
public function query(string $sql)
{
$this->connect('master');
assert($this->_conn instanceof DriverConnection);
$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);
$statement->setFetchMode($this->defaultFetchMode);
......
......@@ -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.
......
......@@ -22,7 +22,6 @@ use function db2_prepare;
use function db2_rollback;
use function db2_server_info;
use function db2_stmt_errormsg;
use function func_get_args;
class DB2Connection implements Connection, ServerInfoAwareConnection
{
......@@ -89,10 +88,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();
......
......@@ -15,7 +15,6 @@ use const MYSQLI_READ_DEFAULT_GROUP;
use const MYSQLI_SERVER_PUBLIC_KEY;
use function defined;
use function floor;
use function func_get_args;
use function in_array;
use function ini_get;
use function mysqli_errno;
......@@ -134,10 +133,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();
......
......@@ -10,7 +10,6 @@ use const OCI_COMMIT_ON_SUCCESS;
use const OCI_DEFAULT;
use const OCI_NO_AUTO_COMMIT;
use function addcslashes;
use function func_get_args;
use function is_float;
use function is_int;
use function oci_commit;
......@@ -111,11 +110,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,18 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\ParameterType;
use PDO;
use function func_get_args;
use function assert;
/**
* 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 +27,8 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
public function __construct($dsn, $user = null, $password = null, ?array $options = null)
{
try {
parent::__construct($dsn, (string) $user, (string) $password, (array) $options);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$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);
}
......@@ -36,7 +40,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 +51,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,14 +71,13 @@ 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)
);
$stmt = $this->connection->query($sql);
assert($stmt instanceof \PDOStatement);
return $this->createStatement($stmt);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
......@@ -85,7 +88,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);
}
/**
......@@ -95,10 +98,10 @@ class PDOConnection extends PDO implements Connection, ServerInfoAwareConnection
{
try {
if ($name === null) {
return parent::lastInsertId();
return $this->connection->lastInsertId();
}
return parent::lastInsertId($name);
return $this->connection->lastInsertId($name);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
......@@ -119,4 +122,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;
}
/**
......
......@@ -6,7 +6,6 @@ use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ParameterType;
use function assert;
use function func_get_args;
use function is_float;
use function is_int;
use function is_resource;
......@@ -151,11 +150,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;
......@@ -83,10 +82,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)
{
$connection = $this->getWrappedConnection();
$stmt = $connection->query(...func_get_args());
$stmt = $connection->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');
......
......@@ -954,8 +954,9 @@ class DataAccessTest extends DbalFunctionalTestCase
}
/** @var PDOConnection $connection */
$connection = $this->connection->getWrappedConnection();
$connection->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
$connection = $this->connection
->getWrappedConnection();
$connection->getWrappedConnection()->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
}
}
......
......@@ -90,7 +90,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->expectException(PDOException::class);
......
......@@ -4,9 +4,11 @@ namespace Doctrine\Tests\DBAL\Functional\Driver\PDOSqlsrv;
use Doctrine\DBAL\Driver as DriverInterface;
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
......@@ -70,6 +72,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() : void
{
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() : void
{
$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
?bool $statementValue,
?bool $databaseConvertedValue
) : void {
$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
?bool $statementValue,
bool $databaseConvertedValue
) : void {
$this->connection->getWrappedConnection()->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$this->connection->getWrappedConnection()
->getWrappedConnection()
->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
$platform = $this->connection->getDatabasePlatform();
......
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