From 9fe2871b91452c100cd4a19176518a400a151b28 Mon Sep 17 00:00:00 2001 From: Nicolas PHILIPPE Date: Tue, 3 Sep 2024 14:09:51 +0200 Subject: [PATCH] [PostgreSQL] list partitionned tables --- src/Schema/PostgreSQLSchemaManager.php | 15 +++++- .../Schema/PostgreSQLSchemaManagerTest.php | 51 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/Schema/PostgreSQLSchemaManager.php b/src/Schema/PostgreSQLSchemaManager.php index db27815c551..163277d2d33 100644 --- a/src/Schema/PostgreSQLSchemaManager.php +++ b/src/Schema/PostgreSQLSchemaManager.php @@ -453,8 +453,21 @@ protected function selectTableColumns(string $databaseName, ?string $tableName = $conditions = array_merge([ 'a.attnum > 0', - "c.relkind = 'r'", 'd.refobjid IS NULL', + + // 'r' for regular tables - 'p' for partitioned tables + "c.relkind IN('r', 'p')", + + // exclude partitions (tables that inherit from partitioned tables) + <<<'SQL' + NOT EXISTS ( + SELECT 1 + FROM pg_inherits + INNER JOIN pg_class parent on pg_inherits.inhparent = parent.oid + AND parent.relkind = 'p' + WHERE inhrelid = c.oid + ) + SQL, ], $this->buildQueryConditions($tableName)); $sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY a.attnum'; diff --git a/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php b/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php index 2480a472163..591340c8864 100644 --- a/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php +++ b/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php @@ -7,6 +7,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\PostgreSQL120Platform; use Doctrine\DBAL\Platforms\PostgreSQLPlatform; +use Doctrine\DBAL\Schema\Exception\TableDoesNotExist; use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Table; @@ -598,6 +599,56 @@ public static function autoIncrementTypeMigrations(): iterable 'bigint->int' => ['bigint', 'integer', 'INT'], ]; } + + public function testPartitionTable(): void + { + $this->connection->executeStatement('DROP TABLE IF EXISTS partitioned_table'); + $this->connection->executeStatement( + 'CREATE TABLE partitioned_table (id INT) PARTITION BY LIST (id);', + ); + $this->connection->executeStatement('CREATE TABLE partition PARTITION OF partitioned_table FOR VALUES IN (1);'); + try { + $this->schemaManager->introspectTable('partition'); + } catch (TableDoesNotExist $e) { + } + + self::assertNotNull($e ?? null, 'Partition table should not be introspected'); + + $tableFrom = $this->schemaManager->introspectTable('partitioned_table'); + + $tableTo = $this->schemaManager->introspectTable('partitioned_table'); + $tableTo->addColumn('foo', Types::INTEGER); + + $platform = $this->connection->getDatabasePlatform(); + $diff = $this->schemaManager->createComparator()->compareTables($tableFrom, $tableTo); + + $sql = $platform->getAlterTableSQL($diff); + self::assertSame(['ALTER TABLE partitioned_table ADD foo INT NOT NULL'], $sql); + + $this->schemaManager->alterTable($diff); + + $tableFinal = $this->schemaManager->introspectTable('partitioned_table'); + self::assertTrue($tableFinal->hasColumn('id')); + self::assertTrue($tableFinal->hasColumn('foo')); + + $partitionedTableCount = (int) ($this->connection->fetchOne( + "select count(*) as count from pg_class where relname = 'partitioned_table' and relkind = 'p'", + )); + self::assertSame(1, $partitionedTableCount); + + $partitionsCount = (int) ($this->connection->fetchOne( + <<<'SQL' + select count(*) as count + from pg_class parent + inner join pg_inherits on pg_inherits.inhparent = parent.oid + inner join pg_class child on pg_inherits.inhrelid = child.oid + and child.relkind = 'r' + and child.relname = 'partition' + where parent.relname = 'partitioned_table' and parent.relkind = 'p'; + SQL, + )); + self::assertSame(1, $partitionsCount); + } } class MoneyType extends Type