Passed
Pull Request — 2.6 (#7328)
by
unknown
09:27
created

testPaginationWithSubSelectStripsParametersInSelect()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 12
nc 1
nop 2
dl 0
loc 18
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
namespace Doctrine\Tests\ORM\Functional;
4
5
use Doctrine\ORM\Query;
6
use Doctrine\ORM\Tools\Pagination\Paginator;
7
use Doctrine\Tests\Models\CMS\CmsArticle;
8
use Doctrine\Tests\Models\CMS\CmsEmail;
9
use Doctrine\Tests\Models\CMS\CmsGroup;
10
use Doctrine\Tests\Models\CMS\CmsUser;
11
use Doctrine\Tests\Models\Company\CompanyManager;
12
use Doctrine\Tests\Models\Pagination\Company;
13
use Doctrine\Tests\Models\Pagination\Department;
14
use Doctrine\Tests\Models\Pagination\Logo;
15
use Doctrine\Tests\Models\Pagination\User1;
16
use Doctrine\Tests\OrmFunctionalTestCase;
17
use ReflectionMethod;
18
19
/**
20
 * @group DDC-1613
21
 */
22
class PaginationTest extends OrmFunctionalTestCase
23
{
24
    protected function setUp()
25
    {
26
        $this->useModelSet('cms');
27
        $this->useModelSet('pagination');
28
        $this->useModelSet('company');
29
        parent::setUp();
30
        $this->populate();
31
    }
32
33
    /**
34
     * @dataProvider useOutputWalkers
35
     */
36
    public function testCountSimpleWithoutJoin($useOutputWalkers)
37
    {
38
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u';
39
        $query = $this->_em->createQuery($dql);
40
41
        $paginator = new Paginator($query);
42
        $paginator->setUseOutputWalkers($useOutputWalkers);
43
        $this->assertCount(9, $paginator);
44
    }
45
46
    /**
47
     * @dataProvider useOutputWalkers
48
     */
49
    public function testCountWithFetchJoin($useOutputWalkers)
50
    {
51
        $dql = 'SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g';
52
        $query = $this->_em->createQuery($dql);
53
54
        $paginator = new Paginator($query);
55
        $paginator->setUseOutputWalkers($useOutputWalkers);
56
        $this->assertCount(9, $paginator);
57
    }
58
59
    public function testCountComplexWithOutputWalker()
60
    {
61
        $dql = 'SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g HAVING COUNT(u.id) > 0';
62
        $query = $this->_em->createQuery($dql);
63
64
        $paginator = new Paginator($query);
65
        $paginator->setUseOutputWalkers(true);
66
        $this->assertCount(3, $paginator);
67
    }
68
69
    public function testCountComplexWithoutOutputWalker()
70
    {
71
        $dql = 'SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g HAVING COUNT(u.id) > 0';
72
        $query = $this->_em->createQuery($dql);
73
74
        $paginator = new Paginator($query);
75
        $paginator->setUseOutputWalkers(false);
76
77
        $this->expectException(\RuntimeException::class);
78
        $this->expectExceptionMessage('Cannot count query that uses a HAVING clause. Use the output walkers for pagination');
79
80
        $this->assertCount(3, $paginator);
81
    }
82
83
    /**
84
     * @dataProvider useOutputWalkers
85
     */
86
    public function testCountWithComplexScalarOrderBy($useOutputWalkers)
87
    {
88
        $dql = 'SELECT l FROM Doctrine\Tests\Models\Pagination\Logo l ORDER BY l.image_width * l.image_height DESC';
89
        $query = $this->_em->createQuery($dql);
90
91
        $paginator = new Paginator($query);
92
        $paginator->setUseOutputWalkers($useOutputWalkers);
93
        $this->assertCount(9, $paginator);
94
    }
95
96
    /**
97
     * @dataProvider useOutputWalkersAndFetchJoinCollection
98
     */
99
    public function testIterateSimpleWithoutJoin($useOutputWalkers, $fetchJoinCollection)
100
    {
101
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u';
102
        $query = $this->_em->createQuery($dql);
103
104
        $paginator = new Paginator($query, $fetchJoinCollection);
105
        $paginator->setUseOutputWalkers($useOutputWalkers);
106
        $this->assertCount(9, $paginator->getIterator());
107
108
        // Test with limit
109
        $query->setMaxResults(3);
110
        $paginator = new Paginator($query, $fetchJoinCollection);
111
        $paginator->setUseOutputWalkers($useOutputWalkers);
112
        $this->assertCount(3, $paginator->getIterator());
113
114
        // Test with limit and offset
115
        $query->setMaxResults(3)->setFirstResult(4);
116
        $paginator = new Paginator($query, $fetchJoinCollection);
117
        $paginator->setUseOutputWalkers($useOutputWalkers);
118
        $this->assertCount(3, $paginator->getIterator());
119
    }
120
121
    private function iterateWithOrderAsc($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
122
    {
123
        // Ascending
124
        $dql = "$baseDql ASC";
125
        $query = $this->_em->createQuery($dql);
126
127
        $paginator = new Paginator($query, $fetchJoinCollection);
128
        $paginator->setUseOutputWalkers($useOutputWalkers);
129
        $iter = $paginator->getIterator();
130
        $this->assertCount(9, $iter);
131
        $result = iterator_to_array($iter);
132
        $this->assertEquals($checkField . "0", $result[0]->$checkField);
133
    }
134
135
    private function iterateWithOrderAscWithLimit($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
136
    {
137
        // Ascending
138
        $dql = "$baseDql ASC";
139
        $query = $this->_em->createQuery($dql);
140
141
        // With limit
142
        $query->setMaxResults(3);
143
        $paginator = new Paginator($query, $fetchJoinCollection);
144
        $paginator->setUseOutputWalkers($useOutputWalkers);
145
        $iter = $paginator->getIterator();
146
        $this->assertCount(3, $iter);
147
        $result = iterator_to_array($iter);
148
        $this->assertEquals($checkField . "0", $result[0]->$checkField);
149
    }
150
151
    private function iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
152
    {
153
        // Ascending
154
        $dql = "$baseDql ASC";
155
        $query = $this->_em->createQuery($dql);
156
157
        // With offset
158
        $query->setMaxResults(3)->setFirstResult(3);
159
        $paginator = new Paginator($query, $fetchJoinCollection);
160
        $paginator->setUseOutputWalkers($useOutputWalkers);
161
        $iter = $paginator->getIterator();
162
        $this->assertCount(3, $iter);
163
        $result = iterator_to_array($iter);
164
        $this->assertEquals($checkField . "3", $result[0]->$checkField);
165
    }
166
167
    private function iterateWithOrderDesc($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
168
    {
169
        $dql = "$baseDql DESC";
170
        $query = $this->_em->createQuery($dql);
171
172
        $paginator = new Paginator($query, $fetchJoinCollection);
173
        $paginator->setUseOutputWalkers($useOutputWalkers);
174
        $iter = $paginator->getIterator();
175
        $this->assertCount(9, $iter);
176
        $result = iterator_to_array($iter);
177
        $this->assertEquals($checkField . "8", $result[0]->$checkField);
178
    }
179
180
    private function iterateWithOrderDescWithLimit($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
181
    {
182
        $dql = "$baseDql DESC";
183
        $query = $this->_em->createQuery($dql);
184
185
        // With limit
186
        $query->setMaxResults(3);
187
        $paginator = new Paginator($query, $fetchJoinCollection);
188
        $paginator->setUseOutputWalkers($useOutputWalkers);
189
        $iter = $paginator->getIterator();
190
        $this->assertCount(3, $iter);
191
        $result = iterator_to_array($iter);
192
        $this->assertEquals($checkField . "8", $result[0]->$checkField);
193
    }
194
195
    private function iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $baseDql, $checkField)
196
    {
197
        $dql = "$baseDql DESC";
198
        $query = $this->_em->createQuery($dql);
199
200
        // With offset
201
        $query->setMaxResults(3)->setFirstResult(3);
202
        $paginator = new Paginator($query, $fetchJoinCollection);
203
        $paginator->setUseOutputWalkers($useOutputWalkers);
204
        $iter = $paginator->getIterator();
205
        $this->assertCount(3, $iter);
206
        $result = iterator_to_array($iter);
207
        $this->assertEquals($checkField . "5", $result[0]->$checkField);
208
    }
209
210
    /**
211
     * @dataProvider useOutputWalkersAndFetchJoinCollection
212
     */
213
    public function testIterateSimpleWithoutJoinWithOrder($useOutputWalkers, $fetchJoinCollection)
214
    {
215
        // Ascending
216
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY u.username';
217
        $this->iterateWithOrderAsc($useOutputWalkers, $fetchJoinCollection, $dql, "username");
218
        $this->iterateWithOrderDesc($useOutputWalkers, $fetchJoinCollection, $dql, "username");
219
    }
220
221
    /**
222
     * @dataProvider useOutputWalkersAndFetchJoinCollection
223
     */
224
    public function testIterateSimpleWithoutJoinWithOrderAndLimit($useOutputWalkers, $fetchJoinCollection)
225
    {
226
        // Ascending
227
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY u.username';
228
        $this->iterateWithOrderAscWithLimit($useOutputWalkers, $fetchJoinCollection, $dql, "username");
229
        $this->iterateWithOrderDescWithLimit($useOutputWalkers, $fetchJoinCollection, $dql, "username");
230
    }
231
232
    /**
233
     * @dataProvider useOutputWalkersAndFetchJoinCollection
234
     */
235
    public function testIterateSimpleWithoutJoinWithOrderAndLimitAndOffset($useOutputWalkers, $fetchJoinCollection)
236
    {
237
        // Ascending
238
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u ORDER BY u.username';
239
        $this->iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $dql, "username");
240
        $this->iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $dql, "username");
241
    }
242
243
    /**
244
     * @dataProvider fetchJoinCollection
245
     */
246
    public function testIterateSimpleWithOutputWalkerWithoutJoinWithComplexOrder($fetchJoinCollection)
247
    {
248
        // Ascending
249
        $dql = 'SELECT l FROM Doctrine\Tests\Models\Pagination\Logo l ORDER BY l.image_width * l.image_height';
250
        $this->iterateWithOrderAsc(true, $fetchJoinCollection, $dql, "image");
251
        $this->iterateWithOrderDesc(true, $fetchJoinCollection, $dql, "image");
252
    }
253
254
    /**
255
     * @dataProvider fetchJoinCollection
256
     */
257
    public function testIterateSimpleWithOutputWalkerWithoutJoinWithComplexOrderAndLimit($fetchJoinCollection)
258
    {
259
        // Ascending
260
        $dql = 'SELECT l FROM Doctrine\Tests\Models\Pagination\Logo l ORDER BY l.image_width * l.image_height';
261
        $this->iterateWithOrderAscWithLimit(true, $fetchJoinCollection, $dql, "image");
262
        $this->iterateWithOrderDescWithLimit(true, $fetchJoinCollection, $dql, "image");
263
    }
264
265
    /**
266
     * @dataProvider fetchJoinCollection
267
     */
268
    public function testIterateSimpleWithOutputWalkerWithoutJoinWithComplexOrderAndLimitAndOffset($fetchJoinCollection)
269
    {
270
        // Ascending
271
        $dql = 'SELECT l FROM Doctrine\Tests\Models\Pagination\Logo l ORDER BY l.image_width * l.image_height';
272
        $this->iterateWithOrderAscWithLimitAndOffset(true, $fetchJoinCollection, $dql, "image");
273
        $this->iterateWithOrderDescWithLimitAndOffset(true, $fetchJoinCollection, $dql, "image");
274
    }
275
276
    /**
277
     * @dataProvider useOutputWalkers
278
     */
279
    public function testIterateWithFetchJoin($useOutputWalkers)
280
    {
281
        $dql = 'SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g';
282
        $query = $this->_em->createQuery($dql);
283
284
        $paginator = new Paginator($query, true);
285
        $paginator->setUseOutputWalkers($useOutputWalkers);
286
        $this->assertCount(9, $paginator->getIterator());
287
    }
288
289
    /**
290
     * @dataProvider useOutputWalkers
291
     */
292
    public function testIterateWithFetchJoinWithOrder($useOutputWalkers)
293
    {
294
        $dql = 'SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g ORDER BY u.username';
295
        $this->iterateWithOrderAsc($useOutputWalkers, true, $dql, "username");
296
        $this->iterateWithOrderDesc($useOutputWalkers, true, $dql, "username");
297
    }
298
299
    /**
300
     * @dataProvider useOutputWalkers
301
     */
302
    public function testIterateWithFetchJoinWithOrderAndLimit($useOutputWalkers)
303
    {
304
        $dql = 'SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g ORDER BY u.username';
305
        $this->iterateWithOrderAscWithLimit($useOutputWalkers, true, $dql, "username");
306
        $this->iterateWithOrderDescWithLimit($useOutputWalkers, true, $dql, "username");
307
    }
308
309
    /**
310
     * @dataProvider useOutputWalkers
311
     */
312
    public function testIterateWithFetchJoinWithOrderAndLimitAndOffset($useOutputWalkers)
313
    {
314
        $dql = 'SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g ORDER BY u.username';
315
        $this->iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, true, $dql, "username");
316
        $this->iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, true, $dql, "username");
317
    }
318
319
    /**
320
     * @dataProvider useOutputWalkersAndFetchJoinCollection
321
     */
322
    public function testIterateWithRegularJoinWithOrderByColumnFromJoined($useOutputWalkers, $fetchJoinCollection)
323
    {
324
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e ORDER BY e.email';
325
        $this->iterateWithOrderAsc($useOutputWalkers, $fetchJoinCollection, $dql, "username");
326
        $this->iterateWithOrderDesc($useOutputWalkers, $fetchJoinCollection, $dql, "username");
327
    }
328
329
    /**
330
     * @dataProvider useOutputWalkersAndFetchJoinCollection
331
     */
332
    public function testIterateWithRegularJoinWithOrderByColumnFromJoinedWithLimit($useOutputWalkers, $fetchJoinCollection)
333
    {
334
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e ORDER BY e.email';
335
        $this->iterateWithOrderAscWithLimit($useOutputWalkers, $fetchJoinCollection, $dql, "username");
336
        $this->iterateWithOrderDescWithLimit($useOutputWalkers, $fetchJoinCollection, $dql, "username");
337
    }
338
339
    /**
340
     * @dataProvider useOutputWalkersAndFetchJoinCollection
341
     */
342
    public function testIterateWithRegularJoinWithOrderByColumnFromJoinedWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection)
