Passed
Pull Request — master (#405)
by Wilmer
31:05 queued 28:30
created

AbstractQueryBuilderTest::testAddForeignKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
nc 1
nop 8
dl 0
loc 16
rs 10
c 1
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Tests;
6
7
use Closure;
8
use PHPUnit\Framework\TestCase;
9
use stdClass;
10
use Yiisoft\Arrays\ArrayHelper;
11
use Yiisoft\Db\Exception\InvalidArgumentException;
12
use Yiisoft\Db\Exception\NotSupportedException;
13
use Yiisoft\Db\Expression\Expression;
14
use Yiisoft\Db\Expression\ExpressionBuilderInterface;
15
use Yiisoft\Db\Expression\ExpressionInterface;
16
use Yiisoft\Db\Query\Query;
17
use Yiisoft\Db\Query\QueryInterface;
18
use Yiisoft\Db\QueryBuilder\Condition\SimpleCondition;
19
use Yiisoft\Db\Schema\QuoterInterface;
20
use Yiisoft\Db\Schema\Schema;
21
use Yiisoft\Db\Tests\Support\Assert;
22
use Yiisoft\Db\Tests\Support\DbHelper;
23
use Yiisoft\Db\Tests\Support\TestTrait;
24
25
abstract class AbstractQueryBuilderTest extends TestCase
26
{
27
    use TestTrait;
28
29
    public function testAddCheck(): void
30
    {
31
        $db = $this->getConnection();
32
33
        $qb = $db->getQueryBuilder();
34
        $sql = $qb->addCheck('T_constraints_1', 'CN_check', '[[C_not_null]] > 100');
35
36
        $this->assertSame(
37
            DbHelper::replaceQuotes(
38
                <<<SQL
39
                ALTER TABLE [[CN_check]] ADD CONSTRAINT [[T_constraints_1]] CHECK ([[C_not_null]] > 100)
40
                SQL,
41
                $db->getName(),
42
            ),
43
            $sql,
44
        );
45
    }
46
47
    public function testAddColumn(): void
48
    {
49
        $db = $this->getConnection();
50
51
        $qb = $db->getQueryBuilder();
52
        $schema = $db->getSchema();
53
        $sql = $qb->addColumn('table', 'column', $schema::TYPE_STRING);
0 ignored issues
show
Bug introduced by
The constant Yiisoft\Db\Schema\SchemaInterface::TYPE_STRING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
54
55
        $this->assertSame(
56
            DbHelper::replaceQuotes(
57
                <<<SQL
58
                ALTER TABLE [[table]] ADD [[column]]
59
                SQL . ' ' . $qb->getColumnType($schema::TYPE_STRING),
60
                $db->getName(),
61
            ),
62
            $sql,
63
        );
64
    }
65
66
    public function testAddCommentOnColumn(): void
67
    {
68
        $db = $this->getConnection();
69
70
        $qb = $db->getQueryBuilder();
71
        $sql = $qb->addCommentOnColumn('customer', 'id', 'Primary key.');
72
73
        $this->assertSame(
74
            DbHelper::replaceQuotes(
75
                <<<SQL
76
                COMMENT ON COLUMN [[customer]].[[id]] IS 'Primary key.'
77
                SQL,
78
                $db->getName(),
79
            ),
80
            $sql,
81
        );
82
    }
83
84
    public function testAddCommentOnTable(): void
85
    {
86
        $db = $this->getConnection();
87
88
        $qb = $db->getQueryBuilder();
89
        $sql = $qb->addCommentOnTable('customer', 'Customer table.');
90
91
        $this->assertSame(
92
            DbHelper::replaceQuotes(
93
                <<<SQL
94
                COMMENT ON TABLE [[customer]] IS 'Customer table.'
95
                SQL,
96
                $db->getName(),
97
            ),
98
            $sql,
99
        );
100
    }
101
102
    public function testAddDefaultValue(): void
103
    {
104
        $db = $this->getConnection();
105
106
        $qb = $db->getQueryBuilder();
107
        $sql = $qb->addDefaultValue('CN_pk', 'T_constraints_1', 'C_default', 1);
108
109
        $this->assertSame(
110
            DbHelper::replaceQuotes(
111
                <<<SQL
112
                ALTER TABLE [[T_constraints_1]] ALTER COLUMN [[C_default]] SET DEFAULT 1
113
                SQL,
114
                $db->getName(),
115
            ),
116
            $sql,
117
        );
118
    }
119
120
    /**
121
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addForeignKey()
122
     */
123
    public function testAddForeignKey(
124
        string $name,
125
        string $table,
126
        array|string $columns,
127
        string $refTable,
128
        array|string $refColumns,
129
        string|null $delete,
130
        string|null $update,
131
        string $expected
132
    ): void {
133
        $db = $this->getConnection();
134
135
        $qb = $db->getQueryBuilder();
136
        $sql = $qb->addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete, $update);
137
138
        $this->assertSame($expected, $sql);
139
    }
140
141
    /**
142
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addPrimaryKey()
143
     */
144
    public function testAddPrimaryKey(string $name, string $table, array|string $columns, string $expected): void
145
    {
146
        $db = $this->getConnection();
147
148
        $qb = $db->getQueryBuilder();
149
        $sql = $qb->addPrimaryKey($name, $table, $columns);
150
151
        $this->assertSame($expected, $sql);
152
    }
153
154
    /**
155
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addUnique()
156
     */
157
    public function testAddUnique(string $name, string $table, array|string $columns, string $expected): void
158
    {
159
        $db = $this->getConnection();
160
161
        $qb = $db->getQueryBuilder();
162
        $sql = $qb->addUnique($name, $table, $columns);
163
164
        $this->assertSame($expected, $sql);
165
    }
166
167
    public function testAlterColumn(): void
168
    {
169
        $db = $this->getConnection();
170
171
        $qb = $db->getQueryBuilder();
172
        $schema = $db->getSchema();
173
        $sql = $qb->alterColumn('customer', 'email', $schema::TYPE_STRING);
0 ignored issues
show
Bug introduced by
The constant Yiisoft\Db\Schema\SchemaInterface::TYPE_STRING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
174
175
        $this->assertSame(
176
            DbHelper::replaceQuotes(
177
                <<<SQL
178
                ALTER TABLE [[customer]] CHANGE [[email]] [[email]]
179
                SQL . ' ' . $qb->getColumnType($schema::TYPE_STRING),
180
                $db->getName(),
181
            ),
182
            $sql,
183
        );
184
    }
185
186
    /**
187
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::batchInsert()
188
     */
189
    public function testBatchInsert(string $table, array $columns, array $rows, string $expected): void
190
    {
191
        $db = $this->getConnection();
192
193
        $qb = $db->getQueryBuilder();
194
        $sql = $qb->batchInsert($table, $columns, $rows);
195
196
        $this->assertSame($expected, $sql);
197
    }
198
199
    /**
200
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildCondition()
201
     */
202
    public function testBuildCondition(
203
        array|ExpressionInterface|string $condition,
204
        string|null $expected,
205
        array $expectedParams
206
    ): void {
207
        $db = $this->getConnection();
208
209
        $query = (new Query($db))->where($condition);
210
211
        [$sql, $params] = $db->getQueryBuilder()->build($query);
212
213
        $replacedQuotes = DbHelper::replaceQuotes($expected, $db->getName());
0 ignored issues
show
Bug introduced by
It seems like $expected can also be of type null; however, parameter $sql of Yiisoft\Db\Tests\Support\DbHelper::replaceQuotes() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

213
        $replacedQuotes = DbHelper::replaceQuotes(/** @scrutinizer ignore-type */ $expected, $db->getName());
Loading history...
214
215
        $this->assertIsString($replacedQuotes);
216
        $this->assertEquals('SELECT *' . (empty($expected) ? '' : ' WHERE ' . $replacedQuotes), $sql);
217
        $this->assertEquals($expectedParams, $params);
218
    }
219
220
    public function testBuildColumnsWithString(): void
221
    {
222
        $db = $this->getConnection();
223
224
        $qb = $db->getQueryBuilder();
225
226
        $this->assertSame('(id)', $qb->buildColumns('(id)'));
227
    }
228
229
    public function testBuildColumnsWithArray(): void
230
    {
231
        $db = $this->getConnection();
232
233
        $qb = $db->getQueryBuilder();
234
235
        $this->assertSame(
236
            DbHelper::replaceQuotes('[[id]], [[name]], [[email]], [[address]], [[status]]', $db->getName()),
237
            $qb->buildColumns(['id', 'name', 'email', 'address', 'status']),
238
        );
239
    }
240
241
    public function testBuildColumnsWithExpression(): void
242
    {
243
        $db = $this->getConnection();
244
245
        $qb = $db->getQueryBuilder();
246
247
        $this->assertSame(
248
            DbHelper::replaceQuotes(
249
                '[[id]], [[name]], [[email]], [[address]], [[status]], COUNT(*)',
250
                $db->getName(),
251
            ),
252
            $qb->buildColumns(['id', 'name', 'email', 'address', 'status', new Expression('COUNT(*)')]),
253
        );
254
    }
255
256
    /**
257
     * {@see https://github.com/yiisoft/yii2/issues/15653}
258
     */
259
    public function testBuildIssue15653(): void
260
    {
261
        $db = $this->getConnection();
262
263
        $qb = $db->getQueryBuilder();
264
        $query = (new Query($db))->from('admin_user')->where(['is_deleted' => false]);
265
        $query->where([])->andWhere(['in', 'id', ['1', '0']]);
266
267
        [$sql, $params] = $qb->build($query);
268
269
        $this->assertSame(
270
            DbHelper::replaceQuotes(
271
                <<<SQL
272
                SELECT * FROM [[admin_user]] WHERE [[id]] IN (:qp0, :qp1)
273
                SQL,
274
                $db->getName(),
275
            ),
276
            $sql,
277
        );
278
        $this->assertSame([':qp0' => '1', ':qp1' => '0'], $params);
279
    }
280
281
    /**
282
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildFilterCondition()
283
     */
284
    public function testBuildFilterCondition(array $condition, string $expected, array $expectedParams): void
285
    {
286
        $db = $this->getConnection();
287
288
        $qb = $db->getQueryBuilder();
289
        $query = (new Query($db))->filterWhere($condition);
290
291
        [$sql, $params] = $qb->build($query);
292
293
        $this->assertSame(
294
            'SELECT *' . (
295
                empty($expected) ? '' : ' WHERE ' . DbHelper::replaceQuotes($expected, $db->getName())
296
            ),
297
            $sql,
298
        );
299
        $this->assertSame($expectedParams, $params);
300
    }
301
302
    public function testBuildFrom(): void
303
    {
304
        $db = $this->getConnection();
305
306
        $qb = $db->getQueryBuilder();
307
        $query = (new Query($db))->from('admin_user');
308
        $params = [];
309
310
        $this->assertSame(
311
            DbHelper::replaceQuotes(
312
                <<<SQL
313
                FROM [[admin_user]]
314
                SQL,
315
                $db->getName(),
316
            ),
317
            $qb->buildFrom($query->getFrom(), $params),
318
        );
319
    }
320
321
    public function testBuildGroupBy(): void
322
    {
323
        $db = $this->getConnection();
324
325
        $qb = $db->getQueryBuilder();
326
        $query = (new Query($db))->from('admin_user')->groupBy(['id', 'name']);
327
        $params = [];
328
329
        $this->assertSame(
330
            DbHelper::replaceQuotes(
331
                <<<SQL
332
                GROUP BY [[id]], [[name]]
333
                SQL,
334
                $db->getName(),
335
            ),
336
            $qb->buildGroupBy($query->getGroupBy(), $params),
337
        );
338
    }
339
340
    public function testBuildHaving(): void
341
    {
342
        $db = $this->getConnection();
343
344
        $qb = $db->getQueryBuilder();
345
        $query = (new Query($db))->from('admin_user')->having(['id' => 1]);
346
        $params = [];
347
348
        $this->assertSame(
349
            DbHelper::replaceQuotes(
350
                <<<SQL
351
                HAVING [[id]]=:qp0
352
                SQL,
353
                $db->getName(),
354
            ),
355
            $qb->buildHaving($query->getHaving(), $params),
356
        );
357
    }
358
359
    public function testBuildJoin(): void
360
    {
361
        $db = $this->getConnection();
362
363
        $qb = $db->getQueryBuilder();
364
        $query = (new Query($db))
365
            ->from('admin_user')
366
            ->join('INNER JOIN', 'admin_profile', 'admin_user.id = admin_profile.user_id');
367
        $params = [];
368
369
        $this->assertSame(
370
            DbHelper::replaceQuotes(
371
                <<<SQL
372
                INNER JOIN [[admin_profile]] ON admin_user.id = admin_profile.user_id
373
                SQL,
374
                $db->getName(),
375
            ),
376
            $qb->buildJoin($query->getJoin(), $params),
377
        );
378
    }
379
380
    /**
381
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildLikeCondition()
382
     */
383
    public function testBuildLikeCondition(
384
        array|ExpressionInterface $condition,
385
        string $expected,
386
        array $expectedParams
387
    ): void {
388
        $db = $this->getConnection();
389
390
        $query = (new Query($db))->where($condition);
391
392
        [$sql, $params] = $db->getQueryBuilder()->build($query);
393
394
        $replacedQuotes = DbHelper::replaceQuotes($expected, $db->getName());
395
396
        $this->assertIsString($replacedQuotes);
397
        $this->assertSame('SELECT *' . (empty($expected) ? '' : ' WHERE ' . $replacedQuotes), $sql);
398
        $this->assertSame($expectedParams, $params);
399
    }
400
401
    public function testBuildLimit(): void
402
    {
403
        $db = $this->getConnection();
404
405
        $qb = $db->getQueryBuilder();
406
        $query = (new Query($db))->from('admin_user')->limit(10);
407
408
        $this->assertSame('LIMIT 10', $qb->buildLimit($query->getLimit(), 0));
409
    }
410
411
    public function testBuildLimitOffset(): void
412
    {
413
        $db = $this->getConnection();
414
415
        $qb = $db->getQueryBuilder();
416
        $query = (new Query($db))->from('admin_user')->limit(10)->offset(5);
417
418
        $this->assertSame('LIMIT 10 OFFSET 5', $qb->buildLimit($query->getLimit(), $query->getOffset()));
419
    }
420
421
    public function testBuildOrderBy(): void
422
    {
423
        $db = $this->getConnection();
424
425
        $qb = $db->getQueryBuilder();
426
        $query = (new Query($db))->from('admin_user')->orderBy(['id' => SORT_ASC, 'name' => SORT_DESC]);
427
        $params = [];
428
429
        $this->assertSame(
430
            DbHelper::replaceQuotes(
431
                <<<SQL
432
                ORDER BY [[id]], [[name]] DESC
433
                SQL,
434
                $db->getName(),
435
            ),
436
            $qb->buildOrderBy($query->getOrderBy(), $params),
437
        );
438
    }
439
440
    public function testBuildOrderByAndLimit(): void
441
    {
442
        $db = $this->getConnection();
443
444
        $qb = $db->getQueryBuilder();
445
        $query = (new Query($db))
446
            ->from('admin_user')
447
            ->orderBy(['id' => SORT_ASC, 'name' => SORT_DESC])
448
            ->limit(10)
449
            ->offset(5);
450
451
        $this->assertSame(
452
            DbHelper::replaceQuotes(
453
                <<<SQL
454
                SELECT * FROM [[admin_user]] ORDER BY [[id]], [[name]] DESC LIMIT 10 OFFSET 5
455
                SQL,
456
                $db->getName(),
457
            ),
458
            $qb->buildOrderByAndLimit(
459
                DbHelper::replaceQuotes(
460
                    <<<SQL
461
                    SELECT * FROM [[admin_user]]
462
                    SQL,
463
                    $db->getName(),
464
                ),
465
                $query->getOrderBy(),
466
                $query->getLimit(),
467
                $query->getOffset(),
468
            ),
469
        );
470
    }
471
472
    public function testBuildSelect(): void
473
    {
474
        $db = $this->getConnection();
475
476
        $qb = $db->getQueryBuilder();
477
        $query = (new Query($db))->select(['id', 'name', 'email', 'address', 'status']);
478
        $params = [];
479
480
        $this->assertSame(
481
            DbHelper::replaceQuotes(
482
                <<<SQL
483
                SELECT [[id]], [[name]], [[email]], [[address]], [[status]]
484
                SQL,
485
                $db->getName(),
486
            ),
487
            $qb->buildSelect($query->getSelect(), $params),
488
        );
489
    }
490
491
    public function testBuildSelectWithDistinct(): void
492
    {
493
        $db = $this->getConnection();
494
495
        $qb = $db->getQueryBuilder();
496
        $query = (new Query($db))->select(['id', 'name', 'email', 'address', 'status'])->distinct();
497
        $params = [];
498
499
        $this->assertSame(
500
            DbHelper::replaceQuotes(
501
                <<<SQL
502
                SELECT DISTINCT [[id]], [[name]], [[email]], [[address]], [[status]]
503
                SQL,
504
                $db->getName(),
505
            ),
506
            $qb->buildSelect($query->getSelect(), $params, true),
507
        );
508
    }
509
510
    public function testBuildUnion(): void
511
    {
512
        $db = $this->getConnection();
513
514
        $qb = $db->getQueryBuilder();
515
        $query = (new Query($db))->from('admin_user')->union((new Query($db))->from('admin_profile'));
516
        $params = [];
517
518
        $this->assertSame(
519
            DbHelper::replaceQuotes(
520
                <<<SQL
521
                UNION ( SELECT * FROM [[admin_profile]] )
522
                SQL,
523
                $db->getName(),
524
            ),
525
            $qb->buildUnion($query->getUnion(), $params),
526
        );
527
    }
528
529
    public function testBuildWithQueries(): void
530
    {
531
        $db = $this->getConnection();
532
533
        $qb = $db->getQueryBuilder();
534
        $query = (new Query($db))->withQuery((new Query($db))->from('admin_user')->from('admin_profile'), 'cte');
535
        $params = [];
536
537
        $this->assertSame(
538
            DbHelper::replaceQuotes(
539
                <<<SQL
540
                WITH cte AS (SELECT * FROM [[admin_profile]])
541
                SQL,
542
                $db->getName(),
543
            ),
544
            $qb->buildWithQueries($query->getWithQueries(), $params),
545
        );
546
    }
547
548
    public function testBuildWithComplexSelect(): void
549
    {
550
        $db = $this->getConnection();
551
552
        $qb = $db->getQueryBuilder();
553
        $expressionString = DbHelper::replaceQuotes(
554
            <<<SQL
555
            case t.Status_Id when 1 then 'Acknowledge' when 2 then 'No Action' else 'Unknown Action' END as [[Next Action]]
556
            SQL,
557
            $db->getName(),
558
        );
559
560
        $this->assertIsString($expressionString);
561
562
        $query = (new Query($db))
563
            ->select(
564
                [
565
                    'ID' => 't.id',
566
                    'gsm.username as GSM',
567
                    'part.Part',
568
                    'Part Cost' => 't.Part_Cost',
569
                    'st_x(location::geometry) as lon',
570
                    new Expression($expressionString),
571
                ]
572
            )
573
            ->from('tablename');
574
575
        [$sql, $params] = $qb->build($query);
576
577
        $this->assertSame(
578
            DbHelper::replaceQuotes(
579
                <<<SQL
580
                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]]
581
                SQL,
582
                $db->getName(),
583
            ),
584
            $sql,
585
        );
