]> granicus.if.org Git - postgresql/commitdiff
Back-patch copyOject fix for EXPLAIN/PREPARE.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 13 Dec 2004 00:17:52 +0000 (00:17 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
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);