343
    {
344
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.email e ORDER BY e.email';
345
        $this->iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $dql, "username");
346
        $this->iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, $fetchJoinCollection, $dql, "username");
347
    }
348
349
    /**
350
     * @dataProvider fetchJoinCollection
351
     */
352
    public function testIterateWithOutputWalkersWithRegularJoinWithComplexOrderByReferencingJoined($fetchJoinCollection)
353
    {
354
        // long function name is loooooooooooong
355
356
        $dql = 'SELECT c FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_height * l.image_width';
357
        $this->iterateWithOrderAsc(true, $fetchJoinCollection, $dql, "name");
358
        $this->iterateWithOrderDesc(true, $fetchJoinCollection, $dql, "name");
359
    }
360
361
    /**
362
     * @dataProvider fetchJoinCollection
363
     */
364
    public function testIterateWithOutputWalkersWithRegularJoinWithComplexOrderByReferencingJoinedWithLimit($fetchJoinCollection)
365
    {
366
        // long function name is loooooooooooong
367
368
        $dql = 'SELECT c FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_height * l.image_width';
369
        $this->iterateWithOrderAscWithLimit(true, $fetchJoinCollection, $dql, "name");
370
        $this->iterateWithOrderDescWithLimit(true, $fetchJoinCollection, $dql, "name");
371
    }