586
        $this->assertEmpty($params);
587
    }
588
589
    /**
590
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildFrom()
591
     */
592
    public function testBuildWithFrom(mixed $table, string $expectedSql, array $expectedParams = []): void
593
    {
594
        $db = $this->getConnection();
595
596
        $query = (new Query($db))->from($table);
597
        $queryBuilder = $db->getQueryBuilder();
598
599
        [$sql, $params] = $queryBuilder->build($query);
600
601
        $this->assertSame($expectedSql, $sql);
602
        $this->assertSame($expectedParams, $params);
603
    }
604
605
    public function testBuildWithFromAliasesNoExist(): void
606
    {
607
        $db = $this->getConnection();
608
609
        $qb = $db->getQueryBuilder();
610
        $query = (new Query($db))->from('no_exist_table');
611
612
        [$sql, $params] = $qb->build($query);
613
614
        $this->assertSame(
615
            DbHelper::replaceQuotes(
616
                <<<SQL
617
                SELECT * FROM [[no_exist_table]]
618
                SQL,
619
                $db->getName(),
620
            ),
621
            $sql,
622
        );
623
624
        $this->assertSame([], $params);
625
    }
626
627
    /**
628
     * {@see https://github.com/yiisoft/yii2/issues/10869}
629
     */
630
    public function testBuildWithFromIndexHint(): void
