Passed
Push — master ( 914087...c6011d )
by Alexander
11:22
created

TestQueryTrait::testColumn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 51
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 32
c 1
b 0
f 0
dl 0
loc 51
rs 9.408
cc 1
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\TestSupport;
6
7
use Yiisoft\Db\Connection\ConnectionInterface;
8
use Yiisoft\Db\Exception\Exception;
9
use Yiisoft\Db\Exception\InvalidArgumentException;
10
use Yiisoft\Db\Exception\InvalidConfigException;
11
use Yiisoft\Db\Exception\NotSupportedException;
12
use Yiisoft\Db\Expression\Expression;
13
use Yiisoft\Db\Query\Query;
14
use Yiisoft\Db\Query\QueryInterface;
15
use Yiisoft\Db\Schema\Schema;
16
17
trait TestQueryTrait
18
{
19
    use GetTablesAliasTestTrait;
20
21
    public function testSelect(): void
22
    {
23
        $db = $this->getConnection();
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

23
        /** @scrutinizer ignore-call */ 
24
        $db = $this->getConnection();
Loading history...
24
25
        /* default */
26
        $query = new Query($db);
27
28
        $query->select('*');
29
30
        $this->assertEquals(['*' => '*'], $query->getSelect());
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

30
        $this->/** @scrutinizer ignore-call */ 
31
               assertEquals(['*' => '*'], $query->getSelect());
Loading history...
31
        $this->assertNull($query->getDistinct());
0 ignored issues
show
Bug introduced by
It seems like assertNull() 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

31
        $this->/** @scrutinizer ignore-call */ 
32
               assertNull($query->getDistinct());
Loading history...
32
        $this->assertNull($query->getSelectOption());
0 ignored issues
show
Bug introduced by
Are you sure the usage of $query->getSelectOption() targeting Yiisoft\Db\Query\Query::getSelectOption() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
33
34
        $query = new Query($db);
35
36
        $query->select('id, name', 'something')->distinct(true);
37
38
        $this->assertEquals(['id' => 'id', 'name' => 'name'], $query->getSelect());
39
        $this->assertTrue($query->getDistinct());
0 ignored issues
show
Bug introduced by
It seems like assertTrue() 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

39
        $this->/** @scrutinizer ignore-call */ 
40
               assertTrue($query->getDistinct());
Loading history...
40
        $this->assertEquals('something', $query->getSelectOption());
41
42
        $query = new Query($db);
43
44
        $query->addSelect('email');
45
46
        $this->assertEquals(['email' => 'email'], $query->getSelect());
47
48
        $query = new Query($db);
49
50
        $query->select('id, name');
51
        $query->addSelect('email');
52
53
        $this->assertEquals(['id' => 'id', 'name' => 'name', 'email' => 'email'], $query->getSelect());
54
55
        $query = new Query($db);
56
57
        $query->select('name, lastname');
58
        $query->addSelect('name');
59
60
        $this->assertEquals(['name' => 'name', 'lastname' => 'lastname'], $query->getSelect());
61
62
        $query = new Query($db);
63
64
        $query->addSelect(['*', 'abc']);
65
        $query->addSelect(['*', 'bca']);
66
67
        $this->assertEquals(['*' => '*', 'abc' => 'abc', 'bca' => 'bca'], $query->getSelect());
68
69
        $query = new Query($db);
70
71
        $query->addSelect(['field1 as a', 'field 1 as b']);
72
73
        $this->assertEquals(['a' => 'field1', 'b' => 'field 1'], $query->getSelect());
74
75
        $query = new Query($db);
76
77
        $query->addSelect(['field1 a', 'field 1 b']);
78
79
        $this->assertEquals(['a' => 'field1', 'b' => 'field 1'], $query->getSelect());
80
81
        $query = new Query($db);
82
83
        $query->select(['name' => 'firstname', 'lastname']);
84
        $query->addSelect(['firstname', 'surname' => 'lastname']);
85
        $query->addSelect(['firstname', 'lastname']);
86
87
        $this->assertEquals(
88
            ['name' => 'firstname', 'lastname' => 'lastname', 'firstname' => 'firstname', 'surname' => 'lastname'],
89
            $query->getSelect()
90
        );
91
92
        $query = new Query($db);
93
94
        $query->select('name, name, name as X, name as X');
95
96
        $this->assertEquals(['name' => 'name', 'X' => 'name'], $query->getSelect());
97
98
        /**
99
         * {@see https://github.com/yiisoft/yii2/issues/15676}
100
         */
101
        $query = (new Query($db))->select('id');
102
103
        $this->assertSame(['id' => 'id'], $query->getSelect());
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

103
        $this->/** @scrutinizer ignore-call */ 
104
               assertSame(['id' => 'id'], $query->getSelect());
Loading history...
104
105
        $query->select(['id', 'brand_id']);
106
107
        $this->assertSame(['id' => 'id', 'brand_id' => 'brand_id'], $query->getSelect());
108
109
        /**
110
         * {@see https://github.com/yiisoft/yii2/issues/15676}
111
         */
112
        $query = (new Query($db))
113
            ->select(['prefix' => 'LEFT(name, 7)', 'prefix_key' => 'LEFT(name, 7)']);
114
115
        $this->assertSame(['prefix' => 'LEFT(name, 7)', 'prefix_key' => 'LEFT(name, 7)'], $query->getSelect());
116
117
        $query->addSelect(['LEFT(name,7) as test']);
118
119
        $this->assertSame(
120
            ['prefix' => 'LEFT(name, 7)', 'prefix_key' => 'LEFT(name, 7)', 'test' => 'LEFT(name,7)'],
121
            $query->getSelect()
122
        );
123
124
        $query->addSelect(['LEFT(name,7) as test']);
125
126
        $this->assertSame(
127
            ['prefix' => 'LEFT(name, 7)', 'prefix_key' => 'LEFT(name, 7)', 'test' => 'LEFT(name,7)'],
128
            $query->getSelect()
129
        );
130
131
        $query->addSelect(['test' => 'LEFT(name,7)']);
132
133
        $this->assertSame(
134
            ['prefix' => 'LEFT(name, 7)', 'prefix_key' => 'LEFT(name, 7)', 'test' => 'LEFT(name,7)'],
135
            $query->getSelect()
136
        );
137
138
        /**
139
         * {@see https://github.com/yiisoft/yii2/issues/15731}
140
         */
141
        $selectedCols = [
142
            'total_sum' => 'SUM(f.amount)',
143
            'in_sum' => 'SUM(IF(f.type = :type_in, f.amount, 0))',
144
            'out_sum' => 'SUM(IF(f.type = :type_out, f.amount, 0))',
145
        ];
146
147
        $query = (new Query($db))->select($selectedCols)->addParams([
148
            ':type_in' => 'in',
149
            ':type_out' => 'out',
150
            ':type_partner' => 'partner',
151
        ]);
152
153
        $this->assertSame($selectedCols, $query->getSelect());
154
155
        $query->select($selectedCols);
156
157
        $this->assertSame($selectedCols, $query->getSelect());
158
159
        /**
160
         * {@see https://github.com/yiisoft/yii2/issues/17384}
161
         */
162
        $query = new Query($db);
163
164
        $query->select('DISTINCT ON(tour_dates.date_from) tour_dates.date_from, tour_dates.id');
165
166
        $this->assertEquals(
167
            ['DISTINCT ON(tour_dates.date_from) tour_dates.date_from', 'tour_dates.id' => 'tour_dates.id'],
168
            $query->getSelect()
169
        );
170
    }
171
172
    public function testFrom(): void
173
    {
174
        $db = $this->getConnection();
175
176
        $query = new Query($db);
177
178
        $query->from('user');
179
180
        $this->assertEquals(['user'], $query->getFrom());
181
    }
182
183
    public function testFromTableIsArrayWithExpression(): void
184
    {
185
        $db = $this->getConnection();
186
187
        $query = new Query($db);
188
189
        $tables = new Expression('(SELECT id,name FROM user) u');
190
191
        $query->from($tables);
192
        $from = $query->getFrom();
193
194
        $this->assertIsArray($from);
0 ignored issues
show
Bug introduced by
It seems like assertIsArray() 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

194
        $this->/** @scrutinizer ignore-call */ 
195
               assertIsArray($from);
Loading history...
195
        $this->assertInstanceOf(Expression::class, $from[0]);
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

195
        $this->/** @scrutinizer ignore-call */ 
196
               assertInstanceOf(Expression::class, $from[0]);
Loading history...
196
    }
197
198
    protected function createQuery(): QueryInterface
199
    {
200
        return new Query($this->getConnection());
201
    }
202
203
    public function testWhere(): void
204
    {
205
        $db = $this->getConnection();
206
207
        $query = new Query($db);
208
209
        $query->where('id = :id', [':id' => 1]);
210
211
        $this->assertEquals('id = :id', $query->getWhere());
212
        $this->assertEquals([':id' => 1], $query->getParams());
213
214
        $query->andWhere('name = :name', [':name' => 'something']);
215
216
        $this->assertEquals(['and', 'id = :id', 'name = :name'], $query->getWhere());
217
        $this->assertEquals([':id' => 1, ':name' => 'something'], $query->getParams());
218
219
        $query->orWhere('age = :age', [':age' => '30']);
220
221
        $this->assertEquals(['or', ['and', 'id = :id', 'name = :name'], 'age = :age'], $query->getWhere());
222
        $this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->getParams());
223
    }
