Passed
Pull Request — master (#163)
by Wilmer
10:25
created

TestQueryTrait::testLimitOffset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 10
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\TestUtility;
6
7
use Yiisoft\Db\Connection\Connection;
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\Schema\Schema;
15
16
trait TestQueryTrait
17
{
18
    use GetTablesAliasTestTrait;
19
20
    public function testSelect(): void
21
    {
22
        $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

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

29
        $this->/** @scrutinizer ignore-call */ 
30
               assertEquals(['*' => '*'], $query->getSelect());
Loading history...
30
        $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

30
        $this->/** @scrutinizer ignore-call */ 
31
               assertNull($query->getDistinct());
Loading history...
31
        $this->assertNull($query->getSelectOption());
32
33
        $query = new Query($db);
34
35
        $query->select('id, name', 'something')->distinct(true);
36
37
        $this->assertEquals(['id' => 'id', 'name' => 'name'], $query->getSelect());
38
        $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

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

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

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

485
        $this->/** @scrutinizer ignore-call */ 
486
               assertCount(2, $result);
Loading history...
486
        $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

486
        $this->/** @scrutinizer ignore-call */ 
487
               assertContains("2", $result);
Loading history...
487
        $this->assertContains("3", $result);
488
        $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

488
        $this->/** @scrutinizer ignore-call */ 
489
               assertNotContains(1, $result);
Loading history...
489
    }
490
491
    public function testOne(): void
492
    {
493
        $db = $this->getConnection();
494
495
        $result = (new Query($db))->from('customer')->where(['status' => 2])->one();
496
497
        $this->assertEquals('user3', $result['name']);
498
499
        $result = (new Query($db))->from('customer')->where(['status' => 3])->one();
500
501
        $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

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

636
        $this->/** @scrutinizer ignore-call */ 
637
               assertGreaterThan(0, (new Query($db))->from('customer')->count('*'));
Loading history...
637
638
        $rows = (new Query($db))->from('customer')->emulateExecution()->all();
639
640
        $this->assertSame([], $rows);
641
642
        $row = (new Query($db))->from('customer')->emulateExecution()->one();
643
644
        $this->assertFalse($row);
645
646
        $exists = (new Query($db))->from('customer')->emulateExecution()->exists($db);
647
648
        $this->assertFalse($exists);
649
650
        $count = (new Query($db))->from('customer')->emulateExecution()->count('*');
651
652
        $this->assertSame(0, $count);
653
654
        $sum = (new Query($db))->from('customer')->emulateExecution()->sum('id');
655
656
        $this->assertSame(0, $sum);
657
658
        $sum = (new Query($db))->from('customer')->emulateExecution()->average('id');
659
660
        $this->assertSame(0, $sum);
661
662
        $max = (new Query($db))->from('customer')->emulateExecution()->max('id');
663
664
        $this->assertNull($max);
665
666
        $min = (new Query($db))->from('customer')->emulateExecution()->min('id');
667
668
        $this->assertNull($min);
669
670
        $scalar = (new Query($db))->select(['id'])->from('customer')->emulateExecution()->scalar();
671
672
        $this->assertNull($scalar);
673
674
        $column = (new Query($db))->select(['id'])->from('customer')->emulateExecution()->column();
675
676
        $this->assertSame([], $column);
677
    }
678
679
    /**
680
     * @param Connection $db
681
     * @param string $tableName
682
     * @param string $columnName
683
     * @param array $condition
684
     * @param string $operator
685
     *
686
     * @throws Exception
687
     * @throws InvalidArgumentException
688
     * @throws InvalidConfigException
689
     * @throws NotSupportedException
690
     *
691
     * @return int
692
     */
693
    protected function countLikeQuery(
694
        Connection $db,
0 ignored issues
show
Unused Code introduced by
The parameter $db is not used and could be removed. ( Ignorable by Annotation )

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

694
        /** @scrutinizer ignore-unused */ Connection $db,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
695
        string $tableName,
696
        string $columnName,
697
        array $condition,
698
        string $operator = 'or'
699
    ): int {
700
        $db = $this->getConnection();
701
702
        $whereCondition = [$operator];
703
704
        foreach ($condition as $value) {
705
            $whereCondition[] = ['like', $columnName, $value];
706
        }
707
708
        $result = (new Query($db))->from($tableName)->where($whereCondition)->count('*');
709
710
        if (is_numeric($result)) {
711
            $result = (int) $result;
712
        }
713
714
        return $result;
715
    }
716
717
    /**
718
     * {@see https://github.com/yiisoft/yii2/issues/13745}
719
     */
720
    public function testMultipleLikeConditions(): void
721
    {
722
        $db = $this->getConnection();
723
724
        $tableName = 'like_test';
725
        $columnName = 'col';
726
727
        if ($db->getSchema()->getTableSchema($tableName) !== null) {
728
            $db->createCommand()->dropTable($tableName)->execute();
729
        }
730
731
        $db->createCommand()->createTable($tableName, [
732
            $columnName => $db->getSchema()->createColumnSchemaBuilder(Schema::TYPE_STRING, 64),
733
        ])->execute();
734
735
        $db->createCommand()->batchInsert($tableName, ['col'], [
736
            ['test0'],
737
            ['test\1'],
738
            ['test\2'],
739
            ['foo%'],
740
            ['%bar'],
741
            ['%baz%'],
742
        ])->execute();
743
744
        /* Basic tests */
745
        $this->assertSame(1, $this->countLikeQuery($db, $tableName, $columnName, ['test0']));
746
        $this->assertSame(2, $this->countLikeQuery($db, $tableName, $columnName, ['test\\']));
747
        $this->assertSame(0, $this->countLikeQuery($db, $tableName, $columnName, ['test%']));
748
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, ['%']));
749
750
        /* Multiple condition tests */
751
        $this->assertSame(2, $this->countLikeQuery($db, $tableName, $columnName, [
752
            'test0',
753
            'test\1',
754
        ]));
755
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, [
756
            'test0',
757
            'test\1',
758
            'test\2',
759
        ]));
