Passed
Branch dev (f56f10)
by Wilmer
04:41 queued 01:34
created

TestQueryBuilderTrait::testBuildUnion()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 33
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 22
nc 1
nop 0
dl 0
loc 33
rs 9.568
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\TestSupport;
6
7
use Yiisoft\Db\Expression\Expression;
8
use Yiisoft\Db\Query\Query;
9
use Yiisoft\Db\Query\QueryBuilder;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Db\Query\QueryBuilder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Yiisoft\Db\Schema\Schema;
11
use Yiisoft\Db\Schema\SchemaBuilderTrait;
12
13
use function array_key_exists;
14
use function array_values;
15
use function is_array;
16
use function str_replace;
17
use function strncmp;
18
use function substr;
19
20
trait TestQueryBuilderTrait
21
{
22
    use SchemaBuilderTrait;
23
24
    /**
25
     * This is not used as a dataprovider for testGetColumnType to speed up the test when used as dataprovider every
26
     * single line will cause a reconnect with the database which is not needed here.
27
     */
28
    public function columnTypes(): array
29
    {
30
        $version = $this->getConnection()->getServerVersion();
0 ignored issues
show
Bug introduced by
It seems like getConnection() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

30
        $version = $this->/** @scrutinizer ignore-call */ getConnection()->getServerVersion();
Loading history...
31
32
        $items = [
33
            [
34
                Schema::TYPE_BIGINT,
35
                $this->bigInteger(),
36
                [
37
                    'mysql' => 'bigint(20)',
38
                    'pgsql' => 'bigint',
39
                    'sqlite' => 'bigint',
40
                    'oci' => 'NUMBER(20)',
41
                    'sqlsrv' => 'bigint',
42
                ],
43
            ],
44
            [
45
                Schema::TYPE_BIGINT . ' NOT NULL',
46
                $this->bigInteger()->notNull(),
47
                [
48
                    'mysql' => 'bigint(20) NOT NULL',
49
                    'pgsql' => 'bigint NOT NULL',
50
                    'sqlite' => 'bigint NOT NULL',
51
                    'oci' => 'NUMBER(20) NOT NULL',
52
                    'sqlsrv' => 'bigint NOT NULL',
53
                ],
54
            ],
55
            [
56
                Schema::TYPE_BIGINT . ' CHECK (value > 5)',
57
                $this->bigInteger()->check('value > 5'),
58
                [
59
                    'mysql' => 'bigint(20) CHECK (value > 5)',
60
                    'pgsql' => 'bigint CHECK (value > 5)',
61
                    'sqlite' => 'bigint CHECK (value > 5)',
62
                    'oci' => 'NUMBER(20) CHECK (value > 5)',
63
                    'sqlsrv' => 'bigint CHECK (value > 5)',
64
                ],
65
            ],
66
            [
67
                Schema::TYPE_BIGINT . '(8)',
68
                $this->bigInteger(8),
69
                [
70
                    'mysql' => 'bigint(8)',
71
                    'pgsql' => 'bigint',
72
                    'sqlite' => 'bigint',
73
                    'oci' => 'NUMBER(8)',
74
                    'sqlsrv' => 'bigint',
75
                ],
76
            ],
77
            [
78
                Schema::TYPE_BIGINT . '(8) CHECK (value > 5)',
79
                $this->bigInteger(8)->check('value > 5'),
80
                [
81
                    'mysql' => 'bigint(8) CHECK (value > 5)',
82
                    'pgsql' => 'bigint CHECK (value > 5)',
83
                    'sqlite' => 'bigint CHECK (value > 5)',
84
                    'oci' => 'NUMBER(8) CHECK (value > 5)',
85
                    'sqlsrv' => 'bigint CHECK (value > 5)',
86
                ],
87
            ],
88
            [
89
                Schema::TYPE_BIGPK,
90
                $this->bigPrimaryKey(),
91
                [
92
                    'mysql' => 'bigint(20) NOT NULL AUTO_INCREMENT PRIMARY KEY',
93
                    'pgsql' => 'bigserial NOT NULL PRIMARY KEY',
94
                    'sqlite' => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL',
95
                ],
96
            ],
97
            [
98
                Schema::TYPE_BINARY,
99
                $this->binary(),
100
                [
101
                    'mysql' => 'blob',
102
                    'pgsql' => 'bytea',
103
                    'sqlite' => 'blob',
104
                    'oci' => 'BLOB',
105
                    'sqlsrv' => 'varbinary(max)',
106
                ],
107
            ],
108
            [
109
                Schema::TYPE_BOOLEAN . ' NOT NULL DEFAULT 1',
110
                $this->boolean()->notNull()->defaultValue(1),
111
                [
112
                    'mysql' => 'tinyint(1) NOT NULL DEFAULT 1',
113
                    'sqlite' => 'boolean NOT NULL DEFAULT 1',
114
                    'sqlsrv' => 'bit NOT NULL DEFAULT 1',
115
                ],
116
            ],
117
            [
118
                Schema::TYPE_BOOLEAN . ' NOT NULL DEFAULT TRUE',
119
                $this->boolean()->notNull()->defaultValue(true),
120
                [
121
                    'pgsql' => 'boolean NOT NULL DEFAULT TRUE',
122
                ],
123
            ],
124
            [
125
                Schema::TYPE_BOOLEAN,
126
                $this->boolean(),
127
                [
128
                    'mysql' => 'tinyint(1)',
129
                    'pgsql' => 'boolean',
130
                    'sqlite' => 'boolean',
131
                    'oci' => 'NUMBER(1)',
132
                    'sqlsrv' => 'bit',
133
                ],
134
            ],
135
            [
136
                Schema::TYPE_CHAR . ' CHECK (value LIKE \'test%\')',
137
                $this->char()->check('value LIKE \'test%\''),
138
                [
139
                    'pgsql' => 'char(1) CHECK (value LIKE \'test%\')',
140
                ],
141
            ],
142
            [
143
                Schema::TYPE_CHAR . ' CHECK (value LIKE "test%")',
144
                $this->char()->check('value LIKE "test%"'),
145
                [
146
                    'mysql' => 'char(1) CHECK (value LIKE "test%")',
147
                    'sqlite' => 'char(1) CHECK (value LIKE "test%")',
148
                ],
149
            ],
150
            [
151
                Schema::TYPE_CHAR . ' NOT NULL',
152
                $this->char()->notNull(),
153
                [
154
                    'mysql' => 'char(1) NOT NULL',
155
                    'pgsql' => 'char(1) NOT NULL',
156
                    'sqlite' => 'char(1) NOT NULL',
157
                    'oci' => 'CHAR(1) NOT NULL',
158
                ],
159
            ],
160
            [
161
                Schema::TYPE_CHAR . '(6) CHECK (value LIKE "test%")',
162
                $this->char(6)->check('value LIKE "test%"'),
163
                [
164
                    'mysql' => 'char(6) CHECK (value LIKE "test%")',
165
                    'sqlite' => 'char(6) CHECK (value LIKE "test%")',
166
                ],
167
            ],
168
            [
169
                Schema::TYPE_CHAR . '(6)',
170
                $this->char(6)->unsigned(),
171
                [
172
                    'pgsql' => 'char(6)',
173
                ],
174
            ],
175
            [
176
                Schema::TYPE_CHAR . '(6)',
177
                $this->char(6),
178
                [
179
                    'mysql' => 'char(6)',
180
                    'pgsql' => 'char(6)',
181
                    'sqlite' => 'char(6)',
182
                    'oci' => 'CHAR(6)',
183
                ],
184
            ],
185
            [
186
                Schema::TYPE_CHAR,
187
                $this->char(),
188
                [
189
                    'mysql' => 'char(1)',
190
                    'pgsql' => 'char(1)',
191
                    'sqlite' => 'char(1)',
192
                    'oci' => 'CHAR(1)',
193
                ],
194
            ],
195
            [
196
                Schema::TYPE_DATE . ' NOT NULL',
197
                $this->date()->notNull(),
198
                [
199
                    'pgsql' => 'date NOT NULL',
200
                    'sqlite' => 'date NOT NULL',
201
                    'oci' => 'DATE NOT NULL',
202
                    'sqlsrv' => 'date NOT NULL',
203
                ],
204
            ],
205
            [
206
                Schema::TYPE_DATE,
207
                $this->date(),
208
                [
209
                    'mysql' => 'date',
210
                    'pgsql' => 'date',
211
                    'sqlite' => 'date',
212
                    'oci' => 'DATE',
213
                    'sqlsrv' => 'date',
214
                ],
215
            ],
216
            [
217
                Schema::TYPE_DATETIME . ' NOT NULL',
218
                $this->dateTime()->notNull(),
219
                [
220
                    'mysql' => version_compare($version, '5.6.4', '>=') ? 'datetime(0) NOT NULL' : 'datetime NOT NULL',
221
                    'pgsql' => 'timestamp(0) NOT NULL',
222
                    'sqlite' => 'datetime NOT NULL',
223
                    'oci' => 'TIMESTAMP NOT NULL',
224
                    'sqlsrv' => 'datetime NOT NULL',
225
                ],
226
            ],
227
            [
228
                Schema::TYPE_DATETIME,
229
                $this->dateTime(),
230
                [
231
                    'mysql' => version_compare($version, '5.6.4', '>=') ? 'datetime(0)' : 'datetime',
232
                    'pgsql' => 'timestamp(0)',
233
                    'sqlite' => 'datetime',
234
                    'oci' => 'TIMESTAMP',
235
                    'sqlsrv' => 'datetime',
236
                ],
237
            ],
238
            [
239
                Schema::TYPE_DECIMAL . ' CHECK (value > 5.6)',
240
                $this->decimal()->check('value > 5.6'),
241
                [
242
                    'mysql' => 'decimal(10,0) CHECK (value > 5.6)',
243
                    'pgsql' => 'numeric(10,0) CHECK (value > 5.6)',
244
                    'sqlite' => 'decimal(10,0) CHECK (value > 5.6)',
245
                    'oci' => 'NUMBER CHECK (value > 5.6)',
246
                    'sqlsrv' => 'decimal(18,0) CHECK (value > 5.6)',
247
                ],
248
            ],
249
            [
250
                Schema::TYPE_DECIMAL . ' NOT NULL',
251
                $this->decimal()->notNull(),
252
                [
253
                    'mysql' => 'decimal(10,0) NOT NULL',
254
                    'pgsql' => 'numeric(10,0) NOT NULL',
255
                    'sqlite' => 'decimal(10,0) NOT NULL',
256
                    'oci' => 'NUMBER NOT NULL',
257
                    'sqlsrv' => 'decimal(18,0) NOT NULL',
258
                ],
259
            ],
260
            [
261
                Schema::TYPE_DECIMAL . '(12,4) CHECK (value > 5.6)',
262
                $this->decimal(12, 4)->check('value > 5.6'),
263
                [
264
                    'mysql' => 'decimal(12,4) CHECK (value > 5.6)',
265
                    'pgsql' => 'numeric(12,4) CHECK (value > 5.6)',
266
                    'sqlite' => 'decimal(12,4) CHECK (value > 5.6)',
267
                    'oci' => 'NUMBER CHECK (value > 5.6)',
268
                    'sqlsrv' => 'decimal(12,4) CHECK (value > 5.6)',
269
                ],
270
            ],
271
            [
272
                Schema::TYPE_DECIMAL . '(12,4)',
273
                $this->decimal(12, 4),
274
                [
275
                    'mysql' => 'decimal(12,4)',
276
                    'pgsql' => 'numeric(12,4)',
277
                    'sqlite' => 'decimal(12,4)',
278
                    'oci' => 'NUMBER',
279
                    'sqlsrv' => 'decimal(12,4)',
280
                ],
281
            ],
282
            [
283
                Schema::TYPE_DECIMAL,
284
                $this->decimal(),
285
                [
286
                    'mysql' => 'decimal(10,0)',
287
                    'pgsql' => 'numeric(10,0)',
288
                    'sqlite' => 'decimal(10,0)',
289
                    'oci' => 'NUMBER',
290
                    'sqlsrv' => 'decimal(18,0)',
291
                ],
292
            ],
293
            [
294
                Schema::TYPE_DOUBLE . ' CHECK (value > 5.6)',
295
                $this->double()->check('value > 5.6'),
296
                [
297
                    'mysql' => 'double CHECK (value > 5.6)',
298
                    'pgsql' => 'double precision CHECK (value > 5.6)',
299
                    'sqlite' => 'double CHECK (value > 5.6)',
300
                    'oci' => 'NUMBER CHECK (value > 5.6)',
301
                    'sqlsrv' => 'float CHECK (value > 5.6)',
302
                ],
303
            ],
304
            [
305
                Schema::TYPE_DOUBLE . ' NOT NULL',
306
                $this->double()->notNull(),
307
                [
308
                    'mysql' => 'double NOT NULL',
309
                    'pgsql' => 'double precision NOT NULL',
310
                    'sqlite' => 'double NOT NULL',
311
                    'oci' => 'NUMBER NOT NULL',
312
                    'sqlsrv' => 'float NOT NULL',
313
                ],
314
            ],
315
            [
316
                Schema::TYPE_DOUBLE . '(16) CHECK (value > 5.6)',
317
                $this->double(16)->check('value > 5.6'),
318
                [
319
                    'mysql' => 'double CHECK (value > 5.6)',
320
                    'pgsql' => 'double precision CHECK (value > 5.6)',
321
                    'sqlite' => 'double CHECK (value > 5.6)',
322
                    'oci' => 'NUMBER CHECK (value > 5.6)',
323
                    'sqlsrv' => 'float CHECK (value > 5.6)',
324
                ],
325
            ],
326
            [
327
                Schema::TYPE_DOUBLE . '(16)',
328
                $this->double(16),
329
                [
330
                    'mysql' => 'double',
331
                    'sqlite' => 'double',
332
                    'oci' => 'NUMBER',
333
                    'sqlsrv' => 'float',
334
                ],
335
            ],
336
            [
337
                Schema::TYPE_DOUBLE,
338
                $this->double(),
339
                [
340
                    'mysql' => 'double',
341
                    'pgsql' => 'double precision',
342
                    'sqlite' => 'double',
343
                    'oci' => 'NUMBER',
344
                    'sqlsrv' => 'float',
345
                ],
346
            ],
347
            [
348
                Schema::TYPE_FLOAT . ' CHECK (value > 5.6)',
349
                $this->float()->check('value > 5.6'),
350
                [
351
                    'mysql' => 'float CHECK (value > 5.6)',
352
                    'pgsql' => 'double precision CHECK (value > 5.6)',
353
                    'sqlite' => 'float CHECK (value > 5.6)',
354
                    'oci' => 'NUMBER CHECK (value > 5.6)',
355
                    'sqlsrv' => 'float CHECK (value > 5.6)',
356
                ],
357
            ],
358
            [
359
                Schema::TYPE_FLOAT . ' NOT NULL',
360
                $this->float()->notNull(),
361
                [
362
                    'mysql' => 'float NOT NULL',
363
                    'pgsql' => 'double precision NOT NULL',
364
                    'sqlite' => 'float NOT NULL',
365
                    'oci' => 'NUMBER NOT NULL',
366
                    'sqlsrv' => 'float NOT NULL',
367
                ],
368
            ],
369
            [
370
                Schema::TYPE_FLOAT . '(16) CHECK (value > 5.6)',
371
                $this->float(16)->check('value > 5.6'),
372
                [
373
                    'mysql' => 'float CHECK (value > 5.6)',
374
                    'pgsql' => 'double precision CHECK (value > 5.6)',
375
                    'sqlite' => 'float CHECK (value > 5.6)',
376
                    'oci' => 'NUMBER CHECK (value > 5.6)',
377
                    'sqlsrv' => 'float CHECK (value > 5.6)',
378
                ],
379
            ],
380
            [
381
                Schema::TYPE_FLOAT . '(16)',
382
                $this->float(16),
383
                [
384
                    'mysql' => 'float',
385
                    'sqlite' => 'float',
386
                    'oci' => 'NUMBER',
387
                    'sqlsrv' => 'float',
388
                ],
389
            ],
390
            [
391
                Schema::TYPE_FLOAT,
392
                $this->float(),
393
                [
394
                    'mysql' => 'float',
395
                    'pgsql' => 'double precision',
396
                    'sqlite' => 'float',
397
                    'oci' => 'NUMBER',
398
                    'sqlsrv' => 'float',
399
                ],
400
            ],
401
            [
402
                Schema::TYPE_INTEGER . ' CHECK (value > 5)',
403
                $this->integer()->check('value > 5'),
404
                [
405
                    'mysql' => 'int(11) CHECK (value > 5)',
406
                    'pgsql' => 'integer CHECK (value > 5)',
407
                    'sqlite' => 'integer CHECK (value > 5)',
408
                    'oci' => 'NUMBER(10) CHECK (value > 5)',
409
                    'sqlsrv' => 'int CHECK (value > 5)',
410
                ],
411
            ],
412
            [
413
                Schema::TYPE_INTEGER . ' NOT NULL',
414
                $this->integer()->notNull(),
415
                [
416
                    'mysql' => 'int(11) NOT NULL',
417
                    'pgsql' => 'integer NOT NULL',
418
                    'sqlite' => 'integer NOT NULL',
419
                    'oci' => 'NUMBER(10) NOT NULL',
420
                    'sqlsrv' => 'int NOT NULL',
421
                ],
422
            ],
423
            [
424
                Schema::TYPE_INTEGER . '(8) CHECK (value > 5)',
425
                $this->integer(8)->check('value > 5'),
426
                [
427
                    'mysql' => 'int(8) CHECK (value > 5)',
428
                    'pgsql' => 'integer CHECK (value > 5)',
429
                    'sqlite' => 'integer CHECK (value > 5)',
430
                    'oci' => 'NUMBER(8) CHECK (value > 5)',
431
                    'sqlsrv' => 'int CHECK (value > 5)',
432
                ],
433
            ],
434
            [
435
                Schema::TYPE_INTEGER . '(8)',
436
                $this->integer(8)->unsigned(),
437
                [
438
                    'pgsql' => 'integer',
439
                ],
440
            ],
441
            [
442
                Schema::TYPE_INTEGER . '(8)',
443
                $this->integer(8),
444
                [
445
                    'mysql' => 'int(8)',
446
                    'pgsql' => 'integer',
447
                    'sqlite' => 'integer',
448
                    'oci' => 'NUMBER(8)',
449
                    'sqlsrv' => 'int',
450
                ],
451
            ],
452
            [
453
                Schema::TYPE_INTEGER,
454
                $this->integer(),
455
                [
456
                    'mysql' => 'int(11)',
457
                    'pgsql' => 'integer',
458
                    'sqlite' => 'integer',
459
                    'oci' => 'NUMBER(10)',
460
                    'sqlsrv' => 'int',
461
                ],
462
            ],
463
            [
464
                Schema::TYPE_MONEY . ' CHECK (value > 0.0)',
465
                $this->money()->check('value > 0.0'),
466
                [
467
                    'mysql' => 'decimal(19,4) CHECK (value > 0.0)',
468
                    'pgsql' => 'numeric(19,4) CHECK (value > 0.0)',
469
                    'sqlite' => 'decimal(19,4) CHECK (value > 0.0)',
470
                    'oci' => 'NUMBER(19,4) CHECK (value > 0.0)',
471
                    'sqlsrv' => 'decimal(19,4) CHECK (value > 0.0)',
472
                ],
473
            ],
474
            [
475
                Schema::TYPE_MONEY . ' NOT NULL',
476
                $this->money()->notNull(),
477
                [
478
                    'mysql' => 'decimal(19,4) NOT NULL',
479
                    'pgsql' => 'numeric(19,4) NOT NULL',
480
                    'sqlite' => 'decimal(19,4) NOT NULL',
481
                    'oci' => 'NUMBER(19,4) NOT NULL',
482
                    'sqlsrv' => 'decimal(19,4) NOT NULL',
483
                ],
484
            ],
485
            [
486
                Schema::TYPE_MONEY . '(16,2) CHECK (value > 0.0)',
487
                $this->money(16, 2)->check('value > 0.0'),
488
                [
489
                    'mysql' => 'decimal(16,2) CHECK (value > 0.0)',
490
                    'pgsql' => 'numeric(16,2) CHECK (value > 0.0)',
491
                    'sqlite' => 'decimal(16,2) CHECK (value > 0.0)',
492
                    'oci' => 'NUMBER(16,2) CHECK (value > 0.0)',
493
                    'sqlsrv' => 'decimal(16,2) CHECK (value > 0.0)',
494
                ],
495
            ],
496
            [
497
                Schema::TYPE_MONEY . '(16,2)',
498
                $this->money(16, 2),
499
                [
500
                    'mysql' => 'decimal(16,2)',
501
                    'pgsql' => 'numeric(16,2)',
502
                    'sqlite' => 'decimal(16,2)',
503
                    'oci' => 'NUMBER(16,2)',
504
                    'sqlsrv' => 'decimal(16,2)',
505
                ],
506
            ],
507
            [
508
                Schema::TYPE_MONEY,
509
                $this->money(),
510
                [
511
                    'mysql' => 'decimal(19,4)',
512
                    'pgsql' => 'numeric(19,4)',
513
                    'sqlite' => 'decimal(19,4)',
514
                    'oci' => 'NUMBER(19,4)',
515
                    'sqlsrv' => 'decimal(19,4)',
516
                ],
517
            ],
518
            [
519
                Schema::TYPE_PK . ' AFTER `col_before`',
520
                $this->primaryKey()->after('col_before'),
521
                [
522
                    'mysql' => 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY AFTER `col_before`',
523
                ],
524
            ],
525
            [
526
                Schema::TYPE_PK . ' FIRST',
527
                $this->primaryKey()->first(),
528
                [
529
                    'mysql' => 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST',
530
                ],
531
            ],
532
            [
533
                Schema::TYPE_PK . ' FIRST',
534
                $this->primaryKey()->first()->after('col_before'),
535
                [
536
                    'mysql' => 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST',
537
                ],
538
                [
539
                    'sqlite' => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL',
540
                ],
541
            ],
542
            [
543
                Schema::TYPE_PK . '(8) AFTER `col_before`',
544
                $this->primaryKey(8)->after('col_before'),
545
                [
546
                    'mysql' => 'int(8) NOT NULL AUTO_INCREMENT PRIMARY KEY AFTER `col_before`',
547
                ],
548
            ],
549
            [
550
                Schema::TYPE_PK . '(8) FIRST',
551
                $this->primaryKey(8)->first(),
552
                [
553
                    'mysql' => 'int(8) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST',
554
                ],
555
            ],
556
            [
557
                Schema::TYPE_PK . '(8) FIRST',
558
                $this->primaryKey(8)->first()->after('col_before'),
559
                [
560
                    'mysql' => 'int(8) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST',
561
                ],
562
            ],
563
            [
564
                Schema::TYPE_PK . " COMMENT 'test' AFTER `col_before`",
565
                $this->primaryKey()->comment('test')->after('col_before'),
566
                [
567
                    'mysql' => "int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'test' AFTER `col_before`",
568
                ],
569
            ],
570
            [
571
                Schema::TYPE_PK . " COMMENT 'testing \'quote\'' AFTER `col_before`",
572
                $this->primaryKey()->comment('testing \'quote\'')->after('col_before'),
573
                [
574
                    'mysql' => "int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'testing \'quote\''"
575
                        . ' AFTER `col_before`',
576
                ],
577
            ],
578
            [
579
                Schema::TYPE_PK . ' CHECK (value > 5)',
580
                $this->primaryKey()->check('value > 5'),
581
                [
582
                    'mysql' => 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY CHECK (value > 5)',
583
                    'pgsql' => 'serial NOT NULL PRIMARY KEY CHECK (value > 5)',
584
                    'sqlite' => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL CHECK (value > 5)',
585
                    'oci' => 'NUMBER(10) NOT NULL PRIMARY KEY CHECK (value > 5)',
586
                    'sqlsrv' => 'int IDENTITY PRIMARY KEY CHECK (value > 5)',
587
                ],
588
            ],
589
            [
590
                Schema::TYPE_PK . '(8) CHECK (value > 5)',
591
                $this->primaryKey(8)->check('value > 5'),
592
                [
593
                    'mysql' => 'int(8) NOT NULL AUTO_INCREMENT PRIMARY KEY CHECK (value > 5)',
594
                    'oci' => 'NUMBER(8) NOT NULL PRIMARY KEY CHECK (value > 5)',
595
                ],
596
            ],
597
            [
598
                Schema::TYPE_PK . '(8)',
599
                $this->primaryKey(8),
600
                [
601
                    'mysql' => 'int(8) NOT NULL AUTO_INCREMENT PRIMARY KEY',
602
                    'oci' => 'NUMBER(8) NOT NULL PRIMARY KEY',
603
                ],
604
            ],
605
            [
606
                Schema::TYPE_PK,
607
                $this->primaryKey(),
608
                [
609
                    'mysql' => 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY',
610
                    'pgsql' => 'serial NOT NULL PRIMARY KEY',
611
                    'sqlite' => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL',
612
                    'oci' => 'NUMBER(10) NOT NULL PRIMARY KEY',
613
                    'sqlsrv' => 'int IDENTITY PRIMARY KEY',
614
                ],
615
            ],
616
            [
617
                Schema::TYPE_TINYINT . '(2)',
618
                $this->tinyInteger(2),
619
                [
620
                    'mysql' => 'tinyint(2)',
621
                    'pgsql' => 'smallint',
622
                    'sqlite' => 'tinyint',
623
                    'oci' => 'NUMBER(2)',
624
                    'sqlsrv' => 'tinyint',
625
                ],
626
            ],
627
            [
628
                Schema::TYPE_TINYINT . ' UNSIGNED',
629
                $this->tinyInteger()->unsigned(),
630
                [
631
                    'mysql' => 'tinyint(3) UNSIGNED',
632
                    'sqlite' => 'tinyint UNSIGNED',
633
                ],
634
            ],
635
            [
636
                Schema::TYPE_TINYINT,
637
                $this->tinyInteger(),
638
                [
639
                    'mysql' => 'tinyint(3)',
640
                    'pgsql' => 'smallint',
641
                    'sqlite' => 'tinyint',
642
                    'oci' => 'NUMBER(3)',
643
                    'sqlsrv' => 'tinyint',
644
                ],
645
            ],
646
            [
647
                Schema::TYPE_SMALLINT . '(8)',
648
                $this->smallInteger(8),
649
                [
650
                    'mysql' => 'smallint(8)',
651
                    'pgsql' => 'smallint',
652
                    'sqlite' => 'smallint',
653
                    'oci' => 'NUMBER(8)',
654
                    'sqlsrv' => 'smallint',
655
                ],
656
            ],
657
            [
658
                Schema::TYPE_SMALLINT,
659
                $this->smallInteger(),
660
                [
661
                    'mysql' => 'smallint(6)',
662
                    'pgsql' => 'smallint',
663
                    'sqlite' => 'smallint',
664
                    'oci' => 'NUMBER(5)',
665
                    'sqlsrv' => 'smallint',
666
                ],
667
            ],
668
            [
669
                Schema::TYPE_STRING . " CHECK (value LIKE 'test%')",
670
                $this->string()->check("value LIKE 'test%'"),
671
                [
672
                    'mysql' => "varchar(255) CHECK (value LIKE 'test%')",
673
                    'sqlite' => "varchar(255) CHECK (value LIKE 'test%')",
674
                    'sqlsrv' => "nvarchar(255) CHECK (value LIKE 'test%')",
675
                ],
676
            ],
677
            [
678
                Schema::TYPE_STRING . ' CHECK (value LIKE \'test%\')',
679
                $this->string()->check('value LIKE \'test%\''),
680
                [
681
                    'pgsql' => 'varchar(255) CHECK (value LIKE \'test%\')',
682
                    'oci' => 'VARCHAR2(255) CHECK (value LIKE \'test%\')',
683
                ],
684
            ],
685
            [
686
                Schema::TYPE_STRING . ' NOT NULL',
687
                $this->string()->notNull(),
688
                [
689
                    'mysql' => 'varchar(255) NOT NULL',
690
                    'pgsql' => 'varchar(255) NOT NULL',
691
                    'sqlite' => 'varchar(255) NOT NULL',
692
                    'oci' => 'VARCHAR2(255) NOT NULL',
693
                    'sqlsrv' => 'nvarchar(255) NOT NULL',
694
                ],
695
            ],
696
            [
697
                Schema::TYPE_STRING . "(32) CHECK (value LIKE 'test%')",
698
                $this->string(32)->check("value LIKE 'test%'"),
699
                [
700
                    'mysql' => "varchar(32) CHECK (value LIKE 'test%')",
701
                    'sqlite' => "varchar(32) CHECK (value LIKE 'test%')",
702
                    'sqlsrv' => "nvarchar(32) CHECK (value LIKE 'test%')",
703
                ],
704
            ],
705
            [
706
                Schema::TYPE_STRING . '(32) CHECK (value LIKE \'test%\')',
707
                $this->string(32)->check('value LIKE \'test%\''),
708
                [
709
                    'pgsql' => 'varchar(32) CHECK (value LIKE \'test%\')',
710
                    'oci' => 'VARCHAR2(32) CHECK (value LIKE \'test%\')',
711
                ],
712
            ],
713
            [
714
                Schema::TYPE_STRING . '(32)',
715
                $this->string(32),
716
                [
717
                    'mysql' => 'varchar(32)',
718
                    'pgsql' => 'varchar(32)',
719
                    'sqlite' => 'varchar(32)',
720
                    'oci' => 'VARCHAR2(32)',
721
                    'sqlsrv' => 'nvarchar(32)',
722
                ],
723
            ],
724
            [
725
                Schema::TYPE_STRING,
726
                $this->string(),
727
                [
728
                    'mysql' => 'varchar(255)',
729
                    'pgsql' => 'varchar(255)',
730
                    'sqlite' => 'varchar(255)',
731
                    'oci' => 'VARCHAR2(255)',
732
                    'sqlsrv' => 'nvarchar(255)',
733
                ],
734
            ],
735
            [
736
                Schema::TYPE_TEXT . " CHECK (value LIKE 'test%')",
737
                $this->text()->check("value LIKE 'test%'"),
738
                [
739
                    'mysql' => "text CHECK (value LIKE 'test%')",
740
                    'sqlite' => "text CHECK (value LIKE 'test%')",
741
                    'sqlsrv' => "nvarchar(max) CHECK (value LIKE 'test%')",
742
                ],
743
            ],
744
            [
745
                Schema::TYPE_TEXT . ' CHECK (value LIKE \'test%\')',
746
                $this->text()->check('value LIKE \'test%\''),
747
                [
748
                    'pgsql' => 'text CHECK (value LIKE \'test%\')',
749
                    'oci' => 'CLOB CHECK (value LIKE \'test%\')',
750
                ],
751
            ],
752
            [
753
                Schema::TYPE_TEXT . ' NOT NULL',
754
                $this->text()->notNull(),
755
                [
756
                    'mysql' => 'text NOT NULL',
757
                    'pgsql' => 'text NOT NULL',
758
                    'sqlite' => 'text NOT NULL',
759
                    'oci' => 'CLOB NOT NULL',
760
                    'sqlsrv' => 'nvarchar(max) NOT NULL',
761
                ],
762
            ],
763
            [
764
                Schema::TYPE_TEXT . " CHECK (value LIKE 'test%')",
765
                $this->text()->check("value LIKE 'test%'"),
766
                [
767
                    'mysql' => "text CHECK (value LIKE 'test%')",
768
                    'sqlite' => "text CHECK (value LIKE 'test%')",
769
                    'sqlsrv' => "nvarchar(max) CHECK (value LIKE 'test%')",
770
                ],
771
                Schema::TYPE_TEXT . " CHECK (value LIKE 'test%')",
772
            ],
773
            [
774
                Schema::TYPE_TEXT . ' CHECK (value LIKE \'test%\')',
775
                $this->text()->check('value LIKE \'test%\''),
776
                [
777
                    'pgsql' => 'text CHECK (value LIKE \'test%\')',
778
                    'oci' => 'CLOB CHECK (value LIKE \'test%\')',
779
                ],
780
                Schema::TYPE_TEXT . ' CHECK (value LIKE \'test%\')',
781
            ],
782
            [
783
                Schema::TYPE_TEXT . ' NOT NULL',
784
                $this->text()->notNull(),
785
                [
786
                    'mysql' => 'text NOT NULL',
787
                    'pgsql' => 'text NOT NULL',
788
                    'sqlite' => 'text NOT NULL',
789
                    'oci' => 'CLOB NOT NULL',
790
                    'sqlsrv' => 'nvarchar(max) NOT NULL',
791
                ],
792
                Schema::TYPE_TEXT . ' NOT NULL',
793
            ],
794
            [
795
                Schema::TYPE_TEXT,
796
                $this->text(),
797
                [
798
                    'mysql' => 'text',
799
                    'pgsql' => 'text',
800
                    'sqlite' => 'text',
801
                    'oci' => 'CLOB',
802
                    'sqlsrv' => 'nvarchar(max)',
803
                ],
804
                Schema::TYPE_TEXT,
805
            ],
806
            [
807
                Schema::TYPE_TEXT,
808
                $this->text(),
809
                [
810
                    'mysql' => 'text',
811
                    'pgsql' => 'text',
812
                    'sqlite' => 'text',
813
                    'oci' => 'CLOB',
814
                    'sqlsrv' => 'nvarchar(max)',
815
                ],
816
            ],
817
            [
818
                Schema::TYPE_TIME . ' NOT NULL',
819
                $this->time()->notNull(),
820
                [
821
                    'mysql' => version_compare($version, '5.6.4', '>=') ? 'time(0) NOT NULL' : 'time NOT NULL',
822
                    'pgsql' => 'time(0) NOT NULL',
823
                    'sqlite' => 'time NOT NULL',
824
                    'oci' => 'TIMESTAMP NOT NULL',
825
                    'sqlsrv' => 'time NOT NULL',
826
                ],
827
            ],
828
            [
829
                Schema::TYPE_TIME,
830
                $this->time(),
831
                [
832
                    'mysql' => version_compare($version, '5.6.4', '>=') ? 'time(0)' : 'time',
833
                    'pgsql' => 'time(0)',
834
                    'sqlite' => 'time',
835
                    'oci' => 'TIMESTAMP',
836
                    'sqlsrv' => 'time',
837
                ],
838
            ],
839
            [
840
                Schema::TYPE_TIMESTAMP . ' NOT NULL',
841
                $this->timestamp()->notNull(),
842
                [
843
                    'mysql' => version_compare($version, '5.6.4', '>=') ? 'timestamp(0) NOT NULL'
844
                        : 'timestamp NOT NULL',
845
                    'pgsql' => 'timestamp(0) NOT NULL',
846
                    'sqlite' => 'timestamp NOT NULL',
847
                    'oci' => 'TIMESTAMP NOT NULL',
848
                    'sqlsrv' => 'datetime NOT NULL',
849
                ],
850
            ],
851
            [
852
                Schema::TYPE_TIMESTAMP . ' NULL DEFAULT NULL',
853
                $this->timestamp()->defaultValue(null),
854
                [
855
                    'mysql' => version_compare($version, '5.6.4', '>=') ? 'timestamp(0) NULL DEFAULT NULL'
856
                        : 'timestamp NULL DEFAULT NULL',
857
                    'pgsql' => 'timestamp(0) NULL DEFAULT NULL',
858
                    'sqlite' => 'timestamp NULL DEFAULT NULL',
859
                    'sqlsrv' => 'datetime NULL DEFAULT NULL',
860
                ],
861
            ],
862
            [
863
                Schema::TYPE_TIMESTAMP . '(4)',
864
                $this->timestamp(4),
865
                [
866
                    'pgsql' => 'timestamp(4)',
867
                ],
868
            ],
869
            [
870
                Schema::TYPE_TIMESTAMP,
871
                $this->timestamp(),
872
                [
873
                    /**
874
                     * MySQL has its own TIMESTAMP test realization.
875
                     *
876
                     * {@see QueryBuilderTest::columnTypes()}
877
                     */
878
                    'pgsql' => 'timestamp(0)',
879
                    'sqlite' => 'timestamp',
880
                    'oci' => 'TIMESTAMP',
881
                    'sqlsrv' => 'datetime',
882
                ],
883
            ],
884
            [
885
                Schema::TYPE_UPK,
886
                $this->primaryKey()->unsigned(),
887
                [
888
                    'mysql' => 'int(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY',
889
                    'pgsql' => 'serial NOT NULL PRIMARY KEY',
890
                    'sqlite' => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL',
891
                ],
892
            ],
893
            [
894
                Schema::TYPE_UBIGPK,
895
                $this->bigPrimaryKey()->unsigned(),
896
                [
897
                    'mysql' => 'bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY',
898
                    'pgsql' => 'bigserial NOT NULL PRIMARY KEY',
899
                    'sqlite' => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL',
900
                ],
901
            ],
902
            [
903
                Schema::TYPE_INTEGER . " COMMENT 'test comment'",
904
                $this->integer()->comment('test comment'),
905
                [
906
                    'mysql' => "int(11) COMMENT 'test comment'",
907
                    'sqlsrv' => 'int',
908
                ],
909
                [
910
                    'sqlsrv' => 'integer',
911
                ],
912
            ],
913
            [
914
                Schema::TYPE_PK . " COMMENT 'test comment'",
915
                $this->primaryKey()->comment('test comment'),
916
                [
917
                    'mysql' => "int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'test comment'",
918
                    'sqlsrv' => 'int IDENTITY PRIMARY KEY',
919
                ],
920
                [
921
                    'sqlsrv' => 'pk',
922
                ],
923
            ],
924
            [
925
                Schema::TYPE_PK . ' FIRST',
926
                $this->primaryKey()->first(),
927
                [
928
                    'mysql' => 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST',
929
                    'sqlsrv' => 'int IDENTITY PRIMARY KEY',
930
                ],
931
                [
932
                    'oci' => 'NUMBER(10) NOT NULL PRIMARY KEY FIRST',
933
                    'sqlsrv' => 'pk',
934
                ],
935
            ],
936
            [
937
                Schema::TYPE_INTEGER . ' FIRST',
938
                $this->integer()->first(),
939
                [
940
                    'mysql' => 'int(11) FIRST',
941
                    'sqlsrv' => 'int',
942
                ],
943
                [
944
                    'oci' => 'NUMBER(10) FIRST',
945
                    'pgsql' => 'integer',
946
                    'sqlsrv' => 'integer',
947
                ],
948
            ],
949
            [
950
                Schema::TYPE_STRING . ' FIRST',
951
                $this->string()->first(),
952
                [
953
                    'mysql' => 'varchar(255) FIRST',
954
                    'sqlsrv' => 'nvarchar(255)',
955
                ],
956
                [
957
                    'oci' => 'VARCHAR2(255) FIRST',
958
                    'sqlsrv' => 'string',
959
                ],
960
            ],
961
            [
962
                Schema::TYPE_INTEGER . ' NOT NULL FIRST',
963
                $this->integer()->append('NOT NULL')->first(),
964
                [
965
                    'mysql' => 'int(11) NOT NULL FIRST',
966
                    'sqlsrv' => 'int NOT NULL',
967
                ],
968
                [
969
                    'oci' => 'NUMBER(10) NOT NULL FIRST',
970
                    'sqlsrv' => 'integer NOT NULL',
971
                ],
972
            ],
973
            [
974
                Schema::TYPE_STRING . ' NOT NULL FIRST',
975
                $this->string()->append('NOT NULL')->first(),
976
                [
977
                    'mysql' => 'varchar(255) NOT NULL FIRST',
978
                    'sqlsrv' => 'nvarchar(255) NOT NULL',
979
                ],
980
                [
981
                    'oci' => 'VARCHAR2(255) NOT NULL FIRST',
982
                    'sqlsrv' => 'string NOT NULL',
983
                ],
984
            ],
985
            [
986
                Schema::TYPE_JSON,
987
                $this->json(),
988
                [
989
                    'pgsql' => 'jsonb',
990
                ],
991
            ],
992
        ];
993
994
        foreach ($items as $i => $item) {
995
            if (array_key_exists($this->getConnection()->getDriverName(), $item[2])) {
996
                $item[2] = $item[2][$this->getConnection()->getDriverName()];
997
                $items[$i] = $item;
998
            } else {
999
                unset($items[$i]);
1000
            }
1001
        }
1002
1003
        return array_values($items);
1004
    }
1005
1006
    public function testGetColumnType(): void
1007
    {
1008
        $db = $this->getConnection();
1009
        $qb = $db->getQueryBuilder();
1010
1011
        foreach ($this->columnTypes() as $item) {
1012
            [$column, $builder, $expected] = $item;
1013
1014
            if (isset($item[3][$db->getDriverName()])) {
1015
                $expectedColumnSchemaBuilder = $item[3][$db->getDriverName()];
1016
            } elseif (isset($item[3]) && !is_array($item[3])) {
1017
                $expectedColumnSchemaBuilder = $item[3];
1018
            } else {
1019
                $expectedColumnSchemaBuilder = $column;
1020
            }
1021
1022
            $this->assertEquals($expected, $qb->getColumnType($column));
0 ignored issues
show
Bug introduced by
It seems like assertEquals() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

1022
            $this->/** @scrutinizer ignore-call */ 
1023
                   assertEquals($expected, $qb->getColumnType($column));
Loading history...
1023
            $this->assertEquals($expected, $qb->getColumnType($builder));
1024
            $this->assertEquals($expectedColumnSchemaBuilder, $builder->__toString());
1025
        }
1026
    }
1027
1028
    public function testCreateTableColumnTypes(): void
1029
    {
1030
        $db = $this->getConnection();
1031
        $qb = $db->getQueryBuilder();
1032
1033
        if ($db->getTableSchema('column_type_table', true) !== null) {
1034
            $db->createCommand($qb->dropTable('column_type_table'))->execute();
1035
        }
1036
1037
        $columns = [];
1038
        $i = 0;
1039
1040
        foreach ($this->columnTypes() as [$column, $builder, $expected]) {
1041
            if (
1042
                !(
1043
                    strncmp($column, Schema::TYPE_PK, 2) === 0 ||
1044
                    strncmp($column, Schema::TYPE_UPK, 3) === 0 ||
1045
                    strncmp($column, Schema::TYPE_BIGPK, 5) === 0 ||
1046
                    strncmp($column, Schema::TYPE_UBIGPK, 6) === 0 ||
1047
                    strncmp(substr($column, -5), 'FIRST', 5) === 0
1048
                )
1049
            ) {
1050
                $columns['col' . ++$i] = str_replace('CHECK (value', 'CHECK ([[col' . $i . ']]', $column);
1051
            }
1052
        }
1053
1054
        $db->createCommand($qb->createTable('column_type_table', $columns))->execute();
1055
        $this->assertNotEmpty($db->getTableSchema('column_type_table', true));
0 ignored issues
show
Bug introduced by
It seems like assertNotEmpty() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

1055
        $this->/** @scrutinizer ignore-call */ 
1056
               assertNotEmpty($db->getTableSchema('column_type_table', true));
Loading history...
1056
    }
1057
1058
    public function testBuildWhereExistsWithParameters(): void
1059
    {
1060
        $db = $this->getConnection();
1061
1062
        $expectedQuerySql = $this->replaceQuotes(
0 ignored issues
show
Bug introduced by
It seems like replaceQuotes() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

1062
        /** @scrutinizer ignore-call */ 
1063
        $expectedQuerySql = $this->replaceQuotes(
Loading history...
1063
            'SELECT [[id]] FROM [[TotalExample]] [[t]] WHERE (EXISTS (SELECT [[1]] FROM [[Website]] [[w]]'
1064
            . ' WHERE (w.id = t.website_id) AND (w.merchant_id = :merchant_id))) AND (t.some_column = :some_value)'
1065
        );
1066
1067
        $expectedQueryParams = [':some_value' => 'asd', ':merchant_id' => 6];
1068
1069
        $subQuery = new Query($db);
1070
1071
        $subQuery->select('1')
1072
            ->from('Website w')
1073
            ->where('w.id = t.website_id')
1074
            ->andWhere('w.merchant_id = :merchant_id', [':merchant_id' => 6]);
1075
1076
        $query = new Query($db);
1077
1078
        $query->select('id')
1079
            ->from('TotalExample t')
1080
            ->where(['exists', $subQuery])
1081
            ->andWhere('t.some_column = :some_value', [':some_value' => 'asd']);
1082
1083
        [$actualQuerySql, $queryParams] = $db->getQueryBuilder()->build($query);
1084
1085
        $this->assertEquals($expectedQuerySql, $actualQuerySql);
1086
        $this->assertEquals($expectedQueryParams, $queryParams);
1087
    }
1088
1089
    public function testBuildWhereExistsWithArrayParameters(): void
1090
    {
1091
        $db = $this->getConnection();
1092
1093
        $expectedQuerySql = $this->replaceQuotes(
1094
            'SELECT [[id]] FROM [[TotalExample]] [[t]] WHERE (EXISTS (SELECT [[1]] FROM [[Website]] [[w]]'
1095
            . ' WHERE (w.id = t.website_id) AND (([[w]].[[merchant_id]]=:qp0) AND ([[w]].[[user_id]]=:qp1))))'
1096
            . ' AND ([[t]].[[some_column]]=:qp2)'
1097
        );
1098
1099
        $expectedQueryParams = [':qp0' => 6, ':qp1' => 210, ':qp2' => 'asd'];
1100
1101
        $subQuery = new Query($db);
1102
1103
        $subQuery->select('1')
1104
            ->from('Website w')
1105
            ->where('w.id = t.website_id')
1106
            ->andWhere(['w.merchant_id' => 6, 'w.user_id' => '210']);
1107
1108
        $query = new Query($db);
1109
1110
        $query->select('id')
1111
            ->from('TotalExample t')
1112
            ->where(['exists', $subQuery])
1113
            ->andWhere(['t.some_column' => 'asd']);
1114
1115
        [$actualQuerySql, $queryParams] = $db->getQueryBuilder()->build($query);
1116
1117
        $this->assertEquals($expectedQuerySql, $actualQuerySql);
1118
        $this->assertEquals($expectedQueryParams, $queryParams);
1119
    }
1120
1121
    /**
1122
     * This test contains three select queries connected with UNION and UNION ALL constructions.
1123
     * It could be useful to use "phpunit --group=db --filter testBuildUnion" command for run it.
1124
     */
1125
    public function testBuildUnion(): void
1126
    {
1127
        $db = $this->getConnection();
1128
1129
        $expectedQuerySql = $this->replaceQuotes(
1130
            '(SELECT [[id]] FROM [[TotalExample]] [[t1]] WHERE (w > 0) AND (x < 2)) UNION ( SELECT [[id]]'
1131
            . ' FROM [[TotalTotalExample]] [[t2]] WHERE w > 5 ) UNION ALL ( SELECT [[id]] FROM [[TotalTotalExample]]'
1132
            . ' [[t3]] WHERE w = 3 )'
1133
        );
1134
1135
        $query = new Query($db);
1136
        $secondQuery = new Query($db);
1137
1138
        $secondQuery->select('id')
1139
              ->from('TotalTotalExample t2')
1140
              ->where('w > 5');
1141
1142
        $thirdQuery = new Query($db);
1143
1144
        $thirdQuery->select('id')
1145
              ->from('TotalTotalExample t3')
1146
              ->where('w = 3');
1147
1148
        $query->select('id')
1149
              ->from('TotalExample t1')
1150
              ->where(['and', 'w > 0', 'x < 2'])
1151
              ->union($secondQuery)
1152
              ->union($thirdQuery, true);
1153
1154
        [$actualQuerySql, $queryParams] = $db->getQueryBuilder()->build($query);
1155
1156
        $this->assertEquals($expectedQuerySql, $actualQuerySql);
1157
        $this->assertEquals([], $queryParams);
1158
    }
1159
1160
    public function testBuildWithQuery(): void
1161
    {
1162
        $db = $this->getConnection();
1163
1164
        $expectedQuerySql = $this->replaceQuotes(
1165
            'WITH a1 AS (SELECT [[id]] FROM [[t1]] WHERE expr = 1), a2 AS ((SELECT [[id]] FROM [[t2]]'
1166
            . ' INNER JOIN [[a1]] ON t2.id = a1.id WHERE expr = 2) UNION ( SELECT [[id]] FROM [[t3]] WHERE expr = 3 ))'
1167
            . ' SELECT * FROM [[a2]]'
1168
        );
1169
1170
        $with1Query = (new Query($db))
1171
            ->select('id')
1172
            ->from('t1')
1173
            ->where('expr = 1');
1174
1175
        $with2Query = (new Query($db))
1176
            ->select('id')
1177
            ->from('t2')
1178
            ->innerJoin('a1', 't2.id = a1.id')
1179
            ->where('expr = 2');
1180
1181
        $with3Query = (new Query($db))
1182
            ->select('id')
1183
            ->from('t3')
1184
            ->where('expr = 3');
1185
1186
        $query = (new Query($db))
1187
            ->withQuery($with1Query, 'a1')
1188
            ->withQuery($with2Query->union($with3Query), 'a2')
1189
            ->from('a2');
1190
1191
        [$actualQuerySql, $queryParams] = $db->getQueryBuilder()->build($query);
1192
1193
        $this->assertEquals($expectedQuerySql, $actualQuerySql);
1194
        $this->assertEquals([], $queryParams);
1195
    }
1196
1197
    public function testBuildWithQueryRecursive(): void
1198
    {
1199
        $db = $this->getConnection();
1200
1201
        $expectedQuerySql = $this->replaceQuotes(
1202
            'WITH RECURSIVE a1 AS (SELECT [[id]] FROM [[t1]] WHERE expr = 1) SELECT * FROM [[a1]]'
1203
        );
1204
1205
        $with1Query = (new Query($db))
1206
            ->select('id')
1207
            ->from('t1')
1208
            ->where('expr = 1');
1209
1210
        $query = (new Query($db))
1211
            ->withQuery($with1Query, 'a1', true)
1212
            ->from('a1');
1213
1214
        [$actualQuerySql, $queryParams] = $db->getQueryBuilder()->build($query);
1215
1216
        $this->assertEquals($expectedQuerySql, $actualQuerySql);
1217
        $this->assertEquals([], $queryParams);
1218
    }
1219
1220
    public function testSelectSubquery(): void
1221
    {
1222
        $db = $this->getConnection();
1223
1224
        $subquery = (new Query($db))
1225
            ->select('COUNT(*)')
1226
            ->from('operations')
1227
            ->where('account_id = accounts.id');
1228
1229
        $query = (new Query($db))
1230
            ->select('*')
1231
            ->from('accounts')
1232
            ->addSelect(['operations_count' => $subquery]);
1233
1234
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1235
1236
        $expected = $this->replaceQuotes(
1237
            'SELECT *, (SELECT COUNT(*) FROM [[operations]] WHERE account_id = accounts.id) AS [[operations_count]]'
1238
            . ' FROM [[accounts]]'
1239
        );
1240
1241
        $this->assertEquals($expected, $sql);
1242
        $this->assertEmpty($params);
0 ignored issues
show
Bug introduced by
It seems like assertEmpty() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

1242
        $this->/** @scrutinizer ignore-call */ 
1243
               assertEmpty($params);
Loading history...
1243
    }
1244
1245
    public function testComplexSelect(): void
1246
    {
1247
        $db = $this->getConnection();
1248
1249
        $query = (new Query($db))
1250
            ->select([
1251
                'ID' => 't.id',
1252
                'gsm.username as GSM',
1253
                'part.Part',
1254
                'Part Cost' => 't.Part_Cost',
1255
                'st_x(location::geometry) as lon',
1256
                new Expression(
1257
                    $this->replaceQuotes(
1258
                        "case t.Status_Id when 1 then 'Acknowledge' when 2 then 'No Action' else 'Unknown Action'"
1259
                        . ' END as [[Next Action]]'
1260
                    )
1261
                ),
1262
            ])
1263
            ->from('tablename');
1264
1265
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1266
1267
        $expected = $this->replaceQuotes(
1268
            'SELECT [[t]].[[id]] AS [[ID]], [[gsm]].[[username]] AS [[GSM]], [[part]].[[Part]], [[t]].[[Part_Cost]]'
1269
            . ' AS [[Part Cost]], st_x(location::geometry) AS [[lon]], case t.Status_Id when 1 then \'Acknowledge\''
1270
            . ' when 2 then \'No Action\' else \'Unknown Action\' END as [[Next Action]] FROM [[tablename]]'
1271
        );
1272
1273
        $this->assertEquals($expected, $sql);
1274
        $this->assertEmpty($params);
1275
    }
1276
1277
    public function testSelectExpression(): void
1278
    {
1279
        $db = $this->getConnection();
1280
1281
        $query = (new Query($db))
1282
            ->select(new Expression('1 AS ab'))
1283
            ->from('tablename');
1284
1285
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1286
1287
        $expected = $this->replaceQuotes('SELECT 1 AS ab FROM [[tablename]]');
1288
1289
        $this->assertEquals($expected, $sql);
1290
        $this->assertEmpty($params);
1291
1292
        $query = (new Query($db))
1293
            ->select(new Expression('1 AS ab'))
1294
            ->addSelect(new Expression('2 AS cd'))
1295
            ->addSelect(['ef' => new Expression('3')])
1296
            ->from('tablename');
1297
1298
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1299
1300
        $expected = $this->replaceQuotes('SELECT 1 AS ab, 2 AS cd, 3 AS [[ef]] FROM [[tablename]]');
1301
1302
        $this->assertEquals($expected, $sql);
1303
        $this->assertEmpty($params);
1304
1305
        $query = (new Query($db))
1306
            ->select(new Expression('SUBSTR(name, 0, :len)', [':len' => 4]))
1307
            ->from('tablename');
1308
1309
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1310
1311
        $expected = $this->replaceQuotes('SELECT SUBSTR(name, 0, :len) FROM [[tablename]]');
1312
1313
        $this->assertEquals($expected, $sql);
1314
        $this->assertEquals([':len' => 4], $params);
1315
    }
1316
1317
    /**
1318
     * {@see https://github.com/yiisoft/yii2/issues/10869}
1319
     */
1320
    public function testFromIndexHint(): void
1321
    {
1322
        $db = $this->getConnection();
1323
1324
        $query = (new Query($db))->from([new Expression('{{%user}} USE INDEX (primary)')]);
1325
1326
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1327
1328
        $expected = $this->replaceQuotes('SELECT * FROM {{%user}} USE INDEX (primary)');
1329
1330
        $this->assertEquals($expected, $sql);
1331
        $this->assertEmpty($params);
1332
1333
        $query = (new Query($db))
1334
            ->from([new Expression('{{user}} {{t}} FORCE INDEX (primary) IGNORE INDEX FOR ORDER BY (i1)')])
1335
            ->leftJoin(['p' => 'profile'], 'user.id = profile.user_id USE INDEX (i2)');
1336
1337
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1338
1339
        $expected = $this->replaceQuotes(
1340
            'SELECT * FROM {{user}} {{t}} FORCE INDEX (primary) IGNORE INDEX FOR ORDER BY (i1)'
1341
            . ' LEFT JOIN [[profile]] [[p]] ON user.id = profile.user_id USE INDEX (i2)'
1342
        );
1343
1344
        $this->assertEquals($expected, $sql);
1345
        $this->assertEmpty($params);
1346
    }
1347
1348
    public function testFromSubquery(): void
1349
    {
1350
        $db = $this->getConnection();
1351
1352
        /* query subquery */
1353
        $subquery = (new Query($db))->from('user')->where('account_id = accounts.id');
1354
1355
        $query = (new Query($db))->from(['activeusers' => $subquery]);
1356
1357
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
1358
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1359
1360
        $expected = $this->replaceQuotes(
1361
            'SELECT * FROM (SELECT * FROM [[user]] WHERE account_id = accounts.id) [[activeusers]]'
1362
        );
1363
1364
        $this->assertEquals($expected, $sql);
1365
        $this->assertEmpty($params);
1366
1367
        /* query subquery with params */
1368
        $subquery = (new Query($db))->from('user')->where('account_id = :id', ['id' => 1]);
1369
1370
        $query = (new Query($db))->from(['activeusers' => $subquery])->where('abc = :abc', ['abc' => 'abc']);
1371
1372
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
1373
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1374
1375
        $expected = $this->replaceQuotes(
1376
            'SELECT * FROM (SELECT * FROM [[user]] WHERE account_id = :id) [[activeusers]] WHERE abc = :abc'
1377
        );
1378
1379
        $this->assertEquals($expected, $sql);
1380
        $this->assertEquals(['id' => 1, 'abc' => 'abc'], $params);
1381
1382
        /* simple subquery */
1383
        $subquery = '(SELECT * FROM user WHERE account_id = accounts.id)';
1384
1385
        $query = (new Query($db))->from(['activeusers' => $subquery]);
1386
1387
        /* SELECT * FROM (SELECT * FROM [[user]] WHERE [[active]] = 1) [[activeusers]]; */
1388
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1389
1390
        $expected = $this->replaceQuotes(
1391
            'SELECT * FROM (SELECT * FROM user WHERE account_id = accounts.id) [[activeusers]]'
1392
        );
1393
1394
        $this->assertEquals($expected, $sql);
1395
        $this->assertEmpty($params);
1396
    }
1397
1398
    public function testOrderBy(): void
1399
    {
1400
        $db = $this->getConnection();
1401
1402
        /* simple string */
1403
        $query = (new Query($db))
1404
            ->select('*')
1405
            ->from('operations')
1406
            ->orderBy('name ASC, date DESC');
1407
1408
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1409
1410
        $expected = $this->replaceQuotes('SELECT * FROM [[operations]] ORDER BY [[name]], [[date]] DESC');
1411
1412
        $this->assertEquals($expected, $sql);
1413
        $this->assertEmpty($params);
1414
1415
        /* array syntax */
1416
        $query = (new Query($db))
1417
            ->select('*')
1418
            ->from('operations')
1419
            ->orderBy(['name' => SORT_ASC, 'date' => SORT_DESC]);
1420
1421
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1422
1423
        $expected = $this->replaceQuotes('SELECT * FROM [[operations]] ORDER BY [[name]], [[date]] DESC');
1424
1425
        $this->assertEquals($expected, $sql);
1426
        $this->assertEmpty($params);
1427
1428
        /* expression */
1429
        $query = (new Query($db))
1430
            ->select('*')
1431
            ->from('operations')
1432
            ->where('account_id = accounts.id')
1433
            ->orderBy(new Expression('SUBSTR(name, 3, 4) DESC, x ASC'));
1434
1435
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1436
1437
        $expected = $this->replaceQuotes(
1438
            'SELECT * FROM [[operations]] WHERE account_id = accounts.id ORDER BY SUBSTR(name, 3, 4) DESC, x ASC'
1439
        );
1440
1441
        $this->assertEquals($expected, $sql);
1442
        $this->assertEmpty($params);
1443
1444
        /* expression with params */
1445
        $query = (new Query($db))
1446
            ->select('*')
1447
            ->from('operations')
1448
            ->orderBy(new Expression('SUBSTR(name, 3, :to) DESC, x ASC', [':to' => 4]));
1449
1450
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1451
1452
        $expected = $this->replaceQuotes('SELECT * FROM [[operations]] ORDER BY SUBSTR(name, 3, :to) DESC, x ASC');
1453
1454
        $this->assertEquals($expected, $sql);
1455
        $this->assertEquals([':to' => 4], $params);
1456
    }
1457
1458
    public function testGroupBy(): void
1459
    {
1460
        $db = $this->getConnection();
1461
1462
        /* simple string */
1463
        $query = (new Query($db))
1464
            ->select('*')
1465
            ->from('operations')
1466
            ->groupBy('name, date');
1467
1468
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1469
1470
        $expected = $this->replaceQuotes('SELECT * FROM [[operations]] GROUP BY [[name]], [[date]]');
1471
1472
        $this->assertEquals($expected, $sql);
1473
        $this->assertEmpty($params);
1474
1475
        /* array syntax */
1476
        $query = (new Query($db))
1477
            ->select('*')
1478
            ->from('operations')
1479
            ->groupBy(['name', 'date']);
1480
1481
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1482
1483
        $expected = $this->replaceQuotes('SELECT * FROM [[operations]] GROUP BY [[name]], [[date]]');
1484
1485
        $this->assertEquals($expected, $sql);
1486
        $this->assertEmpty($params);
1487
1488
        /* expression */
1489
        $query = (new Query($db))
1490
            ->select('*')
1491
            ->from('operations')
1492
            ->where('account_id = accounts.id')
1493
            ->groupBy(new Expression('SUBSTR(name, 0, 1), x'));
1494
1495
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1496
1497
        $expected = $this->replaceQuotes(
1498
            'SELECT * FROM [[operations]] WHERE account_id = accounts.id GROUP BY SUBSTR(name, 0, 1), x'
1499
        );
1500
1501
        $this->assertEquals($expected, $sql);
1502
        $this->assertEmpty($params);
1503
1504
        /* expression with params */
1505
        $query = (new Query($db))
1506
            ->select('*')
1507
            ->from('operations')
1508
            ->groupBy(new Expression('SUBSTR(name, 0, :to), x', [':to' => 4]));
1509
1510
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1511
1512
        $expected = $this->replaceQuotes('SELECT * FROM [[operations]] GROUP BY SUBSTR(name, 0, :to), x');
1513
1514
        $this->assertEquals($expected, $sql);
1515
        $this->assertEquals([':to' => 4], $params);
1516
    }
1517
1518
    /**
1519
     * Dummy test to speed up QB's tests which rely on DB schema.
1520
     */
1521
    public function testInitFixtures(): void
1522
    {
1523
        $db = $this->getConnection();
1524
        $this->assertInstanceOf(QueryBuilder::class, $db->getQueryBuilder());
0 ignored issues
show
Bug introduced by
It seems like assertInstanceOf() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

1524
        $this->/** @scrutinizer ignore-call */ 
1525
               assertInstanceOf(QueryBuilder::class, $db->getQueryBuilder());
Loading history...
1525
    }
1526
1527
    /**
1528
     * {@see https://github.com/yiisoft/yii2/issues/15653}
1529
     */
1530
    public function testIssue15653(): void
1531
    {
1532
        $db = $this->getConnection();
1533
1534
        $query = (new Query($db))
1535
            ->from('admin_user')
1536
            ->where(['is_deleted' => false]);
1537
1538
        $query
1539
            ->where([])
1540
            ->andWhere(['in', 'id', ['1', '0']]);
1541
1542
        [$sql, $params] = $db->getQueryBuilder()->build($query);
1543
1544
        $this->assertSame($this->replaceQuotes('SELECT * FROM [[admin_user]] WHERE [[id]] IN (:qp0, :qp1)'), $sql);
0 ignored issues
show
Bug introduced by
It seems like assertSame() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

1544
        $this->/** @scrutinizer ignore-call */ 
1545
               assertSame($this->replaceQuotes('SELECT * FROM [[admin_user]] WHERE [[id]] IN (:qp0, :qp1)'), $sql);
Loading history...
1545
        $this->assertSame([':qp0' => '1', ':qp1' => '0'], $params);
1546
    }
1547
}
1548