PostgreSqlSchemaManagerTest.php 19.7 KB
Newer Older
1 2 3 4
<?php

namespace Doctrine\Tests\DBAL\Functional\Schema;

jeroendedauw's avatar
jeroendedauw committed
5
use Doctrine\DBAL\Platforms\AbstractPlatform;
6
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
7
use Doctrine\DBAL\Schema;
8
use Doctrine\DBAL\Schema\Comparator;
Sergei Morozov's avatar
Sergei Morozov committed
9
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
10 11
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
Sergei Morozov's avatar
Sergei Morozov committed
12 13
use Doctrine\DBAL\Types\BlobType;
use Doctrine\DBAL\Types\DecimalType;
14
use Doctrine\DBAL\Types\Type;
15 16 17 18
use function array_map;
use function array_pop;
use function count;
use function strtolower;
19

romanb's avatar
romanb committed
20
class PostgreSqlSchemaManagerTest extends SchemaManagerFunctionalTestCase
21
{
22
    protected function tearDown()
23 24
    {
        parent::tearDown();
25

Sergei Morozov's avatar
Sergei Morozov committed
26
        if (! $this->connection) {
27 28 29
            return;
        }

Sergei Morozov's avatar
Sergei Morozov committed
30
        $this->connection->getConfiguration()->setFilterSchemaAssetsExpression(null);
31
    }
32

33 34 35 36 37
    /**
     * @group DBAL-177
     */
    public function testGetSearchPath()
    {
Sergei Morozov's avatar
Sergei Morozov committed
38
        $params = $this->connection->getParams();
39

Sergei Morozov's avatar
Sergei Morozov committed
40
        $paths = $this->schemaManager->getSchemaSearchPaths();
41
        self::assertEquals([$params['user'], 'public'], $paths);
42 43
    }

44 45 46 47 48
    /**
     * @group DBAL-244
     */
    public function testGetSchemaNames()
    {
Sergei Morozov's avatar
Sergei Morozov committed
49
        $names = $this->schemaManager->getSchemaNames();
50

51
        self::assertInternalType('array', $names);
Gabriel Caruso's avatar
Gabriel Caruso committed
52
        self::assertNotEmpty($names);
53
        self::assertContains('public', $names, 'The public schema should be found.');
54 55
    }

56 57 58 59 60
    /**
     * @group DBAL-21
     */
    public function testSupportDomainTypeFallback()
    {
Sergei Morozov's avatar
Sergei Morozov committed
61
        $createDomainTypeSQL = 'CREATE DOMAIN MyMoney AS DECIMAL(18,2)';
Sergei Morozov's avatar
Sergei Morozov committed
62
        $this->connection->exec($createDomainTypeSQL);
63

Sergei Morozov's avatar
Sergei Morozov committed
64
        $createTableSQL = 'CREATE TABLE domain_type_test (id INT PRIMARY KEY, value MyMoney)';
Sergei Morozov's avatar
Sergei Morozov committed
65
        $this->connection->exec($createTableSQL);
66

Sergei Morozov's avatar
Sergei Morozov committed
67 68
        $table = $this->connection->getSchemaManager()->listTableDetails('domain_type_test');
        self::assertInstanceOf(DecimalType::class, $table->getColumn('value')->getType());
69

Sergei Morozov's avatar
Sergei Morozov committed
70 71
        Type::addType('MyMoney', MoneyType::class);
        $this->connection->getDatabasePlatform()->registerDoctrineTypeMapping('MyMoney', 'MyMoney');
72

Sergei Morozov's avatar
Sergei Morozov committed
73 74
        $table = $this->connection->getSchemaManager()->listTableDetails('domain_type_test');
        self::assertInstanceOf(MoneyType::class, $table->getColumn('value')->getType());
75
    }
76 77 78 79 80 81

    /**
     * @group DBAL-37
     */
    public function testDetectsAutoIncrement()
    {
Sergei Morozov's avatar
Sergei Morozov committed
82 83
        $autoincTable = new Table('autoinc_table');
        $column       = $autoincTable->addColumn('id', 'integer');
84
        $column->setAutoincrement(true);
Sergei Morozov's avatar
Sergei Morozov committed
85 86
        $this->schemaManager->createTable($autoincTable);
        $autoincTable = $this->schemaManager->listTableDetails('autoinc_table');
87

88
        self::assertTrue($autoincTable->getColumn('id')->getAutoincrement());
89 90 91 92 93 94 95
    }

    /**
     * @group DBAL-37
     */
    public function testAlterTableAutoIncrementAdd()
    {
Sergei Morozov's avatar
Sergei Morozov committed
96 97
        $tableFrom = new Table('autoinc_table_add');
        $column    = $tableFrom->addColumn('id', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
98 99
        $this->schemaManager->createTable($tableFrom);
        $tableFrom = $this->schemaManager->listTableDetails('autoinc_table_add');
100
        self::assertFalse($tableFrom->getColumn('id')->getAutoincrement());
101

Sergei Morozov's avatar
Sergei Morozov committed
102 103
        $tableTo = new Table('autoinc_table_add');
        $column  = $tableTo->addColumn('id', 'integer');
104 105
        $column->setAutoincrement(true);

Sergei Morozov's avatar
Sergei Morozov committed
106
        $c    = new Comparator();
107
        $diff = $c->diffTable($tableFrom, $tableTo);
Sergei Morozov's avatar
Sergei Morozov committed
108
        $sql  = $this->connection->getDatabasePlatform()->getAlterTableSQL($diff);
Sergei Morozov's avatar
Sergei Morozov committed
109 110
        self::assertEquals([
            'CREATE SEQUENCE autoinc_table_add_id_seq',
111 112
            "SELECT setval('autoinc_table_add_id_seq', (SELECT MAX(id) FROM autoinc_table_add))",
            "ALTER TABLE autoinc_table_add ALTER id SET DEFAULT nextval('autoinc_table_add_id_seq')",
Sergei Morozov's avatar
Sergei Morozov committed
113
        ], $sql);
114

Sergei Morozov's avatar
Sergei Morozov committed
115 116
        $this->schemaManager->alterTable($diff);
        $tableFinal = $this->schemaManager->listTableDetails('autoinc_table_add');
117
        self::assertTrue($tableFinal->getColumn('id')->getAutoincrement());
118 119 120 121 122 123 124
    }

    /**
     * @group DBAL-37
     */
    public function testAlterTableAutoIncrementDrop()
    {
Sergei Morozov's avatar
Sergei Morozov committed
125 126
        $tableFrom = new Table('autoinc_table_drop');
        $column    = $tableFrom->addColumn('id', 'integer');
127
        $column->setAutoincrement(true);
Sergei Morozov's avatar
Sergei Morozov committed
128 129
        $this->schemaManager->createTable($tableFrom);
        $tableFrom = $this->schemaManager->listTableDetails('autoinc_table_drop');
130
        self::assertTrue($tableFrom->getColumn('id')->getAutoincrement());
131

Sergei Morozov's avatar
Sergei Morozov committed
132 133
        $tableTo = new Table('autoinc_table_drop');
        $column  = $tableTo->addColumn('id', 'integer');
134

Sergei Morozov's avatar
Sergei Morozov committed
135
        $c    = new Comparator();
136
        $diff = $c->diffTable($tableFrom, $tableTo);
Sergei Morozov's avatar
Sergei Morozov committed
137 138
        self::assertInstanceOf(TableDiff::class, $diff, 'There should be a difference and not false being returned from the table comparison');
        self::assertEquals(['ALTER TABLE autoinc_table_drop ALTER id DROP DEFAULT'], $this->connection->getDatabasePlatform()->getAlterTableSQL($diff));
139

Sergei Morozov's avatar
Sergei Morozov committed
140 141
        $this->schemaManager->alterTable($diff);
        $tableFinal = $this->schemaManager->listTableDetails('autoinc_table_drop');
142
        self::assertFalse($tableFinal->getColumn('id')->getAutoincrement());
143
    }
144 145 146 147 148 149

    /**
     * @group DBAL-75
     */
    public function testTableWithSchema()
    {
Sergei Morozov's avatar
Sergei Morozov committed
150
        $this->connection->exec('CREATE SCHEMA nested');
151

Sergei Morozov's avatar
Sergei Morozov committed
152 153
        $nestedRelatedTable = new Table('nested.schemarelated');
        $column             = $nestedRelatedTable->addColumn('id', 'integer');
154
        $column->setAutoincrement(true);
Sergei Morozov's avatar
Sergei Morozov committed
155
        $nestedRelatedTable->setPrimaryKey(['id']);
156

Sergei Morozov's avatar
Sergei Morozov committed
157 158
        $nestedSchemaTable = new Table('nested.schematable');
        $column            = $nestedSchemaTable->addColumn('id', 'integer');
159
        $column->setAutoincrement(true);
Sergei Morozov's avatar
Sergei Morozov committed
160 161
        $nestedSchemaTable->setPrimaryKey(['id']);
        $nestedSchemaTable->addUnnamedForeignKeyConstraint($nestedRelatedTable, ['id'], ['id']);
162

Sergei Morozov's avatar
Sergei Morozov committed
163 164
        $this->schemaManager->createTable($nestedRelatedTable);
        $this->schemaManager->createTable($nestedSchemaTable);
165

Sergei Morozov's avatar
Sergei Morozov committed
166
        $tables = $this->schemaManager->listTableNames();
Sergei Morozov's avatar
Sergei Morozov committed
167
        self::assertContains('nested.schematable', $tables, 'The table should be detected with its non-public schema.');
168

Sergei Morozov's avatar
Sergei Morozov committed
169
        $nestedSchemaTable = $this->schemaManager->listTableDetails('nested.schematable');
170
        self::assertTrue($nestedSchemaTable->hasColumn('id'));
Sergei Morozov's avatar
Sergei Morozov committed
171
        self::assertEquals(['id'], $nestedSchemaTable->getPrimaryKey()->getColumns());
172 173

        $relatedFks = $nestedSchemaTable->getForeignKeys();
Gabriel Caruso's avatar
Gabriel Caruso committed
174
        self::assertCount(1, $relatedFks);
175
        $relatedFk = array_pop($relatedFks);
Sergei Morozov's avatar
Sergei Morozov committed
176
        self::assertEquals('nested.schemarelated', $relatedFk->getForeignTableName());
177
    }
178 179 180 181 182 183 184 185

    /**
     * @group DBAL-91
     * @group DBAL-88
     */
    public function testReturnQuotedAssets()
    {
        $sql = 'create table dbal91_something ( id integer  CONSTRAINT id_something PRIMARY KEY NOT NULL  ,"table"   integer );';
Sergei Morozov's avatar
Sergei Morozov committed
186
        $this->connection->exec($sql);
187 188

        $sql = 'ALTER TABLE dbal91_something ADD CONSTRAINT something_input FOREIGN KEY( "table" ) REFERENCES dbal91_something ON UPDATE CASCADE;';
Sergei Morozov's avatar
Sergei Morozov committed
189
        $this->connection->exec($sql);
190

Sergei Morozov's avatar
Sergei Morozov committed
191
        $table = $this->schemaManager->listTableDetails('dbal91_something');
192

193
        self::assertEquals(
Sergei Morozov's avatar
Sergei Morozov committed
194 195 196 197
            [
                'CREATE TABLE dbal91_something (id INT NOT NULL, "table" INT DEFAULT NULL, PRIMARY KEY(id))',
                'CREATE INDEX IDX_A9401304ECA7352B ON dbal91_something ("table")',
            ],
Sergei Morozov's avatar
Sergei Morozov committed
198
            $this->connection->getDatabasePlatform()->getCreateTableSQL($table)
199 200
        );
    }
201 202 203 204 205 206

    /**
     * @group DBAL-204
     */
    public function testFilterSchemaExpression()
    {
Sergei Morozov's avatar
Sergei Morozov committed
207 208
        $testTable = new Table('dbal204_test_prefix');
        $column    = $testTable->addColumn('id', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
209
        $this->schemaManager->createTable($testTable);
Sergei Morozov's avatar
Sergei Morozov committed
210 211
        $testTable = new Table('dbal204_without_prefix');
        $column    = $testTable->addColumn('id', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
212
        $this->schemaManager->createTable($testTable);
213

Sergei Morozov's avatar
Sergei Morozov committed
214 215
        $this->connection->getConfiguration()->setFilterSchemaAssetsExpression('#^dbal204_#');
        $names = $this->schemaManager->listTableNames();
Gabriel Caruso's avatar
Gabriel Caruso committed
216
        self::assertCount(2, $names);
217

Sergei Morozov's avatar
Sergei Morozov committed
218 219
        $this->connection->getConfiguration()->setFilterSchemaAssetsExpression('#^dbal204_test#');
        $names = $this->schemaManager->listTableNames();
Gabriel Caruso's avatar
Gabriel Caruso committed
220
        self::assertCount(1, $names);
221
    }
222 223 224

    public function testListForeignKeys()
    {
Sergei Morozov's avatar
Sergei Morozov committed
225
        if (! $this->connection->getDatabasePlatform()->supportsForeignKeyConstraints()) {
226 227 228
            $this->markTestSkipped('Does not support foreign key constraints.');
        }

Sergei Morozov's avatar
Sergei Morozov committed
229 230 231 232
        $fkOptions   = ['SET NULL', 'SET DEFAULT', 'NO ACTION','CASCADE', 'RESTRICT'];
        $foreignKeys = [];
        $fkTable     = $this->getTestTable('test_create_fk1');
        for ($i = 0; $i < count($fkOptions); $i++) {
Sergei Morozov's avatar
Sergei Morozov committed
233
            $fkTable->addColumn('foreign_key_test' . $i, 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
234
            $foreignKeys[] = new ForeignKeyConstraint(
Sergei Morozov's avatar
Sergei Morozov committed
235
                ['foreign_key_test' . $i],
Sergei Morozov's avatar
Sergei Morozov committed
236 237
                'test_create_fk2',
                ['id'],
Sergei Morozov's avatar
Sergei Morozov committed
238
                'foreign_key_test' . $i . '_fk',
Sergei Morozov's avatar
Sergei Morozov committed
239 240
                ['onDelete' => $fkOptions[$i]]
            );
241
        }
Sergei Morozov's avatar
Sergei Morozov committed
242
        $this->schemaManager->dropAndCreateTable($fkTable);
243 244
        $this->createTestTable('test_create_fk2');

Sergei Morozov's avatar
Sergei Morozov committed
245
        foreach ($foreignKeys as $foreignKey) {
Sergei Morozov's avatar
Sergei Morozov committed
246
            $this->schemaManager->createForeignKey($foreignKey, 'test_create_fk1');
247
        }
Sergei Morozov's avatar
Sergei Morozov committed
248
        $fkeys = $this->schemaManager->listTableForeignKeys('test_create_fk1');
Sergei Morozov's avatar
Sergei Morozov committed
249
        self::assertEquals(count($foreignKeys), count($fkeys), "Table 'test_create_fk1' has to have " . count($foreignKeys) . ' foreign keys.');
250
        for ($i = 0; $i < count($fkeys); $i++) {
Sergei Morozov's avatar
Sergei Morozov committed
251
            self::assertEquals(['foreign_key_test' . $i], array_map('strtolower', $fkeys[$i]->getLocalColumns()));
Sergei Morozov's avatar
Sergei Morozov committed
252
            self::assertEquals(['id'], array_map('strtolower', $fkeys[$i]->getForeignColumns()));
253
            self::assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName()));
Sergei Morozov's avatar
Sergei Morozov committed
254 255
            if ($foreignKeys[$i]->getOption('onDelete') === 'NO ACTION') {
                self::assertFalse($fkeys[$i]->hasOption('onDelete'), 'Unexpected option: ' . $fkeys[$i]->getOption('onDelete'));
256
            } else {
257
                self::assertEquals($foreignKeys[$i]->getOption('onDelete'), $fkeys[$i]->getOption('onDelete'));
258 259 260
            }
        }
    }
261 262 263 264 265 266

    /**
     * @group DBAL-511
     */
    public function testDefaultValueCharacterVarying()
    {
Sergei Morozov's avatar
Sergei Morozov committed
267
        $testTable = new Table('dbal511_default');
268
        $testTable->addColumn('id', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
269 270
        $testTable->addColumn('def', 'string', ['default' => 'foo']);
        $testTable->setPrimaryKey(['id']);
271

Sergei Morozov's avatar
Sergei Morozov committed
272
        $this->schemaManager->createTable($testTable);
273

Sergei Morozov's avatar
Sergei Morozov committed
274
        $databaseTable = $this->schemaManager->listTableDetails($testTable->getName());
275

276
        self::assertEquals('foo', $databaseTable->getColumn('def')->getDefault());
277
    }
278 279 280 281 282 283

    /**
     * @group DDC-2843
     */
    public function testBooleanDefault()
    {
Sergei Morozov's avatar
Sergei Morozov committed
284
        $table = new Table('ddc2843_bools');
285
        $table->addColumn('id', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
286
        $table->addColumn('checked', 'boolean', ['default' => false]);
287

Sergei Morozov's avatar
Sergei Morozov committed
288
        $this->schemaManager->createTable($table);
289

Sergei Morozov's avatar
Sergei Morozov committed
290
        $databaseTable = $this->schemaManager->listTableDetails($table->getName());
291

Sergei Morozov's avatar
Sergei Morozov committed
292
        $c    = new Comparator();
293 294
        $diff = $c->diffTable($table, $databaseTable);

295
        self::assertFalse($diff);
296
    }
Steve Müller's avatar
Steve Müller committed
297 298 299 300 301

    public function testListTableWithBinary()
    {
        $tableName = 'test_binary_table';

Sergei Morozov's avatar
Sergei Morozov committed
302
        $table = new Table($tableName);
Steve Müller's avatar
Steve Müller committed
303
        $table->addColumn('id', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
304 305 306
        $table->addColumn('column_varbinary', 'binary', []);
        $table->addColumn('column_binary', 'binary', ['fixed' => true]);
        $table->setPrimaryKey(['id']);
Steve Müller's avatar
Steve Müller committed
307

Sergei Morozov's avatar
Sergei Morozov committed
308
        $this->schemaManager->createTable($table);
Steve Müller's avatar
Steve Müller committed
309

Sergei Morozov's avatar
Sergei Morozov committed
310
        $table = $this->schemaManager->listTableDetails($tableName);
Steve Müller's avatar
Steve Müller committed
311

Sergei Morozov's avatar
Sergei Morozov committed
312
        self::assertInstanceOf(BlobType::class, $table->getColumn('column_varbinary')->getType());
313
        self::assertFalse($table->getColumn('column_varbinary')->getFixed());
Steve Müller's avatar
Steve Müller committed
314

Sergei Morozov's avatar
Sergei Morozov committed
315
        self::assertInstanceOf(BlobType::class, $table->getColumn('column_binary')->getType());
316
        self::assertFalse($table->getColumn('column_binary')->getFixed());
Steve Müller's avatar
Steve Müller committed
317
    }
318 319 320 321 322

    public function testListQuotedTable()
    {
        $offlineTable = new Schema\Table('user');
        $offlineTable->addColumn('id', 'integer');
323
        $offlineTable->addColumn('username', 'string');
324
        $offlineTable->addColumn('fk', 'integer');
Sergei Morozov's avatar
Sergei Morozov committed
325 326
        $offlineTable->setPrimaryKey(['id']);
        $offlineTable->addForeignKeyConstraint($offlineTable, ['fk'], ['id']);
327

Sergei Morozov's avatar
Sergei Morozov committed
328
        $this->schemaManager->dropAndCreateTable($offlineTable);
329

Sergei Morozov's avatar
Sergei Morozov committed
330
        $onlineTable = $this->schemaManager->listTableDetails('"user"');
331 332 333

        $comparator = new Schema\Comparator();

334
        self::assertFalse($comparator->diffTable($offlineTable, $onlineTable));
335
    }
336 337 338 339 340

    public function testListTablesExcludesViews()
    {
        $this->createTestTable('list_tables_excludes_views');

Sergei Morozov's avatar
Sergei Morozov committed
341 342
        $name = 'list_tables_excludes_views_test_view';
        $sql  = 'SELECT * from list_tables_excludes_views';
343 344 345

        $view = new Schema\View($name, $sql);

Sergei Morozov's avatar
Sergei Morozov committed
346
        $this->schemaManager->dropAndCreateView($view);
347

Sergei Morozov's avatar
Sergei Morozov committed
348
        $tables = $this->schemaManager->listTables();
349 350 351

        $foundTable = false;
        foreach ($tables as $table) {
Sergei Morozov's avatar
Sergei Morozov committed
352
            self::assertInstanceOf(Table::class, $table, 'No Table instance was found in tables array.');
Sergei Morozov's avatar
Sergei Morozov committed
353 354
            if (strtolower($table->getName()) !== 'list_tables_excludes_views_test_view') {
                continue;
355
            }
Sergei Morozov's avatar
Sergei Morozov committed
356 357

            $foundTable = true;
358 359
        }

360
        self::assertFalse($foundTable, 'View "list_tables_excludes_views_test_view" must not be found in table list');
361
    }
362

363 364 365
    /**
     * @group DBAL-1033
     */
366 367 368 369 370 371
    public function testPartialIndexes()
    {
        $offlineTable = new Schema\Table('person');
        $offlineTable->addColumn('id', 'integer');
        $offlineTable->addColumn('name', 'string');
        $offlineTable->addColumn('email', 'string');
Sergei Morozov's avatar
Sergei Morozov committed
372
        $offlineTable->addUniqueIndex(['id', 'name'], 'simple_partial_index', ['where' => '(id IS NULL)']);
373

Sergei Morozov's avatar
Sergei Morozov committed
374
        $this->schemaManager->dropAndCreateTable($offlineTable);
375

Sergei Morozov's avatar
Sergei Morozov committed
376
        $onlineTable = $this->schemaManager->listTableDetails('person');
377 378 379

        $comparator = new Schema\Comparator();

380 381 382 383
        self::assertFalse($comparator->diffTable($offlineTable, $onlineTable));
        self::assertTrue($onlineTable->hasIndex('simple_partial_index'));
        self::assertTrue($onlineTable->getIndex('simple_partial_index')->hasOption('where'));
        self::assertSame('(id IS NULL)', $onlineTable->getIndex('simple_partial_index')->getOption('where'));
384 385
    }

386 387 388
    /**
     * @dataProvider jsonbColumnTypeProvider
     */
Sergei Morozov's avatar
Sergei Morozov committed
389
    public function testJsonbColumn(string $type) : void
390
    {
Sergei Morozov's avatar
Sergei Morozov committed
391
        if (! $this->schemaManager->getDatabasePlatform() instanceof PostgreSQL94Platform) {
Sergei Morozov's avatar
Sergei Morozov committed
392
            $this->markTestSkipped('Requires PostgresSQL 9.4+');
393 394 395 396
            return;
        }

        $table = new Schema\Table('test_jsonb');
397
        $table->addColumn('foo', $type)->setPlatformOption('jsonb', true);
Sergei Morozov's avatar
Sergei Morozov committed
398
        $this->schemaManager->dropAndCreateTable($table);
399

Sergei Morozov's avatar
Sergei Morozov committed
400
        $columns = $this->schemaManager->listTableColumns('test_jsonb');
401

402
        self::assertSame($type, $columns['foo']->getType()->getName());
403
        self::assertTrue(true, $columns['foo']->getPlatformOption('jsonb'));
404 405
    }

Sergei Morozov's avatar
Sergei Morozov committed
406 407 408
    /**
     * @return mixed[][]
     */
Sergei Morozov's avatar
Sergei Morozov committed
409
    public function jsonbColumnTypeProvider() : array
410 411 412 413 414
    {
        return [
            [Type::JSON],
            [Type::JSON_ARRAY],
        ];
415
    }
416 417 418 419 420 421 422

    /**
     * @group DBAL-2427
     */
    public function testListNegativeColumnDefaultValue()
    {
        $table = new Schema\Table('test_default_negative');
Sergei Morozov's avatar
Sergei Morozov committed
423 424 425 426 427 428
        $table->addColumn('col_smallint', 'smallint', ['default' => -1]);
        $table->addColumn('col_integer', 'integer', ['default' => -1]);
        $table->addColumn('col_bigint', 'bigint', ['default' => -1]);
        $table->addColumn('col_float', 'float', ['default' => -1.1]);
        $table->addColumn('col_decimal', 'decimal', ['default' => -1.1]);
        $table->addColumn('col_string', 'string', ['default' => '(-1)']);
429

Sergei Morozov's avatar
Sergei Morozov committed
430
        $this->schemaManager->dropAndCreateTable($table);
431

Sergei Morozov's avatar
Sergei Morozov committed
432
        $columns = $this->schemaManager->listTableColumns('test_default_negative');
433

434 435 436 437 438 439
        self::assertEquals(-1, $columns['col_smallint']->getDefault());
        self::assertEquals(-1, $columns['col_integer']->getDefault());
        self::assertEquals(-1, $columns['col_bigint']->getDefault());
        self::assertEquals(-1.1, $columns['col_float']->getDefault());
        self::assertEquals(-1.1, $columns['col_decimal']->getDefault());
        self::assertEquals('(-1)', $columns['col_string']->getDefault());
440
    }
441

Sergei Morozov's avatar
Sergei Morozov committed
442 443 444
    /**
     * @return mixed[][]
     */
445 446 447 448 449 450 451 452 453 454 455 456 457 458
    public static function serialTypes() : array
    {
        return [
            ['integer'],
            ['bigint'],
        ];
    }

    /**
     * @dataProvider serialTypes
     * @group 2906
     */
    public function testAutoIncrementCreatesSerialDataTypesWithoutADefaultValue(string $type) : void
    {
Sergei Morozov's avatar
Sergei Morozov committed
459
        $tableName = 'test_serial_type_' . $type;
460 461 462 463

        $table = new Schema\Table($tableName);
        $table->addColumn('id', $type, ['autoincrement' => true, 'notnull' => false]);

Sergei Morozov's avatar
Sergei Morozov committed
464
        $this->schemaManager->dropAndCreateTable($table);
465

Sergei Morozov's avatar
Sergei Morozov committed
466
        $columns = $this->schemaManager->listTableColumns($tableName);
467 468 469 470 471 472 473 474 475 476

        self::assertNull($columns['id']->getDefault());
    }

    /**
     * @dataProvider serialTypes
     * @group 2906
     */
    public function testAutoIncrementCreatesSerialDataTypesWithoutADefaultValueEvenWhenDefaultIsSet(string $type) : void
    {
Sergei Morozov's avatar
Sergei Morozov committed
477
        $tableName = 'test_serial_type_with_default_' . $type;
478 479 480 481

        $table = new Schema\Table($tableName);
        $table->addColumn('id', $type, ['autoincrement' => true, 'notnull' => false, 'default' => 1]);

Sergei Morozov's avatar
Sergei Morozov committed
482
        $this->schemaManager->dropAndCreateTable($table);
483

Sergei Morozov's avatar
Sergei Morozov committed
484
        $columns = $this->schemaManager->listTableColumns($tableName);
485 486 487

        self::assertNull($columns['id']->getDefault());
    }
488 489 490 491 492 493 494 495

    /**
     * @group 2916
     * @dataProvider autoIncrementTypeMigrations
     */
    public function testAlterTableAutoIncrementIntToBigInt(string $from, string $to, string $expected) : void
    {
        $tableFrom = new Table('autoinc_type_modification');
Sergei Morozov's avatar
Sergei Morozov committed
496
        $column    = $tableFrom->addColumn('id', $from);
497
        $column->setAutoincrement(true);
Sergei Morozov's avatar
Sergei Morozov committed
498 499
        $this->schemaManager->dropAndCreateTable($tableFrom);
        $tableFrom = $this->schemaManager->listTableDetails('autoinc_type_modification');
500 501 502
        self::assertTrue($tableFrom->getColumn('id')->getAutoincrement());

        $tableTo = new Table('autoinc_type_modification');
Sergei Morozov's avatar
Sergei Morozov committed
503
        $column  = $tableTo->addColumn('id', $to);
504 505
        $column->setAutoincrement(true);

Sergei Morozov's avatar
Sergei Morozov committed
506
        $c    = new Comparator();
507
        $diff = $c->diffTable($tableFrom, $tableTo);
Sergei Morozov's avatar
Sergei Morozov committed
508
        self::assertInstanceOf(TableDiff::class, $diff, 'There should be a difference and not false being returned from the table comparison');
Sergei Morozov's avatar
Sergei Morozov committed
509
        self::assertSame(['ALTER TABLE autoinc_type_modification ALTER id TYPE ' . $expected], $this->connection->getDatabasePlatform()->getAlterTableSQL($diff));
510

Sergei Morozov's avatar
Sergei Morozov committed
511 512
        $this->schemaManager->alterTable($diff);
        $tableFinal = $this->schemaManager->listTableDetails('autoinc_type_modification');
513 514 515
        self::assertTrue($tableFinal->getColumn('id')->getAutoincrement());
    }

Sergei Morozov's avatar
Sergei Morozov committed
516 517 518
    /**
     * @return mixed[][]
     */
519 520 521 522 523 524 525
    public function autoIncrementTypeMigrations() : array
    {
        return [
            'int->bigint' => ['integer', 'bigint', 'BIGINT'],
            'bigint->int' => ['bigint', 'integer', 'INT'],
        ];
    }
526 527 528 529 530 531
}

class MoneyType extends Type
{
    public function getName()
    {
Sergei Morozov's avatar
Sergei Morozov committed
532
        return 'MyMoney';
533 534
    }

Sergei Morozov's avatar
Sergei Morozov committed
535 536 537
    /**
     * {@inheritDoc}
     */
538
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
539 540 541
    {
        return 'MyMoney';
    }
542
}