631
    {
632
        $db = $this->getConnection();
633
634
        $qb = $db->getQueryBuilder();
635
        $query = (new Query($db))->from([new Expression('{{%user}} USE INDEX (primary)')]);
636
637
        [$sql, $params] = $qb->build($query);
638
639
        $this->assertSame(
640
            DbHelper::replaceQuotes(
641
                <<<SQL
642
                SELECT * FROM {{%user}} USE INDEX (primary)
643
                SQL,
644
                $db->getName(),
645
            ),
646
            $sql,
647
        );
648
649
        $this->assertEmpty($params);
650
651
        $query = (new Query($db))
652
            ->from([new Expression('{{user}} {{t}} FORCE INDEX (primary) IGNORE INDEX FOR ORDER BY (i1)')])
653
            ->leftJoin(['p' => 'profile'], 'user.id = profile.user_id USE INDEX (i2)');
654
655
        [$sql, $params] = $qb->build($query);
656
657
        $this->assertSame(
658
            DbHelper::replaceQuotes(
659
                <<<SQL
660
                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)
661
                SQL,
662
                $db->getName(),
663
            ),
664
            $sql,
665
        );
666
667
        $this->assertEmpty($params);
668
    }
669
670
    public function testBuildWithFromSubquery(): void
671
    {
672
        $db = $this->getConnection();
673
674
        $qb = $db->getQueryBuilder();
675
676
        /* subquery */
677
        $subquery = (new Query($db))->from('user')->where('account_id = accounts.id');
678
        $query = (new Query($db))->from(['activeusers' => $subquery]);
679
680
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
681
        [$sql, $params] = $qb->build($query);
682
683
        $this->assertSame(
684
            DbHelper::replaceQuotes(
685
                <<<SQL
686
                SELECT * FROM (SELECT * FROM [[user]] WHERE account_id = accounts.id) [[activeusers]]
687
                SQL,
688
                $db->getName(),
689
            ),
690
            $sql,
691
        );
692
        $this->assertEmpty($params);
693
694
        /* subquery with params */
695
        $subquery = (new Query($db))->from('user')->where('account_id = :id', ['id' => 1]);
696
        $query = (new Query($db))->from(['activeusers' => $subquery])->where('abc = :abc', ['abc' => 'abc']);
697
698
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
699
        [$sql, $params] = $qb->build($query);
700
701
        $this->assertSame(
702
            DbHelper::replaceQuotes(
703
                <<<SQL
704
                SELECT * FROM (SELECT * FROM [[user]] WHERE account_id = :id) [[activeusers]] WHERE abc = :abc
705
                SQL,
706
                $db->getName(),
707
            ),
708
            $sql,
709
        );
710
        $this->assertSame(['abc' => 'abc', 'id' => 1], $params);
711
712
        /* simple subquery */
713
        $subquery = '(SELECT * FROM user WHERE account_id = accounts.id)';
714
        $query = (new Query($db))->from(['activeusers' => $subquery]);
715
716
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
717
        [$sql, $params] = $qb->build($query);
718
719
        $this->assertSame(
720
            DbHelper::replaceQuotes(
721
                <<<SQL
722
                SELECT * FROM (SELECT * FROM user WHERE account_id = accounts.id) [[activeusers]]
723
                SQL,
724
                $db->getName(),
725
            ),
726
            $sql,
727
        );
728
        $this->assertEmpty($params);
729
    }
730
731
    public function testBuildWithGroupBy(): void
732
    {
733
        $db = $this->getConnection();
734
735
        $qb = $db->getQueryBuilder();
736
737
        /* simple string */
738
        $query = (new Query($db))->select('*')->from('operations')->groupBy('name, date');
739
740
        [$sql, $params] = $qb->build($query);
741
742
        $this->assertSame(
743
            DbHelper::replaceQuotes(
744
                <<<SQL
745
                SELECT * FROM [[operations]] GROUP BY [[name]], [[date]]
746
                SQL,
747
                $db->getName(),
748
            ),
749
            $sql,
750
        );
751
        $this->assertEmpty($params);
752
753
        /* array syntax */
754
        $query = (new Query($db))->select('*')->from('operations')->groupBy(['name', 'date']);
755
756
        [$sql, $params] = $qb->build($query);
757
758
        $this->assertSame(
759
            DbHelper::replaceQuotes(
760
                <<<SQL
761
                SELECT * FROM [[operations]] GROUP BY [[name]], [[date]]
762
                SQL,
763
                $db->getName(),
764
            ),
765
            $sql,
766
        );
767
        $this->assertEmpty($params);
768
769
        /* expression */
770
        $query = (new Query($db))
771
            ->select('*')
772
            ->from('operations')
773
            ->where('account_id = accounts.id')
774
            ->groupBy(new Expression('SUBSTR(name, 0, 1), x'));
775
776
        [$sql, $params] = $qb->build($query);
777
778
        $this->assertSame(
779
            DbHelper::replaceQuotes(
780
                <<<SQL
781
                SELECT * FROM [[operations]] WHERE account_id = accounts.id GROUP BY SUBSTR(name, 0, 1), x
782
                SQL,
783
                $db->getName(),
784
            ),
785
            $sql,
786
        );
787
        $this->assertEmpty($params);
788
789
        /* expression with params */
790
        $query = (new Query($db))
791
            ->select('*')
792
            ->from('operations')
793
            ->groupBy(new Expression('SUBSTR(name, 0, :to), x', [':to' => 4]));
794
795
        [$sql, $params] = $qb->build($query);
796
797
        $this->assertSame(
798
            DbHelper::replaceQuotes(
799
                <<<SQL
800
                SELECT * FROM [[operations]] GROUP BY SUBSTR(name, 0, :to), x
801
                SQL,
802
                $db->getName(),
803
            ),
804
            $sql,
805
        );
806
        $this->assertSame([':to' => 4], $params);
807
    }
