Completed
Pull Request — 2.10.x (#3936)
by Asmir
65:42
created

testNamedPrimaryKeys()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 17
c 1
b 0
f 1
dl 0
loc 26
rs 9.7
cc 2
nc 2
nop 0
1
<?php
2
3
namespace Doctrine\Tests\DBAL\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\SchemaDiff;
18
use Doctrine\DBAL\Schema\Sequence;
19
use Doctrine\DBAL\Schema\Table;
20
use Doctrine\DBAL\Schema\TableDiff;
21
use Doctrine\DBAL\Schema\View;
22
use Doctrine\DBAL\Types\ArrayType;
23
use Doctrine\DBAL\Types\BinaryType;
24
use Doctrine\DBAL\Types\DateIntervalType;
25
use Doctrine\DBAL\Types\DateTimeType;
26
use Doctrine\DBAL\Types\DecimalType;
27
use Doctrine\DBAL\Types\IntegerType;
28
use Doctrine\DBAL\Types\ObjectType;
29
use Doctrine\DBAL\Types\StringType;
30
use Doctrine\DBAL\Types\TextType;
31
use Doctrine\DBAL\Types\Type;
32
use Doctrine\Tests\DbalFunctionalTestCase;
33
use function array_filter;
34
use function array_keys;
35
use function array_map;
36
use function array_search;
37
use function array_values;
38
use function count;
39
use function current;
40
use function end;
41
use function explode;
42
use function in_array;
43
use function sprintf;
44
use function str_replace;
45
use function strcasecmp;
46
use function strlen;
47
use function strtolower;
48
use function substr;
49
50
abstract class SchemaManagerFunctionalTestCase extends DbalFunctionalTestCase
51
{
52
    /** @var AbstractSchemaManager */
53
    protected $schemaManager;
54
55
    protected function getPlatformName() : string
56
    {
57
        $class     = static::class;
58
        $e         = explode('\\', $class);
59
        $testClass = end($e);
60
61
        return strtolower(str_replace('SchemaManagerTest', null, $testClass));
62
    }
63
64
    protected function setUp() : void
65
    {
66
        parent::setUp();
67
68
        $dbms = $this->getPlatformName();
69
70
        if ($this->connection->getDatabasePlatform()->getName() !== $dbms) {
71
            $this->markTestSkipped(static::class . ' requires the use of ' . $dbms);
72
        }
73
74
        $this->schemaManager = $this->connection->getSchemaManager();
75
    }
76
77
    protected function tearDown() : void
78
    {
79
        parent::tearDown();
80
81
        $this->schemaManager->tryMethod('dropTable', 'testschema.my_table_in_namespace');
82
83
        //TODO: SchemaDiff does not drop removed namespaces?
84
        try {
85
            //sql server versions below 2016 do not support 'IF EXISTS' so we have to catch the exception here
86
            $this->connection->exec('DROP SCHEMA testschema');
87
        } catch (DBALException $e) {
88
            return;
89
        }
90
    }
91
92
    /**
93
     * @group DBAL-1220
94
     */
95
    public function testDropsDatabaseWithActiveConnections() : void
96
    {
97
        if (! $this->schemaManager->getDatabasePlatform()->supportsCreateDropDatabase()) {
98
            $this->markTestSkipped('Cannot drop Database client side with this Driver.');
99
        }
100
101
        $this->schemaManager->dropAndCreateDatabase('test_drop_database');
102
103
        $knownDatabases = $this->schemaManager->listDatabases();
104
        if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) {
105
            self::assertContains('TEST_DROP_DATABASE', $knownDatabases);
106
        } else {
107
            self::assertContains('test_drop_database', $knownDatabases);
108
        }
109
110
        $params = $this->connection->getParams();
111
        if ($this->connection->getDatabasePlatform() instanceof OraclePlatform) {
112
            $params['user'] = 'test_drop_database';
113
        } else {
114
            $params['dbname'] = 'test_drop_database';
115
        }
116
117
        $user     = $params['user'] ?? null;
118
        $password = $params['password'] ?? null;
119
120
        $connection = $this->connection->getDriver()->connect($params, $user, $password);
121
122
        self::assertInstanceOf(Connection::class, $connection);
123
124
        $this->schemaManager->dropDatabase('test_drop_database');
125
126
        self::assertNotContains('test_drop_database', $this->schemaManager->listDatabases());
127
    }
128
129
    /**
130
     * @group DBAL-195
131
     */
132
    public function testDropAndCreateSequence() : void
133
    {
134
        $platform = $this->connection->getDatabasePlatform();
135
136
        if (! $platform->supportsSequences()) {
137
            $this->markTestSkipped(
138
                sprintf('The "%s" platform does not support sequences.', $platform->getName())
139
            );
140
        }
141
142
        $name = 'dropcreate_sequences_test_seq';
143
144
        $this->schemaManager->dropAndCreateSequence(new Sequence($name, 20, 10));
145
146
        self::assertTrue($this->hasElementWithName($this->schemaManager->listSequences(), $name));
147
    }
148
149
    /**
150
     * @param AbstractAsset[] $items
151
     */
152
    private function hasElementWithName(array $items, string $name) : bool
153
    {
154
        $filteredList = array_filter(
155
            $items,
156
            static function (AbstractAsset $item) use ($name) : bool {
157
                return $item->getShortestName($item->getNamespaceName()) === $name;
158
            }
159
        );
160
161
        return count($filteredList) === 1;
162
    }
163
164
    public function testListSequences() : void
165
    {
166
        $platform = $this->connection->getDatabasePlatform();
167
168
        if (! $platform->supportsSequences()) {
169
            $this->markTestSkipped(
170
                sprintf('The "%s" platform does not support sequences.', $platform->getName())
171
            );
172
        }
173
174
        $sequence = new Sequence('list_sequences_test_seq', 20, 10);
175
        $this->schemaManager->createSequence($sequence);
176
177
        $sequences = $this->schemaManager->listSequences();
178
179
        self::assertIsArray($sequences, 'listSequences() should return an array.');
180
181
        $foundSequence = null;
182
        foreach ($sequences as $sequence) {
183
            self::assertInstanceOf(Sequence::class, $sequence, 'Array elements of listSequences() should be Sequence instances.');
184
            if (strtolower($sequence->getName()) !== 'list_sequences_test_seq') {
185
                continue;
186
            }
187
188
            $foundSequence = $sequence;
189
        }
190
191
        self::assertNotNull($foundSequence, "Sequence with name 'list_sequences_test_seq' was not found.");
192
        self::assertSame(20, $foundSequence->getAllocationSize(), 'Allocation Size is expected to be 20.');
193
        self::assertSame(10, $foundSequence->getInitialValue(), 'Initial Value is expected to be 10.');
194
    }
195
196
    public function testListDatabases() : void
197
    {
198
        if (! $this->schemaManager->getDatabasePlatform()->supportsCreateDropDatabase()) {
199
            $this->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
            $this->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)) {
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));
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));
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));
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));
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));
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));
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));
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($this->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($this->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
            $this->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 testNamedPrimaryKeys() : void
434
    {
435
        if (! $this->schemaManager->getDatabasePlatform()->supportsNamedPrimaryConstraints()) {
436
            $this->markTestSkipped('Named primary keys are not supported on this platform.');
437
        }
438
439
        $table = new Table('test_users');
440
        $table->addColumn('id', 'integer', ['notnull' => true]);
441
        $table->addColumn('other_id', 'integer', ['notnull' => true]);
442
        $table->setPrimaryKey(['id'], 'test_users_key');
443
444
        $this->schemaManager->dropAndCreateTable($table);
445
446
        $newTable = new Table('test_users');
447
        $newTable->addColumn('id', 'integer', ['notnull' => true]);
448
        $newTable->addColumn('other_id', 'integer', ['notnull' => true]);
449
        $newTable->setPrimaryKey(['id', 'other_id'], 'another_key');
450
451
        $diff      = new Comparator();
452
        $diffTable = $diff->diffTable($table, $newTable);
453
        $this->schemaManager->alterTable($diffTable);
0 ignored issues
show
Bug introduced by
It seems like $diffTable 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

453
        $this->schemaManager->alterTable(/** @scrutinizer ignore-type */ $diffTable);
Loading history...
454
455
        $table = $this->schemaManager->listTableDetails('test_users');
456
457
        self::assertSame('another_key', $table->getPrimaryKey()->getName());
458
        self::assertSame(['id', 'other_id'], $table->getPrimaryKey()->getColumns());
459
    }
460
461
    public function testListTableIndexes() : void
462
    {
463
        $table = $this->getTestCompositeTable('list_table_indexes_test');
464
        $table->addUniqueIndex(['test'], 'test_index_name');
465
        $table->addIndex(['id', 'test'], 'test_composite_idx');
466
467
        $this->schemaManager->dropAndCreateTable($table);
468
469
        $tableIndexes = $this->schemaManager->listTableIndexes('list_table_indexes_test');
470
471
        self::assertEquals(3, count($tableIndexes));
472
473
        self::assertArrayHasKey('primary', $tableIndexes, 'listTableIndexes() has to return a "primary" array key.');
474
        self::assertEquals(['id', 'other_id'], array_map('strtolower', $tableIndexes['primary']->getColumns()));
475
        self::assertTrue($tableIndexes['primary']->isUnique());
476
        self::assertTrue($tableIndexes['primary']->isPrimary());
477
478
        self::assertEquals('test_index_name', strtolower($tableIndexes['test_index_name']->getName()));
479
        self::assertEquals(['test'], array_map('strtolower', $tableIndexes['test_index_name']->getColumns()));
480
        self::assertTrue($tableIndexes['test_index_name']->isUnique());
481
        self::assertFalse($tableIndexes['test_index_name']->isPrimary());
482
483
        self::assertEquals('test_composite_idx', strtolower($tableIndexes['test_composite_idx']->getName()));
484
        self::assertEquals(['id', 'test'], array_map('strtolower', $tableIndexes['test_composite_idx']->getColumns()));
485
        self::assertFalse($tableIndexes['test_composite_idx']->isUnique());
486
        self::assertFalse($tableIndexes['test_composite_idx']->isPrimary());
487
    }
488
489
    public function testDropAndCreateIndex() : void
490
    {
491
        $table = $this->getTestTable('test_create_index');
492
        $table->addUniqueIndex(['test'], 'test');
493
        $this->schemaManager->dropAndCreateTable($table);
494
495
        $this->schemaManager->dropAndCreateIndex($table->getIndex('test'), $table);
496
        $tableIndexes = $this->schemaManager->listTableIndexes('test_create_index');
497
        self::assertIsArray($tableIndexes);
498
499
        self::assertEquals('test', strtolower($tableIndexes['test']->getName()));
500
        self::assertEquals(['test'], array_map('strtolower', $tableIndexes['test']->getColumns()));
501
        self::assertTrue($tableIndexes['test']->isUnique());
502
        self::assertFalse($tableIndexes['test']->isPrimary());
503
    }
504
505
    public function testCreateTableWithForeignKeys() : void
506
    {
507
        if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) {
508
            $this->markTestSkipped('Platform does not support foreign keys.');
509
        }
510
511
        $tableB = $this->getTestTable('test_foreign');
512
513
        $this->schemaManager->dropAndCreateTable($tableB);
514
515
        $tableA = $this->getTestTable('test_create_fk');
516
        $tableA->addForeignKeyConstraint('test_foreign', ['foreign_key_test'], ['id']);
517
518
        $this->schemaManager->dropAndCreateTable($tableA);
519
520
        $fkTable       = $this->schemaManager->listTableDetails('test_create_fk');
521
        $fkConstraints = $fkTable->getForeignKeys();
522
        self::assertEquals(1, count($fkConstraints), "Table 'test_create_fk1' has to have one foreign key.");
523
524
        $fkConstraint = current($fkConstraints);
525
        self::assertInstanceOf(ForeignKeyConstraint::class, $fkConstraint);
526
        self::assertEquals('test_foreign', strtolower($fkConstraint->getForeignTableName()));
527
        self::assertEquals(['foreign_key_test'], array_map('strtolower', $fkConstraint->getColumns()));
528
        self::assertEquals(['id'], array_map('strtolower', $fkConstraint->getForeignColumns()));
529
530
        self::assertTrue($fkTable->columnsAreIndexed($fkConstraint->getColumns()), 'The columns of a foreign key constraint should always be indexed.');
531
    }
532
533
    public function testListForeignKeys() : void
534
    {
535
        if (! $this->connection->getDatabasePlatform()->supportsForeignKeyConstraints()) {
536
            $this->markTestSkipped('Does not support foreign key constraints.');
537
        }
538
539
        $this->createTestTable('test_create_fk1');
540
        $this->createTestTable('test_create_fk2');
541
542
        $foreignKey = new ForeignKeyConstraint(
543
            ['foreign_key_test'],
544
            'test_create_fk2',
545
            ['id'],
546
            'foreign_key_test_fk',
547
            ['onDelete' => 'CASCADE']
548
        );
549
550
        $this->schemaManager->createForeignKey($foreignKey, 'test_create_fk1');
551
552
        $fkeys = $this->schemaManager->listTableForeignKeys('test_create_fk1');
553
554
        self::assertEquals(1, count($fkeys), "Table 'test_create_fk1' has to have one foreign key.");
555
556
        self::assertInstanceOf(ForeignKeyConstraint::class, $fkeys[0]);
557
        self::assertEquals(['foreign_key_test'], array_map('strtolower', $fkeys[0]->getLocalColumns()));
558
        self::assertEquals(['id'], array_map('strtolower', $fkeys[0]->getForeignColumns()));
559
        self::assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName()));
