77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.93 2001/05/03 17:47:49 tgl Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.93.2.1 2001/06/12 18:54:53 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -82,7 +82,7 @@ gatherRewriteMeta(Query *parsetree,
8282
8383/*
8484 * Adjust rule action and qual to offset its varnos, so that we can
85- * merge its rtableinto the main parsetree's rtable.
85+ * merge its rtablewith the main parsetree's rtable.
8686 *
8787 * If the rule action is an INSERT...SELECT, the OLD/NEW rtable entries
8888 * will be in the SELECT part, and we have to modify that rather than
@@ -99,23 +99,19 @@ gatherRewriteMeta(Query *parsetree,
9999PRS2_OLD_VARNO + rt_length ,rt_index ,0 );
100100
101101/*
102- * We want the main parsetree's rtable to end up as the concatenation
103- * of its original contents plus those of all the relevant rule
104- * actions. Also store same into all the rule_action rtables. Some of
105- * the entries may be unused after we finish rewriting, but if we
106- * tried to clean those out we'd have a much harder job to adjust RT
107- * indexes in the query's Vars. It's OK to have unused RT entries,
108- * since planner will ignore them.
102+ * Generate expanded rtable consisting of main parsetree's rtable
103+ * plus rule action's rtable; this becomes the complete rtable for the
104+ * rule action. Some of the entries may be unused after we finish
105+ * rewriting, but if we tried to clean those out we'd have a much harder
106+ * job to adjust RT indexes in the query's Vars. It's OK to have unused
107+ * RT entries, since planner will ignore them.
109108 *
110- * NOTE KLUGY HACK: we assume the parsetree rtable had at least one entry
111- * to begin with (OK enough, else where'd the rule come from?).
112- * Because of this, if multiple rules nconc() their rtable additions
113- * onto parsetree->rtable, they'll all see the same rtable because
114- * they all have the same list head pointer.
109+ * NOTE: because planner will destructively alter rtable, we must ensure
110+ * that rule action's rtable is separate and shares no substructure with
111+ * the main rtable. Hence do a deep copy here.
115112 */
116- parsetree -> rtable = nconc (parsetree -> rtable ,
117- sub_action -> rtable );
118- sub_action -> rtable = parsetree -> rtable ;
113+ sub_action -> rtable = nconc ((List * )copyObject (parsetree -> rtable ),
114+ sub_action -> rtable );
119115
120116/*
121117 * Each rule action's jointree should be the main parsetree's jointree
@@ -128,6 +124,9 @@ gatherRewriteMeta(Query *parsetree,
128124 * data for the quals.We don't want the original rtindex to be
129125 * joined twice, however, so avoid keeping it if the rule action
130126 * mentions it.
127+ *
128+ * As above, the action's jointree must not share substructure with
129+ * the main parsetree's.
131130 */
132131if (sub_action -> jointree != NULL )
133132{
@@ -193,13 +192,13 @@ gatherRewriteMeta(Query *parsetree,
193192 * occurrence of the given rt_index as a top-level join item (we do not look
194193 * for it within join items; this is OK because we are only expecting to find
195194 * it as an UPDATE or DELETE target relation, which will be at the top level
196- * of the join). Returns modified jointree list ---original list isnot
197- *changed .
195+ * of the join). Returns modified jointree list ---this isa separate copy
196+ *sharing no nodes with the original .
198197 */
199198static List *
200199adjustJoinTreeList (Query * parsetree ,bool removert ,int rt_index )
201200{
202- List * newjointree = listCopy (parsetree -> jointree -> fromlist );
201+ List * newjointree = copyObject (parsetree -> jointree -> fromlist );
203202List * jjt ;
204203
205204if (removert )