Unverified Commit 256cefa6 authored by Sergei Morozov's avatar Sergei Morozov Committed by GitHub

Merge pull request #4019 from morozov/deprecate-fetch-mode

Deprecated the concept of the fetch mode
parents df651b2d 5af3709a
# Upgrade to 2.11 # Upgrade to 2.11
## Deprecated `FetchMode` and the corresponding methods
1. The `FetchMode` class and the `setFetchMode()` method of the `Connection` and `Statement` interfaces are deprecated.
2. The `Statement::fetch()` method is deprecated in favor of `fetchNumeric()`, `fetchAssociative()` and `fetchOne()`.
3. The `Statement::fetchAll()` method is deprecated in favor of `fetchAllNumeric()` and `fetchAllAssociative()`. There is no currently replacement for `Statement::fetchAll(FETCH_MODE::COLUMN)`. In a future major version, `fetchColumn()` will be used as a replacement.
4. The `Statement::fetchColumn()` method is deprecated in favor of `fetchOne()`.
5. The `Connection::fetchArray()` and `fetchAssoc()` method are deprecated in favor of `fetchNumeric()` and `fetchAssociative()` respectively.
6. The `StatementIterator` class and the usage of a `Statement` object as `Traversable` is deprecated in favor of `iterateNumeric()`, `iterateAssociative()` and `iterateColumn()`.
7. Fetching data in mixed mode (`FetchMode::MIXED`) is deprecated.
## Deprecated `Connection::project()` ## Deprecated `Connection::project()`
The `Connection::project()` method is deprecated. Implement data transformation outside of DBAL. The `Connection::project()` method is deprecated. Implement data transformation outside of DBAL.
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "6bf4905b268231ccd58bdbe30d4ecf81", "content-hash": "ae54b78f0088f88dbcfa8e179be7c43b",
"packages": [ "packages": [
{ {
"name": "doctrine/cache", "name": "doctrine/cache",
...@@ -2416,16 +2416,16 @@ ...@@ -2416,16 +2416,16 @@
}, },
{ {
"name": "slevomat/coding-standard", "name": "slevomat/coding-standard",
"version": "6.3.3", "version": "6.3.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/slevomat/coding-standard.git", "url": "https://github.com/slevomat/coding-standard.git",
"reference": "b905a82255749de847fd4de607c7a4c8163f058d" "reference": "7876032a4f55acf2de2cf3cd538feaf98a8a0fee"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/b905a82255749de847fd4de607c7a4c8163f058d", "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7876032a4f55acf2de2cf3cd538feaf98a8a0fee",
"reference": "b905a82255749de847fd4de607c7a4c8163f058d", "reference": "7876032a4f55acf2de2cf3cd538feaf98a8a0fee",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
...@@ -2469,7 +2469,7 @@ ...@@ -2469,7 +2469,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2020-04-28T07:15:08+00:00" "time": "2020-05-22T15:11:14+00:00"
}, },
{ {
"name": "squizlabs/php_codesniffer", "name": "squizlabs/php_codesniffer",
...@@ -2920,8 +2920,8 @@ ...@@ -2920,8 +2920,8 @@
"authors": [ "authors": [
{ {
"name": "Arne Blankerts", "name": "Arne Blankerts",
"email": "arne@blankerts.de", "role": "Developer",
"role": "Developer" "email": "arne@blankerts.de"
} }
], ],
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
......
...@@ -3,8 +3,10 @@ ...@@ -3,8 +3,10 @@
namespace Doctrine\DBAL\Cache; namespace Doctrine\DBAL\Cache;
use ArrayIterator; use ArrayIterator;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\ResultStatement; use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use InvalidArgumentException; use InvalidArgumentException;
use IteratorAggregate; use IteratorAggregate;
use PDO; use PDO;
...@@ -13,7 +15,7 @@ use function array_values; ...@@ -13,7 +15,7 @@ use function array_values;
use function count; use function count;
use function reset; use function reset;
class ArrayStatement implements IteratorAggregate, ResultStatement class ArrayStatement implements IteratorAggregate, ResultStatement, ForwardCompatibleResultStatement
{ {
/** @var mixed[] */ /** @var mixed[] */
private $data; private $data;
...@@ -60,6 +62,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement ...@@ -60,6 +62,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/ */
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{ {
...@@ -74,6 +78,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement ...@@ -74,6 +78,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/ */
public function getIterator() public function getIterator()
{ {
...@@ -84,6 +90,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement ...@@ -84,6 +90,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*/ */
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{ {
...@@ -115,6 +123,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement ...@@ -115,6 +123,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/ */
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{ {
...@@ -128,6 +138,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement ...@@ -128,6 +138,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/ */
public function fetchColumn($columnIndex = 0) public function fetchColumn($columnIndex = 0)
{ {
...@@ -136,4 +148,68 @@ class ArrayStatement implements IteratorAggregate, ResultStatement ...@@ -136,4 +148,68 @@ class ArrayStatement implements IteratorAggregate, ResultStatement
// TODO: verify that return false is the correct behavior // TODO: verify that return false is the correct behavior
return $row[$columnIndex] ?? false; return $row[$columnIndex] ?? false;
} }
/**
* {@inheritdoc}
*/
public function fetchNumeric()
{
$row = $this->doFetch();
if ($row === false) {
return false;
}
return array_values($row);
}
/**
* {@inheritdoc}
*/
public function fetchAssociative()
{
return $this->doFetch();
}
/**
* {@inheritdoc}
*/
public function fetchOne()
{
$row = $this->doFetch();
if ($row === false) {
return false;
}
return reset($row);
}
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return FetchUtils::fetchAllNumeric($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
return FetchUtils::fetchAllAssociative($this);
}
/**
* @return mixed|false
*/
private function doFetch()
{
if (! isset($this->data[$this->num])) {
return false;
}
return $this->data[$this->num++];
}
} }
...@@ -4,9 +4,12 @@ namespace Doctrine\DBAL\Cache; ...@@ -4,9 +4,12 @@ namespace Doctrine\DBAL\Cache;
use ArrayIterator; use ArrayIterator;
use Doctrine\Common\Cache\Cache; use Doctrine\Common\Cache\Cache;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\ResultStatement; use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use InvalidArgumentException; use InvalidArgumentException;
use IteratorAggregate; use IteratorAggregate;
use PDO; use PDO;
...@@ -28,7 +31,7 @@ use function reset; ...@@ -28,7 +31,7 @@ use function reset;
* Also you have to realize that the cache will load the whole result into memory at once to ensure 2. * Also you have to realize that the cache will load the whole result into memory at once to ensure 2.
* This means that the memory usage for cached results might increase by using this feature. * This means that the memory usage for cached results might increase by using this feature.
*/ */
class ResultCacheStatement implements IteratorAggregate, ResultStatement class ResultCacheStatement implements IteratorAggregate, ResultStatement, ForwardCompatibleResultStatement
{ {
/** @var Cache */ /** @var Cache */
private $resultCache; private $resultCache;
...@@ -105,6 +108,8 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement ...@@ -105,6 +108,8 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/ */
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{ {
...@@ -115,6 +120,8 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement ...@@ -115,6 +120,8 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/ */
public function getIterator() public function getIterator()
{ {
...@@ -125,6 +132,8 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement ...@@ -125,6 +132,8 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*/ */
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{ {
...@@ -165,6 +174,8 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement ...@@ -165,6 +174,8 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/ */
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{ {
...@@ -184,6 +195,8 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement ...@@ -184,6 +195,8 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/ */
public function fetchColumn($columnIndex = 0) public function fetchColumn($columnIndex = 0)
{ {
...@@ -193,6 +206,64 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement ...@@ -193,6 +206,64 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement
return $row[$columnIndex] ?? false; return $row[$columnIndex] ?? false;
} }
/**
* {@inheritdoc}
*/
public function fetchNumeric()
{
$row = $this->doFetch();
if ($row === false) {
return false;
}
return array_values($row);
}
/**
* {@inheritdoc}
*/
public function fetchAssociative()
{
return $this->doFetch();
}
/**
* {@inheritdoc}
*/
public function fetchOne()
{
return FetchUtils::fetchOne($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
if ($this->statement instanceof ForwardCompatibleResultStatement) {
$data = $this->statement->fetchAllAssociative();
} else {
$data = $this->statement->fetchAll(FetchMode::ASSOCIATIVE);
}
return $this->store($data);
}
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
if ($this->statement instanceof ForwardCompatibleResultStatement) {
$data = $this->statement->fetchAllAssociative();
} else {
$data = $this->statement->fetchAll(FetchMode::ASSOCIATIVE);
}
return $this->store($data);
}
/** /**
* Returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement * Returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement
* executed by the corresponding object. * executed by the corresponding object.
...@@ -210,4 +281,49 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement ...@@ -210,4 +281,49 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement
return $this->statement->rowCount(); return $this->statement->rowCount();
} }
/**
* @return array<string,mixed>|false
*
* @throws DriverException
*/
private function doFetch()
{
if ($this->data === null) {
$this->data = [];
}
if ($this->statement instanceof ForwardCompatibleResultStatement) {
$row = $this->statement->fetchAssociative();
} else {
$row = $this->statement->fetch(FetchMode::ASSOCIATIVE);
}
if ($row !== false) {
$this->data[] = $row;
return $row;
}
$this->emptied = true;
return false;
}
/**
* @param array<int,array<mixed>> $data
*
* @return array<int,array<mixed>>
*/
private function store(array $data) : array
{
foreach ($data as $key => $value) {
$data[$key] = [$value];
}
$this->data = $data;
$this->emptied = true;
return $this->data;
}
} }
This diff is collapsed.
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement;
/**
* @internal
*/
final class FetchUtils
{
/**
* @return mixed|false
*
* @throws DriverException
*/
public static function fetchOne(ResultStatement $stmt)
{
$row = $stmt->fetchNumeric();
if ($row === false) {
return false;
}
return $row[0];
}
/**
* @return array<int,array<int,mixed>>
*
* @throws DriverException
*/
public static function fetchAllNumeric(ResultStatement $stmt) : array
{
$rows = [];
while (($row = $stmt->fetchNumeric()) !== false) {
$rows[] = $row;
}
return $rows;
}
/**
* @return array<int,array<string,mixed>>
*
* @throws DriverException
*/
public static function fetchAllAssociative(ResultStatement $stmt) : array
{
$rows = [];
while (($row = $stmt->fetchAssociative()) !== false) {
$rows[] = $row;
}
return $rows;
}
}
...@@ -232,6 +232,8 @@ class DB2Statement implements IteratorAggregate, Statement ...@@ -232,6 +232,8 @@ class DB2Statement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/ */
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{ {
...@@ -244,6 +246,8 @@ class DB2Statement implements IteratorAggregate, Statement ...@@ -244,6 +246,8 @@ class DB2Statement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/ */
public function getIterator() public function getIterator()
{ {
...@@ -252,6 +256,8 @@ class DB2Statement implements IteratorAggregate, Statement ...@@ -252,6 +256,8 @@ class DB2Statement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*/ */
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{ {
...@@ -303,6 +309,8 @@ class DB2Statement implements IteratorAggregate, Statement ...@@ -303,6 +309,8 @@ class DB2Statement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/ */
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{ {
...@@ -334,6 +342,8 @@ class DB2Statement implements IteratorAggregate, Statement ...@@ -334,6 +342,8 @@ class DB2Statement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/ */
public function fetchColumn($columnIndex = 0) public function fetchColumn($columnIndex = 0)
{ {
......
...@@ -2,10 +2,12 @@ ...@@ -2,10 +2,12 @@
namespace Doctrine\DBAL\Driver\Mysqli; namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator; use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use IteratorAggregate; use IteratorAggregate;
use mysqli; use mysqli;
...@@ -24,7 +26,7 @@ use function is_resource; ...@@ -24,7 +26,7 @@ use function is_resource;
use function sprintf; use function sprintf;
use function str_repeat; use function str_repeat;
class MysqliStatement implements IteratorAggregate, Statement class MysqliStatement implements IteratorAggregate, Statement, ForwardCompatibleResultStatement
{ {
/** @var string[] */ /** @var string[] */
protected static $_paramTypeMap = [ protected static $_paramTypeMap = [
...@@ -307,6 +309,8 @@ class MysqliStatement implements IteratorAggregate, Statement ...@@ -307,6 +309,8 @@ class MysqliStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*/ */
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{ {
...@@ -357,6 +361,8 @@ class MysqliStatement implements IteratorAggregate, Statement ...@@ -357,6 +361,8 @@ class MysqliStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/ */
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{ {
...@@ -379,6 +385,8 @@ class MysqliStatement implements IteratorAggregate, Statement ...@@ -379,6 +385,8 @@ class MysqliStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/ */
public function fetchColumn($columnIndex = 0) public function fetchColumn($columnIndex = 0)
{ {
...@@ -396,6 +404,72 @@ class MysqliStatement implements IteratorAggregate, Statement ...@@ -396,6 +404,72 @@ class MysqliStatement implements IteratorAggregate, Statement
* *
* @deprecated The error information is available via exceptions. * @deprecated The error information is available via exceptions.
*/ */
public function fetchNumeric()
{
// do not try fetching from the statement if it's not expected to contain the result
// in order to prevent exceptional situation
if (! $this->result) {
return false;
}
$values = $this->_fetch();
if ($values === null) {
return false;
}
if ($values === false) {
throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno);
}
return $values;
}
/**
* {@inheritDoc}
*/
public function fetchAssociative()
{
$values = $this->fetchNumeric();
if ($values === false) {
return false;
}
assert(is_array($this->_columnNames));
$row = array_combine($this->_columnNames, $values);
assert(is_array($row));
return $row;
}
/**
* {@inheritdoc}
*/
public function fetchOne()
{
return FetchUtils::fetchOne($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return FetchUtils::fetchAllNumeric($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
return FetchUtils::fetchAllAssociative($this);
}
/**
* {@inheritdoc}
*/
public function errorCode() public function errorCode()
{ {
return $this->_stmt->errno; return $this->_stmt->errno;
...@@ -444,6 +518,8 @@ class MysqliStatement implements IteratorAggregate, Statement ...@@ -444,6 +518,8 @@ class MysqliStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/ */
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{ {
...@@ -454,6 +530,8 @@ class MysqliStatement implements IteratorAggregate, Statement ...@@ -454,6 +530,8 @@ class MysqliStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/ */
public function getIterator() public function getIterator()
{ {
......
...@@ -2,9 +2,11 @@ ...@@ -2,9 +2,11 @@
namespace Doctrine\DBAL\Driver\OCI8; namespace Doctrine\DBAL\Driver\OCI8;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator; use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use InvalidArgumentException; use InvalidArgumentException;
use IteratorAggregate; use IteratorAggregate;
...@@ -47,7 +49,7 @@ use const SQLT_CHR; ...@@ -47,7 +49,7 @@ use const SQLT_CHR;
/** /**
* The OCI8 implementation of the Statement interface. * The OCI8 implementation of the Statement interface.
*/ */
class OCI8Statement implements IteratorAggregate, Statement class OCI8Statement implements IteratorAggregate, Statement, ForwardCompatibleResultStatement
{ {
/** @var resource */ /** @var resource */
protected $_dbh; protected $_dbh;
...@@ -410,6 +412,8 @@ class OCI8Statement implements IteratorAggregate, Statement ...@@ -410,6 +412,8 @@ class OCI8Statement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/ */
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{ {
...@@ -420,6 +424,8 @@ class OCI8Statement implements IteratorAggregate, Statement ...@@ -420,6 +424,8 @@ class OCI8Statement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/ */
public function getIterator() public function getIterator()
{ {
...@@ -428,6 +434,8 @@ class OCI8Statement implements IteratorAggregate, Statement ...@@ -428,6 +434,8 @@ class OCI8Statement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*/ */
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{ {
...@@ -459,6 +467,8 @@ class OCI8Statement implements IteratorAggregate, Statement ...@@ -459,6 +467,8 @@ class OCI8Statement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/ */
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{ {
...@@ -513,6 +523,8 @@ class OCI8Statement implements IteratorAggregate, Statement ...@@ -513,6 +523,8 @@ class OCI8Statement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/ */
public function fetchColumn($columnIndex = 0) public function fetchColumn($columnIndex = 0)
{ {
...@@ -538,4 +550,83 @@ class OCI8Statement implements IteratorAggregate, Statement ...@@ -538,4 +550,83 @@ class OCI8Statement implements IteratorAggregate, Statement
{ {
return oci_num_rows($this->_sth) ?: 0; return oci_num_rows($this->_sth) ?: 0;
} }
/**
* {@inheritdoc}
*/
public function fetchNumeric()
{
return $this->doFetch(OCI_NUM);
}
/**
* {@inheritdoc}
*/
public function fetchAssociative()
{
return $this->doFetch(OCI_ASSOC);
}
/**
* {@inheritdoc}
*/
public function fetchOne()
{
return FetchUtils::fetchOne($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return $this->doFetchAll(OCI_NUM, OCI_FETCHSTATEMENT_BY_ROW);
}
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
return $this->doFetchAll(OCI_ASSOC, OCI_FETCHSTATEMENT_BY_ROW);
}
/**
* @return mixed|false
*/
private function doFetch(int $mode)
{
// do not try fetching from the statement if it's not expected to contain the result
// in order to prevent exceptional situation
if (! $this->result) {
return false;
}
return oci_fetch_array(
$this->_sth,
$mode | OCI_RETURN_NULLS | OCI_RETURN_LOBS
);
}
/**
* @return array<mixed>
*/
private function doFetchAll(int $mode, int $fetchStructure) : array
{
// do not try fetching from the statement if it's not expected to contain the result
// in order to prevent exceptional situation
if (! $this->result) {
return [];
}
oci_fetch_all(
$this->_sth,
$result,
0,
-1,
$mode | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS
);
return $result;
}
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace Doctrine\DBAL\Driver\PDOSqlsrv; namespace Doctrine\DBAL\Driver\PDOSqlsrv;
use Doctrine\DBAL\Driver\PDOConnection; use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use PDO; use PDO;
use function strpos; use function strpos;
...@@ -34,6 +35,10 @@ class Connection extends PDOConnection ...@@ -34,6 +35,10 @@ class Connection extends PDOConnection
$stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?'); $stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?');
$stmt->execute([$name]); $stmt->execute([$name]);
if ($stmt instanceof ForwardCompatibleResultStatement) {
return $stmt->fetchOne();
}
return $stmt->fetchColumn(); return $stmt->fetchColumn();
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace Doctrine\DBAL\Driver; namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use PDO; use PDO;
use function array_slice; use function array_slice;
...@@ -17,7 +18,7 @@ use const E_USER_DEPRECATED; ...@@ -17,7 +18,7 @@ use const E_USER_DEPRECATED;
* The PDO implementation of the Statement interface. * The PDO implementation of the Statement interface.
* Used by all PDO-based drivers. * Used by all PDO-based drivers.
*/ */
class PDOStatement extends \PDOStatement implements Statement class PDOStatement extends \PDOStatement implements Statement, ForwardCompatibleResultStatement
{ {
private const PARAM_TYPE_MAP = [ private const PARAM_TYPE_MAP = [
ParameterType::NULL => PDO::PARAM_NULL, ParameterType::NULL => PDO::PARAM_NULL,
...@@ -46,6 +47,8 @@ class PDOStatement extends \PDOStatement implements Statement ...@@ -46,6 +47,8 @@ class PDOStatement extends \PDOStatement implements Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/ */
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{ {
...@@ -132,6 +135,8 @@ class PDOStatement extends \PDOStatement implements Statement ...@@ -132,6 +135,8 @@ class PDOStatement extends \PDOStatement implements Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*/ */
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{ {
...@@ -150,6 +155,8 @@ class PDOStatement extends \PDOStatement implements Statement ...@@ -150,6 +155,8 @@ class PDOStatement extends \PDOStatement implements Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/ */
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{ {
...@@ -181,6 +188,8 @@ class PDOStatement extends \PDOStatement implements Statement ...@@ -181,6 +188,8 @@ class PDOStatement extends \PDOStatement implements Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/ */
public function fetchColumn($columnIndex = 0) public function fetchColumn($columnIndex = 0)
{ {
...@@ -191,6 +200,46 @@ class PDOStatement extends \PDOStatement implements Statement ...@@ -191,6 +200,46 @@ class PDOStatement extends \PDOStatement implements Statement
} }
} }
/**
* {@inheritdoc}
*/
public function fetchNumeric()
{
return $this->fetch(PDO::FETCH_NUM);
}
/**
* {@inheritdoc}
*/
public function fetchAssociative()
{
return $this->fetch(PDO::FETCH_ASSOC);
}
/**
* {@inheritdoc}
*/
public function fetchOne()
{
return $this->fetch(PDO::FETCH_COLUMN);
}
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return $this->fetchAll(PDO::FETCH_NUM);
}
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
return $this->fetchAll(PDO::FETCH_ASSOC);
}
/** /**
* Converts DBAL parameter type to PDO parameter type * Converts DBAL parameter type to PDO parameter type
* *
......
...@@ -29,6 +29,8 @@ interface ResultStatement extends Traversable ...@@ -29,6 +29,8 @@ interface ResultStatement extends Traversable
/** /**
* Sets the fetch mode to use while iterating this statement. * Sets the fetch mode to use while iterating this statement.
* *
* @deprecated Use one of the fetch- or iterate-related methods.
*
* @param int $fetchMode The fetch mode must be one of the {@link \Doctrine\DBAL\FetchMode} constants. * @param int $fetchMode The fetch mode must be one of the {@link \Doctrine\DBAL\FetchMode} constants.
* @param mixed $arg2 * @param mixed $arg2
* @param mixed $arg3 * @param mixed $arg3
...@@ -40,6 +42,8 @@ interface ResultStatement extends Traversable ...@@ -40,6 +42,8 @@ interface ResultStatement extends Traversable
/** /**
* Returns the next row of a result set. * Returns the next row of a result set.
* *
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*
* @param int|null $fetchMode Controls how the next row will be returned to the caller. * @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, * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants,
* defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}. * defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}.
...@@ -67,6 +71,8 @@ interface ResultStatement extends Traversable ...@@ -67,6 +71,8 @@ interface ResultStatement extends Traversable
/** /**
* Returns an array containing all of the result set rows. * Returns an array containing all of the result set rows.
* *
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*
* @param int|null $fetchMode Controls how the next row will be returned to the caller. * @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, * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants,
* defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}. * defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}.
...@@ -89,6 +95,8 @@ interface ResultStatement extends Traversable ...@@ -89,6 +95,8 @@ interface ResultStatement extends Traversable
/** /**
* Returns a single column from the next row of a result set or FALSE if there are no more rows. * Returns a single column from the next row of a result set or FALSE if there are no more rows.
* *
* @deprecated Use fetchOne() instead.
*
* @param int $columnIndex 0-indexed number of the column you wish to retrieve from the row. * @param int $columnIndex 0-indexed number of the column you wish to retrieve from the row.
* If no value is supplied, fetches the first column. * If no value is supplied, fetches the first column.
* *
......
...@@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Driver\SQLAnywhere; ...@@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use function assert; use function assert;
use function func_get_args; use function func_get_args;
...@@ -125,7 +126,13 @@ class SQLAnywhereConnection implements Connection, ServerInfoAwareConnection ...@@ -125,7 +126,13 @@ class SQLAnywhereConnection implements Connection, ServerInfoAwareConnection
*/ */
public function getServerVersion() public function getServerVersion()
{ {
$version = $this->query("SELECT PROPERTY('ProductVersion')")->fetchColumn(); $stmt = $this->query("SELECT PROPERTY('ProductVersion')");
if ($stmt instanceof ForwardCompatibleResultStatement) {
$version = $stmt->fetchOne();
} else {
$version = $stmt->fetchColumn();
}
assert(is_string($version)); assert(is_string($version));
...@@ -141,7 +148,13 @@ class SQLAnywhereConnection implements Connection, ServerInfoAwareConnection ...@@ -141,7 +148,13 @@ class SQLAnywhereConnection implements Connection, ServerInfoAwareConnection
return sasql_insert_id($this->connection); return sasql_insert_id($this->connection);
} }
return $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn(); $stmt = $this->query('SELECT ' . $name . '.CURRVAL');
if ($stmt instanceof ForwardCompatibleResultStatement) {
return $stmt->fetchOne();
}
return $stmt->fetchColumn();
} }
/** /**
......
...@@ -2,9 +2,12 @@ ...@@ -2,9 +2,12 @@
namespace Doctrine\DBAL\Driver\SQLAnywhere; namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator; use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use IteratorAggregate; use IteratorAggregate;
use PDO; use PDO;
...@@ -39,7 +42,7 @@ use const SASQL_BOTH; ...@@ -39,7 +42,7 @@ use const SASQL_BOTH;
/** /**
* SAP SQL Anywhere implementation of the Statement interface. * SAP SQL Anywhere implementation of the Statement interface.
*/ */
class SQLAnywhereStatement implements IteratorAggregate, Statement class SQLAnywhereStatement implements IteratorAggregate, Statement, ForwardCompatibleResultStatement
{ {
/** @var resource The connection resource. */ /** @var resource The connection resource. */
private $conn; private $conn;
...@@ -201,6 +204,8 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement ...@@ -201,6 +204,8 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
* *
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*
* @throws SQLAnywhereException * @throws SQLAnywhereException
*/ */
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
...@@ -252,6 +257,8 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement ...@@ -252,6 +257,8 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/ */
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{ {
...@@ -283,6 +290,8 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement ...@@ -283,6 +290,8 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/ */
public function fetchColumn($columnIndex = 0) public function fetchColumn($columnIndex = 0)
{ {
...@@ -297,12 +306,68 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement ...@@ -297,12 +306,68 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/ */
public function getIterator() public function getIterator()
{ {
return new StatementIterator($this); return new StatementIterator($this);
} }
/**
* {@inheritDoc}
*/
public function fetchNumeric()
{
if (! is_resource($this->result)) {
return false;
}
return sasql_fetch_row($this->result);
}
/**
* {@inheritdoc}
*/
public function fetchAssociative()
{
if (! is_resource($this->result)) {
return false;
}
return sasql_fetch_assoc($this->result);
}
/**
* {@inheritdoc}
*
* @throws DriverException
*/
public function fetchOne()
{
return FetchUtils::fetchOne($this);
}
/**
* @return array<int,array<int,mixed>>
*
* @throws DriverException
*/
public function fetchAllNumeric() : array
{
return FetchUtils::fetchAllNumeric($this);
}
/**
* @return array<int,array<string,mixed>>
*
* @throws DriverException
*/
public function fetchAllAssociative() : array
{
return FetchUtils::fetchAllAssociative($this);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
...@@ -313,6 +378,8 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement ...@@ -313,6 +378,8 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/ */
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{ {
......
...@@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Driver\SQLSrv; ...@@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use function func_get_args; use function func_get_args;
use function is_float; use function is_float;
...@@ -141,6 +142,10 @@ class SQLSrvConnection implements Connection, ServerInfoAwareConnection ...@@ -141,6 +142,10 @@ class SQLSrvConnection implements Connection, ServerInfoAwareConnection
$stmt = $this->query('SELECT @@IDENTITY'); $stmt = $this->query('SELECT @@IDENTITY');
} }
if ($stmt instanceof ForwardCompatibleResultStatement) {
return $stmt->fetchOne();
}
return $stmt->fetchColumn(); return $stmt->fetchColumn();
} }
......
...@@ -2,9 +2,11 @@ ...@@ -2,9 +2,11 @@
namespace Doctrine\DBAL\Driver\SQLSrv; namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator; use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use IteratorAggregate; use IteratorAggregate;
use PDO; use PDO;
...@@ -38,7 +40,7 @@ use const SQLSRV_PARAM_IN; ...@@ -38,7 +40,7 @@ use const SQLSRV_PARAM_IN;
/** /**
* SQL Server Statement. * SQL Server Statement.
*/ */
class SQLSrvStatement implements IteratorAggregate, Statement class SQLSrvStatement implements IteratorAggregate, Statement, ForwardCompatibleResultStatement
{ {
/** /**
* The SQLSRV Resource. * The SQLSRV Resource.
...@@ -322,6 +324,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -322,6 +324,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/ */
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{ {
...@@ -334,6 +338,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -334,6 +338,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/ */
public function getIterator() public function getIterator()
{ {
...@@ -343,6 +349,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -343,6 +349,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
* *
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*
* @throws SQLSrvException * @throws SQLSrvException
*/ */
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
...@@ -381,6 +389,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -381,6 +389,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/ */
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{ {
...@@ -412,6 +422,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -412,6 +422,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/ */
public function fetchColumn($columnIndex = 0) public function fetchColumn($columnIndex = 0)
{ {
...@@ -424,6 +436,46 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -424,6 +436,46 @@ class SQLSrvStatement implements IteratorAggregate, Statement
return $row[$columnIndex] ?? null; return $row[$columnIndex] ?? null;
} }
/**
* {@inheritdoc}
*/
public function fetchNumeric()
{
return $this->doFetch(SQLSRV_FETCH_NUMERIC);
}
/**
* {@inheritdoc}
*/
public function fetchAssociative()
{
return $this->doFetch(SQLSRV_FETCH_ASSOC);
}
/**
* {@inheritdoc}
*/
public function fetchOne()
{
return FetchUtils::fetchOne($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return FetchUtils::fetchAllNumeric($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
return FetchUtils::fetchAllAssociative($this);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
...@@ -435,4 +487,18 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -435,4 +487,18 @@ class SQLSrvStatement implements IteratorAggregate, Statement
return sqlsrv_rows_affected($this->stmt) ?: 0; return sqlsrv_rows_affected($this->stmt) ?: 0;
} }
/**
* @return mixed|false
*/
private function doFetch(int $fetchType)
{
// do not try fetching from the statement if it's not expected to contain the result
// in order to prevent exceptional situation
if ($this->stmt === null || ! $this->result) {
return false;
}
return sqlsrv_fetch_array($this->stmt, $fetchType) ?? false;
}
} }
...@@ -4,6 +4,9 @@ namespace Doctrine\DBAL\Driver; ...@@ -4,6 +4,9 @@ namespace Doctrine\DBAL\Driver;
use IteratorAggregate; use IteratorAggregate;
/**
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn().
*/
class StatementIterator implements IteratorAggregate class StatementIterator implements IteratorAggregate
{ {
/** @var ResultStatement */ /** @var ResultStatement */
......
...@@ -6,6 +6,8 @@ use PDO; ...@@ -6,6 +6,8 @@ use PDO;
/** /**
* Contains statement fetch modes. * Contains statement fetch modes.
*
* @deprecated Use one of the fetch- or iterate-related methods on the Statement.
*/ */
final class FetchMode final class FetchMode
{ {
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\ForwardCompatibility\Driver;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\ResultStatement as BaseResultStatement;
/**
* Forward compatibility extension for the ResultStatement interface.
*/
interface ResultStatement extends BaseResultStatement
{
/**
* Returns the next row of a result set as a numeric array or FALSE if there are no more rows.
*
* @return array<int,mixed>|false
*
* @throws DriverException
*/
public function fetchNumeric();
/**
* Returns the next row of a result set as an associative array or FALSE if there are no more rows.
*
* @return array<string,mixed>|false
*
* @throws DriverException
*/
public function fetchAssociative();
/**
* Returns the first value of the next row of a result set or FALSE if there are no more rows.
*
* @return mixed|false
*
* @throws DriverException
*/
public function fetchOne();
/**
* Returns an array containing all of the result set rows represented as numeric arrays.
*
* @return array<int,array<int,mixed>>
*
* @throws DriverException
*/
public function fetchAllNumeric() : array;
/**
* Returns an array containing all of the result set rows represented as associative arrays.
*
* @return array<int,array<string,mixed>>
*
* @throws DriverException
*/
public function fetchAllAssociative() : array;
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\ForwardCompatibility;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as BaseResultStatement;
use Traversable;
/**
* Forward compatibility extension for the DBAL ResultStatement interface.
*/
interface ResultStatement extends BaseResultStatement
{
/**
* Returns an iterator over the result set rows represented as numeric arrays.
*
* @return Traversable<int,array<int,mixed>>
*
* @throws DBALException
*/
public function iterateNumeric() : Traversable;
/**
* Returns an iterator over the result set rows represented as associative arrays.
*
* @return Traversable<int,array<string,mixed>>
*
* @throws DBALException
*/
public function iterateAssociative() : Traversable;
/**
* Returns an iterator over the values of the first column of the result set.
*
* @return Traversable<int,mixed>
*
* @throws DBALException
*/
public function iterateColumn() : Traversable;
}
...@@ -5,7 +5,6 @@ namespace Doctrine\DBAL\Id; ...@@ -5,7 +5,6 @@ namespace Doctrine\DBAL\Id;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException; use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\LockMode; use Doctrine\DBAL\LockMode;
use Throwable; use Throwable;
use function array_change_key_case; use function array_change_key_case;
...@@ -105,8 +104,7 @@ class TableGenerator ...@@ -105,8 +104,7 @@ class TableGenerator
$sql = 'SELECT sequence_value, sequence_increment_by' $sql = 'SELECT sequence_value, sequence_increment_by'
. ' FROM ' . $platform->appendLockHint($this->generatorTableName, LockMode::PESSIMISTIC_WRITE) . ' FROM ' . $platform->appendLockHint($this->generatorTableName, LockMode::PESSIMISTIC_WRITE)
. ' WHERE sequence_name = ? ' . $platform->getWriteLockSQL(); . ' WHERE sequence_name = ? ' . $platform->getWriteLockSQL();
$stmt = $this->conn->executeQuery($sql, [$sequenceName]); $row = $this->conn->fetchAssociative($sql, [$sequenceName]);
$row = $stmt->fetch(FetchMode::ASSOCIATIVE);
if ($row !== false) { if ($row !== false) {
$row = array_change_key_case($row, CASE_LOWER); $row = array_change_key_case($row, CASE_LOWER);
......
...@@ -6,6 +6,7 @@ use Doctrine\DBAL\Driver\ResultStatement; ...@@ -6,6 +6,7 @@ use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\Driver\Statement as DriverStatement; use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\DBAL\Driver\StatementIterator; use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use IteratorAggregate; use IteratorAggregate;
use PDO; use PDO;
...@@ -17,7 +18,7 @@ use function rtrim; ...@@ -17,7 +18,7 @@ use function rtrim;
/** /**
* Portability wrapper for a Statement. * Portability wrapper for a Statement.
*/ */
class Statement implements IteratorAggregate, DriverStatement class Statement implements IteratorAggregate, DriverStatement, ForwardCompatibleResultStatement
{ {
/** @var int */ /** @var int */
private $portability; private $portability;
...@@ -115,6 +116,8 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -115,6 +116,8 @@ class Statement implements IteratorAggregate, DriverStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/ */
public function setFetchMode($fetchMode, $arg1 = null, $arg2 = null) public function setFetchMode($fetchMode, $arg1 = null, $arg2 = null)
{ {
...@@ -125,6 +128,8 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -125,6 +128,8 @@ class Statement implements IteratorAggregate, DriverStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/ */
public function getIterator() public function getIterator()
{ {
...@@ -133,6 +138,8 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -133,6 +138,8 @@ class Statement implements IteratorAggregate, DriverStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*/ */
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{ {
...@@ -140,7 +147,7 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -140,7 +147,7 @@ class Statement implements IteratorAggregate, DriverStatement
$row = $this->stmt->fetch($fetchMode); $row = $this->stmt->fetch($fetchMode);
$iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM); $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
$fixCase = $this->case !== null $fixCase = $this->case !== null
&& ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED) && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED)
&& ($this->portability & Connection::PORTABILITY_FIX_CASE); && ($this->portability & Connection::PORTABILITY_FIX_CASE);
...@@ -152,6 +159,8 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -152,6 +159,8 @@ class Statement implements IteratorAggregate, DriverStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/ */
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{ {
...@@ -163,37 +172,138 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -163,37 +172,138 @@ class Statement implements IteratorAggregate, DriverStatement
$rows = $this->stmt->fetchAll($fetchMode); $rows = $this->stmt->fetchAll($fetchMode);
} }
$iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM); $fixCase = $this->case !== null
$fixCase = $this->case !== null
&& ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED) && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED)
&& ($this->portability & Connection::PORTABILITY_FIX_CASE); && ($this->portability & Connection::PORTABILITY_FIX_CASE);
return $this->fixResultSet($rows, $fixCase, $fetchMode !== FetchMode::COLUMN);
}
/**
* {@inheritdoc}
*/
public function fetchNumeric()
{
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
$row = $this->stmt->fetchNumeric();
} else {
$row = $this->stmt->fetch(FetchMode::NUMERIC);
}
return $this->fixResult($row, false);
}
/**
* {@inheritdoc}
*/
public function fetchAssociative()
{
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
$row = $this->stmt->fetchAssociative();
} else {
$row = $this->stmt->fetch(FetchMode::ASSOCIATIVE);
}
return $this->fixResult($row, true);
}
/**
* {@inheritdoc}
*/
public function fetchOne()
{
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
$value = $this->stmt->fetchOne();
} else {
$value = $this->stmt->fetch(FetchMode::COLUMN);
}
if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) !== 0 && $value === '') {
$value = null;
} elseif (($this->portability & Connection::PORTABILITY_RTRIM) !== 0 && is_string($value)) {
$value = rtrim($value);
}
return $value;
}
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
$data = $this->stmt->fetchAllNumeric();
} else {
$data = $this->stmt->fetchAll(FetchMode::NUMERIC);
}
return $this->fixResultSet($data, false, true);
}
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
$data = $this->stmt->fetchAllAssociative();
} else {
$data = $this->stmt->fetchAll(FetchMode::ASSOCIATIVE);
}
return $this->fixResultSet($data, true, true);
}
/**
* @param mixed $result
*
* @return mixed
*/
private function fixResult($result, bool $fixCase)
{
$iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
$fixCase = $fixCase && $this->case !== null && ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0;
return $this->fixRow($result, $iterateRow, $fixCase);
}
/**
* @param array<int,mixed> $resultSet
*
* @return array<int,mixed>
*/
private function fixResultSet(array $resultSet, bool $fixCase, bool $isArray) : array
{
$iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
$fixCase = $fixCase && $this->case !== null && ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0;
if (! $iterateRow && ! $fixCase) { if (! $iterateRow && ! $fixCase) {
return $rows; return $resultSet;
} }
if ($fetchMode === FetchMode::COLUMN) { if (! $isArray) {
foreach ($rows as $num => $row) { foreach ($resultSet as $num => $value) {
$rows[$num] = [$row]; $resultSet[$num] = [$value];
} }
} }
foreach ($rows as $num => $row) { foreach ($resultSet as $num => $row) {
$rows[$num] = $this->fixRow($row, $iterateRow, $fixCase); $resultSet[$num] = $this->fixRow($row, $iterateRow, $fixCase);
} }
if ($fetchMode === FetchMode::COLUMN) { if (! $isArray) {
foreach ($rows as $num => $row) { foreach ($resultSet as $num => $row) {
$rows[$num] = $row[0]; $resultSet[$num] = $row[0];
} }
} }
return $rows; return $resultSet;
} }
/** /**
* @param mixed $row * @param mixed $row
* @param int $iterateRow * @param bool $iterateRow
* @param bool $fixCase * @param bool $fixCase
* *
* @return mixed * @return mixed
...@@ -223,6 +333,8 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -223,6 +333,8 @@ class Statement implements IteratorAggregate, DriverStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/ */
public function fetchColumn($columnIndex = 0) public function fetchColumn($columnIndex = 0)
{ {
......
...@@ -101,7 +101,7 @@ abstract class AbstractSchemaManager ...@@ -101,7 +101,7 @@ abstract class AbstractSchemaManager
{ {
$sql = $this->_platform->getListDatabasesSQL(); $sql = $this->_platform->getListDatabasesSQL();
$databases = $this->_conn->fetchAll($sql); $databases = $this->_conn->fetchAllAssociative($sql);
return $this->_getPortableDatabasesList($databases); return $this->_getPortableDatabasesList($databases);
} }
...@@ -115,7 +115,7 @@ abstract class AbstractSchemaManager ...@@ -115,7 +115,7 @@ abstract class AbstractSchemaManager
{ {
$sql = $this->_platform->getListNamespacesSQL(); $sql = $this->_platform->getListNamespacesSQL();
$namespaces = $this->_conn->fetchAll($sql); $namespaces = $this->_conn->fetchAllAssociative($sql);
return $this->getPortableNamespacesList($namespaces); return $this->getPortableNamespacesList($namespaces);
} }
...@@ -135,7 +135,7 @@ abstract class AbstractSchemaManager ...@@ -135,7 +135,7 @@ abstract class AbstractSchemaManager
$sql = $this->_platform->getListSequencesSQL($database); $sql = $this->_platform->getListSequencesSQL($database);
$sequences = $this->_conn->fetchAll($sql); $sequences = $this->_conn->fetchAllAssociative($sql);
return $this->filterAssetNames($this->_getPortableSequencesList($sequences)); return $this->filterAssetNames($this->_getPortableSequencesList($sequences));
} }
...@@ -163,7 +163,7 @@ abstract class AbstractSchemaManager ...@@ -163,7 +163,7 @@ abstract class AbstractSchemaManager
$sql = $this->_platform->getListTableColumnsSQL($table, $database); $sql = $this->_platform->getListTableColumnsSQL($table, $database);
$tableColumns = $this->_conn->fetchAll($sql); $tableColumns = $this->_conn->fetchAllAssociative($sql);
return $this->_getPortableTableColumnList($table, $database, $tableColumns); return $this->_getPortableTableColumnList($table, $database, $tableColumns);
} }
...@@ -181,7 +181,7 @@ abstract class AbstractSchemaManager ...@@ -181,7 +181,7 @@ abstract class AbstractSchemaManager
{ {
$sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
$tableIndexes = $this->_conn->fetchAll($sql); $tableIndexes = $this->_conn->fetchAllAssociative($sql);
return $this->_getPortableTableIndexesList($tableIndexes, $table); return $this->_getPortableTableIndexesList($tableIndexes, $table);
} }
...@@ -211,7 +211,7 @@ abstract class AbstractSchemaManager ...@@ -211,7 +211,7 @@ abstract class AbstractSchemaManager
{ {
$sql = $this->_platform->getListTablesSQL(); $sql = $this->_platform->getListTablesSQL();
$tables = $this->_conn->fetchAll($sql); $tables = $this->_conn->fetchAllAssociative($sql);
$tableNames = $this->_getPortableTablesList($tables); $tableNames = $this->_getPortableTablesList($tables);
return $this->filterAssetNames($tableNames); return $this->filterAssetNames($tableNames);
...@@ -289,7 +289,7 @@ abstract class AbstractSchemaManager ...@@ -289,7 +289,7 @@ abstract class AbstractSchemaManager
{ {
$database = $this->_conn->getDatabase(); $database = $this->_conn->getDatabase();
$sql = $this->_platform->getListViewsSQL($database); $sql = $this->_platform->getListViewsSQL($database);
$views = $this->_conn->fetchAll($sql); $views = $this->_conn->fetchAllAssociative($sql);
return $this->_getPortableViewsList($views); return $this->_getPortableViewsList($views);
} }
...@@ -309,7 +309,7 @@ abstract class AbstractSchemaManager ...@@ -309,7 +309,7 @@ abstract class AbstractSchemaManager
} }
$sql = $this->_platform->getListTableForeignKeysSQL($table, $database); $sql = $this->_platform->getListTableForeignKeysSQL($table, $database);
$tableForeignKeys = $this->_conn->fetchAll($sql); $tableForeignKeys = $this->_conn->fetchAllAssociative($sql);
return $this->_getPortableTableForeignKeysList($tableForeignKeys); return $this->_getPortableTableForeignKeysList($tableForeignKeys);
} }
......
...@@ -30,7 +30,7 @@ class DB2SchemaManager extends AbstractSchemaManager ...@@ -30,7 +30,7 @@ class DB2SchemaManager extends AbstractSchemaManager
$sql = $this->_platform->getListTablesSQL(); $sql = $this->_platform->getListTablesSQL();
$sql .= ' AND CREATOR = UPPER(' . $this->_conn->quote($this->_conn->getUsername()) . ')'; $sql .= ' AND CREATOR = UPPER(' . $this->_conn->quote($this->_conn->getUsername()) . ')';
$tables = $this->_conn->fetchAll($sql); $tables = $this->_conn->fetchAllAssociative($sql);
return $this->filterAssetNames($this->_getPortableTablesList($tables)); return $this->filterAssetNames($this->_getPortableTablesList($tables));
} }
...@@ -228,7 +228,7 @@ class DB2SchemaManager extends AbstractSchemaManager ...@@ -228,7 +228,7 @@ class DB2SchemaManager extends AbstractSchemaManager
assert($platform instanceof DB2Platform); assert($platform instanceof DB2Platform);
$sql = $platform->getListTableCommentsSQL($tableName); $sql = $platform->getListTableCommentsSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql); $tableOptions = $this->_conn->fetchAssociative($sql);
if ($tableOptions !== false) { if ($tableOptions !== false) {
$table->addOption('comment', $tableOptions['REMARKS']); $table->addOption('comment', $tableOptions['REMARKS']);
......
...@@ -326,7 +326,7 @@ class MySqlSchemaManager extends AbstractSchemaManager ...@@ -326,7 +326,7 @@ class MySqlSchemaManager extends AbstractSchemaManager
assert($platform instanceof MySqlPlatform); assert($platform instanceof MySqlPlatform);
$sql = $platform->getListTableMetadataSQL($tableName); $sql = $platform->getListTableMetadataSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql); $tableOptions = $this->_conn->fetchAssociative($sql);
if ($tableOptions === false) { if ($tableOptions === false) {
return $table; return $table;
......
...@@ -380,7 +380,7 @@ WHERE ...@@ -380,7 +380,7 @@ WHERE
AND p.addr(+) = s.paddr AND p.addr(+) = s.paddr
SQL; SQL;
$activeUserSessions = $this->_conn->fetchAll($sql, [strtoupper($user)]); $activeUserSessions = $this->_conn->fetchAllAssociative($sql, [strtoupper($user)]);
foreach ($activeUserSessions as $activeUserSession) { foreach ($activeUserSessions as $activeUserSession) {
$activeUserSession = array_change_key_case($activeUserSession, CASE_LOWER); $activeUserSession = array_change_key_case($activeUserSession, CASE_LOWER);
...@@ -406,7 +406,7 @@ SQL; ...@@ -406,7 +406,7 @@ SQL;
assert($platform instanceof OraclePlatform); assert($platform instanceof OraclePlatform);
$sql = $platform->getListTableCommentsSQL($tableName); $sql = $platform->getListTableCommentsSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql); $tableOptions = $this->_conn->fetchAssociative($sql);
if ($tableOptions !== false) { if ($tableOptions !== false) {
$table->addOption('comment', $tableOptions['COMMENTS']); $table->addOption('comment', $tableOptions['COMMENTS']);
......
...@@ -221,8 +221,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager ...@@ -221,8 +221,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
implode(' ,', $colNumbers) implode(' ,', $colNumbers)
); );
$stmt = $this->_conn->executeQuery($columnNameSql); $indexColumns = $this->_conn->fetchAllAssociative($columnNameSql);
$indexColumns = $stmt->fetchAll();
// required for getting the order of the columns right. // required for getting the order of the columns right.
foreach ($colNumbers as $colNum) { foreach ($colNumbers as $colNum) {
......
...@@ -248,7 +248,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager ...@@ -248,7 +248,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager
$sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
try { try {
$tableIndexes = $this->_conn->fetchAll($sql); $tableIndexes = $this->_conn->fetchAllAssociative($sql);
} catch (PDOException $e) { } catch (PDOException $e) {
if ($e->getCode() === 'IMSSP') { if ($e->getCode() === 'IMSSP') {
return []; return [];
...@@ -274,7 +274,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager ...@@ -274,7 +274,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager
if (count($tableDiff->removedColumns) > 0) { if (count($tableDiff->removedColumns) > 0) {
foreach ($tableDiff->removedColumns as $col) { foreach ($tableDiff->removedColumns as $col) {
$columnConstraintSql = $this->getColumnConstraintSQL($tableDiff->name, $col->getName()); $columnConstraintSql = $this->getColumnConstraintSQL($tableDiff->name, $col->getName());
foreach ($this->_conn->fetchAll($columnConstraintSql) as $constraint) { foreach ($this->_conn->fetchAllAssociative($columnConstraintSql) as $constraint) {
$this->_conn->exec( $this->_conn->exec(
sprintf( sprintf(
'ALTER TABLE %s DROP CONSTRAINT %s', 'ALTER TABLE %s DROP CONSTRAINT %s',
...@@ -340,7 +340,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager ...@@ -340,7 +340,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager
assert($platform instanceof SQLServerPlatform); assert($platform instanceof SQLServerPlatform);
$sql = $platform->getListTableMetadataSQL($tableName); $sql = $platform->getListTableMetadataSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql); $tableOptions = $this->_conn->fetchAssociative($sql);
if ($tableOptions !== false) { if ($tableOptions !== false) {
$table->addOption('comment', $tableOptions['table_comment']); $table->addOption('comment', $tableOptions['table_comment']);
......
...@@ -4,7 +4,6 @@ namespace Doctrine\DBAL\Schema; ...@@ -4,7 +4,6 @@ namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\DBALException; use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Types\StringType; use Doctrine\DBAL\Types\StringType;
use Doctrine\DBAL\Types\TextType; use Doctrine\DBAL\Types\TextType;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
...@@ -115,7 +114,7 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -115,7 +114,7 @@ class SqliteSchemaManager extends AbstractSchemaManager
} }
$sql = $this->_platform->getListTableForeignKeysSQL($table, $database); $sql = $this->_platform->getListTableForeignKeysSQL($table, $database);
$tableForeignKeys = $this->_conn->fetchAll($sql); $tableForeignKeys = $this->_conn->fetchAllAssociative($sql);
if (! empty($tableForeignKeys)) { if (! empty($tableForeignKeys)) {
$createSql = $this->getCreateTableSQL($table); $createSql = $this->getCreateTableSQL($table);
...@@ -169,11 +168,10 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -169,11 +168,10 @@ class SqliteSchemaManager extends AbstractSchemaManager
$indexBuffer = []; $indexBuffer = [];
// fetch primary // fetch primary
$stmt = $this->_conn->executeQuery(sprintf( $indexArray = $this->_conn->fetchAllAssociative(sprintf(
'PRAGMA TABLE_INFO (%s)', 'PRAGMA TABLE_INFO (%s)',
$this->_conn->quote($tableName) $this->_conn->quote($tableName)
)); ));
$indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE);
usort($indexArray, static function ($a, $b) { usort($indexArray, static function ($a, $b) {
if ($a['pk'] === $b['pk']) { if ($a['pk'] === $b['pk']) {
...@@ -208,11 +206,10 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -208,11 +206,10 @@ class SqliteSchemaManager extends AbstractSchemaManager
$idx['primary'] = false; $idx['primary'] = false;
$idx['non_unique'] = ! $tableIndex['unique']; $idx['non_unique'] = ! $tableIndex['unique'];
$stmt = $this->_conn->executeQuery(sprintf( $indexArray = $this->_conn->fetchAllAssociative(sprintf(
'PRAGMA INDEX_INFO (%s)', 'PRAGMA INDEX_INFO (%s)',
$this->_conn->quote($keyName) $this->_conn->quote($keyName)
)); ));
$indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE);
foreach ($indexArray as $indexColumnRow) { foreach ($indexArray as $indexColumnRow) {
$idx['column_name'] = $indexColumnRow['name']; $idx['column_name'] = $indexColumnRow['name'];
......
...@@ -87,7 +87,7 @@ class PoolingShardManager implements ShardManager ...@@ -87,7 +87,7 @@ class PoolingShardManager implements ShardManager
foreach ($shards as $shard) { foreach ($shards as $shard) {
$this->conn->connect($shard['id']); $this->conn->connect($shard['id']);
foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { foreach ($this->conn->fetchAllAssociative($sql, $params, $types) as $row) {
$result[] = $row; $result[] = $row;
} }
} }
......
...@@ -159,7 +159,7 @@ class SQLAzureShardManager implements ShardManager ...@@ -159,7 +159,7 @@ class SQLAzureShardManager implements ShardManager
INNER JOIN sys.federations f ON f.federation_id = d.federation_id INNER JOIN sys.federations f ON f.federation_id = d.federation_id
WHERE f.name = ' . $this->conn->quote($this->federationName); WHERE f.name = ' . $this->conn->quote($this->federationName);
return $this->conn->fetchAll($sql); return $this->conn->fetchAllAssociative($sql);
} }
/** /**
...@@ -177,7 +177,7 @@ class SQLAzureShardManager implements ShardManager ...@@ -177,7 +177,7 @@ class SQLAzureShardManager implements ShardManager
foreach ($shards as $shard) { foreach ($shards as $shard) {
$this->selectShard($shard['rangeLow']); $this->selectShard($shard['rangeLow']);
foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { foreach ($this->conn->fetchAllAssociative($sql, $params, $types) as $row) {
$result[] = $row; $result[] = $row;
} }
} }
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
namespace Doctrine\DBAL; namespace Doctrine\DBAL;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\Statement as DriverStatement; use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\DBAL\ForwardCompatibility\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
use IteratorAggregate; use IteratorAggregate;
use PDO; use PDO;
use Throwable; use Throwable;
use Traversable;
use function is_array; use function is_array;
use function is_string; use function is_string;
...@@ -15,7 +18,7 @@ use function is_string; ...@@ -15,7 +18,7 @@ use function is_string;
* A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support * A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support
* for logging, DBAL mapping types, etc. * for logging, DBAL mapping types, etc.
*/ */
class Statement implements IteratorAggregate, DriverStatement class Statement implements IteratorAggregate, DriverStatement, ForwardCompatibleResultStatement
{ {
/** /**
* The SQL statement. * The SQL statement.
...@@ -219,6 +222,8 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -219,6 +222,8 @@ class Statement implements IteratorAggregate, DriverStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/ */
public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
{ {
...@@ -236,6 +241,8 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -236,6 +241,8 @@ class Statement implements IteratorAggregate, DriverStatement
/** /**
* Required by interface IteratorAggregate. * Required by interface IteratorAggregate.
* *
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getIterator() public function getIterator()
...@@ -245,6 +252,8 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -245,6 +252,8 @@ class Statement implements IteratorAggregate, DriverStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*/ */
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{ {
...@@ -253,6 +262,8 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -253,6 +262,8 @@ class Statement implements IteratorAggregate, DriverStatement
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/ */
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{ {
...@@ -261,12 +272,176 @@ class Statement implements IteratorAggregate, DriverStatement ...@@ -261,12 +272,176 @@ class Statement implements IteratorAggregate, DriverStatement
/** /**
* {@inheritDoc} * {@inheritDoc}
*
* @deprecated Use fetchOne() instead.
*/ */
public function fetchColumn($columnIndex = 0) public function fetchColumn($columnIndex = 0)
{ {
return $this->stmt->fetchColumn($columnIndex); return $this->stmt->fetchColumn($columnIndex);
} }
/**
* {@inheritdoc}
*
* @throws DBALException
*/
public function fetchNumeric()
{
try {
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
return $this->stmt->fetchNumeric();
}
return $this->stmt->fetch(FetchMode::NUMERIC);
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritdoc}
*
* @throws DBALException
*/
public function fetchAssociative()
{
try {
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
return $this->stmt->fetchAssociative();
}
return $this->stmt->fetch(FetchMode::ASSOCIATIVE);
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritDoc}
*
* @throws DBALException
*/
public function fetchOne()
{
try {
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
return $this->stmt->fetchOne();
}
return $this->stmt->fetch(FetchMode::COLUMN);
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritdoc}
*
* @throws DBALException
*/
public function fetchAllNumeric() : array
{
try {
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
return $this->stmt->fetchAllNumeric();
}
return $this->stmt->fetchAll(FetchMode::NUMERIC);
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritdoc}
*
* @throws DBALException
*/
public function fetchAllAssociative() : array
{
try {
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
return $this->stmt->fetchAllAssociative();
}
return $this->stmt->fetchAll(FetchMode::ASSOCIATIVE);
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritDoc}
*
* @return Traversable<int,array<int,mixed>>
*
* @throws DBALException
*/
public function iterateNumeric() : Traversable
{
try {
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
while (($row = $this->stmt->fetchNumeric()) !== false) {
yield $row;
}
} else {
while (($row = $this->stmt->fetch(FetchMode::NUMERIC)) !== false) {
yield $row;
}
}
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritDoc}
*
* @return Traversable<int,array<string,mixed>>
*
* @throws DBALException
*/
public function iterateAssociative() : Traversable
{
try {
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
while (($row = $this->stmt->fetchAssociative()) !== false) {
yield $row;
}
} else {
while (($row = $this->stmt->fetch(FetchMode::ASSOCIATIVE)) !== false) {
yield $row;
}
}
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritDoc}
*
* @return Traversable<int,mixed>
*
* @throws DBALException
*/
public function iterateColumn() : Traversable
{
try {
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
while (($value = $this->stmt->fetchOne()) !== false) {
yield $value;
}
} else {
while (($value = $this->stmt->fetch(FetchMode::COLUMN)) !== false) {
yield $value;
}
}
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/** /**
* Returns the number of rows affected by the last execution of this statement. * Returns the number of rows affected by the last execution of this statement.
* *
......
...@@ -83,7 +83,7 @@ EOT ...@@ -83,7 +83,7 @@ EOT
} }
if (stripos($sql, 'select') === 0 || $input->getOption('force-fetch')) { if (stripos($sql, 'select') === 0 || $input->getOption('force-fetch')) {
$resultSet = $conn->fetchAll($sql); $resultSet = $conn->fetchAllAssociative($sql);
} else { } else {
$resultSet = $conn->executeUpdate($sql); $resultSet = $conn->executeUpdate($sql);
} }
......
...@@ -97,8 +97,10 @@ class StatementIteratorTest extends DbalTestCase ...@@ -97,8 +97,10 @@ class StatementIteratorTest extends DbalTestCase
yield [PortabilityStatement::class]; yield [PortabilityStatement::class];
yield [SQLAnywhereStatement::class]; yield [SQLAnywhereStatement::class];
if (extension_loaded('sqlsrv')) { if (! extension_loaded('sqlsrv')) {
yield [SQLSrvStatement::class]; return;
} }
yield [SQLSrvStatement::class];
} }
} }
<?php
namespace Doctrine\Tests\DBAL\Functional\Connection\BackwardCompatibility;
use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\DBAL\Connection as BaseConnection;
use function func_get_args;
/**
* Wraps statements in a non-forward-compatible wrapper.
*/
class Connection extends BaseConnection
{
/**
* {@inheritdoc}
*/
public function executeQuery($query, array $params = [], $types = [], ?QueryCacheProfile $qcp = null)
{
return new Statement(parent::executeQuery($query, $params, $types, $qcp));
}
/**
* {@inheritdoc}
*/
public function prepare($statement)
{
return new Statement(parent::prepare($statement));
}
/**
* {@inheritdoc}
*/
public function query()
{
return new Statement(parent::query(...func_get_args()));
}
}
<?php
namespace Doctrine\Tests\DBAL\Functional\Connection\BackwardCompatibility;
use Doctrine\DBAL\DriverManager;
use Doctrine\Tests\DBAL\Functional\Connection\FetchTest as BaseFetchTest;
use function array_merge;
class FetchTest extends BaseFetchTest
{
public function setUp() : void
{
parent::setUp();
$this->connection = DriverManager::getConnection(
array_merge($this->connection->getParams(), [
'wrapperClass' => Connection::class,
]),
$this->connection->getConfiguration(),
$this->connection->getEventManager()
);
}
}
<?php
namespace Doctrine\Tests\DBAL\Functional\Connection\BackwardCompatibility;
use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use PDO;
use function assert;
/**
* A wrapper that does not implement the forward-compatible statement interface.
*/
class Statement implements IteratorAggregate, DriverStatement
{
/** @var DriverStatement|ResultStatement */
private $stmt;
/**
* @param DriverStatement|ResultStatement $stmt
*/
public function __construct($stmt)
{
$this->stmt = $stmt;
}
/**
* {@inheritdoc}
*/
public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null)
{
assert($this->stmt instanceof DriverStatement);
return $this->stmt->bindParam($column, $variable, $type, $length);
}
/**
* {@inheritdoc}
*/
public function bindValue($param, $value, $type = ParameterType::STRING)
{
assert($this->stmt instanceof DriverStatement);
return $this->stmt->bindValue($param, $value, $type);
}
/**
* {@inheritdoc}
*/
public function closeCursor()
{
return $this->stmt->closeCursor();
}
/**
* {@inheritdoc}
*/
public function columnCount()
{
return $this->stmt->columnCount();
}
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function errorCode()
{
assert($this->stmt instanceof DriverStatement);
return $this->stmt->errorCode();
}
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function errorInfo()
{
assert($this->stmt instanceof DriverStatement);
return $this->stmt->errorInfo();
}
/**
* {@inheritdoc}
*/
public function execute($params = null)
{
assert($this->stmt instanceof DriverStatement);
return $this->stmt->execute($params);
}
/**
* {@inheritdoc}
*
* @deprecated Use one of the fetch- or iterate-related methods.
*/
public function setFetchMode($fetchMode, $arg1 = null, $arg2 = null)
{
return $this->stmt->setFetchMode($fetchMode, $arg1, $arg2);
}
/**
* {@inheritdoc}
*
* @deprecated Use iterateNumeric(), iterateAssociative() or iterateColumn() instead.
*/
public function getIterator()
{
return new StatementIterator($this);
}
/**
* {@inheritdoc}
*
* @deprecated Use fetchNumeric(), fetchAssociative() or fetchOne() instead.
*/
public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{
return $this->stmt->fetch($fetchMode);
}
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
return $this->stmt->fetchAll($fetchMode, $fetchArgument);
}
/**
* {@inheritdoc}
*
* @deprecated Use fetchOne() instead.
*/
public function fetchColumn($columnIndex = 0)
{
return $this->stmt->fetchColumn($columnIndex);
}
/**
* {@inheritdoc}
*/
public function rowCount()
{
assert($this->stmt instanceof DriverStatement);
return $this->stmt->rowCount();
}
}
<?php
namespace Doctrine\Tests\DBAL\Functional\Connection;
use Doctrine\Tests\DbalFunctionalTestCase;
use Doctrine\Tests\TestUtil;
use function iterator_to_array;
class FetchTest extends DbalFunctionalTestCase
{
/** @var string */
private $query;
public function setUp() : void
{
parent::setUp();
$this->query = TestUtil::generateResultSetQuery([
[
'a' => 'foo',
'b' => 1,
],
[
'a' => 'bar',
'b' => 2,
],
[
'a' => 'baz',
'b' => 3,
],
], $this->connection->getDatabasePlatform());
}
public function testFetchNumeric() : void
{
self::assertEquals(['foo', 1], $this->connection->fetchNumeric($this->query));
}
public function testFetchOne() : void
{
self::assertEquals('foo', $this->connection->fetchOne($this->query));
}
public function testFetchAssociative() : void
{
self::assertEquals([
'a' => 'foo',
'b' => 1,
], $this->connection->fetchAssociative($this->query));
}
public function testFetchAllNumeric() : void
{
self::assertEquals([
['foo', 1],
['bar', 2],
['baz', 3],
], $this->connection->fetchAllNumeric($this->query));
}
public function testFetchAllAssociative() : void
{
self::assertEquals([
[
'a' => 'foo',
'b' => 1,
],
[
'a' => 'bar',
'b' => 2,
],
[
'a' => 'baz',
'b' => 3,
],
], $this->connection->fetchAllAssociative($this->query));
}
public function testIterateNumeric() : void
{
self::assertEquals([
['foo', 1],
['bar', 2],
['baz', 3],
], iterator_to_array($this->connection->iterateNumeric($this->query)));
}
public function testIterateAssociative() : void
{
self::assertEquals([
[
'a' => 'foo',
'b' => 1,
],
[
'a' => 'bar',
'b' => 2,
],
[
'a' => 'baz',
'b' => 3,
],
], iterator_to_array($this->connection->iterateAssociative($this->query)));
}
public function testIterateColumn() : void
{
self::assertEquals([
'foo',
'bar',
'baz',
], iterator_to_array($this->connection->iterateColumn($this->query)));
}
}
...@@ -30,7 +30,7 @@ final class DB2SchemaManagerTest extends TestCase ...@@ -30,7 +30,7 @@ final class DB2SchemaManagerTest extends TestCase
$platform = $this->createMock(DB2Platform::class); $platform = $this->createMock(DB2Platform::class);
$this->conn = $this $this->conn = $this
->getMockBuilder(Connection::class) ->getMockBuilder(Connection::class)
->onlyMethods(['fetchAll', 'quote']) ->onlyMethods(['fetchAllAssociative', 'quote'])
->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager]) ->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager])
->getMock(); ->getMock();
$this->manager = new DB2SchemaManager($this->conn); $this->manager = new DB2SchemaManager($this->conn);
...@@ -44,7 +44,7 @@ final class DB2SchemaManagerTest extends TestCase ...@@ -44,7 +44,7 @@ final class DB2SchemaManagerTest extends TestCase
public function testListTableNamesFiltersAssetNamesCorrectly() : void public function testListTableNamesFiltersAssetNamesCorrectly() : void
{ {
$this->conn->getConfiguration()->setFilterSchemaAssetsExpression('/^(?!T_)/'); $this->conn->getConfiguration()->setFilterSchemaAssetsExpression('/^(?!T_)/');
$this->conn->expects($this->once())->method('fetchAll')->will($this->returnValue([ $this->conn->expects($this->once())->method('fetchAllAssociative')->will($this->returnValue([
['name' => 'FOO'], ['name' => 'FOO'],
['name' => 'T_FOO'], ['name' => 'T_FOO'],
['name' => 'BAR'], ['name' => 'BAR'],
...@@ -67,7 +67,7 @@ final class DB2SchemaManagerTest extends TestCase ...@@ -67,7 +67,7 @@ final class DB2SchemaManagerTest extends TestCase
{ {
$filterExpression = '/^(?!T_)/'; $filterExpression = '/^(?!T_)/';
$this->conn->getConfiguration()->setFilterSchemaAssetsExpression($filterExpression); $this->conn->getConfiguration()->setFilterSchemaAssetsExpression($filterExpression);
$this->conn->expects($this->once())->method('fetchAll')->will($this->returnValue([ $this->conn->expects($this->once())->method('fetchAllAssociative')->will($this->returnValue([
['name' => 'FOO'], ['name' => 'FOO'],
['name' => 'T_FOO'], ['name' => 'T_FOO'],
['name' => 'BAR'], ['name' => 'BAR'],
...@@ -96,7 +96,7 @@ final class DB2SchemaManagerTest extends TestCase ...@@ -96,7 +96,7 @@ final class DB2SchemaManagerTest extends TestCase
return in_array($assetName, $accepted); return in_array($assetName, $accepted);
}); });
$this->conn->expects($this->any())->method('quote'); $this->conn->expects($this->any())->method('quote');
$this->conn->expects($this->once())->method('fetchAll')->will($this->returnValue([ $this->conn->expects($this->once())->method('fetchAllAssociative')->will($this->returnValue([
['name' => 'FOO'], ['name' => 'FOO'],
['name' => 'T_FOO'], ['name' => 'T_FOO'],
['name' => 'BAR'], ['name' => 'BAR'],
...@@ -121,7 +121,7 @@ final class DB2SchemaManagerTest extends TestCase ...@@ -121,7 +121,7 @@ final class DB2SchemaManagerTest extends TestCase
return in_array($assetName, $accepted); return in_array($assetName, $accepted);
}); });
$this->conn->expects($this->any())->method('quote'); $this->conn->expects($this->any())->method('quote');
$this->conn->expects($this->atLeastOnce())->method('fetchAll')->will($this->returnValue([ $this->conn->expects($this->atLeastOnce())->method('fetchAllAssociative')->will($this->returnValue([
['name' => 'FOO'], ['name' => 'FOO'],
['name' => 'T_FOO'], ['name' => 'T_FOO'],
['name' => 'BAR'], ['name' => 'BAR'],
...@@ -156,7 +156,7 @@ final class DB2SchemaManagerTest extends TestCase ...@@ -156,7 +156,7 @@ final class DB2SchemaManagerTest extends TestCase
$filterExpression = '/^(?!T_)/'; $filterExpression = '/^(?!T_)/';
$this->conn->getConfiguration()->setFilterSchemaAssetsExpression($filterExpression); $this->conn->getConfiguration()->setFilterSchemaAssetsExpression($filterExpression);
$this->conn->expects($this->exactly(2))->method('fetchAll')->will($this->returnValue([ $this->conn->expects($this->exactly(2))->method('fetchAllAssociative')->will($this->returnValue([
['name' => 'FOO'], ['name' => 'FOO'],
['name' => 'T_FOO'], ['name' => 'T_FOO'],
['name' => 'BAR'], ['name' => 'BAR'],
......
...@@ -23,11 +23,15 @@ class MySqlSchemaManagerTest extends TestCase ...@@ -23,11 +23,15 @@ class MySqlSchemaManagerTest extends TestCase
protected function setUp() : void protected function setUp() : void
{ {
$eventManager = new EventManager(); $eventManager = new EventManager();
$driverMock = $this->createMock(Driver::class); $driverMock = $this->createMock(Driver::class);
$platform = $this->createMock(MySqlPlatform::class);
$platform = $this->createMock(MySqlPlatform::class);
$platform->method('getListTableForeignKeysSQL')
->willReturn('');
$this->conn = $this->getMockBuilder(Connection::class) $this->conn = $this->getMockBuilder(Connection::class)
->onlyMethods(['fetchAll']) ->onlyMethods(['fetchAllAssociative'])
->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager]) ->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager])
->getMock(); ->getMock();
$this->manager = new MySqlSchemaManager($this->conn); $this->manager = new MySqlSchemaManager($this->conn);
...@@ -35,7 +39,7 @@ class MySqlSchemaManagerTest extends TestCase ...@@ -35,7 +39,7 @@ class MySqlSchemaManagerTest extends TestCase
public function testCompositeForeignKeys() : void public function testCompositeForeignKeys() : void
{ {
$this->conn->expects($this->once())->method('fetchAll')->will($this->returnValue($this->getFKDefinition())); $this->conn->expects($this->once())->method('fetchAllAssociative')->will($this->returnValue($this->getFKDefinition()));
$fkeys = $this->manager->listTableForeignKeys('dummy'); $fkeys = $this->manager->listTableForeignKeys('dummy');
self::assertCount(1, $fkeys, 'Table has to have one foreign key.'); self::assertCount(1, $fkeys, 'Table has to have one foreign key.');
......
...@@ -16,7 +16,7 @@ class PoolingShardManagerTest extends TestCase ...@@ -16,7 +16,7 @@ class PoolingShardManagerTest extends TestCase
private function createConnectionMock() : PoolingShardConnection private function createConnectionMock() : PoolingShardConnection
{ {
return $this->getMockBuilder(PoolingShardConnection::class) return $this->getMockBuilder(PoolingShardConnection::class)
->onlyMethods(['connect', 'getParams', 'fetchAll']) ->onlyMethods(['connect', 'getParams', 'fetchAllAssociative'])
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
} }
...@@ -101,12 +101,12 @@ class PoolingShardManagerTest extends TestCase ...@@ -101,12 +101,12 @@ class PoolingShardManagerTest extends TestCase
)); ));
$conn->expects($this->at(2))->method('connect')->with($this->equalTo(1)); $conn->expects($this->at(2))->method('connect')->with($this->equalTo(1));
$conn->expects($this->at(3)) $conn->expects($this->at(3))
->method('fetchAll') ->method('fetchAllAssociative')
->with($this->equalTo($sql), $this->equalTo($params), $this->equalTo($types)) ->with($this->equalTo($sql), $this->equalTo($params), $this->equalTo($types))
->will($this->returnValue([ ['id' => 1] ])); ->will($this->returnValue([ ['id' => 1] ]));
$conn->expects($this->at(4))->method('connect')->with($this->equalTo(2)); $conn->expects($this->at(4))->method('connect')->with($this->equalTo(2));
$conn->expects($this->at(5)) $conn->expects($this->at(5))
->method('fetchAll') ->method('fetchAllAssociative')
->with($this->equalTo($sql), $this->equalTo($params), $this->equalTo($types)) ->with($this->equalTo($sql), $this->equalTo($params), $this->equalTo($types))
->will($this->returnValue([ ['id' => 2] ])); ->will($this->returnValue([ ['id' => 2] ]));
...@@ -131,12 +131,12 @@ class PoolingShardManagerTest extends TestCase ...@@ -131,12 +131,12 @@ class PoolingShardManagerTest extends TestCase
)); ));
$conn->expects($this->at(2))->method('connect')->with($this->equalTo(1)); $conn->expects($this->at(2))->method('connect')->with($this->equalTo(1));
$conn->expects($this->at(3)) $conn->expects($this->at(3))
->method('fetchAll') ->method('fetchAllAssociative')
->with($this->equalTo($sql), $this->equalTo($params), $this->equalTo($types)) ->with($this->equalTo($sql), $this->equalTo($params), $this->equalTo($types))
->will($this->returnValue([ ['id' => 1] ])); ->will($this->returnValue([ ['id' => 1] ]));
$conn->expects($this->at(4))->method('connect')->with($this->equalTo(2)); $conn->expects($this->at(4))->method('connect')->with($this->equalTo(2));
$conn->expects($this->at(5)) $conn->expects($this->at(5))
->method('fetchAll') ->method('fetchAllAssociative')
->with($this->equalTo($sql), $this->equalTo($params), $this->equalTo($types)) ->with($this->equalTo($sql), $this->equalTo($params), $this->equalTo($types))
->will($this->returnValue([ ['id' => 2] ])); ->will($this->returnValue([ ['id' => 2] ]));
......
...@@ -30,7 +30,7 @@ class RunSqlCommandTest extends TestCase ...@@ -30,7 +30,7 @@ class RunSqlCommandTest extends TestCase
$this->commandTester = new CommandTester($this->command); $this->commandTester = new CommandTester($this->command);
$this->connectionMock = $this->createMock(Connection::class); $this->connectionMock = $this->createMock(Connection::class);
$this->connectionMock->method('fetchAll') $this->connectionMock->method('fetchAllAssociative')
->willReturn([[1]]); ->willReturn([[1]]);
$this->connectionMock->method('executeUpdate') $this->connectionMock->method('executeUpdate')
->willReturn(42); ->willReturn(42);
...@@ -68,7 +68,7 @@ class RunSqlCommandTest extends TestCase ...@@ -68,7 +68,7 @@ class RunSqlCommandTest extends TestCase
public function testSelectStatementsPrintsResult() : void public function testSelectStatementsPrintsResult() : void
{ {
$this->expectConnectionFetchAll(); $this->expectConnectionFetchAllAssociative();
$exitCode = $this->commandTester->execute([ $exitCode = $this->commandTester->execute([
'command' => $this->command->getName(), 'command' => $this->command->getName(),
...@@ -100,22 +100,22 @@ class RunSqlCommandTest extends TestCase ...@@ -100,22 +100,22 @@ class RunSqlCommandTest extends TestCase
->method('executeUpdate'); ->method('executeUpdate');
$this->connectionMock $this->connectionMock
->expects($this->exactly(0)) ->expects($this->exactly(0))
->method('fetchAll'); ->method('fetchAllAssociative');
} }
private function expectConnectionFetchAll() : void private function expectConnectionFetchAllAssociative() : void
{ {
$this->connectionMock $this->connectionMock
->expects($this->exactly(0)) ->expects($this->exactly(0))
->method('executeUpdate'); ->method('executeUpdate');
$this->connectionMock $this->connectionMock
->expects($this->exactly(1)) ->expects($this->exactly(1))
->method('fetchAll'); ->method('fetchAllAssociative');
} }
public function testStatementsWithFetchResultPrintsResult() : void public function testStatementsWithFetchResultPrintsResult() : void
{ {
$this->expectConnectionFetchAll(); $this->expectConnectionFetchAllAssociative();
$this->commandTester->execute([ $this->commandTester->execute([
'command' => $this->command->getName(), 'command' => $this->command->getName(),
......
...@@ -4,9 +4,15 @@ namespace Doctrine\Tests; ...@@ -4,9 +4,15 @@ namespace Doctrine\Tests;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use PHPUnit\Framework\Assert; use PHPUnit\Framework\Assert;
use function array_keys;
use function array_map;
use function array_values;
use function explode; use function explode;
use function extension_loaded; use function extension_loaded;
use function implode;
use function is_string;
use function unlink; use function unlink;
/** /**
...@@ -207,4 +213,24 @@ class TestUtil ...@@ -207,4 +213,24 @@ class TestUtil
{ {
return DriverManager::getConnection(self::getParamsForTemporaryConnection()); return DriverManager::getConnection(self::getParamsForTemporaryConnection());
} }
/**
* Generates a query that will return the given rows without the need to create a temporary table.
*
* @param array<int,array<string,mixed>> $rows
*/
public static function generateResultSetQuery(array $rows, AbstractPlatform $platform) : string
{
return implode(' UNION ALL ', array_map(static function (array $row) use ($platform) : string {
return $platform->getDummySelectSQL(
implode(', ', array_map(static function (string $column, $value) use ($platform) : string {
if (is_string($value)) {
$value = $platform->quoteStringLiteral($value);
}
return $value . ' ' . $platform->quoteIdentifier($column);
}, array_keys($row), array_values($row)))
);
}, $rows));
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment