Skip to content

Commit

Permalink
Merge pull request #6820 from morozov/alter-table-integration-testing
Browse files Browse the repository at this point in the history
Convert some unit tests to integration tests
  • Loading branch information
morozov authored Mar 6, 2025
2 parents be9c119 + 90e365c commit 37ab825
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 166 deletions.
218 changes: 218 additions & 0 deletions tests/Functional/Schema/AlterTableTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Tests\Functional\Schema;

use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
use Doctrine\DBAL\Platforms\DB2Platform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use Doctrine\DBAL\Platforms\SQLServerPlatform;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Tests\FunctionalTestCase;
use Doctrine\DBAL\Types\Types;

class AlterTableTest extends FunctionalTestCase
{
public function testAddPrimaryKeyOnExistingColumn(): void
{
if ($this->connection->getDatabasePlatform() instanceof SQLitePlatform) {
self::markTestSkipped(
'SQLite will automatically set up auto-increment behavior on the primary key column, which this test'
. ' does not expect.',
);
}

$table = new Table('alter_pk');
$table->addColumn('id', Types::INTEGER);
$table->addColumn('val', Types::INTEGER);

$this->testMigration($table, static function (Table $table): void {
$table->setPrimaryKey(['id']);
});
}

public function testAddPrimaryKeyOnNewAutoIncrementColumn(): void
{
if ($this->connection->getDatabasePlatform() instanceof DB2Platform) {
self::markTestSkipped(
'IBM DB2 LUW does not support adding identity columns to an existing table.',
);
}

$table = new Table('alter_pk');
$table->addColumn('val', Types::INTEGER);

$this->testMigration($table, static function (Table $table): void {
$table->addColumn('id', Types::INTEGER, ['autoincrement' => true]);
$table->setPrimaryKey(['id']);
});
}

public function testAlterPrimaryKeyFromAutoincrementToNonAutoincrementColumn(): void
{
$platform = $this->connection->getDatabasePlatform();

if ($platform instanceof AbstractMySQLPlatform) {
self::markTestIncomplete(
'DBAL should not allow this migration on MySQL because an auto-increment column must be part of the'
. ' primary key constraint.',
);
}

if ($platform instanceof SQLitePlatform) {
self::markTestSkipped(
'SQLite does not support auto-increment columns that are not part the primary key constraint',
);
}

$this->ensureDroppingPrimaryKeyConstraintIsSupported();

$table = new Table('alter_pk');
$table->addColumn('id1', Types::INTEGER, ['autoincrement' => true]);
$table->addColumn('id2', Types::INTEGER);
$table->setPrimaryKey(['id1']);

$this->testMigration($table, static function (Table $table): void {
$table->dropPrimaryKey();
$table->setPrimaryKey(['id2']);
});
}

public function testDropPrimaryKeyWithAutoincrementColumn(): void
{
$platform = $this->connection->getDatabasePlatform();

if ($platform instanceof AbstractMySQLPlatform) {
self::markTestIncomplete(
'DBAL should not allow this migration on MySQL because an auto-increment column must be part of the'
. ' primary key constraint.',
);
}

if ($platform instanceof SQLitePlatform) {
self::markTestSkipped(
'SQLite does not support auto-increment columns as part of composite primary key constraint',
);
}

$this->ensureDroppingPrimaryKeyConstraintIsSupported();

$table = new Table('alter_pk');
$table->addColumn('id1', Types::INTEGER, ['autoincrement' => true]);
$table->addColumn('id2', Types::INTEGER);
$table->setPrimaryKey(['id1', 'id2']);

$this->testMigration($table, static function (Table $table): void {
$table->dropPrimaryKey();
});
}

public function testDropNonAutoincrementColumnFromCompositePrimaryKeyWithAutoincrementColumn(): void
{
if ($this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform) {
self::markTestIncomplete(
'DBAL does not restore the auto-increment attribute after dropping and adding the constraint,'
. ' which is a bug.',
);
}

$this->ensureDroppingPrimaryKeyConstraintIsSupported();

$table = new Table('alter_pk');
$table->addColumn('id1', Types::INTEGER, ['autoincrement' => true]);
$table->addColumn('id2', Types::INTEGER);
$table->setPrimaryKey(['id1', 'id2']);

$this->testMigration($table, static function (Table $table): void {
$table->dropPrimaryKey();
$table->setPrimaryKey(['id1']);
});
}

public function testAddNonAutoincrementColumnToPrimaryKeyWithAutoincrementColumn(): void
{
$platform = $this->connection->getDatabasePlatform();

if ($platform instanceof AbstractMySQLPlatform) {
self::markTestIncomplete(
'DBAL does not restore the auto-increment attribute after dropping and adding the constraint,'
. ' which is a bug.',
);
}

if ($platform instanceof SQLitePlatform) {
self::markTestSkipped(
'SQLite does not support auto-increment columns as part of composite primary key constraint',
);
}

$this->ensureDroppingPrimaryKeyConstraintIsSupported();

$table = new Table('alter_pk');
$table->addColumn('id1', Types::INTEGER, ['autoincrement' => true]);
$table->addColumn('id2', Types::INTEGER);
$table->setPrimaryKey(['id1']);

$this->testMigration($table, static function (Table $table): void {
$table->dropPrimaryKey();
$table->setPrimaryKey(['id1', 'id2']);
});
}

public function testAddNewColumnToPrimaryKey(): void
{
$this->ensureDroppingPrimaryKeyConstraintIsSupported();

$table = new Table('alter_pk');
$table->addColumn('id1', Types::INTEGER);
$table->setPrimaryKey(['id1']);

$this->testMigration($table, static function (Table $table): void {
$table->addColumn('id2', Types::INTEGER);
$table->dropPrimaryKey();
$table->setPrimaryKey(['id1', 'id2']);
});
}

private function ensureDroppingPrimaryKeyConstraintIsSupported(): void
{
$platform = $this->connection->getDatabasePlatform();

if (
! ($platform instanceof DB2Platform)
&& ! ($platform instanceof OraclePlatform)
&& ! ($platform instanceof SQLServerPlatform)
) {
return;
}

self::markTestIncomplete(
'Dropping primary key constraint on the currently used database platform is not implemented.',
);
}

private function testMigration(Table $oldTable, callable $migration): void
{
$this->dropAndCreateTable($oldTable);

$newTable = clone $oldTable;

$migration($newTable);

$schemaManager = $this->connection->createSchemaManager();

$diff = $schemaManager->createComparator()
->compareTables($oldTable, $newTable);

$schemaManager->alterTable($diff);

$introspectedTable = $schemaManager->introspectTable($newTable->getName());

$diff = $schemaManager->createComparator()
->compareTables($newTable, $introspectedTable);

self::assertTrue($diff->isEmpty());
}
}
166 changes: 0 additions & 166 deletions tests/Platforms/AbstractMySQLPlatformTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -282,172 +282,6 @@ public function testBlobTypeDeclarationSQL(): void
self::assertEquals('LONGBLOB', $this->platform->getBlobTypeDeclarationSQL([]));
}

