Passed
Push — master ( cac9d8...c999e9 )
by Wilmer
03:56
created

TestQueryTrait::testFilterRecursively()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 0
dl 0
loc 15
ccs 6
cts 6
cp 1
crap 1
rs 9.9666
c 0
b 0
f 0
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 1
    public function testSelect(): void
21
    {
22 1
        $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 1
        $query = new Query($db);
26
27 1
        $query->select('*');
28
29 1
        $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 1
        $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 1
        $this->assertNull($query->getSelectOption());
32
33 1
        $query = new Query($db);
34
35 1
        $query->select('id, name', 'something')->distinct(true);
36
37 1
        $this->assertEquals(['id' => 'id', 'name' => 'name'], $query->getSelect());
38 1
        $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 1
        $this->assertEquals('something', $query->getSelectOption());
40
41 1
        $query = new Query($db);
42
43 1
        $query->addSelect('email');
44
45 1
        $this->assertEquals(['email' => 'email'], $query->getSelect());
46
47 1
        $query = new Query($db);
48
49 1
        $query->select('id, name');
50 1
        $query->addSelect('email');
51
52 1
        $this->assertEquals(['id' => 'id', 'name' => 'name', 'email' => 'email'], $query->getSelect());
53
54 1
        $query = new Query($db);
55
56 1
        $query->select('name, lastname');
57 1
        $query->addSelect('name');
58
59 1
        $this->assertEquals(['name' => 'name', 'lastname' => 'lastname'], $query->getSelect());
60
61 1
        $query = new Query($db);
62
63 1
        $query->addSelect(['*', 'abc']);
64 1
        $query->addSelect(['*', 'bca']);
65
66 1
        $this->assertEquals(['*' => '*', 'abc' => 'abc', 'bca' => 'bca'], $query->getSelect());
67
68 1
        $query = new Query($db);
69
70 1
        $query->addSelect(['field1 as a', 'field 1 as b']);
71
72 1
        $this->assertEquals(['a' => 'field1', 'b' => 'field 1'], $query->getSelect());
73
74 1
        $query = new Query($db);
75
76 1
        $query->addSelect(['field1 a', 'field 1 b']);
77
78 1
        $this->assertEquals(['a' => 'field1', 'b' => 'field 1'], $query->getSelect());
79
80 1
        $query = new Query($db);
81
82 1
        $query->select(['name' => 'firstname', 'lastname']);
83 1
        $query->addSelect(['firstname', 'surname' => 'lastname']);
84 1
        $query->addSelect(['firstname', 'lastname']);
85
86 1
        $this->assertEquals(
87 1
            ['name' => 'firstname', 'lastname' => 'lastname', 'firstname' => 'firstname', 'surname' => 'lastname'],
88 1
            $query->getSelect()
89
        );
90
91 1
        $query = new Query($db);
92
93 1
        $query->select('name, name, name as X, name as X');
94
95 1
        $this->assertEquals(['name' => 'name', 'X' => 'name'], $query->getSelect());
96
97
        /**
98
         * {@see https://github.com/yiisoft/yii2/issues/15676}
99
         */
100 1
        $query = (new Query($db))->select('id');
101
102 1
        $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 1
        $query->select(['id', 'brand_id']);
105
106 1
        $this->assertSame(['id' => 'id', 'brand_id' => 'brand_id'], $query->getSelect());
107
108
        /**
109
         * {@see https://github.com/yiisoft/yii2/issues/15676}
110
         */
111 1
        $query = (new Query($db))
112 1
            ->select(['prefix' => 'LEFT(name, 7)', 'prefix_key' => 'LEFT(name, 7)']);
113
114 1
        $this->assertSame(['prefix' => 'LEFT(name, 7)', 'prefix_key' => 'LEFT(name, 7)'], $query->getSelect());
115
116 1
        $query->addSelect(['LEFT(name,7) as test']);
117
118 1
        $this->assertSame(
119 1
            ['prefix' => 'LEFT(name, 7)', 'prefix_key' => 'LEFT(name, 7)', 'test' => 'LEFT(name,7)'],
120 1
            $query->getSelect()
121
        );
122
123 1
        $query->addSelect(['LEFT(name,7) as test']);
124
125 1
        $this->assertSame(
126 1
            ['prefix' => 'LEFT(name, 7)', 'prefix_key' => 'LEFT(name, 7)', 'test' => 'LEFT(name,7)'],
127 1
            $query->getSelect()
128
        );
129
130 1
        $query->addSelect(['test' => 'LEFT(name,7)']);
131
132 1
        $this->assertSame(
133 1
            ['prefix' => 'LEFT(name, 7)', 'prefix_key' => 'LEFT(name, 7)', 'test' => 'LEFT(name,7)'],
134 1
            $query->getSelect()
135
        );
136
137
        /**
138
         * {@see https://github.com/yiisoft/yii2/issues/15731}
139
         */
140
        $selectedCols = [
141 1
            '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 1
        $query = (new Query($db))->select($selectedCols)->addParams([
147 1
            ':type_in'      => 'in',
148
            ':type_out'     => 'out',
149
            ':type_partner' => 'partner',
150
        ]);
151
152 1
        $this->assertSame($selectedCols, $query->getSelect());
153
154 1
        $query->select($selectedCols);
155
156 1
        $this->assertSame($selectedCols, $query->getSelect());
157
158
        /**
159
         * {@see https://github.com/yiisoft/yii2/issues/17384}
160
         */
161 1
        $query = new Query($db);
162
163 1
        $query->select('DISTINCT ON(tour_dates.date_from) tour_dates.date_from, tour_dates.id');
164
165 1
        $this->assertEquals(
166 1
            ['DISTINCT ON(tour_dates.date_from) tour_dates.date_from', 'tour_dates.id' => 'tour_dates.id'],
167 1
            $query->getSelect()
168
        );
169 1
    }
170
171 1
    public function testFrom(): void
172
    {
173 1
        $db = $this->getConnection();
174
175 1
        $query = new Query($db);
176
177 1
        $query->from('user');
178
179 1
        $this->assertEquals(['user'], $query->getFrom());
180 1
    }
181
182 1
    public function testFromTableIsArrayWithExpression(): void
183
    {
184 1
        $db = $this->getConnection();
185
186 1
        $query = new Query($db);
187
188 1
        $tables = new Expression('(SELECT id,name FROM user) u');
189
190 1
        $query->from($tables);
191
192 1
        $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 1
    }
194
195 10
    protected function createQuery(): Query
196
    {
197 10
        return new Query($this->getConnection());
198
    }
199
200 1
    public function testWhere(): void
201
    {
202 1
        $db = $this->getConnection();
203
204 1
        $query = new Query($db);
205
206 1
        $query->where('id = :id', [':id' => 1]);
207
208 1
        $this->assertEquals('id = :id', $query->getWhere());
209 1
        $this->assertEquals([':id' => 1], $query->getParams());
210
211 1
        $query->andWhere('name = :name', [':name' => 'something']);
212
213 1
        $this->assertEquals(['and', 'id = :id', 'name = :name'], $query->getWhere());
214 1
        $this->assertEquals([':id' => 1, ':name' => 'something'], $query->getParams());
215
216 1
        $query->orWhere('age = :age', [':age' => '30']);
217
218 1
        $this->assertEquals(['or', ['and', 'id = :id', 'name = :name'], 'age = :age'], $query->getWhere());
219 1
        $this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->getParams());
220 1
    }
