From 3422955735d9b2623532c60c53cb885c9cb6e3b1 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Sat, 2 Mar 2019 18:18:59 +0900 Subject: [PATCH] Consider only relations part of partition trees in partition functions MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This changes the partition functions so as tables and indexes which are not part of partition trees are handled the same way as what is done for undefined objects and unsupported relkinds: pg_partition_tree() returns no rows and pg_partition_root() returns a NULL result. Hence, partitioned tables, partitioned indexes and relations whose flag pg_class.relispartition is set are considered as valid objects to process. Previously, tables and indexes not included in a partition tree were processed the same way as a partition or a partitioned table, which caused the functions to return inconsistent results for inherited tables, especially when inheriting from multiple tables. Reported-by: Álvaro Herrera Author: Amit Langote, Michael Paquier Reviewed-by: Tom Lane Discussion: https://postgr.es/m/20190228193203.GA26151@alvherre.pgsql --- src/backend/utils/adt/partitionfuncs.c | 13 ++---- src/test/regress/expected/partition_info.out | 48 +++++++++++++++----- src/test/regress/sql/partition_info.sql | 17 ++++++- 3 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/backend/utils/adt/partitionfuncs.c b/src/backend/utils/adt/partitionfuncs.c index 36d9f69cbc..a2fe4f34b6 100644 --- a/src/backend/utils/adt/partitionfuncs.c +++ b/src/backend/utils/adt/partitionfuncs.c @@ -35,17 +35,17 @@ static bool check_rel_can_be_partition(Oid relid) { char relkind; + bool relispartition; /* Check if relation exists */ if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid))) return false; relkind = get_rel_relkind(relid); + relispartition = get_rel_relispartition(relid); /* Only allow relation types that can appear in partition trees. */ - if (relkind != RELKIND_RELATION && - relkind != RELKIND_FOREIGN_TABLE && - relkind != RELKIND_INDEX && + if (!relispartition && relkind != RELKIND_PARTITIONED_TABLE && relkind != RELKIND_PARTITIONED_INDEX) return false; @@ -189,13 +189,6 @@ pg_partition_root(PG_FUNCTION_ARGS) if (!check_rel_can_be_partition(relid)) PG_RETURN_NULL(); - /* - * If the relation is not a partition (it may be the partition parent), - * return itself as a result. - */ - if (!get_rel_relispartition(relid)) - PG_RETURN_OID(relid); - /* Fetch the top-most parent */ ancestors = get_partition_ancestors(relid); rootrelid = llast_oid(ancestors); diff --git a/src/test/regress/expected/partition_info.out b/src/test/regress/expected/partition_info.out index 73269ffd09..c1ba53d74d 100644 --- a/src/test/regress/expected/partition_info.out +++ b/src/test/regress/expected/partition_info.out @@ -32,7 +32,10 @@ CREATE TABLE ptif_test1 PARTITION OF ptif_test FOR VALUES FROM (0) TO (100) PARTITION BY list (b); CREATE TABLE ptif_test11 PARTITION OF ptif_test1 FOR VALUES IN (1); CREATE TABLE ptif_test2 PARTITION OF ptif_test - FOR VALUES FROM (100) TO (maxvalue); + FOR VALUES FROM (100) TO (200); +-- This partitioned table should remain with no partitions. +CREATE TABLE ptif_test3 PARTITION OF ptif_test + FOR VALUES FROM (200) TO (maxvalue) PARTITION BY list (b); -- Test index partition tree CREATE INDEX ptif_test_index ON ONLY ptif_test (a); CREATE INDEX ptif_test0_index ON ONLY ptif_test0 (a); @@ -45,6 +48,8 @@ CREATE INDEX ptif_test11_index ON ptif_test11 (a); ALTER INDEX ptif_test1_index ATTACH PARTITION ptif_test11_index; CREATE INDEX ptif_test2_index ON ptif_test2 (a); ALTER INDEX ptif_test_index ATTACH PARTITION ptif_test2_index; +CREATE INDEX ptif_test3_index ON ptif_test3 (a); +ALTER INDEX ptif_test_index ATTACH PARTITION ptif_test3_index; -- List all tables members of the tree SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree('ptif_test'); @@ -54,9 +59,10 @@ SELECT relid, parentrelid, level, isleaf ptif_test0 | ptif_test | 1 | f ptif_test1 | ptif_test | 1 | f ptif_test2 | ptif_test | 1 | t + ptif_test3 | ptif_test | 1 | f ptif_test01 | ptif_test0 | 2 | t ptif_test11 | ptif_test1 | 2 | t -(6 rows) +(7 rows) -- List tables from an intermediate level SELECT relid, parentrelid, level, isleaf @@ -77,6 +83,15 @@ SELECT relid, parentrelid, level, isleaf ptif_test01 | ptif_test0 | 0 | t (1 row) +-- List from partitioned table with no partitions +SELECT relid, parentrelid, level, isleaf + FROM pg_partition_tree('ptif_test3') p + JOIN pg_class c ON (p.relid = c.oid); + relid | parentrelid | level | isleaf +------------+-------------+-------+-------- + ptif_test3 | ptif_test | 0 | f +(1 row) + -- List all members using pg_partition_root with leaf table reference SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree(pg_partition_root('ptif_test01')) p @@ -87,9 +102,10 @@ SELECT relid, parentrelid, level, isleaf ptif_test0 | ptif_test | 1 | f ptif_test1 | ptif_test | 1 | f ptif_test2 | ptif_test | 1 | t + ptif_test3 | ptif_test | 1 | f ptif_test01 | ptif_test0 | 2 | t ptif_test11 | ptif_test1 | 2 | t -(6 rows) +(7 rows) -- List all indexes members of the tree SELECT relid, parentrelid, level, isleaf @@ -100,9 +116,10 @@ SELECT relid, parentrelid, level, isleaf ptif_test0_index | ptif_test_index | 1 | f ptif_test1_index | ptif_test_index | 1 | f ptif_test2_index | ptif_test_index | 1 | t + ptif_test3_index | ptif_test_index | 1 | f ptif_test01_index | ptif_test0_index | 2 | t ptif_test11_index | ptif_test1_index | 2 | t -(6 rows) +(7 rows) -- List indexes from an intermediate level SELECT relid, parentrelid, level, isleaf @@ -123,6 +140,15 @@ SELECT relid, parentrelid, level, isleaf ptif_test01_index | ptif_test0_index | 0 | t (1 row) +-- List from partitioned index with no partitions +SELECT relid, parentrelid, level, isleaf + FROM pg_partition_tree('ptif_test3_index') p + JOIN pg_class c ON (p.relid = c.oid); + relid | parentrelid | level | isleaf +------------------+-----------------+-------+-------- + ptif_test3_index | ptif_test_index | 0 | f +(1 row) + -- List all members using pg_partition_root with leaf index reference SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree(pg_partition_root('ptif_test01_index')) p @@ -133,24 +159,24 @@ SELECT relid, parentrelid, level, isleaf ptif_test0_index | ptif_test_index | 1 | f ptif_test1_index | ptif_test_index | 1 | f ptif_test2_index | ptif_test_index | 1 | t + ptif_test3_index | ptif_test_index | 1 | f ptif_test01_index | ptif_test0_index | 2 | t ptif_test11_index | ptif_test1_index | 2 | t -(6 rows) +(7 rows) DROP TABLE ptif_test; --- Table that is not part of any partition tree is the only member listed. +-- Table that is not part of any partition tree is not listed. CREATE TABLE ptif_normal_table(a int); SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree('ptif_normal_table'); - relid | parentrelid | level | isleaf --------------------+-------------+-------+-------- - ptif_normal_table | | 0 | t -(1 row) + relid | parentrelid | level | isleaf +-------+-------------+-------+-------- +(0 rows) SELECT pg_partition_root('ptif_normal_table'); pg_partition_root ------------------- - ptif_normal_table + (1 row) DROP TABLE ptif_normal_table; diff --git a/src/test/regress/sql/partition_info.sql b/src/test/regress/sql/partition_info.sql index 119b90afe4..44a0abe7e2 100644 --- a/src/test/regress/sql/partition_info.sql +++ b/src/test/regress/sql/partition_info.sql @@ -15,7 +15,10 @@ CREATE TABLE ptif_test1 PARTITION OF ptif_test FOR VALUES FROM (0) TO (100) PARTITION BY list (b); CREATE TABLE ptif_test11 PARTITION OF ptif_test1 FOR VALUES IN (1); CREATE TABLE ptif_test2 PARTITION OF ptif_test - FOR VALUES FROM (100) TO (maxvalue); + FOR VALUES FROM (100) TO (200); +-- This partitioned table should remain with no partitions. +CREATE TABLE ptif_test3 PARTITION OF ptif_test + FOR VALUES FROM (200) TO (maxvalue) PARTITION BY list (b); -- Test index partition tree CREATE INDEX ptif_test_index ON ONLY ptif_test (a); @@ -29,6 +32,8 @@ CREATE INDEX ptif_test11_index ON ptif_test11 (a); ALTER INDEX ptif_test1_index ATTACH PARTITION ptif_test11_index; CREATE INDEX ptif_test2_index ON ptif_test2 (a); ALTER INDEX ptif_test_index ATTACH PARTITION ptif_test2_index; +CREATE INDEX ptif_test3_index ON ptif_test3 (a); +ALTER INDEX ptif_test_index ATTACH PARTITION ptif_test3_index; -- List all tables members of the tree SELECT relid, parentrelid, level, isleaf @@ -41,6 +46,10 @@ SELECT relid, parentrelid, level, isleaf SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree('ptif_test01') p JOIN pg_class c ON (p.relid = c.oid); +-- List from partitioned table with no partitions +SELECT relid, parentrelid, level, isleaf + FROM pg_partition_tree('ptif_test3') p + JOIN pg_class c ON (p.relid = c.oid); -- List all members using pg_partition_root with leaf table reference SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree(pg_partition_root('ptif_test01')) p @@ -57,6 +66,10 @@ SELECT relid, parentrelid, level, isleaf SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree('ptif_test01_index') p JOIN pg_class c ON (p.relid = c.oid); +-- List from partitioned index with no partitions +SELECT relid, parentrelid, level, isleaf + FROM pg_partition_tree('ptif_test3_index') p + JOIN pg_class c ON (p.relid = c.oid); -- List all members using pg_partition_root with leaf index reference SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree(pg_partition_root('ptif_test01_index')) p @@ -64,7 +77,7 @@ SELECT relid, parentrelid, level, isleaf DROP TABLE ptif_test; --- Table that is not part of any partition tree is the only member listed. +-- Table that is not part of any partition tree is not listed. CREATE TABLE ptif_normal_table(a int); SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree('ptif_normal_table'); -- 2.40.0