Passed
Branch add-rector-actions (5668b1)
by Wilmer
03:26
created

ActiveRecordTest::testBooleanValues2()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 37
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 31
nc 1
nop 0
dl 0
loc 37
rs 9.424
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\ActiveRecord\Tests\Pgsql;
6
7
use ArrayAccess;
8
use Traversable;
9
use Yiisoft\ActiveRecord\ActiveQuery;
10
use Yiisoft\ActiveRecord\Tests\ActiveRecordTest as AbstractActiveRecordTest;
11
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\ArrayAndJsonTypes;
12
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Beta;
13
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\BoolAR;
14
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\Customer;
15
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\DefaultPk;
16
use Yiisoft\ActiveRecord\Tests\Stubs\ActiveRecord\UserAR;
17
use Yiisoft\Db\Connection\ConnectionInterface;
18
use Yiisoft\Db\Expression\ArrayExpression;
19
use Yiisoft\Db\Expression\Expression;
20
use Yiisoft\Db\Expression\JsonExpression;
21
use Yiisoft\Db\Pgsql\Schema as SchemaPgsql;
22
23
/**
24
 * @group pgsql
25
 */
26
final class ActiveRecordTest extends AbstractActiveRecordTest
27
{
28
    protected string $driverName = 'pgsql';
29
    protected ConnectionInterface $db;
30
31
    public function setUp(): void
32
    {
33
        parent::setUp();
34
35
        $this->db = $this->pgsqlConnection;
36
    }
37
38
    protected function tearDown(): void
39
    {
40
        parent::tearDown();
41
        $this->pgsqlConnection->close();
42
        unset($this->pgsqlConnection);
43
    }
44
45
    public function testExplicitPkOnAutoIncrement(): void
46
    {
47
        $this->checkFixture($this->db, 'customer');
48
49
        $customer = new Customer($this->db);
50
        $customer->id = 1337;
51
        $customer->email = '[email protected]';
52
        $customer->name = 'user1337';
53
        $customer->address = 'address1337';
54
        $this->assertTrue($customer->isNewRecord);
55
56
        $customer->save();
57
        $this->assertEquals(1337, $customer->id);
58
        $this->assertFalse($customer->isNewRecord);
59
    }
60
61
    /**
62
     * {@see https://github.com/yiisoft/yii2/issues/15482}
63
     */
64
    public function testEagerLoadingUsingStringIdentifiers(): void
65
    {
66
        $this->checkFixture($this->db, 'beta');
67
68
        $betaQuery = new ActiveQuery(Beta::class, $this->db);
69
        $betas = $betaQuery->with('alpha')->all();
70
        $this->assertNotEmpty($betas);
71
72
        $alphaIdentifiers = [];
73
74
        /** @var Beta[] $betas */
75
        foreach ($betas as $beta) {
76
            $this->assertNotNull($beta->alpha);
0 ignored issues
show
Bug introduced by
Accessing alpha on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
77
            $this->assertEquals($beta->alpha_string_identifier, $beta->alpha->string_identifier);
0 ignored issues
show
Bug introduced by
Accessing alpha_string_identifier on the interface Yiisoft\ActiveRecord\ActiveRecordInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
78
            $alphaIdentifiers[] = $beta->alpha->string_identifier;
79
        }
80
81
        $this->assertEquals(['1', '01', '001', '001', '2', '2b', '2b', '02'], $alphaIdentifiers);
82
    }
83
84
    public function testBooleanAttribute(): void
85
    {
86
        $this->checkFixture($this->db, 'customer', true);
87
88
        $customer = new Customer($this->db);
89
        $customer->name = 'boolean customer';
90
        $customer->email = '[email protected]';
91
        $customer->bool_status = false;
0 ignored issues
show
Bug Best Practice introduced by
The property bool_status does not exist on Yiisoft\ActiveRecord\Tes...s\ActiveRecord\Customer. Since you implemented __set, consider adding a @property annotation.
Loading history...
92
        $customer->save();
93
94
        $customer->refresh();
95
        $this->assertFalse($customer->bool_status);
0 ignored issues
show
Bug Best Practice introduced by
The property bool_status does not exist on Yiisoft\ActiveRecord\Tes...s\ActiveRecord\Customer. Since you implemented __get, consider adding a @property annotation.
Loading history...
96
97
        $customer->bool_status = true;
98
99
        $customer->save();
100
        $customer->refresh();
101
        $this->assertTrue($customer->bool_status);
102
103
        $customerQuery = new ActiveQuery(Customer::class, $this->db);
104
        $customers = $customerQuery->where(['bool_status' => true])->all();
105
        $this->assertCount(3, $customers);
106
107
        $customers = $customerQuery->where(['bool_status' => false])->all();
108
        $this->assertCount(1, $customers);
109
    }
110
111
    public function testBooleanValues(): void
112
    {
113
        $this->checkFixture($this->db, 'bool_values');
114
115
        $command = $this->db->createCommand();
116
        $command->batchInsert('bool_values', ['bool_col'], [[true], [false]])->execute();
117
        $boolARQuery = new ActiveQuery(BoolAR::class, $this->db);
118
119
        $this->assertTrue($boolARQuery->where(['bool_col' => true])->one()->bool_col);
120
        $this->assertFalse($boolARQuery->where(['bool_col' => false])->one()->bool_col);
121
122
        $this->assertEquals(1, $boolARQuery->where('bool_col = TRUE')->count('*'));
123
        $this->assertEquals(1, $boolARQuery->where('bool_col = FALSE')->count('*'));
124
        $this->assertEquals(2, $boolARQuery->where('bool_col IN (TRUE, FALSE)')->count('*'));
125
126
        $this->assertEquals(1, $boolARQuery->where(['bool_col' => true])->count('*'));
127
        $this->assertEquals(1, $boolARQuery->where(['bool_col' => false])->count('*'));
128
        $this->assertEquals(2, $boolARQuery->where(['bool_col' => [true, false]])->count('*'));
129
130
        $this->assertEquals(1, $boolARQuery->where('bool_col = :bool_col', ['bool_col' => true])->count('*'));
131
        $this->assertEquals(1, $boolARQuery->where('bool_col = :bool_col', ['bool_col' => false])->count('*'));
132
    }
133
134
    /**
135
     * {@see https://github.com/yiisoft/yii2/issues/4672}
136
     */
137
    public function testBooleanValues2(): void
138
    {
139
        $this->checkFixture($this->db, 'bool_user');
140
141
        //$this->db->setCharset('utf8');
142
        $this->db->createCommand('DROP TABLE IF EXISTS bool_user;')->execute();
143
        $this->db->createCommand()->createTable('bool_user', [
144
            'id' => SchemaPgsql::TYPE_PK,
145
            'username' => SchemaPgsql::TYPE_STRING . ' NOT NULL',
146
            'auth_key' => SchemaPgsql::TYPE_STRING . '(32) NOT NULL',
147
            'password_hash' => SchemaPgsql::TYPE_STRING . ' NOT NULL',
148
            'password_reset_token' => SchemaPgsql::TYPE_STRING,
149
            'email' => SchemaPgsql::TYPE_STRING . ' NOT NULL',
150
            'role' => SchemaPgsql::TYPE_SMALLINT . ' NOT NULL DEFAULT 10',
151
            'status' => SchemaPgsql::TYPE_SMALLINT . ' NOT NULL DEFAULT 10',
152
            'created_at' => SchemaPgsql::TYPE_INTEGER . ' NOT NULL',
153
            'updated_at' => SchemaPgsql::TYPE_INTEGER . ' NOT NULL',
154
        ])->execute();
155
        $this->db->createCommand()->addColumn(
156
            'bool_user',
157
            'is_deleted',
158
            SchemaPgsql::TYPE_BOOLEAN . ' NOT NULL DEFAULT FALSE'
159
        )->execute();
160
161
        $user = new UserAR($this->db);
162
        $user->username = 'test';
0 ignored issues
show
Bug Best Practice introduced by
The property username does not exist on Yiisoft\ActiveRecord\Tes...ubs\ActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
163
        $user->auth_key = 'test';
0 ignored issues
show
Bug Best Practice introduced by
The property auth_key does not exist on Yiisoft\ActiveRecord\Tes...ubs\ActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
164
        $user->password_hash = 'test';
0 ignored issues
show
Bug Best Practice introduced by
The property password_hash does not exist on Yiisoft\ActiveRecord\Tes...ubs\ActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
165
        $user->email = '[email protected]';
0 ignored issues
show
Bug Best Practice introduced by
The property email does not exist on Yiisoft\ActiveRecord\Tes...ubs\ActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
166
        $user->created_at = time();
0 ignored issues
show
Bug Best Practice introduced by
The property created_at does not exist on Yiisoft\ActiveRecord\Tes...ubs\ActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
167
        $user->updated_at = time();
0 ignored issues
show
Bug Best Practice introduced by
The property updated_at does not exist on Yiisoft\ActiveRecord\Tes...ubs\ActiveRecord\UserAR. Since you implemented __set, consider adding a @property annotation.
Loading history...
168
        $user->save();
169
170
        $userQuery = new ActiveQuery(UserAR::class, $this->db);
171
        $this->assertCount(1, $userQuery->where(['is_deleted' => false])->all());
172
        $this->assertCount(0, $userQuery->where(['is_deleted' => true])->all());
173
        $this->assertCount(1, $userQuery->where(['is_deleted' => [true, false]])->all());
174
    }
175
176
    public function testBooleanDefaultValues(): void
177
    {
178
        $this->checkFixture($this->db, 'bool_values');
179
180
        $arClass = new BoolAR($this->db);
181
182
        $this->assertNull($arClass->bool_col);
0 ignored issues
show
Bug Best Practice introduced by
The property bool_col does not exist on Yiisoft\ActiveRecord\Tes...ubs\ActiveRecord\BoolAR. Since you implemented __get, consider adding a @property annotation.
Loading history...
183
        $this->assertNull($arClass->default_true);
0 ignored issues
show
Bug Best Practice introduced by
The property default_true does not exist on Yiisoft\ActiveRecord\Tes...ubs\ActiveRecord\BoolAR. Since you implemented __get, consider adding a @property annotation.
Loading history...
184
        $this->assertNull($arClass->default_false);
0 ignored issues
show
Bug Best Practice introduced by
The property default_false does not exist on Yiisoft\ActiveRecord\Tes...ubs\ActiveRecord\BoolAR. Since you implemented __get, consider adding a @property annotation.
Loading history...
185
186
        $arClass->loadDefaultValues();
187
188
        $this->assertNull($arClass->bool_col);
189
        $this->assertTrue($arClass->default_true);
190
        $this->assertFalse($arClass->default_false);
191
        $this->assertTrue($arClass->save());
192
    }
193
194
    public function testPrimaryKeyAfterSave(): void
195
    {
196
        $this->checkFixture($this->db, 'default_pk');
197
198
        $record = new DefaultPk($this->db);
199
200
        $record->type = 'type';
0 ignored issues
show
Bug Best Practice introduced by
The property type does not exist on Yiisoft\ActiveRecord\Tes...\ActiveRecord\DefaultPk. Since you implemented __set, consider adding a @property annotation.
Loading history...
201
202
        $record->save();
203
204
        $this->assertEquals(5, $record->primaryKey);
205
    }
206
207
    public function arrayValuesProvider(): array
208
    {
209
        return [
210
            'simple arrays values' => [[
211
                'intarray_col' => [
212
                    new ArrayExpression([1,-2,null,'42'], 'int4', 1),
213
                    new ArrayExpression([1,-2,null,42], 'int4', 1),
214
                ],
215
                'textarray2_col' => [
216
                    new ArrayExpression([['text'], [null], [1]], 'text', 2),
217
                    new ArrayExpression([['text'], [null], ['1']], 'text', 2),
218
                ],
219
                'json_col' => [['a' => 1, 'b' => null, 'c' => [1,3,5]]],
220
                'jsonb_col' => [[null, 'a', 'b', '\"', '{"af"}']],
221
                'jsonarray_col' => [new ArrayExpression([[',', 'null', true, 'false', 'f']], 'json')],
222
            ]],
223
            'null arrays values' => [[
224
                'intarray_col' => [
225
                    null,
226
                ],
227
                'textarray2_col' => [
228
                    [null, null],
229
                    new ArrayExpression([null, null], 'text', 2),
230
                ],
231
                'json_col' => [
232
                    null,
233
                ],
234
                'jsonarray_col' => [
235
                    null,
236
                ],
237
            ]],
238
            'empty arrays values' => [[
239
                'textarray2_col' => [
240
                    [[], []],
241
                    new ArrayExpression([], 'text', 2),
242
                ],
243
            ]],
244
            'nested objects' => [[
245
                'intarray_col' => [
246
                    new ArrayExpression(new ArrayExpression([1,2,3]), 'int', 1),
247
                    new ArrayExpression([1,2,3], 'int4', 1),
248
                ],
249
                'textarray2_col' => [
250
                    new ArrayExpression([new ArrayExpression(['text']), [null], [1]], 'text', 2),
251
                    new ArrayExpression([['text'], [null], ['1']], 'text', 2),
252
                ],
253
                'json_col' => [
254
                    new JsonExpression(new JsonExpression(new JsonExpression(['a' => 1, 'b' => null, 'c' => new JsonExpression([1,3,5])]))),
255
                    ['a' => 1, 'b' => null, 'c' => [1,3,5]],
256
                ],
257
                'jsonb_col' => [
258
                    new JsonExpression(new ArrayExpression([1,2,3])),
259
                    [1,2,3],
260
                ],
261
                'jsonarray_col' => [
262
                    new ArrayExpression([new JsonExpression(['1', 2]), [3,4,5]], 'json'),
263
                    new ArrayExpression([['1', 2], [3,4,5]], 'json'),
264
                ],
265
            ]],
266
            'arrays packed in classes' => [[
267
                'intarray_col' => [
268
                    new ArrayExpression([1,-2,null,'42'], 'int', 1),
269
                    new ArrayExpression([1,-2,null,42], 'int4', 1),
270
                ],
271
                'textarray2_col' => [
272
                    new ArrayExpression([['text'], [null], [1]], 'text', 2),
273
                    new ArrayExpression([['text'], [null], ['1']], 'text', 2),
274
                ],
275
                'json_col' => [
276
                    new JsonExpression(['a' => 1, 'b' => null, 'c' => [1,3,5]]),
277
                    ['a' => 1, 'b' => null, 'c' => [1,3,5]],
278
                ],
279
                'jsonb_col' => [
280
                    new JsonExpression([null, 'a', 'b', '\"', '{"af"}']),
281
                    [null, 'a', 'b', '\"', '{"af"}'],
282
                ],
283
                'jsonarray_col' => [
284
                    new Expression("array['[\",\",\"null\",true,\"false\",\"f\"]'::json]::json[]"),
285
                    new ArrayExpression([[',', 'null', true, 'false', 'f']], 'json'),
286
                ],
287
            ]],
288
            'scalars' => [[
289
                'json_col' => [
290
                    '5.8',
291
                ],
292
                'jsonb_col' => [
293
                    M_PI,
294
                ],
295
            ]],
296
        ];
297
    }
298
299
    /**
300
     * @dataProvider arrayValuesProvider $attributes
301
     */
302
    public function testArrayValues($attributes): void
303
    {
304
        $this->checkFixture($this->db, 'array_and_json_types', true);
305
306
        $type = new ArrayAndJsonTypes($this->db);
307
308
        foreach ($attributes as $attribute => $expected) {
309
            $type->$attribute = $expected[0];
310
        }
311
312
        $type->save();
313
314
        $typeQuery = new ActiveQuery($type::class, $this->db);
315
316
        $type = $typeQuery->one();
317
318
        foreach ($attributes as $attribute => $expected) {
319
            $expected = $expected[1] ?? $expected[0];
320
            $value = $type->$attribute;
321
322
            if ($expected instanceof ArrayExpression) {
323
                $expected = $expected->getValue();
324
            }
325
326
            $this->assertEquals($expected, $value, 'In column ' . $attribute);
327
328
            if ($value instanceof ArrayExpression) {
329
                $this->assertInstanceOf(ArrayAccess::class, $value);
330
                $this->assertInstanceOf(Traversable::class, $value);
331
                /** testing arrayaccess */
332
                foreach ($type->$attribute as $key => $v) {
333
                    $this->assertSame($expected[$key], $value[$key]);
334
                }
335
            }
336
        }
337
338
        /** Testing update */
339
        foreach ($attributes as $attribute => $expected) {
340
            $type->markAttributeDirty($attribute);
341
        }
342
343
        $this->assertSame(1, $type->update(), 'The record got updated');
344
    }
345
}
346