From 4d1c83c5226742b720b5b0dead707156f490a2bc Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Tue, 26 Feb 2019 17:05:24 -0300
Subject: [PATCH v3 1/2] pg_partition_ancestors

---
 src/backend/utils/adt/partitionfuncs.c | 51 ++++++++++++++++++++++++++
 src/include/catalog/pg_proc.dat        |  5 +++
 2 files changed, 56 insertions(+)

diff --git a/src/backend/utils/adt/partitionfuncs.c b/src/backend/utils/adt/partitionfuncs.c
index ffd66b64394..b606776e015 100644
--- a/src/backend/utils/adt/partitionfuncs.c
+++ b/src/backend/utils/adt/partitionfuncs.c
@@ -208,3 +208,54 @@ pg_partition_root(PG_FUNCTION_ARGS)
 	Assert(OidIsValid(rootrelid));
 	PG_RETURN_OID(rootrelid);
 }
+
+/*
+ * pg_partition_ancestors
+ *
+ * Produces view with one row per ancestor of the given partition.
+ * If 'includeself', the partition itself is included in the output.
+ */
+Datum
+pg_partition_ancestors(PG_FUNCTION_ARGS)
+{
+	Oid			relid = PG_GETARG_OID(0);
+	bool		includeself = PG_GETARG_BOOL(1);
+	FuncCallContext *funcctx;
+	ListCell  **next;
+
+	if (!check_rel_can_be_partition(relid))
+		PG_RETURN_NULL();
+
+	if (SRF_IS_FIRSTCALL())
+	{
+		MemoryContext oldcxt;
+		List	   *ancestors;
+
+		funcctx = SRF_FIRSTCALL_INIT();
+
+		oldcxt = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+		ancestors = get_partition_ancestors(relid);
+		if (includeself)
+			ancestors = lappend_oid(ancestors, relid);
+
+		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/pg_proc.dat b/src/include/catalog/pg_proc.dat
index a4e173b4846..f433e8ca670 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 => 'oid', proargtypes => 'regclass bool',
+  proallargtypes => '{regclass,bool,regclass}', proargmodes => '{i,i,o}',
+  proargnames => '{partitionid,includeself,relid}', prosrc => 'pg_partition_ancestors' },
 
 # function to get the top-most partition root parent
 { oid => '3424', descr => 'get top-most partition root parent',
-- 
2.17.1

