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.
This commit is contained in:
parent
c1db506ab7
commit
2a06b3bdfd
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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,
|
||||
|
||||
/*
|
||||
* 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
|
||||
* will be in the SELECT part, and we have to modify that rather than
|
||||
@ -99,23 +99,19 @@ gatherRewriteMeta(Query *parsetree,
|
||||
PRS2_OLD_VARNO + rt_length, rt_index, 0);
|
||||
|
||||
/*
|
||||
* We want the main parsetree's rtable to end up as the concatenation
|
||||
* of its original contents plus those of all the relevant rule
|
||||
* actions. Also store same into all the rule_action rtables. Some of
|
||||
* the entries may be unused after we finish rewriting, but if we
|
||||
* tried to clean those out we'd have a much harder job to adjust RT
|
||||
* indexes in the query's Vars. It's OK to have unused RT entries,
|
||||
* since planner will ignore them.
|
||||
* Generate expanded rtable consisting of main parsetree's rtable
|
||||
* plus rule action's rtable; this becomes the complete rtable for the
|
||||
* rule action. Some of the entries may be unused after we finish
|
||||
* rewriting, but if we tried to clean those out we'd have a much harder
|
||||
* job to adjust RT indexes in the query's Vars. It's OK to have unused
|
||||
* RT entries, since planner will ignore them.
|
||||
*
|
||||
* NOTE KLUGY HACK: we assume the parsetree rtable had at least one entry
|
||||
* to begin with (OK enough, else where'd the rule come from?).
|
||||
* Because of this, if multiple rules nconc() their rtable additions
|
||||
* onto parsetree->rtable, they'll all see the same rtable because
|
||||
* they all have the same list head pointer.
|
||||
* NOTE: because planner will destructively alter rtable, we must ensure
|
||||
* that rule action's rtable is separate and shares no substructure with
|
||||
* the main rtable. Hence do a deep copy here.
|
||||
*/
|
||||
parsetree->rtable = nconc(parsetree->rtable,
|
||||
sub_action->rtable);
|
||||
sub_action->rtable = parsetree->rtable;
|
||||
sub_action->rtable = nconc((List *) copyObject(parsetree->rtable),
|
||||
sub_action->rtable);
|
||||
|
||||
/*
|
||||
* Each rule action's jointree should be the main parsetree's jointree
|
||||
@ -128,6 +124,9 @@ gatherRewriteMeta(Query *parsetree,
|
||||
* data for the quals. We don't want the original rtindex to be
|
||||
* joined twice, however, so avoid keeping it if the rule action
|
||||
* mentions it.
|
||||
*
|
||||
* As above, the action's jointree must not share substructure with
|
||||
* the main parsetree's.
|
||||
*/
|
||||
if (sub_action->jointree != NULL)
|
||||
{
|
||||
@ -193,13 +192,13 @@ gatherRewriteMeta(Query *parsetree,
|
||||
* 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
|
||||
* 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
|
||||
* changed.
|
||||
* of the join). Returns modified jointree list --- this is a separate copy
|
||||
* sharing no nodes with the original.
|
||||
*/
|
||||
static List *
|
||||
adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
|
||||
{
|
||||
List *newjointree = listCopy(parsetree->jointree->fromlist);
|
||||
List *newjointree = copyObject(parsetree->jointree->fromlist);
|
||||
List *jjt;
|
||||
|
||||
if (removert)
|
||||
|
Loading…
Reference in New Issue
Block a user