221
222 1
    public function testFilterWhereWithHashFormat(): void
223
    {
224 1
        $db = $this->getConnection();
225
226 1
        $query = new Query($db);
227
228 1
        $query->filterWhere([
229 1
            'id'         => 0,
230
            'title'      => '   ',
231
            'author_ids' => [],
232
        ]);
233
234 1
        $this->assertEquals(['id' => 0], $query->getWhere());
235
236 1
        $query->andFilterWhere(['status' => null]);
237
238 1
        $this->assertEquals(['id' => 0], $query->getWhere());
239
240 1
        $query->orFilterWhere(['name' => '']);
241
242 1
        $this->assertEquals(['id' => 0], $query->getWhere());
243 1
    }
244
245 1
    public function testFilterWhereWithOperatorFormat(): void
246
    {
247 1
        $db = $this->getConnection();
248
249 1
        $query = new Query($db);
250
251 1
        $condition = ['like', 'name', 'Alex'];
252
253 1
        $query->filterWhere($condition);
254
255 1
        $this->assertEquals($condition, $query->getWhere());
256
257 1
        $query->andFilterWhere(['between', 'id', null, null]);
258
259 1
        $this->assertEquals($condition, $query->getWhere());
260
261 1
        $query->orFilterWhere(['not between', 'id', null, null]);
262
263 1
        $this->assertEquals($condition, $query->getWhere());
264
265 1
        $query->andFilterWhere(['in', 'id', []]);
266
267 1
        $this->assertEquals($condition, $query->getWhere());
268
269 1
        $query->andFilterWhere(['not in', 'id', []]);
270
271 1
        $this->assertEquals($condition, $query->getWhere());
272
273 1
        $query->andFilterWhere(['like', 'id', '']);
274
275 1
        $this->assertEquals($condition, $query->getWhere());
276
277 1
        $query->andFilterWhere(['or like', 'id', '']);
278
279 1
        $this->assertEquals($condition, $query->getWhere());
280
281 1
        $query->andFilterWhere(['not like', 'id', '   ']);
282
283 1
        $this->assertEquals($condition, $query->getWhere());
284
285 1
        $query->andFilterWhere(['or not like', 'id', null]);
286
287 1
        $this->assertEquals($condition, $query->getWhere());
288
289 1
        $query->andFilterWhere(['or', ['eq', 'id', null], ['eq', 'id', []]]);
290
291 1
        $this->assertEquals($condition, $query->getWhere());
292 1
    }
