Unverified Commit a7aa9760 authored by Sergei Morozov's avatar Sergei Morozov

Merge branch '3.0.x'

parents 0ac110cf 74eca6ba
......@@ -22,10 +22,6 @@ The `CompositeExpression` class is now immutable.
The `OCI8Statement::convertPositionalToNamedPlaceholders()` method has been extracted to an internal utility class.
## BC BREAK: Dropped handling of one-based numeric arrays of parameters in `Statement::execute()`
The statement implementations no longer detect whether `$params` is a zero- or one-based array. A zero-based numeric array is expected.
## BC BREAK: `ServerInfoAwareConnection::requiresQueryForServerVersion()` is removed.
The `ServerInfoAwareConnection::requiresQueryForServerVersion()` method has been removed as an implementation detail which is the same for almost all supported drivers.
......@@ -97,7 +93,6 @@ Table columns are no longer indexed by column name. Use the `name` attribute of
- The following methods have been removed as leaking internal implementation details: `::getHost()`, `::getPort()`, `::getUsername()`, `::getPassword()`.
- The `::getDatabase()` method can now return null which means that no database is currently selected.
- The `::project()` method has been removed. Use `::executeQuery()` and fetch the data from the statement using one of the `Statement::fetch*()` methods instead.
## BC BREAK: Changes in `Doctrine\DBAL\Driver\SQLSrv\LastInsertId`
......@@ -154,10 +149,6 @@ The `Doctrine\DBAL\Driver::getName()` has been removed.
`AbstractSchemaManager::extractDoctrineTypeFromComment()` made `protected`. It takes the comment by reference, removes the type annotation from it and returns the extracted Doctrine type.
## BC BREAK `::errorCode()` and `::errorInfo()` removed from `Connection` and `Statement` APIs
The error information is available in `DriverException` trown in case of an error.
## BC BREAK Changes in driver exceptions
1. The `Doctrine\DBAL\Driver\DriverException::getErrorCode()` method is removed. In order to obtain the driver error code, please use `::getCode()`.
......@@ -269,6 +260,32 @@ The Doctrine\DBAL\Version class is no longer available: please refrain from chec
# Upgrade to 3.0
## BC BREAK `Statement::rowCount()` is moved.
`Statement::rowCount()` has been moved to the `ResultStatement` interface where it belongs by definition.
## Removed `FetchMode` and the corresponding methods
1. The `FetchMode` class and the `setFetchMode()` method of the `Connection` and `Statement` interfaces are removed.
2. The `Statement::fetch()` method is replaced with `fetchNumeric()`, `fetchAssociative()` and `fetchOne()`.
3. The `Statement::fetchAll()` method is replaced with `fetchAllNumeric()`, `fetchAllAssociative()` and `fechColumn()`.
4. The `Statement::fetchColumn()` method is replaced with `fetchOne()`.
5. The `Connection::fetchArray()` and `fetchAssoc()` methods are replaced with `fetchNumeric()` and `fetchAssociative()` respectively.
6. The `StatementIterator` class is removed. The usage of a `Statement` object as `Traversable` is no longer possible. Use `iterateNumeric()`, `iterateAssociative()` and `iterateColumn()` instead.
7. Fetching data in mixed mode (former `FetchMode::MIXED`) is no longer possible.
## BC BREAK: Dropped handling of one-based numeric arrays of parameters in `Statement::execute()`
The statement implementations no longer detect whether `$params` is a zero- or one-based array. A zero-based numeric array is expected.
## BC BREAK `Statement::project()` has been removed
- The `Statement::project()` method has been removed. Use `::executeQuery()` and fetch the data from the statement using one of the `Statement::fetch*()` methods instead.
## BC BREAK `::errorCode()` and `::errorInfo()` removed from `Connection` and `Statement` APIs
The error information is available in `DriverException` thrown in case of an error.
## BC BREAK: Dropped support for `FetchMode::CUSTOM_OBJECT` and `::STANDARD_OBJECT`
Instead of fetching an object, fetch an array and map it to an object of the desired class.
......@@ -407,6 +424,16 @@ Please use other database client applications for import, e.g.:
# 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()`
The `Connection::project()` method is deprecated. Implement data transformation outside of DBAL.
......
......@@ -32,7 +32,7 @@
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"}
],
"require": {
"php": "^7.3",
"php": "^7.3 || ^8.0",
"doctrine/cache": "^1.0",
"doctrine/event-manager": "^1.0",
"ocramius/package-versions": "^1.4"
......@@ -45,6 +45,7 @@
"phpstan/phpstan-phpunit": "^0.12",
"phpstan/phpstan-strict-rules": "^0.12.2",
"phpunit/phpunit": "^9.1.1",
"slevomat/coding-standard": "^6.3.6",
"symfony/console": "^2.0.5|^3.0|^4.0|^5.0",
"vimeo/psalm": "^3.11"
},
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "380f0866b260bf8eb74733a2461f927f",
"content-hash": "ec7d2054f95cb2a24421dcf208e65186",
"packages": [
{
"name": "doctrine/cache",
......@@ -820,16 +820,16 @@
},
{
"name": "netresearch/jsonmapper",
"version": "v2.1.0",
"version": "v2.0.0",
"source": {
"type": "git",
"url": "https://github.com/cweiske/jsonmapper.git",
"reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e"
"reference": "e245890383c3ed38b6d202ee373c23ccfebc0f54"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/e0f1e33a71587aca81be5cffbb9746510e1fe04e",
"reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/e245890383c3ed38b6d202ee373c23ccfebc0f54",
"reference": "e245890383c3ed38b6d202ee373c23ccfebc0f54",
"shasum": ""
},
"require": {
......@@ -862,7 +862,7 @@
}
],
"description": "Map nested JSON structures onto PHP classes",
"time": "2020-04-16T18:48:43+00:00"
"time": "2020-03-04T17:23:33+00:00"
},
{
"name": "nikic/php-parser",
......@@ -1371,21 +1371,21 @@
},
{
"name": "phpstan/phpstan-phpunit",
"version": "0.12.6",
"version": "0.12.8",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
"reference": "26394996368b6d033d012547d3197f4e07e23021"
"reference": "7232c17e2493dc598173da784477ce0afb2c4e0e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/26394996368b6d033d012547d3197f4e07e23021",
"reference": "26394996368b6d033d012547d3197f4e07e23021",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/7232c17e2493dc598173da784477ce0afb2c4e0e",
"reference": "7232c17e2493dc598173da784477ce0afb2c4e0e",
"shasum": ""
},
"require": {
"php": "~7.1",
"phpstan/phpstan": "^0.12.4"
"phpstan/phpstan": "^0.12.6"
},
"conflict": {
"phpunit/phpunit": "<7.0"
......@@ -1423,7 +1423,7 @@
"MIT"
],
"description": "PHPUnit extensions and rules for PHPStan",
"time": "2020-01-10T12:07:21+00:00"
"time": "2020-04-17T08:04:10+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
......@@ -1872,6 +1872,16 @@
"testing",
"xunit"
],
"funding": [
{
"url": "https://phpunit.de/donate.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-04-03T14:40:04+00:00"
},
{
......@@ -1965,6 +1975,12 @@
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-03-30T11:59:20+00:00"
},
{
......@@ -2183,6 +2199,12 @@
"environment",
"hhvm"
],
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-03-31T12:14:15+00:00"
},
{
......@@ -2587,16 +2609,16 @@
},
{
"name": "slevomat/coding-standard",
"version": "6.3.3",
"version": "6.3.8",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "b905a82255749de847fd4de607c7a4c8163f058d"
"reference": "500f55b5e2dee1dcef8e88f2038990acdba29f1c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/b905a82255749de847fd4de607c7a4c8163f058d",
"reference": "b905a82255749de847fd4de607c7a4c8163f058d",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/500f55b5e2dee1dcef8e88f2038990acdba29f1c",
"reference": "500f55b5e2dee1dcef8e88f2038990acdba29f1c",
"shasum": ""
},
"require": {
......@@ -2640,7 +2662,7 @@
"type": "tidelift"
}
],
"time": "2020-04-28T07:15:08+00:00"
"time": "2020-05-27T06:28:47+00:00"
},
{
"name": "squizlabs/php_codesniffer",
......@@ -3053,8 +3075,8 @@
"authors": [
{
"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",
......@@ -3306,7 +3328,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "^7.3"
"php": "^7.3 || ^8.0"
},
"platform-dev": [],
"platform-overrides": {
......
......@@ -42,7 +42,7 @@ object is closed:
<?php
$stmt = $conn->executeCacheQuery($query, $params, $types, new QueryCacheProfile(0, "some key"));
$data = $stmt->fetchAll();
$data = $stmt->fetchAllAssociative();
$stmt->closeCursor(); // at this point the result is cached
.. warning::
......
......@@ -41,7 +41,7 @@ the query until there are no more rows:
<?php
while ($row = $stmt->fetch()) {
while (($row = $stmt->fetchAssociative()) !== false) {
echo $row['headline'];
}
......@@ -308,7 +308,7 @@ Prepare a given SQL statement and return the
<?php
$statement = $conn->prepare('SELECT * FROM user');
$statement->execute();
$users = $statement->fetchAll();
$users = $statement->fetchAllAssociative();
/*
array(
......@@ -346,7 +346,7 @@ parameters to the execute method, then returning the statement:
<?php
$statement = $conn->executeQuery('SELECT * FROM user WHERE username = ?', array('jwage'));
$user = $statement->fetch();
$user = $statement->fetchAssociative();
/*
array(
......@@ -360,15 +360,15 @@ to perform necessary type conversions between actual input
parameters and expected database values. See the
:ref:`Types <mappingMatrix>` section for more information.
fetchAll()
~~~~~~~~~~
fetchAllAssociative()
~~~~~~~~~~~~~~~~~~~~~
Execute the query and fetch all results into an array:
.. code-block:: php
<?php
$users = $conn->fetchAll('SELECT * FROM user');
$users = $conn->fetchAllAssociative('SELECT * FROM user');
/*
array(
......@@ -379,15 +379,15 @@ Execute the query and fetch all results into an array:
)
*/
fetchArray()
~~~~~~~~~~~~
fetchNumeric()
~~~~~~~~~~~~~~
Numeric index retrieval of first result row of the given query:
.. code-block:: php
<?php
$user = $conn->fetchArray('SELECT * FROM user WHERE username = ?', array('jwage'));
$user = $conn->fetchNumeric('SELECT * FROM user WHERE username = ?', array('jwage'));
/*
array(
......@@ -396,26 +396,26 @@ Numeric index retrieval of first result row of the given query:
)
*/
fetchColumn()
~~~~~~~~~~~~~
fetchOne()
~~~~~~~~~~
Retrieve only the given column of the first result row.
Retrieve only the value of the first column of the first result row.
.. code-block:: php
<?php
$username = $conn->fetchColumn('SELECT username FROM user WHERE id = ?', array(1), 0);
$username = $conn->fetchOne('SELECT username FROM user WHERE id = ?', array(1), 0);
echo $username; // jwage
fetchAssoc()
~~~~~~~~~~~~
fetchAssociative()
~~~~~~~~~~~~~~~~~~
Retrieve assoc row of the first result row.
Retrieve associative array of the first result row.
.. code-block:: php
<?php
$user = $conn->fetchAssoc('SELECT * FROM user WHERE username = ?', array('jwage'));
$user = $conn->fetchAssociative('SELECT * FROM user WHERE username = ?', array('jwage'));
/*
array(
'username' => 'jwage',
......
......@@ -4,18 +4,13 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Cache;
use ArrayIterator;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\FetchMode;
use InvalidArgumentException;
use IteratorAggregate;
use function array_merge;
use function array_values;
use function count;
use function reset;
use function sprintf;
final class ArrayStatement implements IteratorAggregate, ResultStatement
final class ArrayStatement implements ResultStatement
{
/** @var mixed[] */
private $data;
......@@ -26,9 +21,6 @@ final class ArrayStatement implements IteratorAggregate, ResultStatement
/** @var int */
private $num = 0;
/** @var int */
private $defaultFetchMode = FetchMode::MIXED;
/**
* @param mixed[] $data
*/
......@@ -57,78 +49,75 @@ final class ArrayStatement implements IteratorAggregate, ResultStatement
return count($this->data);
}
public function setFetchMode(int $fetchMode) : void
{
$this->defaultFetchMode = $fetchMode;
}
/**
* {@inheritdoc}
*/
public function getIterator()
public function fetchNumeric()
{
$data = $this->fetchAll();
$row = $this->fetch();
if ($row === false) {
return false;
}
return new ArrayIterator($data);
return array_values($row);
}
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null)
public function fetchAssociative()
{
if (! isset($this->data[$this->num])) {
return false;
return $this->fetch();
}
$row = $this->data[$this->num++];
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
if ($fetchMode === FetchMode::ASSOCIATIVE) {
return $row;
}
if ($fetchMode === FetchMode::NUMERIC) {
return array_values($row);
}
/**
* {@inheritdoc}
*/
public function fetchOne()
{
$row = $this->fetch();
if ($fetchMode === FetchMode::MIXED) {
return array_merge($row, array_values($row));
if ($row === false) {
return false;
}
if ($fetchMode === FetchMode::COLUMN) {
return reset($row);
}
throw new InvalidArgumentException(
sprintf('Invalid fetch mode given for fetching result, %d given.', $fetchMode)
);
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null) : array
public function fetchAllNumeric() : array
{
$rows = [];
while ($row = $this->fetch($fetchMode)) {
$rows[] = $row;
return FetchUtils::fetchAllNumeric($this);
}
return $rows;
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
return FetchUtils::fetchAllAssociative($this);
}
/**
* {@inheritdoc}
*/
public function fetchColumn()
public function fetchColumn() : array
{
$row = $this->fetch(FetchMode::NUMERIC);
return FetchUtils::fetchColumn($this);
}
if ($row === false) {
/**
* @return mixed|false
*/
private function fetch()
{
if (! isset($this->data[$this->num])) {
return false;
}
return $row[0];
return $this->data[$this->num++];
}
}
......@@ -4,15 +4,12 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Cache;
use ArrayIterator;
use Doctrine\Common\Cache\Cache;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\FetchMode;
use InvalidArgumentException;
use IteratorAggregate;
use function array_merge;
use function array_map;
use function array_values;
use function reset;
/**
* Cache statement for SQL results.
......@@ -27,7 +24,7 @@ use function reset;
* 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.
*/
final class ResultCacheStatement implements IteratorAggregate, ResultStatement
final class ResultCacheStatement implements ResultStatement
{
/** @var Cache */
private $resultCache;
......@@ -51,12 +48,9 @@ final class ResultCacheStatement implements IteratorAggregate, ResultStatement
*/
private $emptied = false;
/** @var mixed[] */
/** @var array<int,array<string,mixed>> */
private $data;
/** @var int */
private $defaultFetchMode = FetchMode::MIXED;
public function __construct(ResultStatement $stmt, Cache $resultCache, string $cacheKey, string $realKey, int $lifetime)
{
$this->statement = $stmt;
......@@ -90,76 +84,61 @@ final class ResultCacheStatement implements IteratorAggregate, ResultStatement
return $this->statement->columnCount();
}
public function setFetchMode(int $fetchMode) : void
public function rowCount() : int
{
$this->defaultFetchMode = $fetchMode;
return $this->statement->rowCount();
}
/**
* {@inheritdoc}
*/
public function getIterator()
public function fetchNumeric()
{
$data = $this->fetchAll();
$row = $this->fetch();
return new ArrayIterator($data);
if ($row === false) {
return false;
}
return array_values($row);
}
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null)
public function fetchAssociative()
{
if ($this->data === null) {
$this->data = [];
}
$row = $this->statement->fetch(FetchMode::ASSOCIATIVE);
if ($row !== false) {
$this->data[] = $row;
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
if ($fetchMode === FetchMode::ASSOCIATIVE) {
return $row;
}
if ($fetchMode === FetchMode::NUMERIC) {
return array_values($row);
}
if ($fetchMode === FetchMode::MIXED) {
return array_merge($row, array_values($row));
}
if ($fetchMode === FetchMode::COLUMN) {
return reset($row);
return $this->fetch();
}
throw new InvalidArgumentException('Invalid fetch-style given for caching result.');
}
$this->emptied = true;
return false;
/**
* {@inheritdoc}
*/
public function fetchOne()
{
return FetchUtils::fetchOne($this);
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null) : array
public function fetchAllNumeric() : array
{
$data = $this->statement->fetchAll($fetchMode);
$this->store(
$this->statement->fetchAllAssociative()
);
if ($fetchMode === FetchMode::COLUMN) {
foreach ($data as $key => $value) {
$data[$key] = [$value];
}
return array_map('array_values', $this->data);
}
$this->data = $data;
$this->emptied = true;
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
$this->store(
$this->statement->fetchAllAssociative()
);
return $this->data;
}
......@@ -167,30 +146,41 @@ final class ResultCacheStatement implements IteratorAggregate, ResultStatement
/**
* {@inheritdoc}
*/
public function fetchColumn()
public function fetchColumn() : array
{
$row = $this->fetch(FetchMode::NUMERIC);
return FetchUtils::fetchColumn($this);
}
if ($row === false) {
return false;
/**
* @return array<string,mixed>|false
*
* @throws DriverException
*/
private function fetch()
{
if ($this->data === null) {
$this->data = [];
}
return $row[0];
$row = $this->statement->fetchAssociative();
if ($row !== false) {
$this->data[] = $row;
return $row;
}
$this->emptied = true;
return false;
}
/**
* Returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement
* executed by the corresponding object.
*
* If the last SQL statement executed by the associated Statement object was a SELECT statement,
* some databases may return the number of rows returned by that statement. However,
* this behaviour is not guaranteed for all databases and should not be
* relied on for portable applications.
*
* @return int The number of rows.
* @param array<int,array<string,mixed>> $data
*/
public function rowCount() : int
private function store(array $data) : void
{
return $this->statement->rowCount();
$this->data = $data;
$this->emptied = true;
}
}
This diff is collapsed.
......@@ -324,8 +324,6 @@ class MasterSlaveConnection extends Connection
$statement = $this->_conn->query($sql);
$statement->setFetchMode($this->defaultFetchMode);
$logger->stopQuery();
return $statement;
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver;
/**
* @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;
}
/**
* @return array<int,mixed>
*
* @throws DriverException
*/
public static function fetchColumn(ResultStatement $stmt) : array
{
$rows = [];
while (($row = $stmt->fetchOne()) !== false) {
$rows[] = $row;
}
return $rows;
}
}
......@@ -4,17 +4,14 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use function assert;
use function db2_bind_param;
use function db2_execute;
use function db2_fetch_array;
use function db2_fetch_assoc;
use function db2_fetch_both;
use function db2_free_result;
use function db2_num_fields;
use function db2_num_rows;
......@@ -33,7 +30,7 @@ use const DB2_LONG;
use const DB2_PARAM_FILE;
use const DB2_PARAM_IN;
final class DB2Statement implements IteratorAggregate, Statement
final class DB2Statement implements Statement
{
/** @var resource */
private $stmt;
......@@ -49,9 +46,6 @@ final class DB2Statement implements IteratorAggregate, Statement
*/
private $lobs = [];
/** @var int */
private $defaultFetchMode = FetchMode::MIXED;
/**
* Indicates whether the statement is in the state when fetching results is possible
*
......@@ -133,8 +127,6 @@ final class DB2Statement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function execute(?array $params = null) : void
{
......@@ -173,85 +165,62 @@ final class DB2Statement implements IteratorAggregate, Statement
$this->result = true;
}
public function setFetchMode(int $fetchMode) : void
{
$this->defaultFetchMode = $fetchMode;
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
public function getIterator()
public function fetchNumeric()
{
return new StatementIterator($this);
if (! $this->result) {
return false;
}
return db2_fetch_array($this->stmt);
}
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null)
public function fetchAssociative()
{
// do not try fetching from the statement if it's not expected to contain result
// 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;
}
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
switch ($fetchMode) {
case FetchMode::COLUMN:
return $this->fetchColumn();
case FetchMode::MIXED:
return db2_fetch_both($this->stmt);
case FetchMode::ASSOCIATIVE:
return db2_fetch_assoc($this->stmt);
case FetchMode::NUMERIC:
return db2_fetch_array($this->stmt);
default:
throw new DB2Exception('Given Fetch-Style ' . $fetchMode . ' is not supported.');
}
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null) : array
public function fetchOne()
{
$rows = [];
switch ($fetchMode) {
case FetchMode::COLUMN:
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
return FetchUtils::fetchOne($this);
}
break;
default:
while (($row = $this->fetch($fetchMode)) !== false) {
$rows[] = $row;
}
}
return $rows;
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return FetchUtils::fetchAllNumeric($this);
}
/**
* {@inheritdoc}
*/
public function fetchColumn()
public function fetchAllAssociative() : array
{
$row = $this->fetch(FetchMode::NUMERIC);
if ($row === false) {
return false;
return FetchUtils::fetchAllAssociative($this);
}
return $row[0];
/**
* {@inheritdoc}
*/
public function fetchColumn() : array
{
return FetchUtils::fetchColumn($this);
}
public function rowCount() : int
......
......@@ -5,17 +5,14 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Mysqli\Exception\ConnectionError;
use Doctrine\DBAL\Driver\Mysqli\Exception\FailedReadingStreamOffset;
use Doctrine\DBAL\Driver\Mysqli\Exception\StatementError;
use Doctrine\DBAL\Driver\Mysqli\Exception\UnknownFetchMode;
use Doctrine\DBAL\Driver\Mysqli\Exception\UnknownType;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use mysqli;
use mysqli_stmt;
use stdClass;
......@@ -32,7 +29,7 @@ use function is_int;
use function is_resource;
use function str_repeat;
final class MysqliStatement implements IteratorAggregate, Statement
final class MysqliStatement implements Statement
{
/** @var string[] */
private static $paramTypeMap = [
......@@ -89,9 +86,6 @@ final class MysqliStatement implements IteratorAggregate, Statement
*/
private $values = [];
/** @var int */
private $defaultFetchMode = FetchMode::MIXED;
/**
* Indicates whether the statement is in the state when fetching results is possible
*
......@@ -326,20 +320,14 @@ final class MysqliStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null)
public function fetchNumeric()
{
// do not try fetching from the statement if it's not expected to contain result
// 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;
}
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
if ($fetchMode === FetchMode::COLUMN) {
return $this->fetchColumn();
}
$values = $this->_fetch();
if ($values === null) {
......@@ -350,59 +338,56 @@ final class MysqliStatement implements IteratorAggregate, Statement
throw StatementError::new($this->stmt);
}
if ($fetchMode === FetchMode::NUMERIC) {
return $values;
}
$assoc = array_combine($this->columnNames, $values);
assert(is_array($assoc));
/**
* {@inheritDoc}
*/
public function fetchAssociative()
{
$values = $this->fetchNumeric();
switch ($fetchMode) {
case FetchMode::ASSOCIATIVE:
return $assoc;
if ($values === false) {
return false;
}
case FetchMode::MIXED:
return $assoc + $values;
$row = array_combine($this->columnNames, $values);
assert(is_array($row));
default:
throw UnknownFetchMode::new($fetchMode);
}
return $row;
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null) : array
public function fetchOne()
{
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
$rows = [];
if ($fetchMode === FetchMode::COLUMN) {
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
}
} else {
while (($row = $this->fetch($fetchMode)) !== false) {
$rows[] = $row;
}
return FetchUtils::fetchOne($this);
}
return $rows;
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return FetchUtils::fetchAllNumeric($this);
}
/**
* {@inheritdoc}
*/
public function fetchColumn()
public function fetchAllAssociative() : array
{
$row = $this->fetch(FetchMode::NUMERIC);
if ($row === false) {
return false;
return FetchUtils::fetchAllAssociative($this);
}
return $row[0];
/**
* {@inheritdoc}
*/
public function fetchColumn() : array
{
return FetchUtils::fetchColumn($this);
}
public function closeCursor() : void
......@@ -424,17 +409,4 @@ final class MysqliStatement implements IteratorAggregate, Statement
{
return $this->stmt->field_count;
}
public function setFetchMode(int $fetchMode) : void
{
$this->defaultFetchMode = $fetchMode;
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
return new StatementIterator($this);
}
}
......@@ -116,9 +116,7 @@ final class OCI8Connection implements Connection, ServerInfoAwareConnection
throw new OCI8Exception('The driver does not support identity columns.');
}
$sql = 'SELECT ' . $name . '.CURRVAL FROM DUAL';
$stmt = $this->query($sql);
$result = $stmt->fetchColumn();
$result = $this->query('SELECT ' . $name . '.CURRVAL FROM DUAL')->fetchOne();
if ($result === false) {
throw new OCI8Exception('lastInsertId failed: Query was executed but no result was returned.');
......
......@@ -4,12 +4,9 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\OCI8;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use InvalidArgumentException;
use IteratorAggregate;
use function assert;
use function is_int;
use function is_resource;
......@@ -27,11 +24,11 @@ use function sprintf;
use const OCI_ASSOC;
use const OCI_B_BIN;
use const OCI_B_BLOB;
use const OCI_BOTH;
use const OCI_COMMIT_ON_SUCCESS;
use const OCI_D_LOB;
use const OCI_FETCHSTATEMENT_BY_COLUMN;
use const OCI_FETCHSTATEMENT_BY_ROW;
use const OCI_NO_AUTO_COMMIT;
use const OCI_NUM;
use const OCI_RETURN_LOBS;
use const OCI_RETURN_NULLS;
......@@ -41,7 +38,7 @@ use const SQLT_CHR;
/**
* The OCI8 implementation of the Statement interface.
*/
final class OCI8Statement implements IteratorAggregate, Statement
final class OCI8Statement implements Statement
{
/** @var resource */
protected $_dbh;
......@@ -52,17 +49,6 @@ final class OCI8Statement implements IteratorAggregate, Statement
/** @var ExecutionMode */
protected $executionMode;
/** @var int[] */
protected static $fetchModeMap = [
FetchMode::MIXED => OCI_BOTH,
FetchMode::ASSOCIATIVE => OCI_ASSOC,
FetchMode::NUMERIC => OCI_NUM,
FetchMode::COLUMN => OCI_NUM,
];
/** @var int */
protected $_defaultFetchMode = FetchMode::MIXED;
/** @var string[] */
protected $_paramMap = [];
......@@ -190,8 +176,6 @@ final class OCI8Statement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function execute(?array $params = null) : void
{
......@@ -221,71 +205,88 @@ final class OCI8Statement implements IteratorAggregate, Statement
$this->result = true;
}
public function setFetchMode(int $fetchMode) : void
public function rowCount() : int
{
$this->_defaultFetchMode = $fetchMode;
$count = oci_num_rows($this->_sth);
if ($count !== false) {
return $count;
}
return 0;
}
/**
* {@inheritdoc}
*/
public function getIterator()
public function fetchNumeric()
{
return new StatementIterator($this);
return $this->fetch(OCI_NUM);
}
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null)
public function fetchAssociative()
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
if (! $this->result) {
return false;
return $this->fetch(OCI_ASSOC);
}
$fetchMode = $fetchMode ?? $this->_defaultFetchMode;
if ($fetchMode === FetchMode::COLUMN) {
return $this->fetchColumn();
/**
* {@inheritdoc}
*/
public function fetchOne()
{
return FetchUtils::fetchOne($this);
}
if (! isset(self::$fetchModeMap[$fetchMode])) {
throw new InvalidArgumentException(sprintf('Invalid fetch mode %d.', $fetchMode));
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return $this->fetchAll(OCI_NUM, OCI_FETCHSTATEMENT_BY_ROW);
}
return oci_fetch_array(
$this->_sth,
self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | OCI_RETURN_LOBS
);
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
return $this->fetchAll(OCI_ASSOC, OCI_FETCHSTATEMENT_BY_ROW);
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null) : array
public function fetchColumn() : array
{
$fetchMode = $fetchMode ?? $this->_defaultFetchMode;
$result = [];
if (! isset(self::$fetchModeMap[$fetchMode])) {
throw new InvalidArgumentException(sprintf('Invalid fetch mode %d.', $fetchMode));
return $this->fetchAll(OCI_NUM, OCI_FETCHSTATEMENT_BY_COLUMN)[0];
}
if (self::$fetchModeMap[$fetchMode] === OCI_BOTH) {
while ($row = $this->fetch($fetchMode)) {
$result[] = $row;
/**
* @return mixed|false
*/
private function fetch(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;
}
} else {
$fetchStructure = OCI_FETCHSTATEMENT_BY_ROW;
if ($fetchMode === FetchMode::COLUMN) {
$fetchStructure = OCI_FETCHSTATEMENT_BY_COLUMN;
return oci_fetch_array(
$this->_sth,
$mode | OCI_RETURN_NULLS | OCI_RETURN_LOBS
);
}
// do not try fetching from the statement if it's not expected to contain result
/**
* @return array<mixed>
*/
private function fetchAll(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 [];
......@@ -296,45 +297,9 @@ final class OCI8Statement implements IteratorAggregate, Statement
$result,
0,
-1,
self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS
$mode | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS
);
if ($fetchMode === FetchMode::COLUMN) {
$result = $result[0];
}
}
return $result;
}
/**
* {@inheritdoc}
*/
public function fetchColumn()
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
if (! $this->result) {
return false;
}
$row = oci_fetch_array($this->_sth, OCI_NUM | OCI_RETURN_NULLS | OCI_RETURN_LOBS);
if ($row === false) {
return false;
}
return $row[0];
}
public function rowCount() : int
{
$count = oci_num_rows($this->_sth);
if ($count !== false) {
return $count;
}
return 0;
}
}
......@@ -23,7 +23,7 @@ class Connection extends PDOConnection
$stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?');
$stmt->execute([$name]);
return $stmt->fetchColumn();
return $stmt->fetchOne();
}
public function quote(string $input) : string
......
......@@ -4,11 +4,8 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Exception\UnknownFetchMode;
use Doctrine\DBAL\Driver\Exception\UnknownParamType;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use PDO;
use function array_slice;
use function assert;
......@@ -20,7 +17,7 @@ use function is_array;
* The PDO implementation of the Statement interface.
* Used by all PDO-based drivers.
*/
class PDOStatement implements IteratorAggregate, Statement
class PDOStatement implements Statement
{
private const PARAM_TYPE_MAP = [
ParameterType::NULL => PDO::PARAM_NULL,
......@@ -31,13 +28,6 @@ class PDOStatement implements IteratorAggregate, Statement
ParameterType::BOOLEAN => PDO::PARAM_BOOL,
];
private const FETCH_MODE_MAP = [
FetchMode::ASSOCIATIVE => PDO::FETCH_ASSOC,
FetchMode::NUMERIC => PDO::FETCH_NUM,
FetchMode::MIXED => PDO::FETCH_BOTH,
FetchMode::COLUMN => PDO::FETCH_COLUMN,
];
/** @var \PDOStatement */
private $stmt;
......@@ -46,17 +36,6 @@ class PDOStatement implements IteratorAggregate, Statement
$this->stmt = $stmt;
}
public function setFetchMode(int $fetchMode) : void
{
$fetchMode = $this->convertFetchMode($fetchMode);
try {
$this->stmt->setFetchMode($fetchMode);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
}
/**
* {@inheritdoc}
*/
......@@ -122,88 +101,94 @@ class PDOStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null)
public function fetchNumeric()
{
try {
if ($fetchMode === null) {
return $this->stmt->fetch();
return $this->fetch(PDO::FETCH_NUM);
}
return $this->stmt->fetch(
$this->convertFetchMode($fetchMode)
);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
/**
* {@inheritdoc}
*/
public function fetchAssociative()
{
return $this->fetch(PDO::FETCH_ASSOC);
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null) : array
public function fetchOne()
{
try {
if ($fetchMode === null) {
$data = $this->stmt->fetchAll();
} else {
$data = $this->stmt->fetchAll(
$this->convertFetchMode($fetchMode)
);
}
} catch (\PDOException $exception) {
throw new PDOException($exception);
return $this->fetch(PDO::FETCH_COLUMN);
}
assert(is_array($data));
return $data;
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return $this->fetchAll(PDO::FETCH_NUM);
}
/**
* {@inheritdoc}
*/
public function fetchColumn()
public function fetchAllAssociative() : array
{
try {
return $this->stmt->fetchColumn();
} catch (\PDOException $exception) {
throw new PDOException($exception);
return $this->fetchAll(PDO::FETCH_ASSOC);
}
/**
* {@inheritdoc}
*/
public function fetchColumn() : array
{
return $this->fetchAll(PDO::FETCH_COLUMN);
}
/**
* Converts DBAL parameter type to PDO parameter type
* @return mixed|false
*
* @param int $type Parameter type
* @throws PDOException
*/
private function convertParamType(int $type) : int
private function fetch(int $mode)
{
if (! isset(self::PARAM_TYPE_MAP[$type])) {
throw UnknownParamType::new($type);
try {
return $this->stmt->fetch($mode);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
return self::PARAM_TYPE_MAP[$type];
}
/**
* Converts DBAL fetch mode to PDO fetch mode
* @return array<int,mixed>
*
* @param int $fetchMode Fetch mode
* @throws PDOException
*/
private function convertFetchMode(int $fetchMode) : int
private function fetchAll(int $mode) : array
{
if (! isset(self::FETCH_MODE_MAP[$fetchMode])) {
throw UnknownFetchMode::new($fetchMode);
try {
$data = $this->stmt->fetchAll($mode);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
return self::FETCH_MODE_MAP[$fetchMode];
assert(is_array($data));
return $data;
}
/**
* {@inheritdoc}
* Converts DBAL parameter type to PDO parameter type
*
* @param int $type Parameter type
*/
public function getIterator()
private function convertParamType(int $type) : int
{
yield from $this->stmt;
if (! isset(self::PARAM_TYPE_MAP[$type])) {
throw UnknownParamType::new($type);
}
return self::PARAM_TYPE_MAP[$type];
}
}
......@@ -4,12 +4,10 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver;
use Traversable;
/**
* Interface for the reading part of a prepare statement only.
*/
interface ResultStatement extends Traversable
interface ResultStatement
{
/**
* Closes the cursor, enabling the statement to be executed again.
......@@ -37,40 +35,56 @@ interface ResultStatement extends Traversable
public function rowCount() : int;
/**
* Sets the fetch mode to use while iterating this statement.
* 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
*
* @param int $fetchMode Controls how the next row will be returned to the caller.
* The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants.
* @throws DriverException
*/
public function setFetchMode(int $fetchMode) : void;
public function fetchAssociative();
/**
* Returns the next row of a result set.
* Returns the first value of the next row of a result set or FALSE if there are no more rows.
*
* @param int|null $fetchMode Controls how the next row will be returned to the caller.
* The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants,
* defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}.
* @return mixed|false
*
* @return mixed The return value of this method on success depends on the fetch mode. In all cases, FALSE is
* returned on failure.
* @throws DriverException
*/
public function fetch(?int $fetchMode = null);
public function fetchOne();
/**
* Returns an array containing all of the result set rows.
* Returns an array containing all of the result set rows represented as numeric arrays.
*
* @param int|null $fetchMode Controls how the next row will be returned to the caller.
* The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants,
* defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}.
* @return array<int,array<int,mixed>>
*
* @return mixed[]
* @throws DriverException
*/
public function fetchAll(?int $fetchMode = null) : array;
public function fetchAllNumeric() : array;
/**
* Returns a single column from the next row of a result set or FALSE if there are no more rows.
* 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;
/**
* Returns an array containing the values of the first column of the result set.
*
* @return array<int,mixed>
*
* @return mixed|false A single column in the next row of a result set, or FALSE if there are no more rows.
* @throws DriverException
*/
public function fetchColumn();
public function fetchColumn() : array;
}
......@@ -92,8 +92,7 @@ final class SQLAnywhereConnection implements ServerInfoAwareConnection
public function getServerVersion() : string
{
$version = $this->query("SELECT PROPERTY('ProductVersion')")->fetchColumn();
$version = $this->query("SELECT PROPERTY('ProductVersion')")->fetchOne();
assert(is_string($version));
return $version;
......@@ -105,7 +104,7 @@ final class SQLAnywhereConnection implements ServerInfoAwareConnection
return sasql_insert_id($this->connection);
}
return $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn();
return $this->query('SELECT ' . $name . '.CURRVAL')->fetchOne();
}
public function prepare(string $sql) : DriverStatement
......
......@@ -4,17 +4,15 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Exception\GetVariableType;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use function array_key_exists;
use function assert;
use function is_int;
use function is_resource;
use function sasql_fetch_array;
use function sasql_fetch_assoc;
use function sasql_fetch_row;
use function sasql_prepare;
......@@ -25,19 +23,15 @@ use function sasql_stmt_field_count;
use function sasql_stmt_reset;
use function sasql_stmt_result_metadata;
use function sprintf;
use const SASQL_BOTH;
/**
* SAP SQL Anywhere implementation of the Statement interface.
*/
final class SQLAnywhereStatement implements IteratorAggregate, Statement
final class SQLAnywhereStatement implements Statement
{
/** @var resource The connection resource. */
private $conn;
/** @var int Default fetch mode to use. */
private $defaultFetchMode = FetchMode::MIXED;
/** @var resource|null The result set resource to fetch. */
private $result;
......@@ -157,85 +151,69 @@ final class SQLAnywhereStatement implements IteratorAggregate, Statement
*
* @throws SQLAnywhereException
*/
public function fetch(?int $fetchMode = null)
public function fetchNumeric()
{
if (! is_resource($this->result)) {
return false;
}
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
switch ($fetchMode) {
case FetchMode::COLUMN:
return $this->fetchColumn();
case FetchMode::ASSOCIATIVE:
return sasql_fetch_assoc($this->result);
case FetchMode::MIXED:
return sasql_fetch_array($this->result, SASQL_BOTH);
case FetchMode::NUMERIC:
return sasql_fetch_row($this->result);
default:
throw new SQLAnywhereException(sprintf('Fetch mode is not supported %d.', $fetchMode));
}
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null) : array
public function fetchAssociative()
{
$rows = [];
switch ($fetchMode) {
case FetchMode::COLUMN:
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
}
break;
default:
while (($row = $this->fetch($fetchMode)) !== false) {
$rows[] = $row;
}
if (! is_resource($this->result)) {
return false;
}
return $rows;
return sasql_fetch_assoc($this->result);
}
/**
* {@inheritdoc}
*
* @throws DriverException
*/
public function fetchColumn()
public function fetchOne()
{
$row = $this->fetch(FetchMode::NUMERIC);
if ($row === false) {
return false;
return FetchUtils::fetchOne($this);
}
return $row[0];
/**
* @return array<int,array<int,mixed>>
*
* @throws DriverException
*/
public function fetchAllNumeric() : array
{
return FetchUtils::fetchAllNumeric($this);
}
/**
* {@inheritdoc}
* @return array<int,array<string,mixed>>
*
* @throws DriverException
*/
public function getIterator()
public function fetchAllAssociative() : array
{
return new StatementIterator($this);
return FetchUtils::fetchAllAssociative($this);
}
public function rowCount() : int
/**
* @return array<int,mixed>
*
* @throws DriverException
*/
public function fetchColumn() : array
{
return sasql_stmt_affected_rows($this->stmt);
return FetchUtils::fetchColumn($this);
}
public function setFetchMode(int $fetchMode) : void
public function rowCount() : int
{
$this->defaultFetchMode = $fetchMode;
return sasql_stmt_affected_rows($this->stmt);
}
}
......@@ -100,7 +100,7 @@ final class SQLSrvConnection implements ServerInfoAwareConnection
$stmt = $this->query('SELECT @@IDENTITY');
}
return $stmt->fetchColumn();
return $stmt->fetchOne();
}
public function beginTransaction() : void
......
......@@ -4,11 +4,9 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use function assert;
use function is_int;
use function sqlsrv_execute;
......@@ -25,14 +23,13 @@ use function SQLSRV_SQLTYPE_VARBINARY;
use function stripos;
use const SQLSRV_ENC_BINARY;
use const SQLSRV_FETCH_ASSOC;
use const SQLSRV_FETCH_BOTH;
use const SQLSRV_FETCH_NUMERIC;
use const SQLSRV_PARAM_IN;
/**
* SQL Server Statement.
*/
final class SQLSrvStatement implements IteratorAggregate, Statement
final class SQLSrvStatement implements Statement
{
/**
* The SQLSRV Resource.
......@@ -69,24 +66,6 @@ final class SQLSrvStatement implements IteratorAggregate, Statement
*/
private $types = [];
/**
* Translations.
*
* @var int[]
*/
private static $fetchMap = [
FetchMode::MIXED => SQLSRV_FETCH_BOTH,
FetchMode::ASSOCIATIVE => SQLSRV_FETCH_ASSOC,
FetchMode::NUMERIC => SQLSRV_FETCH_NUMERIC,
];
/**
* The fetch style.
*
* @var int
*/
private $defaultFetchMode = FetchMode::MIXED;
/**
* The last insert ID.
*
......@@ -181,8 +160,6 @@ final class SQLSrvStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function execute(?array $params = null) : void
{
......@@ -213,81 +190,52 @@ final class SQLSrvStatement implements IteratorAggregate, Statement
$this->result = true;
}
public function setFetchMode(int $fetchMode) : void
/**
* {@inheritdoc}
*/
public function fetchNumeric()
{
$this->defaultFetchMode = $fetchMode;
return $this->fetch(SQLSRV_FETCH_NUMERIC);
}
/**
* {@inheritdoc}
*/
public function getIterator()
public function fetchAssociative()
{
return new StatementIterator($this);
return $this->fetch(SQLSRV_FETCH_ASSOC);
}
/**
* {@inheritdoc}
*
* @throws SQLSrvException
*/
public function fetch(?int $fetchMode = null)
public function fetchOne()
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
if ($this->stmt === null || ! $this->result) {
return false;
}
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
if ($fetchMode === FetchMode::COLUMN) {
return $this->fetchColumn();
}
if (isset(self::$fetchMap[$fetchMode])) {
return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]) ?? false;
}
throw new SQLSrvException('Fetch mode is not supported.');
return FetchUtils::fetchOne($this);
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null) : array
public function fetchAllNumeric() : array
{
$rows = [];
switch ($fetchMode) {
case FetchMode::COLUMN:
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
}
break;
default:
while (($row = $this->fetch($fetchMode)) !== false) {
$rows[] = $row;
}
}
return $rows;
return FetchUtils::fetchAllNumeric($this);
}
/**
* {@inheritdoc}
*/
public function fetchColumn()
public function fetchAllAssociative() : array
{
$row = $this->fetch(FetchMode::NUMERIC);
if ($row === false) {
return false;
return FetchUtils::fetchAllAssociative($this);
}
return $row[0];
/**
* {@inheritdoc}
*/
public function fetchColumn() : array
{
return FetchUtils::fetchColumn($this);
}
public function rowCount() : int
......@@ -349,4 +297,18 @@ final class SQLSrvStatement implements IteratorAggregate, Statement
return $stmt;
}
/**
* @return mixed|false
*/
private function fetch(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;
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Driver;
use IteratorAggregate;
final class StatementIterator implements IteratorAggregate
{
/** @var ResultStatement */
private $statement;
public function __construct(ResultStatement $statement)
{
$this->statement = $statement;
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
while (($result = $this->statement->fetch()) !== false) {
yield $result;
}
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL;
/**
* Contains statement fetch modes.
*/
final class FetchMode
{
/**
* Specifies that the fetch method shall return each row as an array indexed
* by column name as returned in the corresponding result set. If the result
* set contains multiple columns with the same name, the statement returns
* only a single value per column name.
*
* @see \PDO::FETCH_ASSOC
*/
public const ASSOCIATIVE = 2;
/**
* Specifies that the fetch method shall return each row as an array indexed
* by column number as returned in the corresponding result set, starting at
* column 0.
*
* @see \PDO::FETCH_NUM
*/
public const NUMERIC = 3;
/**
* Specifies that the fetch method shall return each row as an array indexed
* by both column name and number as returned in the corresponding result set,
* starting at column 0.
*
* @see \PDO::FETCH_BOTH
*/
public const MIXED = 4;
/**
* Specifies that the fetch method shall return only a single requested
* column from the next row in the result set.
*
* @see \PDO::FETCH_COLUMN
*/
public const COLUMN = 7;
/**
* This class cannot be instantiated.
*/
private function __construct()
{
}
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\ForwardCompatibility\Driver;
use Doctrine\DBAL\Driver\ResultStatement as BaseResultStatement;
/**
* Forward compatibility extension for the ResultStatement interface.
*
* @deprecated
*/
interface ResultStatement extends BaseResultStatement
{
}
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\ForwardCompatibility;
use Doctrine\DBAL\ForwardCompatibility\Driver\ResultStatement as BaseResultStatement;
/**
* Forward compatibility extension for the DBAL ResultStatement interface.
*
* @deprecated
*/
interface ResultStatement extends BaseResultStatement
{
}
......@@ -7,7 +7,6 @@ namespace Doctrine\DBAL\Id;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\LockMode;
use Throwable;
use function array_change_key_case;
......@@ -102,8 +101,7 @@ class TableGenerator
$sql = 'SELECT sequence_value, sequence_increment_by'
. ' FROM ' . $platform->appendLockHint($this->generatorTableName, LockMode::PESSIMISTIC_WRITE)
. ' WHERE sequence_name = ? ' . $platform->getWriteLockSQL();
$stmt = $this->conn->executeQuery($sql, [$sequenceName]);
$row = $stmt->fetch(FetchMode::ASSOCIATIVE);
$row = $this->conn->fetchAssociative($sql, [$sequenceName]);
if ($row !== false) {
$row = array_change_key_case($row, CASE_LOWER);
......
......@@ -99,28 +99,20 @@ class Connection extends \Doctrine\DBAL\Connection
array $types = [],
?QueryCacheProfile $qcp = null
) : ResultStatement {
$stmt = new Statement(parent::executeQuery($query, $params, $types, $qcp), $this);
$stmt->setFetchMode($this->defaultFetchMode);
return $stmt;
return new Statement(parent::executeQuery($query, $params, $types, $qcp), $this);
}
public function prepare(string $sql) : DriverStatement
{
$stmt = new Statement(parent::prepare($sql), $this);
$stmt->setFetchMode($this->defaultFetchMode);
return $stmt;
return new Statement(parent::prepare($sql), $this);
}
public function query(string $sql) : ResultStatement
{
$connection = $this->getWrappedConnection();
$stmt = $connection->query($sql);
$stmt = new Statement($stmt, $this);
$stmt->setFetchMode($this->defaultFetchMode);
return $stmt;
return new Statement(
$this->getWrappedConnection()
->query($sql),
$this
);
}
}
......@@ -6,10 +6,7 @@ namespace Doctrine\DBAL\Portability;
use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use function array_change_key_case;
use function assert;
use function is_string;
......@@ -18,7 +15,7 @@ use function rtrim;
/**
* Portability wrapper for a Statement.
*/
final class Statement implements IteratorAggregate, DriverStatement
final class Statement implements DriverStatement
{
/** @var int */
private $portability;
......@@ -29,9 +26,6 @@ final class Statement implements IteratorAggregate, DriverStatement
/** @var int|null */
private $case;
/** @var int */
private $defaultFetchMode = FetchMode::MIXED;
/**
* Wraps <tt>Statement</tt> and applies portability measures.
*
......@@ -76,8 +70,6 @@ final class Statement implements IteratorAggregate, DriverStatement
/**
* {@inheritdoc}
*
* @deprecated The error information is available via exceptions.
*/
public function execute(?array $params = null) : void
{
......@@ -86,91 +78,124 @@ final class Statement implements IteratorAggregate, DriverStatement
$this->stmt->execute($params);
}
public function setFetchMode(int $fetchMode) : void
/**
* {@inheritdoc}
*/
public function fetchNumeric()
{
$this->defaultFetchMode = $fetchMode;
$this->stmt->setFetchMode($fetchMode);
return $this->fixResult(
$this->stmt->fetchAssociative(),
false
);
}
/**
* {@inheritdoc}
*/
public function getIterator()
public function fetchAssociative()
{
return new StatementIterator($this);
return $this->fixResult(
$this->stmt->fetchAssociative(),
true
);
}
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null)
public function fetchOne()
{
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
$value = $this->stmt->fetchOne();
$row = $this->stmt->fetch($fetchMode);
$iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
$fixCase = $this->case !== null
&& ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED)
&& ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0;
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);
}
$row = $this->fixRow($row, $iterateRow, $fixCase);
return $value;
}
return $row;
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return $this->fixResultSet(
$this->stmt->fetchAllNumeric(),
false,
true
);
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null) : array
public function fetchAllAssociative() : array
{
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
return $this->fixResultSet(
$this->stmt->fetchAllAssociative(),
true,
true
);
}
$rows = $this->stmt->fetchAll($fetchMode);
/**
* {@inheritdoc}
*/
public function fetchColumn() : array
{
return $this->fixResultSet(
$this->stmt->fetchColumn(),
true,
false
);
}
/**
* @param mixed $result
*
* @return mixed
*/
private function fixResult($result, bool $fixCase)
{
$iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
$fixCase = $this->case !== null
&& ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED)
&& ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0;
$fixCase = $fixCase && $this->case !== null && ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0;
if (! $iterateRow && ! $fixCase) {
return $rows;
return $this->fixRow($result, $iterateRow, $fixCase);
}
if ($fetchMode === FetchMode::COLUMN) {
foreach ($rows as $num => $row) {
$rows[$num] = [$row];
}
}
/**
* @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;
foreach ($rows as $num => $row) {
$rows[$num] = $this->fixRow($row, $iterateRow, $fixCase);
if (! $iterateRow && ! $fixCase) {
return $resultSet;
}
if ($fetchMode === FetchMode::COLUMN) {
foreach ($rows as $num => $row) {
$rows[$num] = $row[0];
if (! $isArray) {
foreach ($resultSet as $num => $value) {
$resultSet[$num] = [$value];
}
}
return $rows;
foreach ($resultSet as $num => $row) {
$resultSet[$num] = $this->fixRow($row, $iterateRow, $fixCase);
}
/**
* {@inheritdoc}
*/
public function fetchColumn()
{
$value = $this->stmt->fetchColumn();
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);
if (! $isArray) {
foreach ($resultSet as $num => $row) {
$resultSet[$num] = $row[0];
}
}
return $value;
return $resultSet;
}
public function rowCount() : int
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL;
use Doctrine\DBAL\Driver\ResultStatement as DriverResultStatement;
use Traversable;
/**
* DBAL-level ResultStatement interface.
*/
interface ResultStatement extends DriverResultStatement
{
/**
* 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;
}
......@@ -93,7 +93,7 @@ abstract class AbstractSchemaManager
{
$sql = $this->_platform->getListDatabasesSQL();
$databases = $this->_conn->fetchAll($sql);
$databases = $this->_conn->fetchAllAssociative($sql);
return $this->_getPortableDatabasesList($databases);
}
......@@ -107,7 +107,7 @@ abstract class AbstractSchemaManager
{
$sql = $this->_platform->getListNamespacesSQL();
$namespaces = $this->_conn->fetchAll($sql);
$namespaces = $this->_conn->fetchAllAssociative($sql);
return $this->getPortableNamespacesList($namespaces);
}
......@@ -126,7 +126,7 @@ abstract class AbstractSchemaManager
$sql = $this->_platform->getListSequencesSQL($database);
$sequences = $this->_conn->fetchAll($sql);
$sequences = $this->_conn->fetchAllAssociative($sql);
return $this->filterAssetNames($this->_getPortableSequencesList($sequences));
}
......@@ -152,7 +152,7 @@ abstract class AbstractSchemaManager
$sql = $this->_platform->getListTableColumnsSQL($table, $database);
$tableColumns = $this->_conn->fetchAll($sql);
$tableColumns = $this->_conn->fetchAllAssociative($sql);
return $this->_getPortableTableColumnList($table, $database, $tableColumns);
}
......@@ -168,7 +168,7 @@ abstract class AbstractSchemaManager
{
$sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
$tableIndexes = $this->_conn->fetchAll($sql);
$tableIndexes = $this->_conn->fetchAllAssociative($sql);
return $this->_getPortableTableIndexesList($tableIndexes, $table);
}
......@@ -199,7 +199,7 @@ abstract class AbstractSchemaManager
{
$sql = $this->_platform->getListTablesSQL();
$tables = $this->_conn->fetchAll($sql);
$tables = $this->_conn->fetchAllAssociative($sql);
$tableNames = $this->_getPortableTablesList($tables);
return $this->filterAssetNames($tableNames);
......@@ -267,7 +267,7 @@ abstract class AbstractSchemaManager
);
$sql = $this->_platform->getListViewsSQL($database);
$views = $this->_conn->fetchAll($sql);
$views = $this->_conn->fetchAllAssociative($sql);
return $this->_getPortableViewsList($views);
}
......@@ -284,7 +284,7 @@ abstract class AbstractSchemaManager
}
$sql = $this->_platform->getListTableForeignKeysSQL($table, $database);
$tableForeignKeys = $this->_conn->fetchAll($sql);
$tableForeignKeys = $this->_conn->fetchAllAssociative($sql);
return $this->_getPortableTableForeignKeysList($tableForeignKeys);
}
......@@ -553,7 +553,7 @@ abstract class AbstractSchemaManager
/**
* Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition.
*
* @param array<int, array<int, mixed>> $namespaces The list of namespace names in the native DBMS data definition.
* @param array<int, array<string, mixed>> $namespaces The list of namespace names in the native DBMS data definition.
*
* @return array<int, string>
*/
......@@ -581,7 +581,7 @@ abstract class AbstractSchemaManager
/**
* Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition.
*
* @param array<string|int, mixed> $namespace The native DBMS namespace definition.
* @param array<string, mixed> $namespace The native DBMS namespace definition.
*/
protected function getPortableNamespaceDefinition(array $namespace) : string
{
......
......@@ -30,7 +30,7 @@ class DB2SchemaManager extends AbstractSchemaManager
{
$sql = $this->_platform->getListTablesSQL() . ' AND CREATOR = CURRENT_USER';
$tables = $this->_conn->fetchAll($sql);
$tables = $this->_conn->fetchAllAssociative($sql);
return $this->filterAssetNames($this->_getPortableTablesList($tables));
}
......@@ -198,7 +198,7 @@ class DB2SchemaManager extends AbstractSchemaManager
assert($platform instanceof DB2Platform);
$sql = $platform->getListTableCommentsSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
$tableOptions = $this->_conn->fetchAssociative($sql);
if ($tableOptions !== false) {
$table->addOption('comment', $tableOptions['REMARKS']);
......
......@@ -311,7 +311,7 @@ class MySqlSchemaManager extends AbstractSchemaManager
assert($platform instanceof MySqlPlatform);
$sql = $platform->getListTableMetadataSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
$tableOptions = $this->_conn->fetchAssociative($sql);
if ($tableOptions === false) {
return $table;
......
......@@ -344,7 +344,7 @@ WHERE
AND p.addr(+) = s.paddr
SQL;
$activeUserSessions = $this->_conn->fetchAll($sql, [strtoupper($user)]);
$activeUserSessions = $this->_conn->fetchAllAssociative($sql, [strtoupper($user)]);
foreach ($activeUserSessions as $activeUserSession) {
$activeUserSession = array_change_key_case($activeUserSession, CASE_LOWER);
......@@ -367,7 +367,7 @@ SQL;
assert($platform instanceof OraclePlatform);
$sql = $platform->getListTableCommentsSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
$tableOptions = $this->_conn->fetchAssociative($sql);
if ($tableOptions !== false) {
$table->addOption('comment', $tableOptions['COMMENTS']);
......
......@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Exception\DriverException;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
......@@ -42,9 +41,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
*/
public function getSchemaNames() : array
{
$statement = $this->_conn->executeQuery("SELECT nspname FROM pg_namespace WHERE nspname !~ '^pg_.*' AND nspname != 'information_schema'");
return $statement->fetchAll(FetchMode::COLUMN);
return $this->_conn->fetchColumn("SELECT nspname FROM pg_namespace WHERE nspname !~ '^pg_.*' AND nspname != 'information_schema'");
}
/**
......@@ -57,7 +54,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
public function getSchemaSearchPaths() : array
{
$params = $this->_conn->getParams();
$schema = explode(',', $this->_conn->fetchColumn('SHOW search_path'));
$schema = explode(',', $this->_conn->fetchOne('SHOW search_path'));
if (isset($params['user'])) {
$schema = str_replace('"$user"', $params['user'], $schema);
......@@ -221,8 +218,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
implode(' ,', $colNumbers)
);
$stmt = $this->_conn->executeQuery($columnNameSql);
$indexColumns = $stmt->fetchAll();
$indexColumns = $this->_conn->fetchAllAssociative($columnNameSql);
// required for getting the order of the columns right.
foreach ($colNumbers as $colNum) {
......@@ -300,7 +296,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
if (! isset($sequence['increment_by'], $sequence['min_value'])) {
/** @var string[] $data */
$data = $this->_conn->fetchAssoc('SELECT min_value, increment_by FROM ' . $this->_platform->quoteIdentifier($sequenceName));
$data = $this->_conn->fetchAssociative('SELECT min_value, increment_by FROM ' . $this->_platform->quoteIdentifier($sequenceName));
$sequence += $data;
}
......@@ -518,7 +514,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
assert($platform instanceof PostgreSQL94Platform);
$sql = $platform->getListTableMetadataSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
$tableOptions = $this->_conn->fetchAssociative($sql);
if ($tableOptions !== false) {
$table->addOption('comment', $tableOptions['table_comment']);
......
......@@ -261,7 +261,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager
$sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
try {
$tableIndexes = $this->_conn->fetchAll($sql);
$tableIndexes = $this->_conn->fetchAllAssociative($sql);
} catch (PDOException $e) {
if ($e->getCode() === 'IMSSP') {
return [];
......@@ -284,7 +284,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager
if (count($tableDiff->removedColumns) > 0) {
foreach ($tableDiff->removedColumns as $col) {
$columnConstraintSql = $this->getColumnConstraintSQL($tableDiff->name, $col->getName());
foreach ($this->_conn->fetchAll($columnConstraintSql) as $constraint) {
foreach ($this->_conn->fetchAllAssociative($columnConstraintSql) as $constraint) {
$this->_conn->exec(
sprintf(
'ALTER TABLE %s DROP CONSTRAINT %s',
......@@ -338,7 +338,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager
assert($platform instanceof SQLServer2012Platform);
$sql = $platform->getListTableMetadataSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
$tableOptions = $this->_conn->fetchAssociative($sql);
if ($tableOptions !== false) {
$table->addOption('comment', $tableOptions['table_comment']);
......
......@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Types\StringType;
use Doctrine\DBAL\Types\TextType;
use Doctrine\DBAL\Types\Type;
......@@ -121,7 +120,7 @@ class SqliteSchemaManager extends AbstractSchemaManager
}
$sql = $this->_platform->getListTableForeignKeysSQL($table, $database);
$tableForeignKeys = $this->_conn->fetchAll($sql);
$tableForeignKeys = $this->_conn->fetchAllAssociative($sql);
if (! empty($tableForeignKeys)) {
$createSql = $this->getCreateTableSQL($table);
......@@ -175,11 +174,10 @@ class SqliteSchemaManager extends AbstractSchemaManager
$indexBuffer = [];
// fetch primary
$stmt = $this->_conn->executeQuery(sprintf(
$indexArray = $this->_conn->fetchAllAssociative(sprintf(
'PRAGMA TABLE_INFO (%s)',
$this->_conn->quote($tableName)
));
$indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE);
usort($indexArray, static function ($a, $b) {
if ($a['pk'] === $b['pk']) {
......@@ -214,11 +212,10 @@ class SqliteSchemaManager extends AbstractSchemaManager
$idx['primary'] = false;
$idx['non_unique'] = ! $tableIndex['unique'];
$stmt = $this->_conn->executeQuery(sprintf(
$indexArray = $this->_conn->fetchAllAssociative(sprintf(
'PRAGMA INDEX_INFO (%s)',
$this->_conn->quote($keyName)
));
$indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE);
foreach ($indexArray as $indexColumnRow) {
$idx['column_name'] = $indexColumnRow['name'];
......@@ -481,7 +478,7 @@ CREATE\sTABLE # Match "CREATE TABLE"
private function getCreateTableSQL(string $table) : string
{
$sql = $this->_conn->fetchColumn(
$sql = $this->_conn->fetchOne(
<<<'SQL'
SELECT sql
FROM (
......
......@@ -8,15 +8,15 @@ use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;
use IteratorAggregate;
use Throwable;
use Traversable;
use function is_string;
/**
* A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support
* for logging, DBAL mapping types, etc.
*/
class Statement implements IteratorAggregate, DriverStatement
class Statement implements DriverStatement, ResultStatement
{
/**
* The SQL statement.
......@@ -180,43 +180,140 @@ class Statement implements IteratorAggregate, DriverStatement
return $this->stmt->columnCount();
}
public function setFetchMode(int $fetchMode) : void
/**
* {@inheritdoc}
*
* @throws DBALException
*/
public function fetchNumeric()
{
$this->stmt->setFetchMode($fetchMode);
try {
return $this->stmt->fetchNumeric();
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* Required by interface IteratorAggregate.
* {@inheritdoc}
*
* @throws DBALException
*/
public function fetchAssociative()
{
try {
return $this->stmt->fetchAssociative();
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritdoc}
*/
public function getIterator()
public function fetchOne()
{
return $this->stmt;
try {
return $this->stmt->fetchOne();
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritdoc}
*
* @throws DBALException
*/
public function fetch(?int $fetchMode = null)
public function fetchAllNumeric() : array
{
return $this->stmt->fetch($fetchMode);
try {
return $this->stmt->fetchAllNumeric();
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritdoc}
*
* @throws DBALException
*/
public function fetchAll(?int $fetchMode = null) : array
public function fetchAllAssociative() : array
{
return $this->stmt->fetchAll($fetchMode);
try {
return $this->stmt->fetchAllAssociative();
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritDoc}
* {@inheritdoc}
*
* @throws DBALException
*/
public function fetchColumn()
public function fetchColumn() : array
{
try {
return $this->stmt->fetchColumn();
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritDoc}
*
* @return Traversable<int,array<int,mixed>>
*
* @throws DBALException
*/
public function iterateNumeric() : Traversable
{
try {
while (($row = $this->stmt->fetchNumeric()) !== 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 {
while (($row = $this->stmt->fetchAssociative()) !== 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 {
while (($value = $this->stmt->fetchOne()) !== false) {
yield $value;
}
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
......
......@@ -88,7 +88,7 @@ EOT
assert(is_bool($forceFetch));
if (stripos($sql, 'select') === 0 || $forceFetch) {
$resultSet = $conn->fetchAll($sql);
$resultSet = $conn->fetchAllAssociative($sql);
} else {
$resultSet = $conn->executeUpdate($sql);
}
......
......@@ -5,11 +5,8 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Tests\Cache;
use Doctrine\DBAL\Cache\ArrayStatement;
use Doctrine\DBAL\FetchMode;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use function array_values;
use function iterator_to_array;
class ArrayStatementTest extends TestCase
{
......@@ -50,79 +47,33 @@ class ArrayStatementTest extends TestCase
self::assertSame(2, $statement->rowCount());
}
public function testSetFetchMode() : void
public function testFetchAssociative() : void
{
$statement = $this->createTestArrayStatement();
$statement->setFetchMode(FetchMode::ASSOCIATIVE);
self::assertSame($this->users[0], $statement->fetch());
}
public function testGetIterator() : void
{
$statement = $this->createTestArrayStatement();
$statement->setFetchMode(FetchMode::ASSOCIATIVE);
self::assertSame($this->users, iterator_to_array($statement->getIterator()));
self::assertSame($this->users[0], $statement->fetchAssociative());
}
public function testFetchModeAssociative() : void
public function testFetchNumeric() : void
{
$statement = $this->createTestArrayStatement();
self::assertSame($this->users[0], $statement->fetch(FetchMode::ASSOCIATIVE));
self::assertSame(array_values($this->users[0]), $statement->fetchNumeric());
}
public function testFetchModeNumeric() : void
public function testFetchOne() : void
{
$statement = $this->createTestArrayStatement();
self::assertSame(array_values($this->users[0]), $statement->fetch(FetchMode::NUMERIC));
}
public function testFetchModeMixed() : void
{
$statement = $this->createTestArrayStatement();
self::assertSame([
'username' => 'jwage',
'active' => true,
0 => 'jwage',
1 => true,
], $statement->fetch(FetchMode::MIXED));
}
public function testFetchModeColumn() : void
{
$statement = $this->createTestArrayStatement();
self::assertSame('jwage', $statement->fetch(FetchMode::COLUMN));
}
public function testFetchThrowsInvalidArgumentException() : void
{
$statement = $this->createTestArrayStatement();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid fetch mode given for fetching result, 9999 given.');
$statement->fetch(9999);
self::assertSame('jwage', $statement->fetchOne());
self::assertSame('romanb', $statement->fetchOne());
}
public function testFetchAll() : void
{
$statement = $this->createTestArrayStatement();
self::assertSame($this->users, $statement->fetchAll(FetchMode::ASSOCIATIVE));
}
public function testFetchColumn() : void
{
$statement = $this->createTestArrayStatement();
self::assertSame('jwage', $statement->fetchColumn());
self::assertSame('romanb', $statement->fetchColumn());
self::assertSame($this->users, $statement->fetchAllAssociative());
}
private function createTestArrayStatement() : ArrayStatement
......
......@@ -19,7 +19,6 @@ use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Events;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Logging\DebugStack;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\AbstractPlatform;
......@@ -494,7 +493,7 @@ class ConnectionTest extends TestCase
);
}
public function testFetchAssoc() : void
public function testFetchAssociative() : void
{
$statement = 'SELECT * FROM foo WHERE bar = ?';
$params = [666];
......@@ -512,8 +511,7 @@ class ConnectionTest extends TestCase
$driverStatementMock = $this->createMock(Statement::class);
$driverStatementMock->expects(self::once())
->method('fetch')
->with(FetchMode::ASSOCIATIVE)
->method('fetchAssociative')
->will(self::returnValue($result));
$conn = $this->getMockBuilder(Connection::class)
......@@ -526,10 +524,10 @@ class ConnectionTest extends TestCase
->with($statement, $params, $types)
->will(self::returnValue($driverStatementMock));
self::assertSame($result, $conn->fetchAssoc($statement, $params, $types));
self::assertSame($result, $conn->fetchAssociative($statement, $params, $types));
}
public function testFetchArray() : void
public function testFetchNumeric() : void
{
$statement = 'SELECT * FROM foo WHERE bar = ?';
$params = [666];
......@@ -547,8 +545,7 @@ class ConnectionTest extends TestCase
$driverStatementMock = $this->createMock(Statement::class);
$driverStatementMock->expects(self::once())
->method('fetch')
->with(FetchMode::NUMERIC)
->method('fetchNumeric')
->will(self::returnValue($result));
$conn = $this->getMockBuilder(Connection::class)
......@@ -561,10 +558,10 @@ class ConnectionTest extends TestCase
->with($statement, $params, $types)
->will(self::returnValue($driverStatementMock));
self::assertSame($result, $conn->fetchArray($statement, $params, $types));
self::assertSame($result, $conn->fetchNumeric($statement, $params, $types));
}
public function testFetchColumn() : void
public function testFetchOne() : void
{
$statement = 'SELECT * FROM foo WHERE bar = ?';
$params = [666];
......@@ -582,7 +579,7 @@ class ConnectionTest extends TestCase
$driverStatementMock = $this->createMock(Statement::class);
$driverStatementMock->expects(self::once())
->method('fetchColumn')
->method('fetchOne')
->will(self::returnValue($result));
$conn = $this->getMockBuilder(Connection::class)
......@@ -595,10 +592,10 @@ class ConnectionTest extends TestCase
->with($statement, $params, $types)
->will(self::returnValue($driverStatementMock));
self::assertSame($result, $conn->fetchColumn($statement, $params, $types));
self::assertSame($result, $conn->fetchOne($statement, $params, $types));
}
public function testFetchAll() : void
public function testFetchAllAssociative() : void
{
$statement = 'SELECT * FROM foo WHERE bar = ?';
$params = [666];
......@@ -616,7 +613,7 @@ class ConnectionTest extends TestCase
$driverStatementMock = $this->createMock(Statement::class);
$driverStatementMock->expects(self::once())
->method('fetchAll')
->method('fetchAllAssociative')
->will(self::returnValue($result));
$conn = $this->getMockBuilder(Connection::class)
......@@ -629,7 +626,7 @@ class ConnectionTest extends TestCase
->with($statement, $params, $types)
->will(self::returnValue($driverStatementMock));
self::assertSame($result, $conn->fetchAll($statement, $params, $types));
self::assertSame($result, $conn->fetchAllAssociative($statement, $params, $types));
}
public function testCallingDeleteWithNoDeletionCriteriaResultsInInvalidArgumentException() : void
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Tests\Driver;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Traversable;
class StatementIteratorTest extends TestCase
{
public function testIteratorIterationCallsFetchOncePerStep() : void
{
$stmt = $this->createMock(Statement::class);
$calls = 0;
$this->configureStatement($stmt, $calls);
$stmtIterator = new StatementIterator($stmt);
$this->assertIterationCallsFetchOncePerStep($stmtIterator, $calls);
}
private function configureStatement(MockObject $stmt, int &$calls) : void
{
$values = ['foo', '', 'bar', '0', 'baz', 0, 'qux', null, 'quz', false, 'impossible'];
$calls = 0;
$stmt->expects(self::exactly(10))
->method('fetch')
->willReturnCallback(static function () use ($values, &$calls) {
$value = $values[$calls];
$calls++;
return $value;
});
}
/**
* @param Traversable<int, mixed> $iterator
*/
private function assertIterationCallsFetchOncePerStep(Traversable $iterator, int &$calls) : void
{
foreach ($iterator as $i => $_) {
self::assertEquals($i + 1, $calls);
}
}
}
......@@ -6,7 +6,6 @@ namespace Doctrine\DBAL\Tests\Functional;
use Doctrine\DBAL\Driver\OCI8\Driver as OCI8Driver;
use Doctrine\DBAL\Driver\PDOOracle\Driver as PDOOracleDriver;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Tests\FunctionalTestCase;
......@@ -160,7 +159,7 @@ class BlobTest extends FunctionalTestCase
private function assertBlobContains(string $text) : void
{
$rows = $this->connection->query('SELECT blobfield FROM blob_table')->fetchAll(FetchMode::COLUMN);
$rows = $this->connection->query('SELECT blobfield FROM blob_table')->fetchColumn();
self::assertCount(1, $rows);
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Tests\Functional\Connection;
use Doctrine\DBAL\Tests\FunctionalTestCase;
use Doctrine\DBAL\Tests\TestUtil;
use function iterator_to_array;
class FetchTest extends FunctionalTestCase
{
/** @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)));
}
}
......@@ -107,7 +107,7 @@ class ConnectionTest extends FunctionalTestCase
$connection->executeQuery('insert into test_nesting values (33)');
$connection->rollBack();
self::assertEquals(0, $connection->fetchColumn('select count(*) from test_nesting'));
self::assertEquals(0, $connection->fetchOne('select count(*) from test_nesting'));
}
public function testTransactionNestingBehaviorWithSavepoints() : void
......
This diff is collapsed.
......@@ -35,7 +35,7 @@ class StatementTest extends FunctionalTestCase
{
self::assertEquals(
$expected,
$this->connection->executeQuery($query, $params)->fetch()
$this->connection->executeQuery($query, $params)->fetchAssociative()
);
}
......@@ -54,7 +54,7 @@ class StatementTest extends FunctionalTestCase
self::assertEquals(
$expected,
$stmt->fetch()
$stmt->fetchAssociative()
);
}
......
......@@ -87,7 +87,7 @@ class DriverTest extends AbstractDriverTest
$hash = microtime(true); // required to identify the record in the results uniquely
$sql = sprintf('SELECT * FROM pg_stat_activity WHERE %d = %d', $hash, $hash);
$statement = $connection->query($sql);
$records = $statement->fetchAll();
$records = $statement->fetchAllAssociative();
foreach ($records as $record) {
// The query column is named "current_query" on PostgreSQL < 9.2
......
......@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Tests\Functional\Driver;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use Doctrine\DBAL\Tests\FunctionalTestCase;
use function extension_loaded;
......@@ -46,7 +45,7 @@ class PDOPgsqlConnectionTest extends FunctionalTestCase
self::assertEquals(
$charset,
$connection->query('SHOW client_encoding')
->fetch(FetchMode::COLUMN)
->fetchOne()
);
}
......
......@@ -59,7 +59,7 @@ class DriverTest extends AbstractDriverTest
public function testConnectionOptions() : void
{
$connection = $this->getConnection(['APP' => 'APP_NAME']);
$result = $connection->query('SELECT APP_NAME()')->fetchColumn();
$result = $connection->query('SELECT APP_NAME()')->fetchOne();
self::assertSame('APP_NAME', $result);
}
......
......@@ -25,6 +25,6 @@ final class LikeWildcardsEscapingTest extends FunctionalTestCase
)
);
$stmt->execute();
self::assertTrue((bool) $stmt->fetchColumn());
self::assertTrue((bool) $stmt->fetchOne());
}
}
......@@ -95,7 +95,7 @@ class MasterSlaveConnectionTest extends FunctionalTestCase
self::assertFalse($conn->isConnectedToMaster());
$clientCharset = $conn->fetchColumn('select @@character_set_client as c');
$clientCharset = $conn->fetchOne('select @@character_set_client as c');
self::assertSame(
$charset,
......@@ -120,7 +120,7 @@ class MasterSlaveConnectionTest extends FunctionalTestCase
$conn = $this->createMasterSlaveConnection();
$sql = 'SELECT count(*) as num FROM master_slave_table';
$data = $conn->fetchAll($sql);
$data = $conn->fetchAllAssociative($sql);
$data[0] = array_change_key_case($data[0], CASE_LOWER);
self::assertEquals(1, $data[0]['num']);
......@@ -135,7 +135,7 @@ class MasterSlaveConnectionTest extends FunctionalTestCase
self::assertTrue($conn->isConnectedToMaster());
$sql = 'SELECT count(*) as num FROM master_slave_table';
$data = $conn->fetchAll($sql);
$data = $conn->fetchAllAssociative($sql);
$data[0] = array_change_key_case($data[0], CASE_LOWER);
self::assertEquals(2, $data[0]['num']);
......@@ -208,9 +208,8 @@ class MasterSlaveConnectionTest extends FunctionalTestCase
//Query must be executed only on Master
self::assertTrue($conn->isConnectedToMaster());
$data = $statement->fetchAll();
$data = $statement->fetchAllAssociative();
//Default fetchmode is FetchMode::ASSOCIATIVE
self::assertArrayHasKey(0, $data);
self::assertArrayHasKey('num', $data[0]);
......@@ -233,9 +232,8 @@ class MasterSlaveConnectionTest extends FunctionalTestCase
//Query must be executed only on Master, even when we connect to the slave
self::assertTrue($conn->isConnectedToMaster());
$data = $statement->fetchAll();
$data = $statement->fetchAllAssociative();
//Default fetchmode is FetchMode::ASSOCIATIVE
self::assertArrayHasKey(0, $data);
self::assertArrayHasKey('num', $data[0]);
......
......@@ -171,7 +171,7 @@ SQL;
{
$p = $this->connection->getDatabasePlatform();
$data = [];
foreach ($this->connection->fetchAll($p->modifyLimitQuery($sql, $limit, $offset)) as $row) {
foreach ($this->connection->fetchAllAssociative($p->modifyLimitQuery($sql, $limit, $offset)) as $row) {
$row = array_change_key_case($row, CASE_LOWER);
$data[] = $row['test_int'];
}
......
......@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Tests\Functional;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Tests\FunctionalTestCase;
......@@ -215,7 +214,7 @@ class NamedParametersTest extends FunctionalTestCase
public function testTicket(string $query, array $params, array $types, array $expected) : void
{
$stmt = $this->connection->executeQuery($query, $params, $types);
$result = $stmt->fetchAll(FetchMode::ASSOCIATIVE);
$result = $stmt->fetchAllAssociative();
foreach ($result as $k => $v) {
$result[$k] = array_change_key_case($v, CASE_LOWER);
......
......@@ -113,7 +113,7 @@ abstract class ColumnTest extends FunctionalTestCase
self::assertSame(1, $this->connection->insert('column_test', ['val' => $value], [$bindType]));
self::assertSame($value, Type::getType($type)->convertToPHPValue(
$this->connection->fetchColumn('SELECT val FROM column_test'),
$this->connection->fetchOne('SELECT val FROM column_test'),
$this->connection->getDatabasePlatform()
));
}
......
......@@ -28,7 +28,7 @@ class DateExpressionTest extends FunctionalTestCase
$platform = $this->connection->getDatabasePlatform();
$sql = sprintf('SELECT %s FROM date_expr_test', $platform->getDateDiffExpression('date1', 'date2'));
$diff = $this->connection->query($sql)->fetchColumn();
$diff = $this->connection->query($sql)->fetchOne();
self::assertEquals($expected, $diff);
}
......
......@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Tests\Functional\Platform;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\MySqlPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform;
......@@ -71,7 +70,7 @@ class DefaultExpressionTest extends FunctionalTestCase
[$actualValue, $defaultValue] = $this->connection->query(
'SELECT default_value, actual_value FROM default_expr_test'
)->fetch(FetchMode::NUMERIC);
)->fetchNumeric();
self::assertEquals($actualValue, $defaultValue);
}
......
......@@ -18,7 +18,7 @@ class QuotingTest extends FunctionalTestCase
$platform->quoteStringLiteral($string)
);
self::assertSame($string, $this->connection->fetchColumn($query));
self::assertSame($string, $this->connection->fetchOne($query));
}
/**
......
......@@ -7,7 +7,6 @@ namespace Doctrine\DBAL\Tests\Functional;
use Doctrine\DBAL\ColumnCase;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Portability\Connection as ConnectionPortability;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Tests\FunctionalTestCase;
......@@ -78,50 +77,38 @@ class PortabilityTest extends FunctionalTestCase
public function testFullFetchMode() : void
{
$rows = $this->portableConnection->fetchAll('SELECT * FROM portability_table');
$rows = $this->portableConnection->fetchAllAssociative('SELECT * FROM portability_table');
$this->assertFetchResultRows($rows);
$stmt = $this->portableConnection->query('SELECT * FROM portability_table');
$stmt->setFetchMode(FetchMode::ASSOCIATIVE);
foreach ($stmt as $row) {
$this->assertFetchResultRow($row);
}
$stmt = $this->portableConnection->query('SELECT * FROM portability_table');
while (($row = $stmt->fetch(FetchMode::ASSOCIATIVE))) {
while (($row = $stmt->fetchAssociative())) {
$this->assertFetchResultRow($row);
}
$stmt = $this->portableConnection->prepare('SELECT * FROM portability_table');
$stmt->execute();
while (($row = $stmt->fetch(FetchMode::ASSOCIATIVE))) {
while (($row = $stmt->fetchAssociative())) {
$this->assertFetchResultRow($row);
}
}
public function testConnFetchMode() : void
{
$this->portableConnection->setFetchMode(FetchMode::ASSOCIATIVE);
$conn = $this->getPortableConnection();
$rows = $this->portableConnection->fetchAll('SELECT * FROM portability_table');
$rows = $conn->fetchAllAssociative('SELECT * FROM portability_table');
$this->assertFetchResultRows($rows);
$stmt = $this->portableConnection->query('SELECT * FROM portability_table');
foreach ($stmt as $row) {
$this->assertFetchResultRow($row);
}
$stmt = $this->portableConnection->query('SELECT * FROM portability_table');
while (($row = $stmt->fetch())) {
$stmt = $conn->query('SELECT * FROM portability_table');
while (($row = $stmt->fetchAssociative())) {
$this->assertFetchResultRow($row);
}
$stmt = $this->portableConnection->prepare('SELECT * FROM portability_table');
$stmt->execute();
while (($row = $stmt->fetch())) {
while (($row = $stmt->fetchAssociative())) {
$this->assertFetchResultRow($row);
}
}
......@@ -156,20 +143,20 @@ class PortabilityTest extends FunctionalTestCase
/**
* @param mixed[] $expected
*
* @dataProvider fetchAllColumnProvider
* @dataProvider fetchColumnProvider
*/
public function testFetchAllColumn(string $field, array $expected) : void
public function testfetchColumn(string $field, array $expected) : void
{
$stmt = $this->portableConnection->query('SELECT ' . $field . ' FROM portability_table');
$column = $stmt->fetchAll(FetchMode::COLUMN);
$column = $stmt->fetchColumn();
self::assertEquals($expected, $column);
}
/**
* @return iterable<string, array<int, mixed>>
*/
public static function fetchAllColumnProvider() : iterable
public static function fetchColumnProvider() : iterable
{
return [
'int' => [
......@@ -187,7 +174,7 @@ class PortabilityTest extends FunctionalTestCase
{
$stmt = $this->portableConnection->query('SELECT Test_Null FROM portability_table');
$column = $stmt->fetchAll(FetchMode::COLUMN);
$column = $stmt->fetchColumn();
self::assertSame([null, null], $column);
}
}
This diff is collapsed.
......@@ -60,7 +60,7 @@ class DefaultValueTest extends FunctionalTestCase
*/
public function testEscapedDefaultValueCanBeInserted(string $name, ?string $expectedDefault) : void
{
$value = $this->connection->fetchColumn(
$value = $this->connection->fetchOne(
sprintf('SELECT %s FROM default_value', $name)
);
......
......@@ -468,7 +468,7 @@ class MySqlSchemaManagerTest extends SchemaManagerFunctionalTestCase
'INSERT INTO test_column_defaults_are_valid () VALUES()'
);
$row = $this->connection->fetchAssoc(
$row = $this->connection->fetchAssociative(
'SELECT *, DATEDIFF(CURRENT_TIMESTAMP(), col_datetime) as diff_seconds FROM test_column_defaults_are_valid'
);
......
......@@ -1236,7 +1236,7 @@ abstract class SchemaManagerFunctionalTestCase extends FunctionalTestCase
assert($query instanceof Statement);
$query->execute();
$lastUsedIdBeforeDelete = (int) $query->fetchColumn();
$lastUsedIdBeforeDelete = (int) $query->fetchOne();
$this->connection->query('DELETE FROM test_pk_auto_increment');
......@@ -1246,7 +1246,7 @@ abstract class SchemaManagerFunctionalTestCase extends FunctionalTestCase
assert($query instanceof Statement);
$query->execute();
$lastUsedIdAfterDelete = (int) $query->fetchColumn();
$lastUsedIdAfterDelete = (int) $query->fetchOne();
self::assertGreaterThan($lastUsedIdBeforeDelete, $lastUsedIdAfterDelete);
}
......
......@@ -279,7 +279,7 @@ SQL;
assert($query instanceof Statement);
$query->execute();
$lastUsedIdAfterDelete = (int) $query->fetchColumn();
$lastUsedIdAfterDelete = (int) $query->fetchOne();
// with an empty table, non autoincrement rowid is always 1
self::assertEquals(1, $lastUsedIdAfterDelete);
......
......@@ -11,7 +11,6 @@ use Doctrine\DBAL\Driver\PDOOracle\Driver as PDOOracleDriver;
use Doctrine\DBAL\Driver\PDOSqlsrv\Driver as PDOSQLSRVDriver;
use Doctrine\DBAL\Driver\SQLSrv\Driver as SQLSRVDriver;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Tests\FunctionalTestCase;
......@@ -46,15 +45,15 @@ class StatementTest extends FunctionalTestCase
$stmt->execute();
$id = $stmt->fetchColumn();
$id = $stmt->fetchOne();
self::assertEquals(1, $id);
$stmt->closeCursor();
$stmt->execute();
$id = $stmt->fetchColumn();
$id = $stmt->fetchOne();
self::assertEquals(1, $id);
$id = $stmt->fetchColumn();
$id = $stmt->fetchOne();
self::assertEquals(2, $id);
}
......@@ -80,7 +79,7 @@ class StatementTest extends FunctionalTestCase
$stmt->execute();
self::assertEquals([
['param1', 'X'],
], $stmt->fetchAll(FetchMode::NUMERIC));
], $stmt->fetchAllNumeric());
$row2 = [
'param' => 'param2',
......@@ -92,7 +91,7 @@ class StatementTest extends FunctionalTestCase
self::assertEquals([
['param1', 'X'],
['param2', 'A bit longer value'],
], $stmt->fetchAll(FetchMode::NUMERIC));
], $stmt->fetchAllNumeric());
}
public function testFetchLongBlob() : void
......@@ -136,7 +135,7 @@ EOF
$stream = Type::getType('blob')
->convertToPHPValue(
$stmt->fetchColumn(),
$stmt->fetchOne(),
$this->connection->getDatabasePlatform()
);
......@@ -150,14 +149,14 @@ EOF
$stmt1 = $this->connection->prepare('SELECT id FROM stmt_test');
$stmt1->execute();
$stmt1->fetch();
$stmt1->fetchAssociative();
$stmt1->execute();
// fetching only one record out of two
$stmt1->fetch();
$stmt1->fetchAssociative();
$stmt2 = $this->connection->prepare('SELECT id FROM stmt_test WHERE id = ?');
$stmt2->execute([1]);
self::assertEquals(1, $stmt2->fetchColumn());
self::assertEquals(1, $stmt2->fetchOne());
}
public function testReuseStatementAfterClosingCursor() : void
......@@ -172,13 +171,13 @@ EOF
$stmt = $this->connection->prepare('SELECT id FROM stmt_test WHERE id = ?');
$stmt->execute([1]);
$id = $stmt->fetchColumn();
$id = $stmt->fetchOne();
self::assertEquals(1, $id);
$stmt->closeCursor();
$stmt->execute([2]);
$id = $stmt->fetchColumn();
$id = $stmt->fetchOne();
self::assertEquals(2, $id);
}
......@@ -192,11 +191,11 @@ EOF
$id = 1;
$stmt->execute();
self::assertEquals(1, $stmt->fetchColumn());
self::assertEquals(1, $stmt->fetchOne());
$id = 2;
$stmt->execute();
self::assertEquals(2, $stmt->fetchColumn());
self::assertEquals(2, $stmt->fetchOne());
}
public function testReuseStatementWithReboundValue() : void
......@@ -208,11 +207,11 @@ EOF
$stmt->bindValue(1, 1);
$stmt->execute();
self::assertEquals(1, $stmt->fetchColumn());
self::assertEquals(1, $stmt->fetchOne());
$stmt->bindValue(1, 2);
$stmt->execute();
self::assertEquals(2, $stmt->fetchColumn());
self::assertEquals(2, $stmt->fetchOne());
}
public function testReuseStatementWithReboundParam() : void
......@@ -225,12 +224,12 @@ EOF
$x = 1;
$stmt->bindParam(1, $x);
$stmt->execute();
self::assertEquals(1, $stmt->fetchColumn());
self::assertEquals(1, $stmt->fetchOne());
$y = 2;
$stmt->bindParam(1, $y);
$stmt->execute();
self::assertEquals(2, $stmt->fetchColumn());
self::assertEquals(2, $stmt->fetchOne());
}
/**
......@@ -264,7 +263,7 @@ EOF
$stmt = $this->connection->prepare('SELECT name FROM stmt_test');
$stmt->execute();
$stmt->fetch();
$stmt->fetchAssociative();
$stmt->closeCursor();
}
......@@ -315,19 +314,19 @@ EOF
return [
'fetch' => [
static function (Statement $stmt) {
return $stmt->fetch();
return $stmt->fetchAssociative();
},
false,
],
'fetch-column' => [
static function (Statement $stmt) {
return $stmt->fetchColumn();
return $stmt->fetchOne();
},
false,
],
'fetch-all' => [
static function (Statement $stmt) : array {
return $stmt->fetchAll();
return $stmt->fetchAllAssociative();
},
[],
],
......@@ -338,7 +337,7 @@ EOF
{
$platform = $this->connection->getDatabasePlatform();
$query = $platform->getDummySelectSQL();
$result = $this->connection->executeQuery($query)->fetch(FetchMode::COLUMN);
$result = $this->connection->executeQuery($query)->fetchOne();
self::assertEquals(1, $result);
}
......
......@@ -69,7 +69,7 @@ class TemporaryTableTest extends FunctionalTestCase
$this->connection->rollBack();
$rows = $this->connection->fetchAll('SELECT * FROM nontemporary');
$rows = $this->connection->fetchAllAssociative('SELECT * FROM nontemporary');
self::assertEquals([], $rows, 'In an event of an error this result has one row, because of an implicit commit.');
}
......@@ -116,7 +116,7 @@ class TemporaryTableTest extends FunctionalTestCase
} catch (Throwable $e) {
}
$rows = $this->connection->fetchAll('SELECT * FROM nontemporary');
$rows = $this->connection->fetchAllAssociative('SELECT * FROM nontemporary');
self::assertEquals([], $rows, 'In an event of an error this result has one row, because of an implicit commit.');
}
}
......@@ -38,7 +38,7 @@ class DBAL202Test extends FunctionalTestCase
$stmt->execute();
$this->connection->rollBack();
self::assertEquals(0, $this->connection->query('SELECT COUNT(1) FROM DBAL202')->fetchColumn());
self::assertEquals(0, $this->connection->query('SELECT COUNT(1) FROM DBAL202')->fetchOne());
}
public function testStatementCommit() : void
......@@ -48,6 +48,6 @@ class DBAL202Test extends FunctionalTestCase
$stmt->execute();
$this->connection->commit();
self::assertEquals(1, $this->connection->query('SELECT COUNT(1) FROM DBAL202')->fetchColumn());
self::assertEquals(1, $this->connection->query('SELECT COUNT(1) FROM DBAL202')->fetchOne());
}
}
......@@ -54,7 +54,7 @@ class DBAL630Test extends FunctionalTestCase
$id = $this->connection->lastInsertId('dbal630_id_seq');
self::assertNotEmpty($id);
$row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]);
$row = $this->connection->fetchAssociative('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]);
self::assertIsArray($row);
self::assertFalse($row['bool_col']);
......@@ -70,7 +70,7 @@ class DBAL630Test extends FunctionalTestCase
$id = $this->connection->lastInsertId('dbal630_id_seq');
self::assertNotEmpty($id);
$row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]);
$row = $this->connection->fetchAssociative('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]);
self::assertIsArray($row);
self::assertFalse($row['bool_col']);
......@@ -91,7 +91,7 @@ class DBAL630Test extends FunctionalTestCase
self::assertNotEmpty($id);
$row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]);
$row = $this->connection->fetchAssociative('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]);
self::assertIsArray($row);
self::assertFalse($row['bool_col']);
......@@ -117,7 +117,7 @@ class DBAL630Test extends FunctionalTestCase
self::assertNotEmpty($id);
$row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630_allow_nulls WHERE id = ?', [$id]);
$row = $this->connection->fetchAssociative('SELECT bool_col FROM dbal630_allow_nulls WHERE id = ?', [$id]);
self::assertIsArray($row);
self::assertSame($databaseConvertedValue, $row['bool_col']);
......@@ -147,7 +147,7 @@ class DBAL630Test extends FunctionalTestCase
self::assertNotEmpty($id);
$row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630_allow_nulls WHERE id = ?', [$id]);
$row = $this->connection->fetchAssociative('SELECT bool_col FROM dbal630_allow_nulls WHERE id = ?', [$id]);
self::assertIsArray($row);
self::assertSame($databaseConvertedValue, $row['bool_col']);
......
......@@ -249,7 +249,7 @@ class TypeConversionTest extends FunctionalTestCase
$sql = 'SELECT ' . $columnName . ' FROM type_conversion WHERE id = ' . self::$typeCounter;
return $typeInstance->convertToPHPValue(
$this->connection->fetchColumn($sql),
$this->connection->fetchOne($sql),
$this->connection->getDatabasePlatform()
);
}
......
......@@ -74,7 +74,7 @@ class BinaryTest extends FunctionalTestCase
*/
private function select(string $id)
{
$value = $this->connection->fetchColumn(
$value = $this->connection->fetchOne(
'SELECT val FROM binary_table WHERE id = ?',
[$id],
[ParameterType::BINARY]
......
......@@ -118,10 +118,10 @@ class WriteTest extends FunctionalTestCase
$this->insertRows();
self::assertEquals(1, $this->connection->delete('write_table', ['test_int' => 2]));
self::assertCount(1, $this->connection->fetchAll('SELECT * FROM write_table'));
self::assertCount(1, $this->connection->fetchAllAssociative('SELECT * FROM write_table'));
self::assertEquals(1, $this->connection->delete('write_table', ['test_int' => 1]));
self::assertCount(0, $this->connection->fetchAll('SELECT * FROM write_table'));
self::assertCount(0, $this->connection->fetchAllAssociative('SELECT * FROM write_table'));
}
public function testUpdate() : void
......@@ -163,7 +163,7 @@ class WriteTest extends FunctionalTestCase
}));
$stmt = $this->connection->query($this->connection->getDatabasePlatform()->getSequenceNextValSQL('write_table_id_seq'));
$nextSequenceVal = $stmt->fetchColumn();
$nextSequenceVal = $stmt->fetchOne();
$lastInsertId = $this->lastInsertId('write_table_id_seq');
......@@ -194,7 +194,7 @@ class WriteTest extends FunctionalTestCase
['test_string' => 'datetime', 'test_int' => 'integer']
);
$data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
$data = $this->connection->fetchOne('SELECT test_string FROM write_table WHERE test_int = 30');
self::assertEquals($testString->format($this->connection->getDatabasePlatform()->getDateTimeFormatString()), $data);
}
......@@ -221,7 +221,7 @@ class WriteTest extends FunctionalTestCase
['test_string' => 'datetime', 'test_int' => 'integer']
);
$data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
$data = $this->connection->fetchOne('SELECT test_string FROM write_table WHERE test_int = 30');
self::assertEquals($testString->format($this->connection->getDatabasePlatform()->getDateTimeFormatString()), $data);
}
......@@ -240,7 +240,7 @@ class WriteTest extends FunctionalTestCase
$this->connection->delete('write_table', ['test_int' => 30, 'test_string' => $val], ['test_string' => 'datetime', 'test_int' => 'integer']);
$data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30');
$data = $this->connection->fetchOne('SELECT test_string FROM write_table WHERE test_int = 30');
self::assertFalse($data);
}
......@@ -296,13 +296,13 @@ class WriteTest extends FunctionalTestCase
['test_string' => 'string', 'test_int' => 'integer']
);
$data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
$data = $this->connection->fetchAllAssociative('SELECT * FROM write_table WHERE test_int = 30');
self::assertCount(1, $data);
$this->connection->update('write_table', ['test_int' => 10], ['test_string' => null], ['test_string' => 'string', 'test_int' => 'integer']);
$data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
$data = $this->connection->fetchAllAssociative('SELECT * FROM write_table WHERE test_int = 30');
self::assertCount(0, $data);
}
......@@ -315,13 +315,13 @@ class WriteTest extends FunctionalTestCase
['test_string' => 'string', 'test_int' => 'integer']
);
$data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
$data = $this->connection->fetchAllAssociative('SELECT * FROM write_table WHERE test_int = 30');
self::assertCount(1, $data);
$this->connection->delete('write_table', ['test_string' => null], ['test_string' => 'string']);
$data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30');
$data = $this->connection->fetchAllAssociative('SELECT * FROM write_table WHERE test_int = 30');
self::assertCount(0, $data);
}
......
......@@ -10,7 +10,6 @@ use Doctrine\DBAL\Portability\Connection;
use Doctrine\DBAL\Portability\Statement;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use function iterator_to_array;
class StatementTest extends TestCase
{
......@@ -93,15 +92,6 @@ class StatementTest extends TestCase
$this->stmt->execute($params);
}
public function testGetIterator() : void
{
$this->wrappedStmt->expects(self::exactly(3))
->method('fetch')
->willReturnOnConsecutiveCalls('foo', 'bar', false);
self::assertSame(['foo', 'bar'], iterator_to_array($this->stmt->getIterator()));
}
public function testRowCount() : void
{
$rowCount = 666;
......
......@@ -33,7 +33,7 @@ final class DB2SchemaManagerTest extends TestCase
$platform = $this->createMock(DB2Platform::class);
$this->conn = $this
->getMockBuilder(Connection::class)
->onlyMethods(['fetchAll'])
->onlyMethods(['fetchAllAssociative'])
->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager])
->getMock();
......@@ -50,7 +50,7 @@ final class DB2SchemaManagerTest extends TestCase
$this->conn->getConfiguration()->setSchemaAssetsFilter(static function (string $name) : bool {
return preg_match('/^(?!T_)/', $name) === 1;
});
$this->conn->expects(self::once())->method('fetchAll')->will(self::returnValue([
$this->conn->expects(self::once())->method('fetchAllAssociative')->will(self::returnValue([
['name' => 'FOO'],
['name' => 'T_FOO'],
['name' => 'BAR'],
......@@ -73,7 +73,7 @@ final class DB2SchemaManagerTest extends TestCase
return in_array($assetName, $accepted, true);
});
$this->conn->expects(self::once())->method('fetchAll')->will(self::returnValue([
$this->conn->expects(self::once())->method('fetchAllAssociative')->will(self::returnValue([
['name' => 'FOO'],
['name' => 'T_FOO'],
['name' => 'BAR'],
......
......@@ -27,9 +27,13 @@ class MySqlSchemaManagerTest extends TestCase
{
$eventManager = new EventManager();
$driverMock = $this->createMock(Driver::class);
$platform = $this->createMock(MySqlPlatform::class);
$platform->method('getListTableForeignKeysSQL')
->willReturn('');
$this->conn = $this->getMockBuilder(Connection::class)
->onlyMethods(['fetchAll'])
->onlyMethods(['fetchAllAssociative'])
->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager])
->getMock();
$this->manager = new MySqlSchemaManager($this->conn);
......@@ -37,7 +41,7 @@ class MySqlSchemaManagerTest extends TestCase
public function testCompositeForeignKeys() : void
{
$this->conn->expects(self::once())->method('fetchAll')->will(self::returnValue($this->getFKDefinition()));
$this->conn->expects(self::once())->method('fetchAllAssociative')->will(self::returnValue($this->getFKDefinition()));
$fkeys = $this->manager->listTableForeignKeys('dummy');
self::assertCount(1, $fkeys, 'Table has to have one foreign key.');
......
......@@ -6,11 +6,17 @@ namespace Doctrine\DBAL\Tests;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use InvalidArgumentException;
use PHPUnit\Framework\Assert;
use function array_keys;
use function array_map;
use function array_values;
use function explode;
use function extension_loaded;
use function implode;
use function is_string;
use function unlink;
/**
......@@ -222,4 +228,24 @@ class TestUtil
{
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));
}
}
......@@ -33,7 +33,7 @@ class RunSqlCommandTest extends TestCase
$this->commandTester = new CommandTester($this->command);
$this->connectionMock = $this->createMock(Connection::class);
$this->connectionMock->method('fetchAll')
$this->connectionMock->method('fetchAllAssociative')
->willReturn([[1]]);
$this->connectionMock->method('executeUpdate')
->willReturn(42);
......@@ -67,7 +67,7 @@ class RunSqlCommandTest extends TestCase
public function testSelectStatementsPrintsResult() : void
{
$this->expectConnectionFetchAll();
$this->expectConnectionFetchAllAssociative();
$exitCode = $this->commandTester->execute([
'command' => $this->command->getName(),
......@@ -99,22 +99,22 @@ class RunSqlCommandTest extends TestCase
->method('executeUpdate');
$this->connectionMock
->expects(self::exactly(0))
->method('fetchAll');
->method('fetchAllAssociative');
}
private function expectConnectionFetchAll() : void
private function expectConnectionFetchAllAssociative() : void
{
$this->connectionMock
->expects(self::exactly(0))
->method('executeUpdate');
$this->connectionMock
->expects(self::exactly(1))
->method('fetchAll');
->method('fetchAllAssociative');
}
public function testStatementsWithFetchResultPrintsResult() : void
{
$this->expectConnectionFetchAll();
$this->expectConnectionFetchAllAssociative();
$this->commandTester->execute([
'command' => $this->command->getName(),
......
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