diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 86ff4e5c9e..6765b0d584 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -20274,6 +20274,17 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup()); their partitions, and so on. + + + pg_partition_ancestors + pg_partition_ancestors(regclass) + + setof regclass + + List the ancestor relations of the given partition, + including the partition itself. + + pg_partition_root diff --git a/src/backend/utils/adt/partitionfuncs.c b/src/backend/utils/adt/partitionfuncs.c index a2fe4f34b6..98c8ef77f1 100644 --- a/src/backend/utils/adt/partitionfuncs.c +++ b/src/backend/utils/adt/partitionfuncs.c @@ -201,3 +201,52 @@ pg_partition_root(PG_FUNCTION_ARGS) Assert(OidIsValid(rootrelid)); PG_RETURN_OID(rootrelid); } + +/* + * pg_partition_ancestors + * + * Produces a view with one row per ancestor of the given partition, + * including the input relation itself. + */ +Datum +pg_partition_ancestors(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + FuncCallContext *funcctx; + ListCell **next; + + if (SRF_IS_FIRSTCALL()) + { + MemoryContext oldcxt; + List *ancestors; + + funcctx = SRF_FIRSTCALL_INIT(); + + if (!check_rel_can_be_partition(relid)) + SRF_RETURN_DONE(funcctx); + + oldcxt = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + ancestors = get_partition_ancestors(relid); + ancestors = lcons_oid(relid, ancestors); + + next = (ListCell **) palloc(sizeof(ListCell *)); + *next = list_head(ancestors); + funcctx->user_fctx = (void *) next; + + MemoryContextSwitchTo(oldcxt); + } + + funcctx = SRF_PERCALL_SETUP(); + next = (ListCell **) funcctx->user_fctx; + + if (*next != NULL) + { + Oid relid = lfirst_oid(*next); + + *next = lnext(*next); + SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(relid)); + } + + SRF_RETURN_DONE(funcctx); +} diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 4887d322a3..0c4c2e11d5 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201902161 +#define CATALOG_VERSION_NO 201903041 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index a4e173b484..5bb56b2c63 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -10528,6 +10528,11 @@ proargmodes => '{i,o,o,o,o}', proargnames => '{rootrelid,relid,parentrelid,isleaf,level}', prosrc => 'pg_partition_tree' }, +{ oid => '3425', descr => 'view ancestors of the partition', + proname => 'pg_partition_ancestors', prorows => '10', proretset => 't', + provolatile => 'v', prorettype => 'regclass', proargtypes => 'regclass', + proallargtypes => '{regclass,regclass}', proargmodes => '{i,o}', + proargnames => '{partitionid,relid}', prosrc => 'pg_partition_ancestors' }, # function to get the top-most partition root parent { oid => '3424', descr => 'get top-most partition root parent', diff --git a/src/test/regress/expected/partition_info.out b/src/test/regress/expected/partition_info.out index 6df7a80a93..92aa6abe3f 100644 --- a/src/test/regress/expected/partition_info.out +++ b/src/test/regress/expected/partition_info.out @@ -11,6 +11,16 @@ SELECT * FROM pg_partition_tree(0); -------+-------------+--------+------- (0 rows) +SELECT * FROM pg_partition_ancestors(NULL); + relid +------- +(0 rows) + +SELECT * FROM pg_partition_ancestors(0); + relid +------- +(0 rows) + SELECT pg_partition_root(NULL); pg_partition_root ------------------- @@ -92,6 +102,21 @@ SELECT relid, parentrelid, level, isleaf ptif_test3 | ptif_test | 0 | f (1 row) +-- List all ancestors of root and leaf tables +SELECT * FROM pg_partition_ancestors('ptif_test01'); + relid +------------- + ptif_test01 + ptif_test0 + ptif_test +(3 rows) + +SELECT * FROM pg_partition_ancestors('ptif_test'); + relid +----------- + ptif_test +(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 @@ -164,6 +189,21 @@ SELECT relid, parentrelid, level, isleaf ptif_test11_index | ptif_test1_index | 2 | t (7 rows) +-- List all ancestors of root and leaf indexes +SELECT * FROM pg_partition_ancestors('ptif_test01_index'); + relid +------------------- + ptif_test01_index + ptif_test0_index + ptif_test_index +(3 rows) + +SELECT * FROM pg_partition_ancestors('ptif_test_index'); + relid +----------------- + ptif_test_index +(1 row) + DROP TABLE ptif_test; -- Table that is not part of any partition tree is not listed. CREATE TABLE ptif_normal_table(a int); @@ -173,6 +213,11 @@ SELECT relid, parentrelid, level, isleaf -------+-------------+-------+-------- (0 rows) +SELECT * FROM pg_partition_ancestors('ptif_normal_table'); + relid +------- +(0 rows) + SELECT pg_partition_root('ptif_normal_table'); pg_partition_root ------------------- @@ -207,6 +252,26 @@ SELECT * FROM pg_partition_tree('ptif_li_child'); -------+-------------+--------+------- (0 rows) +SELECT * FROM pg_partition_ancestors('ptif_test_view'); + relid +------- +(0 rows) + +SELECT * FROM pg_partition_ancestors('ptif_test_matview'); + relid +------- +(0 rows) + +SELECT * FROM pg_partition_ancestors('ptif_li_parent'); + relid +------- +(0 rows) + +SELECT * FROM pg_partition_ancestors('ptif_li_child'); + relid +------- +(0 rows) + SELECT pg_partition_root('ptif_test_view'); pg_partition_root ------------------- diff --git a/src/test/regress/sql/partition_info.sql b/src/test/regress/sql/partition_info.sql index a18c15aef2..adaca23232 100644 --- a/src/test/regress/sql/partition_info.sql +++ b/src/test/regress/sql/partition_info.sql @@ -3,6 +3,8 @@ -- SELECT * FROM pg_partition_tree(NULL); SELECT * FROM pg_partition_tree(0); +SELECT * FROM pg_partition_ancestors(NULL); +SELECT * FROM pg_partition_ancestors(0); SELECT pg_partition_root(NULL); SELECT pg_partition_root(0); @@ -50,6 +52,9 @@ SELECT relid, parentrelid, level, isleaf SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree('ptif_test3') p JOIN pg_class c ON (p.relid = c.oid); +-- List all ancestors of root and leaf tables +SELECT * FROM pg_partition_ancestors('ptif_test01'); +SELECT * FROM pg_partition_ancestors('ptif_test'); -- 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 @@ -74,6 +79,9 @@ SELECT relid, parentrelid, level, isleaf SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree(pg_partition_root('ptif_test01_index')) p JOIN pg_class c ON (p.relid = c.oid); +-- List all ancestors of root and leaf indexes +SELECT * FROM pg_partition_ancestors('ptif_test01_index'); +SELECT * FROM pg_partition_ancestors('ptif_test_index'); DROP TABLE ptif_test; @@ -81,6 +89,7 @@ DROP TABLE ptif_test; CREATE TABLE ptif_normal_table(a int); SELECT relid, parentrelid, level, isleaf FROM pg_partition_tree('ptif_normal_table'); +SELECT * FROM pg_partition_ancestors('ptif_normal_table'); SELECT pg_partition_root('ptif_normal_table'); DROP TABLE ptif_normal_table; @@ -95,6 +104,10 @@ SELECT * FROM pg_partition_tree('ptif_test_view'); SELECT * FROM pg_partition_tree('ptif_test_matview'); SELECT * FROM pg_partition_tree('ptif_li_parent'); SELECT * FROM pg_partition_tree('ptif_li_child'); +SELECT * FROM pg_partition_ancestors('ptif_test_view'); +SELECT * FROM pg_partition_ancestors('ptif_test_matview'); +SELECT * FROM pg_partition_ancestors('ptif_li_parent'); +SELECT * FROM pg_partition_ancestors('ptif_li_child'); SELECT pg_partition_root('ptif_test_view'); SELECT pg_partition_root('ptif_test_matview'); SELECT pg_partition_root('ptif_li_parent');