Skip to content

Commit

Permalink
Merge pull request #4341 from morozov/issues/4206
Browse files Browse the repository at this point in the history
Add Statement::fetchAllIndexedAssociative() and ::iterateIndexedAssociative()
  • Loading branch information
morozov authored Oct 14, 2020
2 parents a5f5c51 + 99f9c7e commit 11fead5
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 7 deletions.
33 changes: 33 additions & 0 deletions docs/en/reference/data-retrieval-and-manipulation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,26 @@ Execute the query and fetch the first two columns into an associative array as k
.. note::
All additional columns will be ignored and are only allowed to be selected by DBAL for its internal purposes.

fetchAllAssociativeIndexed()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Execute the query and fetch the data as an associative array where the key represents the first column and the value is
an associative array of the rest of the columns and their values:

.. code-block:: php
<?php
$users = $conn->fetchAllAssociativeIndexed('SELECT id, username, password FROM user');
/*
array(
1 => array(
'username' => 'jwage',
'password' => 'changeme',
)
)
*/
fetchNumeric()
~~~~~~~~~~~~~~

Expand Down Expand Up @@ -459,6 +479,19 @@ Execute the query and iterate over the first two columns as keys and values resp
.. note::
All additional columns will be ignored and are only allowed to be selected by DBAL for its internal purposes.

iterateAssociativeIndexed()
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Execute the query and iterate over the result with the key representing the first column and the value being
an associative array of the rest of the columns and their values:

.. code-block:: php
<?php
foreach ($conn->iterateAssociativeIndexed('SELECT id, username, password FROM user') as $id => $data) {
// ...
}
delete()
~~~~~~~~~

Expand Down
61 changes: 55 additions & 6 deletions lib/Doctrine/DBAL/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use Traversable;

