Skip to content

Commit

Permalink
Merge pull request #11557 from d-ph/feature/make-count-walker-use-cou…
Browse files Browse the repository at this point in the history
…nt-star-query-sometimes

Make CountWalker use COUNT(*) when $distinct is explicitly set to false (#11552)
  • Loading branch information
greg0ire authored Aug 19, 2024
2 parents 56cd688 + 57247ed commit 5f1fe15
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 16 deletions.
36 changes: 20 additions & 16 deletions src/Tools/Pagination/CountWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,31 @@ public function walkSelectStatement(SelectStatement $selectStatement): void
throw new RuntimeException('Cannot count query which selects two FROM components, cannot make distinction');
}

$fromRoot = reset($from);
$rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable;
$rootClass = $this->getMetadataForDqlAlias($rootAlias);
$identifierFieldName = $rootClass->getSingleIdentifierFieldName();
$distinct = $this->_getQuery()->getHint(self::HINT_DISTINCT);

$pathType = PathExpression::TYPE_STATE_FIELD;
if (isset($rootClass->associationMappings[$identifierFieldName])) {
$pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION;
}
$countPathExpressionOrLiteral = '*';
if ($distinct) {
$fromRoot = reset($from);
$rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable;
$rootClass = $this->getMetadataForDqlAlias($rootAlias);
$identifierFieldName = $rootClass->getSingleIdentifierFieldName();

$pathType = PathExpression::TYPE_STATE_FIELD;
if (isset($rootClass->associationMappings[$identifierFieldName])) {
$pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION;
}

$pathExpression = new PathExpression(
PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION,
$rootAlias,
$identifierFieldName,
);
$pathExpression->type = $pathType;
$countPathExpressionOrLiteral = new PathExpression(
PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION,
$rootAlias,
$identifierFieldName,
);
$countPathExpressionOrLiteral->type = $pathType;
}

$distinct = $this->_getQuery()->getHint(self::HINT_DISTINCT);
$selectStatement->selectClause->selectExpressions = [
new SelectExpression(
new AggregateExpression('count', $pathExpression, $distinct),
new AggregateExpression('count', $countPathExpressionOrLiteral, $distinct),
null,
),
];
Expand Down
14 changes: 14 additions & 0 deletions tests/Tests/ORM/Tools/Pagination/CountWalkerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ public function testCountQuery(): void
);
}

public function testCountQueryWithoutDistinctUsesCountStar(): void
{
$query = $this->entityManager->createQuery(
'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\BlogPost p JOIN p.category c JOIN p.author a',
);
$query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, [CountWalker::class]);
$query->setHint(CountWalker::HINT_DISTINCT, false);

self::assertEquals(
'SELECT count(*) AS sclr_0 FROM BlogPost b0_ INNER JOIN Category c1_ ON b0_.category_id = c1_.id INNER JOIN Author a2_ ON b0_.author_id = a2_.id',
$query->getSQL(),
);
}

public function testCountQueryMixedResultsWithName(): void
{
$query = $this->entityManager->createQuery(
Expand Down

0 comments on commit 5f1fe15

Please sign in to comment.