mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04: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