Failed Conditions
Pull Request — 3.0.x (#3987)
by Grégoire
33:07 queued 11s
created

SchemaManagerFunctionalTestCase   F

Complexity

Total Complexity 125

Size/Duplication

Total Lines 1598
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 875
dl 0
loc 1598
rs 1.725
c 2
b 0
f 0
wmc 125

62 Methods

Rating   Name   Duplication   Size   Complexity  
A testListForeignKeys() 0 33 3
A testListDatabases() 0 12 2
A testChangeColumnsTypeWithDefaultValue() 0 35 1
A testCreateAndListViews() 0 16 2
A testDiffListTableColumns() 0 14 2
A testGetColumnComment() 0 39 4
A testAutomaticallyAppendCommentOnMarkedColumns() 0 23 4
A testTableInNamespace() 0 22 3
A testAutoincrementDetection() 0 16 2
B testAlterTableScenario() 0 87 3
A getCreateExampleViewSql() 0 3 1
A testListTableColumnsWithFixedStringColumn() 0 15 1
A testDropAndCreateIndex() 0 14 1
A testListTableIndexesDispatchEvent() 0 25 1
A testListTableWithBlob() 0 14 1
A testCommentHintOnDateIntervalTypeColumn() 0 20 4
A testRenameIndexUsedInForeignKeyConstraint() 0 36 2
A testListNamespaceNames() 0 18 3
A createListTableColumns() 0 13 1
A testListTables() 0 23 3
A testListTableIndexes() 0 26 1
A testCreateSchema() 0 6 1
A testUpdateSchemaWithForeignKeyRenaming() 0 40 2
A getTestTable() 0 10 1
A createTestTable() 0 9 1
A testListTableColumnsDispatchEvent() 0 24 1
A testAutoincrementDetectionMulticolumns() 0 17 2
A testCreateTableWithForeignKeys() 0 26 2
A getTestCompositeTable() 0 10 1
A testComparatorShouldReturnAllChangesWhenUsingLegacyJsonArrayType() 0 16 2
A commentsProvider() 0 11 1
A testComparisonWithAutoDetectedSequenceDefinition() 0 28 2
A testPrimaryKeyAutoIncrement() 0 23 1
A testCommentInTable() 0 9 1
A tearDown() 0 12 2
A testAlterColumnComment() 0 45 4
A testComparatorShouldReturnAllChangesWhenUsingLegacyJsonArrayTypeEvenWhenPlatformHasJsonSupport() 0 16 2
A testComparatorShouldAddCommentToLegacyJsonArrayTypeThatDoesNotHaveIt() 0 16 2
A removeJsonArrayTable() 0 7 2
A hasElementWithName() 0 10 1
A getAlterColumnComment() 0 15 1
A testCommentNotDuplicated() 0 20 2
A testExtractDoctrineTypeFromComment() 0 5 1
A testListTableDetailsWithFullQualifiedTableName() 0 37 2
A testCommentStringsAreQuoted() 0 16 4
A testListSequences() 0 28 4
A testColumnDefaultLifecycle() 0 49 1
A assertHasTable() 0 13 3
A testDropAndCreateSequence() 0 15 2
A testListTableWithBinary() 0 19 1
A testComparatorShouldReturnFalseWhenLegacyJsonArrayColumnHasComment() 0 11 1
A testDoesNotListIndexesImplicitlyCreatedByForeignKeys() 0 25 2
A testGenerateAnIndexWithPartialColumnLength() 0 18 2
A testComparatorShouldModifyOnlyTheCommentWhenUpdatingFromJsonArrayTypeOnLegacyPlatforms() 0 22 2
A testDropsDatabaseWithActiveConnections() 0 32 4
B testListTableColumns() 0 69 1
A getPlatformName() 0 7 1
B testSchemaDiffForeignKeys() 0 41 6
A setUp() 0 11 2
A testCreateAndListSequences() 0 34 3
A testComparatorShouldNotAddCommentToJsonTypeSinceItIsTheDefaultNow() 0 15 2
A testListForeignKeysComposite() 0 25 2

How to fix   Complexity   

Complex Class

Complex classes like SchemaManagerFunctionalTestCase often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SchemaManagerFunctionalTestCase, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Doctrine\DBAL\Tests\Functional\Schema;
4
5
use Doctrine\Common\EventManager;
6
use Doctrine\DBAL\DBALException;
7
use Doctrine\DBAL\Driver\Connection;
8
use Doctrine\DBAL\Events;
9
use Doctrine\DBAL\Platforms\OraclePlatform;
10
use Doctrine\DBAL\Schema\AbstractAsset;
11
use Doctrine\DBAL\Schema\AbstractSchemaManager;
12
use Doctrine\DBAL\Schema\Column;
13
use Doctrine\DBAL\Schema\ColumnDiff;
14
use Doctrine\DBAL\Schema\Comparator;
15
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
16
use Doctrine\DBAL\Schema\Index;
17
use Doctrine\DBAL\Schema\Schema;
18
use Doctrine\DBAL\Schema\SchemaDiff;
19
use Doctrine\DBAL\Schema\Sequence;
20
use Doctrine\DBAL\Schema\Table;
21
use Doctrine\DBAL\Schema\TableDiff;
22
use Doctrine\DBAL\Schema\View;
23
use Doctrine\DBAL\Tests\FunctionalTestCase;
24
use Doctrine\DBAL\Types\ArrayType;
25
use Doctrine\DBAL\Types\BinaryType;
26
use Doctrine\DBAL\Types\DateIntervalType;
27
use Doctrine\DBAL\Types\DateTimeType;
28
use Doctrine\DBAL\Types\DecimalType;
29
use Doctrine\DBAL\Types\IntegerType;
30
use Doctrine\DBAL\Types\ObjectType;
31
use Doctrine\DBAL\Types\StringType;
32
use Doctrine\DBAL\Types\TextType;
33
use Doctrine\DBAL\Types\Type;
34
use function array_filter;
35
use function array_keys;
36
use function array_map;
37
use function array_search;
38
use function array_values;
39
use function count;
40
use function current;
41
use function end;
42
use function explode;
43
use function implode;
44
use function in_array;
45
use function sprintf;
46
use function str_replace;
47
use function strcasecmp;
48
use function strlen;
49
use function strtolower;
50
use function substr;
51
52
abstract class SchemaManagerFunctionalTestCase extends FunctionalTestCase
53
{
54
    /** @var AbstractSchemaManager */
55
    protected $schemaManager;
56
57
    protected function getPlatformName() : string
58
    {
59
        $class     = static::class;
60
        $e         = explode('\\', $class);
61
        $testClass = end($e);
62
63
        return strtolower(str_replace('SchemaManagerTest', null, $testClass));
64
    }
65
66
    protected function setUp() : void
67
    {
68
        parent::setUp();
69
70
        $dbms = $this->getPlatformName();
71
72
        if ($this->connection->getDatabasePlatform()->getName() !== $dbms) {
73
            self::markTestSkipped(static::class . ' requires the use of ' . $dbms);
74
        }
75
76
        $this->schemaManager = $this->connection->getSchemaManager();
77
    }
78
79
    protected function tearDown() : void
80
    {
81
        parent::tearDown();
82
83
        $this->schemaManager->tryMethod('dropTable', 'testschema.my_table_in_namespace');
84
85
        //TODO: SchemaDiff does not drop removed namespaces?
86
        try {
87
            //sql server versions below 2016 do not support 'IF EXISTS' so we have to catch the exception here
88
            $this->connection->exec('DROP SCHEMA testschema');
89
        } catch (DBALException $e) {
90
            return;
91
        }
92
    }
93
94
    /**
95
     * @group DBAL-1220
96
     */
97
    public function testDropsDatabaseWithActiveConnections() : void
98
    {
99
        if (! $this->schemaManager->getDatabasePlatform()->supportsCreateDropDatabase()) {
100
            self::markTestSkipped('Cannot drop Database client side with this Driver.');
101
        }
102
103
        $this->schemaManager->dropAndCreateDatabase('test_drop_database');
104
105
        $knownDatabases = $this->schemaManager->listDatabases();
106
        if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) {
107
            self::assertContains('TEST_DROP_DATABASE', $knownDatabases);
108
        } else {
109
            self::assertContains('test_drop_database', $knownDatabases);
110
        }
111
112
        $params = $this->connection->getParams();
113
        if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) {
114
            $params['user'] = 'test_drop_database';
115
        } else {
116
            $params['dbname'] = 'test_drop_database';
117
        }
118
119
        $user     = $params['user'] ?? null;
120
        $password = $params['password'] ?? null;
121
122
        $connection = $this->connection->getDriver()->connect($params, $user, $password);
123
124
        self::assertInstanceOf(Connection::class, $connection);
125
126
        $this->schemaManager->dropDatabase('test_drop_database');
127
128
        self::assertNotContains('test_drop_database', $this->schemaManager->listDatabases());
129
    }
130
131
    /**
132
     * @group DBAL-195
133
     */
134
    public function testDropAndCreateSequence() : void
135
    {
136
        $platform = $this->connection->getDatabasePlatform();
137
138
        if (! $platform->supportsSequences()) {
139
            self::markTestSkipped(
140
                sprintf('The "%s" platform does not support sequences.', $platform->getName())
141
            );
142
        }
143
144
        $name = 'dropcreate_sequences_test_seq';
145
146
        $this->schemaManager->dropAndCreateSequence(new Sequence($name, 20, 10));
147
148
        self::assertTrue($this->hasElementWithName($this->schemaManager->listSequences(), $name));
149
    }
150
151
    /**
152
     * @param AbstractAsset[] $items
153
     */
154
    private function hasElementWithName(array $items, string $name) : bool
