mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Consider only relations part of partition trees in partition functions
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
This commit is contained in:
parent
70b9bda65f
commit
3422955735
@ -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);
|
||||
|
@ -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)
|
||||
-------+-------------+-------+--------
|
||||
(0 rows)
|
||||
|
||||
SELECT pg_partition_root('ptif_normal_table');
|
||||
pg_partition_root
|
||||
-------------------
|
||||
ptif_normal_table
|
||||
|
||||
(1 row)
|
||||
|
||||
DROP TABLE ptif_normal_table;
|
||||
|
@ -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');
|
||||
|
Loading…
x
Reference in New Issue
Block a user