protected function fetchByTwoPassStrategy(QueryBuilder $builder, array $values)
{
$builder = clone $builder;
$targetPrimaryKey = $this->targetMapper->getStorageReflection()->getStoragePrimaryKey();
$isComposite = count($targetPrimaryKey) !== 1;
foreach (array_unique(array_merge($targetPrimaryKey, [$this->joinStorageKey])) as $key) {
$builder->addSelect("[{$key}]");
}
$sqls = $args = [];
foreach ($values as $primaryValue) {
$builderPart = clone $builder;
$builderPart->andWhere("%column = %any", $this->joinStorageKey, $primaryValue);
$sqls[] = $builderPart->getQuerySQL();
$args = array_merge($args, $builderPart->getQueryParameters());
}
$query = '(' . implode(') UNION ALL (', $sqls) . ')';
$result = $this->connection->queryArgs($query, $args);
$map = $ids = [];
if ($isComposite) {
foreach ($result as $row) {
$id = [];
foreach ($targetPrimaryKey as $key) {
$id[] = $row->{$key};
}
$ids[] = $id;
$map[$row->{$this->joinStorageKey}][] = implode(',', $id);
}
} else {
$targetPrimaryKey = $targetPrimaryKey[0];
foreach ($result as $row) {
$ids[] = $row->{$targetPrimaryKey};
$map[$row->{$this->joinStorageKey}][] = $row->{$targetPrimaryKey};
}
}
if (count($ids) === 0) {
return new EntityIterator([]);
}
if ($isComposite) {
$builder = $this->targetMapper->builder();
$builder->andWhere('(%column[]) IN %any', $targetPrimaryKey, $ids);
$entitiesResult = [];
$collection = $this->targetMapper->toCollection($builder);
foreach ($collection as $entity) {
$entitiesResult[implode(',', $entity->getValue('id'))] = $entity;
}
} else {
$entitiesResult = $this->targetRepository->findBy(['id' => $ids])->fetchPairs('id', null);
}
$entities = [];
foreach ($map as $joiningStorageKey => $primaryValues) {
foreach ($primaryValues as $primaryValue) {
$entity = $entitiesResult[$primaryValue];
$entities[$entity->getRawValue($this->metadata->relationship->property)][] = $entity;
}
}
return new EntityIterator($entities);
}