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

QueryBuilderTest::testComplexSelect()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 36
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 24
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 36
rs 9.536
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Tests;
6
7
use PHPUnit\Framework\TestCase;
8
use Yiisoft\Db\Expression\Expression;
9
use Yiisoft\Db\Expression\ExpressionInterface;
10
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
11
use Yiisoft\Db\Tests\Support\DbHelper;
12
use Yiisoft\Db\Tests\Support\Mock;
13
14
/**
15
 * @group db
16
 */
17
final class QueryBuilderTest extends TestCase
18
{
19
    private QueryBuilderInterface $queryBuilder;
20
    private Mock $mock;
21
22
    public function setUp(): void
23
    {
24
        parent::setUp();
25
26
        $this->mock = new Mock();
27
        $this->queryBuilder = $this->mock->queryBuilder('`', '`');
28
    }
29
30
    public function tearDown(): void
31
    {
32
        parent::tearDown();
33
34
        unset($this->queryBuilder, $this->mock);
35
    }
36
37
    /**
38
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::batchInsert()
39
     */
40
    public function testBatchInsert(
41
        string $table,
42
        array $columns,
43
        array $value,
44
        string|null $expected,
45
        array $expectedParams = []
46
    ): void {
47
        $params = [];
48
        $db = $this->mock->connection(true);
49
        $sql = $db->getQueryBuilder()->batchInsert($table, $columns, $value, $params);
50
51
        $this->assertSame($expected, $sql);
52
        $this->assertSame($expectedParams, $params);
53
    }
54
55
    /**
56
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildConditions()
57
     */
58
    public function testBuildCondition(
59
        array|ExpressionInterface|string $conditions,
60
        string $expected,
61
        array $expectedParams = []
62
    ): void {
63
        $query = $this->mock->query()->where($conditions);
64
        [$sql, $params] = $this->queryBuilder->build($query);
65
66
        $this->assertSame(
67
            'SELECT *' . (
68
                empty($expected) ? '' : ' WHERE ' . DbHelper::replaceQuotes(
69
                    $expected,
70
                    $this->mock->getDriverName(),
71
                )
72
            ),
73
            $sql,
74
        );
75
        $this->assertSame($expectedParams, $params);
76
    }
77
78
    /**
79
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildFilterCondition()
80
     */
81
    public function testBuildFilterCondition(array $condition, string $expected, array $expectedParams): void
82
    {
83
        $query = $this->mock->query()->filterWhere($condition);
84
        [$sql, $params] = $this->queryBuilder->build($query);
85
86
        $this->assertSame(
87
            'SELECT *' . (
88
                empty($expected) ? '' : ' WHERE ' . DbHelper::replaceQuotes(
89
                    $expected,
90
                    $this->mock->getDriverName(),
91
                )
92
            ),
93
            $sql,
94
        );
95
        $this->assertSame($expectedParams, $params);
96
    }
97
98
    /**
99
     * This test contains three select queries connected with UNION and UNION ALL constructions.
100
     * It could be useful to use "phpunit --group=db --filter testBuildUnion" command for run it.
101
     */
102
    public function testBuildUnion(): void
103
    {
104
        $expectedQuerySql = DbHelper::replaceQuotes(
105
            <<<SQL
106
            (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 )
107
            SQL,
108
            $this->mock->getDriverName(),
109
        );
110
111
        $secondQuery = $this->mock
112
            ->query()
113
            ->select('id')
114
            ->from('TotalTotalExample t2')
115
            ->where('w > 5');
116
117
        $thirdQuery = $this->mock
118
            ->query()
119
            ->select('id')
120
            ->from('TotalTotalExample t3')
121
            ->where('w = 3');
122
123
        $query = $this->mock
124
            ->query()
125
            ->select('id')
126
            ->from('TotalExample t1')
127
            ->where(['and', 'w > 0', 'x < 2'])
128
            ->union($secondQuery)
129
            ->union($thirdQuery, true);
130
131
        [$actualQuerySql, $queryParams] = $this->queryBuilder->build($query);
132
133
        $this->assertSame($expectedQuerySql, $actualQuerySql);
134
        $this->assertSame([], $queryParams);
135
    }
136
137
    public function testBuildWithQuery(): void
138
    {
139
        $expectedQuerySql = DbHelper::replaceQuotes(
140
            <<<SQL
141
            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]]
142
            SQL,
143
            $this->mock->getDriverName(),
144
        );
145
146
        $with1Query = $this->mock
147
            ->query()
148
            ->select('id')
149
            ->from('t1')
