Passed
Pull Request — master (#380)
by Wilmer
10:58 queued 08:13
created

CommonQueryTest   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 216
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 111
dl 0
loc 216
rs 10
c 1
b 0
f 0
wmc 13

8 Methods

Rating   Name   Duplication   Size   Complexity  
A testCount() 0 28 1
A testLimitOffsetWithExpression() 0 21 3
A testMultipleLikeConditions() 0 39 2
A countLikeQuery() 0 20 3
A testExpressionInFrom() 0 15 1
A testOne() 0 11 1
A testExists() 0 11 1
A testColumn() 0 49 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Tests\Common;
6
7
use Yiisoft\Db\Driver\PDO\ConnectionPDOInterface;
8
use Yiisoft\Db\Expression\Expression;
9
use Yiisoft\Db\Query\Query;
10
use Yiisoft\Db\Schema\Schema;
11
use Yiisoft\Db\Tests\AbstractQueryTest;
12
13
/**
14
 * @group mssql
15
 * @group mysql
16
 * @group pgsql
17
 * @group oracle
18
 * @group sqlite
19
 */
20
abstract class CommonQueryTest extends AbstractQueryTest
21
{
22
    public function testColumn(): void
23
    {
24
        $db = $this->getConnectionWithData();
25
26
        $result = (new Query($db))->select('name')->from('customer')->orderBy(['id' => SORT_DESC])->column();
27
28
        $this->assertSame(['user3', 'user2', 'user1'], $result);
29
30
        /**
31
         * {@see https://github.com/yiisoft/yii2/issues/7515}
32
         */
33
        $result = (new Query($db))
34
            ->from('customer')
35
            ->select('name')
36
            ->orderBy(['id' => SORT_DESC])
37
            ->indexBy('id')
38
            ->column();
39
40
        $this->assertSame([3 => 'user3', 2 => 'user2', 1 => 'user1'], $result);
41
42
        /**
43
         * {@see https://github.com/yiisoft/yii2/issues/12649}
44
         */
45
        $result = (new Query($db))
46
            ->from('customer')
47
            ->select(['name', 'id'])
48
            ->orderBy(['id' => SORT_DESC])
49
            ->indexBy(fn ($row) => $row['id'] * 2)
50
            ->column();
51
52
        $this->assertSame([6 => 'user3', 4 => 'user2', 2 => 'user1'], $result);
53
54
        $result = (new Query($db))
55
            ->from('customer')
56
            ->select(['name'])
57
            ->indexBy('name')
58
            ->orderBy(['id' => SORT_DESC])
59
            ->column();
60
61
        $this->assertSame(['user3' => 'user3', 'user2' => 'user2', 'user1' => 'user1'], $result);
62
63
        $result = (new Query($db))
64
            ->from('customer')
65
            ->select(['name'])
66
            ->where(['id' => 10])
67
            ->orderBy(['id' => SORT_DESC])
68
            ->column();
69
70
        $this->assertSame([], $result);
71
    }
72
73
    public function testCount(): void
74
    {
75
        $db = $this->getConnectionWithData();
76
77
        $count = (new Query($db))->from('customer')->count('*');
78
79
        $this->assertSame(3, $count);
80
81
        $count = (new Query($db))->from('customer')->where(['status' => 2])->count('*');
82
83
        $this->assertSame(1, $count);
84
85
        $count = (new Query($db))
86
            ->select('[[status]], COUNT([[id]]) cnt')
87
            ->from('customer')
88
            ->groupBy('status')
89
            ->count('*');
90
91
        $this->assertSame(2, $count);
92
93
        /* testing that orderBy() should be ignored here as it does not affect the count anyway. */
94
        $count = (new Query($db))->from('customer')->orderBy('status')->count('*');
95
96
        $this->assertSame(3, $count);
97
98
        $count = (new Query($db))->from('customer')->orderBy('id')->limit(1)->count('*');
99
100
        $this->assertSame(3, $count);
101
    }
102
103
    public function testExists(): void
104
    {
105
        $db = $this->getConnectionWithData();
106
107
        $result = (new Query($db))->from('customer')->where(['status' => 2])->exists();
108
109
        $this->assertTrue($result);
110
111
        $result = (new Query($db))->from('customer')->where(['status' => 3])->exists();
112
113
        $this->assertFalse($result);
114
    }
115
116
    /**
117
     * {@see https://github.com/yiisoft/yii2/issues/15355}
118
     */
119
    public function testExpressionInFrom(): void
120
    {
121
        $db = $this->getConnectionWithData();
122
123
        $query = (new Query($db))
124
            ->from(
125
                new Expression(
126
                    '(SELECT [[id]], [[name]], [[email]], [[address]], [[status]] FROM {{customer}}) c'
127
                )
128
            )
129
            ->where(['status' => 2]);
130
131
        $result = $query->one();
132
133
        $this->assertSame('user3', $result['name']);
134
    }
135
136
    /**
137
     * {@see https://github.com/yiisoft/yii2/issues/13745}
138
     */
139
    public function testMultipleLikeConditions(): void
140
    {
141
        $db = $this->getConnection();
142
143
        $tableName = 'like_test';
144
        $columnName = 'col';
145
146
        if ($db->getSchema()->getTableSchema($tableName) !== null) {
147
            $db->createCommand()->dropTable($tableName)->execute();
148
        }
149
150
        $db->createCommand()->createTable(
151
            $tableName,
152
            [$columnName => $db->getSchema()->createColumnSchemaBuilder(Schema::TYPE_STRING, 64)],
153
        )->execute();
154
155
        $db->createCommand()->batchInsert(
156
            $tableName,
157
            ['col'],
158
            [
159
                ['test0'],
160
                ['test\1'],
161
                ['test\2'],
162
                ['foo%'],
163
                ['%bar'],
164
                ['%baz%'],
165
            ],
166
        )->execute();
167
168
        /* Basic tests */
169
        $this->assertSame(1, $this->countLikeQuery($db, $tableName, $columnName, ['test0']));
170
        $this->assertSame(2, $this->countLikeQuery($db, $tableName, $columnName, ['test\\']));
171
        $this->assertSame(0, $this->countLikeQuery($db, $tableName, $columnName, ['test%']));
172
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, ['%']));
173
174
        /* Multiple condition tests */
175
        $this->assertSame(2, $this->countLikeQuery($db, $tableName, $columnName, ['test0', 'test\1']));
176
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, ['test0', 'test\1', 'test\2']));
177
        $this->assertSame(3, $this->countLikeQuery($db, $tableName, $columnName, ['foo', '%ba']));