224
225
    public function testFilterWhereWithHashFormat(): void
226
    {
227
        $db = $this->getConnection();
228
229
        $query = new Query($db);
230
231
        $query->filterWhere([
232
            'id' => 0,
233
            'title' => '   ',
234
            'author_ids' => [],
235
        ]);
236
237
        $this->assertEquals(['id' => 0], $query->getWhere());
238
239
        $query->andFilterWhere(['status' => null]);
240
241
        $this->assertEquals(['id' => 0], $query->getWhere());
242
243
        $query->orFilterWhere(['name' => '']);
244
245
        $this->assertEquals(['id' => 0], $query->getWhere());
246
    }
247
248
    public function testFilterWhereWithOperatorFormat(): void
249
    {
250
        $db = $this->getConnection();
251
252
        $query = new Query($db);
253
254
        $condition = ['like', 'name', 'Alex'];
255
256
        $query->filterWhere($condition);
257
258
        $this->assertEquals($condition, $query->getWhere());
259
260
        $query->andFilterWhere(['between', 'id', null, null]);
261
262
        $this->assertEquals($condition, $query->getWhere());
263
264
        $query->orFilterWhere(['not between', 'id', null, null]);
265
266
        $this->assertEquals($condition, $query->getWhere());
267
268
        $query->andFilterWhere(['in', 'id', []]);
269
270
        $this->assertEquals($condition, $query->getWhere());
271
272
        $query->andFilterWhere(['not in', 'id', []]);
273
274
        $this->assertEquals($condition, $query->getWhere());
275
276
        $query->andFilterWhere(['like', 'id', '']);
277
278
        $this->assertEquals($condition, $query->getWhere());
279
280
        $query->andFilterWhere(['or like', 'id', '']);
281
282
        $this->assertEquals($condition, $query->getWhere());
283
284
        $query->andFilterWhere(['not like', 'id', '   ']);
285
286
        $this->assertEquals($condition, $query->getWhere());
287
288
        $query->andFilterWhere(['or not like', 'id', null]);
289
290
        $this->assertEquals($condition, $query->getWhere());
291
292
        $query->andFilterWhere(['or', ['eq', 'id', null], ['eq', 'id', []]]);
293
294
        $this->assertEquals($condition, $query->getWhere());
295
    }
