diff --git a/src/Schema/PostgreSQLSchemaManager.php b/src/Schema/PostgreSQLSchemaManager.php index 7583c4d0234..87df0457f62 100644 --- a/src/Schema/PostgreSQLSchemaManager.php +++ b/src/Schema/PostgreSQLSchemaManager.php @@ -651,6 +651,7 @@ protected function selectTableColumns(string $databaseName, ?string $tableName = LEFT JOIN pg_depend d ON d.objid = c.oid AND d.deptype = 'e' + AND d.classid = (SELECT oid FROM pg_class WHERE relname = 'pg_class') SQL; $conditions = array_merge([ diff --git a/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php b/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php index 4cfe1e9d832..cdfefd1d73e 100644 --- a/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php +++ b/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php @@ -2,6 +2,7 @@ namespace Doctrine\DBAL\Tests\Functional\Schema; +use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Exception\DatabaseObjectNotFoundException; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\PostgreSQLPlatform; @@ -27,6 +28,8 @@ use function array_unshift; use function assert; use function count; +use function preg_match; +use function sprintf; use function strtolower; class PostgreSQLSchemaManagerTest extends SchemaManagerFunctionalTestCase @@ -561,6 +564,73 @@ public function testAlterTableAutoIncrementIntToBigInt( self::assertTrue($tableFinal->getColumn('id')->getAutoincrement()); } + public function testListTableColumnsOidConflictWithNonTableObject(): void + { + $versionParts = []; + $wrappedConnection = $this->connection->getWrappedConnection(); + assert($wrappedConnection instanceof ServerInfoAwareConnection); + assert(preg_match('/^(?P\d+)/', $wrappedConnection->getServerVersion(), $versionParts) > 0); + + $majorVersion = $versionParts['major']; + if ($majorVersion === '9') { + self::markTestSkipped('Manually setting the Oid is not supported in 9.4'); + } + + $table = 'test_list_table_columns_oid_conflicts'; + $this->connection->executeStatement(sprintf('CREATE TABLE IF NOT EXISTS %s(id INT NOT NULL)', $table)); + $beforeColumns = $this->schemaManager->listTableColumns($table); + $this->assertArrayHasKey('id', $beforeColumns); + + $this->connection->executeStatement('CREATE EXTENSION IF NOT EXISTS pg_prewarm'); + $originalTableOid = $this->connection->fetchOne( + 'SELECT oid FROM pg_class WHERE pg_class.relname = ?', + [$table], + ); + + $getConflictingOidSql = <<<'SQL' +SELECT objid +FROM pg_depend +JOIN pg_extension as ex on ex.oid = pg_depend.refobjid +WHERE ex.extname = 'pg_prewarm' +ORDER BY objid +LIMIT 1 +SQL; + $conflictingOid = $this->connection->fetchOne($getConflictingOidSql); + + $this->connection->executeStatement( + 'UPDATE pg_attribute SET attrelid = ? WHERE attrelid = ?', + [$conflictingOid, $originalTableOid], + ); + $this->connection->executeStatement( + 'UPDATE pg_description SET objoid = ? WHERE objoid = ?', + [$conflictingOid, $originalTableOid], + ); + $this->connection->executeStatement( + 'UPDATE pg_class SET oid = ? WHERE oid = ?', + [$conflictingOid, $originalTableOid], + ); + + $afterColumns = $this->schemaManager->listTableColumns($table); + + // revert to the database to original state prior to asserting result + $this->connection->executeStatement( + 'UPDATE pg_attribute SET attrelid = ? WHERE attrelid = ?', + [$originalTableOid, $conflictingOid], + ); + $this->connection->executeStatement( + 'UPDATE pg_description SET objoid = ? WHERE objoid = ?', + [$originalTableOid, $conflictingOid], + ); + $this->connection->executeStatement( + 'UPDATE pg_class SET oid = ? WHERE oid = ?', + [$originalTableOid, $conflictingOid], + ); + $this->connection->executeStatement(sprintf('DROP TABLE IF EXISTS %s', $table)); + $this->connection->executeStatement('DROP EXTENSION IF EXISTS pg_prewarm'); + + $this->assertArrayHasKey('id', $afterColumns); + } + /** @return iterable */ public static function autoIncrementTypeMigrations(): iterable {