Unverified Commit acf84c3d authored by Sergei Morozov's avatar Sergei Morozov Committed by GitHub

Merge pull request #4037 from morozov/fetch-first-column

Introduce Statement::fetchFirstColumn()
parents c08d3bc8 76a8caec
......@@ -4,7 +4,7 @@
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.
3. The `Statement::fetchAll()` method is deprecated in favor of `fetchAllNumeric()`, `fetchAllAssociative()` and `fetchFirstColumn()`.
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()`.
......
......@@ -124,7 +124,7 @@ class ArrayStatement implements IteratorAggregate, ResultStatement, ForwardCompa
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
......@@ -201,6 +201,14 @@ class ArrayStatement implements IteratorAggregate, ResultStatement, ForwardCompa
return FetchUtils::fetchAllAssociative($this);
}
/**
* {@inheritdoc}
*/
public function fetchFirstColumn() : array
{
return FetchUtils::fetchFirstColumn($this);
}
/**
* @return mixed|false
*/
......
......@@ -176,7 +176,7 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement, Forwar
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
......@@ -277,6 +277,14 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement, Forwar
return $this->data;
}
/**
* {@inheritdoc}
*/
public function fetchFirstColumn() : array
{
return FetchUtils::fetchFirstColumn($this);
}
/**
* Returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement
* executed by the corresponding object.
......
......@@ -991,6 +991,32 @@ class Connection implements DriverConnection
}
}
/**
* Prepares and executes an SQL query and returns the result as an array of the first column values.
*
* @param string $query The SQL query.
* @param array<int, mixed>|array<string, mixed> $params The query parameters.
* @param array<int, int|string>|array<string, int|string> $types The query parameter types.
*
* @return array<int,mixed>
*
* @throws DBALException
*/
public function fetchFirstColumn(string $query, array $params = [], array $types = []) : array
{
try {
$stmt = $this->executeQuery($query, $params, $types);
if ($stmt instanceof ForwardCompatibleResultStatement) {
return $stmt->fetchFirstColumn();
}
return $stmt->fetchAll(FetchMode::COLUMN);
} catch (Throwable $e) {
throw DBALException::driverExceptionDuringQuery($this->_driver, $e, $query);
}
}
/**
* Prepares and executes an SQL query and returns the result as an iterator over rows represented as numeric arrays.
*
......
......@@ -58,4 +58,20 @@ final class FetchUtils
return $rows;
}
/**
* @return array<int,mixed>
*
* @throws DriverException
*/
public static function fetchFirstColumn(ResultStatement $stmt) : array
{
$rows = [];
while (($row = $stmt->fetchOne()) !== false) {
$rows[] = $row;
}
return $rows;
}
}
......@@ -2,9 +2,11 @@
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\ForwardCompatibility\Driver\ResultStatement as ForwardCompatibleResultStatement;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use PDO;
......@@ -46,7 +48,7 @@ use const DB2_LONG;
use const DB2_PARAM_FILE;
use const DB2_PARAM_IN;
class DB2Statement implements IteratorAggregate, Statement
class DB2Statement implements IteratorAggregate, Statement, ForwardCompatibleResultStatement
{
/** @var resource */
private $stmt;
......@@ -310,7 +312,7 @@ class DB2Statement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
......@@ -356,6 +358,64 @@ class DB2Statement implements IteratorAggregate, Statement
return $row[$columnIndex] ?? null;
}
/**
* {@inheritDoc}
*/
public function fetchNumeric()
{
if (! $this->result) {
return false;
}
return db2_fetch_array($this->stmt);
}
/**
* {@inheritdoc}
*/
public function fetchAssociative()
{
// do not try fetching from the statement if it's not expected to contain the result
// in order to prevent exceptional situation
if (! $this->result) {
return false;
}
return db2_fetch_assoc($this->stmt);
}
/**
* {@inheritdoc}
*/
public function fetchOne()
{
return FetchUtils::fetchOne($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllNumeric() : array
{
return FetchUtils::fetchAllNumeric($this);
}
/**
* {@inheritdoc}
*/
public function fetchAllAssociative() : array
{
return FetchUtils::fetchAllAssociative($this);
}
/**
* {@inheritdoc}
*/
public function fetchFirstColumn() : array
{
return FetchUtils::fetchFirstColumn($this);
}
/**
* {@inheritdoc}
*/
......
......@@ -362,7 +362,7 @@ class MysqliStatement implements IteratorAggregate, Statement, ForwardCompatible
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
......@@ -467,6 +467,14 @@ class MysqliStatement implements IteratorAggregate, Statement, ForwardCompatible
return FetchUtils::fetchAllAssociative($this);
}
/**
* {@inheritdoc}
*/
public function fetchFirstColumn() : array
{
return FetchUtils::fetchFirstColumn($this);
}
/**
* {@inheritdoc}
*/
......
......@@ -468,7 +468,7 @@ class OCI8Statement implements IteratorAggregate, Statement, ForwardCompatibleRe
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
......@@ -591,6 +591,14 @@ class OCI8Statement implements IteratorAggregate, Statement, ForwardCompatibleRe
return $this->doFetchAll(OCI_ASSOC, OCI_FETCHSTATEMENT_BY_ROW);
}
/**
* {@inheritdoc}
*/
public function fetchFirstColumn() : array
{
return $this->doFetchAll(OCI_NUM, OCI_FETCHSTATEMENT_BY_COLUMN)[0];
}
/**
* @return mixed|false
*/
......
......@@ -156,7 +156,7 @@ class PDOStatement extends \PDOStatement implements Statement, ForwardCompatible
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
......@@ -240,6 +240,14 @@ class PDOStatement extends \PDOStatement implements Statement, ForwardCompatible
return $this->fetchAll(PDO::FETCH_ASSOC);
}
/**
* {@inheritdoc}
*/
public function fetchFirstColumn() : array
{
return $this->fetchAll(PDO::FETCH_COLUMN);
}
/**
* Converts DBAL parameter type to PDO parameter type
*
......
......@@ -71,7 +71,7 @@ interface ResultStatement extends Traversable
/**
* Returns an array containing all of the result set rows.
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*
* @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,
......
......@@ -258,7 +258,7 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement, ForwardCompa
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
......@@ -368,6 +368,16 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement, ForwardCompa
return FetchUtils::fetchAllAssociative($this);
}
/**
* @return array<int,mixed>
*
* @throws DriverException
*/
public function fetchFirstColumn() : array
{
return FetchUtils::fetchFirstColumn($this);
}
/**
* {@inheritdoc}
*/
......
......@@ -390,7 +390,7 @@ class SQLSrvStatement implements IteratorAggregate, Statement, ForwardCompatible
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
......@@ -476,6 +476,14 @@ class SQLSrvStatement implements IteratorAggregate, Statement, ForwardCompatible
return FetchUtils::fetchAllAssociative($this);
}
/**
* {@inheritdoc}
*/
public function fetchFirstColumn() : array
{
return FetchUtils::fetchFirstColumn($this);
}
/**
* {@inheritdoc}
*/
......
......@@ -56,4 +56,13 @@ interface ResultStatement extends BaseResultStatement
* @throws DriverException
*/
public function fetchAllAssociative() : array;
/**
* Returns an array containing the values of the first column of the result set.
*
* @return array<int,mixed>
*
* @throws DriverException
*/
public function fetchFirstColumn() : array;
}
......@@ -160,7 +160,7 @@ class Statement implements IteratorAggregate, DriverStatement, ForwardCompatible
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
......@@ -255,6 +255,20 @@ class Statement implements IteratorAggregate, DriverStatement, ForwardCompatible
return $this->fixResultSet($data, true, true);
}
/**
* {@inheritdoc}
*/
public function fetchFirstColumn() : array
{
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
$data = $this->stmt->fetchFirstColumn();
} else {
$data = $this->stmt->fetchAll(FetchMode::COLUMN);
}
return $this->fixResultSet($data, true, false);
}
/**
* @param mixed $result
*
......
......@@ -263,7 +263,7 @@ class Statement implements IteratorAggregate, DriverStatement, ForwardCompatible
/**
* {@inheritdoc}
*
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchColumn() instead.
* @deprecated Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead.
*/
public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
......@@ -370,6 +370,24 @@ class Statement implements IteratorAggregate, DriverStatement, ForwardCompatible
}
}
/**
* {@inheritdoc}
*
* @throws DBALException
*/
public function fetchFirstColumn() : array
{
try {
if ($this->stmt instanceof ForwardCompatibleResultStatement) {
return $this->stmt->fetchFirstColumn();
}
return $this->stmt->fetchAll(FetchMode::COLUMN);
} catch (DriverException $e) {
throw DBALException::driverException($this->conn->getDriver(), $e);
}
}
/**
* {@inheritDoc}
*
......
......@@ -76,6 +76,15 @@ class FetchTest extends DbalFunctionalTestCase
], $this->connection->fetchAllAssociative($this->query));
}
public function testFetchFirstColumn() : void
{
self::assertEquals([
'foo',
'bar',
'baz',
], $this->connection->fetchFirstColumn($this->query));
}
public function testIterateNumeric() : void
{
self::assertEquals([
......
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