560
561
        if (! $fkeys[0]->hasOption('onDelete')) {
562
            return;
563
        }
564
565
        self::assertEquals('CASCADE', $fkeys[0]->getOption('onDelete'));
566
    }
567
568
    protected function getCreateExampleViewSql() : void
569
    {
570
        $this->markTestSkipped('No Create Example View SQL was defined for this SchemaManager');
571
    }
572
573
    public function testCreateSchema() : void
574
    {
575
        $this->createTestTable('test_table');
576
577
        $schema = $this->schemaManager->createSchema();
578
        self::assertTrue($schema->hasTable('test_table'));
579
    }
580
581
    public function testAlterTableScenario() : void
582
    {
583
        if (! $this->schemaManager->getDatabasePlatform()->supportsAlterTable()) {
584
            $this->markTestSkipped('Alter Table is not supported by this platform.');
585
        }
586
587
        $alterTable = $this->createTestTable('alter_table');
588
        $this->createTestTable('alter_table_foreign');
589
590
        $table = $this->schemaManager->listTableDetails('alter_table');
591
        self::assertTrue($table->hasColumn('id'));
592
        self::assertTrue($table->hasColumn('test'));
593
        self::assertTrue($table->hasColumn('foreign_key_test'));
594
        self::assertEquals(0, count($table->getForeignKeys()));
595
        self::assertEquals(1, count($table->getIndexes()));
596
597
        $tableDiff                         = new TableDiff('alter_table');
598
        $tableDiff->fromTable              = $alterTable;
599
        $tableDiff->addedColumns['foo']    = new Column('foo', Type::getType('integer'));
600
        $tableDiff->removedColumns['test'] = $table->getColumn('test');
601
602
        $this->schemaManager->alterTable($tableDiff);
603
604
        $table = $this->schemaManager->listTableDetails('alter_table');
605
        self::assertFalse($table->hasColumn('test'));
606
        self::assertTrue($table->hasColumn('foo'));
607
608
        $tableDiff                 = new TableDiff('alter_table');
609
        $tableDiff->fromTable      = $table;
610
        $tableDiff->addedIndexes[] = new Index('foo_idx', ['foo']);
611
612
        $this->schemaManager->alterTable($tableDiff);
613
614
        $table = $this->schemaManager->listTableDetails('alter_table');
615
        self::assertEquals(2, count($table->getIndexes()));
616
        self::assertTrue($table->hasIndex('foo_idx'));
617
        self::assertEquals(['foo'], array_map('strtolower', $table->getIndex('foo_idx')->getColumns()));
618
        self::assertFalse($table->getIndex('foo_idx')->isPrimary());
619
        self::assertFalse($table->getIndex('foo_idx')->isUnique());
620
621
        $tableDiff                   = new TableDiff('alter_table');
622
        $tableDiff->fromTable        = $table;
623
        $tableDiff->changedIndexes[] = new Index('foo_idx', ['foo', 'foreign_key_test']);
624
625
        $this->schemaManager->alterTable($tableDiff);
626
627
        $table = $this->schemaManager->listTableDetails('alter_table');
628
        self::assertEquals(2, count($table->getIndexes()));
629
        self::assertTrue($table->hasIndex('foo_idx'));
630
        self::assertEquals(['foo', 'foreign_key_test'], array_map('strtolower', $table->getIndex('foo_idx')->getColumns()));
631
632
        $tableDiff                            = new TableDiff('alter_table');
633
        $tableDiff->fromTable                 = $table;
634
        $tableDiff->renamedIndexes['foo_idx'] = new Index('bar_idx', ['foo', 'foreign_key_test']);
635
636
        $this->schemaManager->alterTable($tableDiff);
637
638
        $table = $this->schemaManager->listTableDetails('alter_table');
639
        self::assertEquals(2, count($table->getIndexes()));
640
        self::assertTrue($table->hasIndex('bar_idx'));
641
        self::assertFalse($table->hasIndex('foo_idx'));
642
        self::assertEquals(['foo', 'foreign_key_test'], array_map('strtolower', $table->getIndex('bar_idx')->getColumns()));
643
        self::assertFalse($table->getIndex('bar_idx')->isPrimary());
644
        self::assertFalse($table->getIndex('bar_idx')->isUnique());
645
646
        $tableDiff                     = new TableDiff('alter_table');
647
        $tableDiff->fromTable          = $table;
648
        $tableDiff->removedIndexes[]   = new Index('bar_idx', ['foo', 'foreign_key_test']);
649
        $fk                            = new ForeignKeyConstraint(['foreign_key_test'], 'alter_table_foreign', ['id']);
650
        $tableDiff->addedForeignKeys[] = $fk;
651
652
        $this->schemaManager->alterTable($tableDiff);
653
        $table = $this->schemaManager->listTableDetails('alter_table');
654
655
        // dont check for index size here, some platforms automatically add indexes for foreign keys.
656
        self::assertFalse($table->hasIndex('bar_idx'));
657
658
        if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) {
659
            return;
660
        }