808
809
    public function testBuildWithLimit(): void
810
    {
811
        $db = $this->getConnection();
812
813
        $qb = $db->getQueryBuilder();
814
        $query = (new Query($db))->limit(10);
815
816
        [$sql, $params] = $qb->build($query);
817
818
        $this->assertSame(
819
            <<<SQL
820
            SELECT * LIMIT 10
821
            SQL,
822
            $sql,
823
        );
824
825
        $this->assertSame([], $params);
826
    }
827
828
    public function testBuildWithOffset(): void
829
    {
830
        $db = $this->getConnection();
831
832
        $qb = $db->getQueryBuilder();
833
        $query = (new Query($db))->offset(10);
834
835
        [$sql, $params] = $qb->build($query);
836
837
        $this->assertSame(
838
            <<<SQL
839
            SELECT * OFFSET 10
840
            SQL,
841
            $sql,
842
        );
843
        $this->assertSame([], $params);
844
    }
845
846
    public function testBuildWithOrderBy(): void
847
    {
848
        $db = $this->getConnection();
849
850
        $qb = $db->getQueryBuilder();
851
852
        /* simple string */
853
        $query = (new Query($db))->select('*')->from('operations')->orderBy('name ASC, date DESC');
854
855
        [$sql, $params] = $qb->build($query);
856
857
        $this->assertSame(
858
            DbHelper::replaceQuotes(
859
                <<<SQL
860
                SELECT * FROM [[operations]] ORDER BY [[name]], [[date]] DESC
861
                SQL,
862
                $db->getName(),
863
            ),
864
            $sql,
865
        );
866
        $this->assertEmpty($params);
867
868
        /* array syntax */
869
        $query = (new Query($db))->select('*')->from('operations')->orderBy(['name' => SORT_ASC, 'date' => SORT_DESC]);
870
871
        [$sql, $params] = $qb->build($query);
872
873
        $this->assertSame(
874
            DbHelper::replaceQuotes(
875
                <<<SQL
876
                SELECT * FROM [[operations]] ORDER BY [[name]], [[date]] DESC
877
                SQL,
878
                $db->getName(),
879
            ),
880
            $sql,
881
        );
882
        $this->assertEmpty($params);
883
884
        /* expression */
885
        $query = (new Query($db))
886
            ->select('*')
887
            ->from('operations')
888
            ->where('account_id = accounts.id')
889
            ->orderBy(new Expression('SUBSTR(name, 3, 4) DESC, x ASC'));
890
891
        [$sql, $params] = $qb->build($query);
892
893
        $this->assertSame(
894
            DbHelper::replaceQuotes(
895
                <<<SQL
896
                SELECT * FROM [[operations]] WHERE account_id = accounts.id ORDER BY SUBSTR(name, 3, 4) DESC, x ASC
897
                SQL,
898
                $db->getName(),
899
            ),
900
            $sql,
901
        );
902
        $this->assertEmpty($params);
903
904
        /* expression with params */
905
        $query = (new Query($db))
906
            ->select('*')
907
            ->from('operations')
908
            ->orderBy(new Expression('SUBSTR(name, 3, :to) DESC, x ASC', [':to' => 4]));
909
910
        [$sql, $params] = $qb->build($query);
911
912
        $this->assertSame(
913
            DbHelper::replaceQuotes(
914
                <<<SQL
915
                SELECT * FROM [[operations]] ORDER BY SUBSTR(name, 3, :to) DESC, x ASC
916
                SQL,
917
                $db->getName(),
918
            ),
919
            $sql,
920
        );
921
        $this->assertSame([':to' => 4], $params);
922
    }
923
924
    public function testBuildWithQuery(): void
925
    {
926
        $db = $this->getConnection();
927
928
        $qb = $db->getQueryBuilder();
929
        $with1Query = (new query($db))->select('id')->from('t1')->where('expr = 1');
930
        $with2Query = (new query($db))->select('id')->from('t2')->innerJoin('a1', 't2.id = a1.id')->where('expr = 2');
931
        $with3Query = (new query($db))->select('id')->from('t3')->where('expr = 3');
932
        $query = (new query($db))
933
            ->withQuery($with1Query, 'a1')
934
            ->withQuery($with2Query->union($with3Query), 'a2')
935
            ->from('a2');
936
937
        [$sql, $params] = $qb->build($query);
938
939
        $this->assertSame(
940
            DbHelper::replaceQuotes(
941
                <<<SQL
942
                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]]
943
                SQL,
944
                $db->getName(),
945
            ),
946
            $sql,
947
        );
948
949
        $this->assertSame([], $params);
950
    }
951
952
    public function testBuildWithQueryRecursive(): void
953
    {
954
        $db = $this->getConnection();
955
956
        $qb = $db->getQueryBuilder();
957
        $with1Query = (new Query($db))->select('id')->from('t1')->where('expr = 1');
958
        $query = (new Query($db))->withQuery($with1Query, 'a1', true)->from('a1');
959
960
        [$sql, $params] = $qb->build($query);
961
962
        $this->assertSame(
963
            DbHelper::replaceQuotes(
964
                <<<SQL
965
                WITH RECURSIVE a1 AS (SELECT [[id]] FROM [[t1]] WHERE expr = 1) SELECT * FROM [[a1]]
966
                SQL,
967
                $db->getName(),
968
            ),
969
            $sql,
970
        );
971
        $this->assertSame([], $params);
972
    }
973
974
    public function testBuildWithSelectExpression(): void
975
    {
976
        $db = $this->getConnection();
977
978
        $qb = $db->getQueryBuilder();
979
        $query = (new Query($db))->select(new Expression('1 AS ab'))->from('tablename');
980
981
        [$sql, $params] = $qb->build($query);
982
983
        $this->assertSame(
984
            DbHelper::replaceQuotes(
985
                <<<SQL
986
                SELECT 1 AS ab FROM [[tablename]]
987
                SQL,
988
                $db->getName(),
989
            ),
990
            $sql,
991
        );
992
        $this->assertEmpty($params);
993
994
        $query = (new Query($db))
995
            ->select(new Expression('1 AS ab'))
996
            ->addSelect(new Expression('2 AS cd'))
997
            ->addSelect(['ef' => new Expression('3')])
998
            ->from('tablename');
999
1000
        [$sql, $params] = $qb->build($query);
1001
1002
        $this->assertSame(
1003
            DbHelper::replaceQuotes(
1004
                <<<SQL
1005
                SELECT 1 AS ab, 2 AS cd, 3 AS [[ef]] FROM [[tablename]]
1006
                SQL,
1007
                $db->getName(),
1008
            ),
1009
            $sql,
1010
        );
1011
        $this->assertEmpty($params);
1012
1013
        $query = (new Query($db))
1014
            ->select(new Expression('SUBSTR(name, 0, :len)', [':len' => 4]))
1015
            ->from('tablename');
1016
1017
        [$sql, $params] = $qb->build($query);
1018
1019
        $this->assertSame(
1020
            DbHelper::replaceQuotes(
1021
                <<<SQL
1022
                SELECT SUBSTR(name, 0, :len) FROM [[tablename]]
1023
                SQL,
1024
                $db->getName(),
1025
            ),
1026
            $sql,
1027
        );
1028
        $this->assertSame([':len' => 4], $params);
1029
    }
1030
1031
    public function testBuildWithSelectSubquery(): void