296
297
    public function testFilterHavingWithHashFormat(): void
298
    {
299
        $db = $this->getConnection();
300
301
        $query = new Query($db);
302
303
        $query->filterHaving([
304
            'id' => 0,
305
            'title' => '   ',
306
            'author_ids' => [],
307
        ]);
308
309
        $this->assertEquals(['id' => 0], $query->getHaving());
310
311
        $query->andFilterHaving(['status' => null]);
312
313
        $this->assertEquals(['id' => 0], $query->getHaving());
314
315
        $query->orFilterHaving(['name' => '']);
316
317
        $this->assertEquals(['id' => 0], $query->getHaving());
318
    }
319
320
    public function testFilterHavingWithOperatorFormat(): void
321
    {
322
        $db = $this->getConnection();
323
324
        $query = new Query($db);
325
326
        $condition = ['like', 'name', 'Alex'];
327
328
        $query->filterHaving($condition);
329
330
        $this->assertEquals($condition, $query->getHaving());
331
332
        $query->andFilterHaving(['between', 'id', null, null]);
333
334
        $this->assertEquals($condition, $query->getHaving());
335
336
        $query->orFilterHaving(['not between', 'id', null, null]);
337
338
        $this->assertEquals($condition, $query->getHaving());
339
340
        $query->andFilterHaving(['in', 'id', []]);
341
342
        $this->assertEquals($condition, $query->getHaving());
343
344
        $query->andFilterHaving(['not in', 'id', []]);
345
346
        $this->assertEquals($condition, $query->getHaving());
347
348
        $query->andFilterHaving(['like', 'id', '']);
349
350
        $this->assertEquals($condition, $query->getHaving());
351
352
        $query->andFilterHaving(['or like', 'id', '']);
353
354
        $this->assertEquals($condition, $query->getHaving());
355
356
        $query->andFilterHaving(['not like', 'id', '   ']);
357
358
        $this->assertEquals($condition, $query->getHaving());
359
360
        $query->andFilterHaving(['or not like', 'id', null]);
361
362
        $this->assertEquals($condition, $query->getHaving());
363
364
        $query->andFilterHaving(['or', ['eq', 'id', null], ['eq', 'id', []]]);
365
366
        $this->assertEquals($condition, $query->getHaving());
367
    }
