mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Fix LATERAL references to join alias variables.
I had thought this case worked already, but perhaps I didn't re-test it after adding extract_lateral_references() ...
This commit is contained in:
		
							parent
							
								
									f789909b59
								
							
						
					
					
						commit
						da3df99870
					
				| @ -52,10 +52,12 @@ planner_hook_type planner_hook = NULL; | |||||||
| #define EXPRKIND_QUAL			0 | #define EXPRKIND_QUAL			0 | ||||||
| #define EXPRKIND_TARGET			1 | #define EXPRKIND_TARGET			1 | ||||||
| #define EXPRKIND_RTFUNC			2 | #define EXPRKIND_RTFUNC			2 | ||||||
| #define EXPRKIND_VALUES		3 | #define EXPRKIND_RTFUNC_LATERAL	3 | ||||||
| #define EXPRKIND_LIMIT		4 | #define EXPRKIND_VALUES			4 | ||||||
| #define EXPRKIND_APPINFO	5 | #define EXPRKIND_VALUES_LATERAL	5 | ||||||
| #define EXPRKIND_PHV		6 | #define EXPRKIND_LIMIT			6 | ||||||
|  | #define EXPRKIND_APPINFO		7 | ||||||
|  | #define EXPRKIND_PHV			8 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind); | static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind); | ||||||
| @ -438,18 +440,38 @@ subquery_planner(PlannerGlobal *glob, Query *parse, | |||||||
| 		preprocess_expression(root, (Node *) root->append_rel_list, | 		preprocess_expression(root, (Node *) root->append_rel_list, | ||||||
| 							  EXPRKIND_APPINFO); | 							  EXPRKIND_APPINFO); | ||||||
| 
 | 
 | ||||||
| 	/* Also need to preprocess expressions for function and values RTEs */ | 	/* Also need to preprocess expressions within RTEs */ | ||||||
| 	foreach(l, parse->rtable) | 	foreach(l, parse->rtable) | ||||||
| 	{ | 	{ | ||||||
| 		RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); | 		RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); | ||||||
|  | 		int			kind; | ||||||
| 
 | 
 | ||||||
| 		if (rte->rtekind == RTE_FUNCTION) | 		if (rte->rtekind == RTE_SUBQUERY) | ||||||
| 			rte->funcexpr = preprocess_expression(root, rte->funcexpr, | 		{ | ||||||
| 												  EXPRKIND_RTFUNC); | 			/*
 | ||||||
|  | 			 * We don't want to do all preprocessing yet on the subquery's | ||||||
|  | 			 * expressions, since that will happen when we plan it.  But if it | ||||||
|  | 			 * contains any join aliases of our level, those have to get | ||||||
|  | 			 * expanded now, because planning of the subquery won't do it. | ||||||
|  | 			 * That's only possible if the subquery is LATERAL. | ||||||
|  | 			 */ | ||||||
|  | 			if (rte->lateral && root->hasJoinRTEs) | ||||||
|  | 				rte->subquery = (Query *) | ||||||
|  | 					flatten_join_alias_vars(root, (Node *) rte->subquery); | ||||||
|  | 		} | ||||||
|  | 		else if (rte->rtekind == RTE_FUNCTION) | ||||||
|  | 		{ | ||||||
|  | 			/* Preprocess the function expression fully */ | ||||||
|  | 			kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC; | ||||||
|  | 			rte->funcexpr = preprocess_expression(root, rte->funcexpr, kind); | ||||||
|  | 		} | ||||||
| 		else if (rte->rtekind == RTE_VALUES) | 		else if (rte->rtekind == RTE_VALUES) | ||||||
|  | 		{ | ||||||
|  | 			/* Preprocess the values lists fully */ | ||||||
|  | 			kind = rte->lateral ? EXPRKIND_VALUES_LATERAL : EXPRKIND_VALUES; | ||||||
| 			rte->values_lists = (List *) | 			rte->values_lists = (List *) | ||||||
| 				preprocess_expression(root, (Node *) rte->values_lists, | 				preprocess_expression(root, (Node *) rte->values_lists, kind); | ||||||
| 									  EXPRKIND_VALUES); | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| @ -594,11 +616,12 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind) | |||||||
| 	/*
 | 	/*
 | ||||||
| 	 * If the query has any join RTEs, replace join alias variables with | 	 * If the query has any join RTEs, replace join alias variables with | ||||||
| 	 * base-relation variables.  We must do this before sublink processing, | 	 * base-relation variables.  We must do this before sublink processing, | ||||||
| 	 * else sublinks expanded out from join aliases wouldn't get processed. We | 	 * else sublinks expanded out from join aliases would not get processed. | ||||||
| 	 * can skip it in VALUES lists, however, since they can't contain any Vars | 	 * We can skip it in non-lateral RTE functions and VALUES lists, however, | ||||||
| 	 * at all. | 	 * since they can't contain any Vars of the current query level. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (root->hasJoinRTEs && kind != EXPRKIND_VALUES) | 	if (root->hasJoinRTEs && | ||||||
|  | 		!(kind == EXPRKIND_RTFUNC || kind == EXPRKIND_VALUES)) | ||||||
| 		expr = flatten_join_alias_vars(root, expr); | 		expr = flatten_join_alias_vars(root, expr); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
|  | |||||||
| @ -600,7 +600,9 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context) | |||||||
|  * hasSubLinks = TRUE, so this is only relevant to un-flattened subqueries. |  * hasSubLinks = TRUE, so this is only relevant to un-flattened subqueries. | ||||||
|  * |  * | ||||||
|  * NOTE: this is used on not-yet-planned expressions.  We do not expect it |  * NOTE: this is used on not-yet-planned expressions.  We do not expect it | ||||||
|  * to be applied directly to a Query node. |  * to be applied directly to the whole Query, so if we see a Query to start | ||||||
|  |  * with, we do want to increment sublevels_up (this occurs for LATERAL | ||||||
|  |  * subqueries). | ||||||
|  */ |  */ | ||||||
| Node * | Node * | ||||||
| flatten_join_alias_vars(PlannerInfo *root, Node *node) | flatten_join_alias_vars(PlannerInfo *root, Node *node) | ||||||
|  | |||||||
| @ -3242,6 +3242,32 @@ select * from int8_tbl a, | |||||||
|  4567890123456789 | -4567890123456789 | 4567890123456789 | -4567890123456789 |                  |  4567890123456789 | -4567890123456789 | 4567890123456789 | -4567890123456789 |                  | ||||||
| (57 rows) | (57 rows) | ||||||
| 
 | 
 | ||||||
|  | -- lateral reference to a join alias variable | ||||||
|  | select * from (select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1, | ||||||
|  |   lateral (select x) ss2(y); | ||||||
|  |  x | f1 | y  | ||||||
|  | ---+----+--- | ||||||
|  |  0 |  0 | 0 | ||||||
|  | (1 row) | ||||||
|  | 
 | ||||||
|  | select * from (select f1 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1, | ||||||
|  |   lateral (values(x)) ss2(y); | ||||||
|  |       x      |     f1      |      y       | ||||||
|  | -------------+-------------+------------- | ||||||
|  |            0 |           0 |           0 | ||||||
|  |       123456 |      123456 |      123456 | ||||||
|  |      -123456 |     -123456 |     -123456 | ||||||
|  |   2147483647 |  2147483647 |  2147483647 | ||||||
|  |  -2147483647 | -2147483647 | -2147483647 | ||||||
|  | (5 rows) | ||||||
|  | 
 | ||||||
|  | select * from ((select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1) j, | ||||||
|  |   lateral (select x) ss2(y); | ||||||
|  |  x | f1 | y  | ||||||
|  | ---+----+--- | ||||||
|  |  0 |  0 | 0 | ||||||
|  | (1 row) | ||||||
|  | 
 | ||||||
| -- lateral references requiring pullup | -- lateral references requiring pullup | ||||||
| select * from (values(1)) x(lb), | select * from (values(1)) x(lb), | ||||||
|   lateral generate_series(lb,4) x4; |   lateral generate_series(lb,4) x4; | ||||||
|  | |||||||
| @ -901,6 +901,14 @@ select * from int8_tbl a, | |||||||
|   int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z) |   int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z) | ||||||
|     on x.q2 = ss.z; |     on x.q2 = ss.z; | ||||||
| 
 | 
 | ||||||
|  | -- lateral reference to a join alias variable | ||||||
|  | select * from (select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1, | ||||||
|  |   lateral (select x) ss2(y); | ||||||
|  | select * from (select f1 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1, | ||||||
|  |   lateral (values(x)) ss2(y); | ||||||
|  | select * from ((select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1) j, | ||||||
|  |   lateral (select x) ss2(y); | ||||||
|  | 
 | ||||||
| -- lateral references requiring pullup | -- lateral references requiring pullup | ||||||
| select * from (values(1)) x(lb), | select * from (values(1)) x(lb), | ||||||
|   lateral generate_series(lb,4) x4; |   lateral generate_series(lb,4) x4; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user