mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
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
|
* 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
|
* 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,
|
|||||||
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,
|
|||||||
* 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,
|
|||||||
* 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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user