Back-patch copyOject fix for EXPLAIN/PREPARE.
authorTom Lane <[email protected]>
Mon, 13 Dec 2004 00:17:52 +0000 (00:17 +0000)
committerTom Lane <[email protected]>
Mon, 13 Dec 2004 00:17:52 +0000 (00:17 +0000)
src/backend/commands/explain.c
src/backend/commands/prepare.c

index 1b34b17585f70341d36c149dd4c73a856a948de4..5295583f17113632ffe6d446e665ef3589ea8d25 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.117 2003/10/17 01:14:26 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.117.2.1 2004/12/13 00:17:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -74,6 +74,16 @@ ExplainQuery(ExplainStmt *stmt, DestReceiver *dest)
    List       *rewritten;
    List       *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));
 
index bbbb61d6f6afcb6c95a5bfaa61b130c99aa5ff72..babae5e148346b2c2343acaf932b4a313bd56678 100644 (file)
@@ -10,7 +10,7 @@
  * Copyright (c) 2002-2003, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.23.4.1 2004/12/03 21:26:52 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.23.4.2 2004/12/13 00:17:52 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, false);