Skip to content

Commit

Permalink
Refactor Query::column() (#815)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov authored Apr 15, 2024
1 parent 3f977a5 commit e380ae2
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 32 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## 2.0.0 under development

- Enh #815: Refactor `Query::column()` method (@Tigrov)
- Enh #816: Allow scalar values for `$columns` parameter of `Query::select()` and `Query::addSelect()` methods (@Tigrov)
- Enh #806: Non-unique placeholder names inside `Expression::$params` will be replaced with unique names (@Tigrov)
- Enh #806: Build `Expression` instances inside `Expression::$params` when build a query using `QueryBuilder` (@Tigrov)
Expand Down
44 changes: 23 additions & 21 deletions src/Query/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@
use Yiisoft\Db\Helper\DbArrayHelper;
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;

use function array_column;
use function array_combine;
use function array_key_exists;
use function array_map;
use function array_merge;
use function array_shift;
use function array_unshift;
use function count;
use function current;
use function gettype;
use function is_array;
use function is_int;
Expand All @@ -29,7 +33,6 @@
use function key;
use function preg_match;
use function preg_split;
use function reset;
use function str_contains;
use function strcasecmp;
use function strlen;
Expand Down Expand Up @@ -84,6 +87,7 @@ class Query implements QueryInterface
protected array $params = [];
protected array $union = [];
protected array $withQueries = [];
/** @psalm-var Closure(array):array-key|string|null $indexBy */
protected Closure|string|null $indexBy = null;
protected ExpressionInterface|int|null $limit = null;
protected ExpressionInterface|int|null $offset = null;
Expand Down Expand Up @@ -256,39 +260,37 @@ public function column(): array
return $this->createCommand()->queryColumn();
}

if (is_string($this->indexBy) && count($this->select) === 1) {
if (!str_contains($this->indexBy, '.') && count($tables = $this->getTablesUsedInFrom()) > 0) {
$this->select[] = key($tables) . '.' . $this->indexBy;
} else {
$this->select[] = $this->indexBy;
if (is_string($this->indexBy)) {
if (count($this->select) === 1) {
if (!str_contains($this->indexBy, '.') && count($tables = $this->getTablesUsedInFrom()) > 0) {
$this->select[] = key($tables) . '.' . $this->indexBy;
} else {
$this->select[] = $this->indexBy;
}
}
}

$rows = $this->createCommand()->queryAll();
$results = [];
$column = null;
$rows = $this->createCommand()->queryAll();

if (empty($rows)) {
return [];
}

if (is_string($this->indexBy)) {
if (($dotPos = strpos($this->indexBy, '.')) === false) {
$column = $this->indexBy;
} else {
$column = substr($this->indexBy, $dotPos + 1);
}

return array_column($rows, key(current($rows)), $column);
}

/** @psalm-var array<array-key, array<string, string>> $rows */
foreach ($rows as $row) {
$value = reset($row);
$rows = $this->createCommand()->queryAll();

if ($this->indexBy instanceof Closure) {
/** @psalm-suppress MixedArrayOffset */
$results[($this->indexBy)($row)] = $value;
} else {
$results[$row[$column] ?? $row[$this->indexBy]] = $value;
}
if (empty($rows)) {
return [];
}

return $results;
return array_combine(array_map($this->indexBy, $rows), array_column($rows, key(current($rows))));
}

public function count(string $sql = '*'): int|string
Expand Down
2 changes: 2 additions & 0 deletions src/Query/QueryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ public function getHaving(): string|array|ExpressionInterface|null;

/**
* @return Closure|string|null The "index by" value.
*
* @psalm-return Closure(array):array-key|string|null
*/
public function getIndexBy(): Closure|string|null;

Expand Down
2 changes: 2 additions & 0 deletions src/Query/QueryPartsInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ public function having(array|ExpressionInterface|string|null $condition, array $
* // return the index value corresponding to $row
* }
* ```
*
* @psalm-param Closure(array):array-key|string|null $column
*/
public function indexBy(string|Closure|null $column): static;

Expand Down
16 changes: 16 additions & 0 deletions tests/AbstractQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,22 @@ public function testColumnWithIndexBy(): void
2 => 'user2',
3 => 'user3',
], $query->column());

$query = (new Query($db))
->select('name')
->from('customer')
->indexBy('id')
->where(['id' => null]);

$this->assertSame([], $query->column());

$query = (new Query($db))
->select(['name', 'id'])
->from('customer')
->indexBy(fn (array $row) => $row['id'] * 2)
->where(['id' => null]);

$this->assertSame([], $query->column());
}

/**
Expand Down
11 changes: 0 additions & 11 deletions tests/Common/CommonQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,6 @@

abstract class CommonQueryTest extends AbstractQueryTest
{
public function testColumnWithIndexBy(): void
{
$db = $this->getConnection(true);

$query = (new Query($db))->select('customer.name')->from('customer')->indexBy('customer.id');

$this->assertSame([1 => 'user1', 2 => 'user2', 3 => 'user3'], $query->column());

$db->close();
}

public function testColumnIndexByWithClosure()
{
$db = $this->getConnection(true);
Expand Down

0 comments on commit e380ae2

Please sign in to comment.