public function testAlterTableAddPrimaryKey(): void
{
$table = new Table('alter_table_add_pk');
$table->addColumn('id', Types::INTEGER);
$table->addColumn('foo', Types::INTEGER);
$table->addIndex(['id'], 'idx_id');

$diffTable = clone $table;

$diffTable->dropIndex('idx_id');
$diffTable->setPrimaryKey(['id']);

$diff = $this->createComparator()
->compareTables($table, $diffTable);

self::assertEquals(
['DROP INDEX idx_id ON alter_table_add_pk', 'ALTER TABLE alter_table_add_pk ADD PRIMARY KEY (id)'],
$this->platform->getAlterTableSQL($diff),
);
}

public function testAlterPrimaryKeyWithAutoincrementColumn(): void
{
$table = new Table('alter_primary_key');
$table->addColumn('id', Types::INTEGER, ['autoincrement' => true]);
$table->addColumn('foo', Types::INTEGER);
$table->setPrimaryKey(['id']);

$diffTable = clone $table;

$diffTable->dropPrimaryKey();
$diffTable->setPrimaryKey(['foo']);

$diff = $this->createComparator()
->compareTables($table, $diffTable);

self::assertEquals(
[
'ALTER TABLE alter_primary_key MODIFY id INT NOT NULL',
'DROP INDEX `primary` ON alter_primary_key',
'ALTER TABLE alter_primary_key ADD PRIMARY KEY (foo)',
],
$this->platform->getAlterTableSQL($diff),
);
}

