Skip to content

Commit da3df99

Browse files
committed
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() ...
1 parent f789909 commit da3df99

File tree

4 files changed

+78
-19
lines changed

4 files changed

+78
-19
lines changed

src/backend/optimizer/plan/planner.c

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,15 @@ planner_hook_type planner_hook = NULL;
4949

5050

5151
/* Expression kind codes for preprocess_expression */
52-
#define EXPRKIND_QUAL 0
53-
#define EXPRKIND_TARGET 1
54-
#define EXPRKIND_RTFUNC 2
55-
#define EXPRKIND_VALUES 3
56-
#define EXPRKIND_LIMIT 4
57-
#define EXPRKIND_APPINFO 5
58-
#define EXPRKIND_PHV 6
52+
#define EXPRKIND_QUAL 0
53+
#define EXPRKIND_TARGET 1
54+
#define EXPRKIND_RTFUNC 2
55+
#define EXPRKIND_RTFUNC_LATERAL 3
56+
#define EXPRKIND_VALUES 4
57+
#define EXPRKIND_VALUES_LATERAL 5
58+
#define EXPRKIND_LIMIT 6
59+
#define EXPRKIND_APPINFO 7
60+
#define EXPRKIND_PHV 8
5961

6062

6163
static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
@@ -438,18 +440,38 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
438440
preprocess_expression(root, (Node *) root->append_rel_list,
439441
EXPRKIND_APPINFO);
440442

441-
/* Also need to preprocess expressions for function and values RTEs */
443+
/* Also need to preprocess expressions within RTEs */
442444
foreach(l, parse->rtable)
443445
{
444446
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
447+
int kind;
445448

446-
if (rte->rtekind == RTE_FUNCTION)
447-
rte->funcexpr = preprocess_expression(root, rte->funcexpr,
448-
EXPRKIND_RTFUNC);
449+
if (rte->rtekind == RTE_SUBQUERY)
450+
{
451+
/*
452+
* We don't want to do all preprocessing yet on the subquery's
453+
* expressions, since that will happen when we plan it. But if it
454+
* contains any join aliases of our level, those have to get
455+
* expanded now, because planning of the subquery won't do it.
456+
* That's only possible if the subquery is LATERAL.
457+
*/
458+
if (rte->lateral && root->hasJoinRTEs)
459+
rte->subquery = (Query *)
460+
flatten_join_alias_vars(root, (Node *) rte->subquery);
461+
}
462+
else if (rte->rtekind == RTE_FUNCTION)
463+
{
464+
/* Preprocess the function expression fully */
465+
kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC;
466+
rte->funcexpr = preprocess_expression(root, rte->funcexpr, kind);
467+
}
449468
else if (rte->rtekind == RTE_VALUES)
469+
{
470+
/* Preprocess the values lists fully */
471+
kind = rte->lateral ? EXPRKIND_VALUES_LATERAL : EXPRKIND_VALUES;
450472
rte->values_lists = (List *)
451-
preprocess_expression(root, (Node *) rte->values_lists,
452-
EXPRKIND_VALUES);
473+
preprocess_expression(root, (Node *) rte->values_lists, kind);
474+
}
453475
}
454476

455477
/*
@@ -593,12 +615,13 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
593615

594616
/*
595617
* If the query has any join RTEs, replace join alias variables with
596-
* base-relation variables. We must do this before sublink processing,
597-
* else sublinks expanded out from join aliases wouldn't get processed. We
598-
* can skip it in VALUES lists, however, since they can't contain any Vars
599-
* at all.
618+
* base-relation variables. We must do this before sublink processing,
619+
* else sublinks expanded out from join aliases would not get processed.
620+
* We can skip it in non-lateral RTE functions and VALUES lists, however,
621+
* since they can't contain any Vars of the current query level.
600622
*/
601-
if (root->hasJoinRTEs && kind != EXPRKIND_VALUES)
623+
if (root->hasJoinRTEs &&
624+
!(kind == EXPRKIND_RTFUNC || kind == EXPRKIND_VALUES))
602625
expr = flatten_join_alias_vars(root, expr);
603626

604627
/*

src/backend/optimizer/util/var.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,9 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context)
600600
* hasSubLinks = TRUE, so this is only relevant to un-flattened subqueries.
601601
*
602602
* NOTE: this is used on not-yet-planned expressions. We do not expect it
603-
* to be applied directly to a Query node.
603+
* to be applied directly to the whole Query, so if we see a Query to start
604+
* with, we do want to increment sublevels_up (this occurs for LATERAL
605+
* subqueries).
604606
*/
605607
Node *
606608
flatten_join_alias_vars(PlannerInfo *root, Node *node)

src/test/regress/expected/join.out

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3242,6 +3242,32 @@ select * from int8_tbl a,
32423242
4567890123456789 | -4567890123456789 | 4567890123456789 | -4567890123456789 |
32433243
(57 rows)
32443244

3245+
-- lateral reference to a join alias variable
3246+
select * from (select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1,
3247+
lateral (select x) ss2(y);
3248+
x | f1 | y
3249+
---+----+---
3250+
0 | 0 | 0
3251+
(1 row)
3252+
3253+
select * from (select f1 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1,
3254+
lateral (values(x)) ss2(y);
3255+
x | f1 | y
3256+
-------------+-------------+-------------
3257+
0 | 0 | 0
3258+
123456 | 123456 | 123456
3259+
-123456 | -123456 | -123456
3260+
2147483647 | 2147483647 | 2147483647
3261+
-2147483647 | -2147483647 | -2147483647
3262+
(5 rows)
3263+
3264+
select * from ((select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1) j,
3265+
lateral (select x) ss2(y);
3266+
x | f1 | y
3267+
---+----+---
3268+
0 | 0 | 0
3269+
(1 row)
3270+
32453271
-- lateral references requiring pullup
32463272
select * from (values(1)) x(lb),
32473273
lateral generate_series(lb,4) x4;

src/test/regress/sql/join.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,14 @@ select * from int8_tbl a,
901901
int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z)
902902
on x.q2 = ss.z;
903903

904+
-- lateral reference to a join alias variable
905+
select * from (select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1,
906+
lateral (select x) ss2(y);
907+
select * from (select f1 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1,
908+
lateral (values(x)) ss2(y);
909+
select * from ((select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1) j,
910+
lateral (select x) ss2(y);
911+
904912
-- lateral references requiring pullup
905913
select * from (values(1)) x(lb),
906914
lateral generate_series(lb,4) x4;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy