Skip to content

Commit 19f0dec

Browse files
f-lombardoderrabus
andauthored
Fix incorrect syntax for dropping primary indexes in PostgreSQL (#6025)
| Q | A |------------- | ----------- | Type | bug/feature/improvement | Fixed issues | #6024 #### Summary The correct way of dropping primary index in PostgreSQL is not dropping the index, but removing the primary key constraints --------- Co-authored-by: Alexander M. Turek <[email protected]>
1 parent 4de9c19 commit 19f0dec

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

src/Platforms/PostgreSQLPlatform.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Doctrine\DBAL\Schema\Index;
1111
use Doctrine\DBAL\Schema\PostgreSQLSchemaManager;
1212
use Doctrine\DBAL\Schema\Sequence;
13+
use Doctrine\DBAL\Schema\Table;
1314
use Doctrine\DBAL\Schema\TableDiff;
1415
use Doctrine\DBAL\Types\BinaryType;
1516
use Doctrine\DBAL\Types\BlobType;
@@ -809,6 +810,36 @@ public function getDropForeignKeySQL($foreignKey, $table)
809810
return $this->getDropConstraintSQL($foreignKey, $table);
810811
}
811812

813+
/**
814+
* {@inheritDoc}
815+
*/
816+
public function getDropIndexSQL($index, $table = null)
817+
{
818+
if ($index instanceof Index && $index->isPrimary() && $table !== null) {
819+
$constraintName = $index->getName() === 'primary' ? $this->tableName($table) . '_pkey' : $index->getName();
820+
821+
return $this->getDropConstraintSQL($constraintName, $table);
822+
}
823+
824+
if ($index === '"primary"' && $table !== null) {
825+
$constraintName = $this->tableName($table) . '_pkey';
826+
827+
return $this->getDropConstraintSQL($constraintName, $table);
828+
}
829+
830+
return parent::getDropIndexSQL($index, $table);
831+
}
832+
833+
/**
834+
* @param Table|string|null $table
835+
*
836+
* @return string
837+
*/
838+
private function tableName($table)
839+
{
840+
return $table instanceof Table ? $table->getName() : (string) $table;
841+
}
842+
812843
/**
813844
* {@inheritDoc}
814845
*/
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Doctrine\DBAL\Tests\Functional\Driver;
4+
5+
use Doctrine\DBAL\Schema\Table;
6+
use Doctrine\DBAL\Tests\FunctionalTestCase;
7+
use Doctrine\DBAL\Tests\TestUtil;
8+
9+
class DBAL6024Test extends FunctionalTestCase
10+
{
11+
protected function setUp(): void
12+
{
13+
if (TestUtil::isDriverOneOf('pdo_pgsql', 'pgsql')) {
14+
return;
15+
}
16+
17+
self::markTestSkipped('This test requires the pdo_pgsql or the pgsql driver.');
18+
}
19+
20+
public function testDropPrimaryKey(): void
21+
{
22+
$table = new Table('mytable');
23+
$table->addColumn('id', 'integer');
24+
$table->setPrimaryKey(['id']);
25+
$this->dropAndCreateTable($table);
26+
27+
$newTable = clone $table;
28+
$newTable->dropPrimaryKey();
29+
30+
$schemaManager = $this->connection->createSchemaManager();
31+
$diff = $schemaManager->createComparator()->compareTables($table, $newTable);
32+
33+
$statements = $this->connection->getDatabasePlatform()->getAlterTableSQL($diff);
34+
foreach ($statements as $statement) {
35+
$this->connection->executeStatement($statement);
36+
}
37+
38+
$validationSchema = $schemaManager->introspectSchema();
39+
$validationTable = $validationSchema->getTable($table->getName());
40+
41+
$this->assertNull($validationTable->getPrimaryKey());
42+
}
43+
}

tests/Platforms/PostgreSQLPlatformTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,44 @@ public function testDroppingConstraintsBeforeColumns(): void
581581
self::assertEquals($expectedSql, $sql);
582582
}
583583

584+
public function testDroppingPrimaryKey(): void
585+
{
586+
$oldTable = new Table('mytable');
587+
$oldTable->addColumn('id', 'integer');
588+
$oldTable->setPrimaryKey(['id']);
589+
590+
$newTable = clone $oldTable;
591+
$newTable->dropPrimaryKey();
592+
593+
$diff = (new Comparator())->compareTables($oldTable, $newTable);
594+
595+
$sql = $this->platform->getAlterTableSQL($diff);
596+
597+
$expectedSql = ['ALTER TABLE mytable DROP CONSTRAINT mytable_pkey'];
598+
599+
self::assertEquals($expectedSql, $sql);
600+
}
601+
602+
public function testDroppingPrimaryKeyWithUserDefinedName(): void
603+
{
604+
self::markTestSkipped('Edge case not covered yet');
605+
606+
$oldTable = new Table('mytable');
607+
$oldTable->addColumn('id', 'integer');
608+
$oldTable->setPrimaryKey(['id'], 'a_user_name');
609+
610+
$newTable = clone $oldTable;
611+
$newTable->dropPrimaryKey();
612+
613+
$diff = (new Comparator())->compareTables($oldTable, $newTable);
614+
615+
$sql = $this->platform->getAlterTableSQL($diff);
616+
617+
$expectedSql = ['ALTER TABLE mytable DROP CONSTRAINT a_user_name'];
618+
619+
self::assertEquals($expectedSql, $sql);
620+
}
621+
584622
public function testUsesSequenceEmulatedIdentityColumns(): void
585623
{
586624
self::assertTrue($this->platform->usesSequenceEmulatedIdentityColumns());

0 commit comments

Comments
 (0)