Passed
Pull Request — master (#399)
by Def
02:38
created

TestSchemaTrait::tableCommentsDataProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\TestSupport;
6
7
use PDO;
8
use Yiisoft\Db\Constraint\CheckConstraint;
9
use Yiisoft\Db\Constraint\Constraint;
10
use Yiisoft\Db\Constraint\DefaultValueConstraint;
11
use Yiisoft\Db\Constraint\ForeignKeyConstraint;
12
use Yiisoft\Db\Constraint\IndexConstraint;
13
use Yiisoft\Db\Schema\ColumnSchema;
14
use Yiisoft\Db\Schema\Schema;
15
16
use Yiisoft\Db\Schema\TableSchemaInterface;
17
use function array_keys;
18
use function fclose;
19
use function fopen;
20
use function gettype;
21
use function is_array;
22
use function json_encode;
23
use function ksort;
24
use function print_r;
25
use function sort;
26
use function sprintf;
27
use function strtolower;
28
29
trait TestSchemaTrait
30
{
31
    public function testGetTableSchemasWithAttrCase(): void
32
    {
33
        $db = $this->getConnection(false);
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

33
        /** @scrutinizer ignore-call */ 
34
        $db = $this->getConnection(false);
Loading history...
34
35
        $db->getActivePDO()->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
36
37
        $this->assertCount(count($db->getSchema()->getTableNames()), $db->getSchema()->getTableSchemas());
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

37
        $this->/** @scrutinizer ignore-call */ 
38
               assertCount(count($db->getSchema()->getTableNames()), $db->getSchema()->getTableSchemas());
Loading history...
38
39
        $db->getActivePDO()->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);
40
41
        $this->assertCount(count($db->getSchema()->getTableNames()), $db->getSchema()->getTableSchemas());
42
    }
43
44
    public function testGetSchemaPrimaryKeys(): void
45
    {
46
        $db = $this->getConnection(false);
47
48
        $tablePks = $db->getSchema()->getSchemaPrimaryKeys();
49
50
        /** @psalm-suppress RedundantCondition */
51
        $this->assertIsArray($tablePks);
0 ignored issues
show
Bug introduced by
It seems like assertIsArray() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

51
        $this->/** @scrutinizer ignore-call */ 
52
               assertIsArray($tablePks);
Loading history...
52
        $this->assertContainsOnlyInstancesOf(Constraint::class, $tablePks);
0 ignored issues
show
Bug introduced by
It seems like assertContainsOnlyInstancesOf() 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

52
        $this->/** @scrutinizer ignore-call */ 
53
               assertContainsOnlyInstancesOf(Constraint::class, $tablePks);
Loading history...
53
    }
54
55
    public function testGetSchemaChecks(): void
56
    {
57
        $db = $this->getConnection(false);
58
59
        $tableChecks = $db->getSchema()->getSchemaChecks();
60
61
        /** @psalm-suppress RedundantCondition */
62
        $this->assertIsArray($tableChecks);
63
64
        foreach ($tableChecks as $checks) {
65
            $this->assertIsArray($checks);
66
            $this->assertContainsOnlyInstancesOf(CheckConstraint::class, $checks);
67
        }
68
    }
69
70
    public function testGetSchemaDefaultValues(): void
71
    {
72
        $db = $this->getConnection(false);
73
74
        $tableDefaultValues = $db->getSchema()->getSchemaDefaultValues();
75
76
        /** @psalm-suppress RedundantCondition */
77
        $this->assertIsArray($tableDefaultValues);
78
79
        foreach ($tableDefaultValues as $defaultValues) {
80
            $this->assertIsArray($defaultValues);
81
            $this->assertContainsOnlyInstancesOf(DefaultValueConstraint::class, $defaultValues);
82
        }
83
    }
84
85
    public function testGetSchemaForeignKeys(): void
86
    {
87
        $db = $this->getConnection(false);
88
89
        $tableForeignKeys = $db->getSchema()->getSchemaForeignKeys();
90
91
        /** @psalm-suppress RedundantCondition */
92
        $this->assertIsArray($tableForeignKeys);
93
94
        foreach ($tableForeignKeys as $foreignKeys) {
95
            $this->assertIsArray($foreignKeys);
96
            $this->assertContainsOnlyInstancesOf(ForeignKeyConstraint::class, $foreignKeys);
97
        }
98
    }
99
100
    public function testGetSchemaIndexes(): void
101
    {
102
        $db = $this->getConnection(false);
103
104
        $tableIndexes = $db->getSchema()->getSchemaIndexes();
105
106
        /** @psalm-suppress RedundantCondition */
107
        $this->assertIsArray($tableIndexes);
108
109
        foreach ($tableIndexes as $indexes) {
110
            $this->assertIsArray($indexes);
111
            $this->assertContainsOnlyInstancesOf(IndexConstraint::class, $indexes);
112
        }
113
    }
114
115
    public function testGetSchemaUniques(): void
116
    {
117
        $db = $this->getConnection(false);
118
119
        $tableUniques = $db->getSchema()->getSchemaUniques();
120
121
        /** @psalm-suppress RedundantCondition */
122
        $this->assertIsArray($tableUniques);
123
124
        foreach ($tableUniques as $uniques) {
125
            $this->assertIsArray($uniques);
126
            $this->assertContainsOnlyInstancesOf(Constraint::class, $uniques);
127
        }
128
    }
129
130
    public function testGetNonExistingTableSchema(): void
131
    {
132
        $this->assertNull($this->getConnection()->getSchema()->getTableSchema('nonexisting_table'));
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

132
        $this->/** @scrutinizer ignore-call */ 
133
               assertNull($this->getConnection()->getSchema()->getTableSchema('nonexisting_table'));
Loading history...
133
    }
134
135
    public function testSchemaCache(): void
136
    {
137
        $db = $this->getConnection();
138
139
        $schema = $db->getSchema();
140
141
        $this->assertNotNull($this->schemaCache);
0 ignored issues
show
Bug introduced by
It seems like assertNotNull() 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

141
        $this->/** @scrutinizer ignore-call */ 
142
               assertNotNull($this->schemaCache);
Loading history...
142
143
        $schema->schemaCacheEnable(true);
144
        $noCacheTable = $schema->getTableSchema('type', true);
145
        $cachedTable = $schema->getTableSchema('type', false);
146
147
        $this->assertEquals($noCacheTable, $cachedTable);
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

147
        $this->/** @scrutinizer ignore-call */ 
148
               assertEquals($noCacheTable, $cachedTable);
Loading history...
148
149
        $db->createCommand()->renameTable('type', 'type_test');
150
151
        $noCacheTable = $schema->getTableSchema('type', true);
152
153
        $this->assertNotSame($noCacheTable, $cachedTable);
0 ignored issues
show
Bug introduced by
It seems like assertNotSame() 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

153
        $this->/** @scrutinizer ignore-call */ 
154
               assertNotSame($noCacheTable, $cachedTable);
Loading history...
154
155
        $db->createCommand()->renameTable('type_test', 'type');
156
    }
157
158
    /**
159
     * @depends testSchemaCache
160
     */
161
    public function testRefreshTableSchema(): void
162
    {
163
        $schema = $this->getConnection()->getSchema();
164
165
        $this->assertNotNull($this->schemaCache);
166
167
        $schema->schemaCacheEnable(true);
168
        $noCacheTable = $schema->getTableSchema('type', true);
169
        $schema->refreshTableSchema('type');
170
        $refreshedTable = $schema->getTableSchema('type', false);
171
172
        $this->assertNotSame($noCacheTable, $refreshedTable);
173
    }
174
175
    public function testCompositeFk(): void
176
    {
177
        $schema = $this->getConnection()->getSchema();
178
179
        $table = $schema->getTableSchema('composite_fk');
180
181
        $this->assertNotNull($table);
182
183
        $fk = $table->getForeignKeys();
184
185
        $this->assertCount(1, $fk);
186
        $this->assertTrue(isset($fk['FK_composite_fk_order_item']));
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

186
        $this->/** @scrutinizer ignore-call */ 
187
               assertTrue(isset($fk['FK_composite_fk_order_item']));
Loading history...
187
        $this->assertEquals('order_item', $fk['FK_composite_fk_order_item'][0]);
188
        $this->assertEquals('order_id', $fk['FK_composite_fk_order_item']['order_id']);
189
        $this->assertEquals('item_id', $fk['FK_composite_fk_order_item']['item_id']);
190
    }
191
192
    public function testGetPDOType(): void
193
    {
194
        $values = [
195
            [null, PDO::PARAM_NULL],
196
            ['', PDO::PARAM_STR],
197
            ['hello', PDO::PARAM_STR],
198
            [0, PDO::PARAM_INT],
199
            [1, PDO::PARAM_INT],
200
            [1337, PDO::PARAM_INT],
201
            [true, PDO::PARAM_BOOL],
202
            [false, PDO::PARAM_BOOL],
203
            [$fp = fopen(__FILE__, 'rb'), PDO::PARAM_LOB],
204
        ];
205
206
        $schema = $this->getConnection()->getSchema();
207
208
        foreach ($values as $value) {
209
            $this->assertEquals($value[1], $schema->getPdoType($value[0]), 'type for value ' . print_r($value[0], true) . ' does not match.');
0 ignored issues
show
Bug introduced by
Are you sure print_r($value[0], true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

209
            $this->assertEquals($value[1], $schema->getPdoType($value[0]), 'type for value ' . /** @scrutinizer ignore-type */ print_r($value[0], true) . ' does not match.');
Loading history...
210
        }
211
212
        fclose($fp);
213
    }
214
215
    public function testColumnSchema(): void
216
    {
217
        $columns = $this->getExpectedColumns();
0 ignored issues
show
Bug introduced by
It seems like getExpectedColumns() 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

217
        /** @scrutinizer ignore-call */ 
218
        $columns = $this->getExpectedColumns();
Loading history...
218
219
        $table = $this->getConnection(false)->getSchema()->getTableSchema('type', true);
220
        $this->assertNotNull($table);
221
222
        $expectedColNames = array_keys($columns);
223
224
        sort($expectedColNames);
225
226
        $colNames = $table->getColumnNames();
227
228
        sort($colNames);
229
230
        $this->assertEquals($expectedColNames, $colNames);
231
232
        foreach ($table->getColumns() as $name => $column) {
233
            $expected = $columns[$name];
234
            $this->assertSame(
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

234
            $this->/** @scrutinizer ignore-call */ 
235
                   assertSame(
Loading history...
235
                $expected['dbType'],
236
                $column->getDbType(),
237
                "dbType of column $name does not match. type is {$column->getType()}, dbType is {$column->getDbType()}."
238
            );
239
            $this->assertSame(
240
                $expected['phpType'],
241
                $column->getPhpType(),
242
                "phpType of column $name does not match. type is {$column->getType()}, dbType is {$column->getDbType()}."
243
            );
244
            $this->assertSame($expected['type'], $column->getType(), "type of column $name does not match.");
245
            $this->assertSame(
246
                $expected['allowNull'],
247
                $column->isAllowNull(),
248
                "allowNull of column $name does not match."
249
            );
250
            $this->assertSame(
251
                $expected['autoIncrement'],
252
                $column->isAutoIncrement(),
253
                "autoIncrement of column $name does not match."
254
            );
255
            $this->assertSame(
256
                $expected['enumValues'],
257
                $column->getEnumValues(),
258
                "enumValues of column $name does not match."
259
            );
260
            $this->assertSame($expected['size'], $column->getSize(), "size of column $name does not match.");
261
            $this->assertSame(
262
                $expected['precision'],
263
                $column->getPrecision(),
264
                "precision of column $name does not match."
265
            );
266
            $this->assertSame($expected['scale'], $column->getScale(), "scale of column $name does not match.");
267
            if (\is_object($expected['defaultValue'])) {
268
                $this->assertIsObject(
0 ignored issues
show
Bug introduced by
It seems like assertIsObject() 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

268
                $this->/** @scrutinizer ignore-call */ 
269
                       assertIsObject(
Loading history...
269
                    $column->getDefaultValue(),
270
                    "defaultValue of column $name is expected to be an object but it is not."
271
                );
272
                $this->assertEquals(
273
                    (string) $expected['defaultValue'],
274
                    (string) $column->getDefaultValue(),
275
                    "defaultValue of column $name does not match."
276
                );
277
            } else {
278
                $this->assertEquals(
279
                    $expected['defaultValue'],
280
                    $column->getDefaultValue(),
281
                    "defaultValue of column $name does not match."
282
                );
283
            }
284
            /* Pgsql only */
285
            if (isset($expected['dimension'])) {
286
                /** @psalm-suppress UndefinedMethod */
287
                $this->assertSame(
288
                    $expected['dimension'],
289
                    $column->getDimension(),
290
                    "dimension of column $name does not match"
291
                );
292
            }
293
        }
294
    }
295
296
    public function testColumnSchemaDbTypecastWithEmptyCharType(): void
297
    {
298
        $columnSchema = new ColumnSchema();
299
300
        $columnSchema->setType(Schema::TYPE_CHAR);
301
302
        $this->assertSame('', $columnSchema->dbTypecast(''));
303
    }
304
305
    public function testNegativeDefaultValues(): void
306
    {
307
        $schema = $this->getConnection()->getSchema();
308
309
        $table = $schema->getTableSchema('negative_default_values');
310
311
        $this->assertNotNull($table);
312
        $this->assertEquals(-123, $table->getColumn('tinyint_col')?->getDefaultValue());
313
        $this->assertEquals(-123, $table->getColumn('smallint_col')?->getDefaultValue());
314
        $this->assertEquals(-123, $table->getColumn('int_col')?->getDefaultValue());
315
        $this->assertEquals(-123, $table->getColumn('bigint_col')?->getDefaultValue());
316
        $this->assertEquals(-12345.6789, $table->getColumn('float_col')?->getDefaultValue());
317
        $this->assertEquals(-33.22, $table->getColumn('numeric_col')?->getDefaultValue());
318
    }
319
320
    public function testContraintTablesExistance(): void
321
    {
322
        $tableNames = [
323
            'T_constraints_1',
324
            'T_constraints_2',
325
            'T_constraints_3',
326
            'T_constraints_4',
327
        ];
328
329
        $schema = $this->getConnection()->getSchema();
330
331
        foreach ($tableNames as $tableName) {
332
            $tableSchema = $schema->getTableSchema($tableName);
333
            $this->assertInstanceOf(TableSchemaInterface::class, $tableSchema, $tableName);
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

333
            $this->/** @scrutinizer ignore-call */ 
334
                   assertInstanceOf(TableSchemaInterface::class, $tableSchema, $tableName);
Loading history...
334
        }
335
    }
336
337
    public function testGetColumnNoExist(): void
338
    {
339
        $schema = $this->getConnection()->getSchema();
340
        $table = $schema->getTableSchema('negative_default_values');
341
342
        $this->assertNotNull($table);
343
        $this->assertNull($table->getColumn('no_exist'));
344
    }
345
346
    public function testQuoterEscapingValue()
347
    {
348
        $db = $this->getConnection(true);
349
        $quoter = $db->getQuoter();
350
351
        $db->createCommand('delete from {{quoter}}')->execute();
352
        $data = $this->generateQuoterEscapingValues();
353
354
        foreach ($data as $index => $value) {
355
            $quotedName = $quoter->quoteValue('testValue_' . $index);
356
            $quoteValue = $quoter->quoteValue($value);
357
358
            $db->createCommand('insert into {{quoter}}([[name]], [[description]]) values(' . $quotedName . ', ' . $quoteValue . ')')->execute();
359
            $result = $db->createCommand('select * from {{quoter}} where [[name]]=' . $quotedName)->queryOne();
360
            $this->assertEquals($value, $result['description']);
361
        }
362
    }
363
364
    public function generateQuoterEscapingValues()
365
    {
366
        $result = [];
367
        $stringLength = 16;
368
        for ($i = 32; $i < 128 - $stringLength; $i += $stringLength) {
369
            $str = '';
370
            for ($symbol = $i; $symbol < $i + $stringLength; $symbol++) {
371
                $str .= mb_chr($symbol, 'UTF-8');
372
            }
373
            $result[] = $str;
374
375
            $str = '';
376
            for ($symbol = $i; $symbol < $i + $stringLength; $symbol++) {
377
                $str .= mb_chr($symbol, 'UTF-8') . mb_chr($symbol, 'UTF-8');
378
            }
379
            $result[] = $str;
380
        }
381
382
        return $result;
383
    }
384
385
    public function testQuoterEscapingValueFull()
386
    {
387
        $this->markTestSkipped('Very long test - only for check quoteValue');
0 ignored issues
show
Bug introduced by
It seems like markTestSkipped() 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

387
        $this->/** @scrutinizer ignore-call */ 
388
               markTestSkipped('Very long test - only for check quoteValue');
Loading history...
388
        $template = 'aaaaa{1}aaa{1}aaaabbbbb{2}bbbb{2}bbbb';
389
390
        $db = $this->getConnection(true);
391
        $quoter = $db->getQuoter();
392
393
        $db->createCommand('delete from {{quoter}}')->execute();
394
395
        for ($symbol1 = 1; $symbol1 <= 127; $symbol1++) {
396
            for ($symbol2 = 1; $symbol2 <= 127; $symbol2++) {
397
                $quotedName = $quoter->quoteValue('test_' . $symbol1 . '_' . $symbol2);
398
                $testString = str_replace(['{1}', '{2}',], [chr($symbol1), chr($symbol2)], $template);
399
400
                $quoteValue = $quoter->quoteValue($testString);
401
402
                $db->createCommand('insert into {{quoter}}([[name]], [[description]]) values(' . $quotedName . ', ' . $quoteValue . ')')->execute();
403
                $result = $db->createCommand('select * from {{quoter}} where [[name]]=' . $quotedName)->queryOne();
404
                $this->assertEquals($testString, $result['description']);
405
            }
406
        }
407
    }
408
409
    private function assertMetadataEquals($expected, $actual): void
410
    {
411
        switch (strtolower(gettype($expected))) {
412
            case 'object':
413
                $this->assertIsObject($actual);
414
                break;
415
            case 'array':
416
                $this->assertIsArray($actual);
417
                break;
418
            case 'null':
419
                $this->assertNull($actual);
420
                break;
421
        }
422
423
        if (is_array($expected)) {
424
            $this->normalizeArrayKeys($expected, false);
425
            /** @psalm-suppress PossiblyInvalidArgument */
426
            $this->normalizeArrayKeys($actual, false);
427
        }
428
429
        $this->normalizeConstraints($expected, $actual);
430
431
        if (is_array($expected)) {
432
            $this->normalizeArrayKeys($expected, true);
433
            $this->normalizeArrayKeys($actual, true);
434
        }
435
436
        $this->assertEquals($expected, $actual);
437
    }
438
439
    private function normalizeArrayKeys(array &$array, bool $caseSensitive): void
440
    {
441
        $newArray = [];
442
443
        foreach ($array as $value) {
444
            if ($value instanceof Constraint) {
445
                $key = (array) $value;
446
                unset(
447
                    $key["\000Yiisoft\Db\Constraint\Constraint\000name"],
448
                    $key["\u0000Yiisoft\\Db\\Constraint\\ForeignKeyConstraint\u0000foreignSchemaName"]
449
                );
450
451
                foreach ($key as $keyName => $keyValue) {
452
                    if ($keyValue instanceof AnyCaseValue) {
453
                        $key[$keyName] = $keyValue->value;
454
                    } elseif ($keyValue instanceof AnyValue) {
455
                        $key[$keyName] = '[AnyValue]';
456
                    }
457
                }
458
459
                ksort($key, SORT_STRING);
460
461
                $newArray[$caseSensitive
462
                    ? json_encode($key, JSON_THROW_ON_ERROR)
463
                    : strtolower(json_encode($key, JSON_THROW_ON_ERROR))] = $value;
464
            } else {
465
                $newArray[] = $value;
466
            }
467
        }
468
469
        ksort($newArray, SORT_STRING);
470
471
        $array = $newArray;
472
    }
473
474
    private function normalizeConstraints(&$expected, &$actual): void
475
    {
476
        if (is_array($expected)) {
477
            foreach ($expected as $key => $value) {
478
                if (!$value instanceof Constraint || !isset($actual[$key]) || !$actual[$key] instanceof Constraint) {
479
                    continue;
480
                }
481
482
                $this->normalizeConstraintPair($value, $actual[$key]);
483
            }
484
        } elseif ($expected instanceof Constraint && $actual instanceof Constraint) {
485
            $this->normalizeConstraintPair($expected, $actual);
486
        }
487
    }
488
489
    private function normalizeConstraintPair(Constraint $expectedConstraint, Constraint $actualConstraint): void
490
    {
491
        if ($expectedConstraint::class !== $actualConstraint::class) {
492
            return;
493
        }
494
495
        foreach (array_keys((array) $expectedConstraint) as $name) {
496
            if ($expectedConstraint->getName() instanceof AnyValue) {
497
                $actualConstraint->name($expectedConstraint->getName());
498
            } elseif ($expectedConstraint->getName() instanceof AnyCaseValue) {
499
                $actualConstraintName = $actualConstraint->getName();
500
                $this->assertIsString($actualConstraintName);
0 ignored issues
show
Bug introduced by
It seems like assertIsString() 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

500
                $this->/** @scrutinizer ignore-call */ 
501
                       assertIsString($actualConstraintName);
Loading history...
501
                $actualConstraint->name(new AnyCaseValue($actualConstraintName));
0 ignored issues
show
Bug introduced by
It seems like $actualConstraintName can also be of type null and object; however, parameter $value of Yiisoft\Db\TestSupport\AnyCaseValue::__construct() does only seem to accept array|string, maybe add an additional type check? ( Ignorable by Annotation )

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

501
                $actualConstraint->name(new AnyCaseValue(/** @scrutinizer ignore-type */ $actualConstraintName));
Loading history...
502
            }
503
        }
504
    }
505
506
    public function constraintsProviderTrait(): array
507
    {
508
        return [
509
            '1: primary key' => [
510
                'T_constraints_1',
511
                Schema::PRIMARY_KEY,
512
                (new Constraint())
513
                    ->name(AnyValue::getInstance())
514
                    ->columnNames(['C_id']),
515
            ],
516
            '1: check' => [
517
                'T_constraints_1',
518
                Schema::CHECKS,
519
                [
520
                    (new CheckConstraint())
521
                        ->name(AnyValue::getInstance())
522
                        ->columnNames(['C_check'])
523
                        ->expression("C_check <> ''"),
524
                ],
525
            ],
526
            '1: unique' => [
527
                'T_constraints_1',
528
                Schema::UNIQUES,
529
                [
530
                    (new Constraint())
531
                        ->name('CN_unique')
532
                        ->columnNames(['C_unique']),
533
                ],
534
            ],
535
            '1: index' => [
536
                'T_constraints_1',
537
                Schema::INDEXES,
538
                [
539
                    (new IndexConstraint())
540
                        ->name(AnyValue::getInstance())
541
                        ->columnNames(['C_id'])
542
                        ->unique(true)
543
                        ->primary(true),
544
                    (new IndexConstraint())
545
                        ->name('CN_unique')
546
                        ->columnNames(['C_unique'])
547
                        ->primary(false)
548
                        ->unique(true),
549
                ],
550
            ],
551
            '1: default' => ['T_constraints_1', Schema::DEFAULT_VALUES, false],
552
553
            '2: primary key' => [
554
                'T_constraints_2',
555
                Schema::PRIMARY_KEY,
556
                (new Constraint())
557
                    ->name('CN_pk')
558
                    ->columnNames(['C_id_1', 'C_id_2']),
559
            ],
560
            '2: unique' => [
561
                'T_constraints_2',
562
                Schema::UNIQUES,
563
                [
564
                    (new Constraint())
565
                        ->name('CN_constraints_2_multi')
566
                        ->columnNames(['C_index_2_1', 'C_index_2_2']),
567
                ],
568
            ],
569
            '2: index' => [
570
                'T_constraints_2',
571
                Schema::INDEXES,
572
                [
573
                    (new IndexConstraint())
574
                        ->name(AnyValue::getInstance())
575
                        ->columnNames(['C_id_1', 'C_id_2'])
576
                        ->unique(true)
577
                        ->primary(true),
578
                    (new IndexConstraint())
579
                        ->name('CN_constraints_2_single')
580
                        ->columnNames(['C_index_1'])
581
                        ->primary(false)
582
                        ->unique(false),
583
                    (new IndexConstraint())
584
                        ->name('CN_constraints_2_multi')
585
                        ->columnNames(['C_index_2_1', 'C_index_2_2'])
586
                        ->primary(false)
587
                        ->unique(true),
588
                ],
589
            ],
590
            '2: check' => ['T_constraints_2', Schema::CHECKS, []],
591
            '2: default' => ['T_constraints_2', Schema::DEFAULT_VALUES, false],
592
593
            '3: primary key' => ['T_constraints_3', Schema::PRIMARY_KEY, null],
594
            '3: foreign key' => [
595
                'T_constraints_3',
596
                Schema::FOREIGN_KEYS,
597
                [
598
                    (new ForeignKeyConstraint())
599
                        ->name('CN_constraints_3')
600
                        ->columnNames(['C_fk_id_1', 'C_fk_id_2'])
601
                        ->foreignTableName('T_constraints_2')
602
                        ->foreignColumnNames(['C_id_1', 'C_id_2'])
603
                        ->onDelete('CASCADE')
604
                        ->onUpdate('CASCADE'),
605
                ],
606
            ],
607
            '3: unique' => ['T_constraints_3', Schema::UNIQUES, []],
608
            '3: index' => [
609
                'T_constraints_3',
610
                Schema::INDEXES,
611
                [
612
                    (new IndexConstraint())
613
                        ->name('CN_constraints_3')
614
                        ->columnNames(['C_fk_id_1', 'C_fk_id_2'])
615
                        ->unique(false)
616
                        ->primary(false),
617
                ],
618
            ],
619
            '3: check' => ['T_constraints_3', Schema::CHECKS, []],
620
            '3: default' => ['T_constraints_3', Schema::DEFAULT_VALUES, false],
621
622
            '4: primary key' => [
623
                'T_constraints_4',
624
                Schema::PRIMARY_KEY,
625
                (new Constraint())
626
                    ->name(AnyValue::getInstance())
627
                    ->columnNames(['C_id']),
628
            ],
629
            '4: unique' => [
630
                'T_constraints_4',
631
                Schema::UNIQUES,
632
                [
633
                    (new Constraint())
634
                        ->name('CN_constraints_4')
635
                        ->columnNames(['C_col_1', 'C_col_2']),
636
                ],
637
            ],
638
            '4: check' => ['T_constraints_4', Schema::CHECKS, []],
639
            '4: default' => ['T_constraints_4', Schema::DEFAULT_VALUES, false],
640
        ];
641
    }
642
643
    public function pdoAttributesProviderTrait(): array
644
    {
645
        return [
646
            [[PDO::ATTR_EMULATE_PREPARES => true]],
647
            [[PDO::ATTR_EMULATE_PREPARES => false]],
648
        ];
649
    }
650
651
    public function tableSchemaCachePrefixesProviderTrait(): array
652
    {
653
        $configs = [
654
            [
655
                'prefix' => '',
656
                'name' => 'type',
657
            ],
658
            [
659
                'prefix' => '',
660
                'name' => '{{%type}}',
661
            ],
662
            [
663
                'prefix' => 'ty',
664
                'name' => '{{%pe}}',
665
            ],
666
        ];
667
668
        $data = [];
669
        foreach ($configs as $config) {
670
            foreach ($configs as $testConfig) {
671
                if ($config === $testConfig) {
672
                    continue;
673
                }
674
675
                $description = sprintf(
676
                    "%s (with '%s' prefix) against %s (with '%s' prefix)",
677
                    $config['name'],
678
                    $config['prefix'],
679
                    $testConfig['name'],
680
                    $testConfig['prefix']
681
                );
682
                $data[$description] = [
683
                    $config['prefix'],
684
                    $config['name'],
685
                    $testConfig['prefix'],
686
                    $testConfig['name'],
687
                ];
688
            }
689
        }
690
691
        return $data;
692
    }
693
694
    public function lowercaseConstraintsProviderTrait(): array
695
    {
696
        return $this->constraintsProvider();
0 ignored issues
show
Bug introduced by
The method constraintsProvider() does not exist on Yiisoft\Db\TestSupport\TestSchemaTrait. Did you maybe mean constraintsProviderTrait()? ( Ignorable by Annotation )

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

696
        return $this->/** @scrutinizer ignore-call */ constraintsProvider();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
697
    }
698
699
    public function uppercaseConstraintsProviderTrait(): array
700
    {
701
        return $this->constraintsProvider();
702
    }
703
704
    /**
705
     * @dataProvider columnCommentsDataProvider
706
     */
707
    public function testColumnComment(string $columnName, string $columnComment): void
708
    {
709
        $tableName = 'testCommentTable';
710
711
        $db = $this->getConnection();
712
713
        if ($db->getSchema()->getTableSchema($tableName) !== null) {
714
            $db->createCommand()->dropTable($tableName)->execute();
715
        }
716
717
        $db->createCommand()->createTable($tableName, [$columnName => Schema::TYPE_INTEGER,])->execute();
718
        $db->createCommand()->addCommentOnColumn($tableName, $columnName, $columnComment)->execute();
719
720
        $this->assertEquals($columnComment, $db->getSchema()->getTableSchema($tableName)->getColumn($columnName)->getComment());
721
    }
722
723
    public function columnCommentsDataProvider(): array
724
    {
725
        return [
726
            ['bar', 'test comment for column'],
727
            ['bar', ''],
728
        ];
729
    }
730
731
    /**
732
     * @dataProvider tableCommentsDataProvider
733
     */
734
    public function testTableComment(string $tableName, string $tableComment): void
735
    {
736
        $db = $this->getConnection();
737
738
        if ($db->getSchema()->getTableSchema($tableName) !== null) {
739
            $db->createCommand()->dropTable($tableName)->execute();
740
        }
741
742
        $db->createCommand()->createTable($tableName, ['bar' => Schema::TYPE_INTEGER,])->execute();
743
        $db->createCommand()->addCommentOnTable($tableName, $tableComment)->execute();
744
745
        $db->getSchema()->refreshTableSchema($tableName);
746
747
        $tableSchema = $db->getSchema()->getTableSchema($tableName);
748
        $this->assertEquals($tableComment, $tableSchema?->getComment());
749
    }
750
751
    public function tableCommentsDataProvider(): array
752
    {
753
        return [
754
            ['testCommentTable', 'test comment for table'],
755
            ['testCommentTable', ''],
756
        ];
757
    }
758
}
759