368
369
    public function testFilterRecursively(): void
370
    {
371
        $db = $this->getConnection();
372
373
        $query = new Query($db);
374
375
        $query->filterWhere(
376
            ['and', ['like', 'name', ''],
377
                ['like', 'title', ''],
378
                ['id' => 1],
379
                ['not',
380
                    ['like', 'name', ''], ], ]
381
        );
382
383
        $this->assertEquals(['and', ['id' => 1]], $query->getWhere());
384
    }
385
386
    public function testGroup(): void
387
    {
388
        $db = $this->getConnection();
389
390
        $query = new Query($db);
391
392
        $query->groupBy('team');
393
394
        $this->assertEquals(['team'], $query->getGroupBy());
395
396
        $query->addGroupBy('company');
397
398
        $this->assertEquals(['team', 'company'], $query->getGroupBy());
399
400
        $query->addGroupBy('age');
401
402
        $this->assertEquals(['team', 'company', 'age'], $query->getGroupBy());
403
    }
404
405
    public function testHaving(): void
406
    {
407
        $db = $this->getConnection();
408
409
        $query = new Query($db);
410
411
        $query->having('id = :id', [':id' => 1]);
412
413
        $this->assertEquals('id = :id', $query->getHaving());
414
        $this->assertEquals([':id' => 1], $query->getParams());
415
416
        $query->andHaving('name = :name', [':name' => 'something']);
417
        $this->assertEquals(['and', 'id = :id', 'name = :name'], $query->getHaving());
418
        $this->assertEquals([':id' => 1, ':name' => 'something'], $query->getParams());
419
420
        $query->orHaving('age = :age', [':age' => '30']);
421
        $this->assertEquals(['or', ['and', 'id = :id', 'name = :name'], 'age = :age'], $query->getHaving());
422
        $this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->getParams());
423
    }
424
425
    public function testOrder(): void
426
    {
427
        $db = $this->getConnection();
428
429
        $query = new Query($db);
430
431
        $query->orderBy('team');
432
433
        $this->assertEquals(['team' => SORT_ASC], $query->getOrderBy());
434
435
        $query->addOrderBy('company');
436
437
        $this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC], $query->getOrderBy());