661
662
        $fks = $table->getForeignKeys();
663
        self::assertCount(1, $fks);
664
        $foreignKey = current($fks);
665
        self::assertEquals('alter_table_foreign', strtolower($foreignKey->getForeignTableName()));
666
        self::assertEquals(['foreign_key_test'], array_map('strtolower', $foreignKey->getColumns()));
667
        self::assertEquals(['id'], array_map('strtolower', $foreignKey->getForeignColumns()));
668
    }
669
670
    public function testTableInNamespace() : void
671
    {
672
        if (! $this->schemaManager->getDatabasePlatform()->supportsSchemas()) {
673
            $this->markTestSkipped('Schema definition is not supported by this platform.');
674
        }
675
676
        //create schema
677
        $diff                  = new SchemaDiff();
678
        $diff->newNamespaces[] = 'testschema';
679
680
        foreach ($diff->toSql($this->schemaManager->getDatabasePlatform()) as $sql) {
681
            $this->connection->exec($sql);
682
        }
683
684
        //test if table is create in namespace
685
        $this->createTestTable('testschema.my_table_in_namespace');
686
        self::assertContains('testschema.my_table_in_namespace', $this->schemaManager->listTableNames());
687
688
        //tables without namespace should be created in default namespace
689
        //default namespaces are ignored in table listings
690
        $this->createTestTable('my_table_not_in_namespace');
691
        self::assertContains('my_table_not_in_namespace', $this->schemaManager->listTableNames());
692
    }