372
373
    /**
374
     * @dataProvider fetchJoinCollection
375
     */
376
    public function testIterateWithOutputWalkersWithRegularJoinWithComplexOrderByReferencingJoinedWithLimitAndOffset($fetchJoinCollection)
377
    {
378
        // long function name is loooooooooooong
379
380
        $dql = 'SELECT c FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_height * l.image_width';
381
        $this->iterateWithOrderAscWithLimitAndOffset(true, $fetchJoinCollection, $dql, "name");
382
        $this->iterateWithOrderDescWithLimitAndOffset(true, $fetchJoinCollection, $dql, "name");
383
    }
384
385
    /**
386
     * @dataProvider useOutputWalkers
387
     */
388
    public function testIterateWithFetchJoinWithOrderByColumnFromJoined($useOutputWalkers)
389
    {
390
        $dql = 'SELECT u,g,e FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g JOIN u.email e ORDER BY e.email';
391
        $this->iterateWithOrderAsc($useOutputWalkers, true, $dql, "username");
392
        $this->iterateWithOrderDesc($useOutputWalkers, true, $dql, "username");
393
    }
394
395
    /**
396
     * @dataProvider useOutputWalkers
397
     */
398
    public function testIterateWithFetchJoinWithOrderByColumnFromJoinedWithLimit($useOutputWalkers)