1032
    {
1033
        $db = $this->getConnection();
1034
1035
        $qb = $db->getQueryBuilder();
1036
        $subquery = (new Query($db))->select('COUNT(*)')->from('operations')->where('account_id = accounts.id');
1037
        $query = (new Query($db))->select('*')->from('accounts')->addSelect(['operations_count' => $subquery]);
1038
1039
        [$sql, $params] = $qb->build($query);
1040
1041
        $this->assertSame(
1042
            DbHelper::replaceQuotes(
1043
                <<<SQL
1044
                SELECT *, (SELECT COUNT(*) FROM [[operations]] WHERE account_id = accounts.id) AS [[operations_count]] FROM [[accounts]]
1045
                SQL,
1046
                $db->getName(),
1047
            ),
1048
            $sql,
1049
        );
1050
        $this->assertEmpty($params);
1051
    }
1052
1053
    public function testBuildWithSelectOption(): void
1054
    {
1055
        $db = $this->getConnection();
1056
1057
        $qb = $db->getQueryBuilder();
1058
        $query = (new Query($db))->selectOption('DISTINCT');
1059
1060
        [$sql, $params] = $qb->build($query);
1061
1062
        $this->assertSame(
1063
            <<<SQL
1064
            SELECT DISTINCT *
1065
            SQL,
1066
            $sql,
1067
        );
1068
        $this->assertSame([], $params);
1069
    }
1070
1071
    public function testBuildWithSetSeparator(): void
1072
    {
1073
        $db = $this->getConnection();
1074
1075
        $qb = $db->getQueryBuilder();
1076
        $qb->setSeparator(' ');
1077
1078
        [$sql, $params] = $qb->build((new Query($db))->select('*')->from('table'));
1079
1080
        $this->assertSame(
1081
            DbHelper::replaceQuotes(
1082
                <<<SQL
1083
                SELECT * FROM [[table]]
1084
                SQL,
1085
                $db->getName(),
1086
            ),
1087
            $sql
1088
        );
1089
        $this->assertEmpty($params);
1090
1091
        $qb->setSeparator("\n");
1092
        [$sql, $params] = $qb->build((new Query($db))->select('*')->from('table'));
1093
1094
        $this->assertSame(
1095
            DbHelper::replaceQuotes(
1096
                <<<SQL
1097
                SELECT *
1098
                FROM [[table]]
1099
                SQL,
1100
                $db->getName(),
1101
            ),
1102
            $sql,
1103
        );
1104
        $this->assertEmpty($params);
1105
    }
1106
1107
    /**
1108
     * This test contains three select queries connected with UNION and UNION ALL constructions.
1109
     */
1110
    public function testBuildWithUnion(): void
1111
    {
1112
        $db = $this->getConnection();
1113
1114
        $qb = $db->getQueryBuilder();
1115
1116
        $secondQuery = (new Query($db))->select('id')->from('TotalTotalExample t2')->where('w > 5');
1117
        $thirdQuery = (new Query($db))->select('id')->from('TotalTotalExample t3')->where('w = 3');
1118
        $firtsQuery = (new Query($db))
1119
            ->select('id')
1120
            ->from('TotalExample t1')
1121
            ->where(['and', 'w > 0', 'x < 2'])
1122
            ->union($secondQuery)
1123
            ->union($thirdQuery, true);
1124
1125
        [$sql, $params] = $qb->build($firtsQuery);
1126
1127
        $this->assertSame(
1128
            DbHelper::replaceQuotes(
1129
                <<<SQL
1130
                (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 )
1131
                SQL,
1132
                $db->getName(),
1133
            ),
1134
            $sql,
1135
        );
1136
        $this->assertSame([], $params);
1137
    }
1138
1139
    /**
1140
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildWhereExists()
1141
     */
1142
    public function testBuildWithWhereExists(string $cond, string $expectedQuerySql): void
1143
    {
1144
        $db = $this->getConnection();
1145
1146
        $expectedQueryParams = [];
1147
1148
        $subQuery = new Query($db);
1149
        $subQuery->select('1')->from('Website w');
1150
        $query = new Query($db);
1151
        $query->select('id')->from('TotalExample t')->where([$cond, $subQuery]);
1152
1153
        [$actualQuerySql, $actualQueryParams] = $db->getQueryBuilder()->build($query);
1154
1155
        $this->assertSame($expectedQuerySql, $actualQuerySql);
1156
        $this->assertSame($expectedQueryParams, $actualQueryParams);
1157
    }
1158
1159
    public function testBuildWithWhereExistsArrayParameters(): void
1160
    {
1161
        $db = $this->getConnection();
1162
1163
        $qb = $db->getQueryBuilder();
1164
        $subQuery = (new query($db))
1165
            ->select('1')
1166
            ->from('Website w')
1167
            ->where('w.id = t.website_id')
1168
            ->andWhere(['w.merchant_id' => 6, 'w.user_id' => 210]);
1169
        $query = (new query($db))
1170
            ->select('id')
1171
            ->from('TotalExample t')
1172
            ->where(['exists', $subQuery])
1173
            ->andWhere(['t.some_column' => 'asd']);
1174
1175
        [$sql, $params] = $qb->build($query);
1176
1177
        $this->assertSame(
1178
            DbHelper::replaceQuotes(
1179
                <<<SQL
1180
                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)
1181
                SQL,
1182
                $db->getName(),
1183
            ),
1184
            $sql,
1185
        );
1186
        $this->assertSame([':qp0' => 6, ':qp1' => 210, ':qp2' => 'asd'], $params);
1187
    }
1188
1189
    public function testBuildWithWhereExistsWithParameters(): void
1190
    {
1191
        $db = $this->getConnection();
1192
1193
        $qb = $db->getQueryBuilder();
1194
        $subQuery = (new query($db))
1195
            ->select('1')
1196
            ->from('Website w')
1197
            ->where('w.id = t.website_id')
1198
            ->andWhere('w.merchant_id = :merchant_id', [':merchant_id' => 6]);
1199
        $query = (new query($db))
1200
            ->select('id')
1201
            ->from('TotalExample t')
1202
            ->where(['exists', $subQuery])
1203
            ->andWhere('t.some_column = :some_value', [':some_value' => 'asd']);
1204
1205
        [$sql, $params] = $qb->build($query);
1206
1207
        $this->assertSame(
1208
            DbHelper::replaceQuotes(
1209
                <<<SQL
1210
                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)
1211
                SQL,
1212
                $db->getName(),
1213
            ),
1214
            $sql,
1215
        );
1216
        $this->assertSame([':some_value' => 'asd', ':merchant_id' => 6], $params);
1217
    }
1218
1219
    public function testsCreateConditionFromArray(): void
1220
    {
1221
        $db = $this->getConnection();
1222
1223
        $qb = $db->getQueryBuilder();
1224
1225
        $condition = $qb->createConditionFromArray(['and', 'a = 1', 'b = 2']);
1226
1227
        $this->assertSame('AND', $condition->getOperator());
0 ignored issues
show
Bug introduced by
The method getOperator() does not exist on Yiisoft\Db\QueryBuilder\...face\ConditionInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Yiisoft\Db\QueryBuilder\...\HashConditionInterface or Yiisoft\Db\QueryBuilder\...e\NotConditionInterface or Yiisoft\Db\QueryBuilder\Condition\HashCondition or Yiisoft\Db\QueryBuilder\Condition\NotCondition. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1227
        $this->assertSame('AND', $condition->/** @scrutinizer ignore-call */ getOperator());
Loading history...
1228
        $this->assertSame(['a = 1', 'b = 2'], $condition->getExpressions());
0 ignored issues
show
Bug introduced by
The method getExpressions() does not exist on Yiisoft\Db\QueryBuilder\...face\ConditionInterface. It seems like you code against a sub-type of Yiisoft\Db\QueryBuilder\...face\ConditionInterface such as Yiisoft\Db\QueryBuilder\...ctionConditionInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1228
        $this->assertSame(['a = 1', 'b = 2'], $condition->/** @scrutinizer ignore-call */ getExpressions());
Loading history...
1229
1230
        $condition = $qb->createConditionFromArray(['or', 'a = 1', 'b = 2']);
1231
1232
        $this->assertSame('OR', $condition->getOperator());
1233
        $this->assertSame(['a = 1', 'b = 2'], $condition->getExpressions());
1234
1235
        $condition = $qb->createConditionFromArray(['and', 'a = 1', ['or', 'b = 2', 'c = 3']]);
1236
1237
        $this->assertSame('AND', $condition->getOperator());
1238
        $this->assertSame(['a = 1', ['or', 'b = 2', 'c = 3']], $condition->getExpressions());
1239
1240
        $condition = $qb->createConditionFromArray(['or', 'a = 1', ['and', 'b = 2', 'c = 3']]);
1241
1242
        $this->assertSame('OR', $condition->getOperator());
1243
        $this->assertSame(['a = 1', ['and', 'b = 2', 'c = 3']], $condition->getExpressions());
1244
1245
        $condition = $qb->createConditionFromArray(['and', 'a = 1', ['or', 'b = 2', ['and', 'c = 3', 'd = 4']]]);
1246
1247
        $this->assertSame('AND', $condition->getOperator());
1248
        $this->assertSame(['a = 1', ['or', 'b = 2', ['and', 'c = 3', 'd = 4']]], $condition->getExpressions());
1249
1250
        $condition = $qb->createConditionFromArray(['or', 'a = 1', ['and', 'b = 2', ['or', 'c = 3', 'd = 4']]]);
1251
1252
        $this->assertSame('OR', $condition->getOperator());
1253
        $this->assertSame(['a = 1', ['and', 'b = 2', ['or', 'c = 3', 'd = 4']]], $condition->getExpressions());
1254
1255
        $condition = $qb->createConditionFromArray(
1256
            ['and', 'a = 1', ['or', 'b = 2', ['and', 'c = 3', ['or', 'd = 4', 'e = 5']]]]
1257
        );
1258
        $this->assertSame('AND', $condition->getOperator());
1259
        $this->assertSame(
1260
            ['a = 1', ['or', 'b = 2', ['and', 'c = 3', ['or', 'd = 4', 'e = 5']]]],
1261
            $condition->getExpressions(),
1262
        );
1263
    }