293
294 1
    public function testFilterHavingWithHashFormat(): void
295
    {
296 1
        $db = $this->getConnection();
297
298 1
        $query = new Query($db);
299
300 1
        $query->filterHaving([
301 1
            'id'         => 0,
302
            'title'      => '   ',
303
            'author_ids' => [],
304
        ]);
305
306 1
        $this->assertEquals(['id' => 0], $query->getHaving());
307
308 1
        $query->andFilterHaving(['status' => null]);
309
310 1
        $this->assertEquals(['id' => 0], $query->getHaving());
311
312 1
        $query->orFilterHaving(['name' => '']);
313
314 1
        $this->assertEquals(['id' => 0], $query->getHaving());
315 1
    }
316
317 1
    public function testFilterHavingWithOperatorFormat(): void
318
    {
319 1
        $db = $this->getConnection();
320
321 1
        $query = new Query($db);
322
323 1
        $condition = ['like', 'name', 'Alex'];
324
325 1
        $query->filterHaving($condition);
326
327 1
        $this->assertEquals($condition, $query->getHaving());
328
329 1
        $query->andFilterHaving(['between', 'id', null, null]);
330
331 1
        $this->assertEquals($condition, $query->getHaving());
332
333 1
        $query->orFilterHaving(['not between', 'id', null, null]);
334
335 1
        $this->assertEquals($condition, $query->getHaving());
336
337 1
        $query->andFilterHaving(['in', 'id', []]);
338
339 1
        $this->assertEquals($condition, $query->getHaving());
340
341 1
        $query->andFilterHaving(['not in', 'id', []]);
342
343 1
        $this->assertEquals($condition, $query->getHaving());
344
345 1
        $query->andFilterHaving(['like', 'id', '']);
346
347 1
        $this->assertEquals($condition, $query->getHaving());
348
349 1
        $query->andFilterHaving(['or like', 'id', '']);
350
351 1
        $this->assertEquals($condition, $query->getHaving());
352
353 1
        $query->andFilterHaving(['not like', 'id', '   ']);
354
355 1
        $this->assertEquals($condition, $query->getHaving());
356
357 1
        $query->andFilterHaving(['or not like', 'id', null]);
358
359 1
        $this->assertEquals($condition, $query->getHaving());
360
361 1
        $query->andFilterHaving(['or', ['eq', 'id', null], ['eq', 'id', []]]);
362
363 1
        $this->assertEquals($condition, $query->getHaving());
364 1
    }