155
    {
156
        $filteredList = array_filter(
157
            $items,
158
            static function (AbstractAsset $item) use ($name) : bool {
159
                return $item->getShortestName($item->getNamespaceName()) === $name;
160
            }
161
        );
162
163
        return count($filteredList) === 1;
164
    }
165
166
    public function testListSequences() : void
167
    {
168
        $platform = $this->connection->getDatabasePlatform();
169
170
        if (! $platform->supportsSequences()) {
171
            self::markTestSkipped(
172
                sprintf('The "%s" platform does not support sequences.', $platform->getName())
173
            );
174
        }
175
176
        $this->schemaManager->createSequence(
177
            new Sequence('list_sequences_test_seq', 20, 10)
178
        );
179
180
        $sequences = $this->schemaManager->listSequences();
181
182
        self::assertIsArray($sequences, 'listSequences() should return an array.');
183
184
        foreach ($sequences as $sequence) {
185
            if (strtolower($sequence->getName()) === 'list_sequences_test_seq') {
186
                self::assertSame(20, $sequence->getAllocationSize());
187
                self::assertSame(10, $sequence->getInitialValue());
188
189
                return;
190
            }
191
        }
192
193
        self::fail('Sequence was not found.');
194
    }
195
196
    public function testListDatabases() : void
197
    {
198
        if (! $this->schemaManager->getDatabasePlatform()->supportsCreateDropDatabase()) {
199
            self::markTestSkipped('Cannot drop Database client side with this Driver.');
200
        }
201
202
        $this->schemaManager->dropAndCreateDatabase('test_create_database');
203
        $databases = $this->schemaManager->listDatabases();
204
205
        $databases = array_map('strtolower', $databases);
206
207
        self::assertContains('test_create_database', $databases);
208
    }
209
210
    /**
211
     * @group DBAL-1058
212
     */
213
    public function testListNamespaceNames() : void
214
    {
215
        if (! $this->schemaManager->getDatabasePlatform()->supportsSchemas()) {
216
            self::markTestSkipped('Platform does not support schemas.');
217
        }
218
219
        // Currently dropping schemas is not supported, so we have to workaround here.
220
        $namespaces = $this->schemaManager->listNamespaceNames();
221
        $namespaces = array_map('strtolower', $namespaces);
222
223
        if (! in_array('test_create_schema', $namespaces, true)) {
224
            $this->connection->executeUpdate($this->schemaManager->getDatabasePlatform()->getCreateSchemaSQL('test_create_schema'));
225
226
            $namespaces = $this->schemaManager->listNamespaceNames();
227
            $namespaces = array_map('strtolower', $namespaces);
228
        }
229
230
        self::assertContains('test_create_schema', $namespaces);
231
    }
232
233
    public function testListTables() : void
234
    {
235
        $this->createTestTable('list_tables_test');
236
        $tables = $this->schemaManager->listTables();
237
238
        self::assertIsArray($tables);
239
        self::assertTrue(count($tables) > 0, "List Tables has to find at least one table named 'list_tables_test'.");
240
241
        $foundTable = false;
242
        foreach ($tables as $table) {
243
            self::assertInstanceOf(Table::class, $table);
244
            if (strtolower($table->getName()) !== 'list_tables_test') {
245
                continue;
246
            }
247
248
            $foundTable = true;
249
250
            self::assertTrue($table->hasColumn('id'));
251
            self::assertTrue($table->hasColumn('test'));
252
            self::assertTrue($table->hasColumn('foreign_key_test'));
253
        }
254
255
        self::assertTrue($foundTable, "The 'list_tables_test' table has to be found.");
256
    }
257
258
    public function createListTableColumns() : Table
259
    {
260
        $table = new Table('list_table_columns');
261
        $table->addColumn('id', 'integer', ['notnull' => true]);
262
        $table->addColumn('test', 'string', ['length' => 255, 'notnull' => false, 'default' => 'expected default']);
263
        $table->addColumn('foo', 'text', ['notnull' => true]);
264
        $table->addColumn('bar', 'decimal', ['precision' => 10, 'scale' => 4, 'notnull' => false]);
265
        $table->addColumn('baz1', 'datetime');
266
        $table->addColumn('baz2', 'time');
267
        $table->addColumn('baz3', 'date');
268
        $table->setPrimaryKey(['id']);
269
270
        return $table;
271
    }
272
273
    public function testListTableColumns() : void
274
    {
275
        $table = $this->createListTableColumns();
276
277
        $this->schemaManager->dropAndCreateTable($table);
278
279
        $columns     = $this->schemaManager->listTableColumns('list_table_columns');
280
        $columnsKeys = array_keys($columns);
281
282
        self::assertArrayHasKey('id', $columns);
283
        self::assertEquals(0, array_search('id', $columnsKeys, true));
284
        self::assertEquals('id', strtolower($columns['id']->getName()));
285
        self::assertInstanceOf(IntegerType::class, $columns['id']->getType());
286
        self::assertEquals(false, $columns['id']->getUnsigned());
287
        self::assertEquals(true, $columns['id']->getNotnull());
288
        self::assertEquals(null, $columns['id']->getDefault());
289
        self::assertIsArray($columns['id']->getPlatformOptions());
290
291
        self::assertArrayHasKey('test', $columns);
292
        self::assertEquals(1, array_search('test', $columnsKeys, true));
293
        self::assertEquals('test', strtolower($columns['test']->getname()));
294
        self::assertInstanceOf(StringType::class, $columns['test']->gettype());
295
        self::assertEquals(255, $columns['test']->getlength());
296
        self::assertEquals(false, $columns['test']->getfixed());
297
        self::assertEquals(false, $columns['test']->getnotnull());
298
        self::assertEquals('expected default', $columns['test']->getdefault());
299
        self::assertIsArray($columns['test']->getPlatformOptions());
300
301
        self::assertEquals('foo', strtolower($columns['foo']->getname()));
302
        self::assertEquals(2, array_search('foo', $columnsKeys, true));
303
        self::assertInstanceOf(TextType::class, $columns['foo']->gettype());
304
        self::assertEquals(false, $columns['foo']->getunsigned());
305
        self::assertEquals(false, $columns['foo']->getfixed());
306
        self::assertEquals(true, $columns['foo']->getnotnull());
307
        self::assertEquals(null, $columns['foo']->getdefault());
308
        self::assertIsArray($columns['foo']->getPlatformOptions());
309
310
        self::assertEquals('bar', strtolower($columns['bar']->getname()));
311
        self::assertEquals(3, array_search('bar', $columnsKeys, true));
312
        self::assertInstanceOf(DecimalType::class, $columns['bar']->gettype());
313
        self::assertEquals(null, $columns['bar']->getlength());
314
        self::assertEquals(10, $columns['bar']->getprecision());
315
        self::assertEquals(4, $columns['bar']->getscale());
316
        self::assertEquals(false, $columns['bar']->getunsigned());
317
        self::assertEquals(false, $columns['bar']->getfixed());
318
        self::assertEquals(false, $columns['bar']->getnotnull());
319
        self::assertEquals(null, $columns['bar']->getdefault());
320
        self::assertIsArray($columns['bar']->getPlatformOptions());
321
322
        self::assertEquals('baz1', strtolower($columns['baz1']->getname()));
323
        self::assertEquals(4, array_search('baz1', $columnsKeys, true));
324
        self::assertInstanceOf(DateTimeType::class, $columns['baz1']->gettype());
325
        self::assertEquals(true, $columns['baz1']->getnotnull());
326
        self::assertEquals(null, $columns['baz1']->getdefault());
327
        self::assertIsArray($columns['baz1']->getPlatformOptions());
328
329
        self::assertEquals('baz2', strtolower($columns['baz2']->getname()));
330
        self::assertEquals(5, array_search('baz2', $columnsKeys, true));
331
        self::assertContains($columns['baz2']->gettype()->getName(), ['time', 'date', 'datetime']);
332
        self::assertEquals(true, $columns['baz2']->getnotnull());
333
        self::assertEquals(null, $columns['baz2']->getdefault());
334
        self::assertIsArray($columns['baz2']->getPlatformOptions());
335
336
        self::assertEquals('baz3', strtolower($columns['baz3']->getname()));
337
        self::assertEquals(6, array_search('baz3', $columnsKeys, true));
338
        self::assertContains($columns['baz3']->gettype()->getName(), ['time', 'date', 'datetime']);
339
        self::assertEquals(true, $columns['baz3']->getnotnull());
340
        self::assertEquals(null, $columns['baz3']->getdefault());
341
        self::assertIsArray($columns['baz3']->getPlatformOptions());
342
    }
343
344
    /**
345
     * @group DBAL-1078
346
     */
347
    public function testListTableColumnsWithFixedStringColumn() : void
348
    {
349
        $tableName = 'test_list_table_fixed_string';
350
351
        $table = new Table($tableName);
352
        $table->addColumn('column_char', 'string', ['fixed' => true, 'length' => 2]);
353
354
        $this->schemaManager->createTable($table);
355
356
        $columns = $this->schemaManager->listTableColumns($tableName);
357
358
        self::assertArrayHasKey('column_char', $columns);
359
        self::assertInstanceOf(StringType::class, $columns['column_char']->getType());
360
        self::assertTrue($columns['column_char']->getFixed());
361
        self::assertSame(2, $columns['column_char']->getLength());
362
    }
363
364
    public function testListTableColumnsDispatchEvent() : void
365
    {
366
        $table = $this->createListTableColumns();
367
368
        $this->schemaManager->dropAndCreateTable($table);
369
370
        $listenerMock = $this->getMockBuilder($this->getMockClass('ListTableColumnsDispatchEventListener'))
371
            ->addMethods(['onSchemaColumnDefinition'])
372
            ->getMock();
373
374
        $listenerMock
375
            ->expects(self::exactly(7))
376
            ->method('onSchemaColumnDefinition');
377
378
        $oldEventManager = $this->schemaManager->getDatabasePlatform()->getEventManager();
379
380
        $eventManager = new EventManager();
381
        $eventManager->addEventListener([Events::onSchemaColumnDefinition], $listenerMock);
382
383
        $this->schemaManager->getDatabasePlatform()->setEventManager($eventManager);
384
385
        $this->schemaManager->listTableColumns('list_table_columns');
386
387
        $this->schemaManager->getDatabasePlatform()->setEventManager($oldEventManager);
388
    }