693
694
    public function testCreateAndListViews() : void
695
    {
696
        if (! $this->schemaManager->getDatabasePlatform()->supportsViews()) {
697
            $this->markTestSkipped('Views is not supported by this platform.');
698
        }
699
700
        $this->createTestTable('view_test_table');
701
702
        $name = 'doctrine_test_view';
703
        $sql  = 'SELECT * FROM view_test_table';
704
705
        $view = new View($name, $sql);
706
707
        $this->schemaManager->dropAndCreateView($view);
708
709
        self::assertTrue($this->hasElementWithName($this->schemaManager->listViews(), $name));
710
    }
711
712
    public function testAutoincrementDetection() : void
713
    {
714
        if (! $this->schemaManager->getDatabasePlatform()->supportsIdentityColumns()) {
715
            $this->markTestSkipped('This test is only supported on platforms that have autoincrement');
716
        }
717
718
        $table = new Table('test_autoincrement');
719
        $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
720
        $table->addColumn('id', 'integer', ['autoincrement' => true]);
721
        $table->setPrimaryKey(['id']);
722
723
        $this->schemaManager->createTable($table);
724
725
        $inferredTable = $this->schemaManager->listTableDetails('test_autoincrement');
726
        self::assertTrue($inferredTable->hasColumn('id'));
727
        self::assertTrue($inferredTable->getColumn('id')->getAutoincrement());
728
    }