365
366 1
    public function testFilterRecursively(): void
367
    {
368 1
        $db = $this->getConnection();
369
370 1
        $query = new Query($db);
371
372 1
        $query->filterWhere(
373 1
            ['and', ['like', 'name', ''],
374
            ['like', 'title', ''],
375
            ['id' => 1],
376
            ['not',
377
            ['like', 'name', '']]]
378
        );
379
380 1
        $this->assertEquals(['and', ['id' => 1]], $query->getWhere());
381 1
    }
382
383 1
    public function testGroup(): void
384
    {
385 1
        $db = $this->getConnection();
386
387 1
        $query = new Query($db);
388
389 1
        $query->groupBy('team');
390
391 1
        $this->assertEquals(['team'], $query->getGroupBy());
392
393 1
        $query->addGroupBy('company');
394
395 1
        $this->assertEquals(['team', 'company'], $query->getGroupBy());
396
397 1
        $query->addGroupBy('age');
398
399 1
        $this->assertEquals(['team', 'company', 'age'], $query->getGroupBy());
400 1
    }
401
402 1
    public function testHaving(): void
403
    {
404 1
        $db = $this->getConnection();
405
406 1
        $query = new Query($db);
407
408 1
        $query->having('id = :id', [':id' => 1]);
409
410 1
        $this->assertEquals('id = :id', $query->getHaving());
411 1
        $this->assertEquals([':id' => 1], $query->getParams());
412
413 1
        $query->andHaving('name = :name', [':name' => 'something']);
414 1
        $this->assertEquals(['and', 'id = :id', 'name = :name'], $query->getHaving());
415 1
        $this->assertEquals([':id' => 1, ':name' => 'something'], $query->getParams());
416
417 1
        $query->orHaving('age = :age', [':age' => '30']);
418 1
        $this->assertEquals(['or', ['and', 'id = :id', 'name = :name'], 'age = :age'], $query->getHaving());
419 1
        $this->assertEquals([':id' => 1, ':name' => 'something', ':age' => '30'], $query->getParams());
420 1
    }
421
422 1
    public function testOrder(): void
423
    {
424 1
        $db = $this->getConnection();
425
426 1
        $query = new Query($db);
427
428 1
        $query->orderBy('team');
429
430 1
        $this->assertEquals(['team' => SORT_ASC], $query->getOrderBy());
431
432 1
        $query->addOrderBy('company');
433
434 1
        $this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC], $query->getOrderBy());
435
436 1
        $query->addOrderBy('age');
437
438 1
        $this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC, 'age' => SORT_ASC], $query->getOrderBy());
439
440 1
        $query->addOrderBy(['age' => SORT_DESC]);
441
442 1
        $this->assertEquals(['team' => SORT_ASC, 'company' => SORT_ASC, 'age' => SORT_DESC], $query->getOrderBy());
443
444 1
        $query->addOrderBy('age ASC, company DESC');
445
446 1
        $this->assertEquals(['team' => SORT_ASC, 'company' => SORT_DESC, 'age' => SORT_ASC], $query->getOrderBy());
447
448 1
        $expression = new Expression('SUBSTR(name, 3, 4) DESC, x ASC');
449
450 1
        $query->orderBy($expression);
451
452 1
        $this->assertEquals([$expression], $query->getOrderBy());
453
454 1
        $expression = new Expression('SUBSTR(name, 3, 4) DESC, x ASC');
455
456 1
        $query->addOrderBy($expression);
457
458 1
        $this->assertEquals([$expression, $expression], $query->getOrderBy());
459 1
    }
460
461 1
    public function testLimitOffset(): void
462
    {
463 1
        $db = $this->getConnection();
464
465 1
        $query = new Query($db);
466
467 1
        $query->limit(10)->offset(5);
468
469 1
        $this->assertEquals(10, $query->getLimit());
470 1
        $this->assertEquals(5, $query->getOffset());
471 1
    }
472
473 1
    public function testLimitOffsetWithExpression(): void