389
390
    public function testListTableIndexesDispatchEvent() : void
391
    {
392
        $table = $this->getTestTable('list_table_indexes_test');
393
        $table->addUniqueIndex(['test'], 'test_index_name');
394
        $table->addIndex(['id', 'test'], 'test_composite_idx');
395
396
        $this->schemaManager->dropAndCreateTable($table);
397
398
        $listenerMock = $this->getMockBuilder($this->getMockClass('ListTableIndexesDispatchEventListener'))
399
            ->addMethods(['onSchemaIndexDefinition'])
400
            ->getMock();
401
        $listenerMock
402
            ->expects(self::exactly(3))
403
            ->method('onSchemaIndexDefinition');
404
405
        $oldEventManager = $this->schemaManager->getDatabasePlatform()->getEventManager();
406
407
        $eventManager = new EventManager();
408
        $eventManager->addEventListener([Events::onSchemaIndexDefinition], $listenerMock);
409
410
        $this->schemaManager->getDatabasePlatform()->setEventManager($eventManager);
411
412
        $this->schemaManager->listTableIndexes('list_table_indexes_test');
413
414
        $this->schemaManager->getDatabasePlatform()->setEventManager($oldEventManager);
415
    }
416
417
    public function testDiffListTableColumns() : void
418
    {
419
        if ($this->schemaManager->getDatabasePlatform()->getName() === 'oracle') {
420
            self::markTestSkipped('Does not work with Oracle, since it cannot detect DateTime, Date and Time differenecs (at the moment).');
421
        }
422
423
        $offlineTable = $this->createListTableColumns();
424
        $this->schemaManager->dropAndCreateTable($offlineTable);
425
        $onlineTable = $this->schemaManager->listTableDetails('list_table_columns');
426
427
        $comparator = new Comparator();
428
        $diff       = $comparator->diffTable($offlineTable, $onlineTable);
429
430
        self::assertFalse($diff, 'No differences should be detected with the offline vs online schema.');
431
    }
432
433
    public function testListTableIndexes() : void
434
    {
435
        $table = $this->getTestCompositeTable('list_table_indexes_test');
436
        $table->addUniqueIndex(['test'], 'test_index_name');
437
        $table->addIndex(['id', 'test'], 'test_composite_idx');
438
439
        $this->schemaManager->dropAndCreateTable($table);
440
441
        $tableIndexes = $this->schemaManager->listTableIndexes('list_table_indexes_test');
442
443
        self::assertEquals(3, count($tableIndexes));
444
445
        self::assertArrayHasKey('primary', $tableIndexes, 'listTableIndexes() has to return a "primary" array key.');
446
        self::assertEquals(['id', 'other_id'], array_map('strtolower', $tableIndexes['primary']->getColumns()));
447
        self::assertTrue($tableIndexes['primary']->isUnique());
448
        self::assertTrue($tableIndexes['primary']->isPrimary());
449
450
        self::assertEquals('test_index_name', strtolower($tableIndexes['test_index_name']->getName()));
451
        self::assertEquals(['test'], array_map('strtolower', $tableIndexes['test_index_name']->getColumns()));
452
        self::assertTrue($tableIndexes['test_index_name']->isUnique());
453
        self::assertFalse($tableIndexes['test_index_name']->isPrimary());
454
455
        self::assertEquals('test_composite_idx', strtolower($tableIndexes['test_composite_idx']->getName()));
456
        self::assertEquals(['id', 'test'], array_map('strtolower', $tableIndexes['test_composite_idx']->getColumns()));
457
        self::assertFalse($tableIndexes['test_composite_idx']->isUnique());
458
        self::assertFalse($tableIndexes['test_composite_idx']->isPrimary());
459
    }
460
461
    public function testDropAndCreateIndex() : void
462
    {
463
        $table = $this->getTestTable('test_create_index');
464
        $table->addUniqueIndex(['test'], 'test');
465
        $this->schemaManager->dropAndCreateTable($table);
466
467
        $this->schemaManager->dropAndCreateIndex($table->getIndex('test'), $table);
468
        $tableIndexes = $this->schemaManager->listTableIndexes('test_create_index');
469
        self::assertIsArray($tableIndexes);
470
471
        self::assertEquals('test', strtolower($tableIndexes['test']->getName()));
472
        self::assertEquals(['test'], array_map('strtolower', $tableIndexes['test']->getColumns()));
473
        self::assertTrue($tableIndexes['test']->isUnique());
474
        self::assertFalse($tableIndexes['test']->isPrimary());
475
    }
476
477
    public function testCreateTableWithForeignKeys() : void
478
    {
479
        if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) {
480
            self::markTestSkipped('Platform does not support foreign keys.');
481
        }
482
483
        $tableB = $this->getTestTable('test_foreign');
484
485
        $this->schemaManager->dropAndCreateTable($tableB);
486
487
        $tableA = $this->getTestTable('test_create_fk');
488
        $tableA->addForeignKeyConstraint('test_foreign', ['foreign_key_test'], ['id']);
489
490
        $this->schemaManager->dropAndCreateTable($tableA);
491
492
        $fkTable       = $this->schemaManager->listTableDetails('test_create_fk');
493
        $fkConstraints = $fkTable->getForeignKeys();
494
        self::assertEquals(1, count($fkConstraints), "Table 'test_create_fk1' has to have one foreign key.");
495
496
        $fkConstraint = current($fkConstraints);
497
        self::assertInstanceOf(ForeignKeyConstraint::class, $fkConstraint);
498
        self::assertEquals('test_foreign', strtolower($fkConstraint->getForeignTableName()));
499
        self::assertEquals(['foreign_key_test'], array_map('strtolower', $fkConstraint->getColumns()));
500
        self::assertEquals(['id'], array_map('strtolower', $fkConstraint->getForeignColumns()));
501
502
        self::assertTrue($fkTable->columnsAreIndexed($fkConstraint->getColumns()), 'The columns of a foreign key constraint should always be indexed.');
503
    }
504
505
    public function testListForeignKeys() : void
506
    {
507
        if (! $this->connection->getDatabasePlatform()->supportsForeignKeyConstraints()) {
508
            self::markTestSkipped('Does not support foreign key constraints.');
509
        }
510
511
        $this->createTestTable('test_create_fk1');
512
        $this->createTestTable('test_create_fk2');
513
514
        $foreignKey = new ForeignKeyConstraint(
515
            ['foreign_key_test'],
516
            'test_create_fk2',
517
            ['id'],
518
            'foreign_key_test_fk',
519
            ['onDelete' => 'CASCADE']
520
        );
521
522
        $this->schemaManager->createForeignKey($foreignKey, 'test_create_fk1');
523
524
        $fkeys = $this->schemaManager->listTableForeignKeys('test_create_fk1');
525
526
        self::assertEquals(1, count($fkeys), "Table 'test_create_fk1' has to have one foreign key.");
527
528
        self::assertInstanceOf(ForeignKeyConstraint::class, $fkeys[0]);
529
        self::assertEquals(['foreign_key_test'], array_map('strtolower', $fkeys[0]->getLocalColumns()));
530
        self::assertEquals(['id'], array_map('strtolower', $fkeys[0]->getForeignColumns()));
531
        self::assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName()));
532
533
        if (! $fkeys[0]->hasOption('onDelete')) {
534
            return;
535
        }
536
537
        self::assertEquals('CASCADE', $fkeys[0]->getOption('onDelete'));
538
    }
539
540
    protected function getCreateExampleViewSql() : void
541
    {
542
        self::markTestSkipped('No Create Example View SQL was defined for this SchemaManager');
543
    }
544
545
    public function testCreateSchema() : void
546
    {
547
        $this->createTestTable('test_table');
548
549
        $schema = $this->schemaManager->createSchema();
550
        self::assertTrue($schema->hasTable('test_table'));
551
    }
552
553
    public function testAlterTableScenario() : void