1264
1265
    /**
1266
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::createIndex()
1267
     */
1268
    public function testCreateIndex(string $sql, Closure $builder): void
1269
    {
1270
        $db = $this->getConnection();
1271
1272
        $qb = $db->getQueryBuilder();
1273
1274
        $this->assertSame($db->getQuoter()->quoteSql($sql), $builder($qb));
1275
    }
1276
1277
    public function testCreateTable(): void
1278
    {
1279
        $db = $this->getConnection();
1280
1281
        $qb = $db->getQueryBuilder();
1282
1283
        $this->assertSame(
1284
            DbHelper::replaceQuotes(
1285
                <<<SQL
1286
                CREATE TABLE [[test]] (
1287
                \t[[id]] pk,
1288
                \t[[name]] string(255) NOT NULL,
1289
                \t[[email]] string(255) NOT NULL,
1290
                \t[[status]] integer NOT NULL,
1291
                \t[[created_at]] datetime NOT NULL
1292
                )
1293
                SQL,
1294
                $db->getName(),
1295
            ),
1296
            $qb->createTable(
1297
                'test',
1298
                [
1299
                    'id' => 'pk',
1300
                    'name' => 'string(255) NOT NULL',
1301
                    'email' => 'string(255) NOT NULL',
1302
                    'status' => 'integer NOT NULL',
1303
                    'created_at' => 'datetime NOT NULL',
1304
                ],
1305
            ),
1306
        );
1307
    }
1308
1309
    public function testCreateView(): void
1310
    {
1311
        $db = $this->getConnection();
1312
1313
        $qb = $db->getQueryBuilder();
1314
1315
        $this->assertSame(
1316
            DbHelper::replaceQuotes(
1317
                <<<SQL
1318
                CREATE VIEW [[animal_view]] AS SELECT [[1]]
1319
                SQL,
1320
                $db->getName(),
1321
            ),
1322
            $qb->createView('animal_view', (new query($db))->select('1')),
1323
        );
1324
    }
1325
1326
    /**
1327
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::delete()
1328
     */
1329
    public function testDelete(string $table, array|string $condition, string $expectedSQL, array $expectedParams): void
1330
    {
1331
        $db = $this->getConnection();
1332
1333
        $qb = $db->getQueryBuilder();
1334
        $actualParams = [];
1335
        $actualSQL = $qb->delete($table, $condition, $actualParams);
1336
1337
        $this->assertSame($expectedSQL, $actualSQL);
1338
        $this->assertSame($expectedParams, $actualParams);
1339
    }
1340
1341
    public function testDropCheck(): void
1342
    {
1343
        $db = $this->getConnection();
1344
1345
        $qb = $db->getQueryBuilder();
1346
1347
        $this->assertSame(
1348
            DbHelper::replaceQuotes(
1349
                <<<SQL
1350
                ALTER TABLE [[T_constraints_1]] DROP CONSTRAINT [[CN_check]]
1351
                SQL,
1352
                $db->getName(),
1353
            ),
1354
            $qb->dropCheck('CN_check', 'T_constraints_1'),
1355
        );
1356
    }
1357
1358
    public function testDropColumn(): void
1359
    {
1360
        $db = $this->getConnection();
1361
1362
        $qb = $db->getQueryBuilder();
1363
1364
        $this->assertSame(
1365
            DbHelper::replaceQuotes(
1366
                <<<SQL
1367
                ALTER TABLE [[customer]] DROP COLUMN [[id]]
1368
                SQL,
1369
                $db->getName(),
1370
            ),
1371
            $qb->dropColumn('customer', 'id'),
1372
        );
1373
    }
1374
1375
    public function testDropCommentFromColumn(): void
1376
    {
1377
        $db = $this->getConnection(true);
1378
1379
        $qb = $db->getQueryBuilder();
1380
1381
        $this->assertSame(
1382
            DbHelper::replaceQuotes(
1383
                <<<SQL
1384
                COMMENT ON COLUMN [customer].[id] IS NULL
1385
                SQL,
1386
                $db->getName(),
1387
            ),
1388
            $qb->dropCommentFromColumn('customer', 'id'),
1389
        );
1390
    }
1391
1392
    public function testDropCommentFromTable(): void
1393
    {
1394
        $db = $this->getConnection();
1395
1396
        $qb = $db->getQueryBuilder();
1397
1398
        $this->assertSame(
1399
            DbHelper::replaceQuotes(
1400
                <<<SQL
1401
                COMMENT ON TABLE [[customer]] IS NULL
1402
                SQL,
1403
                $db->getName(),
1404
            ),
1405
            $qb->dropCommentFromTable('customer'),
1406
        );
1407
    }
1408
1409
    public function testDropDefaultValue(): void
1410
    {
1411
        $db = $this->getConnection(true);
1412
1413
        $qb = $db->getQueryBuilder();
1414
1415
        $this->assertSame(
1416
            DbHelper::replaceQuotes(
1417
                <<<SQL
1418
                ALTER TABLE [[T_constraints_1]] ALTER COLUMN [[C_default]] DROP DEFAULT
1419
                SQL,
1420
                $db->getName(),
1421
            ),
1422
            $qb->dropDefaultValue('CN_pk', 'T_constraints_1'),
1423
        );
1424
    }
1425
1426
    public function testDropForeignKey(): void
1427
    {
1428
        $db = $this->getConnection();
1429
1430
        $qb = $db->getQueryBuilder();
1431
1432
        $this->assertSame(
1433
            DbHelper::replaceQuotes(
1434
                <<<SQL
1435
                ALTER TABLE [[T_constraints_3]] DROP CONSTRAINT [[CN_constraints_3]]
1436
                SQL,
1437
                $db->getName(),
1438
            ),
1439
            $qb->dropForeignKey('CN_constraints_3', 'T_constraints_3'),
1440
        );
1441
    }
1442
1443
    public function testDropIndex(): void
1444
    {
1445
        $db = $this->getConnection();
1446
1447
        $qb = $db->getQueryBuilder();
1448
1449
        $this->assertSame(
1450
            DbHelper::replaceQuotes(
1451
                <<<SQL
1452
                DROP INDEX [[CN_constraints_2_single]] ON [[T_constraints_2]]
1453
                SQL,
1454
                $db->getName(),
1455
            ),
1456
            $qb->dropIndex('CN_constraints_2_single', 'T_constraints_2'),
1457
        );
1458
    }
1459
1460
    public function testDropPrimaryKey(): void
1461
    {
1462
        $db = $this->getConnection();
1463
1464
        $qb = $db->getQueryBuilder();
1465
1466
        $this->assertSame(
1467
            DbHelper::replaceQuotes(
1468
                <<<SQL
1469
                ALTER TABLE [[T_constraints_1]] DROP CONSTRAINT [[CN_pk]]
1470
                SQL,
1471
                $db->getName(),
1472
            ),
1473
            $qb->dropPrimaryKey('CN_pk', 'T_constraints_1'),
1474
        );
1475
    }
1476
1477
    public function testDropTable(): void
1478
    {
1479
        $db = $this->getConnection();
1480
1481
        $qb = $db->getQueryBuilder();
1482
1483
        $this->assertSame(
1484
            DbHelper::replaceQuotes(
1485
                <<<SQL
1486
                DROP TABLE [[customer]]
1487
                SQL,
1488
                $db->getName(),
1489
            ),
1490
            $qb->dropTable('customer'),
1491
        );
1492
    }
