File tree Expand file tree Collapse file tree 4 files changed +38
-3
lines changed Expand file tree Collapse file tree 4 files changed +38
-3
lines changed Original file line number Diff line number Diff line change @@ -43,3 +43,18 @@ the future.
43
43
.. note ::
44
44
45
45
``fetchJoinCollection `` argument set to ``true `` might affect results if you use aggregations in your query.
46
+
47
+ By using the ``Paginator::HINT_ENABLE_DISTINCT `` you can instruct doctrine that the query to be executed
48
+ will not produce "duplicate" rows (only to-one relations are joined), thus the SQL limit will work as expected.
49
+ In this way the `DISTINCT ` keyword will be omitted and can bring important performance improvements.
50
+
51
+ .. code-block :: php
52
+
53
+ <?php
54
+ use Doctrine\ORM\Tools\Pagination\Paginator;
55
+
56
+ $dql = "SELECT u, p FROM User u JOIN u.mainPicture p";
57
+ $query = $entityManager->createQuery($dql)
58
+ ->setHint(Paginator::HINT_ENABLE_DISTINCT, false)
59
+ ->setFirstResult(0)
60
+ ->setMaxResults(100);
Original file line number Diff line number Diff line change @@ -50,12 +50,14 @@ public function walkSelectStatement(SelectStatement $AST)
50
50
throw new RuntimeException ('Paginating an entity with foreign key as identifier only works when using the Output Walkers. Call Paginator#setUseOutputWalkers(true) before iterating the paginator. ' );
51
51
}
52
52
53
- $ this ->_getQuery ()->setHint (
53
+ $ query = $ this ->_getQuery ();
54
+
55
+ $ query ->setHint (
54
56
self ::IDENTIFIER_TYPE ,
55
57
Type::getType ($ rootClass ->fieldMappings [$ identifier ]['type ' ])
56
58
);
57
59
58
- $ this -> _getQuery () ->setHint (self ::FORCE_DBAL_TYPE_CONVERSION , true );
60
+ $ query ->setHint (self ::FORCE_DBAL_TYPE_CONVERSION , true );
59
61
60
62
$ pathExpression = new PathExpression (
61
63
PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION ,
@@ -66,7 +68,7 @@ public function walkSelectStatement(SelectStatement $AST)
66
68
$ pathExpression ->type = PathExpression::TYPE_STATE_FIELD ;
67
69
68
70
$ AST ->selectClause ->selectExpressions = [new SelectExpression ($ pathExpression , '_dctrn_id ' )];
69
- $ AST ->selectClause ->isDistinct = true ;
71
+ $ AST ->selectClause ->isDistinct = ( $ query -> getHints ()[Paginator:: HINT_ENABLE_DISTINCT ] ?? true ) === true ;
70
72
71
73
if (! isset ($ AST ->orderByClause )) {
72
74
return ;
Original file line number Diff line number Diff line change @@ -34,6 +34,8 @@ class Paginator implements Countable, IteratorAggregate
34
34
{
35
35
use SQLResultCasing;
36
36
37
+ public const HINT_ENABLE_DISTINCT = 'paginator.distinct.enable ' ;
38
+
37
39
/** @var Query */
38
40
private $ query ;
39
41
Original file line number Diff line number Diff line change 6
6
7
7
use Doctrine \ORM \Query ;
8
8
use Doctrine \ORM \Tools \Pagination \LimitSubqueryWalker ;
9
+ use Doctrine \ORM \Tools \Pagination \Paginator ;
9
10
10
11
/** @group DDC-1613 */
11
12
class LimitSubqueryWalkerTest extends PaginationTestCase
@@ -24,6 +25,21 @@ public function testLimitSubquery(): void
24
25
);
25
26
}
26
27
28
+ public function testHintCanDisableDistinct (): void
29
+ {
30
+ $ dql = 'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a ' ;
31
+ $ query = $ this ->entityManager ->createQuery ($ dql );
32
+ $ limitQuery = clone $ query ;
33
+
34
+ $ limitQuery ->setHint (Query::HINT_CUSTOM_TREE_WALKERS , [LimitSubqueryWalker::class]);
35
+ $ limitQuery ->setHint (Paginator::HINT_ENABLE_DISTINCT , false );
36
+
37
+ self ::assertEquals (
38
+ 'SELECT m0_.id AS id_0 FROM MyBlogPost m0_ INNER JOIN Category c1_ ON m0_.category_id = c1_.id INNER JOIN Author a2_ ON m0_.author_id = a2_.id ' ,
39
+ $ limitQuery ->getSQL ()
40
+ );
41
+ }
42
+
27
43
public function testLimitSubqueryWithSort (): void
28
44
{
29
45
$ dql = 'SELECT p, c, a FROM Doctrine\Tests\ORM\Tools\Pagination\MyBlogPost p JOIN p.category c JOIN p.author a ORDER BY p.title ' ;
You can’t perform that action at this time.
0 commit comments