554
    {
555
        if (! $this->schemaManager->getDatabasePlatform()->supportsAlterTable()) {
556
            self::markTestSkipped('Alter Table is not supported by this platform.');
557
        }
558
559
        $alterTable = $this->createTestTable('alter_table');
560
        $this->createTestTable('alter_table_foreign');
561
562
        $table = $this->schemaManager->listTableDetails('alter_table');
563
        self::assertTrue($table->hasColumn('id'));
564
        self::assertTrue($table->hasColumn('test'));
565
        self::assertTrue($table->hasColumn('foreign_key_test'));
566
        self::assertEquals(0, count($table->getForeignKeys()));
567
        self::assertEquals(1, count($table->getIndexes()));
568
569
        $tableDiff                         = new TableDiff('alter_table');
570
        $tableDiff->fromTable              = $alterTable;
571
        $tableDiff->addedColumns['foo']    = new Column('foo', Type::getType('integer'));
572
        $tableDiff->removedColumns['test'] = $table->getColumn('test');
573
574
        $this->schemaManager->alterTable($tableDiff);
575
576
        $table = $this->schemaManager->listTableDetails('alter_table');
577
        self::assertFalse($table->hasColumn('test'));
578
        self::assertTrue($table->hasColumn('foo'));
579
580
        $tableDiff                 = new TableDiff('alter_table');
581
        $tableDiff->fromTable      = $table;
582
        $tableDiff->addedIndexes[] = new Index('foo_idx', ['foo']);
583
584
        $this->schemaManager->alterTable($tableDiff);
585
586
        $table = $this->schemaManager->listTableDetails('alter_table');
587
        self::assertEquals(2, count($table->getIndexes()));
588
        self::assertTrue($table->hasIndex('foo_idx'));
589
        self::assertEquals(['foo'], array_map('strtolower', $table->getIndex('foo_idx')->getColumns()));
590
        self::assertFalse($table->getIndex('foo_idx')->isPrimary());
591
        self::assertFalse($table->getIndex('foo_idx')->isUnique());
592
593
        $tableDiff                   = new TableDiff('alter_table');
594
        $tableDiff->fromTable        = $table;
595
        $tableDiff->changedIndexes[] = new Index('foo_idx', ['foo', 'foreign_key_test']);
596
597
        $this->schemaManager->alterTable($tableDiff);
598
599
        $table = $this->schemaManager->listTableDetails('alter_table');
600
        self::assertEquals(2, count($table->getIndexes()));
601
        self::assertTrue($table->hasIndex('foo_idx'));
602
        self::assertEquals(['foo', 'foreign_key_test'], array_map('strtolower', $table->getIndex('foo_idx')->getColumns()));
603
604
        $tableDiff                            = new TableDiff('alter_table');
605
        $tableDiff->fromTable                 = $table;
606
        $tableDiff->renamedIndexes['foo_idx'] = new Index('bar_idx', ['foo', 'foreign_key_test']);
607
608
        $this->schemaManager->alterTable($tableDiff);
609
610
        $table = $this->schemaManager->listTableDetails('alter_table');
611
        self::assertEquals(2, count($table->getIndexes()));
612
        self::assertTrue($table->hasIndex('bar_idx'));
613
        self::assertFalse($table->hasIndex('foo_idx'));
614
        self::assertEquals(['foo', 'foreign_key_test'], array_map('strtolower', $table->getIndex('bar_idx')->getColumns()));
615
        self::assertFalse($table->getIndex('bar_idx')->isPrimary());
616
        self::assertFalse($table->getIndex('bar_idx')->isUnique());
617
618
        $tableDiff                     = new TableDiff('alter_table');
619
        $tableDiff->fromTable          = $table;
620
        $tableDiff->removedIndexes[]   = new Index('bar_idx', ['foo', 'foreign_key_test']);
621
        $fk                            = new ForeignKeyConstraint(['foreign_key_test'], 'alter_table_foreign', ['id']);
622
        $tableDiff->addedForeignKeys[] = $fk;
623
624
        $this->schemaManager->alterTable($tableDiff);
625
        $table = $this->schemaManager->listTableDetails('alter_table');
626
627
        // dont check for index size here, some platforms automatically add indexes for foreign keys.
628
        self::assertFalse($table->hasIndex('bar_idx'));
629
630
        if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) {
631
            return;
632
        }
633
634
        $fks = $table->getForeignKeys();
635
        self::assertCount(1, $fks);
636
        $foreignKey = current($fks);
637
        self::assertEquals('alter_table_foreign', strtolower($foreignKey->getForeignTableName()));
638
        self::assertEquals(['foreign_key_test'], array_map('strtolower', $foreignKey->getColumns()));
639
        self::assertEquals(['id'], array_map('strtolower', $foreignKey->getForeignColumns()));
640
    }
641
642
    public function testTableInNamespace() : void
643
    {
644
        if (! $this->schemaManager->getDatabasePlatform()->supportsSchemas()) {
645
            self::markTestSkipped('Schema definition is not supported by this platform.');
646
        }
647
648
        //create schema
649
        $diff                  = new SchemaDiff();
650
        $diff->newNamespaces[] = 'testschema';
651
652
        foreach ($diff->toSql($this->schemaManager->getDatabasePlatform()) as $sql) {
653
            $this->connection->exec($sql);
654
        }
655
656
        //test if table is create in namespace
657
        $this->createTestTable('testschema.my_table_in_namespace');
658
        self::assertContains('testschema.my_table_in_namespace', $this->schemaManager->listTableNames());
659
660
        //tables without namespace should be created in default namespace
661
        //default namespaces are ignored in table listings
662
        $this->createTestTable('my_table_not_in_namespace');
663
        self::assertContains('my_table_not_in_namespace', $this->schemaManager->listTableNames());
664
    }
665
666
    public function testCreateAndListViews() : void
667
    {
668
        if (! $this->schemaManager->getDatabasePlatform()->supportsViews()) {
669
            self::markTestSkipped('Views is not supported by this platform.');
670
        }
671
672
        $this->createTestTable('view_test_table');
673
674
        $name = 'doctrine_test_view';
675
        $sql  = 'SELECT * FROM view_test_table';
676
677
        $view = new View($name, $sql);
678
679
        $this->schemaManager->dropAndCreateView($view);
680
681
        self::assertTrue($this->hasElementWithName($this->schemaManager->listViews(), $name));
682
    }
683
684
    public function testAutoincrementDetection() : void
685
    {
686
        if (! $this->schemaManager->getDatabasePlatform()->supportsIdentityColumns()) {
687
            self::markTestSkipped('This test is only supported on platforms that have autoincrement');
688
        }
689
690
        $table = new Table('test_autoincrement');
691
        $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
692
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
693
        $table->setPrimaryKey(['id']);
694
695
        $this->schemaManager->createTable($table);
696
697
        $inferredTable = $this->schemaManager->listTableDetails('test_autoincrement');
698
        self::assertTrue($inferredTable->hasColumn('id'));
699
        self::assertTrue($inferredTable->getColumn('id')->getAutoincrement());
700
    }
701
702
    /**
703
     * @group DBAL-792
704
     */
705
    public function testAutoincrementDetectionMulticolumns() : void
706
    {
707
        if (! $this->schemaManager->getDatabasePlatform()->supportsIdentityColumns()) {
708
            self::markTestSkipped('This test is only supported on platforms that have autoincrement');
709
        }
710
711
        $table = new Table('test_not_autoincrement');
712
        $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
713
        $table->addColumn('id', 'integer');
714
        $table->addColumn('other_id', 'integer');
715
        $table->setPrimaryKey(['id', 'other_id']);
716
717
        $this->schemaManager->createTable($table);
718
719
        $inferredTable = $this->schemaManager->listTableDetails('test_not_autoincrement');
720
        self::assertTrue($inferredTable->hasColumn('id'));
721
        self::assertFalse($inferredTable->getColumn('id')->getAutoincrement());
722
    }
723
724
    /**
725
     * @group DDC-887
726
     */
727
    public function testUpdateSchemaWithForeignKeyRenaming() : void
728
    {
729
        if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) {
730
            self::markTestSkipped('This test is only supported on platforms that have foreign keys.');
731
        }
732
733
        $table = new Table('test_fk_base');
734
        $table->addColumn('id', 'integer');
735
        $table->setPrimaryKey(['id']);
736
737
        $tableFK = new Table('test_fk_rename');
738
        $tableFK->setSchemaConfig($this->schemaManager->createSchemaConfig());
739
        $tableFK->addColumn('id', 'integer');
740
        $tableFK->addColumn('fk_id', 'integer');
741
        $tableFK->setPrimaryKey(['id']);
742
        $tableFK->addIndex(['fk_id'], 'fk_idx');
743
        $tableFK->addForeignKeyConstraint('test_fk_base', ['fk_id'], ['id']);
744
745
        $this->schemaManager->createTable($table);
746
        $this->schemaManager->createTable($tableFK);
747
748
        $tableFKNew = new Table('test_fk_rename');
749
        $tableFKNew->setSchemaConfig($this->schemaManager->createSchemaConfig());
750
        $tableFKNew->addColumn('id', 'integer');
751
        $tableFKNew->addColumn('rename_fk_id', 'integer');
752
        $tableFKNew->setPrimaryKey(['id']);
753
        $tableFKNew->addIndex(['rename_fk_id'], 'fk_idx');
754
        $tableFKNew->addForeignKeyConstraint('test_fk_base', ['rename_fk_id'], ['id']);
755
756
        $c         = new Comparator();
757
        $tableDiff = $c->diffTable($tableFK, $tableFKNew);
758
759
        $this->schemaManager->alterTable($tableDiff);
0 ignored issues
show
Bug introduced by
It seems like $tableDiff can also be of type false; however, parameter $tableDiff of Doctrine\DBAL\Schema\Abs...maManager::alterTable() does only seem to accept Doctrine\DBAL\Schema\TableDiff, 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

759
        $this->schemaManager->alterTable(/** @scrutinizer ignore-type */ $tableDiff);
Loading history...
760
761
        $table       = $this->schemaManager->listTableDetails('test_fk_rename');
762
        $foreignKeys = $table->getForeignKeys();
763
764
        self::assertTrue($table->hasColumn('rename_fk_id'));
765
        self::assertCount(1, $foreignKeys);
766
        self::assertSame(['rename_fk_id'], array_map('strtolower', current($foreignKeys)->getColumns()));
767
    }
768
769
    /**
770
     * @group DBAL-1062
771
     */
772
    public function testRenameIndexUsedInForeignKeyConstraint() : void
773
    {
774
        if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) {
775
            self::markTestSkipped('This test is only supported on platforms that have foreign keys.');
776
        }
777
778
        $primaryTable = new Table('test_rename_index_primary');
779
        $primaryTable->addColumn('id', 'integer');
780
        $primaryTable->setPrimaryKey(['id']);
781
782
        $foreignTable = new Table('test_rename_index_foreign');
783
        $foreignTable->addColumn('fk', 'integer');
784
        $foreignTable->addIndex(['fk'], 'rename_index_fk_idx');
785
        $foreignTable->addForeignKeyConstraint(
786
            'test_rename_index_primary',
787
            ['fk'],
788
            ['id'],
789
            [],
790
            'fk_constraint'
791
        );