438
439
        $query->addOrderBy('age');
440
441
        $this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC, 'age' => SORT_ASC], $query->getOrderBy());
442
443
        $query->addOrderBy(['age' => SORT_DESC]);
444
445
        $this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC, 'age' => SORT_DESC], $query->getOrderBy());
446
447
        $query->addOrderBy('age ASC, company DESC');
448
449
        $this->assertEquals(['team' => SORT_ASC, 'company' => SORT_DESC, 'age' => SORT_ASC], $query->getOrderBy());
450
451
        $expression = new Expression('SUBSTR(name, 3, 4) DESC, x ASC');
452
453
        $query->orderBy($expression);
454
455
        $this->assertEquals([$expression], $query->getOrderBy());
456
457
        $expression = new Expression('SUBSTR(name, 3, 4) DESC, x ASC');
458
459
        $query->addOrderBy($expression);
460
461
        $this->assertEquals([$expression, $expression], $query->getOrderBy());
462
    }
463
464
    public function testLimitOffset(): void
465
    {
466
        $db = $this->getConnection();
467
468
        $query = new Query($db);
469
470
        $query->limit(10)->offset(5);
471
472
        $this->assertEquals(10, $query->getLimit());
473
        $this->assertEquals(5, $query->getOffset());
474
    }
475
476
    public function testLimitOffsetWithExpression(): void
477
    {
478
        $db = $this->getConnection();
479
480
        $query = (new Query($db))->from('customer')->select('id')->orderBy('id');
481
482
        $query
483
            ->limit(new Expression('1 + 1'))
484
            ->offset(new Expression('1 + 0'));
485
486
        $result = $query->column();
487
488
        $this->assertCount(2, $result);
0 ignored issues
show
Bug introduced by
It seems like assertCount() 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

488
        $this->/** @scrutinizer ignore-call */ 
489
               assertCount(2, $result);
Loading history...
489
490
        if ($db->getDriverName() !== 'sqlsrv' && $db->getDriverName() !== 'oci') {
491
            $this->assertContains(2, $result);
0 ignored issues
show
Bug introduced by
It seems like assertContains() 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

491
            $this->/** @scrutinizer ignore-call */ 
492
                   assertContains(2, $result);
Loading history...
492
            $this->assertContains(3, $result);
493
        } else {
494
            $this->assertContains('2', $result);
495
            $this->assertContains('3', $result);
496
        }
497
498
        $this->assertNotContains(1, $result);
0 ignored issues
show
Bug introduced by
It seems like assertNotContains() 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

498
        $this->/** @scrutinizer ignore-call */ 
499
               assertNotContains(1, $result);
Loading history...
499
    }
500
501
    public function testOne(): void
502
    {
503
        $db = $this->getConnection(true);
504
505
        $result = (new Query($db))->from('customer')->where(['status' => 2])->one();
506
507
        $this->assertEquals('user3', $result['name']);
508
509
        $result = (new Query($db))->from('customer')->where(['status' => 3])->one();
510
511
        $this->assertFalse($result);
0 ignored issues
show
Bug introduced by
It seems like assertFalse() 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

511
        $this->/** @scrutinizer ignore-call */ 
512
               assertFalse($result);
Loading history...
512
    }
513
514
    public function testExists(): void
515
    {
516
        $db = $this->getConnection();
517
518
        $result = (new Query($db))->from('customer')->where(['status' => 2])->exists();
519
520
        $this->assertTrue($result);
521
522
        $result = (new Query($db))->from('customer')->where(['status' => 3])->exists();
523
524
        $this->assertFalse($result);
525
    }
526
527
    public function testColumn(): void