474
    {
475 1
        $db = $this->getConnection();
476
477 1
        $query = (new Query($db))->from('customer')->select('id')->orderBy('id');
478
479
        $query
480 1
            ->limit(new Expression('1 + 1'))
481 1
            ->offset(new Expression('1 + 0'));
482
483 1
        $result = $query->column();
484
485 1
        $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 1
        if ($db->getDriverName() !== 'sqlsrv') {
487 1
            $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

487
            $this->/** @scrutinizer ignore-call */ 
488
                   assertContains(2, $result);
Loading history...
488 1
            $this->assertContains(3, $result);
489
        } else {
490
            $this->assertContains("2", $result);
491
            $this->assertContains("3", $result);
492
        }
493 1
        $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

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

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

641
        $this->/** @scrutinizer ignore-call */ 
642
               assertGreaterThan(0, (new Query($db))->from('customer')->count('*'));
Loading history...
642
643 1
        $rows = (new Query($db))->from('customer')->emulateExecution()->all();
644
645 1
        $this->assertSame([], $rows);
646
647 1
        $row = (new Query($db))->from('customer')->emulateExecution()->one();
648
649 1
        $this->assertFalse($row);
650
651 1
        $exists = (new Query($db))->from('customer')->emulateExecution()->exists($db);
652
653 1
        $this->assertFalse($exists);
654
655 1
        $count = (new Query($db))->from('customer')->emulateExecution()->count('*');
656
657 1
        $this->assertSame(0, $count);
658
659 1
        $sum = (new Query($db))->from('customer')->emulateExecution()->sum('id');
660
661 1
        $this->assertSame(0, $sum);
662
663 1
        $sum = (new Query($db))->from('customer')->emulateExecution()->average('id');
664
665 1
        $this->assertSame(0, $sum);
666
667 1
        $max = (new Query($db))->from('customer')->emulateExecution()->max('id');
668
669 1
        $this->assertNull($max);
670
671 1
        $min = (new Query($db))->from('customer')->emulateExecution()->min('id');
672
673 1
        $this->assertNull($min);
674
675 1
        $scalar = (new Query($db))->select(['id'])->from('customer')->emulateExecution()->scalar();
676
677 1
        $this->assertNull($scalar);
678
679 1
        $column = (new Query($db))->select(['id'])->from('customer')->emulateExecution()->column();
680
681 1
        $this->assertSame([], $column);
682 1
    }
683
684
    /**
685
     * @param Connection $db
686
     * @param string $tableName
687
     * @param string $columnName
688
     * @param array $condition
689
     * @param string $operator
690
     *
691
     * @throws Exception
692
     * @throws InvalidArgumentException
693
     * @throws InvalidConfigException
694
     * @throws NotSupportedException
695
     *
696
     * @return int
697
     */
698 1
    protected function countLikeQuery(
699
        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

699
        /** @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...
700
        string $tableName,
701
        string $columnName,
702
        array $condition,
703
        string $operator = 'or'
704
    ): int {
705 1
        $db = $this->getConnection();
706
707 1
        $whereCondition = [$operator];
708
709 1
        foreach ($condition as $value) {
710 1
            $whereCondition[] = ['like', $columnName, $value];
711
        }
712
713 1
        $result = (new Query($db))->from($tableName)->where($whereCondition)->count('*');
714
715 1
        if (is_numeric($result)) {
716 1
            $result = (int) $result;
717
        }
718
719 1
        return $result;
720
    }
721
722
    /**
723
     * {@see https://github.com/yiisoft/yii2/issues/13745}
724
     */
725 1
    public function testMultipleLikeConditions(): void
726
    {
727 1
        $db = $this->getConnection();
728
729 1
        $tableName = 'like_test';
730 1
        $columnName = 'col';
731
732 1
        if ($db->getSchema()->getTableSchema($tableName) !== null) {
733
            $db->createCommand()->dropTable($tableName)->execute();
734
        }
735
736 1
        $db->createCommand()->createTable($tableName, [
737 1
            $columnName => $db->getSchema()->createColumnSchemaBuilder(Schema::TYPE_STRING, 64),
738 1
        ])->execute();
739
740 1
        $db->createCommand()->batchInsert($tableName, ['col'], [
741 1
            ['test0'],
742
            ['test\1'],
743
            ['test\2'],
744
            ['foo%'],
745
            ['%bar'],
746
            ['%baz%'],
747 1
        ])->execute();
748
749
        /* Basic tests */
750 1
        $this->assertSame(1, $this->countLikeQuery($db, $tableName, $columnName, ['test0']));
751 1
        $this->assertSame(2, $this->countLikeQuery($db, $tableName, $columnName, ['test\\']));
752 1
        $this->assertSame(0, $this->countLikeQuery($db, $tableName, $columnName, ['test%']));
753 1
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, ['%']));
754
755
        /* Multiple condition tests */
