Passed
Pull Request — master (#380)
by Wilmer
02:57
created

testSetConditionClasses()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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