Failed Conditions
Pull Request — 2.9 (#3420)
by
unknown
62:40
created

testListTableIndexesWithLength()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

1004
        $table = new Table($name, [], [], [], /** @scrutinizer ignore-type */ false, $options);
Loading history...
1005
        $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
1006
        $table->addColumn('id', 'integer', ['notnull' => true]);
1007
        $table->setPrimaryKey(['id']);
1008
        $table->addColumn('test', 'string', ['length' => 255]);
1009
        $table->addColumn('foreign_key_test', 'integer');
1010
        return $table;
1011
    }
1012
1013
    protected function getTestCompositeTable($name)
1014
    {
1015
        $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

1015
        $table = new Table($name, [], [], [], /** @scrutinizer ignore-type */ false, []);
Loading history...
1016
        $table->setSchemaConfig($this->schemaManager->createSchemaConfig());
1017
        $table->addColumn('id', 'integer', ['notnull' => true]);
1018
        $table->addColumn('other_id', 'integer', ['notnull' => true]);
1019
        $table->setPrimaryKey(['id', 'other_id']);
1020
        $table->addColumn('test', 'string', ['length' => 255]);
1021
        return $table;
1022
    }
1023
1024
    protected function assertHasTable($tables, $tableName)
0 ignored issues
show
Unused Code introduced by
The parameter $tableName is not used and could be removed. ( Ignorable by Annotation )

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

1024
    protected function assertHasTable($tables, /** @scrutinizer ignore-unused */ $tableName)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

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