178
    }
179
180
    public function testLimitOffsetWithExpression(): void
181
    {
182
        $db = $this->getConnectionWithData();
183
184
        $query = (new Query($db))->from('customer')->select('id')->orderBy('id');
185
        $query->limit(new Expression('1 + 1'))->offset(new Expression('1 + 0'));
186
        $result = $query->column();
187
188
        $this->assertCount(2, $result);
189
190
        $driverName = $db->getName();
191
192
        if ($driverName !== 'sqlsrv' && $driverName !== 'oci') {
193
            $this->assertContains(2, $result);
194
            $this->assertContains(3, $result);
195
        } else {
196
            $this->assertContains('2', $result);
197
            $this->assertContains('3', $result);
198
        }
199
200
        $this->assertNotContains(1, $result);
201
    }
202
203
    public function testOne(): void
204
    {
205
        $db = $this->getConnectionWithData();
206
207
        $result = (new Query($db))->from('customer')->where(['status' => 2])->one();
208
209
        $this->assertEquals('user3', $result['name']);
210
211
        $result = (new Query($db))->from('customer')->where(['status' => 3])->one();
212
213
        $this->assertNull($result);
214
    }
215
216
    private function countLikeQuery(
217
        ConnectionPDOInterface $db,
218
        string $tableName,
219
        string $columnName,
220
        array $condition,
221
        string $operator = 'or'
222
    ): int {
223
        $whereCondition = [$operator];
224
225
        foreach ($condition as $value) {
226
            $whereCondition[] = ['like', $columnName, $value];
227
        }
228
229
        $result = (new Query($db))->from($tableName)->where($whereCondition)->count('*');
230
231
        if (is_numeric($result)) {
232
            return (int) $result;
233
        }
234
235
        return 0;
236
    }
237
}
238