From ebbc3b5715f8aaaa9526a21e67e9ca8dd2668c2d Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Tue, 7 Aug 2018 09:13:23 -0700 Subject: [PATCH 01/13] [DBAL-3241] Removed dbal:import CLI command --- UPGRADE.md | 11 ++ .../Tools/Console/Command/ImportCommand.php | 138 ------------------ .../DBAL/Tools/Console/ConsoleRunner.php | 2 - 3 files changed, 11 insertions(+), 140 deletions(-) delete mode 100644 lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php diff --git a/UPGRADE.md b/UPGRADE.md index 205bf991974..59c15565ea7 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,3 +1,14 @@ +# Upgrade to 3.0 + +## BC BREAK: Removed dbal:import CLI command + +The `dbal:import` CLI command has been removed since it only worked with PDO-based drivers by relying on a non-documented behavior of the extension, and it was impossible to make it work with other drivers. +Please use other database client applications for import, e.g.: + + * For MySQL and MariaDB: `mysql [dbname] < data.sql`. + * For PostgreSQL: `psql [dbname] < data.sql`. + * For SQLite: `sqlite3 /path/to/file.db < data.sql`. + # Upgrade to 2.10 ## Deprecated `Doctrine\DBAL\Event\ConnectionEventArgs` methods diff --git a/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php b/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php deleted file mode 100644 index 0cd2999c97a..00000000000 --- a/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php +++ /dev/null @@ -1,138 +0,0 @@ -setName('dbal:import') - ->setDescription('Import SQL file(s) directly to Database.') - ->setDefinition([new InputArgument( - 'file', - InputArgument::REQUIRED | InputArgument::IS_ARRAY, - 'File path(s) of SQL to be executed.' - ), - ]) - ->setHelp(<<getHelper('db')->getConnection(); - - $fileNames = $input->getArgument('file'); - - if ($fileNames === null) { - return 0; - } - - foreach ((array) $fileNames as $fileName) { - $filePath = realpath($fileName); - - // Phar compatibility. - if ($filePath === false) { - $filePath = $fileName; - } - - if (! file_exists($filePath)) { - throw new InvalidArgumentException( - sprintf("SQL file '%s' does not exist.", $filePath) - ); - } - - if (! is_readable($filePath)) { - throw new InvalidArgumentException( - sprintf("SQL file '%s' does not have read permissions.", $filePath) - ); - } - - $output->write(sprintf("Processing file '%s'... ", $filePath)); - $sql = @file_get_contents($filePath); - - if ($sql === false) { - throw new RuntimeException( - sprintf("Unable to read SQL file '%s': %s", $filePath, error_get_last()['message']) - ); - } - - if ($conn instanceof PDOConnection) { - // PDO Drivers - try { - $lines = 0; - - $stmt = $conn->prepare($sql); - assert($stmt instanceof PDOStatement); - - $stmt->execute(); - - do { - // Required due to "MySQL has gone away!" issue - $stmt->fetch(); - $stmt->closeCursor(); - - $lines++; - } while ($stmt->nextRowset()); - - $output->write(sprintf('%d statements executed!', $lines) . PHP_EOL); - } catch (PDOException $e) { - $output->write('error!' . PHP_EOL); - - throw new RuntimeException($e->getMessage(), $e->getCode(), $e); - } - } else { - // Non-PDO Drivers (ie. OCI8 driver) - $stmt = $conn->prepare($sql); - $rs = $stmt->execute(); - - if (! $rs) { - $error = $stmt->errorInfo(); - - $output->write('error!' . PHP_EOL); - - throw new RuntimeException($error[2], $error[0]); - } - - $output->writeln('OK!' . PHP_EOL); - - $stmt->closeCursor(); - } - } - - return 0; - } -} diff --git a/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php b/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php index 520a9af80aa..5dd89494f89 100644 --- a/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php +++ b/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php @@ -3,7 +3,6 @@ namespace Doctrine\DBAL\Tools\Console; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Tools\Console\Command\ImportCommand; use Doctrine\DBAL\Tools\Console\Command\ReservedWordsCommand; use Doctrine\DBAL\Tools\Console\Command\RunSqlCommand; use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper; @@ -56,7 +55,6 @@ public static function addCommands(Application $cli) { $cli->addCommands([ new RunSqlCommand(), - new ImportCommand(), new ReservedWordsCommand(), ]); } From 9053ad109da3dd4988f8e0d4ac25443a079f869c Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Sun, 31 Dec 2017 19:11:53 -0800 Subject: [PATCH 02/13] [DBAL-2958] Added conversion of DBAL constants to PDO ones for PDOStatement --- lib/Doctrine/DBAL/Driver/PDOStatement.php | 21 ++------ .../DBAL/Functional/PDOStatementTest.php | 54 ------------------- 2 files changed, 3 insertions(+), 72 deletions(-) delete mode 100644 tests/Doctrine/Tests/DBAL/Functional/PDOStatementTest.php diff --git a/lib/Doctrine/DBAL/Driver/PDOStatement.php b/lib/Doctrine/DBAL/Driver/PDOStatement.php index 6e61d22555a..42d20dd2be7 100644 --- a/lib/Doctrine/DBAL/Driver/PDOStatement.php +++ b/lib/Doctrine/DBAL/Driver/PDOStatement.php @@ -4,14 +4,12 @@ use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; +use InvalidArgumentException; use PDO; -use const E_USER_DEPRECATED; use function array_slice; use function assert; use function func_get_args; use function is_array; -use function sprintf; -use function trigger_error; /** * The PDO implementation of the Statement interface. @@ -193,13 +191,7 @@ public function fetchColumn($columnIndex = 0) private function convertParamType(int $type) : int { if (! isset(self::PARAM_TYPE_MAP[$type])) { - // TODO: next major: throw an exception - @trigger_error(sprintf( - 'Using a PDO parameter type (%d given) is deprecated and will cause an error in Doctrine DBAL 3.0', - $type - ), E_USER_DEPRECATED); - - return $type; + throw new InvalidArgumentException('Invalid parameter type: ' . $type); } return self::PARAM_TYPE_MAP[$type]; @@ -213,14 +205,7 @@ private function convertParamType(int $type) : int private function convertFetchMode(int $fetchMode) : int { if (! isset(self::FETCH_MODE_MAP[$fetchMode])) { - // TODO: next major: throw an exception - @trigger_error(sprintf( - 'Using a PDO fetch mode or their combination (%d given)' . - ' is deprecated and will cause an error in Doctrine DBAL 3.0', - $fetchMode - ), E_USER_DEPRECATED); - - return $fetchMode; + throw new InvalidArgumentException('Invalid fetch mode: ' . $fetchMode); } return self::FETCH_MODE_MAP[$fetchMode]; diff --git a/tests/Doctrine/Tests/DBAL/Functional/PDOStatementTest.php b/tests/Doctrine/Tests/DBAL/Functional/PDOStatementTest.php deleted file mode 100644 index 2ea5fa49284..00000000000 --- a/tests/Doctrine/Tests/DBAL/Functional/PDOStatementTest.php +++ /dev/null @@ -1,54 +0,0 @@ -markTestSkipped('PDO is not installed'); - } - - parent::setUp(); - - if (! $this->connection->getWrappedConnection() instanceof PDOConnection) { - $this->markTestSkipped('PDO-only test'); - } - - $table = new Table('stmt_test'); - $table->addColumn('id', 'integer'); - $table->addColumn('name', 'string'); - $this->connection->getSchemaManager()->dropAndCreateTable($table); - } - - /** - * @group legacy - * @expectedDeprecation Using a PDO fetch mode or their combination (%d given) is deprecated and will cause an error in Doctrine DBAL 3.0 - */ - public function testPDOSpecificModeIsAccepted() : void - { - $this->connection->insert('stmt_test', [ - 'id' => 1, - 'name' => 'Alice', - ]); - $this->connection->insert('stmt_test', [ - 'id' => 2, - 'name' => 'Bob', - ]); - - $data = $this->connection->query('SELECT id, name FROM stmt_test ORDER BY id') - ->fetchAll(PDO::FETCH_KEY_PAIR); - - self::assertSame([ - 1 => 'Alice', - 2 => 'Bob', - ], $data); - } -} From 11106683a1a5b6397bf4c1aba561c4d7e8213857 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Tue, 26 Dec 2017 21:01:19 -0800 Subject: [PATCH 03/13] [DBAL-2958] Removed support for PDO::PARAM_INPUT_OUTPUT in Statement::bindParam() --- lib/Doctrine/DBAL/Driver/Statement.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Doctrine/DBAL/Driver/Statement.php b/lib/Doctrine/DBAL/Driver/Statement.php index 388983e46a6..3c778eeb74c 100644 --- a/lib/Doctrine/DBAL/Driver/Statement.php +++ b/lib/Doctrine/DBAL/Driver/Statement.php @@ -49,8 +49,7 @@ public function bindValue($param, $value, $type = ParameterType::STRING); * question mark placeholders, this will be the 1-indexed position of the parameter. * @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter. * @param int $type Explicit data type for the parameter using the {@link \Doctrine\DBAL\ParameterType} - * constants. To return an INOUT parameter from a stored procedure, use the bitwise - * OR operator to set the PDO::PARAM_INPUT_OUTPUT bits for the data_type parameter. + * constants. * @param int|null $length You must specify maxlength when using an OUT bind * so that PHP allocates enough memory to hold the returned value. * From a451eef823ce72c0197370778d0fd554e37be1cc Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Tue, 2 Jan 2018 15:07:37 -0800 Subject: [PATCH 04/13] [DBAL-2958] Replaced extension of \PDOStatement with a composition to avoid having to replicate the \PDOStatement interface in ResultStatement --- lib/Doctrine/DBAL/Cache/ArrayStatement.php | 11 +- .../DBAL/Cache/ResultCacheStatement.php | 9 +- .../DBAL/Driver/IBMDB2/DB2Statement.php | 31 ++--- .../DBAL/Driver/Mysqli/MysqliStatement.php | 7 +- .../DBAL/Driver/OCI8/OCI8Statement.php | 7 +- lib/Doctrine/DBAL/Driver/PDOConnection.php | 15 ++- lib/Doctrine/DBAL/Driver/PDOStatement.php | 117 ++++++++++-------- lib/Doctrine/DBAL/Driver/ResultStatement.php | 58 +++------ .../SQLAnywhere/SQLAnywhereStatement.php | 33 ++--- .../DBAL/Driver/SQLSrv/SQLSrvStatement.php | 29 +++-- lib/Doctrine/DBAL/Portability/Statement.php | 17 +-- lib/Doctrine/DBAL/Statement.php | 25 +--- 12 files changed, 174 insertions(+), 185 deletions(-) diff --git a/lib/Doctrine/DBAL/Cache/ArrayStatement.php b/lib/Doctrine/DBAL/Cache/ArrayStatement.php index 449a220a2af..494876c935e 100644 --- a/lib/Doctrine/DBAL/Cache/ArrayStatement.php +++ b/lib/Doctrine/DBAL/Cache/ArrayStatement.php @@ -7,7 +7,6 @@ use Doctrine\DBAL\FetchMode; use InvalidArgumentException; use IteratorAggregate; -use PDO; use function array_merge; use function array_values; use function count; @@ -59,9 +58,9 @@ public function columnCount() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + public function setFetchMode($fetchMode, ...$args) { - if ($arg2 !== null || $arg3 !== null) { + if (count($args) > 0) { throw new InvalidArgumentException('Caching layer does not support 2nd/3rd argument to setFetchMode()'); } @@ -83,7 +82,7 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + public function fetch($fetchMode = null, ...$args) { if (! isset($this->data[$this->num])) { return false; @@ -114,10 +113,10 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + public function fetchAll($fetchMode = null, ...$args) { $rows = []; - while ($row = $this->fetch($fetchMode)) { + while ($row = $this->fetch($fetchMode, ...$args)) { $rows[] = $row; } diff --git a/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php b/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php index f04c8524974..156de78ce2e 100644 --- a/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php +++ b/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php @@ -9,7 +9,6 @@ use Doctrine\DBAL\FetchMode; use InvalidArgumentException; use IteratorAggregate; -use PDO; use function array_merge; use function array_values; use function assert; @@ -105,7 +104,7 @@ public function columnCount() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + public function setFetchMode($fetchMode, ...$args) { $this->defaultFetchMode = $fetchMode; @@ -125,7 +124,7 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + public function fetch($fetchMode = null, ...$args) { if ($this->data === null) { $this->data = []; @@ -165,9 +164,9 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + public function fetchAll($fetchMode = null, ...$args) { - $data = $this->statement->fetchAll($fetchMode, $fetchArgument, $ctorArgs); + $data = $this->statement->fetchAll($fetchMode, ...$args); if ($fetchMode === FetchMode::COLUMN) { foreach ($data as $key => $value) { diff --git a/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php b/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php index af6e852bc43..b77067bd4da 100644 --- a/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php +++ b/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php @@ -7,7 +7,6 @@ use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use IteratorAggregate; -use PDO; use ReflectionClass; use ReflectionObject; use ReflectionProperty; @@ -19,6 +18,7 @@ use const DB2_PARAM_FILE; use const DB2_PARAM_IN; use function array_change_key_case; +use function count; use function db2_bind_param; use function db2_execute; use function db2_fetch_array; @@ -32,8 +32,6 @@ use function db2_stmt_errormsg; use function error_get_last; use function fclose; -use function func_get_args; -use function func_num_args; use function fwrite; use function gettype; use function is_object; @@ -229,11 +227,17 @@ public function execute($params = null) /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + public function setFetchMode($fetchMode, ...$args) { - $this->defaultFetchMode = $fetchMode; - $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; - $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; + $this->defaultFetchMode = $fetchMode; + + if (isset($args[0])) { + $this->defaultFetchClass = $args[0]; + } + + if (isset($args[1])) { + $this->defaultFetchClassCtorArgs = (array) $args[1]; + } return true; } @@ -249,7 +253,7 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + public function fetch($fetchMode = null, ...$args) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation @@ -272,10 +276,9 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX $className = $this->defaultFetchClass; $ctorArgs = $this->defaultFetchClassCtorArgs; - if (func_num_args() >= 2) { - $args = func_get_args(); - $className = $args[1]; - $ctorArgs = $args[2] ?? []; + if (count($args) > 0) { + $className = $args[0]; + $ctorArgs = $args[1] ?? []; } $result = db2_fetch_object($this->stmt); @@ -300,13 +303,13 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + public function fetchAll($fetchMode = null, ...$args) { $rows = []; switch ($fetchMode) { case FetchMode::CUSTOM_OBJECT: - while (($row = $this->fetch(...func_get_args())) !== false) { + while (($row = $this->fetch($fetchMode, ...$args)) !== false) { $rows[] = $row; } break; diff --git a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php index 43d70853ef5..acf8b4ec54c 100644 --- a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php +++ b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php @@ -10,7 +10,6 @@ use IteratorAggregate; use mysqli; use mysqli_stmt; -use PDO; use function array_combine; use function array_fill; use function assert; @@ -303,7 +302,7 @@ private function _fetch() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + public function fetch($fetchMode = null, ...$args) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation @@ -353,7 +352,7 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + public function fetchAll($fetchMode = null, ...$args) { $fetchMode = $fetchMode ?: $this->_defaultFetchMode; @@ -436,7 +435,7 @@ public function columnCount() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + public function setFetchMode($fetchMode, ...$args) { $this->_defaultFetchMode = $fetchMode; diff --git a/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php b/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php index 2f8b9323817..a244db8a6cd 100644 --- a/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php +++ b/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php @@ -8,7 +8,6 @@ use Doctrine\DBAL\ParameterType; use InvalidArgumentException; use IteratorAggregate; -use PDO; use const OCI_ASSOC; use const OCI_B_BIN; use const OCI_B_BLOB; @@ -407,7 +406,7 @@ public function execute($params = null) /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + public function setFetchMode($fetchMode, ...$args) { $this->_defaultFetchMode = $fetchMode; @@ -425,7 +424,7 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + public function fetch($fetchMode = null, ...$args) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation @@ -456,7 +455,7 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + public function fetchAll($fetchMode = null, ...$args) { $fetchMode = $fetchMode ?: $this->_defaultFetchMode; diff --git a/lib/Doctrine/DBAL/Driver/PDOConnection.php b/lib/Doctrine/DBAL/Driver/PDOConnection.php index 336542ea50a..df67a508956 100644 --- a/lib/Doctrine/DBAL/Driver/PDOConnection.php +++ b/lib/Doctrine/DBAL/Driver/PDOConnection.php @@ -25,7 +25,6 @@ public function __construct($dsn, $user = null, $password = null, ?array $option { try { parent::__construct($dsn, (string) $user, (string) $password, (array) $options); - $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, [PDOStatement::class, []]); $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (\PDOException $exception) { throw new PDOException($exception); @@ -58,7 +57,9 @@ public function getServerVersion() public function prepare($prepareString, $driverOptions = []) { try { - return parent::prepare($prepareString, $driverOptions); + return $this->createStatement( + parent::prepare($prepareString, $driverOptions) + ); } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -75,7 +76,7 @@ public function query() $stmt = parent::query(...$args); assert($stmt instanceof \PDOStatement); - return $stmt; + return $this->createStatement($stmt); } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -112,4 +113,12 @@ public function requiresQueryForServerVersion() { return false; } + + /** + * Creates a wrapped statement + */ + private function createStatement(\PDOStatement $stmt) : PDOStatement + { + return new PDOStatement($stmt); + } } diff --git a/lib/Doctrine/DBAL/Driver/PDOStatement.php b/lib/Doctrine/DBAL/Driver/PDOStatement.php index 42d20dd2be7..92125768340 100644 --- a/lib/Doctrine/DBAL/Driver/PDOStatement.php +++ b/lib/Doctrine/DBAL/Driver/PDOStatement.php @@ -5,6 +5,7 @@ use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use InvalidArgumentException; +use IteratorAggregate; use PDO; use function array_slice; use function assert; @@ -15,7 +16,7 @@ * The PDO implementation of the Statement interface. * Used by all PDO-based drivers. */ -class PDOStatement extends \PDOStatement implements Statement +class PDOStatement implements IteratorAggregate, Statement { private const PARAM_TYPE_MAP = [ ParameterType::NULL => PDO::PARAM_NULL, @@ -35,34 +36,23 @@ class PDOStatement extends \PDOStatement implements Statement FetchMode::CUSTOM_OBJECT => PDO::FETCH_CLASS, ]; - /** - * Protected constructor. - */ - protected function __construct() + /** @var \PDOStatement */ + private $stmt; + + public function __construct(\PDOStatement $stmt) { + $this->stmt = $stmt; } /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + public function setFetchMode($fetchMode, ...$args) { $fetchMode = $this->convertFetchMode($fetchMode); - // This thin wrapper is necessary to shield against the weird signature - // of PDOStatement::setFetchMode(): even if the second and third - // parameters are optional, PHP will not let us remove it from this - // declaration. try { - if ($arg2 === null && $arg3 === null) { - return parent::setFetchMode($fetchMode); - } - - if ($arg3 === null) { - return parent::setFetchMode($fetchMode, $arg2); - } - - return parent::setFetchMode($fetchMode, $arg2, $arg3); + return $this->stmt->setFetchMode($fetchMode, ...$args); } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -76,7 +66,7 @@ public function bindValue($param, $value, $type = ParameterType::STRING) $type = $this->convertParamType($type); try { - return parent::bindValue($param, $value, $type); + return $this->stmt->bindValue($param, $value, $type); } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -90,7 +80,7 @@ public function bindParam($column, &$variable, $type = ParameterType::STRING, $l $type = $this->convertParamType($type); try { - return parent::bindParam($column, $variable, $type, ...array_slice(func_get_args(), 3)); + return $this->stmt->bindParam($column, $variable, $type, ...array_slice(func_get_args(), 3)); } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -102,7 +92,7 @@ public function bindParam($column, &$variable, $type = ParameterType::STRING, $l public function closeCursor() { try { - return parent::closeCursor(); + return $this->stmt->closeCursor(); } catch (\PDOException $exception) { // Exceptions not allowed by the interface. // In case driver implementations do not adhere to the interface, silence exceptions here. @@ -110,31 +100,52 @@ public function closeCursor() } } + public function columnCount() + { + return $this->stmt->columnCount(); + } + + public function errorCode() + { + return $this->stmt->errorCode(); + } + + public function errorInfo() + { + return $this->stmt->errorInfo(); + } + /** * {@inheritdoc} */ public function execute($params = null) { try { - return parent::execute($params); + return $this->stmt->execute($params); } catch (\PDOException $exception) { throw new PDOException($exception); } } + public function rowCount() + { + return $this->stmt->rowCount(); + } + /** * {@inheritdoc} */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + public function fetch($fetchMode = null, ...$args) { - $args = func_get_args(); - - if (isset($args[0])) { - $args[0] = $this->convertFetchMode($args[0]); - } - try { - return parent::fetch(...$args); + if ($fetchMode === null) { + return $this->stmt->fetch(); + } + + return $this->stmt->fetch( + $this->convertFetchMode($fetchMode), + ...$args + ); } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -143,32 +154,24 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + public function fetchAll($fetchMode = null, ...$args) { - $args = func_get_args(); - - if (isset($args[0])) { - $args[0] = $this->convertFetchMode($args[0]); - } - - if ($fetchMode === null && $fetchArgument === null && $ctorArgs === null) { - $args = []; - } elseif ($fetchArgument === null && $ctorArgs === null) { - $args = [$fetchMode]; - } elseif ($ctorArgs === null) { - $args = [$fetchMode, $fetchArgument]; - } else { - $args = [$fetchMode, $fetchArgument, $ctorArgs]; - } - try { - $data = parent::fetchAll(...$args); - assert(is_array($data)); - - return $data; + if ($fetchMode === null) { + $data = $this->stmt->fetchAll(); + } else { + $data = $this->stmt->fetchAll( + $this->convertFetchMode($fetchMode), + ...$args + ); + } } catch (\PDOException $exception) { throw new PDOException($exception); } + + assert(is_array($data)); + + return $data; } /** @@ -177,7 +180,7 @@ public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = n public function fetchColumn($columnIndex = 0) { try { - return parent::fetchColumn($columnIndex); + return $this->stmt->fetchColumn($columnIndex); } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -210,4 +213,12 @@ private function convertFetchMode(int $fetchMode) : int return self::FETCH_MODE_MAP[$fetchMode]; } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + yield from $this->stmt; + } } diff --git a/lib/Doctrine/DBAL/Driver/ResultStatement.php b/lib/Doctrine/DBAL/Driver/ResultStatement.php index 1e6df0269b8..8cbd2688a21 100644 --- a/lib/Doctrine/DBAL/Driver/ResultStatement.php +++ b/lib/Doctrine/DBAL/Driver/ResultStatement.php @@ -2,7 +2,6 @@ namespace Doctrine\DBAL\Driver; -use PDO; use Traversable; /** @@ -29,62 +28,43 @@ public function columnCount(); /** * Sets the fetch mode to use while iterating this statement. * - * @param int $fetchMode The fetch mode must be one of the {@link \Doctrine\DBAL\FetchMode} constants. - * @param mixed $arg2 - * @param mixed $arg3 + * @param int $fetchMode Controls how the next row will be returned to the caller. + * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants. + * @param mixed ...$args Optional mode-specific arguments (see {@link self::fetchAll()}). * * @return bool */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null); + public function setFetchMode($fetchMode, ...$args); /** * Returns the next row of a result set. * - * @param int|null $fetchMode Controls how the next row will be returned to the caller. - * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants, - * defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}. - * @param int $cursorOrientation For a ResultStatement object representing a scrollable cursor, - * this value determines which row will be returned to the caller. - * This value must be one of the \PDO::FETCH_ORI_* constants, - * defaulting to \PDO::FETCH_ORI_NEXT. To request a scrollable - * cursor for your ResultStatement object, you must set the \PDO::ATTR_CURSOR - * attribute to \PDO::CURSOR_SCROLL when you prepare the SQL statement with - * \PDO::prepare(). - * @param int $cursorOffset For a ResultStatement object representing a scrollable cursor for which the - * cursorOrientation parameter is set to \PDO::FETCH_ORI_ABS, this value - * specifies the absolute number of the row in the result set that shall be - * fetched. - * For a ResultStatement object representing a scrollable cursor for which the - * cursorOrientation parameter is set to \PDO::FETCH_ORI_REL, this value - * specifies the row to fetch relative to the cursor position before - * ResultStatement::fetch() was called. + * @param int|null $fetchMode Controls how the next row will be returned to the caller. + * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants, + * defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}. + * @param mixed ...$args Optional mode-specific arguments (see {@link self::fetchAll()}). * * @return mixed The return value of this method on success depends on the fetch mode. In all cases, FALSE is * returned on failure. */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0); + public function fetch($fetchMode = null, ...$args); /** * Returns an array containing all of the result set rows. * - * @param int|null $fetchMode Controls how the next row will be returned to the caller. - * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants, - * defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}. - * @param int|null $fetchArgument This argument has a different meaning depending on the value of the $fetchMode parameter: - * * {@link \Doctrine\DBAL\FetchMode::COLUMN}: - * Returns the indicated 0-indexed column. - * * {@link \Doctrine\DBAL\FetchMode::CUSTOM_OBJECT}: - * Returns instances of the specified class, mapping the columns of each row - * to named properties in the class. - * * \PDO::FETCH_FUNC: Returns the results of calling the specified function, using each row's - * columns as parameters in the call. - * @param mixed[]|null $ctorArgs Controls how the next row will be returned to the caller. - * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants, - * defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}. + * @param int|null $fetchMode Controls how the next row will be returned to the caller. + * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants, + * defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}. + * @param mixed ...$args Optional mode-specific arguments. Supported modes: + * * {@link \Doctrine\DBAL\FetchMode::COLUMN} + * 1. The 0-indexed column to be returned. + * * {@link \Doctrine\DBAL\FetchMode::CUSTOM_OBJECT} + * 1. The class name of the object to be created, + * 2. Array of constructor arguments * * @return mixed[] */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null); + public function fetchAll($fetchMode = null, ...$args); /** * Returns a single column from the next row of a result set or FALSE if there are no more rows. diff --git a/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php b/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php index 886bb245873..afe569104e2 100644 --- a/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php +++ b/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php @@ -7,14 +7,12 @@ use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use IteratorAggregate; -use PDO; use ReflectionClass; use ReflectionObject; use stdClass; use const SASQL_BOTH; use function array_key_exists; -use function func_get_args; -use function func_num_args; +use function count; use function gettype; use function is_array; use function is_int; @@ -199,7 +197,7 @@ public function execute($params = null) * * @throws SQLAnywhereException */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + public function fetch($fetchMode = null, ...$args) { if (! is_resource($this->result)) { return false; @@ -221,10 +219,9 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX $className = $this->defaultFetchClass; $ctorArgs = $this->defaultFetchClassCtorArgs; - if (func_num_args() >= 2) { - $args = func_get_args(); - $className = $args[1]; - $ctorArgs = $args[2] ?? []; + if (count($args) > 0) { + $className = $args[0]; + $ctorArgs = $args[1] ?? []; } $result = sasql_fetch_object($this->result); @@ -249,13 +246,13 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + public function fetchAll($fetchMode = null, ...$args) { $rows = []; switch ($fetchMode) { case FetchMode::CUSTOM_OBJECT: - while (($row = $this->fetch(...func_get_args())) !== false) { + while (($row = $this->fetch($fetchMode, ...$args)) !== false) { $rows[] = $row; } break; @@ -308,11 +305,19 @@ public function rowCount() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + public function setFetchMode($fetchMode, ...$args) { - $this->defaultFetchMode = $fetchMode; - $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; - $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; + $this->defaultFetchMode = $fetchMode; + + if (isset($args[0])) { + $this->defaultFetchClass = $args[0]; + } + + if (isset($args[1])) { + $this->defaultFetchClassCtorArgs = (array) $args[1]; + } + + return true; } /** diff --git a/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php b/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php index 5e7016c5a74..905d16fb997 100644 --- a/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php +++ b/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php @@ -7,7 +7,6 @@ use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use IteratorAggregate; -use PDO; use const SQLSRV_ENC_BINARY; use const SQLSRV_ERR_ERRORS; use const SQLSRV_FETCH_ASSOC; @@ -16,7 +15,6 @@ use const SQLSRV_PARAM_IN; use function array_key_exists; use function count; -use function func_get_args; use function in_array; use function is_int; use function is_numeric; @@ -313,11 +311,17 @@ private function prepare() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + public function setFetchMode($fetchMode, ...$args) { - $this->defaultFetchMode = $fetchMode; - $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; - $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; + $this->defaultFetchMode = $fetchMode; + + if (isset($args[0])) { + $this->defaultFetchClass = $args[0]; + } + + if (isset($args[1])) { + $this->defaultFetchClassCtorArgs = (array) $args[1]; + } return true; } @@ -335,7 +339,7 @@ public function getIterator() * * @throws SQLSrvException */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + public function fetch($fetchMode = null, ...$args) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation @@ -343,7 +347,6 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX return false; } - $args = func_get_args(); $fetchMode = $fetchMode ?: $this->defaultFetchMode; if ($fetchMode === FetchMode::COLUMN) { @@ -358,9 +361,9 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX $className = $this->defaultFetchClass; $ctorArgs = $this->defaultFetchClassCtorArgs; - if (count($args) >= 2) { - $className = $args[1]; - $ctorArgs = $args[2] ?? []; + if (count($args) > 0) { + $className = $args[0]; + $ctorArgs = $args[1] ?? []; } return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs) ?: false; @@ -372,13 +375,13 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + public function fetchAll($fetchMode = null, ...$args) { $rows = []; switch ($fetchMode) { case FetchMode::CUSTOM_OBJECT: - while (($row = $this->fetch(...func_get_args())) !== false) { + while (($row = $this->fetch($fetchMode, ...$args)) !== false) { $rows[] = $row; } break; diff --git a/lib/Doctrine/DBAL/Portability/Statement.php b/lib/Doctrine/DBAL/Portability/Statement.php index 514b3be2d74..51deeb5aff1 100644 --- a/lib/Doctrine/DBAL/Portability/Statement.php +++ b/lib/Doctrine/DBAL/Portability/Statement.php @@ -8,7 +8,6 @@ use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use IteratorAggregate; -use PDO; use function array_change_key_case; use function assert; use function is_string; @@ -112,11 +111,11 @@ public function execute($params = null) /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, $arg1 = null, $arg2 = null) + public function setFetchMode($fetchMode, ...$args) { $this->defaultFetchMode = $fetchMode; - return $this->stmt->setFetchMode($fetchMode, $arg1, $arg2); + return $this->stmt->setFetchMode($fetchMode, ...$args); } /** @@ -130,11 +129,11 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + public function fetch($fetchMode = null, ...$args) { $fetchMode = $fetchMode ?: $this->defaultFetchMode; - $row = $this->stmt->fetch($fetchMode); + $row = $this->stmt->fetch($fetchMode, ...$args); $iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM); $fixCase = $this->case !== null @@ -149,15 +148,11 @@ public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEX /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + public function fetchAll($fetchMode = null, ...$args) { $fetchMode = $fetchMode ?: $this->defaultFetchMode; - if ($fetchArgument) { - $rows = $this->stmt->fetchAll($fetchMode, $fetchArgument); - } else { - $rows = $this->stmt->fetchAll($fetchMode); - } + $rows = $this->stmt->fetchAll($fetchMode, ...$args); $iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM); $fixCase = $this->case !== null diff --git a/lib/Doctrine/DBAL/Statement.php b/lib/Doctrine/DBAL/Statement.php index 09913bb56ae..e6881093bf7 100644 --- a/lib/Doctrine/DBAL/Statement.php +++ b/lib/Doctrine/DBAL/Statement.php @@ -6,7 +6,6 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\Type; use IteratorAggregate; -use PDO; use Throwable; use function is_array; use function is_string; @@ -213,17 +212,9 @@ public function errorInfo() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + public function setFetchMode($fetchMode, ...$args) { - if ($arg2 === null) { - return $this->stmt->setFetchMode($fetchMode); - } - - if ($arg3 === null) { - return $this->stmt->setFetchMode($fetchMode, $arg2); - } - - return $this->stmt->setFetchMode($fetchMode, $arg2, $arg3); + return $this->stmt->setFetchMode($fetchMode, ...$args); } /** @@ -239,21 +230,17 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + public function fetch($fetchMode = null, ...$args) { - return $this->stmt->fetch($fetchMode); + return $this->stmt->fetch($fetchMode, ...$args); } /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + public function fetchAll($fetchMode = null, ...$args) { - if ($fetchArgument) { - return $this->stmt->fetchAll($fetchMode, $fetchArgument); - } - - return $this->stmt->fetchAll($fetchMode); + return $this->stmt->fetchAll($fetchMode, ...$args); } /** From 5402e4106332d766564e50cbc055b990971ce6df Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Sun, 31 Dec 2017 19:25:28 -0800 Subject: [PATCH 05/13] [DBAL-2958] Replaced PDO constants with values --- composer.json | 1 - lib/Doctrine/DBAL/ColumnCase.php | 6 ++---- lib/Doctrine/DBAL/FetchMode.php | 14 ++++++-------- lib/Doctrine/DBAL/ParameterType.php | 12 +++++------- 4 files changed, 13 insertions(+), 20 deletions(-) diff --git a/composer.json b/composer.json index 4a426e4881a..7d25886269a 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,6 @@ ], "require": { "php": "^7.2", - "ext-pdo": "*", "doctrine/cache": "^1.0", "doctrine/event-manager": "^1.0" }, diff --git a/lib/Doctrine/DBAL/ColumnCase.php b/lib/Doctrine/DBAL/ColumnCase.php index 872d3ede873..c78ad372e65 100644 --- a/lib/Doctrine/DBAL/ColumnCase.php +++ b/lib/Doctrine/DBAL/ColumnCase.php @@ -2,8 +2,6 @@ namespace Doctrine\DBAL; -use PDO; - /** * Contains portable column case conversions. */ @@ -14,14 +12,14 @@ final class ColumnCase * * @see \PDO::CASE_UPPER */ - public const UPPER = PDO::CASE_UPPER; + public const UPPER = 1; /** * Convert column names to lower case. * * @see \PDO::CASE_LOWER */ - public const LOWER = PDO::CASE_LOWER; + public const LOWER = 2; /** * This class cannot be instantiated. diff --git a/lib/Doctrine/DBAL/FetchMode.php b/lib/Doctrine/DBAL/FetchMode.php index b3fe42f4ceb..65af014f1e0 100644 --- a/lib/Doctrine/DBAL/FetchMode.php +++ b/lib/Doctrine/DBAL/FetchMode.php @@ -2,8 +2,6 @@ namespace Doctrine\DBAL; -use PDO; - /** * Contains statement fetch modes. */ @@ -17,7 +15,7 @@ final class FetchMode * * @see \PDO::FETCH_ASSOC */ - public const ASSOCIATIVE = PDO::FETCH_ASSOC; + public const ASSOCIATIVE = 2; /** * Specifies that the fetch method shall return each row as an array indexed @@ -26,7 +24,7 @@ final class FetchMode * * @see \PDO::FETCH_NUM */ - public const NUMERIC = PDO::FETCH_NUM; + public const NUMERIC = 3; /** * Specifies that the fetch method shall return each row as an array indexed @@ -35,7 +33,7 @@ final class FetchMode * * @see \PDO::FETCH_BOTH */ - public const MIXED = PDO::FETCH_BOTH; + public const MIXED = 4; /** * Specifies that the fetch method shall return each row as an object with @@ -44,7 +42,7 @@ final class FetchMode * * @see \PDO::FETCH_OBJ */ - public const STANDARD_OBJECT = PDO::FETCH_OBJ; + public const STANDARD_OBJECT = 5; /** * Specifies that the fetch method shall return only a single requested @@ -52,7 +50,7 @@ final class FetchMode * * @see \PDO::FETCH_COLUMN */ - public const COLUMN = PDO::FETCH_COLUMN; + public const COLUMN = 7; /** * Specifies that the fetch method shall return a new instance of the @@ -60,7 +58,7 @@ final class FetchMode * * @see \PDO::FETCH_CLASS */ - public const CUSTOM_OBJECT = PDO::FETCH_CLASS; + public const CUSTOM_OBJECT = 8; /** * This class cannot be instantiated. diff --git a/lib/Doctrine/DBAL/ParameterType.php b/lib/Doctrine/DBAL/ParameterType.php index 422fee895ee..022b2703ef5 100644 --- a/lib/Doctrine/DBAL/ParameterType.php +++ b/lib/Doctrine/DBAL/ParameterType.php @@ -2,8 +2,6 @@ namespace Doctrine\DBAL; -use PDO; - /** * Contains statement parameter types. */ @@ -14,35 +12,35 @@ final class ParameterType * * @see \PDO::PARAM_NULL */ - public const NULL = PDO::PARAM_NULL; + public const NULL = 0; /** * Represents the SQL INTEGER data type. * * @see \PDO::PARAM_INT */ - public const INTEGER = PDO::PARAM_INT; + public const INTEGER = 1; /** * Represents the SQL CHAR, VARCHAR, or other string data type. * * @see \PDO::PARAM_STR */ - public const STRING = PDO::PARAM_STR; + public const STRING = 2; /** * Represents the SQL large object data type. * * @see \PDO::PARAM_LOB */ - public const LARGE_OBJECT = PDO::PARAM_LOB; + public const LARGE_OBJECT = 3; /** * Represents a boolean data type. * * @see \PDO::PARAM_BOOL */ - public const BOOLEAN = PDO::PARAM_BOOL; + public const BOOLEAN = 5; /** * Represents a binary string data type. From 9638385d5c2fec0e08df87b19ece1862815a8705 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Mon, 25 Dec 2017 13:02:38 -0800 Subject: [PATCH 06/13] [DBAL-2958] Updated UPGRADE.md --- UPGRADE.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/UPGRADE.md b/UPGRADE.md index 59c15565ea7..12d938deaa5 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,37 @@ # Upgrade to 3.0 +## BC BREAK: the PDO symbols are no longer part of the DBAL API + +1. The support of `PDO::PARAM_*`, `PDO::FETCH_*`, `PDO::CASE_*` and `PDO::PARAM_INPUT_OUTPUT` constants in the DBAL API is removed. +2. `\Doctrine\DBAL\Driver\PDOStatement` does not extend `\PDOStatement` anymore. + +Before: + + use Doctrine\DBAL\Portability\Connection; + + $params = array( + 'wrapperClass' => Connection::class, + 'fetch_case' => PDO::CASE_LOWER, + ); + + $stmt->bindValue(1, 1, PDO::PARAM_INT); + $stmt->fetchAll(PDO::FETCH_COLUMN); + +After: + + use Doctrine\DBAL\ColumnCase; + use Doctrine\DBAL\FetchMode; + use Doctrine\DBAL\ParameterType; + use Doctrine\DBAL\Portability\Connection; + + $params = array( + 'wrapperClass' => Connection::class, + 'fetch_case' => ColumnCase::LOWER, + ); + + $stmt->bindValue(1, 1, ParameterType::INTEGER); + $stmt->fetchAll(FetchMode::COLUMN); + ## BC BREAK: Removed dbal:import CLI command The `dbal:import` CLI command has been removed since it only worked with PDO-based drivers by relying on a non-documented behavior of the extension, and it was impossible to make it work with other drivers. From 4e258420a1f1823f5ace3f64fa52bcffe23a8626 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Sun, 1 Apr 2018 19:53:57 -0700 Subject: [PATCH 07/13] [DBAL-3079] Reworked the usage of PDO in PDOConnection from inheritance to composition --- lib/Doctrine/DBAL/Connection.php | 17 ++--- .../Connections/MasterSlaveConnection.php | 9 +-- lib/Doctrine/DBAL/Driver/Connection.php | 5 +- .../DBAL/Driver/IBMDB2/DB2Connection.php | 5 +- .../DBAL/Driver/Mysqli/MysqliConnection.php | 5 +- .../DBAL/Driver/OCI8/OCI8Connection.php | 6 +- lib/Doctrine/DBAL/Driver/PDOConnection.php | 76 +++++++++++++++---- lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php | 8 +- lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php | 6 +- .../SQLAnywhere/SQLAnywhereConnection.php | 7 +- .../DBAL/Driver/SQLSrv/SQLSrvConnection.php | 5 +- lib/Doctrine/DBAL/Portability/Connection.php | 7 +- .../Tests/DBAL/Driver/PDOPgSql/DriverTest.php | 9 ++- .../Tests/DBAL/Functional/DataAccessTest.php | 5 +- .../Functional/Driver/PDOConnectionTest.php | 4 +- .../Driver/PDOSqlsrv/DriverTest.php | 11 ++- .../DBAL/Functional/Ticket/DBAL630Test.php | 16 +++- 17 files changed, 124 insertions(+), 77 deletions(-) diff --git a/lib/Doctrine/DBAL/Connection.php b/lib/Doctrine/DBAL/Connection.php index ee6c08635ce..6386e1f3d23 100644 --- a/lib/Doctrine/DBAL/Connection.php +++ b/lib/Doctrine/DBAL/Connection.php @@ -23,7 +23,6 @@ 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; @@ -994,27 +993,21 @@ public function project($query, array $params, Closure $function) } /** - * 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(); if ($logger) { - $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); diff --git a/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php b/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php index ff310d9196b..00446c3b1a3 100644 --- a/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php +++ b/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php @@ -13,7 +13,6 @@ use function array_rand; use function assert; use function count; -use function func_get_args; /** * Master-Slave Connection @@ -342,19 +341,17 @@ public function rollbackSavepoint($savepoint) /** * {@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(); if ($logger) { - $logger->startQuery($args[0]); + $logger->startQuery($sql); } - $statement = $this->_conn->query(...$args); + $statement = $this->_conn->query($sql); $statement->setFetchMode($this->defaultFetchMode); diff --git a/lib/Doctrine/DBAL/Driver/Connection.php b/lib/Doctrine/DBAL/Driver/Connection.php index 1574581c2ad..8d1d1384db0 100644 --- a/lib/Doctrine/DBAL/Driver/Connection.php +++ b/lib/Doctrine/DBAL/Driver/Connection.php @@ -2,6 +2,7 @@ namespace Doctrine\DBAL\Driver; +use Doctrine\DBAL\DBALException; use Doctrine\DBAL\ParameterType; /** @@ -25,8 +26,10 @@ public function prepare($prepareString); * 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. diff --git a/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php b/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php index cb1e6018f3e..561c9eb22a9 100644 --- a/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php +++ b/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php @@ -22,7 +22,6 @@ 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 @@ public function prepare($sql) /** * {@inheritdoc} */ - public function query() + public function query(string $sql) { - $args = func_get_args(); - $sql = $args[0]; $stmt = $this->prepare($sql); $stmt->execute(); diff --git a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php index 1f1a1d218c3..39ef8b2bd2a 100644 --- a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php +++ b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php @@ -15,7 +15,6 @@ 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 @@ public function prepare($prepareString) /** * {@inheritdoc} */ - public function query() + public function query(string $sql) { - $args = func_get_args(); - $sql = $args[0]; $stmt = $this->prepare($sql); $stmt->execute(); diff --git a/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php b/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php index c1857936f5a..4d95b66628b 100644 --- a/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php +++ b/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php @@ -10,7 +10,6 @@ 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 @@ public function prepare($prepareString) /** * {@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(); diff --git a/lib/Doctrine/DBAL/Driver/PDOConnection.php b/lib/Doctrine/DBAL/Driver/PDOConnection.php index df67a508956..eabd4312b18 100644 --- a/lib/Doctrine/DBAL/Driver/PDOConnection.php +++ b/lib/Doctrine/DBAL/Driver/PDOConnection.php @@ -5,14 +5,17 @@ use Doctrine\DBAL\ParameterType; use PDO; use function assert; -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 @@ -24,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); } @@ -37,7 +40,7 @@ public function __construct($dsn, $user = null, $password = null, ?array $option public function exec($statement) { try { - return parent::exec($statement); + return $this->connection->exec($statement); } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -48,17 +51,17 @@ public function exec($statement) */ 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); @@ -68,12 +71,10 @@ public function prepare($prepareString, $driverOptions = []) /** * {@inheritdoc} */ - public function query() + public function query(string $sql) { - $args = func_get_args(); - try { - $stmt = parent::query(...$args); + $stmt = $this->connection->query($sql); assert($stmt instanceof \PDOStatement); return $this->createStatement($stmt); @@ -87,7 +88,7 @@ public function query() */ public function quote($input, $type = ParameterType::STRING) { - return parent::quote($input, $type); + return $this->connection->quote($input, $type); } /** @@ -97,10 +98,10 @@ public function lastInsertId($name = null) { 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); } @@ -121,4 +122,49 @@ private function createStatement(\PDOStatement $stmt) : PDOStatement { 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; + } } diff --git a/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php b/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php index f25cd5cded3..f77f967ae47 100644 --- a/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php +++ b/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php @@ -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 @@ public function connect(array $params, $username = null, $password = null, array || $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 @@ public function connect(array $params, $username = null, $password = null, array * - 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); } diff --git a/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php b/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php index d08c6a2c848..7c960ab3e14 100644 --- a/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php +++ b/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php @@ -35,7 +35,7 @@ public function connect(array $params, $username = null, $password = null, array } try { - $pdo = new PDOConnection( + $connection = new PDOConnection( $this->_constructPdoDsn($params), $username, $password, @@ -45,11 +45,13 @@ public function connect(array $params, $username = null, $password = null, array 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; } /** diff --git a/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php b/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php index d47782003e6..29de2ab95f3 100644 --- a/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php +++ b/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php @@ -6,7 +6,6 @@ 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 @@ public function prepare($prepareString) /** * {@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; diff --git a/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php b/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php index 35ad913ff5b..f64c5c537b2 100644 --- a/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php +++ b/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php @@ -6,7 +6,6 @@ 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 @@ public function prepare($sql) /** * {@inheritDoc} */ - public function query() + public function query(string $sql) { - $args = func_get_args(); - $sql = $args[0]; $stmt = $this->prepare($sql); $stmt->execute(); diff --git a/lib/Doctrine/DBAL/Portability/Connection.php b/lib/Doctrine/DBAL/Portability/Connection.php index 7b4af8a8799..4a11733f382 100644 --- a/lib/Doctrine/DBAL/Portability/Connection.php +++ b/lib/Doctrine/DBAL/Portability/Connection.php @@ -8,7 +8,6 @@ use PDO; use const CASE_LOWER; use const CASE_UPPER; -use function func_get_args; /** * Portability wrapper for a Connection. @@ -68,7 +67,7 @@ public function connect() 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; } @@ -119,11 +118,11 @@ public function prepare($statement) /** * {@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); diff --git a/tests/Doctrine/Tests/DBAL/Driver/PDOPgSql/DriverTest.php b/tests/Doctrine/Tests/DBAL/Driver/PDOPgSql/DriverTest.php index 2b976233c27..ba0036ebe4a 100644 --- a/tests/Doctrine/Tests/DBAL/Driver/PDOPgSql/DriverTest.php +++ b/tests/Doctrine/Tests/DBAL/Driver/PDOPgSql/DriverTest.php @@ -36,7 +36,7 @@ public function testConnectionDisablesPreparesOnPhp56() : void 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 @@ public function testConnectionDoesNotDisablePreparesOnPhp56WhenAttributeDefined( 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 @@ public function testConnectionDisablePreparesOnPhp56WhenDisablePreparesIsExplici 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'); diff --git a/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php b/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php index b7d625c8600..e6381044a71 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php @@ -954,8 +954,9 @@ private function beforeFetchClassTest() : void } /** @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); } } diff --git a/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOConnectionTest.php b/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOConnectionTest.php index 6dfb1b85c3d..204103a771a 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOConnectionTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOConnectionTest.php @@ -90,7 +90,9 @@ public function testThrowsWrappedExceptionOnPrepare() : void // 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); diff --git a/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOSqlsrv/DriverTest.php b/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOSqlsrv/DriverTest.php index d2dfd5925f5..ef468ccb99c 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOSqlsrv/DriverTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOSqlsrv/DriverTest.php @@ -4,9 +4,11 @@ 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 @@ public function testDriverOptions() : void { $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) + ); } } diff --git a/tests/Doctrine/Tests/DBAL/Functional/Ticket/DBAL630Test.php b/tests/Doctrine/Tests/DBAL/Functional/Ticket/DBAL630Test.php index 687e6e834a0..b146d5a00fa 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Ticket/DBAL630Test.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Ticket/DBAL630Test.php @@ -37,7 +37,9 @@ protected function setUp() : void 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 @@ public function testBooleanConversionBoolParamRealPrepares() : void 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 @@ public function testBooleanConversionNullParamEmulatedPrepares( ?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 @@ public function testBooleanConversionNullParamEmulatedPreparesWithBooleanTypeInB ?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(); From 7c90be8946df1fb144601142f4a80b83c81b9237 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Tue, 10 Apr 2018 23:58:28 -0700 Subject: [PATCH 08/13] [DBAL-3079] Added type hints to query-related method parameters and return values --- .../DBAL/Cache/ResultCacheStatement.php | 2 +- lib/Doctrine/DBAL/Connection.php | 42 +++++++------------ .../Connections/MasterSlaveConnection.php | 12 +++--- lib/Doctrine/DBAL/Driver/Connection.php | 16 ++----- .../DBAL/Driver/IBMDB2/DB2Connection.php | 8 ++-- .../DBAL/Driver/IBMDB2/DB2Statement.php | 2 +- .../DBAL/Driver/Mysqli/MysqliConnection.php | 10 +++-- .../DBAL/Driver/Mysqli/MysqliStatement.php | 2 +- .../DBAL/Driver/OCI8/OCI8Connection.php | 10 +++-- .../DBAL/Driver/OCI8/OCI8Statement.php | 2 +- lib/Doctrine/DBAL/Driver/PDOConnection.php | 8 ++-- lib/Doctrine/DBAL/Driver/PDOStatement.php | 2 +- .../SQLAnywhere/SQLAnywhereConnection.php | 10 +++-- .../SQLAnywhere/SQLAnywhereStatement.php | 2 +- .../DBAL/Driver/SQLSrv/SQLSrvConnection.php | 8 ++-- .../DBAL/Driver/SQLSrv/SQLSrvStatement.php | 2 +- lib/Doctrine/DBAL/Driver/Statement.php | 2 +- lib/Doctrine/DBAL/Portability/Connection.php | 10 +++-- lib/Doctrine/DBAL/Portability/Statement.php | 2 +- lib/Doctrine/DBAL/Statement.php | 2 +- .../Driver/SQLSrv/StatementTest.php | 2 +- tests/Doctrine/Tests/DBAL/StatementTest.php | 16 ++++--- 22 files changed, 81 insertions(+), 91 deletions(-) diff --git a/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php b/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php index 156de78ce2e..b0de89632bb 100644 --- a/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php +++ b/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php @@ -202,7 +202,7 @@ public function fetchColumn($columnIndex = 0) * * @return int The number of rows. */ - public function rowCount() + public function rowCount() : int { assert($this->statement instanceof Statement); diff --git a/lib/Doctrine/DBAL/Connection.php b/lib/Doctrine/DBAL/Connection.php index 6386e1f3d23..8b71224ea0f 100644 --- a/lib/Doctrine/DBAL/Connection.php +++ b/lib/Doctrine/DBAL/Connection.php @@ -846,18 +846,16 @@ public function fetchAll($sql, array $params = [], $types = []) /** * Prepares an SQL statement. * - * @param string $statement The SQL statement to prepare. - * - * @return DriverStatement The prepared statement. + * @param string $sql The SQL statement to prepare. * * @throws DBALException */ - public function prepare($statement) + public function prepare(string $sql) : DriverStatement { try { - $stmt = new Statement($statement, $this); + $stmt = new Statement($sql, $this); } catch (Throwable $ex) { - throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement); + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $sql); } $stmt->setFetchMode($this->defaultFetchMode); @@ -880,7 +878,7 @@ public function prepare($statement) * * @throws DBALException */ - public function executeQuery($query, array $params = [], $types = [], ?QueryCacheProfile $qcp = null) + public function executeQuery(string $query, array $params = [], $types = [], ?QueryCacheProfile $qcp = null) : ResultStatement { if ($qcp !== null) { return $this->executeCacheQuery($query, $params, $types, $qcp); @@ -928,11 +926,9 @@ public function executeQuery($query, array $params = [], $types = [], ?QueryCach * @param int[]|string[] $types The types the previous parameters are in. * @param QueryCacheProfile $qcp The query cache profile. * - * @return ResultStatement - * * @throws CacheException */ - public function executeCacheQuery($query, $params, $types, QueryCacheProfile $qcp) + public function executeCacheQuery($query, $params, $types, QueryCacheProfile $qcp) : ResultStatement { $resultCache = $qcp->getResultCacheDriver() ?? $this->_config->getResultCacheImpl(); @@ -995,7 +991,7 @@ public function project($query, array $params, Closure $function) /** * {@inheritDoc} */ - public function query(string $sql) + public function query(string $sql) : ResultStatement { $connection = $this->getWrappedConnection(); @@ -1029,11 +1025,9 @@ public function query(string $sql) * @param mixed[] $params The query parameters. * @param int[]|string[] $types The parameter types. * - * @return int The number of affected rows. - * * @throws DBALException */ - public function executeUpdate($query, array $params = [], array $types = []) + public function executeUpdate(string $query, array $params = [], array $types = []) : int { $connection = $this->getWrappedConnection(); @@ -1070,15 +1064,9 @@ public function executeUpdate($query, array $params = [], array $types = []) } /** - * Executes an SQL statement and return the number of affected rows. - * - * @param string $statement - * - * @return int The number of affected rows. - * - * @throws DBALException + * {@inheritDoc} */ - public function exec($statement) + public function exec(string $statement) : int { $connection = $this->getWrappedConnection(); @@ -1520,13 +1508,11 @@ public function convertToPHPValue($value, $type) * @internal Duck-typing used on the $stmt parameter to support driver statements as well as * raw PDOStatement instances. * - * @param \Doctrine\DBAL\Driver\Statement $stmt The statement to bind the values to. - * @param mixed[] $params The map/list of named/positional parameters. - * @param int[]|string[] $types The parameter types (PDO binding types or DBAL mapping types). - * - * @return void + * @param DriverStatement $stmt The statement to bind the values to. + * @param mixed[] $params The map/list of named/positional parameters. + * @param int[]|string[] $types The parameter types (PDO binding types or DBAL mapping types). */ - private function _bindTypedValues($stmt, array $params, array $types) + private function _bindTypedValues(DriverStatement $stmt, array $params, array $types) : void { // Check whether parameters are positional or named. Mixing is not allowed, just like in PDO. if (is_int(key($params))) { diff --git a/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php b/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php index 00446c3b1a3..8e6c535f85d 100644 --- a/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php +++ b/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php @@ -7,6 +7,8 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Driver\Connection as DriverConnection; +use Doctrine\DBAL\Driver\ResultStatement; +use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Event\ConnectionEventArgs; use Doctrine\DBAL\Events; use InvalidArgumentException; @@ -218,7 +220,7 @@ protected function chooseConnectionConfiguration($connectionName, $params) /** * {@inheritDoc} */ - public function executeUpdate($query, array $params = [], array $types = []) + public function executeUpdate(string $query, array $params = [], array $types = []) : int { $this->connect('master'); @@ -301,7 +303,7 @@ public function insert($tableName, array $data, array $types = []) /** * {@inheritDoc} */ - public function exec($statement) + public function exec(string $statement) : int { $this->connect('master'); @@ -341,7 +343,7 @@ public function rollbackSavepoint($savepoint) /** * {@inheritDoc} */ - public function query(string $sql) + public function query(string $sql) : ResultStatement { $this->connect('master'); assert($this->_conn instanceof DriverConnection); @@ -365,10 +367,10 @@ public function query(string $sql) /** * {@inheritDoc} */ - public function prepare($statement) + public function prepare(string $sql) : Statement { $this->connect('master'); - return parent::prepare($statement); + return parent::prepare($sql); } } diff --git a/lib/Doctrine/DBAL/Driver/Connection.php b/lib/Doctrine/DBAL/Driver/Connection.php index 8d1d1384db0..2632483e931 100644 --- a/lib/Doctrine/DBAL/Driver/Connection.php +++ b/lib/Doctrine/DBAL/Driver/Connection.php @@ -15,21 +15,15 @@ interface Connection { /** * Prepares a statement for execution and returns a Statement object. - * - * @param string $prepareString - * - * @return Statement */ - public function prepare($prepareString); + public function prepare(string $sql) : Statement; /** * Executes an SQL statement, returning a result set as a Statement object. * - * @return Statement - * * @throws DBALException */ - public function query(string $sql); + public function query(string $sql) : ResultStatement; /** * Quotes a string for use in a query. @@ -44,11 +38,9 @@ public function quote($input, $type = ParameterType::STRING); /** * Executes an SQL statement and return the number of affected rows. * - * @param string $statement - * - * @return int + * @throws DBALException */ - public function exec($statement); + public function exec(string $statement) : int; /** * Returns the ID of the last inserted row or sequence value. diff --git a/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php b/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php index 561c9eb22a9..20ecd7fc86a 100644 --- a/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php +++ b/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php @@ -3,7 +3,9 @@ namespace Doctrine\DBAL\Driver\IBMDB2; use Doctrine\DBAL\Driver\Connection; +use Doctrine\DBAL\Driver\ResultStatement; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\Driver\Statement as DriverStatement; use Doctrine\DBAL\ParameterType; use stdClass; use const DB2_AUTOCOMMIT_OFF; @@ -75,7 +77,7 @@ public function requiresQueryForServerVersion() /** * {@inheritdoc} */ - public function prepare($sql) + public function prepare(string $sql) : DriverStatement { $stmt = @db2_prepare($this->conn, $sql); if (! $stmt) { @@ -88,7 +90,7 @@ public function prepare($sql) /** * {@inheritdoc} */ - public function query(string $sql) + public function query(string $sql) : ResultStatement { $stmt = $this->prepare($sql); $stmt->execute(); @@ -113,7 +115,7 @@ public function quote($input, $type = ParameterType::STRING) /** * {@inheritdoc} */ - public function exec($statement) + public function exec(string $statement) : int { $stmt = @db2_exec($this->conn, $statement); diff --git a/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php b/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php index b77067bd4da..07fc87c08f3 100644 --- a/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php +++ b/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php @@ -344,7 +344,7 @@ public function fetchColumn($columnIndex = 0) /** * {@inheritdoc} */ - public function rowCount() + public function rowCount() : int { return @db2_num_rows($this->stmt) ? : 0; } diff --git a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php index 39ef8b2bd2a..80a23087591 100644 --- a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php +++ b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php @@ -4,7 +4,9 @@ use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\PingableConnection; +use Doctrine\DBAL\Driver\ResultStatement; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\Driver\Statement as DriverStatement; use Doctrine\DBAL\ParameterType; use mysqli; use const MYSQLI_INIT_COMMAND; @@ -125,15 +127,15 @@ public function requiresQueryForServerVersion() /** * {@inheritdoc} */ - public function prepare($prepareString) + public function prepare(string $sql) : DriverStatement { - return new MysqliStatement($this->conn, $prepareString); + return new MysqliStatement($this->conn, $sql); } /** * {@inheritdoc} */ - public function query(string $sql) + public function query(string $sql) : ResultStatement { $stmt = $this->prepare($sql); $stmt->execute(); @@ -152,7 +154,7 @@ public function quote($input, $type = ParameterType::STRING) /** * {@inheritdoc} */ - public function exec($statement) + public function exec(string $statement) : int { if ($this->conn->query($statement) === false) { throw new MysqliException($this->conn->error, $this->conn->sqlstate, $this->conn->errno); diff --git a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php index acf8b4ec54c..eff8f88c569 100644 --- a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php +++ b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php @@ -415,7 +415,7 @@ public function closeCursor() /** * {@inheritdoc} */ - public function rowCount() + public function rowCount() : int { if ($this->_columnNames === false) { return $this->_stmt->affected_rows; diff --git a/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php b/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php index 4d95b66628b..ce651559eb5 100644 --- a/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php +++ b/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php @@ -3,7 +3,9 @@ namespace Doctrine\DBAL\Driver\OCI8; use Doctrine\DBAL\Driver\Connection; +use Doctrine\DBAL\Driver\ResultStatement; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\Driver\Statement as DriverStatement; use Doctrine\DBAL\ParameterType; use UnexpectedValueException; use const OCI_COMMIT_ON_SUCCESS; @@ -102,15 +104,15 @@ public function requiresQueryForServerVersion() /** * {@inheritdoc} */ - public function prepare($prepareString) + public function prepare(string $sql) : DriverStatement { - return new OCI8Statement($this->dbh, $prepareString, $this); + return new OCI8Statement($this->dbh, $sql, $this); } /** * {@inheritdoc} */ - public function query(string $sql) + public function query(string $sql) : ResultStatement { $stmt = $this->prepare($sql); $stmt->execute(); @@ -134,7 +136,7 @@ public function quote($value, $type = ParameterType::STRING) /** * {@inheritdoc} */ - public function exec($statement) + public function exec(string $statement) : int { $stmt = $this->prepare($statement); $stmt->execute(); diff --git a/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php b/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php index a244db8a6cd..27bc78cf4df 100644 --- a/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php +++ b/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php @@ -529,7 +529,7 @@ public function fetchColumn($columnIndex = 0) /** * {@inheritdoc} */ - public function rowCount() + public function rowCount() : int { return oci_num_rows($this->_sth) ?: 0; } diff --git a/lib/Doctrine/DBAL/Driver/PDOConnection.php b/lib/Doctrine/DBAL/Driver/PDOConnection.php index eabd4312b18..5db1538b9ec 100644 --- a/lib/Doctrine/DBAL/Driver/PDOConnection.php +++ b/lib/Doctrine/DBAL/Driver/PDOConnection.php @@ -37,7 +37,7 @@ public function __construct($dsn, $user = null, $password = null, ?array $option /** * {@inheritdoc} */ - public function exec($statement) + public function exec(string $statement) : int { try { return $this->connection->exec($statement); @@ -57,11 +57,11 @@ public function getServerVersion() /** * {@inheritdoc} */ - public function prepare($prepareString) + public function prepare(string $sql) : Statement { try { return $this->createStatement( - $this->connection->prepare($prepareString) + $this->connection->prepare($sql) ); } catch (\PDOException $exception) { throw new PDOException($exception); @@ -71,7 +71,7 @@ public function prepare($prepareString) /** * {@inheritdoc} */ - public function query(string $sql) + public function query(string $sql) : ResultStatement { try { $stmt = $this->connection->query($sql); diff --git a/lib/Doctrine/DBAL/Driver/PDOStatement.php b/lib/Doctrine/DBAL/Driver/PDOStatement.php index 92125768340..ae7b78616c4 100644 --- a/lib/Doctrine/DBAL/Driver/PDOStatement.php +++ b/lib/Doctrine/DBAL/Driver/PDOStatement.php @@ -127,7 +127,7 @@ public function execute($params = null) } } - public function rowCount() + public function rowCount() : int { return $this->stmt->rowCount(); } diff --git a/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php b/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php index 29de2ab95f3..6c117904c58 100644 --- a/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php +++ b/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php @@ -3,7 +3,9 @@ namespace Doctrine\DBAL\Driver\SQLAnywhere; use Doctrine\DBAL\Driver\Connection; +use Doctrine\DBAL\Driver\ResultStatement; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\Driver\Statement as DriverStatement; use Doctrine\DBAL\ParameterType; use function assert; use function is_float; @@ -106,7 +108,7 @@ public function errorInfo() /** * {@inheritdoc} */ - public function exec($statement) + public function exec(string $statement) : int { if (sasql_real_query($this->connection, $statement) === false) { throw SQLAnywhereException::fromSQLAnywhereError($this->connection); @@ -142,15 +144,15 @@ public function lastInsertId($name = null) /** * {@inheritdoc} */ - public function prepare($prepareString) + public function prepare(string $sql) : DriverStatement { - return new SQLAnywhereStatement($this->connection, $prepareString); + return new SQLAnywhereStatement($this->connection, $sql); } /** * {@inheritdoc} */ - public function query(string $sql) + public function query(string $sql) : ResultStatement { $stmt = $this->prepare($sql); $stmt->execute(); diff --git a/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php b/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php index afe569104e2..31d4aec7210 100644 --- a/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php +++ b/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php @@ -297,7 +297,7 @@ public function getIterator() /** * {@inheritdoc} */ - public function rowCount() + public function rowCount() : int { return sasql_stmt_affected_rows($this->stmt); } diff --git a/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php b/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php index f64c5c537b2..caa04efce5f 100644 --- a/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php +++ b/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php @@ -3,7 +3,9 @@ namespace Doctrine\DBAL\Driver\SQLSrv; use Doctrine\DBAL\Driver\Connection; +use Doctrine\DBAL\Driver\ResultStatement; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\Driver\Statement as DriverStatement; use Doctrine\DBAL\ParameterType; use const SQLSRV_ERR_ERRORS; use function is_float; @@ -74,7 +76,7 @@ public function requiresQueryForServerVersion() /** * {@inheritDoc} */ - public function prepare($sql) + public function prepare(string $sql) : DriverStatement { return new SQLSrvStatement($this->conn, $sql, $this->lastInsertId); } @@ -82,7 +84,7 @@ public function prepare($sql) /** * {@inheritDoc} */ - public function query(string $sql) + public function query(string $sql) : ResultStatement { $stmt = $this->prepare($sql); $stmt->execute(); @@ -109,7 +111,7 @@ public function quote($value, $type = ParameterType::STRING) /** * {@inheritDoc} */ - public function exec($statement) + public function exec(string $statement) : int { $stmt = sqlsrv_query($this->conn, $statement); diff --git a/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php b/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php index 905d16fb997..aad7fb33a90 100644 --- a/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php +++ b/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php @@ -418,7 +418,7 @@ public function fetchColumn($columnIndex = 0) /** * {@inheritdoc} */ - public function rowCount() + public function rowCount() : int { if ($this->stmt === null) { return 0; diff --git a/lib/Doctrine/DBAL/Driver/Statement.php b/lib/Doctrine/DBAL/Driver/Statement.php index 3c778eeb74c..fd3c0bd0bf6 100644 --- a/lib/Doctrine/DBAL/Driver/Statement.php +++ b/lib/Doctrine/DBAL/Driver/Statement.php @@ -100,5 +100,5 @@ public function execute($params = null); * * @return int The number of rows. */ - public function rowCount(); + public function rowCount() : int; } diff --git a/lib/Doctrine/DBAL/Portability/Connection.php b/lib/Doctrine/DBAL/Portability/Connection.php index 4a11733f382..dc3ac088812 100644 --- a/lib/Doctrine/DBAL/Portability/Connection.php +++ b/lib/Doctrine/DBAL/Portability/Connection.php @@ -5,6 +5,8 @@ use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\ColumnCase; use Doctrine\DBAL\Driver\PDOConnection; +use Doctrine\DBAL\Driver\ResultStatement; +use Doctrine\DBAL\Driver\Statement as DriverStatement; use PDO; use const CASE_LOWER; use const CASE_UPPER; @@ -96,7 +98,7 @@ public function getFetchCase() /** * {@inheritdoc} */ - public function executeQuery($query, array $params = [], $types = [], ?QueryCacheProfile $qcp = null) + public function executeQuery(string $query, array $params = [], $types = [], ?QueryCacheProfile $qcp = null) : ResultStatement { $stmt = new Statement(parent::executeQuery($query, $params, $types, $qcp), $this); $stmt->setFetchMode($this->defaultFetchMode); @@ -107,9 +109,9 @@ public function executeQuery($query, array $params = [], $types = [], ?QueryCach /** * {@inheritdoc} */ - public function prepare($statement) + public function prepare(string $sql) : DriverStatement { - $stmt = new Statement(parent::prepare($statement), $this); + $stmt = new Statement(parent::prepare($sql), $this); $stmt->setFetchMode($this->defaultFetchMode); return $stmt; @@ -118,7 +120,7 @@ public function prepare($statement) /** * {@inheritdoc} */ - public function query(string $sql) + public function query(string $sql) : ResultStatement { $connection = $this->getWrappedConnection(); diff --git a/lib/Doctrine/DBAL/Portability/Statement.php b/lib/Doctrine/DBAL/Portability/Statement.php index 51deeb5aff1..38173c286d4 100644 --- a/lib/Doctrine/DBAL/Portability/Statement.php +++ b/lib/Doctrine/DBAL/Portability/Statement.php @@ -233,7 +233,7 @@ public function fetchColumn($columnIndex = 0) /** * {@inheritdoc} */ - public function rowCount() + public function rowCount() : int { assert($this->stmt instanceof DriverStatement); diff --git a/lib/Doctrine/DBAL/Statement.php b/lib/Doctrine/DBAL/Statement.php index e6881093bf7..0ea10de3e58 100644 --- a/lib/Doctrine/DBAL/Statement.php +++ b/lib/Doctrine/DBAL/Statement.php @@ -256,7 +256,7 @@ public function fetchColumn($columnIndex = 0) * * @return int The number of affected rows. */ - public function rowCount() + public function rowCount() : int { return $this->stmt->rowCount(); } diff --git a/tests/Doctrine/Tests/DBAL/Functional/Driver/SQLSrv/StatementTest.php b/tests/Doctrine/Tests/DBAL/Functional/Driver/SQLSrv/StatementTest.php index 4e34f693c0c..29df5aea958 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Driver/SQLSrv/StatementTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Driver/SQLSrv/StatementTest.php @@ -27,7 +27,7 @@ protected function setUp() : void public function testFailureToPrepareResultsInException() : void { // use the driver connection directly to avoid having exception wrapped - $stmt = $this->connection->getWrappedConnection()->prepare(null); + $stmt = $this->connection->getWrappedConnection()->prepare(''); // it's impossible to prepare the statement without bound variables for SQL Server, // so the preparation happens before the first execution when variables are already in place diff --git a/tests/Doctrine/Tests/DBAL/StatementTest.php b/tests/Doctrine/Tests/DBAL/StatementTest.php index bb86e9cab3c..1d152bcb56b 100644 --- a/tests/Doctrine/Tests/DBAL/StatementTest.php +++ b/tests/Doctrine/Tests/DBAL/StatementTest.php @@ -7,6 +7,7 @@ use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Driver\Connection as DriverConnection; +use Doctrine\DBAL\Driver\Statement as DriverStatement; use Doctrine\DBAL\Logging\SQLLogger; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Statement; @@ -23,18 +24,15 @@ class StatementTest extends DbalTestCase private $configuration; /** @var PDOStatement */ - private $pdoStatement; + private $driverStatement; protected function setUp() : void { - $this->pdoStatement = $this->getMockBuilder(PDOStatement::class) - ->onlyMethods(['execute', 'bindParam', 'bindValue']) - ->getMock(); + $this->driverStatement = $this->createMock(DriverStatement::class); - $driverConnection = $this->createMock(DriverConnection::class); - $driverConnection->expects($this->any()) - ->method('prepare') - ->will($this->returnValue($this->pdoStatement)); + $driverConnection = $this->createConfiguredMock(DriverConnection::class, [ + 'prepare' => $this->driverStatement, + ]); $driver = $this->createMock(Driver::class); @@ -140,7 +138,7 @@ public function testExecuteCallsLoggerStopQueryOnException() : void $logger->expects($this->once()) ->method('stopQuery'); - $this->pdoStatement->expects($this->once()) + $this->driverStatement->expects($this->once()) ->method('execute') ->will($this->throwException(new Exception('Mock test exception'))); From 19c29a951a492ebe211262f753e42b9212b308d6 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Wed, 11 Apr 2018 20:27:31 -0700 Subject: [PATCH 09/13] [DBAL-3079] Updated upgrade documentation --- UPGRADE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UPGRADE.md b/UPGRADE.md index 12d938deaa5..15ee6face47 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -3,7 +3,8 @@ ## BC BREAK: the PDO symbols are no longer part of the DBAL API 1. The support of `PDO::PARAM_*`, `PDO::FETCH_*`, `PDO::CASE_*` and `PDO::PARAM_INPUT_OUTPUT` constants in the DBAL API is removed. -2. `\Doctrine\DBAL\Driver\PDOStatement` does not extend `\PDOStatement` anymore. +2. `\Doctrine\DBAL\Driver\PDOConnection` does not extend `\PDO` anymore. Please use `\Doctrine\DBAL\Driver\PDOConnection::getWrappedConnection()` to access the underlying `PDO` object. +3. `\Doctrine\DBAL\Driver\PDOStatement` does not extend `\PDOStatement` anymore. Before: From 7f8e2b1f64f91d868c4d3600e6aabf4c68739876 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Mon, 19 Mar 2018 22:15:10 -0700 Subject: [PATCH 10/13] [DBAL-3060] Fixed build failure on SQL Server (pdo_sqlsrv) Use a wrapped PDO Statement instead of a custom class for `pdo_sqlsrv` since `PDOSqlsrv\Statement` doesn't extend `PDOStatement` anymore. --- lib/Doctrine/DBAL/Driver/PDOConnection.php | 2 +- .../DBAL/Driver/PDOSqlsrv/Connection.php | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/Doctrine/DBAL/Driver/PDOConnection.php b/lib/Doctrine/DBAL/Driver/PDOConnection.php index 5db1538b9ec..995ebee6adb 100644 --- a/lib/Doctrine/DBAL/Driver/PDOConnection.php +++ b/lib/Doctrine/DBAL/Driver/PDOConnection.php @@ -118,7 +118,7 @@ public function requiresQueryForServerVersion() /** * Creates a wrapped statement */ - private function createStatement(\PDOStatement $stmt) : PDOStatement + protected function createStatement(\PDOStatement $stmt) : PDOStatement { return new PDOStatement($stmt); } diff --git a/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php b/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php index bd3894477b5..33331bd0a5a 100644 --- a/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php +++ b/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php @@ -3,8 +3,8 @@ namespace Doctrine\DBAL\Driver\PDOSqlsrv; use Doctrine\DBAL\Driver\PDOConnection; +use Doctrine\DBAL\Driver\PDOStatement; use Doctrine\DBAL\ParameterType; -use PDO; use function strpos; use function substr; @@ -13,15 +13,6 @@ */ class Connection extends PDOConnection { - /** - * {@inheritdoc} - */ - public function __construct($dsn, $user = null, $password = null, ?array $options = null) - { - parent::__construct($dsn, $user, $password, $options); - $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, [Statement::class, []]); - } - /** * {@inheritDoc} */ @@ -51,4 +42,12 @@ public function quote($value, $type = ParameterType::STRING) return $val; } + + /** + * {@inheritDoc} + */ + protected function createStatement(\PDOStatement $stmt) : PDOStatement + { + return new Statement($stmt); + } } From 87edf7ad02446f3f3f816d2d95017344f0642cd4 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Thu, 2 Aug 2018 23:24:39 -0700 Subject: [PATCH 11/13] [DBAL-3798] Suppressed issues found by PHPStan --- phpstan.neon.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 4ae1fda3f8a..a9523aac100 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -29,7 +29,7 @@ parameters: - '~^Method Doctrine\\DBAL\\Driver\\SQLSrv\\SQLSrvConnection::errorCode\(\) should return string\|null but returns false\.\z~' # https://bugs.php.net/bug.php?id=78126 - - '~^Call to an undefined method Doctrine\\DBAL\\Driver\\PDOConnection::sqliteCreateFunction\(\)\.\z~' + - '~^Call to an undefined method PDO::sqliteCreateFunction\(\)\.\z~' # https://github.com/phpstan/phpstan/issues/1847 - '~^Parameter #2 \$registeredAliases of static method Doctrine\\DBAL\\Query\\QueryException::unknownAlias\(\) expects array, array given\.\z~' From d9c4e3d8e0d4f7c52838b7880039e2203adbe1c2 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Sat, 13 Apr 2019 23:50:35 -0700 Subject: [PATCH 12/13] [DBAL-3515] Implemented support for persistent connections in PDO and mysqli drivers --- .../DBAL/Driver/Mysqli/MysqliConnection.php | 7 ++++- lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php | 5 ++++ lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php | 5 ++++ lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php | 4 +++ lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php | 5 ++++ .../Tests/DBAL/Functional/ConnectionTest.php | 28 +++++++++++++++++++ 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php index 80a23087591..a9047b10ef7 100644 --- a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php +++ b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php @@ -57,6 +57,11 @@ public function __construct(array $params, $username, $password, array $driverOp $socket = $params['unix_socket'] ?? ini_get('mysqli.default_socket'); $dbname = $params['dbname'] ?? null; + $host = $params['host']; + + if (! empty($params['persistent'])) { + $host = 'p:' . $host; + } $flags = $driverOptions[static::OPTION_FLAGS] ?? null; @@ -68,7 +73,7 @@ public function __construct(array $params, $username, $password, array $driverOp set_error_handler(static function () { }); try { - if (! $this->conn->real_connect($params['host'], $username, $password, $dbname, $port, $socket, $flags)) { + if (! $this->conn->real_connect($host, $username, $password, $dbname, $port, $socket, $flags)) { throw new MysqliException($this->conn->connect_error, $this->conn->sqlstate ?? 'HY000', $this->conn->connect_errno); } } finally { diff --git a/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php b/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php index dcd4ff51895..b90f153f7d2 100644 --- a/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php +++ b/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php @@ -5,6 +5,7 @@ use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\AbstractMySQLDriver; use Doctrine\DBAL\Driver\PDOConnection; +use PDO; use PDOException; /** @@ -17,6 +18,10 @@ class Driver extends AbstractMySQLDriver */ public function connect(array $params, $username = null, $password = null, array $driverOptions = []) { + if (! empty($params['persistent'])) { + $driverOptions[PDO::ATTR_PERSISTENT] = true; + } + try { $conn = new PDOConnection( $this->constructPdoDsn($params), diff --git a/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php b/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php index f1239eafbd4..942cf6740dc 100644 --- a/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php +++ b/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php @@ -5,6 +5,7 @@ use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\AbstractOracleDriver; use Doctrine\DBAL\Driver\PDOConnection; +use PDO; use PDOException; /** @@ -22,6 +23,10 @@ class Driver extends AbstractOracleDriver */ public function connect(array $params, $username = null, $password = null, array $driverOptions = []) { + if (! empty($params['persistent'])) { + $driverOptions[PDO::ATTR_PERSISTENT] = true; + } + try { return new PDOConnection( $this->constructPdoDsn($params), diff --git a/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php b/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php index f77f967ae47..563b6dd3a2d 100644 --- a/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php +++ b/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php @@ -19,6 +19,10 @@ class Driver extends AbstractPostgreSQLDriver */ public function connect(array $params, $username = null, $password = null, array $driverOptions = []) { + if (! empty($params['persistent'])) { + $driverOptions[PDO::ATTR_PERSISTENT] = true; + } + try { $connection = new PDOConnection( $this->_constructPdoDsn($params), diff --git a/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php b/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php index 6d6c4844d57..5fbba4c245f 100644 --- a/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php +++ b/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php @@ -3,6 +3,7 @@ namespace Doctrine\DBAL\Driver\PDOSqlsrv; use Doctrine\DBAL\Driver\AbstractSQLServerDriver; +use PDO; use function is_int; use function sprintf; @@ -26,6 +27,10 @@ public function connect(array $params, $username = null, $password = null, array } } + if (! empty($params['persistent'])) { + $pdoOptions[PDO::ATTR_PERSISTENT] = true; + } + return new Connection( $this->_constructPdoDsn($params, $dsnOptions), $username, diff --git a/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php b/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php index 655b5897c72..ea8d193b1fa 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php @@ -5,11 +5,15 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\ConnectionException; use Doctrine\DBAL\Driver\Connection as DriverConnection; +use Doctrine\DBAL\Driver\PDOConnection; use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Platforms\SqlitePlatform; +use Doctrine\DBAL\Platforms\SQLServerPlatform; use Doctrine\DBAL\Types\Types; use Doctrine\Tests\DbalFunctionalTestCase; +use Doctrine\Tests\TestUtil; use Error; use Exception; use PDO; @@ -364,4 +368,28 @@ public function testUserProvidedPDOConnection() : void ])->ping() ); } + + public function testPersistentConnection() : void + { + $platform = $this->connection->getDatabasePlatform(); + + if ($platform instanceof SqlitePlatform + || $platform instanceof SQLServerPlatform) { + self::markTestSkipped('The platform does not support persistent connections'); + } + + $params = TestUtil::getConnectionParams(); + $params['persistent'] = true; + + $connection = DriverManager::getConnection($params); + $driverConnection = $connection->getWrappedConnection(); + + if (! $driverConnection instanceof PDOConnection) { + self::markTestSkipped('Unable to test if the connection is persistent'); + } + + $pdo = $driverConnection->getWrappedConnection(); + + self::assertTrue($pdo->getAttribute(PDO::ATTR_PERSISTENT)); + } } From dcc3f2d4dcea0e7e82cfd3bfd4c1adbc925c746a Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Mon, 20 May 2019 15:22:56 -0700 Subject: [PATCH 13/13] [DBAL-3548] Remove user provided PDO functionality --- UPGRADE.md | 4 + lib/Doctrine/DBAL/Connection.php | 6 - lib/Doctrine/DBAL/DriverManager.php | 17 +-- tests/Doctrine/Tests/DBAL/ConnectionTest.php | 77 ++---------- .../Tests/DBAL/Driver/PDOExceptionTest.php | 8 +- .../Doctrine/Tests/DBAL/DriverManagerTest.php | 118 +----------------- .../Tests/DBAL/Functional/ConnectionTest.php | 12 -- .../Functional/Driver/PDOConnectionTest.php | 8 +- 8 files changed, 26 insertions(+), 224 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index 15ee6face47..402083b5ac7 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,9 @@ # Upgrade to 3.0 +## BC BREAK User-provided `PDO` instance is no longer supported + +In order to share the same `PDO` instances between DBAL and other components, initialize the connection in DBAL and access it using `Connection::getWrappedConnection()->getWrappedConnection()`. + ## BC BREAK: the PDO symbols are no longer part of the DBAL API 1. The support of `PDO::PARAM_*`, `PDO::FETCH_*`, `PDO::CASE_*` and `PDO::PARAM_INPUT_OUTPUT` constants in the DBAL API is removed. diff --git a/lib/Doctrine/DBAL/Connection.php b/lib/Doctrine/DBAL/Connection.php index 8b71224ea0f..bc53ded5d85 100644 --- a/lib/Doctrine/DBAL/Connection.php +++ b/lib/Doctrine/DBAL/Connection.php @@ -187,12 +187,6 @@ public function __construct( $this->_driver = $driver; $this->params = $params; - if (isset($params['pdo'])) { - $this->_conn = $params['pdo']; - $this->isConnected = true; - unset($this->params['pdo']); - } - if (isset($params['platform'])) { if (! $params['platform'] instanceof Platforms\AbstractPlatform) { throw DBALException::invalidPlatformType($params['platform']); diff --git a/lib/Doctrine/DBAL/DriverManager.php b/lib/Doctrine/DBAL/DriverManager.php index 6888d73b0c4..1872a2e57a0 100644 --- a/lib/Doctrine/DBAL/DriverManager.php +++ b/lib/Doctrine/DBAL/DriverManager.php @@ -14,7 +14,6 @@ use Doctrine\DBAL\Driver\PDOSqlsrv\Driver as PDOSQLSrvDriver; use Doctrine\DBAL\Driver\SQLAnywhere\Driver as SQLAnywhereDriver; use Doctrine\DBAL\Driver\SQLSrv\Driver as SQLSrvDriver; -use PDO; use function array_keys; use function array_map; use function array_merge; @@ -171,17 +170,7 @@ public static function getConnection( } } - // check for existing pdo object - if (isset($params['pdo']) && ! $params['pdo'] instanceof PDO) { - throw DBALException::invalidPdoInstance(); - } - - if (isset($params['pdo'])) { - $params['pdo']->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $params['driver'] = 'pdo_' . $params['pdo']->getAttribute(PDO::ATTR_DRIVER_NAME); - } else { - self::_checkParams($params); - } + self::_checkParams($params); $className = $params['driverClass'] ?? self::$_driverMap[$params['driver']]; @@ -277,10 +266,6 @@ private static function parseDatabaseUrl(array $params) : array $url = array_map('rawurldecode', $url); - // If we have a connection URL, we have to unset the default PDO instance connection parameter (if any) - // as we cannot merge connection details from the URL into the PDO instance (URL takes precedence). - unset($params['pdo']); - $params = self::parseDatabaseUrlScheme($url, $params); if (isset($url['host'])) { diff --git a/tests/Doctrine/Tests/DBAL/ConnectionTest.php b/tests/Doctrine/Tests/DBAL/ConnectionTest.php index fb0157314d6..9cb31486b21 100644 --- a/tests/Doctrine/Tests/DBAL/ConnectionTest.php +++ b/tests/Doctrine/Tests/DBAL/ConnectionTest.php @@ -27,7 +27,6 @@ use Exception; use PHPUnit\Framework\MockObject\MockObject; use stdClass; -use function call_user_func_array; /** * @requires extension pdo_mysql @@ -686,82 +685,28 @@ public function testFetchAll() : void self::assertSame($result, $conn->fetchAll($statement, $params, $types)); } - public function testConnectionDoesNotMaintainTwoReferencesToExternalPDO() : void - { - $params['pdo'] = new stdClass(); - - $driverMock = $this->createMock(Driver::class); - - $conn = new Connection($params, $driverMock); - - self::assertArrayNotHasKey('pdo', $conn->getParams(), 'Connection is maintaining additional reference to the PDO connection'); - } - - public function testPassingExternalPDOMeansConnectionIsConnected() : void - { - $params['pdo'] = new stdClass(); - - $driverMock = $this->createMock(Driver::class); - - $conn = new Connection($params, $driverMock); - - self::assertTrue($conn->isConnected(), 'Connection is not connected after passing external PDO'); - } - public function testCallingDeleteWithNoDeletionCriteriaResultsInInvalidArgumentException() : void { /** @var Driver $driver */ - $driver = $this->createMock(Driver::class); - $pdoMock = $this->createMock(\Doctrine\DBAL\Driver\Connection::class); - - // should never execute queries with invalid arguments - $pdoMock->expects($this->never())->method('exec'); - $pdoMock->expects($this->never())->method('prepare'); - - $conn = new Connection(['pdo' => $pdoMock], $driver); + $driver = $this->createMock(Driver::class); + $conn = new Connection([], $driver); $this->expectException(InvalidArgumentException::class); $conn->delete('kittens', []); } - /** - * @return array> - */ - public static function dataCallConnectOnce() : iterable - { - return [ - ['delete', ['tbl', ['id' => 12345]]], - ['insert', ['tbl', ['data' => 'foo']]], - ['update', ['tbl', ['data' => 'bar'], ['id' => 12345]]], - ['prepare', ['select * from dual']], - ['executeUpdate', ['insert into tbl (id) values (?)'], [123]], - ]; - } - - /** - * @param array $params - * - * @dataProvider dataCallConnectOnce - */ - public function testCallConnectOnce(string $method, array $params) : void + public function testCallConnectOnce() : void { - $driverMock = $this->createMock(Driver::class); - $pdoMock = $this->createMock(Connection::class); - $platformMock = $this->createMock(AbstractPlatform::class); - $stmtMock = $this->createMock(Statement::class); - - $pdoMock->expects($this->any()) - ->method('prepare') - ->will($this->returnValue($stmtMock)); - - $conn = $this->getMockBuilder(Connection::class) - ->setConstructorArgs([['pdo' => $pdoMock, 'platform' => $platformMock], $driverMock]) - ->onlyMethods(['connect']) - ->getMock(); + /** @var Driver|MockObject $driver */ + $driver = $this->createMock(Driver::class); + $driver->expects($this->once()) + ->method('connect'); - $conn->expects($this->once())->method('connect'); + $platform = $this->createMock(AbstractPlatform::class); - call_user_func_array([$conn, $method], $params); + $conn = new Connection(['platform' => $platform], $driver); + $conn->connect(); + $conn->connect(); } /** diff --git a/tests/Doctrine/Tests/DBAL/Driver/PDOExceptionTest.php b/tests/Doctrine/Tests/DBAL/Driver/PDOExceptionTest.php index 9ed9a06aa5b..c8c3b92b017 100644 --- a/tests/Doctrine/Tests/DBAL/Driver/PDOExceptionTest.php +++ b/tests/Doctrine/Tests/DBAL/Driver/PDOExceptionTest.php @@ -5,8 +5,10 @@ use Doctrine\DBAL\Driver\PDOException; use Doctrine\Tests\DbalTestCase; use PHPUnit\Framework\MockObject\MockObject; -use function extension_loaded; +/** + * @requires extension pdo + */ class PDOExceptionTest extends DbalTestCase { public const ERROR_CODE = 666; @@ -31,10 +33,6 @@ class PDOExceptionTest extends DbalTestCase protected function setUp() : void { - if (! extension_loaded('PDO')) { - $this->markTestSkipped('PDO is not installed.'); - } - parent::setUp(); $this->wrappedException = new \PDOException(self::MESSAGE, self::SQLSTATE); diff --git a/tests/Doctrine/Tests/DBAL/DriverManagerTest.php b/tests/Doctrine/Tests/DBAL/DriverManagerTest.php index ced3e5d993f..08ed2f106ee 100644 --- a/tests/Doctrine/Tests/DBAL/DriverManagerTest.php +++ b/tests/Doctrine/Tests/DBAL/DriverManagerTest.php @@ -15,50 +15,13 @@ use Doctrine\DBAL\Sharding\PoolingShardConnection; use Doctrine\DBAL\Sharding\ShardChoser\MultiTenantShardChoser; use Doctrine\Tests\DbalTestCase; -use PDO; use stdClass; -use function extension_loaded; use function get_class; use function in_array; use function is_array; class DriverManagerTest extends DbalTestCase { - /** - * @requires extension pdo_sqlite - */ - public function testInvalidPdoInstance() : void - { - $this->expectException(DBALException::class); - DriverManager::getConnection(['pdo' => 'test']); - } - - /** - * @requires extension pdo_sqlite - */ - public function testValidPdoInstance() : void - { - $conn = DriverManager::getConnection([ - 'pdo' => new PDO('sqlite::memory:'), - ]); - - self::assertEquals('sqlite', $conn->getDatabasePlatform()->getName()); - } - - /** - * @group DBAL-32 - * @requires extension pdo_sqlite - */ - public function testPdoInstanceSetErrorMode() : void - { - $pdo = new PDO('sqlite::memory:'); - $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); - $options = ['pdo' => $pdo]; - - DriverManager::getConnection($options); - self::assertEquals(PDO::ERRMODE_EXCEPTION, $pdo->getAttribute(PDO::ATTR_ERRMODE)); - } - public function testCheckParams() : void { $this->expectException(DBALException::class); @@ -80,7 +43,7 @@ public function testCustomPlatform() : void { $platform = $this->createMock(AbstractPlatform::class); $options = [ - 'pdo' => new PDO('sqlite::memory:'), + 'url' => 'sqlite::memory:', 'platform' => $platform, ]; @@ -97,7 +60,7 @@ public function testCustomWrapper() : void $wrapperClass = get_class($wrapper); $options = [ - 'pdo' => new PDO('sqlite::memory:'), + 'url' => 'sqlite::memory:', 'wrapperClass' => $wrapperClass, ]; @@ -113,7 +76,7 @@ public function testInvalidWrapperClass() : void $this->expectException(DBALException::class); $options = [ - 'pdo' => new PDO('sqlite::memory:'), + 'url' => 'sqlite::memory:', 'wrapperClass' => stdClass::class, ]; @@ -215,16 +178,6 @@ public function testDatabaseUrl($url, $expected) : void { $options = is_array($url) ? $url : ['url' => $url]; - if (isset($options['pdo'])) { - if (! extension_loaded('pdo')) { - $this->markTestSkipped('PDO is not installed'); - } - - $options['pdo'] = $this->createMock(PDO::class); - } - - $options = is_array($url) ? $url : ['url' => $url]; - if ($expected === false) { $this->expectException(DBALException::class); } @@ -233,7 +186,7 @@ public function testDatabaseUrl($url, $expected) : void $params = $conn->getParams(); foreach ($expected as $key => $value) { - if (in_array($key, ['pdo', 'driver', 'driverClass'], true)) { + if (in_array($key, ['driver', 'driverClass'], true)) { self::assertInstanceOf($value, $conn->getDriver()); } else { self::assertEquals($value, $params[$key]); @@ -394,13 +347,6 @@ public function databaseUrls() : iterable ['url' => '//foo:bar@localhost/baz'], false, ], - 'URL without scheme but default PDO driver' => [ - [ - 'url' => '//foo:bar@localhost/baz', - 'pdo' => true, - ], - false, - ], 'URL without scheme but default driver' => [ [ 'url' => '//foo:bar@localhost/baz', @@ -427,20 +373,6 @@ public function databaseUrls() : iterable 'driverClass' => $driverClass, ], ], - 'URL without scheme but default PDO driver and default driver' => [ - [ - 'url' => '//foo:bar@localhost/baz', - 'pdo' => true, - 'driver' => 'pdo_mysql', - ], - [ - 'user' => 'foo', - 'password' => 'bar', - 'host' => 'localhost', - 'dbname' => 'baz', - 'driver' => PDOMySQLDriver::class, - ], - ], 'URL without scheme but driver and custom driver' => [ [ 'url' => '//foo:bar@localhost/baz', @@ -455,19 +387,6 @@ public function databaseUrls() : iterable 'driverClass' => $driverClass, ], ], - 'URL with default PDO driver' => [ - [ - 'url' => 'mysql://foo:bar@localhost/baz', - 'pdo' => true, - ], - [ - 'user' => 'foo', - 'password' => 'bar', - 'host' => 'localhost', - 'dbname' => 'baz', - 'driver' => PDOMySQLDriver::class, - ], - ], 'URL with default driver' => [ [ 'url' => 'mysql://foo:bar@localhost/baz', @@ -494,20 +413,6 @@ public function databaseUrls() : iterable 'driver' => PDOMySQLDriver::class, ], ], - 'URL with default PDO driver and default driver' => [ - [ - 'url' => 'mysql://foo:bar@localhost/baz', - 'pdo' => true, - 'driver' => 'sqlite', - ], - [ - 'user' => 'foo', - 'password' => 'bar', - 'host' => 'localhost', - 'dbname' => 'baz', - 'driver' => PDOMySQLDriver::class, - ], - ], 'URL with default driver and default custom driver' => [ [ 'url' => 'mysql://foo:bar@localhost/baz', @@ -522,21 +427,6 @@ public function databaseUrls() : iterable 'driver' => PDOMySQLDriver::class, ], ], - 'URL with default PDO driver and default driver and default custom driver' => [ - [ - 'url' => 'mysql://foo:bar@localhost/baz', - 'pdo' => true, - 'driver' => 'sqlite', - 'driverClass' => $driverClass, - ], - [ - 'user' => 'foo', - 'password' => 'bar', - 'host' => 'localhost', - 'dbname' => 'baz', - 'driver' => PDOMySQLDriver::class, - ], - ], ]; } } diff --git a/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php b/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php index ea8d193b1fa..2ff0aef4361 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/ConnectionTest.php @@ -357,18 +357,6 @@ public function testDeterminesDatabasePlatformWhenConnectingToNonExistentDatabas $connection->close(); } - /** - * @requires extension pdo_sqlite - */ - public function testUserProvidedPDOConnection() : void - { - self::assertTrue( - DriverManager::getConnection([ - 'pdo' => new PDO('sqlite::memory:'), - ])->ping() - ); - } - public function testPersistentConnection() : void { $platform = $this->connection->getDatabasePlatform(); diff --git a/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOConnectionTest.php b/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOConnectionTest.php index 204103a771a..c5dc9daa7b6 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOConnectionTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Driver/PDOConnectionTest.php @@ -9,10 +9,12 @@ use Doctrine\DBAL\Driver\PDOSqlsrv\Driver as PDOSQLSRVDriver; use Doctrine\Tests\DbalFunctionalTestCase; use PDO; -use function extension_loaded; use function get_class; use function sprintf; +/** + * @requires extension pdo + */ class PDOConnectionTest extends DbalFunctionalTestCase { /** @@ -24,10 +26,6 @@ class PDOConnectionTest extends DbalFunctionalTestCase protected function setUp() : void { - if (! extension_loaded('PDO')) { - $this->markTestSkipped('PDO is not installed.'); - } - parent::setUp(); $this->driverConnection = $this->connection->getWrappedConnection();