729
730
    /**
731
     * @group DBAL-792
732
     */
733
    public function testAutoincrementDetectionMulticolumns() : void
734
    {
735
        if (! $this->schemaManager->getDatabasePlatform()->supportsIdentityColumns()) {
736
            $this->markTestSkipped('This test is only supported on platforms that have autoincrement');
737
        }
738
739
        $table = new Table('test_not_autoincrement');
740
        $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
741
        $table->addColumn('id', 'integer');
742
        $table->addColumn('other_id', 'integer');
743
        $table->setPrimaryKey(['id', 'other_id']);
744
745
        $this->schemaManager->createTable($table);
746
747
        $inferredTable = $this->schemaManager->listTableDetails('test_not_autoincrement');
748
        self::assertTrue($inferredTable->hasColumn('id'));
749
        self::assertFalse($inferredTable->getColumn('id')->getAutoincrement());
750
    }
751
752
    /**
753
     * @group DDC-887
754
     */
755
    public function testUpdateSchemaWithForeignKeyRenaming() : void
756
    {
757
        if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) {
758
            $this->markTestSkipped('This test is only supported on platforms that have foreign keys.');
759
        }
760
761
        $table = new Table('test_fk_base');
762
        $table->addColumn('id', 'integer');
763
        $table->setPrimaryKey(['id']);
