Passed
Pull Request — master (#380)
by Wilmer
03:09
created

AbstractQueryBuilderTest   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 885
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 517
c 1
b 0
f 0
dl 0
loc 885
rs 9.76
wmc 33

33 Methods

Rating   Name   Duplication   Size   Complexity  
A testBuildColumnsWithArray() 0 9 1
A testBuildColumnsWithExpression() 0 12 1
A testAddColumn() 0 11 1
A testBuildColumnsWithString() 0 8 1
A testComplexSelect() 0 37 1
A testBuildSelectColumnWithoutParentheses() 0 16 1
A testTruncateTable() 0 27 1
A testDropTable() 0 14 1
A testCreateViewWithParams() 0 17 1
A testSelectExpression() 0 52 1
A testDropCommentFromTable() 0 15 1
A testBuildUnion() 0 25 1
A testSetConditionClasses() 0 10 1
A testBuildLimit() 0 16 1
A testSelectSubquery() 0 18 1
A testFromWithAliasesNoExist() 0 20 1
A testCreateView() 0 17 1
A testSelectExpressionBuilder() 0 10 1
A testBuildWithQueryRecursive() 0 18 1
A testBuildWhereExistsWithParameters() 0 30 1
A testSelectExists() 0 8 1
A testIssue15653() 0 20 1
A testFromSubquery() 0 56 1
A testRenameColumn() 0 21 1
A testFromIndexHint() 0 34 1
A testBuildOffset() 0 16 1
A testDropView() 0 14 1
A testGroupBy() 0 72 1
A testSetSeparator() 0 33 1
A testBuildSelectOptions() 0 16 1
A testOrderBy() 0 72 1
A testBuildWhereExistsWithArrayParameters() 0 30 1
A testBuildWithQuery() 0 24 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Tests;
6
7
use PHPUnit\Framework\TestCase;
8
use stdClass;
9
use Yiisoft\Db\Driver\PDO\ConnectionPDOInterface;
10
use Yiisoft\Db\Expression\Expression;
11
use Yiisoft\Db\Query\Query;
12
use Yiisoft\Db\Schema\SchemaBuilderTrait;
13
use Yiisoft\Db\Tests\Support\Assert;
14
use Yiisoft\Db\Tests\Support\DbHelper;
15
use Yiisoft\Db\Tests\Support\TestTrait;
16
17
abstract class AbstractQueryBuilderTest extends TestCase
18
{
19
    use SchemaBuilderTrait;
20
    use TestTrait;
21
22
    protected ConnectionPDOInterface $db;
23
24
    public function testAddColumn(): void
25
    {
26
        $db = $this->getConnection();
27
28
        $qb = $db->getQueryBuilder();
29
30
        $this->assertSame(
31
            <<<SQL
32
            ALTER TABLE `user` ADD `age` integer
33
            SQL,
34
            $qb->addColumn('user', 'age', 'integer')
35
        );
36
    }
37
38
    public function testBuildColumnsWithString(): void
39
    {
40
        $db = $this->getConnection();
41
42
        $qb = $db->getQueryBuilder();
43
        $columns = '(id)';
44
45
        $this->assertSame($columns, $qb->buildColumns($columns));
46
    }
47
48
    public function testBuildColumnsWithArray(): void
49
    {
50
        $db = $this->getConnection();
51
52
        $qb = $db->getQueryBuilder();
53
        $columns = ['id', 'name', 'email', 'address', 'status'];
54
        $expected = DbHelper::replaceQuotes('[[id]], [[name]], [[email]], [[address]], [[status]]', $db->getName());
55
56
        $this->assertSame($expected, $qb->buildColumns($columns));
57
    }
58
59
    public function testBuildColumnsWithExpression(): void
60
    {
61
        $db = $this->getConnection();
62
63
        $columns = ['id', 'name', 'email', 'address', 'status', new Expression('COUNT(*)')];
64
        $expected = DbHelper::replaceQuotes(
65
            '[[id]], [[name]], [[email]], [[address]], [[status]], COUNT(*)',
66
            $db->getName(),
67
        );
68
        $qb = $db->getQueryBuilder();
69
70
        $this->assertSame($expected, $qb->buildColumns($columns));
71
    }
72
73
    public function testFromWithAliasesNoExist(): void
74
    {
75
        $db = $this->getConnection();
76
77
        $qb = $db->getQueryBuilder();
78
        $query = (new Query($db))->from('no_exist_table');
79
80
81
        [$sql, $params] = $qb->build($query);
82
83
        $this->assertSame(
84
            DbHelper::replaceQuotes(
85
                <<<SQL
86
                SELECT * FROM [[no_exist_table]]
87
                SQL,
88
                $db->getName(),
89
            ),
90
            $sql,
91
        );
92
        $this->assertSame([], $params);
93
    }
94
95
    public function testBuildLimit(): void
96
    {
97
        $db = $this->getConnection();
98
99
        $qb = $db->getQueryBuilder();
100
        $query = $this->getQuery($db)->limit(10);
101
102
        [$sql, $params] = $qb->build($query);
103
104
        $this->assertSame(
105
            <<<SQL
106
            SELECT * LIMIT 10
107
            SQL,
108
            $sql,
109
        );
110
        $this->assertSame([], $params);
111
    }
112
113
    public function testBuildOffset(): void
114
    {
115
        $db = $this->getConnection();
116
117
        $qb = $db->getQueryBuilder();
118
        $query = $this->getQuery($db)->offset(10);
119
120
        [$sql, $params] = $qb->build($query);
121
122
        $this->assertSame(
123
            <<<SQL
124
            SELECT * OFFSET 10
125
            SQL,
126
            $sql,
127
        );
128
        $this->assertSame([], $params);
129
    }
130
131
    public function testBuildSelectColumnWithoutParentheses(): void
132
    {
133
        $db = $this->getConnection();
134
135
        $qb = $db->getQueryBuilder();
136
        $params = [];
137
        $sql = $qb->buildSelect(['1'], $params);
138
139
        $this->assertSame(
140
            DbHelper::replaceQuotes(
141
                <<<SQL
142
                SELECT [[1]]
143
                SQL,
144
                $db->getName(),
145
            ),
146
            $sql,
147
        );
148
    }
149
150
    public function testBuildSelectOptions(): void
151
    {
152
        $db = $this->getConnection();
153
154
        $qb = $db->getQueryBuilder();
155
        $query = $this->getQuery($db)->selectOption('DISTINCT');
156
157
        [$sql, $params] = $qb->build($query);
158
159
        $this->assertSame(
160
            <<<SQL
161
            SELECT DISTINCT *
162
            SQL,
163
            $sql,
164
        );
165
        $this->assertSame([], $params);
166
    }
167
168
    /**
169
     * This test contains three select queries connected with UNION and UNION ALL constructions.
170
     * It could be useful to use "phpunit --group=db --filter testBuildUnion" command for run it.
171
     */
172
    public function testBuildUnion(): void
173
    {
174
        $db = $this->getConnection();
175
176
        $qb = $db->getQueryBuilder();
177
        $expectedQuerySql = DbHelper::replaceQuotes(
178
            <<<SQL
179
            (SELECT [[id]] FROM [[TotalExample]] [[t1]] WHERE (w > 0) AND (x < 2)) UNION ( SELECT [[id]] FROM [[TotalTotalExample]] [[t2]] WHERE w > 5 ) UNION ALL ( SELECT [[id]] FROM [[TotalTotalExample]] [[t3]] WHERE w = 3 )
180
            SQL,
181
            $db->getName(),
182
        );
183
184
        $secondQuery = $this->getQuery($db)->select('id')->from('TotalTotalExample t2')->where('w > 5');
185
        $thirdQuery = $this->getQuery($db)->select('id')->from('TotalTotalExample t3')->where('w = 3');
186
        $query = $this->getQuery($db)
187
            ->select('id')
188
            ->from('TotalExample t1')
189
            ->where(['and', 'w > 0', 'x < 2'])
190
            ->union($secondQuery)
191
            ->union($thirdQuery, true);
192
193
        [$actualQuerySql, $queryParams] = $qb->build($query);
194
195
        $this->assertSame($expectedQuerySql, $actualQuerySql);
196
        $this->assertSame([], $queryParams);
197
    }
198
199
    public function testBuildWithQuery(): void
200
    {
201
        $db = $this->getConnection();
202
203
        $qb = $db->getQueryBuilder();
204
        $expectedQuerySql = DbHelper::replaceQuotes(
205
            <<<SQL
206
            WITH a1 AS (SELECT [[id]] FROM [[t1]] WHERE expr = 1), a2 AS ((SELECT [[id]] FROM [[t2]] INNER JOIN [[a1]] ON t2.id = a1.id WHERE expr = 2) UNION ( SELECT [[id]] FROM [[t3]] WHERE expr = 3 )) SELECT * FROM [[a2]]
207
            SQL,
208
            $db->getName(),
209
        );
210
211
        $with1Query = $this->getQuery($db)->select('id')->from('t1')->where('expr = 1');
212
        $with2Query = $this->getQuery($db)->select('id')->from('t2')->innerJoin('a1', 't2.id = a1.id')->where('expr = 2');
213
        $with3Query = $this->getQuery($db)->select('id')->from('t3')->where('expr = 3');
214
        $query = $this->getQuery($db)
215
            ->withQuery($with1Query, 'a1')
216
            ->withQuery($with2Query->union($with3Query), 'a2')
217
            ->from('a2');
218
219
        [$actualQuerySql, $queryParams] = $qb->build($query);
220
221
        $this->assertSame($expectedQuerySql, $actualQuerySql);
222
        $this->assertSame([], $queryParams);
223
    }
224
225
    public function testBuildWithQueryRecursive(): void
226
    {
227
        $db = $this->getConnection();
228
229
        $qb = $db->getQueryBuilder();
230
        $expectedQuerySql = DbHelper::replaceQuotes(
231
            <<<SQL
232
            WITH RECURSIVE a1 AS (SELECT [[id]] FROM [[t1]] WHERE expr = 1) SELECT * FROM [[a1]]
233
            SQL,
234
            $db->getName(),
235
        );
236
        $with1Query = $this->getQuery($db)->select('id')->from('t1')->where('expr = 1');
237
        $query = $this->getQuery($db)->withQuery($with1Query, 'a1', true)->from('a1');
238
239
        [$actualQuerySql, $queryParams] = $qb->build($query);
240
241
        $this->assertSame($expectedQuerySql, $actualQuerySql);
242
        $this->assertSame([], $queryParams);
243
    }
244
245
    public function testBuildWhereExistsWithArrayParameters(): void
246
    {
247
        $db = $this->getConnection();
248
249
        $qb = $db->getQueryBuilder();
250
        $expectedQuerySql = DbHelper::replaceQuotes(
251
            <<<SQL
252
            SELECT [[id]] FROM [[TotalExample]] [[t]] WHERE (EXISTS (SELECT [[1]] FROM [[Website]] [[w]] WHERE (w.id = t.website_id) AND (([[w]].[[merchant_id]]=:qp0) AND ([[w]].[[user_id]]=:qp1)))) AND ([[t]].[[some_column]]=:qp2)
253
            SQL,
254
            $db->getName(),
255
        );
256
257
        $expectedQueryParams = [':qp0' => 6, ':qp1' => 210, ':qp2' => 'asd'];
258
259
        $subQuery = $this->getQuery($db)
260
            ->select('1')
261
            ->from('Website w')
262
            ->where('w.id = t.website_id')
263
            ->andWhere(['w.merchant_id' => 6, 'w.user_id' => 210]);
264
265
        $query = $this->getQuery($db)
266
            ->select('id')
267
            ->from('TotalExample t')
268
            ->where(['exists', $subQuery])
269
            ->andWhere(['t.some_column' => 'asd']);
270
271
        [$actualQuerySql, $queryParams] = $qb->build($query);
272
273
        $this->assertSame($expectedQuerySql, $actualQuerySql);
274
        $this->assertSame($expectedQueryParams, $queryParams);
275
    }
276
277
    public function testBuildWhereExistsWithParameters(): void
278
    {
279
        $db = $this->getConnection();
280
281
        $qb = $db->getQueryBuilder();
282
        $expectedQuerySql = DbHelper::replaceQuotes(
283
            <<<SQL
284
            SELECT [[id]] FROM [[TotalExample]] [[t]] WHERE (EXISTS (SELECT [[1]] FROM [[Website]] [[w]] WHERE (w.id = t.website_id) AND (w.merchant_id = :merchant_id))) AND (t.some_column = :some_value)
285
            SQL,
286
            $db->getName(),
287
        );
288
289
        $expectedQueryParams = [':some_value' => 'asd', ':merchant_id' => 6];
290
291
        $subQuery = $this->getQuery($db)
292
            ->select('1')
293
            ->from('Website w')
294
            ->where('w.id = t.website_id')
295
            ->andWhere('w.merchant_id = :merchant_id', [':merchant_id' => 6]);
296
297
        $query = $this->getQuery($db)
298
            ->select('id')
299
            ->from('TotalExample t')
300
            ->where(['exists', $subQuery])
301
            ->andWhere('t.some_column = :some_value', [':some_value' => 'asd']);
302
303
        [$actualQuerySql, $queryParams] = $qb->build($query);
304
305
        $this->assertSame($expectedQuerySql, $actualQuerySql);
306
        $this->assertSame($expectedQueryParams, $queryParams);
307
    }
308
309
    public function testComplexSelect(): void
310
    {
311
        $db = $this->getConnection();
312
313
        $qb = $db->getQueryBuilder();
314
        $expressionString = DbHelper::replaceQuotes(
315
            <<<SQL
316
            case t.Status_Id when 1 then 'Acknowledge' when 2 then 'No Action' else 'Unknown Action' END as [[Next Action]]
317
            SQL,
318
            $db->getName(),
319
        );
320
        $expected = DbHelper::replaceQuotes(
321
            <<<SQL
322
            SELECT [[t]].[[id]] AS [[ID]], [[gsm]].[[username]] AS [[GSM]], [[part]].[[Part]], [[t]].[[Part_Cost]] AS [[Part Cost]], st_x(location::geometry) AS [[lon]], case t.Status_Id when 1 then 'Acknowledge' when 2 then 'No Action' else 'Unknown Action' END as [[Next Action]] FROM [[tablename]]
323
            SQL,
324
            $db->getName(),
325
        );
326
327
        $this->assertIsString($expressionString);
328
329
        $query = $this->getQuery($db)
330
            ->select(
331
                [
332
                    'ID' => 't.id',
333
                    'gsm.username as GSM',
334
                    'part.Part',
335
                    'Part Cost' => 't.Part_Cost',
336
                    'st_x(location::geometry) as lon',
337
                    new Expression($expressionString),
338
                ]
339
            )
340
            ->from('tablename');
341
342
        [$sql, $params] = $qb->build($query);
343
344
        $this->assertSame($expected, $sql);
345
        $this->assertEmpty($params);
346
    }
347
348
    public function testCreateView(): void
349
    {
350
        $db = $this->getConnection();
351
352
        $qb = $db->getQueryBuilder();
353
        $expected = DbHelper::replaceQuotes(
354
            <<<SQL
355
            CREATE VIEW [[test_view]] AS SELECT [[id]], [[name]] FROM [[test_table]]
356
            SQL,
357
            $db->getName(),
358
        );
359
        $sql = $qb->createView(
360
            'test_view',
361
            $this->getQuery($db)->select(['id', 'name'])->from('test_table'),
362
        );
363
364
        $this->assertSame($expected, $sql);
365
    }
366
367
    public function testCreateViewWithParams(): void
368
    {
369
        $db = $this->getConnection();
370
371
        $qb = $db->getQueryBuilder();
372
        $expected = DbHelper::replaceQuotes(
373
            <<<SQL
374
            CREATE VIEW [[test_view]] AS SELECT [[id]], [[name]] FROM [[test_table]] WHERE [[id]]=1
375
            SQL,
376
            $db->getName(),
377
        );
378
        $sql = $qb->createView(
379
            'test_view',
380
            $this->getQuery($db)->select(['id', 'name'])->from('test_table')->where(['id' => 1]),
381
        );
382
383
        $this->assertSame($expected, $sql);
384
    }
385
386
    public function testDropCommentFromTable(): void
387
    {
388
        $db = $this->getConnection();
389
390
        $qb = $db->getQueryBuilder();
391
        $expected = DbHelper::replaceQuotes(
392
            <<<SQL
393
            COMMENT ON TABLE `test_table` IS NULL
394
            SQL,
395
            $db->getName(),
396
        );
397
398
        $sql = $qb->dropCommentFromTable('test_table');
399
400
        $this->assertSame($expected, $sql);
401
    }
402
403
    public function testDropTable(): void
404
    {
405
        $db = $this->getConnection();
406
407
        $qb = $db->getQueryBuilder();
408
        $expected = DbHelper::replaceQuotes(
409
            <<<SQL
410
            DROP TABLE [[test_table]]
411
            SQL,
412
            $db->getName(),
413
        );
414
        $sql = $qb->dropTable('test_table');
415
416
        $this->assertSame($expected, $sql);
417
    }
418
419
    public function testDropView(): void
420
    {
421
        $db = $this->getConnection();
422
423
        $qb = $db->getQueryBuilder();
424
        $expected = DbHelper::replaceQuotes(
425
            <<<SQL
426
            DROP VIEW [[test_view]]
427
            SQL,
428
            $db->getName(),
429
        );
430
        $sql = $qb->dropView('test_view');
431
432
        $this->assertSame($expected, $sql);
433
    }
434
435
    /**
436
     * {@see https://github.com/yiisoft/yii2/issues/10869}
437
     */
438
    public function testFromIndexHint(): void
439
    {
440
        $db = $this->getConnection();
441
442
        $qb = $db->getQueryBuilder();
443
        $query = $this->getQuery($db)->from([new Expression('{{%user}} USE INDEX (primary)')]);
444
445
        [$sql, $params] = $qb->build($query);
446
447
        $expected = DbHelper::replaceQuotes(
448
            <<<SQL
449
            SELECT * FROM {{%user}} USE INDEX (primary)
450
            SQL,
451
            $db->getName(),
452
        );
453
454
        $this->assertSame($expected, $sql);
455
        $this->assertEmpty($params);
456
457
        $query = $this->getQuery($db)
458
            ->from([new Expression('{{user}} {{t}} FORCE INDEX (primary) IGNORE INDEX FOR ORDER BY (i1)')])
459
            ->leftJoin(['p' => 'profile'], 'user.id = profile.user_id USE INDEX (i2)');
460
461
        [$sql, $params] = $qb->build($query);
462
463
        $expected = DbHelper::replaceQuotes(
464
            <<<SQL
465
            SELECT * FROM {{user}} {{t}} FORCE INDEX (primary) IGNORE INDEX FOR ORDER BY (i1) LEFT JOIN [[profile]] [[p]] ON user.id = profile.user_id USE INDEX (i2)
466
            SQL,
467
            $db->getName(),
468
        );
469
470
        $this->assertSame($expected, $sql);
471
        $this->assertEmpty($params);
472
    }
473
474
    public function testFromSubquery(): void
475
    {
476
        $db = $this->getConnection();
477
478
        $qb = $db->getQueryBuilder();
479
480
        /* subquery */
481
        $subquery = $this->getQuery($db)->from('user')->where('account_id = accounts.id');
482
        $query = $this->getQuery($db)->from(['activeusers' => $subquery]);
483
484
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
485
        [$sql, $params] = $qb->build($query);
486
487
        $expected = DbHelper::replaceQuotes(
488
            <<<SQL
489
            SELECT * FROM (SELECT * FROM [[user]] WHERE account_id = accounts.id) [[activeusers]]
490
            SQL,
491
            $db->getName(),
492
        );
493
494
        $this->assertSame($expected, $sql);
495
        $this->assertEmpty($params);
496
497
        /* subquery with params */
498
        $subquery = $this->getQuery($db)->from('user')->where('account_id = :id', ['id' => 1]);
499
        $query = $this->getQuery($db)->from(['activeusers' => $subquery])->where('abc = :abc', ['abc' => 'abc']);
500
501
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
502
        [$sql, $params] = $qb->build($query);
503
504
        $expected = DbHelper::replaceQuotes(
505
            <<<SQL
506
            SELECT * FROM (SELECT * FROM [[user]] WHERE account_id = :id) [[activeusers]] WHERE abc = :abc
507
            SQL,
508
            $db->getName(),
509
        );
510
511
        $this->assertSame($expected, $sql);
512
        $this->assertSame(['abc' => 'abc', 'id' => 1], $params);
513
514
        /* simple subquery */
515
        $subquery = '(SELECT * FROM user WHERE account_id = accounts.id)';
516
        $query = $this->getQuery($db)->from(['activeusers' => $subquery]);
517
518
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
519
        [$sql, $params] = $qb->build($query);
520
521
        $expected = DbHelper::replaceQuotes(
522
            <<<SQL
523
            SELECT * FROM (SELECT * FROM user WHERE account_id = accounts.id) [[activeusers]]
524
            SQL,
525
            $db->getName(),
526
        );
527
528
        $this->assertSame($expected, $sql);
529
        $this->assertEmpty($params);
530
    }
531
532
    public function testGroupBy(): void
533
    {
534
        $db = $this->getConnection();
535
536
        $qb = $db->getQueryBuilder();
537
538
        /* simple string */
539
        $query = $this->getQuery($db)->select('*')->from('operations')->groupBy('name, date');
540
541
        [$sql, $params] = $qb->build($query);
542
543
        $expected = DbHelper::replaceQuotes(
544
            <<<SQL
545
            SELECT * FROM [[operations]] GROUP BY [[name]], [[date]]
546
            SQL,
547
            $db->getName(),
548
        );
549
550
        $this->assertSame($expected, $sql);
551
        $this->assertEmpty($params);
552
553
        /* array syntax */
554
        $query = $this->getQuery($db)->select('*')->from('operations')->groupBy(['name', 'date']);
555
556
        [$sql, $params] = $qb->build($query);
557
558
        $expected = DbHelper::replaceQuotes(
559
            <<<SQL
560
            SELECT * FROM [[operations]] GROUP BY [[name]], [[date]]
561
            SQL,
562
            $db->getName(),
563
        );
564
565
        $this->assertSame($expected, $sql);
566
        $this->assertEmpty($params);
567
568
        /* expression */
569
        $query = $this->getQuery($db)
570
            ->select('*')
571
            ->from('operations')
572
            ->where('account_id = accounts.id')
573
            ->groupBy(new Expression('SUBSTR(name, 0, 1), x'));
574
575
        [$sql, $params] = $qb->build($query);
576
577
        $expected = DbHelper::replaceQuotes(
578
            <<<SQL
579
            SELECT * FROM [[operations]] WHERE account_id = accounts.id GROUP BY SUBSTR(name, 0, 1), x
580
            SQL,
581
            $db->getName(),
582
        );
583
584
        $this->assertSame($expected, $sql);
585
        $this->assertEmpty($params);
586
587
        /* expression with params */
588
        $query = $this->getQuery($db)
589
            ->select('*')
590
            ->from('operations')
591
            ->groupBy(new Expression('SUBSTR(name, 0, :to), x', [':to' => 4]));
592
593
        [$sql, $params] = $qb->build($query);
594
595
        $expected = DbHelper::replaceQuotes(
596
            <<<SQL
597
            SELECT * FROM [[operations]] GROUP BY SUBSTR(name, 0, :to), x
598
            SQL,
599
            $db->getName(),
600
        );
601
602
        $this->assertSame($expected, $sql);
603
        $this->assertSame([':to' => 4], $params);
604
    }
605
606
    /**
607
     * {@see https://github.com/yiisoft/yii2/issues/15653}
608
     */
609
    public function testIssue15653(): void
610
    {
611
        $db = $this->getConnection();
612
613
        $qb = $db->getQueryBuilder();
614
        $query = $this->getQuery($db)->from('admin_user')->where(['is_deleted' => false]);
615
        $query->where([])->andWhere(['in', 'id', ['1', '0']]);
616
617
        [$sql, $params] = $qb->build($query);
618
619
        $this->assertSame(
620
            DbHelper::replaceQuotes(
621
                <<<SQL
622
                SELECT * FROM [[admin_user]] WHERE [[id]] IN (:qp0, :qp1)
623
                SQL,
624
                $db->getName(),
625
            ),
626
            $sql,
627
        );
628
        $this->assertSame([':qp0' => '1', ':qp1' => '0'], $params);
629
    }
630
631
    public function testOrderBy(): void
632
    {
633
        $db = $this->getConnection();
634
635
        $qb = $db->getQueryBuilder();
636
637
        /* simple string */
638
        $query = $this->getQuery($db)->select('*')->from('operations')->orderBy('name ASC, date DESC');
639
640
        [$sql, $params] = $qb->build($query);
641
642
        $expected = DbHelper::replaceQuotes(
643
            <<<SQL
644
            SELECT * FROM [[operations]] ORDER BY [[name]], [[date]] DESC
645
            SQL,
646
            $db->getName(),
647
        );
648
649
        $this->assertSame($expected, $sql);
650
        $this->assertEmpty($params);
651
652
        /* array syntax */
653
        $query = $this->getQuery($db)->select('*')->from('operations')->orderBy(['name' => SORT_ASC, 'date' => SORT_DESC]);
654
655
        [$sql, $params] = $qb->build($query);
656
657
        $expected = DbHelper::replaceQuotes(
658
            <<<SQL
659
            SELECT * FROM [[operations]] ORDER BY [[name]], [[date]] DESC
660
            SQL,
661
            $db->getName(),
662
        );
663
664
        $this->assertSame($expected, $sql);
665
        $this->assertEmpty($params);
666
667
        /* expression */
668
        $query = $this->getQuery($db)
669
            ->select('*')
670
            ->from('operations')
671
            ->where('account_id = accounts.id')
672
            ->orderBy(new Expression('SUBSTR(name, 3, 4) DESC, x ASC'));
673
674
        [$sql, $params] = $qb->build($query);
675
676
        $expected = DbHelper::replaceQuotes(
677
            <<<SQL
678
            SELECT * FROM [[operations]] WHERE account_id = accounts.id ORDER BY SUBSTR(name, 3, 4) DESC, x ASC
679
            SQL,
680
            $db->getName(),
681
        );
682
683
        $this->assertSame($expected, $sql);
684
        $this->assertEmpty($params);
685
686
        /* expression with params */
687
        $query = $this->getQuery($db)
688
            ->select('*')
689
            ->from('operations')
690
            ->orderBy(new Expression('SUBSTR(name, 3, :to) DESC, x ASC', [':to' => 4]));
691
692
        [$sql, $params] = $qb->build($query);
693
694
        $expected = DbHelper::replaceQuotes(
695
            <<<SQL
696
            SELECT * FROM [[operations]] ORDER BY SUBSTR(name, 3, :to) DESC, x ASC
697
            SQL,
698
            $db->getName(),
699
        );
700
701
        $this->assertSame($expected, $sql);
702
        $this->assertSame([':to' => 4], $params);
703
    }
704
705
    public function testRenameColumn(): void
706
    {
707
        $db = $this->getConnection();
708
709
        $qb = $db->getQueryBuilder();
710
        $sql = $qb->renameColumn('alpha', 'string_identifier', 'string_identifier_test');
711
712
        $this->assertSame(
713
            <<<SQL
714
            ALTER TABLE `alpha` RENAME COLUMN `string_identifier` TO `string_identifier_test`
715
            SQL,
716
            $sql,
717
        );
718
719
        $sql = $qb->renameColumn('alpha', 'string_identifier_test', 'string_identifier');
720
721
        $this->assertSame(
722
            <<<SQL
723
            ALTER TABLE `alpha` RENAME COLUMN `string_identifier_test` TO `string_identifier`
724
            SQL,
725
            $sql,
726
        );
727
    }
728
729
    public function testSelectExpression(): void
730
    {
731
        $db = $this->getConnection();
732
733
        $qb = $db->getQueryBuilder();
734
        $query = $this->getQuery($db)->select(new Expression('1 AS ab'))->from('tablename');
735
736
        [$sql, $params] = $qb->build($query);
737
738
        $expected = DbHelper::replaceQuotes(
739
            <<<SQL
740
            SELECT 1 AS ab FROM [[tablename]]
741
            SQL,
742
            $db->getName(),
743
        );
744
745
        $this->assertSame($expected, $sql);
746
        $this->assertEmpty($params);
747
748
        $query = $this->getQuery($db)
749
            ->select(new Expression('1 AS ab'))
750
            ->addSelect(new Expression('2 AS cd'))
751
            ->addSelect(['ef' => new Expression('3')])
752
            ->from('tablename');
753
754
        [$sql, $params] = $qb->build($query);
755
756
        $expected = DbHelper::replaceQuotes(
757
            <<<SQL
758
            SELECT 1 AS ab, 2 AS cd, 3 AS [[ef]] FROM [[tablename]]
759
            SQL,
760
            $db->getName(),
761
        );
762
763
        $this->assertSame($expected, $sql);
764
        $this->assertEmpty($params);
765
766
        $query = $this->getQuery($db)
767
            ->select(new Expression('SUBSTR(name, 0, :len)', [':len' => 4]))
768
            ->from('tablename');
769
770
        [$sql, $params] = $qb->build($query);
771
772
        $expected = DbHelper::replaceQuotes(
773
            <<<SQL
774
            SELECT SUBSTR(name, 0, :len) FROM [[tablename]]
775
            SQL,
776
            $db->getName(),
777
        );
778
779
        $this->assertSame($expected, $sql);
780
        $this->assertSame([':len' => 4], $params);
781
    }
782
783
    /**
784
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::selectExist()
785
     */
786
    public function testSelectExists(string $sql, string $expected): void
787
    {
788
        $db = $this->getConnection();
789
790
        $qb = $db->getQueryBuilder();
791
        $sqlSelectExist = $qb->selectExists($sql);
792
793
        $this->assertSame($expected, $sqlSelectExist);
794
    }
795
796
    public function testSelectSubquery(): void
797
    {
798
        $db = $this->getConnection();
799
800
        $qb = $db->getQueryBuilder();
801
        $expected = DbHelper::replaceQuotes(
802
            <<<SQL
803
            SELECT *, (SELECT COUNT(*) FROM [[operations]] WHERE account_id = accounts.id) AS [[operations_count]] FROM [[accounts]]
804
            SQL,
805
            $db->getName(),
806
        );
807
        $subquery = $this->getQuery($db)->select('COUNT(*)')->from('operations')->where('account_id = accounts.id');
808
        $query = $this->getQuery($db)->select('*')->from('accounts')->addSelect(['operations_count' => $subquery]);
809
810
        [$sql, $params] = $qb->build($query);
811
812
        $this->assertSame($expected, $sql);
813
        $this->assertEmpty($params);
814
    }
815
816
    public function testSetConditionClasses(): void
817
    {
818
        $db = $this->getConnection();
819
820
        $qb = $db->getQueryBuilder();
821
        $qb->setConditionClasses(['stdClass' => stdClass::class]);
822
        $dqlBuilder = Assert::getInaccessibleProperty($qb, 'dqlBuilder');
823
        $conditionClasses = Assert::getInaccessibleProperty($dqlBuilder, 'conditionClasses');
824
825
        $this->assertSame(stdClass::class, $conditionClasses['stdClass']);
826
    }
827
828
    public function testSelectExpressionBuilder(): void
829
    {
830
        $db = $this->getConnection();
831
832
        $qb = $db->getQueryBuilder();
833
        $qb->setExpressionBuilders(['stdClass' => stdClass::class]);
834
        $dqlBuilder = Assert::getInaccessibleProperty($qb, 'dqlBuilder');
835
        $expressionBuilders = Assert::getInaccessibleProperty($dqlBuilder, 'expressionBuilders');
836
837
        $this->assertSame(stdClass::class, $expressionBuilders['stdClass']);
838
    }
839
840
    public function testSetSeparator(): void
841
    {
842
        $db = $this->getConnection();
843
844
        $qb = $db->getQueryBuilder();
845
        $qb->setSeparator(' ');
846
        [$sql, $params] = $qb->build($this->getQuery($db)->select('*')->from('table'));
847
848
        $this->assertSame(
849
            DbHelper::replaceQuotes(
850
                <<<SQL
851
                SELECT * FROM [[table]]
852
                SQL,
853
                $db->getName(),
854
            ),
855
            $sql
856
        );
857
        $this->assertEmpty($params);
858
859
        $qb->setSeparator("\n");
860
        [$sql, $params] = $qb->build($this->getQuery($db)->select('*')->from('table'));
861
862
        $this->assertSame(
863
            DbHelper::replaceQuotes(
864
                <<<SQL
865
                SELECT *
866
                FROM [[table]]
867
                SQL,
868
                $db->getName(),
869
            ),
870
            $sql,
871
        );
872
        $this->assertEmpty($params);
873
    }
874
875
    public function testTruncateTable(): void
876
    {
877
        $db = $this->getConnection();
878
879
        $qb = $db->getQueryBuilder();
880
        $sql = $qb->truncateTable('table');
881
882
        $this->assertSame(
883
            DbHelper::replaceQuotes(
884
                <<<SQL
885
                TRUNCATE TABLE [[table]]
886
                SQL,
887
                $db->getName(),
888
            ),
889
            $sql,
890
        );
891
892
        $sql = $qb->truncateTable('table2');
893
894
        $this->assertSame(
895
            DbHelper::replaceQuotes(
896
                <<<SQL
897
                TRUNCATE TABLE [[table2]]
898
                SQL,
899
                $db->getName(),
900
            ),
901
            $sql,
902
        );
903
    }
904
}
905