792
793
        $this->schemaManager->dropAndCreateTable($primaryTable);
794
        $this->schemaManager->dropAndCreateTable($foreignTable);
795
796
        $foreignTable2 = clone $foreignTable;
797
        $foreignTable2->renameIndex('rename_index_fk_idx', 'renamed_index_fk_idx');
798
799
        $comparator = new Comparator();
800
801
        $this->schemaManager->alterTable($comparator->diffTable($foreignTable, $foreignTable2));
0 ignored issues
show
Bug introduced by
It seems like $comparator->diffTable($...nTable, $foreignTable2) can also be of type false; however, parameter $tableDiff of Doctrine\DBAL\Schema\Abs...maManager::alterTable() does only seem to accept Doctrine\DBAL\Schema\TableDiff, 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

801
        $this->schemaManager->alterTable(/** @scrutinizer ignore-type */ $comparator->diffTable($foreignTable, $foreignTable2));
Loading history...
802
803
        $foreignTable = $this->schemaManager->listTableDetails('test_rename_index_foreign');
804
805
        self::assertFalse($foreignTable->hasIndex('rename_index_fk_idx'));
806
        self::assertTrue($foreignTable->hasIndex('renamed_index_fk_idx'));
807
        self::assertTrue($foreignTable->hasForeignKey('fk_constraint'));
808
    }
809
810
    /**
811
     * @group DBAL-42
812
     */
813
    public function testGetColumnComment() : void
814
    {
815
        if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() &&
816
             ! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() &&
817
            $this->connection->getDatabasePlatform()->getName() !== 'mssql') {
818
            self::markTestSkipped('Database does not support column comments.');
819
        }
820
821
        $table = new Table('column_comment_test');
822
        $table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
823
        $table->setPrimaryKey(['id']);
824
825
        $this->schemaManager->createTable($table);
826
827
        $columns = $this->schemaManager->listTableColumns('column_comment_test');
828
        self::assertEquals(1, count($columns));
829
        self::assertEquals('This is a comment', $columns['id']->getComment());
830
831
        $tableDiff                       = new TableDiff('column_comment_test');
832
        $tableDiff->fromTable            = $table;
833
        $tableDiff->changedColumns['id'] = new ColumnDiff(
834
            'id',
835
            new Column(
836
                'id',
837
                Type::getType('integer')
838
            ),
839
            ['comment'],
840
            new Column(
841
                'id',
842
                Type::getType('integer'),
843
                ['comment' => 'This is a comment']
844
            )
845
        );
846
847
        $this->schemaManager->alterTable($tableDiff);
848
849
        $columns = $this->schemaManager->listTableColumns('column_comment_test');
850
        self::assertEquals(1, count($columns));
851
        self::assertEmpty($columns['id']->getComment());
852
    }
853
854
    /**
855
     * @group DBAL-42
856
     */
857
    public function testAutomaticallyAppendCommentOnMarkedColumns() : void
858
    {
859
        if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() &&
860
             ! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() &&
861
            $this->connection->getDatabasePlatform()->getName() !== 'mssql') {
862
            self::markTestSkipped('Database does not support column comments.');
863
        }
864
865
        $table = new Table('column_comment_test2');
866
        $table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
867
        $table->addColumn('obj', 'object', ['comment' => 'This is a comment']);
868
        $table->addColumn('arr', 'array', ['comment' => 'This is a comment']);
869
        $table->setPrimaryKey(['id']);
870
871
        $this->schemaManager->createTable($table);
872
873
        $columns = $this->schemaManager->listTableColumns('column_comment_test2');
874
        self::assertEquals(3, count($columns));
875
        self::assertEquals('This is a comment', $columns['id']->getComment());
876
        self::assertEquals('This is a comment', $columns['obj']->getComment(), 'The Doctrine2 Typehint should be stripped from comment.');
877
        self::assertInstanceOf(ObjectType::class, $columns['obj']->getType(), 'The Doctrine2 should be detected from comment hint.');
878
        self::assertEquals('This is a comment', $columns['arr']->getComment(), 'The Doctrine2 Typehint should be stripped from comment.');
879
        self::assertInstanceOf(ArrayType::class, $columns['arr']->getType(), 'The Doctrine2 should be detected from comment hint.');
880
    }
881
882
    /**
883
     * @group DBAL-1228
884
     */
885
    public function testCommentHintOnDateIntervalTypeColumn() : void
886
    {
887
        if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() &&
888
            ! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() &&
889
            $this->connection->getDatabasePlatform()->getName() !== 'mssql') {
890
            self::markTestSkipped('Database does not support column comments.');
891
        }
892
893
        $table = new Table('column_dateinterval_comment');
894
        $table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
895
        $table->addColumn('date_interval', 'dateinterval', ['comment' => 'This is a comment']);
896
        $table->setPrimaryKey(['id']);
897
898
        $this->schemaManager->createTable($table);
899
900
        $columns = $this->schemaManager->listTableColumns('column_dateinterval_comment');
901
        self::assertEquals(2, count($columns));
902
        self::assertEquals('This is a comment', $columns['id']->getComment());
903
        self::assertEquals('This is a comment', $columns['date_interval']->getComment(), 'The Doctrine2 Typehint should be stripped from comment.');
904
        self::assertInstanceOf(DateIntervalType::class, $columns['date_interval']->getType(), 'The Doctrine2 should be detected from comment hint.');
905
    }
906
907
    /**
908
     * @group DBAL-825
909
     */
910
    public function testChangeColumnsTypeWithDefaultValue() : void
911
    {
912
        $tableName = 'column_def_change_type';
913
        $table     = new Table($tableName);
914
915
        $table->addColumn('col_int', 'smallint', ['default' => 666]);
916
        $table->addColumn('col_string', 'string', ['default' => 'foo']);
917
918
        $this->schemaManager->dropAndCreateTable($table);
919
920
        $tableDiff                            = new TableDiff($tableName);
921
        $tableDiff->fromTable                 = $table;
922
        $tableDiff->changedColumns['col_int'] = new ColumnDiff(
923
            'col_int',
924
            new Column('col_int', Type::getType('integer'), ['default' => 666]),
925
            ['type'],
926
            new Column('col_int', Type::getType('smallint'), ['default' => 666])
927
        );
928
929
        $tableDiff->changedColumns['col_string'] = new ColumnDiff(
930
            'col_string',
931
            new Column('col_string', Type::getType('string'), ['default' => 'foo', 'fixed' => true]),
932
            ['fixed'],
933
            new Column('col_string', Type::getType('string'), ['default' => 'foo'])
934
        );
935
936
        $this->schemaManager->alterTable($tableDiff);
937
938
        $columns = $this->schemaManager->listTableColumns($tableName);
939
940
        self::assertInstanceOf(IntegerType::class, $columns['col_int']->getType());
941
        self::assertEquals(666, $columns['col_int']->getDefault());
942
943
        self::assertInstanceOf(StringType::class, $columns['col_string']->getType());
944
        self::assertEquals('foo', $columns['col_string']->getDefault());
945
    }
946
947
    /**
948
     * @group DBAL-197
949
     */
950
    public function testListTableWithBlob() : void
951
    {
952
        $table = new Table('test_blob_table');
953
        $table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
954
        $table->addColumn('binarydata', 'blob', []);
955
        $table->setPrimaryKey(['id']);
956
957
        $this->schemaManager->createTable($table);
958
959
        $created = $this->schemaManager->listTableDetails('test_blob_table');
960
961
        self::assertTrue($created->hasColumn('id'));
962
        self::assertTrue($created->hasColumn('binarydata'));
963
        self::assertTrue($created->hasPrimaryKey());
964
    }
965
966
    /**
967
     * @param mixed[] $data
968
     */
969
    protected function createTestTable(string $name = 'test_table', array $data = []) : Table
970
    {
971
        $options = $data['options'] ?? [];
972
973
        $table = $this->getTestTable($name, $options);
974
975
        $this->schemaManager->dropAndCreateTable($table);
976
977
        return $table;
978
    }
979
980
    /**
981
     * @param mixed[] $options
982
     */
983
    protected function getTestTable(string $name, array $options = []) : Table
984
    {
985
        $table = new Table($name, [], [], [], false, $options);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type integer expected by parameter $idGeneratorType of Doctrine\DBAL\Schema\Table::__construct(). ( Ignorable by Annotation )

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

985
        $table = new Table($name, [], [], [], /** @scrutinizer ignore-type */ false, $options);
Loading history...
986
        $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
987
        $table->addColumn('id', 'integer', ['notnull' => true]);
988
        $table->setPrimaryKey(['id']);
989
        $table->addColumn('test', 'string', ['length' => 255]);
990
        $table->addColumn('foreign_key_test', 'integer');
991
992
        return $table;
993
    }
994
995
    protected function getTestCompositeTable(string $name) : Table
996
    {
997
        $table = new Table($name, [], [], [], false, []);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type integer expected by parameter $idGeneratorType of Doctrine\DBAL\Schema\Table::__construct(). ( Ignorable by Annotation )

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

997
        $table = new Table($name, [], [], [], /** @scrutinizer ignore-type */ false, []);
Loading history...
998
        $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
999
        $table->addColumn('id', 'integer', ['notnull' => true]);
1000
        $table->addColumn('other_id', 'integer', ['notnull' => true]);
1001
        $table->setPrimaryKey(['id', 'other_id']);
1002
        $table->addColumn('test', 'string', ['length' => 255]);
1003
1004
        return $table;
1005
    }
1006
1007
    /**
1008
     * @param Table[] $tables
1009
     */
1010
    protected function assertHasTable(array $tables) : void