756 1
        $this->assertSame(2, $this->countLikeQuery($db, $tableName, $columnName, [
757 1
            'test0',
758
            'test\1',
759
        ]));
760 1
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, [
761 1
            'test0',
762
            'test\1',
763
            'test\2',
764
        ]));
765 1
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, [
766 1
            'foo',
767
            '%ba',
768
        ]));
769 1
    }
770
771
    /**
772
     * {@see https://github.com/yiisoft/yii2/issues/15355}
773
     */
774 1
    public function testExpressionInFrom(): void
775
    {
776 1
        $db = $this->getConnection();
777
778 1
        $query = (new Query($db))
779 1
            ->from(new Expression('(SELECT id, name, email, address, status FROM customer) c'))
780 1
            ->where(['status' => 2]);
781
782 1
        $result = $query->one();
783
784 1
        $this->assertEquals('user3', $result['name']);
785 1
    }
786
787 1
    public function testQueryCache()
788
    {
789 1
        $db = $this->getConnection();
790
791 1
        $db->setEnableQueryCache(true);
792 1
        $db->setQueryCache($this->cache);
793
794 1
        $query = (new Query($db))
795 1
            ->select(['name'])
796 1
            ->from('customer');
797
798 1
        $update = $db->createCommand('UPDATE {{customer}} SET [[name]] = :name WHERE [[id]] = :id');
799
800 1
        $this->assertEquals('user1', $query->where(['id' => 1])->scalar(), 'Asserting initial value');
801
802
        /* No cache */
803 1
        $update->bindValues([':id' => 1, ':name' => 'user11'])->execute();
804
805 1
        $this->assertEquals(
806 1
            'user11',
807 1
            $query->where(['id' => 1])->scalar(),
808 1
            'Query reflects DB changes when caching is disabled'
809
        );
810
811
        /* Connection cache */
812 1
        $db->cache(function (Connection $db) use ($query, $update) {
813 1
            $this->assertEquals(
814 1
                'user2',
815 1
                $query->where(['id' => 2])->scalar(),
816 1
                'Asserting initial value for user #2'
817
            );
818
819 1
            $update->bindValues([':id' => 2, ':name' => 'user22'])->execute();
820
821 1
            $this->assertEquals(
822 1
                'user2',
823 1
                $query->where(['id' => 2])->scalar(),
824 1
                'Query does NOT reflect DB changes when wrapped in connection caching'
825
            );
826
827 1
            $db->noCache(function () use ($query) {
828 1
                $this->assertEquals(
829 1
                    'user22',
830 1
                    $query->where(['id' => 2])->scalar(),
831 1
                    'Query reflects DB changes when wrapped in connection caching and noCache simultaneously'
832
                );
833 1
            });
834
835 1
            $this->assertEquals(
836 1
                'user2',
837 1
                $query->where(['id' => 2])->scalar(),
838 1
                'Cache does not get changes after getting newer data from DB in noCache block.'
839
            );
840 1
        }, 10);
841
842 1
        $db->setEnableQueryCache(false);
843
844 1
        $db->cache(function () use ($query, $update) {
845 1
            $this->assertEquals(
846 1
                'user22',
847 1
                $query->where(['id' => 2])->scalar(),
848 1
                'When cache is disabled for the whole connection, Query inside cache block does not get cached'
849
            );
850
851 1
            $update->bindValues([':id' => 2, ':name' => 'user2'])->execute();
852
853 1
            $this->assertEquals('user2', $query->where(['id' => 2])->scalar());
854 1
        }, 10);
855
856 1
        $db->setEnableQueryCache(true);
857 1
        $query->cache();
858
859 1
        $this->assertEquals('user11', $query->where(['id' => 1])->scalar());
860
861 1
        $update->bindValues([':id' => 1, ':name' => 'user1'])->execute();
862
863 1
        $this->assertEquals(
864 1
            'user11',
865 1
            $query->where(['id' => 1])->scalar(),
866 1
            'When both Connection and Query have cache enabled, we get cached value'
867
        );
868 1
        $this->assertEquals(
869 1
            'user1',
870 1
            $query->noCache()->where(['id' => 1])->scalar(),
871 1
            'When Query has disabled cache, we get actual data'
872
        );
873
874 1
        $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...
875 1
            $this->assertEquals('user1', $query->noCache()->where(['id' => 1])->scalar());
876 1
            $this->assertEquals('user11', $query->cache()->where(['id' => 1])->scalar());
877 1
        }, 10);