public function testDropPrimaryKeyWithAutoincrementColumn(): void
{
$table = new Table('drop_primary_key');
$table->addColumn('id', Types::INTEGER, ['autoincrement' => true]);
$table->addColumn('foo', Types::INTEGER);
$table->addColumn('bar', Types::INTEGER);
$table->setPrimaryKey(['id', 'foo']);

$diffTable = clone $table;

$diffTable->dropPrimaryKey();

$diff = $this->createComparator()
->compareTables($table, $diffTable);

self::assertEquals(
[
'ALTER TABLE drop_primary_key MODIFY id INT NOT NULL',
'DROP INDEX `primary` ON drop_primary_key',
],
$this->platform->getAlterTableSQL($diff),
);
}

public function testDropNonAutoincrementColumnFromCompositePrimaryKeyWithAutoincrementColumn(): void
{
$table = new Table('tbl');
$table->addColumn('id', Types::INTEGER, ['autoincrement' => true]);
$table->addColumn('foo', Types::INTEGER);
$table->addColumn('bar', Types::INTEGER);
$table->setPrimaryKey(['id', 'foo']);

$diffTable = clone $table;

$diffTable->dropPrimaryKey();
$diffTable->setPrimaryKey(['id']);

$diff = $this->createComparator()
->compareTables($table, $diffTable);

self::assertSame(
[
'ALTER TABLE tbl MODIFY id INT NOT NULL',
'DROP INDEX `primary` ON tbl',
'ALTER TABLE tbl ADD PRIMARY KEY (id)',
],
$this->platform->getAlterTableSQL($diff),
);
}

public function testAddNonAutoincrementColumnToPrimaryKeyWithAutoincrementColumn(): void
{
$table = new Table('tbl');
$table->addColumn('id', Types::INTEGER, ['autoincrement' => true]);
$table->addColumn('foo', Types::INTEGER);
$table->addColumn('bar', Types::INTEGER);
$table->setPrimaryKey(['id']);

$diffTable = clone $table;

$diffTable->dropPrimaryKey();
$diffTable->setPrimaryKey(['id', 'foo']);

$diff = $this->createComparator()
->compareTables($table, $diffTable);

self::assertSame(
[
'ALTER TABLE tbl MODIFY id INT NOT NULL',
'DROP INDEX `primary` ON tbl',
'ALTER TABLE tbl ADD PRIMARY KEY (id, foo)',
],
$this->platform->getAlterTableSQL($diff),
);
}

public function testAddAutoIncrementPrimaryKey(): void
{
$keyTable = new Table('foo');
$keyTable->addColumn('id', Types::INTEGER, ['autoincrement' => true]);
$keyTable->addColumn('baz', Types::STRING, ['length' => 32]);
$keyTable->setPrimaryKey(['id']);

$oldTable = new Table('foo');
$oldTable->addColumn('baz', Types::STRING, ['length' => 32]);

$diff = $this->createComparator()
->compareTables($oldTable, $keyTable);

$sql = $this->platform->getAlterTableSQL($diff);

self::assertEquals(['ALTER TABLE foo ADD id INT AUTO_INCREMENT NOT NULL, ADD PRIMARY KEY (id)'], $sql);
}

public function testAlterPrimaryKeyWithNewColumn(): void
{
$table = new Table('yolo');
$table->addColumn('pkc1', Types::INTEGER);
$table->addColumn('col_a', Types::INTEGER);
$table->setPrimaryKey(['pkc1']);

$diffTable = clone $table;

$diffTable->addColumn('pkc2', Types::INTEGER);
$diffTable->dropPrimaryKey();
$diffTable->setPrimaryKey(['pkc1', 'pkc2']);

$diff = $this->createComparator()
->compareTables($table, $diffTable);

self::assertSame(
[
'DROP INDEX `primary` ON yolo',
'ALTER TABLE yolo ADD pkc2 INT NOT NULL',
'ALTER TABLE yolo ADD PRIMARY KEY (pkc1, pkc2)',
],
$this->platform->getAlterTableSQL($diff),
);
}

public function testInitializesDoctrineTypeMappings(): void
{
self::assertTrue($this->platform->hasDoctrineTypeMappingFor('binary'));
Expand Down

0 comments on commit 37ab825

Please # to comment.