Skip to content

Commit

Permalink
fix: fill null values when doing a left join where the left part does…
Browse files Browse the repository at this point in the history
…n't exist

Signed-off-by: Robin Appelman <robin@icewind.nl>
  • Loading branch information
icewind1991 committed Jul 25, 2024
1 parent 362ea5e commit 512351a
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
11 changes: 9 additions & 2 deletions lib/private/DB/QueryBuilder/Partitioned/PartitionQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

namespace OC\DB\QueryBuilder\Partitioned;

use OC\DB\QueryBuilder\Sharded\ShardedQueryBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;

class PartitionQuery {
Expand All @@ -34,7 +35,7 @@ class PartitionQuery {
public const JOIN_MODE_RIGHT = 'right';

public function __construct(
public IQueryBuilder $query,
public ShardedQueryBuilder $query,
public string $joinFromColumn,
public string $joinToColumn,
public string $joinMode,
Expand All @@ -55,8 +56,14 @@ public function mergeWith(array $rows): array {
$joinFromValues = array_map(function (array $row) use ($joinFromColumn) {
return $row[$joinFromColumn];
}, $rows);
$joinFromValues = array_filter($joinFromValues, function($value) {
return $value !== null;
});
$this->query->andWhere($this->query->expr()->in($this->joinToColumn, $this->query->createNamedParameter($joinFromValues, IQueryBuilder::PARAM_STR_ARRAY, ':' . uniqid())));

$columns = $this->query->getOutputColumns();
$nullResult = array_combine($this->query->getOutputColumns(), array_fill(0, count($columns), null));

$s = $this->query->getSQL();
$partitionedRows = $this->query->executeQuery()->fetchAll();
$partitionedRowsByKey = [];
Expand All @@ -70,7 +77,7 @@ public function mergeWith(array $rows): array {
$result[] = array_merge($row, $partitionedRowsByKey[$row[$joinFromColumn]]);
}
} elseif ($this->joinMode === self::JOIN_MODE_LEFT || $this->joinMode === self::JOIN_MODE_LEFT_NULL) {
$result[] = $row;
$result[] = array_merge($nullResult, $row);
}
}
return $result;
Expand Down
46 changes: 45 additions & 1 deletion lib/private/DB/QueryBuilder/Sharded/ShardedQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class ShardedQueryBuilder extends ExtendedQueryBuilder {
private mixed $lastInsertId = null;
private ?IDBConnection $lastInsertConnection = null;
private ?int $updateShardKey = null;
private array $outputColumns = [];

/**
* @param ConnectionAdapter $connection
Expand Down Expand Up @@ -83,6 +84,40 @@ private function getKeyValue($value): array {
}
}

public function select(...$selects) {
$this->addOutputColumns($selects);
return parent::select(...$selects);
}

public function selectAlias($select, $alias) {
$this->addOutputColumns([$alias]);
return parent::selectAlias($select, $alias);
}

public function selectDistinct($select) {
$this->addOutputColumns([$select]);
return parent::selectDistinct($select);
}

public function addSelect(...$select) {
$this->addOutputColumns($select);
return parent::addSelect(...$select);
}

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->outputColumns[] = $column;
}
}
}


public function where(...$predicates) {
return $this->andWhere(...$predicates);
}
Expand Down Expand Up @@ -371,5 +406,14 @@ public function getLastInsertId(): int {
}
}


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->outputColumns));
}
}

0 comments on commit 512351a

Please sign in to comment.