Passed
Pull Request — master (#380)
by Wilmer
03:41 queued 44s
created

AbstractQueryBuilderTest   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 863
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 505
dl 0
loc 863
rs 9.84
c 1
b 0
f 0
wmc 32

32 Methods

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