Skip to content

Commit

Permalink
Replace "WHERE <identifier> IN ( ...subresource... )" via a direct "W…
Browse files Browse the repository at this point in the history
…HERE <identifier = ..." to improve performance
  • Loading branch information
clemherreman committed Feb 19, 2020
1 parent a59af14 commit df4ad61
Showing 1 changed file with 27 additions and 1 deletion.
28 changes: 27 additions & 1 deletion src/Bridge/Doctrine/Orm/SubresourceDataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,16 +198,42 @@ private function buildQuery(array $identifiers, array $context, QueryNameGenerat
->from($identifierResourceClass, $alias);
}

$lastIdentifer = 1 === $remainingIdentifiers;
$association = $classMetadata->hasAssociation($previousAssociationProperty) ? $classMetadata->getAssociationMapping($previousAssociationProperty) : [];
$optimizable = $lastIdentifer && (
(isset($association['inversedBy']) && ClassMetadataInfo::ONE_TO_ONE === $association['type'])
|| (isset($association['mappedBy']) && ClassMetadataInfo::ONE_TO_MANY === $association['type'])
);

// Add where clause for identifiers
foreach ($normalizedIdentifiers as $key => $value) {
$placeholder = $queryNameGenerator->generateParameterName($key);
$qb->andWhere("$alias.$key = :$placeholder");
if ($optimizable) {
// Add where clause for identifiers, but not via a WHERE ... IN ( ...subquery... ). Instead we use
// a direct identifier equality clause, to speed thing up when dealing with large tables.
// We may do so as there is no more recursion levels from here.

if (ClassMetadataInfo::ONE_TO_ONE === $association['type']) {
$joinAlias = $queryNameGenerator->generateJoinAlias($association['inversedBy']);

$previousQueryBuilder->innerJoin("$previousAlias.{$association['inversedBy']}", $joinAlias)
->andWhere("$joinAlias.$key = :$placeholder");
} else {
$previousQueryBuilder->andWhere("IDENTITY($previousAlias) = :$placeholder");
}
} else {
$qb->andWhere("$alias.$key = :$placeholder");
}
$topQueryBuilder->setParameter($placeholder, $value, (string) $classMetadata->getTypeOfField($key));
}

// Recurse queries
$qb = $this->buildQuery($identifiers, $context, $queryNameGenerator, $qb, $alias, --$remainingIdentifiers, $topQueryBuilder);

if ($optimizable) {
return $previousQueryBuilder;
}

return $previousQueryBuilder->andWhere($qb->expr()->in($previousAlias, $qb->getDQL()));
}
}

0 comments on commit df4ad61

Please sign in to comment.