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..a7192dbede8 100644 --- a/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php +++ b/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php @@ -27,6 +27,8 @@ use function array_unshift; use function assert; use function count; +use function explode; +use function sprintf; use function strtolower; class PostgreSQLSchemaManagerTest extends SchemaManagerFunctionalTestCase @@ -561,6 +563,69 @@ public function testAlterTableAutoIncrementIntToBigInt( self::assertTrue($tableFinal->getColumn('id')->getAutoincrement()); } + public function testListTableColumnsOidConflictWithNonTableObject(): void + { + $semanticVersion = $this->connection->fetchOne('SHOW SERVER_VERSION'); + $majorVersion = explode('.', $semanticVersion)[0]; + + 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); + $this->assertArrayHasKey('id', $afterColumns); + + // revert to the original oid + $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)); + } + /** @return iterable */ public static function autoIncrementTypeMigrations(): iterable {