150
            ->where('expr = 1');
151
152
        $with2Query = $this->mock
153
            ->query()
154
            ->select('id')
155
            ->from('t2')
156
            ->innerJoin('a1', 't2.id = a1.id')
157
            ->where('expr = 2');
158
159
        $with3Query = $this->mock
160
            ->query()
161
            ->select('id')
162
            ->from('t3')
163
            ->where('expr = 3');
164
165
        $query = $this->mock
166
            ->query()
167
            ->withQuery($with1Query, 'a1')
168
            ->withQuery($with2Query->union($with3Query), 'a2')
169
            ->from('a2');
170
171
        [$actualQuerySql, $queryParams] = $this->queryBuilder->build($query);
172
173
        $this->assertSame($expectedQuerySql, $actualQuerySql);
174
        $this->assertSame([], $queryParams);
175
    }
176
177
    public function testBuildWithQueryRecursive(): void
178
    {
179
        $expectedQuerySql = DbHelper::replaceQuotes(
180
            <<<SQL
181
            WITH RECURSIVE a1 AS (SELECT [[id]] FROM [[t1]] WHERE expr = 1) SELECT * FROM [[a1]]
182
            SQL,
183
            $this->mock->getDriverName(),
184
        );
185
186
        $with1Query = $this->mock
187
            ->query()
188
            ->select('id')
189
            ->from('t1')
190
            ->where('expr = 1');
191
192
        $query = $this->mock
193
            ->query()
194
            ->withQuery($with1Query, 'a1', true)
195
            ->from('a1');
196
197
        [$actualQuerySql, $queryParams] = $this->queryBuilder->build($query);
198
199
        $this->assertSame($expectedQuerySql, $actualQuerySql);
200
        $this->assertSame([], $queryParams);
201
    }
202
203
    /**
204
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildWhereExists()
205
     */
206
    public function testBuildWhereExists(string $cond, string $expectedQuerySql): void
207
    {
208
        $expectedQueryParams = [];
209
        $subQuery = $this->mock->query()->select('1')->from('Website w');
210
        $query = $this->mock->query()->select('id')->from('TotalExample t')->where([$cond, $subQuery]);
211
212
        [$actualQuerySql, $actualQueryParams] = $this->queryBuilder->build($query);
213
214
        $this->assertSame($expectedQuerySql, $actualQuerySql);
215
        $this->assertSame($expectedQueryParams, $actualQueryParams);
216
    }
217
218
    public function testBuildWhereExistsWithArrayParameters(): void
219
    {
220
        $expectedQuerySql = DbHelper::replaceQuotes(
221
            <<<SQL
222
            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)
223
            SQL,
224
            $this->mock->getDriverName(),
225
        );
226
227
        $expectedQueryParams = [':qp0' => 6, ':qp1' => 210, ':qp2' => 'asd'];
228
229
        $subQuery = $this->mock
230
            ->query()
231
            ->select('1')
232
            ->from('Website w')
233
            ->where('w.id = t.website_id')
234
            ->andWhere(['w.merchant_id' => 6, 'w.user_id' => 210]);
235
236
        $query = $this->mock
237
            ->query()
238
            ->select('id')
239
            ->from('TotalExample t')
240
            ->where(['exists', $subQuery])
241
            ->andWhere(['t.some_column' => 'asd']);
242
243
        [$actualQuerySql, $queryParams] = $this->queryBuilder->build($query);
244
245
        $this->assertSame($expectedQuerySql, $actualQuerySql);
246
        $this->assertSame($expectedQueryParams, $queryParams);
247
    }
248
249
    public function testBuildWhereExistsWithParameters(): void
250
    {
251
        $expectedQuerySql = DbHelper::replaceQuotes(
252
            <<<SQL
253
            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)
254
            SQL,
255
            $this->mock->getDriverName(),
256
        );
257
258
        $expectedQueryParams = [':some_value' => 'asd', ':merchant_id' => 6];
259
260
        $subQuery = $this->mock
261
            ->query()
262
            ->select('1')
263
            ->from('Website w')
264
            ->where('w.id = t.website_id')
265
            ->andWhere('w.merchant_id = :merchant_id', [':merchant_id' => 6]);
266
267
        $query = $this->mock
268
            ->query()
269
            ->select('id')
270
            ->from('TotalExample t')
271
            ->where(['exists', $subQuery])
272
            ->andWhere('t.some_column = :some_value', [':some_value' => 'asd']);
273
274
        [$actualQuerySql, $queryParams] = $this->queryBuilder->build($query);