760
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, [
761
            'foo',
762
            '%ba',
763
        ]));
764
    }
765
766
    /**
767
     * {@see https://github.com/yiisoft/yii2/issues/15355}
768
     */
769
    public function testExpressionInFrom(): void
770
    {
771
        $db = $this->getConnection();
772
773
        $query = (new Query($db))
774
            ->from(new Expression('(SELECT id, name, email, address, status FROM customer) c'))
775
            ->where(['status' => 2]);
776
777
        $result = $query->one();
778
779
        $this->assertEquals('user3', $result['name']);
780
    }
781
782
    public function testQueryCache()
783
    {
784
        $db = $this->getConnection();
785
786
        $db->setEnableQueryCache(true);
787
        $db->setQueryCache($this->cache);
788
789
        $query = (new Query($db))
790
            ->select(['name'])
791
            ->from('customer');
792
793
        $update = $db->createCommand('UPDATE {{customer}} SET [[name]] = :name WHERE [[id]] = :id');
794
795
        $this->assertEquals('user1', $query->where(['id' => 1])->scalar(), 'Asserting initial value');
796
797
        /* No cache */
798
        $update->bindValues([':id' => 1, ':name' => 'user11'])->execute();
799
800
        $this->assertEquals(
801
            'user11',
802
            $query->where(['id' => 1])->scalar(),
803
            'Query reflects DB changes when caching is disabled'
804
        );
805
806
        /* Connection cache */
807
        $db->cache(function (Connection $db) use ($query, $update) {
808
            $this->assertEquals(
809
                'user2',
810
                $query->where(['id' => 2])->scalar(),
811
                'Asserting initial value for user #2'
812
            );
813
814
            $update->bindValues([':id' => 2, ':name' => 'user22'])->execute();
815
816
            $this->assertEquals(
817
                'user2',
818
                $query->where(['id' => 2])->scalar(),
819
                'Query does NOT reflect DB changes when wrapped in connection caching'
820
            );
821
822
            $db->noCache(function () use ($query) {
823
                $this->assertEquals(
824
                    'user22',
825
                    $query->where(['id' => 2])->scalar(),
826
                    'Query reflects DB changes when wrapped in connection caching and noCache simultaneously'
827
                );
828
            });
829
830
            $this->assertEquals(
831
                'user2',
832
                $query->where(['id' => 2])->scalar(),
833
                'Cache does not get changes after getting newer data from DB in noCache block.'
834
            );
835
        }, 10);
836
837
        $db->setEnableQueryCache(false);
838
839
        $db->cache(function () use ($query, $update) {
840
            $this->assertEquals(
841
                'user22',
842
                $query->where(['id' => 2])->scalar(),
843
                'When cache is disabled for the whole connection, Query inside cache block does not get cached'
844
            );
845
846
            $update->bindValues([':id' => 2, ':name' => 'user2'])->execute();
847
848
            $this->assertEquals('user2', $query->where(['id' => 2])->scalar());
849
        }, 10);
850
851
        $db->setEnableQueryCache(true);
852
        $query->cache();
853
854
        $this->assertEquals('user11', $query->where(['id' => 1])->scalar());
855
856
        $update->bindValues([':id' => 1, ':name' => 'user1'])->execute();
857
858
        $this->assertEquals(
859
            'user11',
860
            $query->where(['id' => 1])->scalar(),
861
            'When both Connection and Query have cache enabled, we get cached value'
862
        );
863
        $this->assertEquals(
864
            'user1',
865
            $query->noCache()->where(['id' => 1])->scalar(),
866
            'When Query has disabled cache, we get actual data'
867
        );
868
869
        $db->cache(function () use ($query, $update) {
0 ignored issues
show
Unused Code introduced by
The import $update is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
870
            $this->assertEquals('user1', $query->noCache()->where(['id' => 1])->scalar());
871
            $this->assertEquals('user11', $query->cache()->where(['id' => 1])->scalar());
872
        }, 10);
873
    }
874
}
875