399
    {
400
        $dql = 'SELECT u,g,e FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g JOIN u.email e ORDER BY e.email';
401
        $this->iterateWithOrderAscWithLimit($useOutputWalkers, true, $dql, "username");
402
        $this->iterateWithOrderDescWithLimit($useOutputWalkers, true, $dql, "username");
403
    }
404
405
    /**
406
     * @dataProvider useOutputWalkers
407
     */
408
    public function testIterateWithFetchJoinWithOrderByColumnFromJoinedWithLimitAndOffset($useOutputWalkers)
409
    {
410
        $dql = 'SELECT u,g,e FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g JOIN u.email e ORDER BY e.email';
411
        $this->iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, true, $dql, "username");
412
        $this->iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, true, $dql, "username");
413
    }
414
415
    /**
416
     * @dataProvider fetchJoinCollection
417
     */
418
    public function testIterateWithOutputWalkersWithFetchJoinWithComplexOrderByReferencingJoined($fetchJoinCollection)
419
    {
420
        $dql = 'SELECT c,l FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_width * l.image_height';
421
        $this->iterateWithOrderAsc(true, $fetchJoinCollection, $dql, "name");
422
        $this->iterateWithOrderDesc(true, $fetchJoinCollection, $dql, "name");
423
    }
424
425
    /**
426
     * @dataProvider fetchJoinCollection
427
     */