275
276
        $this->assertSame($expectedQuerySql, $actualQuerySql);
277
        $this->assertSame($expectedQueryParams, $queryParams);
278
    }
279
280
    public function testComplexSelect(): void
281
    {
282
        $expressionString = DbHelper::replaceQuotes(
283
            <<<SQL
284
            case t.Status_Id when 1 then 'Acknowledge' when 2 then 'No Action' else 'Unknown Action' END as [[Next Action]]
285
            SQL,
286
            $this->mock->getDriverName(),
287
        );
288
289
        $expected = DbHelper::replaceQuotes(
290
            <<<SQL
291
            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]]
292
            SQL,
293
            $this->mock->getDriverName(),
294
        );
295
296
        $this->assertIsString($expressionString);
297
298
        $query = $this->mock
299
            ->query()
300
            ->select(
301
                [
302
                    'ID' => 't.id',
303
                    'gsm.username as GSM',
304
                    'part.Part',
305
                    'Part Cost' => 't.Part_Cost',
306
                    'st_x(location::geometry) as lon',
307
                    new Expression($expressionString),
308
                ]
309
            )
310
            ->from('tablename');
311
312
        [$sql, $params] = $this->queryBuilder->build($query);
313
314
        $this->assertSame($expected, $sql);
315
        $this->assertEmpty($params);
316
    }
317
318
    /**
319
     * {@see https://github.com/yiisoft/yii2/issues/10869}
320
     */
321
    public function testFromIndexHint(): void
322
    {
323
        $query = $this->mock->query()->from([new Expression('{{%user}} USE INDEX (primary)')]);
324
325
        [$sql, $params] = $this->queryBuilder->build($query);
326
327
        $expected = DbHelper::replaceQuotes(
328
            <<<SQL
329
            SELECT * FROM {{%user}} USE INDEX (primary)
330
            SQL,
331
            $this->mock->getDriverName(),
332
        );
333
334
        $this->assertSame($expected, $sql);
335
        $this->assertEmpty($params);
336
337
        $query = $this->mock
338
            ->query()
339
            ->from([new Expression('{{user}} {{t}} FORCE INDEX (primary) IGNORE INDEX FOR ORDER BY (i1)')])
340
            ->leftJoin(['p' => 'profile'], 'user.id = profile.user_id USE INDEX (i2)');
341
342
        [$sql, $params] = $this->queryBuilder->build($query);
343
344
        $expected = DbHelper::replaceQuotes(
345
            <<<SQL
346
            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)
347
            SQL,
348
            $this->mock->getDriverName(),
349
        );
350
351
        $this->assertSame($expected, $sql);
352
        $this->assertEmpty($params);
353
    }
354
355
    public function testFromSubquery(): void
356
    {
357
        /* subquery */
358
        $subquery = $this->mock->query()->from('user')->where('account_id = accounts.id');
359
        $query = $this->mock->query()->from(['activeusers' => $subquery]);
360
361
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
362
        [$sql, $params] = $this->queryBuilder->build($query);
363
364
        $expected = DbHelper::replaceQuotes(
365
            <<<SQL
366
            SELECT * FROM (SELECT * FROM [[user]] WHERE account_id = accounts.id) [[activeusers]]
367
            SQL,
368
            $this->mock->getDriverName(),
369
        );
370
371
        $this->assertSame($expected, $sql);
372
        $this->assertEmpty($params);
373
374
        /* subquery with params */
375
        $subquery = $this->mock->query()->from('user')->where('account_id = :id', ['id' => 1]);
376
        $query = $this->mock->query()->from(['activeusers' => $subquery])->where('abc = :abc', ['abc' => 'abc']);
377
378
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
379
        [$sql, $params] = $this->queryBuilder->build($query);
380
381
        $expected = DbHelper::replaceQuotes(
382
            <<<SQL
383
            SELECT * FROM (SELECT * FROM [[user]] WHERE account_id = :id) [[activeusers]] WHERE abc = :abc
384
            SQL,
385
            $this->mock->getDriverName(),
386
        );
387
388
        $this->assertSame($expected, $sql);
389
        $this->assertSame(['abc' => 'abc', 'id' => 1], $params);
390
391
        /* simple subquery */
392
        $subquery = '(SELECT * FROM user WHERE account_id = accounts.id)';
393
        $query = $this->mock->query()->from(['activeusers' => $subquery]);
394
395
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
396
        [$sql, $params] = $this->queryBuilder->build($query);
397
398
        $expected = DbHelper::replaceQuotes(
399
            <<<SQL
400
            SELECT * FROM (SELECT * FROM user WHERE account_id = accounts.id) [[activeusers]]
401
            SQL,
402
            $this->mock->getDriverName(),
403
        );
404
405
        $this->assertSame($expected, $sql);
406
        $this->assertEmpty($params);
407
    }