528
    {
529
        $db = $this->getConnection();
530
531
        $result = (new Query($db))
532
            ->select('name')
533
            ->from('customer')
534
            ->orderBy(['id' => SORT_DESC])
535
            ->column();
536
537
        $this->assertEquals(['user3', 'user2', 'user1'], $result);
538
539
        /**
540
         * {@see https://github.com/yiisoft/yii2/issues/7515}
541
         */
542
        $result = (new Query($db))->from('customer')
543
            ->select('name')
544
            ->orderBy(['id' => SORT_DESC])
545
            ->indexBy('id')
546
            ->column();
547
548
        $this->assertEquals([3 => 'user3', 2 => 'user2', 1 => 'user1'], $result);
549
550
        /**
551
         * {@see https://github.com/yiisoft/yii2/issues/12649}
552
         */
553
        $result = (new Query($db))->from('customer')
554
            ->select(['name', 'id'])
555
            ->orderBy(['id' => SORT_DESC])
556
            ->indexBy(function ($row) {
557
                return $row['id'] * 2;
558
            })
559
            ->column();
560
561
        $this->assertEquals([6 => 'user3', 4 => 'user2', 2 => 'user1'], $result);
562
563
        $result = (new Query($db))->from('customer')
564
            ->select(['name'])
565
            ->indexBy('name')
566
            ->orderBy(['id' => SORT_DESC])
567
            ->column();
568
569
        $this->assertEquals(['user3' => 'user3', 'user2' => 'user2', 'user1' => 'user1'], $result);
570
571
        $result = (new Query($db))->from('customer')
572
            ->select(['name'])
573
            ->where(['id' => 10])
574
            ->orderBy(['id' => SORT_DESC])
575
            ->column();
576
577
        $this->assertEquals([], $result);
578
    }
579
580
    public function testCount(): void
581
    {
582
        $db = $this->getConnection();
583
584
        $count = (new Query($db))->from('customer')->count('*');
585
586
        $this->assertEquals(3, $count);
587
588
        $count = (new Query($db))->from('customer')->where(['status' => 2])->count('*');
589
590
        $this->assertEquals(1, $count);
591
592
        $count = (new Query($db))
593
            ->select('[[status]], COUNT([[id]]) cnt')
594
            ->from('customer')
595
            ->groupBy('status')
596
            ->count('*');
597
598
        $this->assertEquals(2, $count);
599
600
        /* testing that orderBy() should be ignored here as it does not affect the count anyway. */
601
        $count = (new Query($db))->from('customer')->orderBy('status')->count('*');
602
603
        $this->assertEquals(3, $count);
604
605
        $count = (new Query($db))->from('customer')->orderBy('id')->limit(1)->count('*');
606
607
        $this->assertEquals(3, $count);
608
    }
609
610
    /**
611
     * @depends testFilterWhereWithHashFormat
612
     * @depends testFilterWhereWithOperatorFormat
613
     */
614
    public function testAndFilterCompare(): void
615
    {
616
        $db = $this->getConnection();
617
618
        $query = new Query($db);
619
620
        $result = $query->andFilterCompare('name', null);
621
622
        $this->assertInstanceOf(QueryInterface::class, $result);
623
        $this->assertNull($query->getWhere());
624
625
        $query->andFilterCompare('name', '');
626
627
        $this->assertNull($query->getWhere());
628
629
        $query->andFilterCompare('name', 'John Doe');
630
        $condition = ['=', 'name', 'John Doe'];
631
632
        $this->assertEquals($condition, $query->getWhere());
633
634
        $condition = ['and', $condition, ['like', 'name', 'Doe']];
635
        $query->andFilterCompare('name', 'Doe', 'like');
636
637
        $this->assertEquals($condition, $query->getWhere());
638
639
        $condition[] = ['>', 'rating', '9'];
640
        $query->andFilterCompare('rating', '>9');
641
642
        $this->assertEquals($condition, $query->getWhere());
643
644
        $condition[] = ['<=', 'value', '100'];
645
        $query->andFilterCompare('value', '<=100');
646
647
        $this->assertEquals($condition, $query->getWhere());
648
    }
649
650
    public function testEmulateExecution(): void
