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');