428
    public function testIterateWithOutputWalkersWithFetchJoinWithComplexOrderByReferencingJoinedWithLimit($fetchJoinCollection)
429
    {
430
        $dql = 'SELECT c,l FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_width * l.image_height';
431
        $this->iterateWithOrderAscWithLimit(true, $fetchJoinCollection, $dql, "name");
432
        $this->iterateWithOrderDescWithLimit(true, $fetchJoinCollection, $dql, "name");
433
    }
434
435
    /**
436
     * @dataProvider fetchJoinCollection
437
     */
438
    public function testIterateWithOutputWalkersWithFetchJoinWithComplexOrderByReferencingJoinedWithLimitAndOffset($fetchJoinCollection)
439
    {
440
        $dql = 'SELECT c,l FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.logo l ORDER BY l.image_width * l.image_height';
441
        $this->iterateWithOrderAscWithLimitAndOffset(true, $fetchJoinCollection, $dql, "name");
442
        $this->iterateWithOrderDescWithLimitAndOffset(true, $fetchJoinCollection, $dql, "name");
443
    }
444
445
    /**
446
     * @dataProvider fetchJoinCollection
447
     */
448
    public function testIterateWithOutputWalkersWithFetchJoinWithComplexOrderByReferencingJoinedWithLimitAndOffsetWithInheritanceType($fetchJoinCollection)
449
    {
450
        $dql = 'SELECT u FROM Doctrine\Tests\Models\Pagination\User u ORDER BY u.id';
451
        $this->iterateWithOrderAscWithLimit(true, $fetchJoinCollection, $dql, "name");
452
        $this->iterateWithOrderDescWithLimit(true, $fetchJoinCollection, $dql, "name");
453
    }
454
455
    public function testIterateComplexWithOutputWalker()
456
    {
457
        $dql = 'SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g HAVING COUNT(u.id) > 0';
458
        $query = $this->_em->createQuery($dql);
459
460
        $paginator = new Paginator($query);
461
        $paginator->setUseOutputWalkers(true);
462
        $this->assertCount(3, $paginator->getIterator());
463
    }
464
465
    public function testJoinedClassTableInheritance()
466
    {
467
        $dql = 'SELECT c FROM Doctrine\Tests\Models\Company\CompanyManager c ORDER BY c.startDate';
468
        $query = $this->_em->createQuery($dql);
469
470
        $paginator = new Paginator($query);
471
        $this->assertCount(1, $paginator->getIterator());
472
    }
473
474
    /**
475
     * @dataProvider useOutputWalkers
476
     */
477
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromBoth($useOutputWalkers)
478
    {
479
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
480
        $dqlAsc = $dql . " ASC, d.name";
481
        $dqlDesc = $dql . " DESC, d.name";
482
        $this->iterateWithOrderAsc($useOutputWalkers, true, $dqlAsc, "name");
483
        $this->iterateWithOrderDesc($useOutputWalkers, true, $dqlDesc, "name");
484
    }
485
486
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromBothWithLimitWithOutputWalker()
487
    {
488
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
489
        $dqlAsc = $dql . " ASC, d.name";
490
        $dqlDesc = $dql . " DESC, d.name";
491
        $this->iterateWithOrderAscWithLimit(true, true, $dqlAsc, "name");
492
        $this->iterateWithOrderDescWithLimit(true, true, $dqlDesc, "name");
493
    }
