OSDN Git Service

PREPARE and EXPLAIN need to copy the source query just like we recently
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 12 Dec 2004 20:17:06 +0000 (20:17 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 12 Dec 2004 20:17:06 +0000 (20:17 +0000)
had to do in DECLARE CURSOR.  AFAICS these are all the places affected.
PREPARE case per example from Michael Fuhr, EXPLAIN case located by
grepping for planner calls ...

src/backend/commands/explain.c
src/backend/commands/prepare.c

index 34f6aa5..66e795d 100644 (file)
@@ -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));
 
index ae9366c..66fa15c 100644 (file)
@@ -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);