Skip to content
Snippets Groups Projects
Commit 2a06b3bd authored by Tom Lane's avatar Tom Lane
Browse files

Repair problem with multi-action rules in combination with any nontrivial

manipulation of rtable/jointree by planner.  Rewriter was generating
actions that shared rtable/jointree substructure, which caused havoc
when planner got to the later actions that it'd already mucked up.
parent c1db506a
No related branches found
No related tags found
No related merge requests found
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.93 2001/05/03 17:47:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.94 2001/06/12 18:54:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -82,7 +82,7 @@ gatherRewriteMeta(Query *parsetree, ...@@ -82,7 +82,7 @@ gatherRewriteMeta(Query *parsetree,
/* /*
* Adjust rule action and qual to offset its varnos, so that we can * Adjust rule action and qual to offset its varnos, so that we can
* merge its rtable into the main parsetree's rtable. * merge its rtable with the main parsetree's rtable.
* *
* If the rule action is an INSERT...SELECT, the OLD/NEW rtable entries * If the rule action is an INSERT...SELECT, the OLD/NEW rtable entries
* will be in the SELECT part, and we have to modify that rather than * will be in the SELECT part, and we have to modify that rather than
...@@ -99,23 +99,19 @@ gatherRewriteMeta(Query *parsetree, ...@@ -99,23 +99,19 @@ gatherRewriteMeta(Query *parsetree,
PRS2_OLD_VARNO + rt_length, rt_index, 0); PRS2_OLD_VARNO + rt_length, rt_index, 0);
/* /*
* We want the main parsetree's rtable to end up as the concatenation * Generate expanded rtable consisting of main parsetree's rtable
* of its original contents plus those of all the relevant rule * plus rule action's rtable; this becomes the complete rtable for the
* actions. Also store same into all the rule_action rtables. Some of * rule action. Some of the entries may be unused after we finish
* the entries may be unused after we finish rewriting, but if we * rewriting, but if we tried to clean those out we'd have a much harder
* tried to clean those out we'd have a much harder job to adjust RT * job to adjust RT indexes in the query's Vars. It's OK to have unused
* indexes in the query's Vars. It's OK to have unused RT entries, * RT entries, since planner will ignore them.
* since planner will ignore them.
* *
* NOTE KLUGY HACK: we assume the parsetree rtable had at least one entry * NOTE: because planner will destructively alter rtable, we must ensure
* to begin with (OK enough, else where'd the rule come from?). * that rule action's rtable is separate and shares no substructure with
* Because of this, if multiple rules nconc() their rtable additions * the main rtable. Hence do a deep copy here.
* onto parsetree->rtable, they'll all see the same rtable because
* they all have the same list head pointer.
*/ */
parsetree->rtable = nconc(parsetree->rtable, sub_action->rtable = nconc((List *) copyObject(parsetree->rtable),
sub_action->rtable); sub_action->rtable);
sub_action->rtable = parsetree->rtable;
/* /*
* Each rule action's jointree should be the main parsetree's jointree * Each rule action's jointree should be the main parsetree's jointree
...@@ -128,6 +124,9 @@ gatherRewriteMeta(Query *parsetree, ...@@ -128,6 +124,9 @@ gatherRewriteMeta(Query *parsetree,
* data for the quals. We don't want the original rtindex to be * data for the quals. We don't want the original rtindex to be
* joined twice, however, so avoid keeping it if the rule action * joined twice, however, so avoid keeping it if the rule action
* mentions it. * mentions it.
*
* As above, the action's jointree must not share substructure with
* the main parsetree's.
*/ */
if (sub_action->jointree != NULL) if (sub_action->jointree != NULL)
{ {
...@@ -193,13 +192,13 @@ gatherRewriteMeta(Query *parsetree, ...@@ -193,13 +192,13 @@ gatherRewriteMeta(Query *parsetree,
* occurrence of the given rt_index as a top-level join item (we do not look * occurrence of the given rt_index as a top-level join item (we do not look
* for it within join items; this is OK because we are only expecting to find * for it within join items; this is OK because we are only expecting to find
* it as an UPDATE or DELETE target relation, which will be at the top level * it as an UPDATE or DELETE target relation, which will be at the top level
* of the join). Returns modified jointree list --- original list is not * of the join). Returns modified jointree list --- this is a separate copy
* changed. * sharing no nodes with the original.
*/ */
static List * static List *
adjustJoinTreeList(Query *parsetree, bool removert, int rt_index) adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
{ {
List *newjointree = listCopy(parsetree->jointree->fromlist); List *newjointree = copyObject(parsetree->jointree->fromlist);
List *jjt; List *jjt;
if (removert) if (removert)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment