feat: track expected output columns in query builder

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2024-07-31 19:52:41 +02:00 committed by Louis Chemineau
parent 32d76b0b4b
commit c09ec95255
No known key found for this signature in database
3 changed files with 41 additions and 0 deletions

View file

@ -288,4 +288,8 @@ abstract class ExtendedQueryBuilder implements IQueryBuilder {
public function executeStatement(?IDBConnection $connection = null): int {
return $this->builder->executeStatement($connection);
}
public function getOutputColumns(): array {
return $this->builder->getOutputColumns();
}
}

View file

@ -49,6 +49,7 @@ class QueryBuilder implements IQueryBuilder {
/** @var string */
protected $lastInsertedTable;
private array $selectedColumns = [];
/**
* Initializes a new QueryBuilder.
@ -470,6 +471,7 @@ class QueryBuilder implements IQueryBuilder {
if (count($selects) === 1 && is_array($selects[0])) {
$selects = $selects[0];
}
$this->addOutputColumns($selects);
$this->queryBuilder->select(
$this->helper->quoteColumnNames($selects)
@ -497,6 +499,7 @@ class QueryBuilder implements IQueryBuilder {
$this->queryBuilder->addSelect(
$this->helper->quoteColumnName($select) . ' AS ' . $this->helper->quoteColumnName($alias)
);
$this->addOutputColumns([$alias]);
return $this;
}
@ -518,6 +521,7 @@ class QueryBuilder implements IQueryBuilder {
if (!is_array($select)) {
$select = [$select];
}
$this->addOutputColumns($select);
$quotedSelect = $this->helper->quoteColumnNames($select);
@ -547,6 +551,7 @@ class QueryBuilder implements IQueryBuilder {
if (count($selects) === 1 && is_array($selects[0])) {
$selects = $selects[0];
}
$this->addOutputColumns($selects);
$this->queryBuilder->addSelect(
$this->helper->quoteColumnNames($selects)
@ -555,6 +560,30 @@ class QueryBuilder implements IQueryBuilder {
return $this;
}
private function addOutputColumns(array $columns) {
foreach ($columns as $column) {
if (is_array($column)) {
$this->addOutputColumns($column);
} elseif (is_string($column) && !str_contains($column, '*')) {
if (str_contains($column, '.')) {
[, $column] = explode('.', $column);
}
$this->selectedColumns[] = $column;
}
}
}
public function getOutputColumns(): array {
return array_unique(array_map(function (string $column) {
if (str_contains($column, '.')) {
[, $column] = explode('.', $column);
return $column;
} else {
return $column;
}
}, $this->selectedColumns));
}
/**
* Turns the query being built into a bulk delete query that ranges over
* a certain table.

View file

@ -1018,4 +1018,12 @@ interface IQueryBuilder {
* @since 9.0.0
*/
public function getColumnName($column, $tableAlias = '');
/**
* Get a list of column names that are expected in the query output
*
* @return array
* @since 30.0.0
*/
public function getOutputColumns(): array;
}