Passed
Pull Request — master (#405)
by Wilmer
05:12 queued 02:35
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\Expression\Expression;
12
use Yiisoft\Db\Expression\ExpressionBuilderInterface;
13
use Yiisoft\Db\Expression\ExpressionInterface;
14
use Yiisoft\Db\Query\Query;
15
use Yiisoft\Db\Query\QueryInterface;
16
use Yiisoft\Db\QueryBuilder\Condition\SimpleCondition;
17
use Yiisoft\Db\Schema\QuoterInterface;
18
use Yiisoft\Db\Schema\Schema;
19
use Yiisoft\Db\Tests\Support\Assert;
20
use Yiisoft\Db\Tests\Support\DbHelper;
21
use Yiisoft\Db\Tests\Support\TestTrait;
22
23
abstract class AbstractQueryBuilderTest extends TestCase
24
{
25
    use TestTrait;
26
27
    public function testAddCheck(): void
28
    {
29
        $db = $this->getConnection();
30
31
        $qb = $db->getQueryBuilder();
32
        $sql = $qb->addCheck('T_constraints_1', 'CN_check', '[[C_not_null]] > 100');
33
34
        $this->assertSame(
35
            DbHelper::replaceQuotes(
36
                <<<SQL
37
                ALTER TABLE [[CN_check]] ADD CONSTRAINT [[T_constraints_1]] CHECK ([[C_not_null]] > 100)
38
                SQL,
39
                $db->getName(),
40
            ),
41
            $sql,
42
        );
43
    }
44
45
    public function testAddColumn(): void
46
    {
47
        $db = $this->getConnection();
48
49
        $qb = $db->getQueryBuilder();
50
        $schema = $db->getSchema();
51
        $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...
52
53
        $this->assertSame(
54
            DbHelper::replaceQuotes(
55
                <<<SQL
56
                ALTER TABLE [[table]] ADD [[column]]
57
                SQL . ' ' . $qb->getColumnType($schema::TYPE_STRING),
58
                $db->getName(),
59
            ),
60
            $sql,
61
        );
62
    }
63
64
    public function testAddCommentOnColumn(): void
65
    {
66
        $db = $this->getConnection();
67
68
        $qb = $db->getQueryBuilder();
69
        $sql = $qb->addCommentOnColumn('customer', 'id', 'Primary key.');
70
71
        $this->assertSame(
72
            DbHelper::replaceQuotes(
73
                <<<SQL
74
                COMMENT ON COLUMN [[customer]].[[id]] IS 'Primary key.'
75
                SQL,
76
                $db->getName(),
77
            ),
78
            $sql,
79
        );
80
    }
81
82
    public function testAddCommentOnTable(): void
83
    {
84
        $db = $this->getConnection();
85
86
        $qb = $db->getQueryBuilder();
87
        $sql = $qb->addCommentOnTable('customer', 'Customer table.');
88
89
        $this->assertSame(
90
            DbHelper::replaceQuotes(
91
                <<<SQL
92
                COMMENT ON TABLE [[customer]] IS 'Customer table.'
93
                SQL,
94
                $db->getName(),
95
            ),
96
            $sql,
97
        );
98
    }
99
100
    public function testAddDefaultValue(): void
101
    {
102
        $db = $this->getConnection();
103
104
        $qb = $db->getQueryBuilder();
105
        $sql = $qb->addDefaultValue('CN_pk', 'T_constraints_1', 'C_default', 1);
106
107
        $this->assertSame(
108
            DbHelper::replaceQuotes(
109
                <<<SQL
110
                ALTER TABLE [[T_constraints_1]] ALTER COLUMN [[C_default]] SET DEFAULT 1
111
                SQL,
112
                $db->getName(),
113
            ),
114
            $sql,
115
        );
116
    }
117
118
    /**
119
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addForeignKey()
120
     */
121
    public function testAddForeignKey(
122
        string $name,
123
        string $table,
124
        array|string $columns,
125
        string $refTable,
126
        array|string $refColumns,
127
        string|null $delete,
128
        string|null $update,
129
        string $expected
130
    ): void {
131
        $db = $this->getConnection();
132
133
        $qb = $db->getQueryBuilder();
134
        $sql = $qb->addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete, $update);
135
136
        $this->assertSame($expected, $sql);
137
    }
138
139
    /**
140
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addPrimaryKey()
141
     */
142
    public function testAddPrimaryKey(string $name, string $table, array|string $columns, string $expected): void
143
    {
144
        $db = $this->getConnection();
145
146
        $qb = $db->getQueryBuilder();
147
        $sql = $qb->addPrimaryKey($name, $table, $columns);
148
149
        $this->assertSame($expected, $sql);
150
    }
151
152
    /**
153
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::addUnique()
154
     */
155
    public function testAddUnique(string $name, string $table, array|string $columns, string $expected): void
156
    {
157
        $db = $this->getConnection();
158
159
        $qb = $db->getQueryBuilder();
160
        $sql = $qb->addUnique($name, $table, $columns);
161
162
        $this->assertSame($expected, $sql);
163
    }
164
165
    public function testAlterColumn(): void
166
    {
167
        $db = $this->getConnection();
168
169
        $qb = $db->getQueryBuilder();
170
        $schema = $db->getSchema();
171
        $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...
172
173
        $this->assertSame(
174
            DbHelper::replaceQuotes(
175
                <<<SQL
176
                ALTER TABLE [[customer]] CHANGE [[email]] [[email]]
177
                SQL . ' ' . $qb->getColumnType($schema::TYPE_STRING),
178
                $db->getName(),
179
            ),
180
            $sql,
181
        );
182
    }
183
184
    /**
185
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::batchInsert()
186
     */
187
    public function testBatchInsert(string $table, array $columns, array $rows, string $expected): void
188
    {
189
        $db = $this->getConnection();
190
191
        $qb = $db->getQueryBuilder();
192
        $sql = $qb->batchInsert($table, $columns, $rows);
193
194
        $this->assertSame($expected, $sql);
195
    }
196
197
    /**
198
     * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::buildCondition()
199
     */
200
    public function testBuildCondition(
201
        array|ExpressionInterface|string $condition,
202
        string|null $expected,
203
        array $expectedParams
204
    ): void {
205
        $db = $this->getConnection();
206
207
        $query = (new Query($db))->where($condition);
208
209
        [$sql, $params] = $db->getQueryBuilder()->build($query);
210
211
        $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

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

1225
        $this->assertSame('AND', $condition->/** @scrutinizer ignore-call */ getOperator());
Loading history...
1226
        $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

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

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