651
    {
652
        $db = $this->getConnection();
653
654
        $this->assertGreaterThan(0, (new Query($db))->from('customer')->count('*'));
0 ignored issues
show
Bug introduced by
It seems like assertGreaterThan() 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

654
        $this->/** @scrutinizer ignore-call */ 
655
               assertGreaterThan(0, (new Query($db))->from('customer')->count('*'));
Loading history...
655
656
        $rows = (new Query($db))->from('customer')->emulateExecution()->all();
657
        $this->assertSame([], $rows);
658
659
        $row = (new Query($db))->from('customer')->emulateExecution()->one();
660
        $this->assertFalse($row);
661
662
        $exists = (new Query($db))->from('customer')->emulateExecution()->exists();
663
        $this->assertFalse($exists);
664
665
        $count = (new Query($db))->from('customer')->emulateExecution()->count('*');
666
        $this->assertSame(0, $count);
667
668
        $sum = (new Query($db))->from('customer')->emulateExecution()->sum('id');
669
        $this->assertNull($sum);
670
671
        $sum = (new Query($db))->from('customer')->emulateExecution()->average('id');
672
        $this->assertNull($sum);
673
674
        $max = (new Query($db))->from('customer')->emulateExecution()->max('id');
675
        $this->assertNull($max);
676
677
        $min = (new Query($db))->from('customer')->emulateExecution()->min('id');
678
        $this->assertNull($min);
679
680
        $scalar = (new Query($db))->select(['id'])->from('customer')->emulateExecution()->scalar();
681
        $this->assertNull($scalar);
682
683
        $column = (new Query($db))->select(['id'])->from('customer')->emulateExecution()->column();
684
        $this->assertSame([], $column);
685
    }
686
687
    /**
688
     * @param ConnectionInterface $db
689
     * @param string $tableName
690
     * @param string $columnName
691
     * @param array $condition
692
     * @param string $operator
693
     *
694
     * @throws Exception
695
     * @throws InvalidArgumentException
696
     * @throws InvalidConfigException
697
     * @throws NotSupportedException
698
     *
699
     * @return int
700
     */
701
    protected function countLikeQuery(
702
        ConnectionInterface $db,
703
        string $tableName,
704
        string $columnName,
705
        array $condition,
706
        string $operator = 'or'
707
    ): int {
708
        $whereCondition = [$operator];
709
710
        foreach ($condition as $value) {
711
            $whereCondition[] = ['like', $columnName, $value];
712
        }
713
714
        $result = (new Query($db))->from($tableName)->where($whereCondition)->count('*');
715
716
        if (is_numeric($result)) {
717
            return (int) $result;
718
        }
719
720
        return 0;
721
    }
722
723
    /**
724
     * {@see https://github.com/yiisoft/yii2/issues/13745}
725
     */
726
    public function testMultipleLikeConditions(): void
727
    {
728
        $db = $this->getConnection();
729
730
        $tableName = 'like_test';
731
        $columnName = 'col';
732
733
        if ($db->getSchema()->getTableSchema($tableName) !== null) {
734
            $db->createCommand()->dropTable($tableName)->execute();
735
        }
736
737
        $db->createCommand()->createTable($tableName, [
738
            $columnName => $db->getSchema()->createColumnSchemaBuilder(Schema::TYPE_STRING, 64),
739
        ])->execute();
740
741
        $db->createCommand()->batchInsert($tableName, ['col'], [
742
            ['test0'],
743
            ['test\1'],
744
            ['test\2'],
745
            ['foo%'],
746
            ['%bar'],
747
            ['%baz%'],
748
        ])->execute();
749
750
        /* Basic tests */
751
        $this->assertSame(1, $this->countLikeQuery($db, $tableName, $columnName, ['test0']));
752
        $this->assertSame(2, $this->countLikeQuery($db, $tableName, $columnName, ['test\\']));
753
        $this->assertSame(0, $this->countLikeQuery($db, $tableName, $columnName, ['test%']));
754
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, ['%']));
755
756
        /* Multiple condition tests */
757
        $this->assertSame(2, $this->countLikeQuery($db, $tableName, $columnName, [
758
            'test0',
759
            'test\1',
760
        ]));
761
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, [
762
            'test0',
763
            'test\1',
764
            'test\2',
765
        ]));
