diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 34f6aa51f78e4e3253dc6aad927429dd12637dcf..66e795d422df9f281210d3726d451e6d37ea58bd 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.127 2004/09/30 17:42:42 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.128 2004/12/12 20:17:06 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,6 +75,16 @@ ExplainQuery(ExplainStmt *stmt, DestReceiver *dest)
 	List	   *rewritten;
 	ListCell   *l;
 
+	/*
+	 * Because the planner is not cool about not scribbling on its input,
+	 * we make a preliminary copy of the source querytree.  This prevents
+	 * problems in the case that the EXPLAIN is in a portal or plpgsql
+	 * function and is executed repeatedly.  (See also the same hack in
+	 * DECLARE CURSOR and PREPARE.)  XXX the planner really shouldn't
+	 * modify its input ... FIXME someday.
+	 */
+	query = copyObject(query);
+
 	/* prepare for projection of tuples */
 	tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
 
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index ae9366c5ee1b47c464aaffb76fdce4465d5828fb..66fa15c37a35874001b8300dab2c5cd2db781e8f 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -10,7 +10,7 @@
  * Copyright (c) 2002-2004, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.34 2004/12/03 21:26:31 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.35 2004/12/12 20:17:06 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,6 +48,7 @@ void
 PrepareQuery(PrepareStmt *stmt)
 {
 	const char *commandTag;
+	Query	   *query;
 	List	   *query_list,
 			   *plan_list;
 
@@ -87,8 +88,18 @@ PrepareQuery(PrepareStmt *stmt)
 	 * the query.
 	 */
 
+	/*
+	 * Because the planner is not cool about not scribbling on its input,
+	 * we make a preliminary copy of the source querytree.  This prevents
+	 * problems in the case that the PREPARE is in a portal or plpgsql
+	 * function and is executed repeatedly.  (See also the same hack in
+	 * DECLARE CURSOR and EXPLAIN.)  XXX the planner really shouldn't
+	 * modify its input ... FIXME someday.
+	 */
+	query = copyObject(stmt->query);
+
 	/* Rewrite the query. The result could be 0, 1, or many queries. */
-	query_list = QueryRewrite(stmt->query);
+	query_list = QueryRewrite(query);
 
 	/* Generate plans for queries.	Snapshot is already set. */
 	plan_list = pg_plan_queries(query_list, NULL, false);