764
765
        $tableFK = new Table('test_fk_rename');
766
        $tableFK->setSchemaConfig($this->schemaManager->createSchemaConfig());
767
        $tableFK->addColumn('id', 'integer');
768
        $tableFK->addColumn('fk_id', 'integer');
769
        $tableFK->setPrimaryKey(['id']);
770
        $tableFK->addIndex(['fk_id'], 'fk_idx');
771
        $tableFK->addForeignKeyConstraint('test_fk_base', ['fk_id'], ['id']);
772
773
        $this->schemaManager->createTable($table);
774
        $this->schemaManager->createTable($tableFK);
775
776
        $tableFKNew = new Table('test_fk_rename');
777
        $tableFKNew->setSchemaConfig($this->schemaManager->createSchemaConfig());
778
        $tableFKNew->addColumn('id', 'integer');
779
        $tableFKNew->addColumn('rename_fk_id', 'integer');
780
        $tableFKNew->setPrimaryKey(['id']);
781
        $tableFKNew->addIndex(['rename_fk_id'], 'fk_idx');
782
        $tableFKNew->addForeignKeyConstraint('test_fk_base', ['rename_fk_id'], ['id']);
783
784
        $c         = new Comparator();
785
        $tableDiff = $c->diffTable($tableFK, $tableFKNew);
786
787
        $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

787
        $this->schemaManager->alterTable(/** @scrutinizer ignore-type */ $tableDiff);
Loading history...
788
789
        $table       = $this->schemaManager->listTableDetails('test_fk_rename');
790
        $foreignKeys = $table->getForeignKeys();
791
792
        self::assertTrue($table->hasColumn('rename_fk_id'));
793
        self::assertCount(1, $foreignKeys);
794
        self::assertSame(['rename_fk_id'], array_map('strtolower', current($foreignKeys)->getColumns()));
795
    }
796
797
    /**
798
     * @group DBAL-1062
799
     */
800
    public function testRenameIndexUsedInForeignKeyConstraint() : void
