private function fetchByTwoPassStrategy(QueryBuilder $builder, array $values)
{
$sourceTable = $builder->getFromAlias();
$targetTable = QueryBuilderHelper::getAlias($this->joinTable);
$builder = clone $builder;
$builder->leftJoin($sourceTable, '%table', $targetTable, '%column = %column', $this->joinTable, "{$targetTable}.{$this->primaryKeyTo}", "{$sourceTable}." . $this->targetRepository->getMapper()->getStorageReflection()->getStoragePrimaryKey()[0]);
$builder->addSelect('%column', "{$targetTable}.{$this->primaryKeyTo}");
$builder->addSelect('%column', "{$targetTable}.{$this->primaryKeyFrom}");
if ($builder->hasLimitOffsetClause()) {
// todo !== 1
$sqls = $args = [];
foreach ($values as $value) {
$builderPart = clone $builder;
$builderPart->andWhere('%column = %any', "{$targetTable}.{$this->primaryKeyFrom}", $value);
$sqls[] = $builderPart->getQuerySQL();
$args = array_merge($args, $builderPart->getQueryParameters());
}
$query = '(' . implode(') UNION ALL (', $sqls) . ')';
$result = $this->connection->queryArgs($query, $args);
} else {
$builder->andWhere('%column IN %any', "{$targetTable}.{$this->primaryKeyFrom}", $values);
$result = $this->connection->queryArgs($builder->getQuerySQL(), $builder->getQueryParameters());
}
$values = [];
foreach ($result as $row) {
$values[$row->{$this->primaryKeyTo}] = null;
}
if (count($values) === 0) {
return new EntityIterator([]);
}
$entitiesResult = $this->targetRepository->findBy(['id' => array_keys($values)]);
$entities = $entitiesResult->fetchPairs('id', null);
$grouped = [];
foreach ($result as $row) {
$grouped[$row->{$this->primaryKeyFrom}][] = $entities[$row->{$this->primaryKeyTo}];
}
return new EntityIterator($grouped);
}