use function array_key_exists;
use function array_shift;
use function assert;
use function func_get_args;
use function implode;
Expand Down Expand Up @@ -990,9 +991,9 @@ public function fetchAllAssociative(string $query, array $params = [], array $ty
* Prepares and executes an SQL query and returns the result as an associative array with the keys
* mapped to the first column and the values mapped to the second column.
*
* @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.
* @param string $query SQL query
* @param array<int, mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string>|array<string, int|string> $types Parameter types
*
* @return array<mixed,mixed>
*
Expand All @@ -1013,6 +1014,32 @@ public function fetchAllKeyValue(string $query, array $params = [], array $types
return $data;
}

/**
* Prepares and executes an SQL query and returns the result as an associative array with the keys mapped
* to the first column and the values being an associative array representing the rest of the columns
* and their values.
*
* @param string $query SQL query
* @param array<int, mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string>|array<string, int|string> $types Parameter types
*
* @return array<mixed,array<string,mixed>>
*
* @throws Exception
*/
public function fetchAllAssociativeIndexed(string $query, array $params = [], array $types = []): array
{
$stmt = $this->executeQuery($query, $params, $types);

$data = [];

foreach ($stmt->fetchAll(FetchMode::ASSOCIATIVE) as $row) {
$data[array_shift($row)] = $row;
}

return $data;
}

/**
* Prepares and executes an SQL query and returns the result as an array of the first column values.
*
Expand Down Expand Up @@ -1100,9 +1127,9 @@ public function iterateAssociative(string $query, array $params = [], array $typ
* Prepares and executes an SQL query and returns the result as an iterator with the keys
* mapped to the first column and the values mapped to the second column.
*
* @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.
* @param string $query SQL query
* @param array<int, mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string>|array<string, int|string> $types Parameter types
*
* @return Traversable<mixed,mixed>
*
Expand All @@ -1119,6 +1146,28 @@ public function iterateKeyValue(string $query, array $params = [], array $types
}
}

/**
* Prepares and executes an SQL query and returns the result as an iterator with the keys mapped
* to the first column and the values being an associative array representing the rest of the columns
* and their values.
*
* @param string $query SQL query
* @param array<int, mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string>|array<string, int|string> $types Parameter types
*
* @return Traversable<mixed,array<string,mixed>>
*
* @throws Exception
*/
public function iterateAssociativeIndexed(string $query, array $params = [], array $types = []): Traversable
{
$stmt = $this->executeQuery($query, $params, $types);

while (($row = $stmt->fetch(FetchMode::ASSOCIATIVE)) !== false) {
yield array_shift($row) => $row;
}
}

/**
* Prepares and executes an SQL query and returns the result as an iterator over the first column values.
*
Expand Down
35 changes: 35 additions & 0 deletions lib/Doctrine/DBAL/Statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Throwable;
use Traversable;

use function array_shift;
use function is_array;
use function is_string;

Expand Down Expand Up @@ -398,6 +399,25 @@ public function fetchAllKeyValue(): array
return $data;
}

/**
* Returns an associative array with the keys mapped to the first column and the values being
* an associative array representing the rest of the columns and their values.
*
* @return array<mixed,array<string,mixed>>
*
* @throws Exception
*/
public function fetchAllAssociativeIndexed(): array
{
$data = [];

foreach ($this->fetchAll(FetchMode::ASSOCIATIVE) as $row) {
$data[array_shift($row)] = $row;
}

return $data;
}

/**
* {@inheritdoc}
*
Expand Down Expand Up @@ -483,6 +503,21 @@ public function iterateKeyValue(): Traversable
}
}

/**
* Returns an iterator over the result set with the keys mapped to the first column and the values being
* an associative array representing the rest of the columns and their values.
*
* @return Traversable<mixed,array<string,mixed>>
*
* @throws Exception
*/
public function iterateAssociativeIndexed(): Traversable
{
while (($row = $this->stmt->fetch(FetchMode::ASSOCIATIVE)) !== false) {
yield array_shift($row) => $row;
}
}

/**
* {@inheritDoc}
*
Expand Down
44 changes: 43 additions & 1 deletion tests/Doctrine/Tests/DBAL/Functional/Connection/FetchTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,27 @@ public function testFetchAllKeyValueOneColumn(): void
$this->connection->fetchAllKeyValue($sql);
}

public function testFetchAllAssociativeIndexed(): void
{
self::assertEquals([
'foo' => ['b' => 1],
'bar' => ['b' => 2],
'baz' => ['b' => 3],
], $this->connection->fetchAllAssociativeIndexed($this->query));
}

public function testStatementFetchAllAssociativeIndexed(): void
{
$stmt = $this->connection->prepare($this->query);
$stmt->execute();

self::assertEquals([
'foo' => ['b' => 1],
'bar' => ['b' => 2],
'baz' => ['b' => 3],
], $stmt->fetchAllAssociativeIndexed());
}

public function testFetchFirstColumn(): void
{
self::assertEquals([
Expand Down Expand Up @@ -171,7 +192,7 @@ public function testIterateKeyValue(): void
], iterator_to_array($this->connection->iterateKeyValue($this->query)));
}

public function testStatementKeyValue(): void
public function testStatementIterateKeyValue(): void
{
$stmt = $this->connection->prepare($this->query);
$stmt->execute();
Expand All @@ -192,6 +213,27 @@ public function testIterateKeyValueOneColumn(): void
iterator_to_array($this->connection->iterateKeyValue($sql));
}

public function testIterateAssociativeIndexed(): void
{
self::assertEquals([
'foo' => ['b' => 1],
'bar' => ['b' => 2],
'baz' => ['b' => 3],
], iterator_to_array($this->connection->iterateAssociativeIndexed($this->query)));
}

public function testStatementIterateAssociativeIndexed(): void
{
$stmt = $this->connection->prepare($this->query);
$stmt->execute();

self::assertEquals([
'foo' => ['b' => 1],
'bar' => ['b' => 2],
'baz' => ['b' => 3],
], iterator_to_array($stmt->iterateAssociativeIndexed()));
}

public function testIterateColumn(): void
{
self::assertEquals([
Expand Down

0 comments on commit 11fead5

Please sign in to comment.