494
495
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromBothWithLimitWithoutOutputWalker()
496
    {
497
        $this->expectException(\RuntimeException::class);
498
        $this->expectExceptionMessage('Cannot select distinct identifiers from query with LIMIT and ORDER BY on a column from a fetch joined to-many association. Use output walkers.');
499
500
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
501
        $dqlAsc = $dql . " ASC, d.name";
502
        $dqlDesc = $dql . " DESC, d.name";
503
        $this->iterateWithOrderAscWithLimit(false, true, $dqlAsc, "name");
504
        $this->iterateWithOrderDescWithLimit(false, true, $dqlDesc, "name");
505
    }
506
507
    /**
508
     * @dataProvider useOutputWalkers
509
     */
510
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromRoot($useOutputWalkers)
511
    {
512
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
513
        $this->iterateWithOrderAsc($useOutputWalkers, true, $dql, "name");
514
        $this->iterateWithOrderDesc($useOutputWalkers, true, $dql, "name");
515
    }
516
517
    /**
518
     * @dataProvider useOutputWalkers
519
     */
520
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromRootWithLimit($useOutputWalkers)
521
    {
522
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
523
        $this->iterateWithOrderAscWithLimit($useOutputWalkers, true, $dql, "name");
524
        $this->iterateWithOrderDescWithLimit($useOutputWalkers, true, $dql, "name");
525
    }
526
527
    /**
528
     * @dataProvider useOutputWalkers
529
     */
530
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromRootWithLimitAndOffset($useOutputWalkers)
531
    {
532
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY c.name';
533
        $this->iterateWithOrderAscWithLimitAndOffset($useOutputWalkers, true, $dql, "name");
534
        $this->iterateWithOrderDescWithLimitAndOffset($useOutputWalkers, true, $dql, "name");
535
    }
536
537
    /**
538
     * @dataProvider useOutputWalkers
539
     */
540
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromJoined($useOutputWalkers)
541
    {
542
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY d.name';
543
        $this->iterateWithOrderAsc($useOutputWalkers, true, $dql, "name");
544
        $this->iterateWithOrderDesc($useOutputWalkers, true, $dql, "name");
545
    }
546
547
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromJoinedWithLimitWithOutputWalker()
548
    {
549
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY d.name';
550
        $this->iterateWithOrderAscWithLimit(true, true, $dql, "name");
551
        $this->iterateWithOrderDescWithLimit(true, true, $dql, "name");
552
    }
553
554
    public function testIterateWithFetchJoinOneToManyWithOrderByColumnFromJoinedWithLimitWithoutOutputWalker()
555
    {
556
        $this->expectException(\RuntimeException::class);
557
        $this->expectExceptionMessage('Cannot select distinct identifiers from query with LIMIT and ORDER BY on a column from a fetch joined to-many association. Use output walkers.');
558
559
        $dql = 'SELECT c, d FROM Doctrine\Tests\Models\Pagination\Company c JOIN c.departments d ORDER BY d.name';
560
561
        $this->iterateWithOrderAscWithLimit(false, true, $dql, "name");
562
        $this->iterateWithOrderDescWithLimit(false, true, $dql, "name");
563
    }
564
565
    public function testCountWithCountSubqueryInWhereClauseWithOutputWalker()
566
    {
567
        $dql = "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE ((SELECT COUNT(s.id) FROM Doctrine\Tests\Models\CMS\CmsUser s) = 9) ORDER BY u.id desc";
568
        $query = $this->_em->createQuery($dql);
569
570
        $paginator = new Paginator($query, true);
571
        $paginator->setUseOutputWalkers(true);
572
        $this->assertCount(9, $paginator);
573
    }
574
575
    public function testIterateWithCountSubqueryInWhereClause()
576
    {
577
        $dql = "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE ((SELECT COUNT(s.id) FROM Doctrine\Tests\Models\CMS\CmsUser s) = 9) ORDER BY u.id desc";
578
        $query = $this->_em->createQuery($dql);
579
580
        $paginator = new Paginator($query, true);
581
        $paginator->setUseOutputWalkers(true);
582
583
        $users = iterator_to_array($paginator->getIterator());
584
        $this->assertCount(9, $users);
585
        foreach ($users as $i => $user) {
586
            $this->assertEquals("username" . (8 - $i), $user->username);
587
        }
588
    }
589
590
    public function testDetectOutputWalker()