801
    {
802
        if (! $this->schemaManager->getDatabasePlatform()->supportsForeignKeyConstraints()) {
803
            $this->markTestSkipped('This test is only supported on platforms that have foreign keys.');
804
        }
805
806
        $primaryTable = new Table('test_rename_index_primary');
807
        $primaryTable->addColumn('id', 'integer');
808
        $primaryTable->setPrimaryKey(['id']);
809
810
        $foreignTable = new Table('test_rename_index_foreign');
811
        $foreignTable->addColumn('fk', 'integer');
812
        $foreignTable->addIndex(['fk'], 'rename_index_fk_idx');
813
        $foreignTable->addForeignKeyConstraint(
814
            'test_rename_index_primary',
815
            ['fk'],
816
            ['id'],
817
            [],
818
            'fk_constraint'
819
        );
820
821
        $this->schemaManager->dropAndCreateTable($primaryTable);
822
        $this->schemaManager->dropAndCreateTable($foreignTable);
823
824
        $foreignTable2 = clone $foreignTable;
825
        $foreignTable2->renameIndex('rename_index_fk_idx', 'renamed_index_fk_idx');
826
827
        $comparator = new Comparator();
828
829
        $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

829
        $this->schemaManager->alterTable(/** @scrutinizer ignore-type */ $comparator->diffTable($foreignTable, $foreignTable2));
Loading history...
830
831
        $foreignTable = $this->schemaManager->listTableDetails('test_rename_index_foreign');
832
833
        self::assertFalse($foreignTable->hasIndex('rename_index_fk_idx'));
834
        self::assertTrue($foreignTable->hasIndex('renamed_index_fk_idx'));
835
        self::assertTrue($foreignTable->hasForeignKey('fk_constraint'));
836
    }
837
838
    /**
839
     * @group DBAL-42
840
     */
841
    public function testGetColumnComment() : void
842
    {
843
        if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() &&
844
             ! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() &&
845
            $this->connection->getDatabasePlatform()->getName() !== 'mssql') {
846
            $this->markTestSkipped('Database does not support column comments.');
847
        }
848
849
        $table = new Table('column_comment_test');
850
        $table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
851
        $table->setPrimaryKey(['id']);
852
853
        $this->schemaManager->createTable($table);
854
855
        $columns = $this->schemaManager->listTableColumns('column_comment_test');
856
        self::assertEquals(1, count($columns));
857
        self::assertEquals('This is a comment', $columns['id']->getComment());
858
859
        $tableDiff                       = new TableDiff('column_comment_test');
860
        $tableDiff->fromTable            = $table;
861
        $tableDiff->changedColumns['id'] = new ColumnDiff(
862
            'id',
863
            new Column(
864
                'id',
865
                Type::getType('integer')
866
            ),
867
            ['comment'],
868
            new Column(
869
                'id',
870
                Type::getType('integer'),
871
                ['comment' => 'This is a comment']
872
            )
873
        );
874
875
        $this->schemaManager->alterTable($tableDiff);
876
877
        $columns = $this->schemaManager->listTableColumns('column_comment_test');
878
        self::assertEquals(1, count($columns));
879
        self::assertEmpty($columns['id']->getComment());
880
    }
881
882
    /**
883
     * @group DBAL-42
884
     */
885
    public function testAutomaticallyAppendCommentOnMarkedColumns() : void
886
    {
887
        if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() &&
888
             ! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() &&
889
            $this->connection->getDatabasePlatform()->getName() !== 'mssql') {
890
            $this->markTestSkipped('Database does not support column comments.');
891
        }
892
893
        $table = new Table('column_comment_test2');
894
        $table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
895
        $table->addColumn('obj', 'object', ['comment' => 'This is a comment']);
896
        $table->addColumn('arr', 'array', ['comment' => 'This is a comment']);
897
        $table->setPrimaryKey(['id']);
898
899
        $this->schemaManager->createTable($table);
900
901
        $columns = $this->schemaManager->listTableColumns('column_comment_test2');
902
        self::assertEquals(3, count($columns));
903
        self::assertEquals('This is a comment', $columns['id']->getComment());
904
        self::assertEquals('This is a comment', $columns['obj']->getComment(), 'The Doctrine2 Typehint should be stripped from comment.');
905
        self::assertInstanceOf(ObjectType::class, $columns['obj']->getType(), 'The Doctrine2 should be detected from comment hint.');
906
        self::assertEquals('This is a comment', $columns['arr']->getComment(), 'The Doctrine2 Typehint should be stripped from comment.');
907
        self::assertInstanceOf(ArrayType::class, $columns['arr']->getType(), 'The Doctrine2 should be detected from comment hint.');
908
    }
909
910
    /**
911
     * @group DBAL-1228
912
     */
913
    public function testCommentHintOnDateIntervalTypeColumn() : void
