mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Fix more problems with rewriter failing to set Query.hasSubLinks when inserting
a SubLink expression into a rule query. We missed cases where the original query contained a sub-SELECT in a function in FROM, a multi-row VALUES list, or a RETURNING list. Per bug #4434 from Dean Rasheed and subsequent investigation. Back-patch to 8.1; older releases don't have the issue because they didn't try to be smart about setting hasSubLinks only when needed.
This commit is contained in:
		@@ -7,7 +7,7 @@
 | 
				
			|||||||
 * Portions Copyright (c) 1994, Regents of the University of California
 | 
					 * Portions Copyright (c) 1994, Regents of the University of California
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.179 2008/08/28 23:09:48 tgl Exp $
 | 
					 *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.180 2008/09/24 16:52:46 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -346,6 +346,37 @@ rewriteRuleAction(Query *parsetree,
 | 
				
			|||||||
	sub_action->rtable = list_concat((List *) copyObject(parsetree->rtable),
 | 
						sub_action->rtable = list_concat((List *) copyObject(parsetree->rtable),
 | 
				
			||||||
									 sub_action->rtable);
 | 
														 sub_action->rtable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * There could have been some SubLinks in parsetree's rtable, in which
 | 
				
			||||||
 | 
						 * case we'd better mark the sub_action correctly.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (parsetree->hasSubLinks && !sub_action->hasSubLinks)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ListCell   *lc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							foreach(lc, parsetree->rtable)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								switch (rte->rtekind)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									case RTE_FUNCTION:
 | 
				
			||||||
 | 
										sub_action->hasSubLinks =
 | 
				
			||||||
 | 
											checkExprHasSubLink(rte->funcexpr);
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									case RTE_VALUES:
 | 
				
			||||||
 | 
										sub_action->hasSubLinks =
 | 
				
			||||||
 | 
											checkExprHasSubLink((Node *) rte->values_lists);
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									default:
 | 
				
			||||||
 | 
										/* other RTE types don't contain bare expressions */
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (sub_action->hasSubLinks)
 | 
				
			||||||
 | 
									break;		/* no need to keep scanning 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
 | 
				
			||||||
	 * plus that rule's jointree, but usually *without* the original rtindex
 | 
						 * plus that rule's jointree, but usually *without* the original rtindex
 | 
				
			||||||
@@ -455,6 +486,14 @@ rewriteRuleAction(Query *parsetree,
 | 
				
			|||||||
					   rule_action->returningList,
 | 
										   rule_action->returningList,
 | 
				
			||||||
					   CMD_SELECT,
 | 
										   CMD_SELECT,
 | 
				
			||||||
					   0);
 | 
										   0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * There could have been some SubLinks in parsetree's returningList,
 | 
				
			||||||
 | 
							 * in which case we'd better mark the rule_action correctly.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (parsetree->hasSubLinks && !rule_action->hasSubLinks)
 | 
				
			||||||
 | 
								rule_action->hasSubLinks =
 | 
				
			||||||
 | 
										checkExprHasSubLink((Node *) rule_action->returningList);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return rule_action;
 | 
						return rule_action;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user