diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 8afde2b..84c75f1 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -43,6 +43,7 @@
 #include "parser/parsetree.h"
 #include "parser/parse_agg.h"
 #include "rewrite/rewriteManip.h"
+#include "utils/memutils.h"
 #include "utils/rel.h"
 #include "utils/selfuncs.h"
 
@@ -845,9 +846,17 @@ inheritance_planner(PlannerInfo *root)
 	List	   *returningLists = NIL;
 	List	   *rowMarks;
 	ListCell   *lc;
+	MemoryContext	myctx;
+	MemoryContext	oldctx;
 
 	Assert(parse->commandType != CMD_INSERT);
 
+	myctx = AllocSetContextCreate(CurrentMemoryContext,
+								  "inheritance_planner",
+								  ALLOCSET_DEFAULT_MINSIZE,
+								  ALLOCSET_DEFAULT_INITSIZE,
+								  ALLOCSET_DEFAULT_MAXSIZE);
+
 	/*
 	 * We generate a modified instance of the original Query for each target
 	 * relation, plan that, and put all the plans into a list that will be
@@ -908,18 +917,16 @@ inheritance_planner(PlannerInfo *root)
 
 		/*
 		 * The rowMarks list might contain references to subquery RTEs, so
-		 * make a copy that we can apply ChangeVarNodes to.  (Fortunately, the
-		 * executor doesn't need to see the modified copies --- we can just
-		 * pass it the original rowMarks list.)
+		 * make a copy that we can apply ChangeVarNodes to.  If any security
+		 * barrier quals are present, the rowMarks list may be further modified
+		 * by grouping_planner. (Fortunately, the executor doesn't need to see
+		 * the modified copies --- we can just pass it the original rowMarks
+		 * list.  For the same reason, we can arrange to throw away the copy
+		 * we make here relatively quickly.)
 		 */
+		oldctx = MemoryContextSwitchTo(myctx);
 		subroot.rowMarks = (List *) copyObject(root->rowMarks);
-
-		/*
-		 * The append_rel_list likewise might contain references to subquery
-		 * RTEs (if any subqueries were flattenable UNION ALLs).  So prepare
-		 * to apply ChangeVarNodes to that, too.
-		 */
-		subroot.append_rel_list = (List *) copyObject(root->append_rel_list);
+		MemoryContextSwitchTo(oldctx);
 
 		/*
 		 * Add placeholders to the child Query's rangetable list to fill the
@@ -942,6 +949,7 @@ inheritance_planner(PlannerInfo *root)
 		if (final_rtable != NIL)
 		{
 			ListCell   *lr;
+			bool		did_copy = false;
 
 			rti = 1;
 			foreach(lr, parse->rtable)
@@ -960,6 +968,21 @@ inheritance_planner(PlannerInfo *root)
 					Index		newrti;
 
 					/*
+					 * The append_rel_list likewise might contain references
+					 * to subquery RTEs (if any subqueries were flattenable
+					 * UNION ALLs).  So we need to mutate that too, and must
+					 * therefore copy it.
+					 */
+					if (!did_copy)
+					{
+						oldctx = MemoryContextSwitchTo(myctx);
+						subroot.append_rel_list =
+							(List *) copyObject(root->append_rel_list);
+						MemoryContextSwitchTo(oldctx);
+						did_copy = true;
+					}
+
+					/*
 					 * The RTE can't contain any references to its own RT
 					 * index, except in the security barrier quals, so we can
 					 * save a few cycles by applying ChangeVarNodes before we
@@ -989,6 +1012,9 @@ inheritance_planner(PlannerInfo *root)
 		/* Generate plan */
 		subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ );
 
+		/* Reclaim some memory */
+		MemoryContextReset(myctx);
+
 		/*
 		 * Planning may have modified the query result relation (if there were
 		 * security barrier quals on the result RTE).
@@ -1097,6 +1123,8 @@ inheritance_planner(PlannerInfo *root)
 		Assert(!parse->onConflict);
 	}
 
+	MemoryContextDelete(myctx);
+
 	/* Mark result as unordered (probably unnecessary) */
 	root->query_pathkeys = NIL;
 