408
409
    public function testGroupBy(): void
410
    {
411
        /* simple string */
412
        $query = $this->mock->query()->select('*')->from('operations')->groupBy('name, date');
413
414
        [$sql, $params] = $this->queryBuilder->build($query);
415
416
        $expected = DbHelper::replaceQuotes(
417
            <<<SQL
418
            SELECT * FROM [[operations]] GROUP BY [[name]], [[date]]
419
            SQL,
420
            $this->mock->getDriverName(),
421
        );
422
423
        $this->assertSame($expected, $sql);
424
        $this->assertEmpty($params);
425
426
        /* array syntax */
427
        $query = $this->mock->query()->select('*')->from('operations')->groupBy(['name', 'date']);
428
429
        [$sql, $params] = $this->queryBuilder->build($query);
430
431
        $expected = DbHelper::replaceQuotes(
432
            <<<SQL
433
            SELECT * FROM [[operations]] GROUP BY [[name]], [[date]]
434
            SQL,
435
            $this->mock->getDriverName(),
436
        );
437
438
        $this->assertSame($expected, $sql);
439
        $this->assertEmpty($params);
440
441
        /* expression */
442
        $query = $this->mock
443
            ->query()
444
            ->select('*')
445
            ->from('operations')
446
            ->where('account_id = accounts.id')
447
            ->groupBy(new Expression('SUBSTR(name, 0, 1), x'));
448
449
        [$sql, $params] = $this->queryBuilder->build($query);
450
451
        $expected = DbHelper::replaceQuotes(
452
            <<<SQL
453
            SELECT * FROM [[operations]] WHERE account_id = accounts.id GROUP BY SUBSTR(name, 0, 1), x
454
            SQL,
455
            $this->mock->getDriverName(),
456
        );
457
458
        $this->assertSame($expected, $sql);
459
        $this->assertEmpty($params);
460
461
        /* expression with params */
462
        $query = $this->mock
463
            ->query()
464
            ->select('*')
465
            ->from('operations')
466
            ->groupBy(new Expression('SUBSTR(name, 0, :to), x', [':to' => 4]));
467
468
        [$sql, $params] = $this->queryBuilder->build($query);
469
470
        $expected = DbHelper::replaceQuotes(
471
            <<<SQL
472
            SELECT * FROM [[operations]] GROUP BY SUBSTR(name, 0, :to), x
473
            SQL,
474
            $this->mock->getDriverName(),
475
        );
476
477
        $this->assertSame($expected, $sql);
478
        $this->assertSame([':to' => 4], $params);
479
    }
480
481
    /**
482
     * {@see https://github.com/yiisoft/yii2/issues/15653}
483
     */
484
    public function testIssue15653(): void
485
    {
486
        $query = $this->mock->query()->from('admin_user')->where(['is_deleted' => false]);
487
        $query->where([])->andWhere(['in', 'id', ['1', '0']]);
488
489
        [$sql, $params] = $this->queryBuilder->build($query);
490
491
        $this->assertSame(
492
            DbHelper::replaceQuotes(
493
                <<<SQL
494
                SELECT * FROM [[admin_user]] WHERE [[id]] IN (:qp0, :qp1)
495
                SQL,
496
                $this->mock->getDriverName(),
497
            ),
498
            $sql,
499
        );
500
        $this->assertSame([':qp0' => '1', ':qp1' => '0'], $params);
501
    }
502
503
    public function testOrderBy(): void
