Skip to content

Commit 3d942cc

Browse files
committed
Allow to deactivate fetch join collection
Having this option by default is a good choice since it offers better and more accurate perfomance in many situations. However there is some cases when having the fetch join collection counter productive : like many items retrieved for a simple query without join, as it forces to have 2 queries (first the disctinct, then an IN queries which is worst for performance in heavy table) This commit allow users to set use fetch join collection to false (it still is true by default) in their resource / operation attributes for those special cases.
1 parent 433b84e commit 3d942cc

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

src/Bridge/Doctrine/Orm/Extension/PaginationExtension.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public function supportsResult(string $resourceClass, string $operationName = nu
144144
*/
145145
public function getResult(QueryBuilder $queryBuilder, string $resourceClass = null, string $operationName = null, array $context = [])
146146
{
147-
$doctrineOrmPaginator = new DoctrineOrmPaginator($queryBuilder, $this->useFetchJoinCollection($queryBuilder));
147+
$doctrineOrmPaginator = new DoctrineOrmPaginator($queryBuilder, $this->useFetchJoinCollection($queryBuilder, $resourceClass, $operationName));
148148
$doctrineOrmPaginator->setUseOutputWalkers($this->useOutputWalkers($queryBuilder));
149149

150150
$resourceMetadata = null === $resourceClass ? null : $this->resourceMetadataFactory->create($resourceClass);
@@ -193,14 +193,20 @@ private function isPaginationEnabled(Request $request, ResourceMetadata $resourc
193193
* Determines whether the Paginator should fetch join collections, if the root entity uses composite identifiers it should not.
194194
*
195195
* @see https://github.com/doctrine/doctrine2/issues/2910
196-
*
197-
* @param QueryBuilder $queryBuilder
198-
*
199-
* @return bool
200196
*/
201-
private function useFetchJoinCollection(QueryBuilder $queryBuilder): bool
197+
private function useFetchJoinCollection(QueryBuilder $queryBuilder, string $resourceClass = null, string $operationName = null): bool
202198
{
203-
return !QueryChecker::hasRootEntityWithCompositeIdentifier($queryBuilder, $this->managerRegistry);
199+
if (QueryChecker::hasRootEntityWithCompositeIdentifier($queryBuilder, $this->managerRegistry)) {
200+
return false;
201+
}
202+
203+
if (null === $resourceClass) {
204+
return true;
205+
}
206+
207+
$resourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
208+
209+
return $resourceMetadata->getCollectionOperationAttribute($operationName, 'pagination_fetch_join_collection', true, true);
204210
}
205211

206212
/**

tests/Bridge/Doctrine/Orm/Extension/PaginationExtensionTest.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,14 @@ public function testGetResult()
424424
$this->assertInstanceOf(PaginatorInterface::class, $result);
425425
}
426426

427+
public function testGetResultWithoutFetchJoinCollection()
428+
{
429+
$result = $this->getPaginationExtensionResult(false, false, false);
430+
431+
$this->assertInstanceOf(PartialPaginatorInterface::class, $result);
432+
$this->assertInstanceOf(PaginatorInterface::class, $result);
433+
}
434+
427435
public function testGetResultWithPartial()
428436
{
429437
$result = $this->getPaginationExtensionResult(true);
@@ -440,15 +448,15 @@ public function testSimpleGetResult()
440448
$this->assertInstanceOf(PaginatorInterface::class, $result);
441449
}
442450

443-
private function getPaginationExtensionResult(bool $partial = false, bool $legacy = false)
451+
private function getPaginationExtensionResult(bool $partial = false, bool $legacy = false, bool $fetchJoinCollection = true)
444452
{
445453
$requestStack = new RequestStack();
446454
$requestStack->push(new Request(['partial' => $partial]));
447455

448456
$resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class);
449457

450458
if (!$legacy) {
451-
$resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], ['pagination_partial' => false, 'pagination_client_partial' => true]))->shouldBeCalled();
459+
$resourceMetadataFactoryProphecy->create('Foo')->willReturn(new ResourceMetadata(null, null, null, [], [], ['pagination_partial' => false, 'pagination_client_partial' => true, 'pagination_fetch_join_collection' => $fetchJoinCollection]))->shouldBeCalled();
452460
}
453461

454462
$configuration = new Configuration();

0 commit comments

Comments
 (0)