their partitions, and so on.
</entry>
</row>
+ <row>
+ <entry>
+ <indexterm><primary>pg_partition_ancestors</primary></indexterm>
+ <literal><function>pg_partition_ancestors(<type>regclass</type>)</function></literal>
+ </entry>
+ <entry><type>setof regclass</type></entry>
+ <entry>
+ List the ancestor relations of the given partition,
+ including the partition itself.
+ </entry>
+ </row>
<row>
<entry>
<indexterm><primary>pg_partition_root</primary></indexterm>
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);
+}
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201902161
+#define CATALOG_VERSION_NO 201903041
#endif
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',
-------+-------------+--------+-------
(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
-------------------
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
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);
-------+-------------+-------+--------
(0 rows)
+SELECT * FROM pg_partition_ancestors('ptif_normal_table');
+ relid
+-------
+(0 rows)
+
SELECT pg_partition_root('ptif_normal_table');
pg_partition_root
-------------------
-------+-------------+--------+-------
(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
-------------------
--
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);
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
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;
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;
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');