591
    {
592
        // This query works using the output walkers but causes an exception using the TreeWalker
593
        $dql = 'SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g HAVING COUNT(u.id) > 0';
594
        $query = $this->_em->createQuery($dql);
595
596
        // If the Paginator detects the custom output walker it should fall back to using the
597
        // Tree walkers for pagination, which leads to an exception. If the query works, the output walkers were used
598
        $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, Query\SqlWalker::class);
599
        $paginator = new Paginator($query);
600
601
        $this->expectException(\RuntimeException::class);
602
        $this->expectExceptionMessage('Cannot count query that uses a HAVING clause. Use the output walkers for pagination');
603
604
        count($paginator);
605
    }
606
607
    /**
608
     * Test using a paginator when the entity attribute name and corresponding column name are not the same.
609
     */
610
    public function testPaginationWithColumnAttributeNameDifference()
611
    {
612
        $dql = 'SELECT c FROM Doctrine\Tests\Models\Pagination\Company c ORDER BY c.id';
613
        $query = $this->_em->createQuery($dql);
614
615
        $paginator = new Paginator($query);
616
        $paginator->getIterator();
617
618
        $this->assertCount(9, $paginator->getIterator());
619
    }
620
621
    public function testCloneQuery()
622
    {
623
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u';
624
        $query = $this->_em->createQuery($dql);
625
626
        $paginator = new Paginator($query);
627
        $paginator->getIterator();
628
629
        $this->assertTrue($query->getParameters()->isEmpty());
630
    }
631
632
    public function testQueryWalkerIsKept()
633
    {
634
        $dql = 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u';
635
        $query = $this->_em->createQuery($dql);
636
        $query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, [CustomPaginationTestTreeWalker::class]);
637
638
        $paginator = new Paginator($query, true);
639
        $paginator->setUseOutputWalkers(false);
640
        $this->assertCount(1, $paginator->getIterator());
641
        $this->assertEquals(1, $paginator->count());
642
    }
643
644
    public function testCountQueryStripsParametersInSelect()
645
    {
646
        $query = $this->_em->createQuery(
647
            'SELECT u, (CASE WHEN u.id < :vipMaxId THEN 1 ELSE 0 END) AS hidden promotedFirst
648
            FROM Doctrine\\Tests\\Models\\CMS\\CmsUser u
649
            WHERE u.id < :id or 1=1'
650
        );
651
        $query->setParameter('vipMaxId', 10);
652
        $query->setParameter('id', 100);
653
        $query->setFirstResult(null)->setMaxResults(null);
654
655
        $paginator = new Paginator($query);
656
657
        $getCountQuery = new ReflectionMethod($paginator, 'getCountQuery');
658
659
        $getCountQuery->setAccessible(true);
660
661
        $this->assertCount(2, $getCountQuery->invoke($paginator)->getParameters());
662
        $this->assertCount(9, $paginator);
663
664
        $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, Query\SqlWalker::class);
665
666
        $paginator = new Paginator($query);
667
668
        // if select part of query is replaced with count(...) paginator should remove
669
        // parameters from query object not used in new query.
670
        $this->assertCount(1, $getCountQuery->invoke($paginator)->getParameters());
671
        $this->assertCount(9, $paginator);
672
    }
673
674
    /**
675
     * @dataProvider useOutputWalkersAndFetchJoinCollection
676
     */
677
    public function testPaginationWithSubSelectOrderByExpression($useOutputWalker, $fetchJoinCollection)
678
    {
679
        $query = $this->_em->createQuery(
680
            "SELECT u, 
681
                (
682
                    SELECT MAX(a.version)
683
                    FROM Doctrine\\Tests\\Models\\CMS\\CmsArticle a
684
                    WHERE a.user = u
685
                ) AS HIDDEN max_version
686
            FROM Doctrine\\Tests\\Models\\CMS\\CmsUser u
687
            ORDER BY max_version DESC"
688
        );
689
690
        $paginator = new Paginator($query, $fetchJoinCollection);
691
        $paginator->setUseOutputWalkers($useOutputWalker);
692
693
        $this->assertCount(9, $paginator->getIterator());
694
    }
695
696
    /**
697
     * @dataProvider useOutputWalkersAndFetchJoinCollection
698
     */
699
    public function testPaginationWithSubSelectStripsParametersInSelect($useOutputWalker, $fetchJoinCollection)