914
    {
915
        if (! $this->connection->getDatabasePlatform()->supportsInlineColumnComments() &&
916
            ! $this->connection->getDatabasePlatform()->supportsCommentOnStatement() &&
917
            $this->connection->getDatabasePlatform()->getName() !== 'mssql') {
918
            $this->markTestSkipped('Database does not support column comments.');
919
        }
920
921
        $table = new Table('column_dateinterval_comment');
922
        $table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
923
        $table->addColumn('date_interval', 'dateinterval', ['comment' => 'This is a comment']);
924
        $table->setPrimaryKey(['id']);
925
926
        $this->schemaManager->createTable($table);
927
928
        $columns = $this->schemaManager->listTableColumns('column_dateinterval_comment');
929
        self::assertEquals(2, count($columns));
930
        self::assertEquals('This is a comment', $columns['id']->getComment());
931
        self::assertEquals('This is a comment', $columns['date_interval']->getComment(), 'The Doctrine2 Typehint should be stripped from comment.');
932
        self::assertInstanceOf(DateIntervalType::class, $columns['date_interval']->getType(), 'The Doctrine2 should be detected from comment hint.');
933
    }
934
935
    /**
936
     * @group DBAL-825
937
     */
938
    public function testChangeColumnsTypeWithDefaultValue() : void
939
    {
940
        $tableName = 'column_def_change_type';
941
        $table     = new Table($tableName);
942
943
        $table->addColumn('col_int', 'smallint', ['default' => 666]);
944
        $table->addColumn('col_string', 'string', ['default' => 'foo']);
945
946
        $this->schemaManager->dropAndCreateTable($table);
947
948
        $tableDiff                            = new TableDiff($tableName);
949
        $tableDiff->fromTable                 = $table;
950
        $tableDiff->changedColumns['col_int'] = new ColumnDiff(
951
            'col_int',
952
            new Column('col_int', Type::getType('integer'), ['default' => 666]),
953
            ['type'],
954
            new Column('col_int', Type::getType('smallint'), ['default' => 666])
955
        );
956
957
        $tableDiff->changedColumns['col_string'] = new ColumnDiff(
958
            'col_string',
959
            new Column('col_string', Type::getType('string'), ['default' => 'foo', 'fixed' => true]),
960
            ['fixed'],
961
            new Column('col_string', Type::getType('string'), ['default' => 'foo'])
962
        );
963
964
        $this->schemaManager->alterTable($tableDiff);
965
966
        $columns = $this->schemaManager->listTableColumns($tableName);
967
968
        self::assertInstanceOf(IntegerType::class, $columns['col_int']->getType());
969
        self::assertEquals(666, $columns['col_int']->getDefault());
970
971
        self::assertInstanceOf(StringType::class, $columns['col_string']->getType());
972
        self::assertEquals('foo', $columns['col_string']->getDefault());
973
    }
974
975
    /**
976
     * @group DBAL-197
977
     */
978
    public function testListTableWithBlob() : void
979
    {
980
        $table = new Table('test_blob_table');
981
        $table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
982
        $table->addColumn('binarydata', 'blob', []);
983
        $table->setPrimaryKey(['id']);
984
985
        $this->schemaManager->createTable($table);
986
987
        $created = $this->schemaManager->listTableDetails('test_blob_table');
988
989
        self::assertTrue($created->hasColumn('id'));
990
        self::assertTrue($created->hasColumn('binarydata'));
991
        self::assertTrue($created->hasPrimaryKey());
992
    }
993
994
    /**
995
     * @param mixed[] $data
996
     */
997
    protected function createTestTable(string $name = 'test_table', array $data = []) : Table
998
    {
999
        $options = $data['options'] ?? [];
1000
1001
        $table = $this->getTestTable($name, $options);
1002
1003
        $this->schemaManager->dropAndCreateTable($table);
1004
1005
        return $table;
1006
    }
1007
1008
    /**
1009
     * @param mixed[] $options
1010
     */
1011
    protected function getTestTable(string $name, array $options = []) : Table
1012
    {
1013
        $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

1013
        $table = new Table($name, [], [], [], /** @scrutinizer ignore-type */ false, $options);
Loading history...
1014
        $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
1015
        $table->addColumn('id', 'integer', ['notnull' => true]);
1016
        $table->setPrimaryKey(['id']);
1017
        $table->addColumn('test', 'string', ['length' => 255]);
1018
        $table->addColumn('foreign_key_test', 'integer');
1019
1020
        return $table;
1021
    }
1022
1023
    protected function getTestCompositeTable(string $name) : Table
1024
    {
1025
        $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

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