Failed Conditions
Pull Request — master (#2825)
by Sébastien
62:38
created

testExistingTableWithQuotedDefaultsDoesNotTriggerChange()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 23
rs 9.0856
cc 1
eloc 13
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Tests\DBAL\Functional\Schema;
4
5
use Doctrine\DBAL\Platforms\MariaDb102Platform;
6
use Doctrine\DBAL\Platforms\MySqlPlatform;
7
use Doctrine\DBAL\Schema\Comparator;
8
use Doctrine\DBAL\Schema\Schema;
9
use Doctrine\DBAL\Schema\Table;
10
use Doctrine\DBAL\Types\Type;
11
use Doctrine\Tests\Types\MySqlPointType;
12
13
class MySqlSchemaManagerTest extends SchemaManagerFunctionalTestCase
14
{
15
16
    protected function setUp()
17
    {
18
        parent::setUp();
19
20
        if (!Type::hasType('point')) {
21
            Type::addType('point', MySqlPointType::class);
22
        }
23
    }
24
25
    public function testSwitchPrimaryKeyColumns()
26
    {
27
        $tableOld = new Table("switch_primary_key_columns");
28
        $tableOld->addColumn('foo_id', 'integer');
29
        $tableOld->addColumn('bar_id', 'integer');
30
31
        $this->_sm->createTable($tableOld);
32
        $tableFetched = $this->_sm->listTableDetails("switch_primary_key_columns");
33
        $tableNew = clone $tableFetched;
34
        $tableNew->setPrimaryKey(array('bar_id', 'foo_id'));
35
36
        $comparator = new Comparator;
37
        $this->_sm->alterTable($comparator->diffTable($tableFetched, $tableNew));
0 ignored issues
show
Security Bug introduced by
It seems like $comparator->diffTable($tableFetched, $tableNew) targeting Doctrine\DBAL\Schema\Comparator::diffTable() can also be of type false; however, Doctrine\DBAL\Schema\Abs...maManager::alterTable() does only seem to accept object<Doctrine\DBAL\Schema\TableDiff>, did you maybe forget to handle an error condition?
Loading history...
38
39
        $table      = $this->_sm->listTableDetails('switch_primary_key_columns');
40
        $primaryKey = $table->getPrimaryKeyColumns();
41
42
        self::assertCount(2, $primaryKey);
43
        self::assertContains('bar_id', $primaryKey);
44
        self::assertContains('foo_id', $primaryKey);
45
    }
46
47
    public function testDiffTableBug()
48
    {
49
        $schema = new Schema();
50
        $table = $schema->createTable('diffbug_routing_translations');
51
        $table->addColumn('id', 'integer');
52
        $table->addColumn('route', 'string');
53
        $table->addColumn('locale', 'string');
54
        $table->addColumn('attribute', 'string');
55
        $table->addColumn('localized_value', 'string');
56
        $table->addColumn('original_value', 'string');
57
        $table->setPrimaryKey(array('id'));
58
        $table->addUniqueIndex(array('route', 'locale', 'attribute'));
59
        $table->addIndex(array('localized_value')); // this is much more selective than the unique index
60
61
        $this->_sm->createTable($table);
62
        $tableFetched = $this->_sm->listTableDetails("diffbug_routing_translations");
63
64
        $comparator = new Comparator;
65
        $diff = $comparator->diffTable($tableFetched, $table);
66
67
        self::assertFalse($diff, "no changes expected.");
0 ignored issues
show
Bug introduced by
It seems like $diff defined by $comparator->diffTable($tableFetched, $table) on line 65 can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
68
    }
69
70 View Code Duplication
    public function testFulltextIndex()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
71
    {
72
        $table = new Table('fulltext_index');
73
        $table->addColumn('text', 'text');
74
        $table->addIndex(array('text'), 'f_index');
75
        $table->addOption('engine', 'MyISAM');
76
77
        $index = $table->getIndex('f_index');
78
        $index->addFlag('fulltext');
79
80
        $this->_sm->dropAndCreateTable($table);
81
82
        $indexes = $this->_sm->listTableIndexes('fulltext_index');
83
        self::assertArrayHasKey('f_index', $indexes);
84
        self::assertTrue($indexes['f_index']->hasFlag('fulltext'));
85
    }
86
87 View Code Duplication
    public function testSpatialIndex()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
88
    {
89
        $table = new Table('spatial_index');
90
        $table->addColumn('point', 'point');
91
        $table->addIndex(array('point'), 's_index');
92
        $table->addOption('engine', 'MyISAM');
93
94
        $index = $table->getIndex('s_index');
95
        $index->addFlag('spatial');
96
97
        $this->_sm->dropAndCreateTable($table);
98
99
        $indexes = $this->_sm->listTableIndexes('spatial_index');
100
        self::assertArrayHasKey('s_index', $indexes);
101
        self::assertTrue($indexes['s_index']->hasFlag('spatial'));
102
    }
103
104
    /**
105
     * @group DBAL-400
106
     */
107
    public function testAlterTableAddPrimaryKey()
108
    {
109
        $table = new Table('alter_table_add_pk');
110
        $table->addColumn('id', 'integer');
111
        $table->addColumn('foo', 'integer');
112
        $table->addIndex(array('id'), 'idx_id');
113
114
        $this->_sm->createTable($table);
115
116
        $comparator = new Comparator();
117
        $diffTable  = clone $table;
118
119
        $diffTable->dropIndex('idx_id');
120
        $diffTable->setPrimaryKey(array('id'));
121
122
        $this->_sm->alterTable($comparator->diffTable($table, $diffTable));
0 ignored issues
show
Security Bug introduced by
It seems like $comparator->diffTable($table, $diffTable) targeting Doctrine\DBAL\Schema\Comparator::diffTable() can also be of type false; however, Doctrine\DBAL\Schema\Abs...maManager::alterTable() does only seem to accept object<Doctrine\DBAL\Schema\TableDiff>, did you maybe forget to handle an error condition?
Loading history...
123
124
        $table = $this->_sm->listTableDetails("alter_table_add_pk");
125
126
        self::assertFalse($table->hasIndex('idx_id'));
127
        self::assertTrue($table->hasPrimaryKey());
128
    }
129
130
    /**
131
     * @group DBAL-464
132
     */
133
    public function testDropPrimaryKeyWithAutoincrementColumn()
134
    {
135
        $table = new Table("drop_primary_key");
136
        $table->addColumn('id', 'integer', array('primary' => true, 'autoincrement' => true));
137
        $table->addColumn('foo', 'integer', array('primary' => true));
138
        $table->setPrimaryKey(array('id', 'foo'));
139
140
        $this->_sm->dropAndCreateTable($table);
141
142
        $diffTable = clone $table;
143
144
        $diffTable->dropPrimaryKey();
145
146
        $comparator = new Comparator();
147
148
        $this->_sm->alterTable($comparator->diffTable($table, $diffTable));
0 ignored issues
show
Security Bug introduced by
It seems like $comparator->diffTable($table, $diffTable) targeting Doctrine\DBAL\Schema\Comparator::diffTable() can also be of type false; however, Doctrine\DBAL\Schema\Abs...maManager::alterTable() does only seem to accept object<Doctrine\DBAL\Schema\TableDiff>, did you maybe forget to handle an error condition?
Loading history...
149
150
        $table = $this->_sm->listTableDetails("drop_primary_key");
151
152
        self::assertFalse($table->hasPrimaryKey());
153
        self::assertFalse($table->getColumn('id')->getAutoincrement());
154
    }
155
156
    /**
157
     * @group DBAL-789
158
     */
159
    public function testDoesNotPropagateDefaultValuesForUnsupportedColumnTypes()
160
    {
161
        if ($this->_sm->getDatabasePlatform() instanceof MariaDb102Platform) {
162
            $this->markTestSkipped('MariaDb102Platform supports default values for BLOB and TEXT columns and will propagate values');
163
        }
164
165
        $table = new Table("text_blob_default_value");
166
        $table->addColumn('def_text', 'text', ['default' => 'def']);
167
        $table->addColumn('def_text_null', 'text', ['notnull' => false, 'default' => 'def']);
168
        $table->addColumn('def_blob', 'blob', ['default' => 'def']);
169
        $table->addColumn('def_blob_null', 'blob', ['notnull' => false, 'default' => 'def']);
170
171
        $this->_sm->dropAndCreateTable($table);
172
173
        $onlineTable = $this->_sm->listTableDetails("text_blob_default_value");
174
175
        self::assertNull($onlineTable->getColumn('def_text')->getDefault());
176
        self::assertNull($onlineTable->getColumn('def_text_null')->getDefault());
177
        self::assertFalse($onlineTable->getColumn('def_text_null')->getNotnull());
178
        self::assertNull($onlineTable->getColumn('def_blob')->getDefault());
179
        self::assertNull($onlineTable->getColumn('def_blob_null')->getDefault());
180
        self::assertFalse($onlineTable->getColumn('def_blob_null')->getNotnull());
181
182
        $comparator = new Comparator();
183
184
        $this->_sm->alterTable($comparator->diffTable($table, $onlineTable));
0 ignored issues
show
Security Bug introduced by
It seems like $comparator->diffTable($table, $onlineTable) targeting Doctrine\DBAL\Schema\Comparator::diffTable() can also be of type false; however, Doctrine\DBAL\Schema\Abs...maManager::alterTable() does only seem to accept object<Doctrine\DBAL\Schema\TableDiff>, did you maybe forget to handle an error condition?
Loading history...
185
186
        $onlineTable = $this->_sm->listTableDetails("text_blob_default_value");
187
188
        self::assertNull($onlineTable->getColumn('def_text')->getDefault());
189
        self::assertNull($onlineTable->getColumn('def_text_null')->getDefault());
190
        self::assertFalse($onlineTable->getColumn('def_text_null')->getNotnull());
191
        self::assertNull($onlineTable->getColumn('def_blob')->getDefault());
192
        self::assertNull($onlineTable->getColumn('def_blob_null')->getDefault());
193
        self::assertFalse($onlineTable->getColumn('def_blob_null')->getNotnull());
194
    }
195
196 View Code Duplication
    public function testColumnCollation()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
197
    {
198
        $table = new Table('test_collation');
199
        $table->addOption('collate', $collation = 'latin1_swedish_ci');
200
        $table->addOption('charset', 'latin1');
201
        $table->addColumn('id', 'integer');
202
        $table->addColumn('text', 'text');
203
        $table->addColumn('foo', 'text')->setPlatformOption('collation', 'latin1_swedish_ci');
204
        $table->addColumn('bar', 'text')->setPlatformOption('collation', 'utf8_general_ci');
205
        $this->_sm->dropAndCreateTable($table);
206
207
        $columns = $this->_sm->listTableColumns('test_collation');
208
209
        self::assertArrayNotHasKey('collation', $columns['id']->getPlatformOptions());
210
        self::assertEquals('latin1_swedish_ci', $columns['text']->getPlatformOption('collation'));
211
        self::assertEquals('latin1_swedish_ci', $columns['foo']->getPlatformOption('collation'));
212
        self::assertEquals('utf8_general_ci', $columns['bar']->getPlatformOption('collation'));
213
    }
214
215
    /**
216
     * @group DBAL-843
217
     */
218
    public function testListLobTypeColumns()
219
    {
220
        $tableName = 'lob_type_columns';
221
        $table = new Table($tableName);
222
223
        $table->addColumn('col_tinytext', 'text', array('length' => MySqlPlatform::LENGTH_LIMIT_TINYTEXT));
224
        $table->addColumn('col_text', 'text', array('length' => MySqlPlatform::LENGTH_LIMIT_TEXT));
225
        $table->addColumn('col_mediumtext', 'text', array('length' => MySqlPlatform::LENGTH_LIMIT_MEDIUMTEXT));
226
        $table->addColumn('col_longtext', 'text');
227
228
        $table->addColumn('col_tinyblob', 'text', array('length' => MySqlPlatform::LENGTH_LIMIT_TINYBLOB));
229
        $table->addColumn('col_blob', 'blob', array('length' => MySqlPlatform::LENGTH_LIMIT_BLOB));
230
        $table->addColumn('col_mediumblob', 'blob', array('length' => MySqlPlatform::LENGTH_LIMIT_MEDIUMBLOB));
231
        $table->addColumn('col_longblob', 'blob');
232
233
        $this->_sm->dropAndCreateTable($table);
234
235
        $platform = $this->_sm->getDatabasePlatform();
236
        $offlineColumns = $table->getColumns();
237
        $onlineColumns = $this->_sm->listTableColumns($tableName);
238
239
        self::assertSame(
240
            $platform->getClobTypeDeclarationSQL($offlineColumns['col_tinytext']->toArray()),
241
            $platform->getClobTypeDeclarationSQL($onlineColumns['col_tinytext']->toArray())
242
        );
243
        self::assertSame(
244
            $platform->getClobTypeDeclarationSQL($offlineColumns['col_text']->toArray()),
245
            $platform->getClobTypeDeclarationSQL($onlineColumns['col_text']->toArray())
246
        );
247
        self::assertSame(
248
            $platform->getClobTypeDeclarationSQL($offlineColumns['col_mediumtext']->toArray()),
249
            $platform->getClobTypeDeclarationSQL($onlineColumns['col_mediumtext']->toArray())
250
        );
251
        self::assertSame(
252
            $platform->getClobTypeDeclarationSQL($offlineColumns['col_longtext']->toArray()),
253
            $platform->getClobTypeDeclarationSQL($onlineColumns['col_longtext']->toArray())
254
        );
255
256
        self::assertSame(
257
            $platform->getBlobTypeDeclarationSQL($offlineColumns['col_tinyblob']->toArray()),
258
            $platform->getBlobTypeDeclarationSQL($onlineColumns['col_tinyblob']->toArray())
259
        );
260
        self::assertSame(
261
            $platform->getBlobTypeDeclarationSQL($offlineColumns['col_blob']->toArray()),
262
            $platform->getBlobTypeDeclarationSQL($onlineColumns['col_blob']->toArray())
263
        );
264
        self::assertSame(
265
            $platform->getBlobTypeDeclarationSQL($offlineColumns['col_mediumblob']->toArray()),
266
            $platform->getBlobTypeDeclarationSQL($onlineColumns['col_mediumblob']->toArray())
267
        );
268
        self::assertSame(
269
            $platform->getBlobTypeDeclarationSQL($offlineColumns['col_longblob']->toArray()),
270
            $platform->getBlobTypeDeclarationSQL($onlineColumns['col_longblob']->toArray())
271
        );
272
    }
273
274
    /**
275
     * @group DBAL-423
276
     */
277
    public function testDiffListGuidTableColumn()
278
    {
279
        $offlineTable = new Table('list_guid_table_column');
280
        $offlineTable->addColumn('col_guid', 'guid');
281
282
        $this->_sm->dropAndCreateTable($offlineTable);
283
284
        $onlineTable = $this->_sm->listTableDetails('list_guid_table_column');
285
286
        $comparator = new Comparator();
287
288
        self::assertFalse(
289
            $comparator->diffTable($offlineTable, $onlineTable),
0 ignored issues
show
Bug introduced by
It seems like $comparator->diffTable($...ineTable, $onlineTable) targeting Doctrine\DBAL\Schema\Comparator::diffTable() can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
290
            "No differences should be detected with the offline vs online schema."
291
        );
292
    }
293
294
    /**
295
     * @group DBAL-1082
296
     */
297 View Code Duplication
    public function testListDecimalTypeColumns()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
298
    {
299
        $tableName = 'test_list_decimal_columns';
300
        $table = new Table($tableName);
301
302
        $table->addColumn('col', 'decimal');
303
        $table->addColumn('col_unsigned', 'decimal', array('unsigned' => true));
304
305
        $this->_sm->dropAndCreateTable($table);
306
307
        $columns = $this->_sm->listTableColumns($tableName);
308
309
        self::assertArrayHasKey('col', $columns);
310
        self::assertArrayHasKey('col_unsigned', $columns);
311
        self::assertFalse($columns['col']->getUnsigned());
312
        self::assertTrue($columns['col_unsigned']->getUnsigned());
313
    }
314
315
    /**
316
     * @group DBAL-1082
317
     */
318 View Code Duplication
    public function testListFloatTypeColumns()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
319
    {
320
        $tableName = 'test_list_float_columns';
321
        $table = new Table($tableName);
322
323
        $table->addColumn('col', 'float');
324
        $table->addColumn('col_unsigned', 'float', array('unsigned' => true));
325
326
        $this->_sm->dropAndCreateTable($table);
327
328
        $columns = $this->_sm->listTableColumns($tableName);
329
330
        self::assertArrayHasKey('col', $columns);
331
        self::assertArrayHasKey('col_unsigned', $columns);
332
        self::assertFalse($columns['col']->getUnsigned());
333
        self::assertTrue($columns['col_unsigned']->getUnsigned());
334
    }
335
336
337
    /**
338
     * As of MariaDB 10.2.7, nullable default values literals are always single quoted in
339
     * information_schema. Non-nullable defaults behaviour is not affected.
340
     * This test ensure accidental removal of double single encoded defaults for MariaDB >= 10.2.7.
341
     *
342
     * @link https://mariadb.com/kb/en/library/information-schema-columns-table/
343
     * @link https://dev.mysql.com/doc/refman/5.5/en/string-literals.html
344
     */
345
    public function testColumnDefaultValuesDoubleQuoted(): void
346
    {
347
        $table = new Table("test_column_default_values_double_quoted");
348
        $table->addColumn('string_nullable_quoted', 'string', ['notnull' => false, 'default' => 'NULL']);
349
        $table->addColumn('string_nullable_double_quoted', 'string', ['notnull' => false, 'default' => "'NULL'"]);
350
351
        $table->addColumn('string_notnull_quoted', 'string', ['notnull' => true, 'default' => 'NULL']);
352
        $table->addColumn('string_notnull_double_quoted', 'string', ['notnull' => true, 'default' => "\\'NULL\\'"]);
353
354
        $this->_sm->dropAndCreateTable($table);
355
356
        $onlineTable = $this->_sm->listTableDetails("test_column_default_values_double_quoted");
357
        self::assertSame('NULL', $onlineTable->getColumn('string_nullable_quoted')->getDefault());
358
359
        self::assertSame("'NULL'", $onlineTable->getColumn('string_nullable_double_quoted')->getDefault());
360
        self::assertSame("NULL", $onlineTable->getColumn('string_notnull_quoted')->getDefault());
361
        self::assertSame("\\'NULL\\'", $onlineTable->getColumn('string_notnull_double_quoted')->getDefault());
362
363
        $comparator = new Comparator();
364
365
        $diff = $comparator->diffTable($table, $onlineTable);
366
        self::assertFalse($diff, "Tables should be identical with double quoted literals.");
0 ignored issues
show
Bug introduced by
It seems like $diff defined by $comparator->diffTable($table, $onlineTable) on line 365 can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
367
    }
368
369
    public function testColumnDefaultCurrentTimestamp(): void
370
    {
371
        $platform = $this->_sm->getDatabasePlatform();
372
373
        $table = new Table("test_column_defaults_current_timestamp");
374
375
        $currentTimeStampSql = $platform->getCurrentTimestampSQL();
376
377
        $table->addColumn('col_datetime', 'datetime', ['notnull' => true, 'default' => $currentTimeStampSql]);
378
        $table->addColumn('col_datetime_nullable', 'datetime', ['notnull' => false, 'default' => $currentTimeStampSql]);
379
380
        $this->_sm->dropAndCreateTable($table);
381
382
        $onlineTable = $this->_sm->listTableDetails("test_column_defaults_current_timestamp");
383
        self::assertSame($currentTimeStampSql, $onlineTable->getColumn('col_datetime')->getDefault());
384
        self::assertSame($currentTimeStampSql, $onlineTable->getColumn('col_datetime_nullable')->getDefault());
385
386
        $comparator = new Comparator();
387
388
        $diff = $comparator->diffTable($table, $onlineTable);
389
        self::assertFalse($diff, "Tables should be identical with column defaults.");
0 ignored issues
show
Bug introduced by
It seems like $diff defined by $comparator->diffTable($table, $onlineTable) on line 388 can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
390
    }
391
392
    /**
393
     * @link https://mariadb.com/kb/en/library/string-literals
394
     */
395
    public function testColumnDefaultValuesEscaping(): void
396
    {
397
        $table = new Table("test_column_default_values_escaping");
398
        $table->addColumn('no_quotes', 'string', ['notnull' => false, 'default' => 'az']);
399
400
        $table->addColumn('backslash', 'string', ['notnull' => false, 'default' => 'a\\\z']);
401
        $table->addColumn('repeated_single_quotes', 'string', ['notnull' => false, 'default' => "a''z"]);
402
403
        $this->_sm->dropAndCreateTable($table);
404
405
        $onlineTable = $this->_sm->listTableDetails("test_column_default_values_escaping");
406
        self::assertSame("az", $onlineTable->getColumn('no_quotes')->getDefault());
407
        self::assertSame('a\\\z', $onlineTable->getColumn('backslash')->getDefault());
408
        self::assertSame("a''z", $onlineTable->getColumn('repeated_single_quotes')->getDefault());
409
410
        $comparator = new Comparator();
411
412
        $diff = $comparator->diffTable($table, $onlineTable);
413
        self::assertFalse($diff, "Tables should be identical with values escape sequences.");
0 ignored issues
show
Bug introduced by
It seems like $diff defined by $comparator->diffTable($table, $onlineTable) on line 412 can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
414
    }
415
416
    public function testJsonColumnType(): void
417
    {
418
        $platform = $this->_sm->getDatabasePlatform();
419
        if (!$platform->hasNativeJsonType()) {
420
            $this->markTestSkipped("Requires native JSON type");
421
        }
422
423
        $table = new Table('test_mysql_json');
424
        $table->addColumn('col_json', 'json');
425
        $this->_sm->dropAndCreateTable($table);
426
427
        $columns = $this->_sm->listTableColumns('test_mysql_json');
428
429
        self::assertSame(TYPE::JSON, $columns['col_json']->getType()->getName());
430
    }
431
    /**
432
     * @todo split into multiple tests (most of them already made) and remove
433
     */
434
    public function testColumnDefaultsUsingDoctrineTable(): void
435
    {
436
        $table = new Table("test_column_defaults_with_table");
437
        $table->addColumn('col0', 'integer', ['notnull' => false]);
438
        $table->addColumn('col1', 'integer', ['notnull' => false, 'default' => null]);
439
        $table->addColumn('col2', 'string', ['notnull' => false, 'default' => null]);
440
        $table->addColumn('col3', 'string', ['notnull' => false, 'default' => 'NULL']);
441
        $table->addColumn('col4', 'string', ['notnull' => false, 'default' => 'Hello world']);
442
        $table->addColumn('col5', 'datetime', ['notnull' => false, 'default' => null]);
443
        $table->addColumn('col6', 'decimal', ['scale' => 3, 'precision' => 6, 'notnull' => false, 'default' => -2.3]);
444
        $table->addColumn('col7', 'date', ['notnull' => false, 'default' => '2012-12-12']);
445
        $table->addColumn('col8', 'string', ['notnull' => true, 'default' => '']);
446
        $table->addColumn('col9', 'integer', ['notnull' => false, 'default' => 0]);
447
        $table->addColumn('col10', 'string', ['notnull' => false, 'default' => 'He"ll"o world']);
448
        $table->addColumn('col11', 'string', ['notnull' => false, 'default' => '2012-12-12 23:59:59']);
449
        //$table->addColumn('col12', 'string', ['notnull' => false, 'default' => 'He\\\'llo \\\world']);
450
451
        $table->addColumn('col20', 'string', ['notnull' => true, 'default' => 'CURRENT_TIMESTAMP()']);
452
        $table->addColumn('col21', 'string', ['notnull' => false, 'default' => 'CURRENT_TIMESTAMP']);
453
454
        $this->_sm->dropAndCreateTable($table);
455
456
        $onlineTable = $this->_sm->listTableDetails("test_column_defaults_with_table");
457
        self::assertNull($onlineTable->getColumn('col0')->getDefault());
458
        self::assertNull($onlineTable->getColumn('col1')->getDefault());
459
        self::assertNull($onlineTable->getColumn('col2')->getDefault());
460
        self::assertEquals('NULL', $onlineTable->getColumn('col3')->getDefault());
461
        self::assertEquals('Hello world', $onlineTable->getColumn('col4')->getDefault());
462
        self::assertNull($onlineTable->getColumn('col5')->getDefault());
463
        self::assertEquals(-2.3, $onlineTable->getColumn('col6')->getDefault());
464
        self::assertEquals('2012-12-12', $onlineTable->getColumn('col7')->getDefault());
465
        self::assertTrue($onlineTable->getColumn('col8')->getNotnull());
466
        self::assertEquals('', $onlineTable->getColumn('col8')->getDefault());
467
        self::assertSame('0', $onlineTable->getColumn('col9')->getDefault());
468
        self::assertEquals('He"ll"o world', $onlineTable->getColumn('col10')->getDefault());
469
        self::assertEquals('2012-12-12 23:59:59', $onlineTable->getColumn('col11')->getDefault());
470
        //self::assertEquals('He\\\'llo \\world', $onlineTable->getColumn('col12')->getDefault());
471
472
        // MariaDB 10.2 and MySQL 5.7 differences while storing default now() in information schema.
473
        // MariaDB will always store "current_timestamp()", mysql "CURRENT_TIMESTAMP"
474
        self::assertStringStartsWith('current_timestamp', strtolower($onlineTable->getColumn('col20')->getDefault()));
475
        self::assertStringStartsWith('current_timestamp', strtolower($onlineTable->getColumn('col21')->getDefault()));
476
477
        $comparator = new Comparator();
478
479
        $diff = $comparator->diffTable($table, $onlineTable);
480
        self::assertFalse($diff, "Tables should be identical with column defaults.");
0 ignored issues
show
Bug introduced by
It seems like $diff defined by $comparator->diffTable($table, $onlineTable) on line 479 can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
481
    }
482
483
    /**
484
     * Ensure that a table created outside doctrine and containing
485
     * quoted default values does not trigger a table diff change. I
486
     * Note: MariaDb 10.2 silently change "\'" into "''" when storing in
487
     * information schema, MariaDb102Platform should normalize the table details.
488
     */
489
    public function testExistingTableWithQuotedDefaultsDoesNotTriggerChange(): void
490
    {
491
        $this->_conn->query('DROP TABLE IF EXISTS test_column_defaults_with_create');
492
        $sql = "
493
            CREATE TABLE test_column_defaults_with_create (
494
                col1 VARCHAR(255) NULL DEFAULT 'O''Connor\'\"',
495
                col2 VARCHAR(255) NULL DEFAULT '''A'''
496
                );
497
        ";
498
        $this->_conn->query($sql);
499
500
        $onlineTable = $this->_sm->listTableDetails("test_column_defaults_with_create");
501
        self::assertSame("O'Connor'\"", $onlineTable->getColumn('col1')->getDefault());
502
        self::assertSame("'A'", $onlineTable->getColumn('col2')->getDefault());
503
504
        $table = new Table("test_column_defaults_no_diff");
505
        $table->addColumn('col1', 'string', ['notnull' => false, 'default' => "O'Connor'\""]);
506
        $table->addColumn('col2', 'string', ['notnull' => false, 'default' => "'A'"]);
507
508
        $comparator = new Comparator();
509
        $diff = $comparator->diffTable($table, $onlineTable);
510
        self::assertFalse($diff);
0 ignored issues
show
Bug introduced by
It seems like $diff defined by $comparator->diffTable($table, $onlineTable) on line 509 can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
511
    }
512
513
    /**
514
     * Since MariaDB 10.2.1, Blob and text columns can have a default value
515
     *
516
     * @link https://mariadb.com/kb/en/library/blob-and-text-data-types
517
     */
518
    public function testDoesPropagateDefaultValuesForBlobTextAndJson(): void
519
    {
520
        if (!$this->_sm->getDatabasePlatform() instanceof MariaDb102Platform) {
521
            $this->markTestSkipped('Only relevant for MariaDb102Platform.');
522
        }
523
524
        $table = new Table("text_blob_default_value");
525
526
        $json = json_encode(['prop1' => "O'Connor", 'prop2' => 10]);
527
528
        $table->addColumn('def_text', 'text', ['default' => "O'Connor"]);
529
        $table->addColumn('def_text_null', 'text', ['notnull' => false, 'default' => 'def']);
530
        $table->addColumn('def_blob', 'blob', ['default' => 'def']);
531
        $table->addColumn('def_json', 'json', ['default' => $json]);
532
533
        $this->_sm->dropAndCreateTable($table);
534
535
        $onlineTable = $this->_sm->listTableDetails("text_blob_default_value");
536
537
        self::assertSame("O'Connor", $onlineTable->getColumn('def_text')->getDefault());
538
        self::assertSame('def', $onlineTable->getColumn('def_text_null')->getDefault());
539
        self::assertSame('def', $onlineTable->getColumn('def_blob')->getDefault());
540
        self::assertSame($json, $onlineTable->getColumn('def_json')->getDefault());
541
542
        $comparator = new Comparator();
543
544
        self::assertFalse($comparator->diffTable($table, $onlineTable));
0 ignored issues
show
Bug introduced by
It seems like $comparator->diffTable($table, $onlineTable) targeting Doctrine\DBAL\Schema\Comparator::diffTable() can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
545
    }
546
547
    /**
548
     * Note: MySQL (as of 5.7.19) does not support default value
549
     * for DATE and TIME fields while MariaDB 10.2+ does
550
     */
551
    public function testColumnDefaultValuesCurrentTimeAndDate(): void
552
    {
553
        if (!$this->_sm->getDatabasePlatform() instanceof MariaDb102Platform) {
554
            $this->markTestSkipped('Only relevant for MariaDb102Platform.');
555
        }
556
557
        $platform = $this->_sm->getDatabasePlatform();
558
559
        $table = new Table("test_column_defaults_current_time_and_date");
560
561
        $currentTimeSql = $platform->getCurrentTimeSQL();
562
        $currentDateSql = $platform->getCurrentDateSQL();
563
564
        $table->addColumn('col_date', 'date', ['notnull' => true, 'default' => $currentDateSql]);
565
        $table->addColumn('col_time', 'time', ['notnull' => true, 'default' => $currentTimeSql]);
566
567
        $this->_sm->dropAndCreateTable($table);
568
569
        $onlineTable = $this->_sm->listTableDetails("test_column_defaults_current_time_and_date");
570
571
        self::assertSame($currentDateSql, $onlineTable->getColumn('col_date')->getDefault());
572
        self::assertSame($currentTimeSql, $onlineTable->getColumn('col_time')->getDefault());
573
574
        $comparator = new Comparator();
575
576
        $diff = $comparator->diffTable($table, $onlineTable);
577
        self::assertFalse($diff, "Tables should be identical with column defaults.");
0 ignored issues
show
Bug introduced by
It seems like $diff defined by $comparator->diffTable($table, $onlineTable) on line 576 can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
578
    }
579
580
    /**
581
     * MariaDB supports expressions as default values
582
     *
583
     * @todo remove or implement !!!
584
     *
585
     * @link https://mariadb.com/kb/en/library/information-schema-columns-table/
586
     */
587
    public function testColumnDefaultExpressions(): void
588
    {
589
        $this->markTestSkipped('Setting an expression as a default value is not yet supported (WIP)');
590
591
        if (!$this->_sm->getDatabasePlatform() instanceof MariaDb102Platform) {
592
            $this->markTestSkipped('Only relevant for MariaDb102Platform.');
593
        }
594
595
        $table = new Table("test_column_default_expressions");
596
597
        $table->addColumn('expression', 'string', ['notnull' => false, 'default' => "concat('A','B')"]);
598
599
        $this->_sm->dropAndCreateTable($table);
600
601
        $onlineTable = $this->_sm->listTableDetails("test_column_default_expressions");
602
        self::assertSame("concat('A','B')", $onlineTable->getColumn('expression')->getDefault());
603
604
        $comparator = new Comparator();
605
606
        $diff = $comparator->diffTable($table, $onlineTable);
607
        self::assertFalse($diff, "Tables should be identical with expression column defaults.");
0 ignored issues
show
Bug introduced by
It seems like $diff defined by $comparator->diffTable($table, $onlineTable) on line 606 can also be of type object<Doctrine\DBAL\Schema\TableDiff>; however, PHPUnit\Framework\Assert::assertFalse() does only seem to accept boolean, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
608
    }
609
610
}
611