504
    {
505
        /* simple string */
506
        $query = $this->mock->query()->select('*')->from('operations')->orderBy('name ASC, date DESC');
507
508
        [$sql, $params] = $this->queryBuilder->build($query);
509
510
        $expected = DbHelper::replaceQuotes(
511
            <<<SQL
512
            SELECT * FROM [[operations]] ORDER BY [[name]], [[date]] DESC
513
            SQL,
514
            $this->mock->getDriverName(),
515
        );
516
517
        $this->assertSame($expected, $sql);
518
        $this->assertEmpty($params);
519
520
        /* array syntax */
521
        $query = $this->mock->query()->select('*')->from('operations')->orderBy(['name' => SORT_ASC, 'date' => SORT_DESC]);
522
523
        [$sql, $params] = $this->queryBuilder->build($query);
524
525
        $expected = DbHelper::replaceQuotes(
526
            <<<SQL
527
            SELECT * FROM [[operations]] ORDER BY [[name]], [[date]] DESC
528
            SQL,
529
            $this->mock->getDriverName(),
530
        );
531
532
        $this->assertSame($expected, $sql);
533
        $this->assertEmpty($params);
534
535
        /* expression */
536
        $query = $this->mock
537
            ->query()
538
            ->select('*')
539
            ->from('operations')
540
            ->where('account_id = accounts.id')
541
            ->orderBy(new Expression('SUBSTR(name, 3, 4) DESC, x ASC'));
542
543
        [$sql, $params] = $this->queryBuilder->build($query);
544
545
        $expected = DbHelper::replaceQuotes(
546
            <<<SQL
547
            SELECT * FROM [[operations]] WHERE account_id = accounts.id ORDER BY SUBSTR(name, 3, 4) DESC, x ASC
548
            SQL,
549
            $this->mock->getDriverName(),
550
        );
551
552
        $this->assertSame($expected, $sql);
553
        $this->assertEmpty($params);
554
555
        /* expression with params */
556
        $query = $this->mock
557
            ->query()
558
            ->select('*')
559
            ->from('operations')
560
            ->orderBy(new Expression('SUBSTR(name, 3, :to) DESC, x ASC', [':to' => 4]));
561
562
        [$sql, $params] = $this->queryBuilder->build($query);
563
564
        $expected = DbHelper::replaceQuotes(
565
            <<<SQL
566
            SELECT * FROM [[operations]] ORDER BY SUBSTR(name, 3, :to) DESC, x ASC
567
            SQL,
568
            $this->mock->getDriverName(),
569
        );
570
571
        $this->assertSame($expected, $sql);
572
        $this->assertSame([':to' => 4], $params);
573
    }
574
575
    public function testSelectExpression(): void
576
    {
577
        $query = $this->mock->query()->select(new Expression('1 AS ab'))->from('tablename');
578
579
        [$sql, $params] = $this->queryBuilder->build($query);
580
581
        $expected = DbHelper::replaceQuotes(
582
            <<<SQL
583
            SELECT 1 AS ab FROM [[tablename]]
584
            SQL,
585
            $this->mock->getDriverName(),
586
        );
587
588
        $this->assertSame($expected, $sql);
589
        $this->assertEmpty($params);
590
591
        $query = $this->mock
592
            ->query()
593
            ->select(new Expression('1 AS ab'))
594
            ->addSelect(new Expression('2 AS cd'))
595
            ->addSelect(['ef' => new Expression('3')])
596
            ->from('tablename');
597
598
        [$sql, $params] = $this->queryBuilder->build($query);
599
600
        $expected = DbHelper::replaceQuotes(
601
            <<<SQL
602
            SELECT 1 AS ab, 2 AS cd, 3 AS [[ef]] FROM [[tablename]]
603
            SQL,
604
            $this->mock->getDriverName(),
605
        );
606
607
        $this->assertSame($expected, $sql);
608
        $this->assertEmpty($params);
609
610
        $query = $this->mock
611
            ->query()
612
            ->select(new Expression('SUBSTR(name, 0, :len)', [':len' => 4]))
613
            ->from('tablename');
614
615
        [$sql, $params] = $this->queryBuilder->build($query);
616
617
        $expected = DbHelper::replaceQuotes(
618
            <<<SQL
619
            SELECT SUBSTR(name, 0, :len) FROM [[tablename]]
620
            SQL,
621
            $this->mock->getDriverName(),
622
        );
623
624
        $this->assertSame($expected, $sql);
625
        $this->assertSame([':len' => 4], $params);
626
    }
627
628
    public function testSelectSubquery(): void
629
    {
630
        $expected = DbHelper::replaceQuotes(
631
            <<<SQL
632
            SELECT *, (SELECT COUNT(*) FROM [[operations]] WHERE account_id = accounts.id) AS [[operations_count]] FROM [[accounts]]
633
            SQL,
634
            $this->mock->getDriverName(),
635
        );
636
637
        $subquery = $this->mock
638
            ->query()
639
            ->select('COUNT(*)')
640
            ->from('operations')
641
            ->where('account_id = accounts.id');
642
643
        $query = $this->mock
644
            ->query()
645
            ->select('*')
646
            ->from('accounts')
647
            ->addSelect(['operations_count' => $subquery]);
648
649
        [$sql, $params] = $this->queryBuilder->build($query);
650
651
        $this->assertSame($expected, $sql);
652
        $this->assertEmpty($params);
653
    }
654
}
655