Skip to content

Commit

Permalink
Merge pull request #3345 from tvt/8.3
Browse files Browse the repository at this point in the history
BUGFIX: Fix count for query across OneToMany joins
  • Loading branch information
Sebobo committed May 13, 2024
2 parents 6f3f5da + 42b1c9d commit 13060b8
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
15 changes: 15 additions & 0 deletions Neos.Flow/Classes/Persistence/Doctrine/CountWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* with this package in the file License-BSD.txt. *
* */

use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Query\AST\AggregateExpression;
use Doctrine\ORM\Query\AST\PathExpression;
use Doctrine\ORM\Query\AST\SelectExpression;
Expand Down Expand Up @@ -40,6 +41,10 @@ public function walkSelectStatement(SelectStatement $AST)
}
}

if ($this->isDistinctRequired()) {
$AST->selectClause->isDistinct = true;
}

$pathExpression = new PathExpression(
PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION,
$parentName,
Expand All @@ -57,4 +62,14 @@ public function walkSelectStatement(SelectStatement $AST)
// ORDER BY is not needed, only increases query execution through unnecessary sorting.
$AST->orderByClause = null;
}

private function isDistinctRequired(): bool
{
foreach ($this->getQueryComponents() as $queryComponent) {
if (isset($queryComponent['relation']['type']) && $queryComponent['relation']['type'] === ClassMetadataInfo::ONE_TO_MANY) {
return true;
}
}
return false;
}
}
39 changes: 39 additions & 0 deletions Neos.Flow/Tests/Functional/Persistence/Doctrine/QueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,45 @@ public function comlexQueryWithJoinsCanBeExecutedAfterDeserialization()
self::assertEquals([$testEntity2], $unserializedQuery->execute()->toArray());
}

/**
* @test
*/
public function countReturnsCorrectNumberOfEntities()
{
$testEntityRepository = new \Neos\Flow\Tests\Functional\Persistence\Fixtures\TestEntityRepository();
$testEntityRepository->removeAll();

$testEntity = new \Neos\Flow\Tests\Functional\Persistence\Fixtures\TestEntity;
$testEntity->setName('Flow');

$subEntity1 = new \Neos\Flow\Tests\Functional\Persistence\Fixtures\SubEntity;
$subEntity1->setContent('foo');
$subEntity1->setParentEntity($testEntity);
$testEntity->addSubEntity($subEntity1);
$this->persistenceManager->add($subEntity1);

$subEntity2 = new \Neos\Flow\Tests\Functional\Persistence\Fixtures\SubEntity;
$subEntity2->setContent('foo');
$subEntity2->setParentEntity($testEntity);
$testEntity->addSubEntity($subEntity2);
$this->persistenceManager->add($subEntity2);

$testEntityRepository->add($testEntity);

$this->persistenceManager->persistAll();

$query = new Query(\Neos\Flow\Tests\Functional\Persistence\Fixtures\TestEntity::class);

$constraint = $query->logicalAnd($query->equals('subEntities.content', 'foo'));
$result = $query->matching($constraint)->execute();

$count = $result->count();
$arrayCount = $result->toArray();

self::assertEquals(1, count($arrayCount), 'This correctly returns 1');
self::assertEquals(1, $count, 'this returns 2');
}

protected function assertQueryEquals(Query $expected, Query $actual)
{
self::assertEquals($expected->getConstraint(), $actual->getConstraint());
Expand Down

0 comments on commit 13060b8

Please sign in to comment.