Completed
Pull Request — master (#3685)
by
unknown
62:27
created

QueryBuilderTest::testSelectEmptyGroupBy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 10
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Tests\DBAL\Query;
4
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\ParameterType;
7
use Doctrine\DBAL\Query\Expression\ExpressionBuilder;
8
use Doctrine\DBAL\Query\QueryBuilder;
9
use Doctrine\DBAL\Query\QueryException;
10
use Doctrine\Tests\DbalTestCase;
11
12
/**
13
 * @group DBAL-12
14
 */
15
class QueryBuilderTest extends DbalTestCase
16
{
17
    /** @var Connection */
18
    protected $conn;
19
20
    protected function setUp() : void
21
    {
22
        $this->conn = $this->createMock(Connection::class);
23
24
        $expressionBuilder = new ExpressionBuilder($this->conn);
25
26
        $this->conn->expects($this->any())
27
                   ->method('getExpressionBuilder')
28
                   ->will($this->returnValue($expressionBuilder));
29
    }
30
31
    /**
32
     * @group DBAL-2291
33
     */
34
    public function testSimpleSelectWithoutFrom() : void
35
    {
36
        $qb = new QueryBuilder($this->conn);
37
38
        $qb->select('some_function()');
39
40
        self::assertEquals('SELECT some_function()', (string) $qb);
41
    }
42
43
    public function testSimpleSelect() : void
44
    {
45
        $qb = new QueryBuilder($this->conn);
46
47
        $qb->select('u.id')
48
           ->from('users', 'u');
49
50
        self::assertEquals('SELECT u.id FROM users u', (string) $qb);
51
    }
52
53
    public function testSelectWithSimpleWhere() : void
54
    {
55
        $qb   = new QueryBuilder($this->conn);
56
        $expr = $qb->expr();
57
58
        $qb->select('u.id')
59
           ->from('users', 'u')
60
           ->where($expr->andX($expr->eq('u.nickname', '?')));
61
62
        self::assertEquals('SELECT u.id FROM users u WHERE u.nickname = ?', (string) $qb);
63
    }
64
65
    public function testSelectWithLeftJoin() : void
66
    {
67
        $qb   = new QueryBuilder($this->conn);
68
        $expr = $qb->expr();
69
70
        $qb->select('u.*', 'p.*')
71
           ->from('users', 'u')
72
           ->leftJoin('u', 'phones', 'p', $expr->eq('p.user_id', 'u.id'));
73
74
        self::assertEquals('SELECT u.*, p.* FROM users u LEFT JOIN phones p ON p.user_id = u.id', (string) $qb);
75
    }
76
77
    public function testSelectWithJoin() : void
78
    {
79
        $qb   = new QueryBuilder($this->conn);
80
        $expr = $qb->expr();
81
82
        $qb->select('u.*', 'p.*')
83
           ->from('users', 'u')
84
           ->Join('u', 'phones', 'p', $expr->eq('p.user_id', 'u.id'));
85
86
        self::assertEquals('SELECT u.*, p.* FROM users u INNER JOIN phones p ON p.user_id = u.id', (string) $qb);
87
    }
88
89
    public function testSelectWithInnerJoin() : void
90
    {
91
        $qb   = new QueryBuilder($this->conn);
92
        $expr = $qb->expr();
93
94
        $qb->select('u.*', 'p.*')
95
           ->from('users', 'u')
96
           ->innerJoin('u', 'phones', 'p', $expr->eq('p.user_id', 'u.id'));
97
98
        self::assertEquals('SELECT u.*, p.* FROM users u INNER JOIN phones p ON p.user_id = u.id', (string) $qb);
99
    }
100
101
    public function testSelectWithRightJoin() : void
102
    {
103
        $qb   = new QueryBuilder($this->conn);
104
        $expr = $qb->expr();
105
106
        $qb->select('u.*', 'p.*')
107
           ->from('users', 'u')
108
           ->rightJoin('u', 'phones', 'p', $expr->eq('p.user_id', 'u.id'));
109
110
        self::assertEquals('SELECT u.*, p.* FROM users u RIGHT JOIN phones p ON p.user_id = u.id', (string) $qb);
111
    }
112
113
    public function testSelectWithAndWhereConditions() : void
114
    {
115
        $qb   = new QueryBuilder($this->conn);
116
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
117
118
        $qb->select('u.*', 'p.*')
119
           ->from('users', 'u')
120
           ->where('u.username = ?')
121
           ->andWhere('u.name = ?');
122
123
        self::assertEquals('SELECT u.*, p.* FROM users u WHERE (u.username = ?) AND (u.name = ?)', (string) $qb);
124
    }
125
126
    public function testSelectWithOrWhereConditions() : void
127
    {
128
        $qb   = new QueryBuilder($this->conn);
129
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
130
131
        $qb->select('u.*', 'p.*')
132
           ->from('users', 'u')
133
           ->where('u.username = ?')
134
           ->orWhere('u.name = ?');
135
136
        self::assertEquals('SELECT u.*, p.* FROM users u WHERE (u.username = ?) OR (u.name = ?)', (string) $qb);
137
    }
138
139
    public function testSelectWithOrOrWhereConditions() : void
140
    {
141
        $qb   = new QueryBuilder($this->conn);
142
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
143
144
        $qb->select('u.*', 'p.*')
145
           ->from('users', 'u')
146
           ->orWhere('u.username = ?')
147
           ->orWhere('u.name = ?');
148
149
        self::assertEquals('SELECT u.*, p.* FROM users u WHERE (u.username = ?) OR (u.name = ?)', (string) $qb);
150
    }
151
152
    public function testSelectWithAndOrWhereConditions() : void
153
    {
154
        $qb   = new QueryBuilder($this->conn);
155
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
156
157
        $qb->select('u.*', 'p.*')
158
           ->from('users', 'u')
159
           ->where('u.username = ?')
160
           ->andWhere('u.username = ?')
161
           ->orWhere('u.name = ?')
162
           ->andWhere('u.name = ?');
163
164
        self::assertEquals('SELECT u.*, p.* FROM users u WHERE (((u.username = ?) AND (u.username = ?)) OR (u.name = ?)) AND (u.name = ?)', (string) $qb);
165
    }
166
167
    public function testSelectGroupBy() : void
168
    {
169
        $qb   = new QueryBuilder($this->conn);
170
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
171
172
        $qb->select('u.*', 'p.*')
173
           ->from('users', 'u')
174
           ->groupBy('u.id');
175
176
        self::assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id', (string) $qb);
177
    }
178
179
    public function testSelectEmptyGroupBy() : void
180
    {
181
        $qb   = new QueryBuilder($this->conn);
182
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
183
184
        $qb->select('u.*', 'p.*')
185
           ->groupBy([])
186
           ->from('users', 'u');
187
188
        self::assertEquals('SELECT u.*, p.* FROM users u', (string) $qb);
189
    }
190
191
    public function testSelectEmptyAddGroupBy() : void
192
    {
193
        $qb   = new QueryBuilder($this->conn);
194
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
195
196
        $qb->select('u.*', 'p.*')
197
           ->addGroupBy([])
198
           ->from('users', 'u');
199
200
        self::assertEquals('SELECT u.*, p.* FROM users u', (string) $qb);
201
    }
202
203
    public function testSelectAddGroupBy() : void
204
    {
205
        $qb   = new QueryBuilder($this->conn);
206
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
207
208
        $qb->select('u.*', 'p.*')
209
           ->from('users', 'u')
210
           ->groupBy('u.id')
211
           ->addGroupBy('u.foo');
212
213
        self::assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id, u.foo', (string) $qb);
214
    }
215
216
    public function testSelectAddGroupBys() : void
217
    {
218
        $qb   = new QueryBuilder($this->conn);
219
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
220
221
        $qb->select('u.*', 'p.*')
222
           ->from('users', 'u')
223
           ->groupBy('u.id')
224
           ->addGroupBy('u.foo', 'u.bar');
225
226
        self::assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id, u.foo, u.bar', (string) $qb);
227
    }
228
229
    public function testSelectHaving() : void
230
    {
231
        $qb   = new QueryBuilder($this->conn);
232
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
233
234
        $qb->select('u.*', 'p.*')
235
           ->from('users', 'u')
236
           ->groupBy('u.id')
237
           ->having('u.name = ?');
238
239
        self::assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING u.name = ?', (string) $qb);
240
    }
241
242
    public function testSelectAndHaving() : void
243
    {
244
        $qb   = new QueryBuilder($this->conn);
245
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
246
247
        $qb->select('u.*', 'p.*')
248
           ->from('users', 'u')
249
           ->groupBy('u.id')
250
           ->andHaving('u.name = ?');
251
252
        self::assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING u.name = ?', (string) $qb);
253
    }
254
255
    public function testSelectHavingAndHaving() : void
256
    {
257
        $qb   = new QueryBuilder($this->conn);
258
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
259
260
        $qb->select('u.*', 'p.*')
261
           ->from('users', 'u')
262
           ->groupBy('u.id')
263
           ->having('u.name = ?')
264
           ->andHaving('u.username = ?');
265
266
        self::assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING (u.name = ?) AND (u.username = ?)', (string) $qb);
267
    }
268
269
    public function testSelectHavingOrHaving() : void
270
    {
271
        $qb   = new QueryBuilder($this->conn);
272
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
273
274
        $qb->select('u.*', 'p.*')
275
           ->from('users', 'u')
276
           ->groupBy('u.id')
277
           ->having('u.name = ?')
278
           ->orHaving('u.username = ?');
279
280
        self::assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING (u.name = ?) OR (u.username = ?)', (string) $qb);
281
    }
282
283
    public function testSelectOrHavingOrHaving() : void
284
    {
285
        $qb   = new QueryBuilder($this->conn);
286
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
287
288
        $qb->select('u.*', 'p.*')
289
           ->from('users', 'u')
290
           ->groupBy('u.id')
291
           ->orHaving('u.name = ?')
292
           ->orHaving('u.username = ?');
293
294
        self::assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING (u.name = ?) OR (u.username = ?)', (string) $qb);
295
    }
296
297
    public function testSelectHavingAndOrHaving() : void
298
    {
299
        $qb   = new QueryBuilder($this->conn);
300
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
301
302
        $qb->select('u.*', 'p.*')
303
           ->from('users', 'u')
304
           ->groupBy('u.id')
305
           ->having('u.name = ?')
306
           ->orHaving('u.username = ?')
307
           ->andHaving('u.username = ?');
308
309
        self::assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING ((u.name = ?) OR (u.username = ?)) AND (u.username = ?)', (string) $qb);
310
    }
311
312
    public function testSelectOrderBy() : void
313
    {
314
        $qb   = new QueryBuilder($this->conn);
315
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
316
317
        $qb->select('u.*', 'p.*')
318
           ->from('users', 'u')
319
           ->orderBy('u.name');
320
321
        self::assertEquals('SELECT u.*, p.* FROM users u ORDER BY u.name ASC', (string) $qb);
322
    }
323
324
    public function testSelectAddOrderBy() : void
325
    {
326
        $qb   = new QueryBuilder($this->conn);
327
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
328
329
        $qb->select('u.*', 'p.*')
330
           ->from('users', 'u')
331
           ->orderBy('u.name')
332
           ->addOrderBy('u.username', 'DESC');
333
334
        self::assertEquals('SELECT u.*, p.* FROM users u ORDER BY u.name ASC, u.username DESC', (string) $qb);
335
    }
336
337
    public function testSelectAddAddOrderBy() : void
338
    {
339
        $qb   = new QueryBuilder($this->conn);
340
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
341
342
        $qb->select('u.*', 'p.*')
343
           ->from('users', 'u')
344
           ->addOrderBy('u.name')
345
           ->addOrderBy('u.username', 'DESC');
346
347
        self::assertEquals('SELECT u.*, p.* FROM users u ORDER BY u.name ASC, u.username DESC', (string) $qb);
348
    }
349
350
    public function testEmptySelect() : void
351
    {
352
        $qb  = new QueryBuilder($this->conn);
353
        $qb2 = $qb->select();
354
355
        self::assertSame($qb, $qb2);
356
        self::assertEquals(QueryBuilder::SELECT, $qb->getType());
357
    }
358
359
    public function testSelectAddSelect() : void
360
    {
361
        $qb   = new QueryBuilder($this->conn);
362
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
363
364
        $qb->select('u.*')
365
           ->addSelect('p.*')
366
           ->from('users', 'u');
367
368
        self::assertEquals('SELECT u.*, p.* FROM users u', (string) $qb);
369
    }
370
371
    public function testEmptyAddSelect() : void
372
    {
373
        $qb  = new QueryBuilder($this->conn);
374
        $qb2 = $qb->addSelect();
375
376
        self::assertSame($qb, $qb2);
377
        self::assertEquals(QueryBuilder::SELECT, $qb->getType());
378
    }
379
380
    public function testSelectMultipleFrom() : void
381
    {
382
        $qb   = new QueryBuilder($this->conn);
383
        $expr = $qb->expr();
0 ignored issues
show
Unused Code introduced by
The assignment to $expr is dead and can be removed.
Loading history...
384
385
        $qb->select('u.*')
386
           ->addSelect('p.*')
387
           ->from('users', 'u')
388
           ->from('phonenumbers', 'p');
389
390
        self::assertEquals('SELECT u.*, p.* FROM users u, phonenumbers p', (string) $qb);
391
    }
392
393
    public function testUpdate() : void
394
    {
395
        $qb = new QueryBuilder($this->conn);
396
        $qb->update('users', 'u')
397
           ->set('u.foo', '?')
398
           ->set('u.bar', '?');
399
400
        self::assertEquals(QueryBuilder::UPDATE, $qb->getType());
401
        self::assertEquals('UPDATE users u SET u.foo = ?, u.bar = ?', (string) $qb);
402
    }
403
404
    public function testUpdateWithoutAlias() : void
405
    {
406
        $qb = new QueryBuilder($this->conn);
407
        $qb->update('users')
408
           ->set('foo', '?')
409
           ->set('bar', '?');
410
411
        self::assertEquals('UPDATE users SET foo = ?, bar = ?', (string) $qb);
412
    }
413
414
    public function testUpdateWhere() : void
415
    {
416
        $qb = new QueryBuilder($this->conn);
417
        $qb->update('users', 'u')
418
           ->set('u.foo', '?')
419
           ->where('u.foo = ?');
420
421
        self::assertEquals('UPDATE users u SET u.foo = ? WHERE u.foo = ?', (string) $qb);
422
    }
423
424
    public function testEmptyUpdate() : void
425
    {
426
        $qb  = new QueryBuilder($this->conn);
427
        $qb2 = $qb->update();
428
429
        self::assertEquals(QueryBuilder::UPDATE, $qb->getType());
430
        self::assertSame($qb2, $qb);
431
    }
432
433
    public function testDelete() : void
434
    {
435
        $qb = new QueryBuilder($this->conn);
436
        $qb->delete('users', 'u');
437
438
        self::assertEquals(QueryBuilder::DELETE, $qb->getType());
439
        self::assertEquals('DELETE FROM users u', (string) $qb);
440
    }
441
442
    public function testDeleteWithoutAlias() : void
443
    {
444
        $qb = new QueryBuilder($this->conn);
445
        $qb->delete('users');
446
447
        self::assertEquals(QueryBuilder::DELETE, $qb->getType());
448
        self::assertEquals('DELETE FROM users', (string) $qb);
449
    }
450
451
    public function testDeleteWhere() : void
452
    {
453
        $qb = new QueryBuilder($this->conn);
454
        $qb->delete('users', 'u')
455
           ->where('u.foo = ?');
456
457
        self::assertEquals('DELETE FROM users u WHERE u.foo = ?', (string) $qb);
458
    }
459
460
    public function testEmptyDelete() : void
461
    {
462
        $qb  = new QueryBuilder($this->conn);
463
        $qb2 = $qb->delete();
464
465
        self::assertEquals(QueryBuilder::DELETE, $qb->getType());
466
        self::assertSame($qb2, $qb);
467
    }
468
469
    public function testInsertValues() : void
470
    {
471
        $qb = new QueryBuilder($this->conn);
472
        $qb->insert('users')
473
            ->values(
474
                [
475
                    'foo' => '?',
476
                    'bar' => '?',
477
                ]
478
            );
479
480
        self::assertEquals(QueryBuilder::INSERT, $qb->getType());
481
        self::assertEquals('INSERT INTO users (foo, bar) VALUES(?, ?)', (string) $qb);
482
    }
483
484
    public function testInsertReplaceValues() : void
485
    {
486
        $qb = new QueryBuilder($this->conn);
487
        $qb->insert('users')
488
            ->values(
489
                [
490
                    'foo' => '?',
491
                    'bar' => '?',
492
                ]
493
            )
494
            ->values(
495
                [
496
                    'bar' => '?',
497
                    'foo' => '?',
498
                ]
499
            );
500
501
        self::assertEquals(QueryBuilder::INSERT, $qb->getType());
502
        self::assertEquals('INSERT INTO users (bar, foo) VALUES(?, ?)', (string) $qb);
503
    }
504
505
    public function testInsertSetValue() : void
506
    {
507
        $qb = new QueryBuilder($this->conn);
508
        $qb->insert('users')
509
            ->setValue('foo', 'bar')
510
            ->setValue('bar', '?')
511
            ->setValue('foo', '?');
512
513
        self::assertEquals(QueryBuilder::INSERT, $qb->getType());
514
        self::assertEquals('INSERT INTO users (foo, bar) VALUES(?, ?)', (string) $qb);
515
    }
516
517
    public function testInsertValuesSetValue() : void
518
    {
519
        $qb = new QueryBuilder($this->conn);
520
        $qb->insert('users')
521
            ->values(
522
                ['foo' => '?']
523
            )
524
            ->setValue('bar', '?');
525
526
        self::assertEquals(QueryBuilder::INSERT, $qb->getType());
527
        self::assertEquals('INSERT INTO users (foo, bar) VALUES(?, ?)', (string) $qb);
528
    }
529
530
    public function testEmptyInsert() : void
531
    {
532
        $qb  = new QueryBuilder($this->conn);
533
        $qb2 = $qb->insert();
534
535
        self::assertEquals(QueryBuilder::INSERT, $qb->getType());
536
        self::assertSame($qb2, $qb);
537
    }
538
539
    public function testGetConnection() : void
540
    {
541
        $qb = new QueryBuilder($this->conn);
542
        self::assertSame($this->conn, $qb->getConnection());
543
    }
544
545
    public function testGetState() : void
546
    {
547
        $qb = new QueryBuilder($this->conn);
548
549
        self::assertEquals(QueryBuilder::STATE_CLEAN, $qb->getState());
550
551
        $qb->select('u.*')->from('users', 'u');
552
553
        self::assertEquals(QueryBuilder::STATE_DIRTY, $qb->getState());
554
555
        $sql1 = $qb->getSQL();
556
557
        self::assertEquals(QueryBuilder::STATE_CLEAN, $qb->getState());
558
        self::assertEquals($sql1, $qb->getSQL());
559
    }
560
561
    public function testSetMaxResults() : void
562
    {
563
        $qb = new QueryBuilder($this->conn);
564
        $qb->setMaxResults(10);
565
566
        self::assertEquals(QueryBuilder::STATE_DIRTY, $qb->getState());
567
        self::assertEquals(10, $qb->getMaxResults());
568
    }
569
570
    public function testSetFirstResult() : void
571
    {
572
        $qb = new QueryBuilder($this->conn);
573
        $qb->setFirstResult(10);
574
575
        self::assertEquals(QueryBuilder::STATE_DIRTY, $qb->getState());
576
        self::assertEquals(10, $qb->getFirstResult());
577
    }
578
579
    public function testResetQueryPart() : void
580
    {
581
        $qb = new QueryBuilder($this->conn);
582
583
        $qb->select('u.*')->from('users', 'u')->where('u.name = ?');
584
585
        self::assertEquals('SELECT u.* FROM users u WHERE u.name = ?', (string) $qb);
586
        $qb->resetQueryPart('where');
587
        self::assertEquals('SELECT u.* FROM users u', (string) $qb);
588
    }
589
590
    public function testResetQueryParts() : void
591
    {
592
        $qb = new QueryBuilder($this->conn);
593
594
        $qb->select('u.*')->from('users', 'u')->where('u.name = ?')->orderBy('u.name');
595
596
        self::assertEquals('SELECT u.* FROM users u WHERE u.name = ? ORDER BY u.name ASC', (string) $qb);
597
        $qb->resetQueryParts(['where', 'orderBy']);
598
        self::assertEquals('SELECT u.* FROM users u', (string) $qb);
599
    }
600
601
    public function testCreateNamedParameter() : void
602
    {
603
        $qb = new QueryBuilder($this->conn);
604
605
        $qb->select('u.*')->from('users', 'u')->where(
606
            $qb->expr()->eq('u.name', $qb->createNamedParameter(10, ParameterType::INTEGER))
607
        );
608
609
        self::assertEquals('SELECT u.* FROM users u WHERE u.name = :dcValue1', (string) $qb);
610
        self::assertEquals(10, $qb->getParameter('dcValue1'));
611
        self::assertEquals(ParameterType::INTEGER, $qb->getParameterType('dcValue1'));
612
    }
613
614
    public function testCreateNamedParameterCustomPlaceholder() : void
615
    {
616
        $qb = new QueryBuilder($this->conn);
617
618
        $qb->select('u.*')->from('users', 'u')->where(
619
            $qb->expr()->eq('u.name', $qb->createNamedParameter(10, ParameterType::INTEGER, ':test'))
620
        );
621
622
        self::assertEquals('SELECT u.* FROM users u WHERE u.name = :test', (string) $qb);
623
        self::assertEquals(10, $qb->getParameter('test'));
624
        self::assertEquals(ParameterType::INTEGER, $qb->getParameterType('test'));
625
    }
626
627
    public function testCreatePositionalParameter() : void
628
    {
629
        $qb = new QueryBuilder($this->conn);
630
631
        $qb->select('u.*')->from('users', 'u')->where(
632
            $qb->expr()->eq('u.name', $qb->createPositionalParameter(10, ParameterType::INTEGER))
633
        );
634
635
        self::assertEquals('SELECT u.* FROM users u WHERE u.name = ?', (string) $qb);
636
        self::assertEquals(10, $qb->getParameter(1));
637
        self::assertEquals(ParameterType::INTEGER, $qb->getParameterType(1));
638
    }
639
640
    /**
641
     * @group DBAL-172
642
     */
643
    public function testReferenceJoinFromJoin() : void
644
    {
645
        $qb = new QueryBuilder($this->conn);
646
647
        $qb->select('COUNT(DISTINCT news.id)')
648
            ->from('cb_newspages', 'news')
649
            ->innerJoin('news', 'nodeversion', 'nv', 'nv.refId = news.id AND nv.refEntityname=\'News\'')
650
            ->innerJoin('invalid', 'nodetranslation', 'nt', 'nv.nodetranslation = nt.id')
651
            ->innerJoin('nt', 'node', 'n', 'nt.node = n.id')
652
            ->where('nt.lang = :lang AND n.deleted != 1');
653
654
        $this->expectException(QueryException::class);
655
        $this->expectExceptionMessage("The given alias 'invalid' is not part of any FROM or JOIN clause table. The currently registered aliases are: news, nv.");
656
        self::assertEquals('', $qb->getSQL());
657
    }
658
659
    /**
660
     * @group DBAL-172
661
     */
662
    public function testSelectFromMasterWithWhereOnJoinedTables() : void
663
    {
664
        $qb = new QueryBuilder($this->conn);
665
666
        $qb->select('COUNT(DISTINCT news.id)')
667
            ->from('newspages', 'news')
668
            ->innerJoin('news', 'nodeversion', 'nv', "nv.refId = news.id AND nv.refEntityname='Entity\\News'")
669
            ->innerJoin('nv', 'nodetranslation', 'nt', 'nv.nodetranslation = nt.id')
670
            ->innerJoin('nt', 'node', 'n', 'nt.node = n.id')
671
            ->where('nt.lang = ?')
672
            ->andWhere('n.deleted = 0');
673
674
        self::assertEquals("SELECT COUNT(DISTINCT news.id) FROM newspages news INNER JOIN nodeversion nv ON nv.refId = news.id AND nv.refEntityname='Entity\\News' INNER JOIN nodetranslation nt ON nv.nodetranslation = nt.id INNER JOIN node n ON nt.node = n.id WHERE (nt.lang = ?) AND (n.deleted = 0)", $qb->getSQL());
675
    }
676
677
    /**
678
     * @group DBAL-442
679
     */
680
    public function testSelectWithMultipleFromAndJoins() : void
681
    {
682
        $qb = new QueryBuilder($this->conn);
683
684
        $qb->select('DISTINCT u.id')
685
            ->from('users', 'u')
686
            ->from('articles', 'a')
687
            ->innerJoin('u', 'permissions', 'p', 'p.user_id = u.id')
688
            ->innerJoin('a', 'comments', 'c', 'c.article_id = a.id')
689
            ->where('u.id = a.user_id')
690
            ->andWhere('p.read = 1');
691
692
        self::assertEquals('SELECT DISTINCT u.id FROM users u INNER JOIN permissions p ON p.user_id = u.id, articles a INNER JOIN comments c ON c.article_id = a.id WHERE (u.id = a.user_id) AND (p.read = 1)', $qb->getSQL());
693
    }
694
695
    /**
696
     * @group DBAL-774
697
     */
698
    public function testSelectWithJoinsWithMultipleOnConditionsParseOrder() : void
699
    {
700
        $qb = new QueryBuilder($this->conn);
701
702
        $qb->select('a.id')
703
            ->from('table_a', 'a')
704
            ->join('a', 'table_b', 'b', 'a.fk_b = b.id')
705
            ->join('b', 'table_c', 'c', 'c.fk_b = b.id AND b.language = ?')
706
            ->join('a', 'table_d', 'd', 'a.fk_d = d.id')
707
            ->join('c', 'table_e', 'e', 'e.fk_c = c.id AND e.fk_d = d.id');
708
709
        self::assertEquals(
710
            'SELECT a.id ' .
711
            'FROM table_a a ' .
712
            'INNER JOIN table_b b ON a.fk_b = b.id ' .
713
            'INNER JOIN table_d d ON a.fk_d = d.id ' .
714
            'INNER JOIN table_c c ON c.fk_b = b.id AND b.language = ? ' .
715
            'INNER JOIN table_e e ON e.fk_c = c.id AND e.fk_d = d.id',
716
            (string) $qb
717
        );
718
    }
719
720
    /**
721
     * @group DBAL-774
722
     */
723
    public function testSelectWithMultipleFromsAndJoinsWithMultipleOnConditionsParseOrder() : void
724
    {
725
        $qb = new QueryBuilder($this->conn);
726
727
        $qb->select('a.id')
728
            ->from('table_a', 'a')
729
            ->from('table_f', 'f')
730
            ->join('a', 'table_b', 'b', 'a.fk_b = b.id')
731
            ->join('b', 'table_c', 'c', 'c.fk_b = b.id AND b.language = ?')
732
            ->join('a', 'table_d', 'd', 'a.fk_d = d.id')
733
            ->join('c', 'table_e', 'e', 'e.fk_c = c.id AND e.fk_d = d.id')
734
            ->join('f', 'table_g', 'g', 'f.fk_g = g.id');
735
736
        self::assertEquals(
737
            'SELECT a.id ' .
738
            'FROM table_a a ' .
739
            'INNER JOIN table_b b ON a.fk_b = b.id ' .
740
            'INNER JOIN table_d d ON a.fk_d = d.id ' .
741
            'INNER JOIN table_c c ON c.fk_b = b.id AND b.language = ? ' .
742
            'INNER JOIN table_e e ON e.fk_c = c.id AND e.fk_d = d.id, ' .
743
            'table_f f ' .
744
            'INNER JOIN table_g g ON f.fk_g = g.id',
745
            (string) $qb
746
        );
747
    }
748
749
    public function testClone() : void
750
    {
751
        $qb = new QueryBuilder($this->conn);
752
753
        $qb->select('u.id')
754
            ->from('users', 'u')
755
            ->where('u.id = :test');
756
757
        $qb->setParameter(':test', (object) 1);
758
759
        $qb_clone = clone $qb;
760
761
        self::assertEquals((string) $qb, (string) $qb_clone);
762
763
        $qb->andWhere('u.id = 1');
764
765
        self::assertNotSame($qb->getQueryParts(), $qb_clone->getQueryParts());
766
        self::assertNotSame($qb->getParameters(), $qb_clone->getParameters());
767
    }
768
769
    public function testSimpleSelectWithoutTableAlias() : void
770
    {
771
        $qb = new QueryBuilder($this->conn);
772
773
        $qb->select('id')
774
            ->from('users');
775
776
        self::assertEquals('SELECT id FROM users', (string) $qb);
777
    }
778
779
    public function testSelectWithSimpleWhereWithoutTableAlias() : void
780
    {
781
        $qb = new QueryBuilder($this->conn);
782
783
        $qb->select('id', 'name')
784
            ->from('users')
785
            ->where('awesome=9001');
786
787
        self::assertEquals('SELECT id, name FROM users WHERE awesome=9001', (string) $qb);
788
    }
789
790
    public function testComplexSelectWithoutTableAliases() : void
791
    {
792
        $qb = new QueryBuilder($this->conn);
793
794
        $qb->select('DISTINCT users.id')
795
            ->from('users')
796
            ->from('articles')
797
            ->innerJoin('users', 'permissions', 'p', 'p.user_id = users.id')
798
            ->innerJoin('articles', 'comments', 'c', 'c.article_id = articles.id')
799
            ->where('users.id = articles.user_id')
800
            ->andWhere('p.read = 1');
801
802
        self::assertEquals('SELECT DISTINCT users.id FROM users INNER JOIN permissions p ON p.user_id = users.id, articles INNER JOIN comments c ON c.article_id = articles.id WHERE (users.id = articles.user_id) AND (p.read = 1)', $qb->getSQL());
803
    }
804
805
    public function testComplexSelectWithSomeTableAliases() : void
806
    {
807
        $qb = new QueryBuilder($this->conn);
808
809
        $qb->select('u.id')
810
            ->from('users', 'u')
811
            ->from('articles')
812
            ->innerJoin('u', 'permissions', 'p', 'p.user_id = u.id')
813
            ->innerJoin('articles', 'comments', 'c', 'c.article_id = articles.id');
814
815
        self::assertEquals('SELECT u.id FROM users u INNER JOIN permissions p ON p.user_id = u.id, articles INNER JOIN comments c ON c.article_id = articles.id', $qb->getSQL());
816
    }
817
818
    public function testSelectAllFromTableWithoutTableAlias() : void
819
    {
820
        $qb = new QueryBuilder($this->conn);
821
822
        $qb->select('users.*')
823
            ->from('users');
824
825
        self::assertEquals('SELECT users.* FROM users', (string) $qb);
826
    }
827
828
    public function testSelectAllWithoutTableAlias() : void
829
    {
830
        $qb = new QueryBuilder($this->conn);
831
832
        $qb->select('*')
833
            ->from('users');
834
835
        self::assertEquals('SELECT * FROM users', (string) $qb);
836
    }
837
838
    /**
839
     * @group DBAL-959
840
     */
841
    public function testGetParameterType() : void
842
    {
843
        $qb = new QueryBuilder($this->conn);
844
845
        $qb->select('*')->from('users');
846
847
        self::assertNull($qb->getParameterType('name'));
848
849
        $qb->where('name = :name');
850
        $qb->setParameter('name', 'foo');
851
852
        self::assertNull($qb->getParameterType('name'));
853
854
        $qb->setParameter('name', 'foo', ParameterType::STRING);
855
856
        self::assertSame(ParameterType::STRING, $qb->getParameterType('name'));
857
    }
858
859
    /**
860
     * @group DBAL-959
861
     */
862
    public function testGetParameterTypes() : void
863
    {
864
        $qb = new QueryBuilder($this->conn);
865
866
        $qb->select('*')->from('users');
867
868
        self::assertSame([], $qb->getParameterTypes());
869
870
        $qb->where('name = :name');
871
        $qb->setParameter('name', 'foo');
872
873
        self::assertSame([], $qb->getParameterTypes());
874
875
        $qb->setParameter('name', 'foo', ParameterType::STRING);
876
877
        $qb->where('is_active = :isActive');
878
        $qb->setParameter('isActive', true, ParameterType::BOOLEAN);
879
880
        self::assertSame([
881
            'name'     => ParameterType::STRING,
882
            'isActive' => ParameterType::BOOLEAN,
883
        ], $qb->getParameterTypes());
884
    }
885
886
    /**
887
     * @group DBAL-1137
888
     */
889
    public function testJoinWithNonUniqueAliasThrowsException() : void
890
    {
891
        $qb = new QueryBuilder($this->conn);
892
893
        $qb->select('a.id')
894
            ->from('table_a', 'a')
895
            ->join('a', 'table_b', 'a', 'a.fk_b = a.id');
896
897
        $this->expectException(QueryException::class);
898
        $this->expectExceptionMessage("The given alias 'a' is not unique in FROM and JOIN clause table. The currently registered aliases are: a.");
899
900
        $qb->getSQL();
901
    }
902
903
    public function testUpdateWithJoin() : void
904
    {
905
        $qb   = new QueryBuilder($this->conn);
906
        $expr = $qb->expr();
907
908
        $qb->update('users', 'u')
909
            ->join('u', 'phones', 'p', $expr->eq('p.user_id', 'u.id'))
910
            ->set('u.foo', '?')
911
            ->set('u.bar', '?');
912
913
        $this->expectException(QueryException::class);
914
915
        $qb->getSQL();
916
    }
917
918
    public function testDeleteWithJoin() : void
919
    {
920
        $qb   = new QueryBuilder($this->conn);
921
        $expr = $qb->expr();
922
923
        $qb->delete('users', 'u')
924
            ->join('u', 'phones', 'p', $expr->eq('p.user_id', 'u.id'));
925
926
        $this->expectException(QueryException::class);
927
928
        $qb->getSQL();
929
    }
930
931
    public function testInsertWithJoin() : void
932
    {
933
        $qb   = new QueryBuilder($this->conn);
934
        $expr = $qb->expr();
935
936
        $qb->insert('users')
937
            ->join('u', 'phones', 'p', $expr->eq('p.user_id', 'u.id'))
938
            ->values(
939
                [
940
                    'foo' => '?',
941
                    'bar' => '?',
942
                ]
943
            );
944
945
        $this->expectException(QueryException::class);
946
947
        $qb->getSQL();
948
    }
949
}
950