diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index a33d068a385ef01ab1546d33b8e16926f705c371..6b6bc15bda7b5e2dd70705f52e2611cbe31f5ea0 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.56 2000/07/24 03:11:01 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.57 2000/07/27 04:51:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,6 +28,7 @@
 #include "optimizer/paths.h"
 #include "optimizer/planmain.h"
 #include "optimizer/tlist.h"
+#include "utils/memutils.h"
 
 
 static Plan *subplanner(Query *root, List *flat_tlist, List *qual,
@@ -176,6 +177,9 @@ subplanner(Query *root,
 		   double tuple_fraction)
 {
 	RelOptInfo *final_rel;
+	Plan	   *resultplan;
+	MemoryContext mycontext;
+	MemoryContext oldcxt;
 	Path	   *cheapestpath;
 	Path	   *presortedpath;
 
@@ -212,6 +216,24 @@ subplanner(Query *root,
 	 */
 	root->query_pathkeys = canonicalize_pathkeys(root, root->query_pathkeys);
 
+	/*
+	 * We might allocate quite a lot of storage during planning (due to
+	 * constructing lots of Paths), but all of it can be reclaimed after
+	 * we generate the finished Plan tree.  Work in a temporary context
+	 * to let that happen.  We make the context a child of
+	 * TransactionCommandContext so it will be freed if error abort.
+	 *
+	 * Note: beware of trying to move this up to the start of this routine.
+	 * Some of the data structures built above --- notably the pathkey
+	 * equivalence sets --- will still be needed after this routine exits.
+	 */
+	mycontext = AllocSetContextCreate(TransactionCommandContext,
+									  "Planner",
+									  ALLOCSET_DEFAULT_MINSIZE,
+									  ALLOCSET_DEFAULT_INITSIZE,
+									  ALLOCSET_DEFAULT_MAXSIZE);
+	oldcxt = MemoryContextSwitchTo(mycontext);
+
 	/*
 	 * Ready to do the primary planning.
 	 */
@@ -235,7 +257,9 @@ subplanner(Query *root,
 		root->query_pathkeys = NIL;		/* signal unordered result */
 
 		/* Make childless Result node to evaluate given tlist. */
-		return (Plan *) make_result(flat_tlist, (Node *) qual, (Plan *) NULL);
+		resultplan = (Plan *) make_result(flat_tlist, (Node *) qual,
+										  (Plan *) NULL);
+		goto plan_built;
 	}
 
 #ifdef NOT_USED					/* fix xfunc */
@@ -295,7 +319,8 @@ subplanner(Query *root,
 							  cheapestpath->pathkeys))
 	{
 		root->query_pathkeys = cheapestpath->pathkeys;
-		return create_plan(root, cheapestpath);
+		resultplan = create_plan(root, cheapestpath);
+		goto plan_built;
 	}
 
 	/*
@@ -321,7 +346,8 @@ subplanner(Query *root,
 		{
 			/* Presorted path is cheaper, use it */
 			root->query_pathkeys = presortedpath->pathkeys;
-			return create_plan(root, presortedpath);
+			resultplan = create_plan(root, presortedpath);
+			goto plan_built;
 		}
 		/* otherwise, doing it the hard way is still cheaper */
 	}
@@ -334,5 +360,24 @@ subplanner(Query *root,
 	 * as an aggregate function...)
 	 */
 	root->query_pathkeys = cheapestpath->pathkeys;
-	return create_plan(root, cheapestpath);
+	resultplan = create_plan(root, cheapestpath);
+
+plan_built:
+
+	/*
+	 * Must copy the completed plan tree and its pathkeys out of temporary
+	 * context.
+	 */
+	MemoryContextSwitchTo(oldcxt);
+
+	resultplan = copyObject(resultplan);
+
+	root->query_pathkeys = copyObject(root->query_pathkeys);
+
+	/*
+	 * Now we can release the Path storage.
+	 */
+	MemoryContextDelete(mycontext);
+
+	return resultplan;
 }