1011
    {
1012
        $foundTable = false;
1013
        foreach ($tables as $table) {
1014
            self::assertInstanceOf(Table::class, $table, 'No Table instance was found in tables array.');
1015
            if (strtolower($table->getName()) !== 'list_tables_test_new_name') {
1016
                continue;
1017
            }
1018
1019
            $foundTable = true;
1020
        }
1021
1022
        self::assertTrue($foundTable, 'Could not find new table');
1023
    }
1024
1025
    public function testListForeignKeysComposite() : void
1026
    {
1027
        if (! $this->connection->getDatabasePlatform()->supportsForeignKeyConstraints()) {
1028
            self::markTestSkipped('Does not support foreign key constraints.');
1029
        }
1030
1031
        $this->schemaManager->createTable($this->getTestTable('test_create_fk3'));
1032
        $this->schemaManager->createTable($this->getTestCompositeTable('test_create_fk4'));
1033
1034
        $foreignKey = new ForeignKeyConstraint(
1035
            ['id', 'foreign_key_test'],
1036
            'test_create_fk4',
1037
            ['id', 'other_id'],
1038
            'foreign_key_test_fk2'
1039
        );
1040
1041
        $this->schemaManager->createForeignKey($foreignKey, 'test_create_fk3');
1042
1043
        $fkeys = $this->schemaManager->listTableForeignKeys('test_create_fk3');
1044
1045
        self::assertEquals(1, count($fkeys), "Table 'test_create_fk3' has to have one foreign key.");
1046
1047
        self::assertInstanceOf(ForeignKeyConstraint::class, $fkeys[0]);
1048
        self::assertEquals(['id', 'foreign_key_test'], array_map('strtolower', $fkeys[0]->getLocalColumns()));
1049
        self::assertEquals(['id', 'other_id'], array_map('strtolower', $fkeys[0]->getForeignColumns()));
1050
    }
1051
1052
    /**
1053
     * @group DBAL-44
1054
     */
1055
    public function testColumnDefaultLifecycle() : void
1056
    {
1057
        $table = new Table('col_def_lifecycle');
1058
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
1059
        $table->addColumn('column1', 'string', ['default' => null]);
1060
        $table->addColumn('column2', 'string', ['default' => false]);
1061
        $table->addColumn('column3', 'string', ['default' => true]);
1062
        $table->addColumn('column4', 'string', ['default' => 0]);
1063
        $table->addColumn('column5', 'string', ['default' => '']);
1064
        $table->addColumn('column6', 'string', ['default' => 'def']);
1065
        $table->addColumn('column7', 'integer', ['default' => 0]);
1066
        $table->setPrimaryKey(['id']);
1067
1068
        $this->schemaManager->dropAndCreateTable($table);
1069
1070
        $columns = $this->schemaManager->listTableColumns('col_def_lifecycle');
1071
1072
        self::assertNull($columns['id']->getDefault());
1073
        self::assertNull($columns['column1']->getDefault());
1074
        self::assertSame('', $columns['column2']->getDefault());
1075
        self::assertSame('1', $columns['column3']->getDefault());
1076
        self::assertSame('0', $columns['column4']->getDefault());
1077
        self::assertSame('', $columns['column5']->getDefault());
1078
        self::assertSame('def', $columns['column6']->getDefault());
1079
        self::assertSame('0', $columns['column7']->getDefault());
1080
1081
        $diffTable = clone $table;
1082
1083
        $diffTable->changeColumn('column1', ['default' => false]);
1084
        $diffTable->changeColumn('column2', ['default' => null]);
1085
        $diffTable->changeColumn('column3', ['default' => false]);
1086
        $diffTable->changeColumn('column4', ['default' => null]);
1087
        $diffTable->changeColumn('column5', ['default' => false]);
1088
        $diffTable->changeColumn('column6', ['default' => 666]);
1089
        $diffTable->changeColumn('column7', ['default' => null]);
1090
1091
        $comparator = new Comparator();
1092
1093
        $this->schemaManager->alterTable($comparator->diffTable($table, $diffTable));
1094
1095
        $columns = $this->schemaManager->listTableColumns('col_def_lifecycle');
1096
1097
        self::assertSame('', $columns['column1']->getDefault());
1098
        self::assertNull($columns['column2']->getDefault());
1099
        self::assertSame('', $columns['column3']->getDefault());
1100
        self::assertNull($columns['column4']->getDefault());
1101
        self::assertSame('', $columns['column5']->getDefault());
1102
        self::assertSame('666', $columns['column6']->getDefault());
1103
        self::assertNull($columns['column7']->getDefault());
1104
    }
1105
1106
    public function testListTableWithBinary() : void
1107
    {
1108
        $tableName = 'test_binary_table';
1109
1110
        $table = new Table($tableName);
1111
        $table->addColumn('id', 'integer');
1112
        $table->addColumn('column_varbinary', 'binary', []);
1113
        $table->addColumn('column_binary', 'binary', ['fixed' => true]);
1114
        $table->setPrimaryKey(['id']);
1115
1116
        $this->schemaManager->createTable($table);
1117
1118
        $table = $this->schemaManager->listTableDetails($tableName);
1119
1120
        self::assertInstanceOf(BinaryType::class, $table->getColumn('column_varbinary')->getType());
1121
        self::assertFalse($table->getColumn('column_varbinary')->getFixed());
1122
1123
        self::assertInstanceOf(BinaryType::class, $table->getColumn('column_binary')->getType());
1124
        self::assertTrue($table->getColumn('column_binary')->getFixed());
1125
    }
1126
1127
    public function testListTableDetailsWithFullQualifiedTableName() : void
1128
    {
1129
        if (! $this->schemaManager->getDatabasePlatform()->supportsSchemas()) {
1130
            self::markTestSkipped('Test only works on platforms that support schemas.');
1131
        }
1132
1133
        $defaultSchemaName = $this->schemaManager->getDatabasePlatform()->getDefaultSchemaName();
1134
        $primaryTableName  = 'primary_table';
1135
        $foreignTableName  = 'foreign_table';
1136
1137
        $table = new Table($foreignTableName);
1138
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
1139
        $table->setPrimaryKey(['id']);
1140
1141
        $this->schemaManager->dropAndCreateTable($table);
1142
1143
        $table = new Table($primaryTableName);
1144
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
1145
        $table->addColumn('foo', 'integer');
1146
        $table->addColumn('bar', 'string');
1147
        $table->addForeignKeyConstraint($foreignTableName, ['foo'], ['id']);
1148
        $table->addIndex(['bar']);
1149
        $table->setPrimaryKey(['id']);
1150
1151
        $this->schemaManager->dropAndCreateTable($table);
1152
1153
        self::assertEquals(
1154
            $this->schemaManager->listTableColumns($primaryTableName),
1155
            $this->schemaManager->listTableColumns($defaultSchemaName . '.' . $primaryTableName)
1156
        );
1157
        self::assertEquals(
1158
            $this->schemaManager->listTableIndexes($primaryTableName),
1159
            $this->schemaManager->listTableIndexes($defaultSchemaName . '.' . $primaryTableName)
1160
        );
1161
        self::assertEquals(
1162
            $this->schemaManager->listTableForeignKeys($primaryTableName),
1163
            $this->schemaManager->listTableForeignKeys($defaultSchemaName . '.' . $primaryTableName)
1164
        );
1165
    }
1166
1167
    public function testCommentStringsAreQuoted() : void
1168
    {
1169
        if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() &&
1170
            ! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() &&
1171
            $this->connection->getDatabasePlatform()->getName() !== 'mssql') {
1172
            self::markTestSkipped('Database does not support column comments.');
1173
        }
1174
1175
        $table = new Table('my_table');
1176
        $table->addColumn('id', 'integer', ['comment' => "It's a comment with a quote"]);
1177
        $table->setPrimaryKey(['id']);
1178
1179
        $this->schemaManager->createTable($table);
1180
1181
        $columns = $this->schemaManager->listTableColumns('my_table');
1182
        self::assertEquals("It's a comment with a quote", $columns['id']->getComment());
1183
    }
1184
1185
    public function testCommentNotDuplicated() : void
1186
    {
1187
        if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments()) {
1188
            self::markTestSkipped('Database does not support column comments.');
1189
        }
1190
1191
        $options          = [
1192
            'type' => Type::getType('integer'),
1193
            'default' => 0,
1194
            'notnull' => true,
1195
            'comment' => 'expected+column+comment',
1196
        ];
1197
        $columnDefinition = substr($this->connection->getDatabasePlatform()->getColumnDeclarationSQL('id', $options), strlen('id') + 1);
1198
1199
        $table = new Table('my_table');
1200
        $table->addColumn('id', 'integer', ['columnDefinition' => $columnDefinition, 'comment' => 'unexpected_column_comment']);
1201
        $sql = $this->connection->getDatabasePlatform()->getCreateTableSQL($table);
1202
1203
        self::assertStringContainsString('expected+column+comment', $sql[0]);
1204
        self::assertStringNotContainsString('unexpected_column_comment', $sql[0]);
1205
    }
1206
1207
    /**
1208
     * @group DBAL-1009
1209
     * @dataProvider getAlterColumnComment
1210
     */
1211
    public function testAlterColumnComment(
1212
        ?string $comment1,
1213
        ?string $expectedComment1,
1214
        ?string $comment2,
1215
        ?string $expectedComment2
1216
    ) : void {
1217
        if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() &&
1218
            ! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() &&
1219
            $this->connection->getDatabasePlatform()->getName() !== 'mssql') {
1220
            self::markTestSkipped('Database does not support column comments.');
1221
        }
1222
1223
        $offlineTable = new Table('alter_column_comment_test');
1224
        $offlineTable->addColumn('comment1', 'integer', ['comment' => $comment1]);
1225
        $offlineTable->addColumn('comment2', 'integer', ['comment' => $comment2]);
1226
        $offlineTable->addColumn('no_comment1', 'integer');
1227
        $offlineTable->addColumn('no_comment2', 'integer');
1228
        $this->schemaManager->dropAndCreateTable($offlineTable);
