Failed Conditions
Pull Request — master (#2850)
by Adrien
33:12 queued 23:11
created

MySqlSchemaManagerTest::testEnsureDefaultsAreUnescapedFromSchemaIntrospection()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 20
nc 1
nop 0
1
<?php
2
3
namespace Doctrine\Tests\DBAL\Functional\Schema;
4
5
use Doctrine\DBAL\Platforms\MariaDb1027Platform;
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
    protected function setUp()
16
    {
17
        parent::setUp();
18
19
        if ( ! Type::hasType('point')) {
20
            Type::addType('point', MySqlPointType::class);
21
        }
22
    }
23
24
    public function testSwitchPrimaryKeyColumns()
25
    {
26
        $tableOld = new Table("switch_primary_key_columns");
27
        $tableOld->addColumn('foo_id', 'integer');
28
        $tableOld->addColumn('bar_id', 'integer');
29
30
        $this->_sm->createTable($tableOld);
31
        $tableFetched = $this->_sm->listTableDetails("switch_primary_key_columns");
32
        $tableNew = clone $tableFetched;
33
        $tableNew->setPrimaryKey(array('bar_id', 'foo_id'));
34
35
        $comparator = new Comparator;
36
        $this->_sm->alterTable($comparator->diffTable($tableFetched, $tableNew));
37
38
        $table      = $this->_sm->listTableDetails('switch_primary_key_columns');
39
        $primaryKey = $table->getPrimaryKeyColumns();
40
41
        self::assertCount(2, $primaryKey);
42
        self::assertContains('bar_id', $primaryKey);
43
        self::assertContains('foo_id', $primaryKey);
44
    }
45
46
    public function testDiffTableBug()
47
    {
48
        $schema = new Schema();
49
        $table = $schema->createTable('diffbug_routing_translations');
50
        $table->addColumn('id', 'integer');
51
        $table->addColumn('route', 'string');
52
        $table->addColumn('locale', 'string');
53
        $table->addColumn('attribute', 'string');
54
        $table->addColumn('localized_value', 'string');
55
        $table->addColumn('original_value', 'string');
56
        $table->setPrimaryKey(array('id'));
57
        $table->addUniqueIndex(array('route', 'locale', 'attribute'));
58
        $table->addIndex(array('localized_value')); // this is much more selective than the unique index
59
60
        $this->_sm->createTable($table);
61
        $tableFetched = $this->_sm->listTableDetails("diffbug_routing_translations");
62
63
        $comparator = new Comparator;
64
        $diff = $comparator->diffTable($tableFetched, $table);
65
66
        self::assertFalse($diff, "no changes expected.");
0 ignored issues
show
Bug introduced by
$diff of type Doctrine\DBAL\Schema\TableDiff is incompatible with the type boolean expected by parameter $condition of PHPUnit\Framework\Assert::assertFalse(). ( Ignorable by Annotation )

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

66
        self::assertFalse(/** @scrutinizer ignore-type */ $diff, "no changes expected.");
Loading history...
67
    }
68
69
    public function testFulltextIndex()
70
    {
71
        $table = new Table('fulltext_index');
72
        $table->addColumn('text', 'text');
73
        $table->addIndex(array('text'), 'f_index');
74
        $table->addOption('engine', 'MyISAM');
75
76
        $index = $table->getIndex('f_index');
77
        $index->addFlag('fulltext');
78
79
        $this->_sm->dropAndCreateTable($table);
80
81
        $indexes = $this->_sm->listTableIndexes('fulltext_index');
82
        self::assertArrayHasKey('f_index', $indexes);
83
        self::assertTrue($indexes['f_index']->hasFlag('fulltext'));
84
    }
85
86
    public function testSpatialIndex()
87
    {
88
        $table = new Table('spatial_index');
89
        $table->addColumn('point', 'point');
90
        $table->addIndex(array('point'), 's_index');
91
        $table->addOption('engine', 'MyISAM');
92
93
        $index = $table->getIndex('s_index');
94
        $index->addFlag('spatial');
95
96
        $this->_sm->dropAndCreateTable($table);
97
98
        $indexes = $this->_sm->listTableIndexes('spatial_index');
99
        self::assertArrayHasKey('s_index', $indexes);
100
        self::assertTrue($indexes['s_index']->hasFlag('spatial'));
101
    }
102
103
    /**
104
     * @group DBAL-400
105
     */
106
    public function testAlterTableAddPrimaryKey()
107
    {
108
        $table = new Table('alter_table_add_pk');
109
        $table->addColumn('id', 'integer');
110
        $table->addColumn('foo', 'integer');
111
        $table->addIndex(array('id'), 'idx_id');
112
113
        $this->_sm->createTable($table);
114
115
        $comparator = new Comparator();
116
        $diffTable  = clone $table;
117
118
        $diffTable->dropIndex('idx_id');
119
        $diffTable->setPrimaryKey(array('id'));
120
121
        $this->_sm->alterTable($comparator->diffTable($table, $diffTable));
122
123
        $table = $this->_sm->listTableDetails("alter_table_add_pk");
124
125
        self::assertFalse($table->hasIndex('idx_id'));
126
        self::assertTrue($table->hasPrimaryKey());
127
    }
128
129
    /**
130
     * @group DBAL-464
131
     */
132
    public function testDropPrimaryKeyWithAutoincrementColumn()
133
    {
134
        $table = new Table("drop_primary_key");
135
        $table->addColumn('id', 'integer', array('autoincrement' => true));
136
        $table->addColumn('foo', 'integer');
137
        $table->setPrimaryKey(array('id', 'foo'));
138
139
        $this->_sm->dropAndCreateTable($table);
140
141
        $diffTable = clone $table;
142
143
        $diffTable->dropPrimaryKey();
144
145
        $comparator = new Comparator();
146
147
        $this->_sm->alterTable($comparator->diffTable($table, $diffTable));
148
149
        $table = $this->_sm->listTableDetails("drop_primary_key");
150
151
        self::assertFalse($table->hasPrimaryKey());
152
        self::assertFalse($table->getColumn('id')->getAutoincrement());
153
    }
154
155
    /**
156
     * @group DBAL-789
157
     */
158
    public function testDoesNotPropagateDefaultValuesForUnsupportedColumnTypes()
159
    {
160
        if ($this->_sm->getDatabasePlatform() instanceof MariaDb1027Platform) {
161
            $this->markTestSkipped(
162
                'MariaDb102Platform supports default values for BLOB and TEXT columns and will propagate values'
163
            );
164
        }
165
166
        $table = new Table("text_blob_default_value");
167
        $table->addColumn('def_text', 'text', ['default' => 'def']);
168
        $table->addColumn('def_text_null', 'text', ['notnull' => false, 'default' => 'def']);
169
        $table->addColumn('def_blob', 'blob', ['default' => 'def']);
170
        $table->addColumn('def_blob_null', 'blob', ['notnull' => false, 'default' => 'def']);
171
172
        $this->_sm->dropAndCreateTable($table);
173
174
        $onlineTable = $this->_sm->listTableDetails("text_blob_default_value");
175
176
        self::assertNull($onlineTable->getColumn('def_text')->getDefault());
177
        self::assertNull($onlineTable->getColumn('def_text_null')->getDefault());
178
        self::assertFalse($onlineTable->getColumn('def_text_null')->getNotnull());
179
        self::assertNull($onlineTable->getColumn('def_blob')->getDefault());
180
        self::assertNull($onlineTable->getColumn('def_blob_null')->getDefault());
181
        self::assertFalse($onlineTable->getColumn('def_blob_null')->getNotnull());
182
183
        $comparator = new Comparator();
184
185
        $this->_sm->alterTable($comparator->diffTable($table, $onlineTable));
186
187
        $onlineTable = $this->_sm->listTableDetails("text_blob_default_value");
188
189
        self::assertNull($onlineTable->getColumn('def_text')->getDefault());
190
        self::assertNull($onlineTable->getColumn('def_text_null')->getDefault());
191
        self::assertFalse($onlineTable->getColumn('def_text_null')->getNotnull());
192
        self::assertNull($onlineTable->getColumn('def_blob')->getDefault());
193
        self::assertNull($onlineTable->getColumn('def_blob_null')->getDefault());
194
        self::assertFalse($onlineTable->getColumn('def_blob_null')->getNotnull());
195
    }
196
197
    public function testColumnCollation()
198
    {
199
        $table = new Table('test_collation');
200
        $table->addOption('collate', $collation = 'latin1_swedish_ci');
201
        $table->addOption('charset', 'latin1');
202
        $table->addColumn('id', 'integer');
203
        $table->addColumn('text', 'text');
204
        $table->addColumn('foo', 'text')->setPlatformOption('collation', 'latin1_swedish_ci');
205
        $table->addColumn('bar', 'text')->setPlatformOption('collation', 'utf8_general_ci');
206
        $this->_sm->dropAndCreateTable($table);
207
208
        $columns = $this->_sm->listTableColumns('test_collation');
209
210
        self::assertArrayNotHasKey('collation', $columns['id']->getPlatformOptions());
211
        self::assertEquals('latin1_swedish_ci', $columns['text']->getPlatformOption('collation'));
212
        self::assertEquals('latin1_swedish_ci', $columns['foo']->getPlatformOption('collation'));
213
        self::assertEquals('utf8_general_ci', $columns['bar']->getPlatformOption('collation'));
214
    }
215
216
    /**
217
     * @group DBAL-843
218
     */
219
    public function testListLobTypeColumns()
220
    {
221
        $tableName = 'lob_type_columns';
222
        $table = new Table($tableName);
223
224
        $table->addColumn('col_tinytext', 'text', array('length' => MySqlPlatform::LENGTH_LIMIT_TINYTEXT));
225
        $table->addColumn('col_text', 'text', array('length' => MySqlPlatform::LENGTH_LIMIT_TEXT));
226
        $table->addColumn('col_mediumtext', 'text', array('length' => MySqlPlatform::LENGTH_LIMIT_MEDIUMTEXT));
227
        $table->addColumn('col_longtext', 'text');
228
229
        $table->addColumn('col_tinyblob', 'text', array('length' => MySqlPlatform::LENGTH_LIMIT_TINYBLOB));
230
        $table->addColumn('col_blob', 'blob', array('length' => MySqlPlatform::LENGTH_LIMIT_BLOB));
231
        $table->addColumn('col_mediumblob', 'blob', array('length' => MySqlPlatform::LENGTH_LIMIT_MEDIUMBLOB));
232
        $table->addColumn('col_longblob', 'blob');
233
234
        $this->_sm->dropAndCreateTable($table);
235
236
        $platform = $this->_sm->getDatabasePlatform();
237
        $offlineColumns = $table->getColumns();
238
        $onlineColumns = $this->_sm->listTableColumns($tableName);
239
240
        self::assertSame(
241
            $platform->getClobTypeDeclarationSQL($offlineColumns['col_tinytext']->toArray()),
242
            $platform->getClobTypeDeclarationSQL($onlineColumns['col_tinytext']->toArray())
243
        );
244
        self::assertSame(
245
            $platform->getClobTypeDeclarationSQL($offlineColumns['col_text']->toArray()),
246
            $platform->getClobTypeDeclarationSQL($onlineColumns['col_text']->toArray())
247
        );
248
        self::assertSame(
249
            $platform->getClobTypeDeclarationSQL($offlineColumns['col_mediumtext']->toArray()),
250
            $platform->getClobTypeDeclarationSQL($onlineColumns['col_mediumtext']->toArray())
251
        );
252
        self::assertSame(
253
            $platform->getClobTypeDeclarationSQL($offlineColumns['col_longtext']->toArray()),
254
            $platform->getClobTypeDeclarationSQL($onlineColumns['col_longtext']->toArray())
255
        );
256
257
        self::assertSame(
258
            $platform->getBlobTypeDeclarationSQL($offlineColumns['col_tinyblob']->toArray()),
259
            $platform->getBlobTypeDeclarationSQL($onlineColumns['col_tinyblob']->toArray())
260
        );
261
        self::assertSame(
262
            $platform->getBlobTypeDeclarationSQL($offlineColumns['col_blob']->toArray()),
263
            $platform->getBlobTypeDeclarationSQL($onlineColumns['col_blob']->toArray())
264
        );
265
        self::assertSame(
266
            $platform->getBlobTypeDeclarationSQL($offlineColumns['col_mediumblob']->toArray()),
267
            $platform->getBlobTypeDeclarationSQL($onlineColumns['col_mediumblob']->toArray())
268
        );
269
        self::assertSame(
270
            $platform->getBlobTypeDeclarationSQL($offlineColumns['col_longblob']->toArray()),
271
            $platform->getBlobTypeDeclarationSQL($onlineColumns['col_longblob']->toArray())
272
        );
273
    }
274
275
    /**
276
     * @group DBAL-423
277
     */
278
    public function testDiffListGuidTableColumn()
279
    {
280
        $offlineTable = new Table('list_guid_table_column');
281
        $offlineTable->addColumn('col_guid', 'guid');
282
283
        $this->_sm->dropAndCreateTable($offlineTable);
284
285
        $onlineTable = $this->_sm->listTableDetails('list_guid_table_column');
286
287
        $comparator = new Comparator();
288
289
        self::assertFalse(
290
            $comparator->diffTable($offlineTable, $onlineTable),
0 ignored issues
show
Bug introduced by
$comparator->diffTable($...ineTable, $onlineTable) of type Doctrine\DBAL\Schema\TableDiff is incompatible with the type boolean expected by parameter $condition of PHPUnit\Framework\Assert::assertFalse(). ( Ignorable by Annotation )

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

290
            /** @scrutinizer ignore-type */ $comparator->diffTable($offlineTable, $onlineTable),
Loading history...
291
            "No differences should be detected with the offline vs online schema."
292
        );
293
    }
294
295
    /**
296
     * @group DBAL-1082
297
     */
298
    public function testListDecimalTypeColumns()
299
    {
300
        $tableName = 'test_list_decimal_columns';
301
        $table = new Table($tableName);
302
303
        $table->addColumn('col', 'decimal');
304
        $table->addColumn('col_unsigned', 'decimal', array('unsigned' => true));
305
306
        $this->_sm->dropAndCreateTable($table);
307
308
        $columns = $this->_sm->listTableColumns($tableName);
309
310
        self::assertArrayHasKey('col', $columns);
311
        self::assertArrayHasKey('col_unsigned', $columns);
312
        self::assertFalse($columns['col']->getUnsigned());
313
        self::assertTrue($columns['col_unsigned']->getUnsigned());
314
    }
315
316
    /**
317
     * @group DBAL-1082
318
     */
319
    public function testListFloatTypeColumns()
320
    {
321
        $tableName = 'test_list_float_columns';
322
        $table = new Table($tableName);
323
324
        $table->addColumn('col', 'float');
325
        $table->addColumn('col_unsigned', 'float', array('unsigned' => true));
326
327
        $this->_sm->dropAndCreateTable($table);
328
329
        $columns = $this->_sm->listTableColumns($tableName);
330
331
        self::assertArrayHasKey('col', $columns);
332
        self::assertArrayHasKey('col_unsigned', $columns);
333
        self::assertFalse($columns['col']->getUnsigned());
334
        self::assertTrue($columns['col_unsigned']->getUnsigned());
335
    }
336
337
    public function testJsonColumnType() : void
338
    {
339
        $table = new Table('test_mysql_json');
340
        $table->addColumn('col_json', 'json');
341
        $this->_sm->dropAndCreateTable($table);
342
343
        $columns = $this->_sm->listTableColumns('test_mysql_json');
344
345
        self::assertSame(TYPE::JSON, $columns['col_json']->getType()->getName());
346
    }
347
348
    public function testColumnDefaultCurrentTimestamp() : void
349
    {
350
        $platform = $this->_sm->getDatabasePlatform();
351
352
        $table = new Table("test_column_defaults_current_timestamp");
353
354
        $currentTimeStampSql = $platform->getCurrentTimestampSQL();
355
356
        $table->addColumn('col_datetime', 'datetime', ['notnull' => true, 'default' => $currentTimeStampSql]);
357
        $table->addColumn('col_datetime_nullable', 'datetime', ['default' => $currentTimeStampSql]);
358
359
        $this->_sm->dropAndCreateTable($table);
360
361
        $onlineTable = $this->_sm->listTableDetails("test_column_defaults_current_timestamp");
362
        self::assertSame($currentTimeStampSql, $onlineTable->getColumn('col_datetime')->getDefault());
363
        self::assertSame($currentTimeStampSql, $onlineTable->getColumn('col_datetime_nullable')->getDefault());
364
365
        $comparator = new Comparator();
366
367
        $diff = $comparator->diffTable($table, $onlineTable);
368
        self::assertFalse($diff, "Tables should be identical with column defaults.");
0 ignored issues
show
Bug introduced by
$diff of type Doctrine\DBAL\Schema\TableDiff is incompatible with the type boolean expected by parameter $condition of PHPUnit\Framework\Assert::assertFalse(). ( Ignorable by Annotation )

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

368
        self::assertFalse(/** @scrutinizer ignore-type */ $diff, "Tables should be identical with column defaults.");
Loading history...
369
    }
370
371
    public function testColumnDefaultsAreValid()
372
    {
373
        $table = new Table("test_column_defaults_are_valid");
374
375
        $currentTimeStampSql = $this->_sm->getDatabasePlatform()->getCurrentTimestampSQL();
376
        $table->addColumn('col_datetime', 'datetime', ['default' => $currentTimeStampSql]);
377
        $table->addColumn('col_datetime_null', 'datetime', ['notnull' => false, 'default' => null]);
378
        $table->addColumn('col_int', 'integer', ['default' => 1]);
379
        $table->addColumn('col_neg_int', 'integer', ['default' => -1]);
380
        $table->addColumn('col_string', 'string', ['default' => 'A']);
381
        $table->addColumn('col_decimal', 'decimal', ['scale' => 3, 'precision' => 6, 'default' => -2.3]);
382
        $table->addColumn('col_date', 'date', ['default' => '2012-12-12']);
383
384
        $this->_sm->dropAndCreateTable($table);
385
386
        $this->_conn->executeUpdate(
387
            "INSERT INTO test_column_defaults_are_valid () VALUES()"
388
        );
389
390
        $row = $this->_conn->fetchAssoc(
391
            'SELECT *, DATEDIFF(CURRENT_TIMESTAMP(), col_datetime) as diff_seconds FROM test_column_defaults_are_valid'
392
        );
393
394
        self::assertInstanceOf(\DateTime::class, \DateTime::createFromFormat('Y-m-d H:i:s', $row['col_datetime']));
395
        self::assertNull($row['col_datetime_null']);
396
        self::assertSame('2012-12-12', $row['col_date']);
397
        self::assertSame('A', $row['col_string']);
398
        self::assertEquals(1, $row['col_int']);
399
        self::assertEquals(-1, $row['col_neg_int']);
400
        self::assertEquals('-2.300', $row['col_decimal']);
401
        self::assertLessThan(5, $row['diff_seconds']);
402
    }
403
404
    /**
405
     * MariaDB 10.2+ does support CURRENT_TIME and CURRENT_DATE as
406
     * column default values for time and date columns.
407
     * (Not supported on Mysql as of 5.7.19)
408
     *
409
     * Note that MariaDB 10.2+, when storing default in information_schema,
410
     * silently change CURRENT_TIMESTAMP as 'current_timestamp()',
411
     * CURRENT_TIME as 'currtime()' and CURRENT_DATE as 'currdate()'.
412
     * This test also ensure proper aliasing to not trigger a table diff.
413
     */
414
    public function testColumnDefaultValuesCurrentTimeAndDate() : void
415
    {
416
        if ( ! $this->_sm->getDatabasePlatform() instanceof MariaDb1027Platform) {
417
            $this->markTestSkipped('Only relevant for MariaDb102Platform.');
418
        }
419
420
        $platform = $this->_sm->getDatabasePlatform();
421
422
        $table = new Table("test_column_defaults_current_time_and_date");
423
424
        $currentTimestampSql = $platform->getCurrentTimestampSQL();
425
        $currentTimeSql      = $platform->getCurrentTimeSQL();
426
        $currentDateSql      = $platform->getCurrentDateSQL();
427
428
        $table->addColumn('col_datetime', 'datetime', ['default' => $currentTimestampSql]);
429
        $table->addColumn('col_date', 'date', ['default' => $currentDateSql]);
430
        $table->addColumn('col_time', 'time', ['default' => $currentTimeSql]);
431
432
        $this->_sm->dropAndCreateTable($table);
433
434
        $onlineTable = $this->_sm->listTableDetails("test_column_defaults_current_time_and_date");
435
436
        self::assertSame($currentTimestampSql, $onlineTable->getColumn('col_datetime')->getDefault());
437
        self::assertSame($currentDateSql, $onlineTable->getColumn('col_date')->getDefault());
438
        self::assertSame($currentTimeSql, $onlineTable->getColumn('col_time')->getDefault());
439
440
        $comparator = new Comparator();
441
442
        $diff = $comparator->diffTable($table, $onlineTable);
443
        self::assertFalse($diff, "Tables should be identical with column defauts time and date.");
0 ignored issues
show
Bug introduced by
$diff of type Doctrine\DBAL\Schema\TableDiff is incompatible with the type boolean expected by parameter $condition of PHPUnit\Framework\Assert::assertFalse(). ( Ignorable by Annotation )

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

443
        self::assertFalse(/** @scrutinizer ignore-type */ $diff, "Tables should be identical with column defauts time and date.");
Loading history...
444
    }
445
}
446