1493
1494
    public function testDropUnique(): void
1495
    {
1496
        $db = $this->getConnection();
1497
1498
        $qb = $db->getQueryBuilder();
1499
1500
        $this->assertSame(
1501
            DbHelper::replaceQuotes(
1502
                <<<SQL
1503
                ALTER TABLE [[test_uq]] DROP CONSTRAINT [[test_uq_constraint]]
1504
                SQL,
1505
                $db->getName(),
1506
            ),
1507
            $qb->dropUnique('test_uq_constraint', 'test_uq', ['int1']),
0 ignored issues
show
Unused Code introduced by
The call to Yiisoft\Db\QueryBuilder\...Interface::dropUnique() has too many arguments starting with array('int1'). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1507
            $qb->/** @scrutinizer ignore-call */ 
1508
                 dropUnique('test_uq_constraint', 'test_uq', ['int1']),

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
1508
        );
1509
    }
1510
1511
    public function testDropView(): void
1512
    {
1513
        $db = $this->getConnection(true);
1514
1515
        $qb = $db->getQueryBuilder();
1516
1517
        $this->assertSame(
1518
            DbHelper::replaceQuotes(
1519
                <<<SQL
1520
                DROP VIEW [[animal_view]]
1521
                SQL,
1522
                $db->getName(),
1523
            ),
1524
            $qb->dropview('animal_view'),
1525
        );
1526
    }
1527
1528
    public function testGetColumnType(): void
1529
    {
1530
        $db = $this->getConnection();
1531
1532
        $qb = $db->getQueryBuilder();
1533
1534
        $this->assertSame('pk', $qb->getColumnType(Schema::TYPE_PK));
1535
        $this->assertSame('upk', $qb->getColumnType(Schema::TYPE_UPK));
1536
        $this->assertSame('bigpk', $qb->getColumnType(Schema::TYPE_BIGPK));
1537
        $this->assertSame('ubigpk', $qb->getColumnType(Schema::TYPE_UBIGPK));
1538
        $this->assertSame('char', $qb->getColumnType(Schema::TYPE_CHAR));
1539
        $this->assertSame('string', $qb->getColumnType(Schema::TYPE_STRING));
1540
        $this->assertSame('text', $qb->getColumnType(Schema::TYPE_TEXT));
1541
        $this->assertSame('tinyint', $qb->getColumnType(Schema::TYPE_TINYINT));
1542
        $this->assertSame('smallint', $qb->getColumnType(Schema::TYPE_SMALLINT));
1543
        $this->assertSame('integer', $qb->getColumnType(Schema::TYPE_INTEGER));
1544
        $this->assertSame('bigint', $qb->getColumnType(Schema::TYPE_BIGINT));
1545
        $this->assertSame('float', $qb->getColumnType(Schema::TYPE_FLOAT));
1546
        $this->assertSame('double', $qb->getColumnType(Schema::TYPE_DOUBLE));
1547
        $this->assertSame('decimal', $qb->getColumnType(Schema::TYPE_DECIMAL));
1548
        $this->assertSame('datetime', $qb->getColumnType(Schema::TYPE_DATETIME));
1549
        $this->assertSame('timestamp', $qb->getColumnType(Schema::TYPE_TIMESTAMP));
1550
        $this->assertSame('time', $qb->getColumnType(Schema::TYPE_TIME));
1551
        $this->assertSame('date', $qb->getColumnType(Schema::TYPE_DATE));
1552
        $this->assertSame('binary', $qb->getColumnType(Schema::TYPE_BINARY));
1553
        $this->assertSame('boolean', $qb->getColumnType(Schema::TYPE_BOOLEAN));
1554
        $this->assertSame('money', $qb->getColumnType(Schema::TYPE_MONEY));
1555
        $this->assertSame('json', $qb->getColumnType(Schema::TYPE_JSON));
1556
    }
1557
1558
    public function testGetExpressionBuilder(): void
1559
    {
1560
        $db = $this->getConnection();
1561
1562
        $qb = $db->getQueryBuilder();
1563
1564
        $simpleCondition = new SimpleCondition('a', '=', 1);
1565
1566
        $this->assertInstanceOf(
1567
            ExpressionBuilderInterface::class,
1568
            $qb->getExpressionBuilder($simpleCondition),
1569
        );
1570
    }
1571
1572
    /**
1573
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::insert()
1574
     */
1575
    public function testInsert(
1576
        string $table,
1577
        array|QueryInterface $columns,
1578
        array $params,
1579
        string $expectedSQL,
1580
        array $expectedParams
1581
    ): void {
1582
        $db = $this->getConnection();
1583
1584
        $qb = $db->getQueryBuilder();
1585
1586
        $this->assertSame($expectedSQL, $qb->insert($table, $columns, $params));
1587
        $this->assertSame($expectedParams, $params);
1588
    }
1589
1590
    /**
1591
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::insertEx()
1592
     */
1593
    public function testInsertEx(
1594
        string $table,
1595
        array|QueryInterface $columns,
1596
        array $params,
1597
        string $expectedSQL,
1598
        array $expectedParams
1599
    ): void {
1600
        $db = $this->getConnection(true);
1601
1602
        $qb = $db->getQueryBuilder();
1603
1604
        $this->assertSame($expectedSQL, $qb->insertEx($table, $columns, $params));
1605
        $this->assertSame($expectedParams, $params);
1606
    }
1607
1608
    public function testQuoter(): void
1609
    {
1610
        $db = $this->getConnection();
1611
1612
        $qb = $db->getQueryBuilder();
1613
1614
        $this->assertInstanceOf(QuoterInterface::class, $qb->quoter());
1615
    }
1616
1617
    public function testRenameColumn(): void
1618
    {
1619
        $db = $this->getConnection();
1620
1621
        $qb = $db->getQueryBuilder();
1622
        $sql = $qb->renameColumn('alpha', 'string_identifier', 'string_identifier_test');
1623
1624
        $this->assertSame(
1625
            DbHelper::replaceQuotes(
1626
                <<<SQL
1627
                ALTER TABLE [[alpha]] RENAME COLUMN [[string_identifier]] TO [[string_identifier_test]]
1628
                SQL,
1629
                $db->getName(),
1630
            ),
1631
            $sql,
1632
        );
1633
    }
1634
1635
    public function testRenameTable(): void
1636
    {
1637
        $db = $this->getConnection();
1638
1639
        $qb = $db->getQueryBuilder();
1640
        $sql = $qb->renameTable('alpha', 'alpha-test');
1641
1642
        $this->assertSame(
1643
            DbHelper::replaceQuotes(
1644
                <<<SQL
1645
                RENAME TABLE [[alpha]] TO [[alpha-test]]
1646
                SQL,
1647
                $db->getName(),
1648
            ),
1649
            $sql,
1650
        );
1651
    }
1652
1653
    public function testResetSequence(): void
1654
    {
1655
        $db = $this->getConnection(true);
1656
1657
        $qb = $db->getQueryBuilder();
1658
1659
        $this->assertSame(
1660
            <<<SQL
1661
            SELECT SETVAL('"item_id_seq"',(SELECT COALESCE(MAX("id"),0) FROM "item")+1,false)
1662
            SQL,
1663
            $qb->resetSequence('item'),
1664
        );
1665
1666
        $this->assertSame(
1667
            <<<SQL
1668
            SELECT SETVAL('"item_id_seq"',3,false)
1669
            SQL,
1670
            $qb->resetSequence('item', 3),
1671
        );
1672
    }
1673
1674
    /**
1675
     * @throws Exception
1676
     * @throws InvalidConfigException
1677
     * @throws NotSupportedException
1678
     */
1679
    public function testResetSequenceNoAssociatedException(): void
1680
    {
1681
        $db = $this->getConnection(true);
1682
1683
        $qb = $db->getQueryBuilder();
1684
1685
        if ($db->getName() === 'db') {
1686
            $this->expectException(NotSupportedException::class);
1687
            $this->expectExceptionMessage(
1688
                'Yiisoft\Db\QueryBuilder\DMLQueryBuilder::resetSequence() is not supported by this DBMS.'
1689
            );
1690
        } else {
1691
            $this->expectException(InvalidArgumentException::class);
1692
            $this->expectExceptionMessage(
1693
                "There is not sequence associated with table 'type'."
1694
            );
1695
        }
1696
1697
        $qb->resetSequence('type');
1698
    }
1699
1700
    /**
1701
     * @throws Exception
1702
     * @throws InvalidConfigException
1703
     * @throws NotSupportedException
1704
     */
1705
    public function testResetSequenceTableNoExistException(): void