766
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, [
767
            'foo',
768
            '%ba',
769
        ]));
770
    }
771
772
    /**
773
     * {@see https://github.com/yiisoft/yii2/issues/15355}
774
     */
775
    public function testExpressionInFrom(): void
776
    {
777
        $db = $this->getConnection(true);
778
779
        $query = (new Query($db))
780
            ->from(
781
                new Expression(
782
                    '(SELECT [[id]], [[name]], [[email]], [[address]], [[status]] FROM {{customer}}) c'
783
                )
784
            )
785
            ->where(['status' => 2]);
786
787
        $result = $query->one();
788
789
        $this->assertEquals('user3', $result['name']);
790
    }
791
792
    public function testQueryCache()
793
    {
794
        $db = $this->getConnection();
795
796
        /** @psalm-suppress PossiblyNullReference */
797
        $this->queryCache->setEnable(true);
798
799
        $query = (new Query($db))
800
            ->select(['name'])
801
            ->from('customer');
802
803
        $update = $db->createCommand('UPDATE {{customer}} SET [[name]] = :name WHERE [[id]] = :id');
804
805
        $this->assertEquals('user1', $query->where(['id' => 1])->scalar(), 'Asserting initial value');
806
807
        /* No cache */
808
        $update->bindValues([':id' => 1, ':name' => 'user11'])->execute();
809
810
        $this->assertEquals(
811
            'user11',
812
            $query->where(['id' => 1])->scalar(),
813
            'Query reflects DB changes when caching is disabled'
814
        );
815
816
        /* Connection cache */
817
        $db->cache(function (ConnectionInterface $db) use ($query, $update) {
818
            $this->assertEquals(
819
                'user2',
820
                $query->where(['id' => 2])->scalar(),
821
                'Asserting initial value for user #2'
822
            );
823
824
            $update->bindValues([':id' => 2, ':name' => 'user22'])->execute();
825
826
            $this->assertEquals(
827
                'user2',
828
                $query->where(['id' => 2])->scalar(),
829
                'Query does NOT reflect DB changes when wrapped in connection caching'
830
            );
831
832
            $db->noCache(function () use ($query) {
833
                $this->assertEquals(
834
                    'user22',
835
                    $query->where(['id' => 2])->scalar(),
836
                    'Query reflects DB changes when wrapped in connection caching and noCache simultaneously'
837
                );
838
            });
839
840
            $this->assertEquals(
841
                'user2',
842
                $query->where(['id' => 2])->scalar(),
843
                'Cache does not get changes after getting newer data from DB in noCache block.'
844
            );
845
        }, 10);
846
847
        $this->queryCache->setEnable(false);
848
849
        $db->cache(function () use ($query, $update) {
850
            $this->assertEquals(
851
                'user22',
852
                $query->where(['id' => 2])->scalar(),
853
                'When cache is disabled for the whole connection, Query inside cache block does not get cached'
854
            );
855
856
            $update->bindValues([':id' => 2, ':name' => 'user2'])->execute();
857
858
            $this->assertEquals('user2', $query->where(['id' => 2])->scalar());
859
        }, 10);
860
861
        $this->queryCache->setEnable(true);
862
863
        $query->cache();
864
865
        $this->assertEquals('user11', $query->where(['id' => 1])->scalar());
866
867
        $update->bindValues([':id' => 1, ':name' => 'user1'])->execute();
868
869
        $this->assertEquals(
870
            'user11',
871
            $query->where(['id' => 1])->scalar(),
872
            'When both Connection and Query have cache enabled, we get cached value'
873
        );
874
        $this->assertEquals(
875
            'user1',
876
            $query->noCache()->where(['id' => 1])->scalar(),
877
            'When Query has disabled cache, we get actual data'
878
        );
879
880
        $db->cache(function () use ($query) {
881
            $this->assertEquals('user1', $query->noCache()->where(['id' => 1])->scalar());
882
            $this->assertEquals('user11', $query->cache()->where(['id' => 1])->scalar());
883
        }, 10);
884
    }
885
}
886