1229
1230
        $onlineTable = $this->schemaManager->listTableDetails('alter_column_comment_test');
1231
1232
        self::assertSame($expectedComment1, $onlineTable->getColumn('comment1')->getComment());
1233
        self::assertSame($expectedComment2, $onlineTable->getColumn('comment2')->getComment());
1234
        self::assertNull($onlineTable->getColumn('no_comment1')->getComment());
1235
        self::assertNull($onlineTable->getColumn('no_comment2')->getComment());
1236
1237
        $onlineTable->changeColumn('comment1', ['comment' => $comment2]);
1238
        $onlineTable->changeColumn('comment2', ['comment' => $comment1]);
1239
        $onlineTable->changeColumn('no_comment1', ['comment' => $comment1]);
1240
        $onlineTable->changeColumn('no_comment2', ['comment' => $comment2]);
1241
1242
        $comparator = new Comparator();
1243
1244
        $tableDiff = $comparator->diffTable($offlineTable, $onlineTable);
1245
1246
        self::assertInstanceOf(TableDiff::class, $tableDiff);
1247
1248
        $this->schemaManager->alterTable($tableDiff);
1249
1250
        $onlineTable = $this->schemaManager->listTableDetails('alter_column_comment_test');
1251
1252
        self::assertSame($expectedComment2, $onlineTable->getColumn('comment1')->getComment());
1253
        self::assertSame($expectedComment1, $onlineTable->getColumn('comment2')->getComment());
1254
        self::assertSame($expectedComment1, $onlineTable->getColumn('no_comment1')->getComment());
1255
        self::assertSame($expectedComment2, $onlineTable->getColumn('no_comment2')->getComment());
1256
    }
1257
1258
    /**
1259
     * @return mixed[][]
1260
     */
1261
    public static function getAlterColumnComment() : iterable
1262
    {
1263
        return [
1264
            [null, null, ' ', ' '],
1265
            [null, null, '0', '0'],
1266
            [null, null, 'foo', 'foo'],
1267
1268
            ['', null, ' ', ' '],
1269
            ['', null, '0', '0'],
1270
            ['', null, 'foo', 'foo'],
1271
1272
            [' ', ' ', '0', '0'],
1273
            [' ', ' ', 'foo', 'foo'],
1274
1275
            ['0', '0', 'foo', 'foo'],
1276
        ];
1277
    }
1278
1279
    /**
1280
     * @group DBAL-1095
1281
     */
1282
    public function testDoesNotListIndexesImplicitlyCreatedByForeignKeys() : void
1283
    {
1284
        if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) {
1285
            self::markTestSkipped('This test is only supported on platforms that have foreign keys.');
1286
        }
1287
1288
        $primaryTable = new Table('test_list_index_impl_primary');
1289
        $primaryTable->addColumn('id', 'integer');
1290
        $primaryTable->setPrimaryKey(['id']);
1291
1292
        $foreignTable = new Table('test_list_index_impl_foreign');
1293
        $foreignTable->addColumn('fk1', 'integer');
1294
        $foreignTable->addColumn('fk2', 'integer');
1295
        $foreignTable->addIndex(['fk1'], 'explicit_fk1_idx');
1296
        $foreignTable->addForeignKeyConstraint('test_list_index_impl_primary', ['fk1'], ['id']);
1297
        $foreignTable->addForeignKeyConstraint('test_list_index_impl_primary', ['fk2'], ['id']);
1298
1299
        $this->schemaManager->dropAndCreateTable($primaryTable);
1300
        $this->schemaManager->dropAndCreateTable($foreignTable);
1301
1302
        $indexes = $this->schemaManager->listTableIndexes('test_list_index_impl_foreign');
1303
1304
        self::assertCount(2, $indexes);
1305
        self::assertArrayHasKey('explicit_fk1_idx', $indexes);
1306
        self::assertArrayHasKey('idx_3d6c147fdc58d6c', $indexes);
1307
    }
1308
1309
    /**
1310
     * @after
1311
     */
1312
    public function removeJsonArrayTable() : void
1313
    {
1314
        if (! $this->schemaManager->tablesExist(['json_array_test'])) {
1315
            return;
1316
        }
1317
1318
        $this->schemaManager->dropTable('json_array_test');
1319
    }
1320
1321
    /**
1322
     * @group 2782
1323
     * @group 6654
1324
     */
1325
    public function testComparatorShouldReturnFalseWhenLegacyJsonArrayColumnHasComment() : void
1326
    {
1327
        $table = new Table('json_array_test');
1328
        $table->addColumn('parameters', 'json_array');
1329
1330
        $this->schemaManager->createTable($table);
1331
1332
        $comparator = new Comparator();
1333
        $tableDiff  = $comparator->diffTable($this->schemaManager->listTableDetails('json_array_test'), $table);
1334
1335
        self::assertFalse($tableDiff);
1336
    }
1337
1338
    /**
1339
     * @group 2782
1340
     * @group 6654
1341
     */
1342
    public function testComparatorShouldModifyOnlyTheCommentWhenUpdatingFromJsonArrayTypeOnLegacyPlatforms() : void
1343
    {
1344
        if ($this->schemaManager->getDatabasePlatform()->hasNativeJsonType()) {
1345
            $this->markTestSkipped('This test is only supported on platforms that do not have native JSON type.');
1346
        }
1347
1348
        $table = new Table('json_array_test');
1349
        $table->addColumn('parameters', 'json_array');
1350
1351
        $this->schemaManager->createTable($table);
1352
1353
        $table = new Table('json_array_test');
1354
        $table->addColumn('parameters', 'json');
1355
1356
        $comparator = new Comparator();
1357
        $tableDiff  = $comparator->diffTable($this->schemaManager->listTableDetails('json_array_test'), $table);
1358
1359
        self::assertInstanceOf(TableDiff::class, $tableDiff);
1360
1361
        $changedColumn = $tableDiff->changedColumns['parameters'] ?? $tableDiff->changedColumns['PARAMETERS'];
1362
1363
        self::assertSame(['comment'], $changedColumn->changedProperties);
1364
    }
1365
1366
    /**
1367
     * @group 2782
1368
     * @group 6654
1369
     */
1370
    public function testComparatorShouldAddCommentToLegacyJsonArrayTypeThatDoesNotHaveIt() : void
1371
    {
1372
        if (! $this->schemaManager->getDatabasePlatform()->hasNativeJsonType()) {
1373
            $this->markTestSkipped('This test is only supported on platforms that have native JSON type.');
1374
        }
1375
1376
        $this->connection->executeQuery('CREATE TABLE json_array_test (parameters JSON NOT NULL)');
1377
1378
        $table = new Table('json_array_test');
1379
        $table->addColumn('parameters', 'json_array');
1380
1381
        $comparator = new Comparator();
1382
        $tableDiff  = $comparator->diffTable($this->schemaManager->listTableDetails('json_array_test'), $table);
1383
1384
        self::assertInstanceOf(TableDiff::class, $tableDiff);
1385
        self::assertSame(['comment'], $tableDiff->changedColumns['parameters']->changedProperties);
1386
    }
1387
1388
    /**
1389
     * @group 2782
1390
     * @group 6654
1391
     */
1392
    public function testComparatorShouldReturnAllChangesWhenUsingLegacyJsonArrayType() : void
1393
    {
1394
        if (! $this->schemaManager->getDatabasePlatform()->hasNativeJsonType()) {
1395
            $this->markTestSkipped('This test is only supported on platforms that have native JSON type.');
1396
        }
1397
1398
        $this->connection->executeQuery('CREATE TABLE json_array_test (parameters JSON DEFAULT NULL)');
1399
1400
        $table = new Table('json_array_test');
1401
        $table->addColumn('parameters', 'json_array');
1402
1403
        $comparator = new Comparator();
1404
        $tableDiff  = $comparator->diffTable($this->schemaManager->listTableDetails('json_array_test'), $table);
1405
1406
        self::assertInstanceOf(TableDiff::class, $tableDiff);
1407
        self::assertSame(['notnull', 'comment'], $tableDiff->changedColumns['parameters']->changedProperties);
1408
    }
1409
1410
    /**
1411
     * @group 2782
1412
     * @group 6654
1413
     */
1414
    public function testComparatorShouldReturnAllChangesWhenUsingLegacyJsonArrayTypeEvenWhenPlatformHasJsonSupport() : void
1415
    {
1416
        if (! $this->schemaManager->getDatabasePlatform()->hasNativeJsonType()) {
1417
            $this->markTestSkipped('This test is only supported on platforms that have native JSON type.');
1418
        }
1419
1420
        $this->connection->executeQuery('CREATE TABLE json_array_test (parameters JSON DEFAULT NULL)');
1421
1422
        $table = new Table('json_array_test');
1423
        $table->addColumn('parameters', 'json_array');
1424
1425
        $comparator = new Comparator();
1426
        $tableDiff  = $comparator->diffTable($this->schemaManager->listTableDetails('json_array_test'), $table);
1427
1428
        self::assertInstanceOf(TableDiff::class, $tableDiff);
1429
        self::assertSame(['notnull', 'comment'], $tableDiff->changedColumns['parameters']->changedProperties);
1430
    }
1431
1432
    /**
1433
     * @group 2782
1434
     * @group 6654
1435
     */
1436
    public function testComparatorShouldNotAddCommentToJsonTypeSinceItIsTheDefaultNow() : void
1437
    {
1438
        if (! $this->schemaManager->getDatabasePlatform()->hasNativeJsonType()) {
1439
            self::markTestSkipped('This test is only supported on platforms that have native JSON type.');
1440
        }
1441
1442
        $this->connection->executeQuery('CREATE TABLE json_test (parameters JSON NOT NULL)');
1443
1444
        $table = new Table('json_test');
1445
        $table->addColumn('parameters', 'json');
1446
1447
        $comparator = new Comparator();
1448
        $tableDiff  = $comparator->diffTable($this->schemaManager->listTableDetails('json_test'), $table);
1449
1450
        self::assertFalse($tableDiff);
1451
    }