1706
    {
1707
        $db = $this->getConnection();
1708
1709
        $qb = $db->getQueryBuilder();
1710
1711
        if ($db->getName() === 'db') {
1712
            $this->expectException(NotSupportedException::class);
1713
            $this->expectExceptionMessage(
1714
                'Yiisoft\Db\QueryBuilder\DMLQueryBuilder::resetSequence() is not supported by this DBMS.'
1715
            );
1716
        } else {
1717
            $this->expectException(InvalidArgumentException::class);
1718
            $this->expectExceptionMessage("Table not found: 'noExist'.");
1719
        }
1720
1721
        $qb->resetSequence('noExist', 1);
1722
    }
1723
1724
    /**
1725
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::selectExist()
1726
     */
1727
    public function testSelectExists(string $sql, string $expected): void
1728
    {
1729
        $db = $this->getConnection();
1730
1731
        $qb = $db->getQueryBuilder();
1732
        $sqlSelectExist = $qb->selectExists($sql);
1733
1734
        $this->assertSame($expected, $sqlSelectExist);
1735
    }
1736
1737
    public function testSelectExpression(): void
1738
    {
1739
        $db = $this->getConnection();
1740
1741
        $qb = $db->getQueryBuilder();
1742
        $query = (new Query($db))->select(new Expression('1 AS ab'))->from('tablename');
1743
1744
        [$sql, $params] = $qb->build($query);
1745
1746
        $expected = DbHelper::replaceQuotes(
1747
            <<<SQL
1748
            SELECT 1 AS ab FROM [[tablename]]
1749
            SQL,
1750
            $db->getName(),
1751
        );
1752
1753
        $this->assertSame($expected, $sql);
1754
        $this->assertEmpty($params);
1755
1756
        $query = (new Query($db))
1757
            ->select(new Expression('1 AS ab'))
1758
            ->addSelect(new Expression('2 AS cd'))
1759
            ->addSelect(['ef' => new Expression('3')])
1760
            ->from('tablename');
1761
1762
        [$sql, $params] = $qb->build($query);
1763
1764
        $expected = DbHelper::replaceQuotes(
1765
            <<<SQL
1766
            SELECT 1 AS ab, 2 AS cd, 3 AS [[ef]] FROM [[tablename]]
1767
            SQL,
1768
            $db->getName(),
1769
        );
1770
1771
        $this->assertSame($expected, $sql);
1772
        $this->assertEmpty($params);
1773
1774
        $query = (new Query($db))
1775
            ->select(new Expression('SUBSTR(name, 0, :len)', [':len' => 4]))
1776
            ->from('tablename');
1777
1778
        [$sql, $params] = $qb->build($query);
1779
1780
        $expected = DbHelper::replaceQuotes(
1781
            <<<SQL
1782
            SELECT SUBSTR(name, 0, :len) FROM [[tablename]]
1783
            SQL,
1784
            $db->getName(),
1785
        );
1786
1787
        $this->assertSame($expected, $sql);
1788
        $this->assertSame([':len' => 4], $params);
1789
    }
1790
1791
    public function testSelectSubquery(): void
1792
    {
1793
        $db = $this->getConnection();
1794
1795
        $qb = $db->getQueryBuilder();
1796
        $expected = DbHelper::replaceQuotes(
1797
            <<<SQL
1798
            SELECT *, (SELECT COUNT(*) FROM [[operations]] WHERE account_id = accounts.id) AS [[operations_count]] FROM [[accounts]]
1799
            SQL,
1800
            $db->getName(),
1801
        );
1802
        $subquery = (new Query($db))->select('COUNT(*)')->from('operations')->where('account_id = accounts.id');
1803
        $query = (new Query($db))->select('*')->from('accounts')->addSelect(['operations_count' => $subquery]);
1804
1805
        [$sql, $params] = $qb->build($query);
1806
1807
        $this->assertSame($expected, $sql);
1808
        $this->assertEmpty($params);
1809
    }
1810
1811
    public function testSetConditionClasses(): void
1812
    {
1813
        $db = $this->getConnection();
1814
1815
        $qb = $db->getQueryBuilder();
1816
        $qb->setConditionClasses(['stdClass' => stdClass::class]);
1817
        $dqlBuilder = Assert::getInaccessibleProperty($qb, 'dqlBuilder');
1818
        $conditionClasses = Assert::getInaccessibleProperty($dqlBuilder, 'conditionClasses');
1819
1820
        $this->assertSame(stdClass::class, $conditionClasses['stdClass']);
1821
    }
1822
1823
    public function testSetExpressionBuilder(): void
1824
    {
1825
        $db = $this->getConnection();
1826
1827
        $qb = $db->getQueryBuilder();
1828
        $qb->setExpressionBuilders(['stdClass' => stdClass::class]);
1829
        $dqlBuilder = Assert::getInaccessibleProperty($qb, 'dqlBuilder');
1830
        $expressionBuilders = Assert::getInaccessibleProperty($dqlBuilder, 'expressionBuilders');
1831
1832
        $this->assertSame(stdClass::class, $expressionBuilders['stdClass']);
1833
    }
1834
1835
    public function testSetSeparator(): void
1836
    {
1837
        $db = $this->getConnection();
1838
1839
        $qb = $db->getQueryBuilder();
1840
        $qb->setSeparator(' ');
1841
        [$sql, $params] = $qb->build((new Query($db))->select('*')->from('table'));
1842
1843
        $this->assertSame(
1844
            DbHelper::replaceQuotes(
1845
                <<<SQL
1846
                SELECT * FROM [[table]]
1847
                SQL,
1848
                $db->getName(),
1849
            ),
1850
            $sql
1851
        );
1852
        $this->assertEmpty($params);
1853
1854
        $qb->setSeparator("\n");
1855
        [$sql, $params] = $qb->build((new Query($db))->select('*')->from('table'));
1856
1857
        $this->assertSame(
1858
            DbHelper::replaceQuotes(
1859
                <<<SQL
1860
                SELECT *
1861
                FROM [[table]]
1862
                SQL,
1863
                $db->getName(),
1864
            ),
1865
            $sql,
1866
        );
1867
        $this->assertEmpty($params);
1868
    }
1869
1870
    public function testTruncateTable(): void
1871
    {
1872
        $db = $this->getConnection();
1873
1874
        $qb = $db->getQueryBuilder();
1875
        $sql = $qb->truncateTable('customer');
1876
1877
        $this->assertSame(
1878
            DbHelper::replaceQuotes(
1879
                <<<SQL
1880
                TRUNCATE TABLE [[customer]]
1881
                SQL,
1882
                $db->getName(),
1883
            ),
1884
            $sql,
1885
        );
1886
1887
        $sql = $qb->truncateTable('T_constraints_1');
1888
1889
        $this->assertSame(
1890
            DbHelper::replaceQuotes(
1891
                <<<SQL
1892
                TRUNCATE TABLE [[T_constraints_1]]
1893
                SQL,
1894
                $db->getName(),
1895
            ),
1896
            $sql,
1897
        );
1898
    }
1899
1900
    /**
1901
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::update()
1902
     */
1903
    public function testUpdate(
1904
        string $table,
1905
        array $columns,
1906
        array|string $condition,
1907
        string $expectedSQL,
1908
        array $expectedParams
1909
    ): void {
1910
        $db = $this->getConnection();
1911
1912
        $qb = $db->getQueryBuilder();
1913
        $actualParams = [];
1914
1915
        $this->assertSame($expectedSQL, $qb->update($table, $columns, $condition, $actualParams));
1916
        $this->assertSame($expectedParams, $actualParams);
1917
    }
1918
1919
    /**
1920
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::upsert()
1921
     */
1922
    public function testUpsert(
1923
        string $table,
1924
        array|QueryInterface $insertColumns,
1925
        array|bool $updateColumns,
1926
        string|array $expectedSQL,
1927
        array $expectedParams
1928
    ): void {
1929
        $db = $this->getConnection();
1930
1931
        $actualParams = [];
1932
        $actualSQL = $db->getQueryBuilder()->upsert($table, $insertColumns, $updateColumns, $actualParams);
1933
1934
        if (is_string($expectedSQL)) {
0 ignored issues
show
introduced by
The condition is_string($expectedSQL) is always false.
Loading history...
1935
            $this->assertSame($expectedSQL, $actualSQL);
1936
        } else {
1937
            $this->assertContains($actualSQL, $expectedSQL);
1938
        }
1939
1940
        if (ArrayHelper::isAssociative($expectedParams)) {
1941
            $this->assertSame($expectedParams, $actualParams);
1942
        } else {
1943
            Assert::isOneOf($actualParams, $expectedParams);
1944
        }
1945
    }
1946
}
1947