700
    {
701
        $query = $this->_em->createQuery(
702
            "SELECT u, 
703
                (
704
                    SELECT MAX(a.version)
705
                    FROM Doctrine\\Tests\\Models\\CMS\\CmsArticle a
706
                    WHERE a.user = u AND 1 = :one
707
                ) AS HIDDEN max_version
708
            FROM Doctrine\\Tests\\Models\\CMS\\CmsUser u"
709
        );
710
711
        $query->setParameter('one',1);
712
713
        $paginator = new Paginator($query, $fetchJoinCollection);
714
        $paginator->setUseOutputWalkers($useOutputWalker);
715
716
        $this->assertCount(9, $paginator->getIterator());
717
    }
718
719
720
    public function populate()
721
    {
722
        $groups = [];
723
        for ($j = 0; $j < 3; $j++) {;
724
            $group = new CmsGroup();
725
            $group->name = "group$j";
726
            $groups[] = $group;
727
            $this->_em->persist($group);
728
        }
729
730
        for ($i = 0; $i < 9; $i++) {
731
            $user = new CmsUser();
732
            $user->name = "Name$i";
733
            $user->username = "username$i";
734
            $user->status = "active";
735
            $user->email = new CmsEmail();
736
            $user->email->user = $user;
737
            $user->email->email = "email$i";
738
            for ($j = 0; $j < 3; $j++) {
739
                $user->addGroup($groups[$j]);
740
            }
741
            $this->_em->persist($user);
742
            for ($j = 0; $j < $i + 1; $j++) {
743
                $article = new CmsArticle();
744
                $article->topic = "topic$i$j";
745
                $article->text = "text$i$j";
746
                $article->setAuthor($user);
747
                $article->version = 0;
748
                $this->_em->persist($article);
749
            }
750
        }
751
752
        for ($i = 0; $i < 9; $i++) {
753
            $company = new Company();
754
            $company->name = "name$i";
755
            $company->logo = new Logo();
756
            $company->logo->image = "image$i";
757
            $company->logo->image_width = 100 + $i;
758
            $company->logo->image_height = 100 + $i;
759
            $company->logo->company = $company;
760
            for($j=0;$j<3;$j++) {
761
                $department = new Department();
762
                $department->name = "name$i$j";
763
                $department->company = $company;
764
                $company->departments[] = $department;
765
            }
766
            $this->_em->persist($company);
767
        }
768
769
        for ($i = 0; $i < 9; $i++) {
770
            $user = new User1();
771
            $user->name = "name$i";
772
            $user->email = "email$i";
773
            $this->_em->persist($user);
774
        }
775
776
        $manager = new CompanyManager();
777
        $manager->setName('Roman B.');
778
        $manager->setTitle('Foo');
779
        $manager->setDepartment('IT');
780
        $manager->setSalary(100000);
781
782
        $this->_em->persist($manager);
783
784
        $this->_em->flush();
785
    }
786
787
    public function useOutputWalkers()
788
    {
789
        return [
790
            [true],
791
            [false],
792
        ];
793
    }
794
795
    public function fetchJoinCollection()
796
    {
797
        return [
798
            [true],
799
            [false],
800
        ];
801
    }
802
803
    public function useOutputWalkersAndFetchJoinCollection()
804
    {
805
        return [
806
            [true, false],
807
            [true, true],
808
            [false, false],
809
            [false, true],
810
        ];
811
    }
812
}
813
814
class CustomPaginationTestTreeWalker extends Query\TreeWalkerAdapter
815
{
816
    public function walkSelectStatement(Query\AST\SelectStatement $selectStatement)
817
    {
818
        $condition = new Query\AST\ConditionalPrimary();
819
820
        $path = new Query\AST\PathExpression(Query\AST\PathExpression::TYPE_STATE_FIELD, 'u', 'name');
821
        $path->type = Query\AST\PathExpression::TYPE_STATE_FIELD;
822
823
        $condition->simpleConditionalExpression = new Query\AST\ComparisonExpression(
824
            $path,
825
            '=',
826
            new Query\AST\Literal(Query\AST\Literal::STRING, 'Name1')
827
        );
828
829
        $selectStatement->whereClause = new Query\AST\WhereClause($condition);
0 ignored issues
show
Bug introduced by
$condition of type Doctrine\ORM\Query\AST\ConditionalPrimary is incompatible with the type Doctrine\ORM\Query\AST\ConditionalExpression expected by parameter $conditionalExpression of Doctrine\ORM\Query\AST\WhereClause::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

829
        $selectStatement->whereClause = new Query\AST\WhereClause(/** @scrutinizer ignore-type */ $condition);
Loading history...
830
    }
831
}
832