1452
1453
    /**
1454
     * @dataProvider commentsProvider
1455
     * @group 2596
1456
     */
1457
    public function testExtractDoctrineTypeFromComment(string $comment, string $expected, string $currentType) : void
1458
    {
1459
        $result = $this->schemaManager->extractDoctrineTypeFromComment($comment, $currentType);
1460
1461
        self::assertSame($expected, $result);
1462
    }
1463
1464
    /**
1465
     * @return string[][]
1466
     */
1467
    public function commentsProvider() : array
1468
    {
1469
        $currentType = 'current type';
1470
1471
        return [
1472
            'invalid custom type comments'      => ['should.return.current.type', $currentType, $currentType],
1473
            'valid doctrine type'               => ['(DC2Type:guid)', 'guid', $currentType],
1474
            'valid with dots'                   => ['(DC2Type:type.should.return)', 'type.should.return', $currentType],
1475
            'valid with namespace'              => ['(DC2Type:Namespace\Class)', 'Namespace\Class', $currentType],
1476
            'valid with extra closing bracket'  => ['(DC2Type:should.stop)).before)', 'should.stop', $currentType],
1477
            'valid with extra opening brackets' => ['(DC2Type:should((.stop)).before)', 'should((.stop', $currentType],
1478
        ];
1479
    }
1480
1481
    public function testCreateAndListSequences() : void
1482
    {
1483
        if (! $this->schemaManager->getDatabasePlatform()->supportsSequences()) {
1484
            self::markTestSkipped('This test is only supported on platforms that support sequences.');
1485
        }
1486
1487
        $sequence1Name           = 'sequence_1';
1488
        $sequence1AllocationSize = 1;
1489
        $sequence1InitialValue   = 2;
1490
        $sequence2Name           = 'sequence_2';
1491
        $sequence2AllocationSize = 3;
1492
        $sequence2InitialValue   = 4;
1493
        $sequence1               = new Sequence($sequence1Name, $sequence1AllocationSize, $sequence1InitialValue);
1494
        $sequence2               = new Sequence($sequence2Name, $sequence2AllocationSize, $sequence2InitialValue);
1495
1496
        $this->schemaManager->createSequence($sequence1);
1497
        $this->schemaManager->createSequence($sequence2);
1498
1499
        /** @var Sequence[] $actualSequences */
1500
        $actualSequences = [];
1501
        foreach ($this->schemaManager->listSequences() as $sequence) {
1502
            $actualSequences[$sequence->getName()] = $sequence;
1503
        }
1504
1505
        $actualSequence1 = $actualSequences[$sequence1Name];
1506
        $actualSequence2 = $actualSequences[$sequence2Name];
1507
1508
        self::assertSame($sequence1Name, $actualSequence1->getName());
1509
        self::assertEquals($sequence1AllocationSize, $actualSequence1->getAllocationSize());
1510
        self::assertEquals($sequence1InitialValue, $actualSequence1->getInitialValue());
1511
1512
        self::assertSame($sequence2Name, $actualSequence2->getName());
1513
        self::assertEquals($sequence2AllocationSize, $actualSequence2->getAllocationSize());
1514
        self::assertEquals($sequence2InitialValue, $actualSequence2->getInitialValue());
1515
    }
1516
1517
    /**
1518
     * @group #3086
1519
     */
1520
    public function testComparisonWithAutoDetectedSequenceDefinition() : void
1521
    {
1522
        if (! $this->schemaManager->getDatabasePlatform()->supportsSequences()) {
1523
            self::markTestSkipped('This test is only supported on platforms that support sequences.');
1524
        }
1525
1526
        $sequenceName           = 'sequence_auto_detect_test';
1527
        $sequenceAllocationSize = 5;
1528
        $sequenceInitialValue   = 10;
1529
        $sequence               = new Sequence($sequenceName, $sequenceAllocationSize, $sequenceInitialValue);
1530
1531
        $this->schemaManager->dropAndCreateSequence($sequence);
1532
1533
        $createdSequence = array_values(
1534
            array_filter(
1535
                $this->schemaManager->listSequences(),
1536
                static function (Sequence $sequence) use ($sequenceName) : bool {
1537
                    return strcasecmp($sequence->getName(), $sequenceName) === 0;
1538
                }
1539
            )
1540
        )[0] ?? null;
1541
1542
        self::assertNotNull($createdSequence);
1543
1544
        $comparator = new Comparator();
1545
        $tableDiff  = $comparator->diffSequence($createdSequence, $sequence);
1546
1547
        self::assertFalse($tableDiff);
1548
    }
1549
1550
    /**
1551
     * @group DBAL-2921
1552
     */
1553
    public function testPrimaryKeyAutoIncrement() : void
1554
    {
1555
        $table = new Table('test_pk_auto_increment');
1556
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
1557
        $table->addColumn('text', 'string');
1558
        $table->setPrimaryKey(['id']);
1559
        $this->schemaManager->dropAndCreateTable($table);
1560
1561
        $this->connection->insert('test_pk_auto_increment', ['text' => '1']);
1562
1563
        $query = $this->connection->query('SELECT id FROM test_pk_auto_increment WHERE text = \'1\'');
1564
        $query->execute();
0 ignored issues
show
Bug introduced by
The method execute() does not exist on Doctrine\DBAL\Driver\ResultStatement. It seems like you code against a sub-type of Doctrine\DBAL\Driver\ResultStatement such as Doctrine\DBAL\Driver\Statement. ( Ignorable by Annotation )

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

1564
        $query->/** @scrutinizer ignore-call */ 
1565
                execute();
Loading history...
1565
        $lastUsedIdBeforeDelete = (int) $query->fetchColumn();
1566
1567
        $this->connection->query('DELETE FROM test_pk_auto_increment');
1568
1569
        $this->connection->insert('test_pk_auto_increment', ['text' => '2']);
1570
1571
        $query = $this->connection->query('SELECT id FROM test_pk_auto_increment WHERE text = \'2\'');
1572
        $query->execute();
1573
        $lastUsedIdAfterDelete = (int) $query->fetchColumn();
1574
1575
        self::assertGreaterThan($lastUsedIdBeforeDelete, $lastUsedIdAfterDelete);
1576
    }
1577
1578
    public function testGenerateAnIndexWithPartialColumnLength() : void
1579
    {
1580
        if (! $this->schemaManager->getDatabasePlatform()->supportsColumnLengthIndexes()) {
1581
            self::markTestSkipped('This test is only supported on platforms that support indexes with column length definitions.');
1582
        }
1583
1584
        $table = new Table('test_partial_column_index');
1585
        $table->addColumn('long_column', 'string', ['length' => 40]);
1586
        $table->addColumn('standard_column', 'integer');
1587
        $table->addIndex(['long_column'], 'partial_long_column_idx', [], ['lengths' => [4]]);
1588
        $table->addIndex(['standard_column', 'long_column'], 'standard_and_partial_idx', [], ['lengths' => [null, 2]]);
1589
1590
        $expected = $table->getIndexes();
1591
1592
        $this->schemaManager->dropAndCreateTable($table);
1593
1594
        $onlineTable = $this->schemaManager->listTableDetails('test_partial_column_index');
1595
        self::assertEquals($expected, $onlineTable->getIndexes());
1596
    }
1597
1598
    public function testCommentInTable() : void
1599
    {
1600
        $table = new Table('table_with_comment');
1601
        $table->addColumn('id', 'integer');
1602
        $table->setComment('Foo with control characters \'\\');
1603
        $this->schemaManager->dropAndCreateTable($table);
1604
1605
        $table = $this->schemaManager->listTableDetails('table_with_comment');
1606
        self::assertSame('Foo with control characters \'\\', $table->getComment());
1607
    }
1608
1609
    public function testSchemaDiffForeignKeys() : void
1610
    {
1611
        $schemaManager = $this->connection->getSchemaManager();
1612
        $platform      = $this->connection->getDatabasePlatform();
1613
1614
        $table1 = new Table('child');
1615
        $table1->addColumn('id', 'integer', ['autoincrement' => true]);
1616
        $table1->addColumn('parent_id', 'integer');
1617
        $table1->setPrimaryKey(['id']);
1618
        $table1->addForeignKeyConstraint('parent', ['parent_id'], ['id']);
1619
1620
        $table2 = new Table('parent');
1621
        $table2->addColumn('id', 'integer', ['autoincrement' => true]);
1622
        $table2->setPrimaryKey(['id']);
1623
1624
        $diff = new SchemaDiff([$table1, $table2]);
1625
        $sqls = $diff->toSql($platform);
1626
1627
        foreach ($sqls as $sql) {
1628
            $this->connection->exec($sql);
1629
        }
1630
1631
        $schema = new Schema([
1632
            $schemaManager->listTableDetails('child'),
1633
            $schemaManager->listTableDetails('parent'),
1634
        ]);
1635
1636
        $this->assertCount(1, $schema->getTable('child')->getForeignKeys());
1637
1638
        $offlineSchema = new Schema([$table1, $table2]);
1639
1640
        $diff = Comparator::compareSchemas($offlineSchema, $schema);
1641
1642
        foreach ($diff->changedTables as $table) {
1643
            if (count($table->changedForeignKeys) <= 0 && count($table->addedForeignKeys) <= 0 && count($table->removedForeignKeys) <= 0) {
1644
                continue;
1645
            }
1646
1647
            $this->fail(
1648
                'No changes on foreigh keys should be detected, but we have: ' .
1649
                implode(', ', $diff->toSql($platform))
1650
            );
1651
        }
1652
    }
1653
}
1654