878 1
    }
879
880
    /**
881
     * checks that all needed properties copied from source to new query
882
     */
883 1
    public function testQueryCreation(): void
884
    {
885 1
        $db = $this->getConnection();
886
887 1
        $where = 'id > :min_user_id';
888 1
        $limit = 50;
889 1
        $offset = 2;
890 1
        $orderBy = ['name' => SORT_ASC];
891 1
        $indexBy = 'id';
892 1
        $select = ['id' => 'id', 'name' => 'name', 'articles_count' => 'count(*)'];
893 1
        $selectOption = 'SQL_NO_CACHE';
894 1
        $from = 'recent_users';
895 1
        $groupBy = 'id';
896 1
        $having = ['>', 'articles_count', 0];
897 1
        $params = [':min_user_id' => 100];
898
899 1
        [$joinType, $joinTable, $joinOn] = $join = ['INNER', 'articles', 'articles.author_id=users.id'];
900
901 1
        $unionQuery = (new Query($db))
902 1
            ->select('id, name, 1000 as articles_count')
903 1
            ->from('admins');
904
905 1
        $withQuery = (new Query($db))
906 1
            ->select('id, name')
907 1
            ->from('users')
908 1
            ->where('DATE(registered_at) > "2020-01-01"');
909
910
        /** build target query */
911 1
        $sourceQuery = (new Query($db))
912 1
            ->where($where)
913 1
            ->limit($limit)
914 1
            ->offset($offset)
915 1
            ->orderBy($orderBy)
916 1
            ->indexBy($indexBy)
917 1
            ->select($select, $selectOption)
918 1
            ->distinct()
919 1
            ->from($from)
920 1
            ->groupBy($groupBy)
921 1
            ->having($having)
922 1
            ->addParams($params)
923 1
            ->join($joinType, $joinTable, $joinOn)
924 1
            ->union($unionQuery)
925 1
            ->withQuery($withQuery, $from);
926
927 1
        $newQuery = Query::create($db, $sourceQuery);
928
929 1
        $this->assertEquals($where, $newQuery->getWhere());
930 1
        $this->assertEquals($limit, $newQuery->getLimit());
931 1
        $this->assertEquals($offset, $newQuery->getOffset());
932 1
        $this->assertEquals($orderBy, $newQuery->getOrderBy());
933 1
        $this->assertEquals($indexBy, $newQuery->getIndexBy());
934 1
        $this->assertEquals($select, $newQuery->getSelect());
935 1
        $this->assertEquals($selectOption, $newQuery->getSelectOption());
936 1
        $this->assertTrue($newQuery->getDistinct());
937 1
        $this->assertEquals([$from], $newQuery->getFrom());
938 1
        $this->assertEquals([$groupBy], $newQuery->getGroupBy());
939 1
        $this->assertEquals($having, $newQuery->getHaving());
940 1
        $this->assertEquals($params, $newQuery->getParams());
941 1
        $this->assertEquals([$join], $newQuery->getJoin());
942 1
        $this->assertEquals([['query' => $unionQuery, 'all' => false]], $newQuery->getUnion());
943 1
        $this->assertEquals(
944 1
            [['query' => $withQuery, 'alias' => $from, 'recursive' => false]],
945 1
            $newQuery->getWithQueries()
946
        );
947 1
    }
948
}
949