Skip to content

Commit 489072a

Browse files
committed
Replace relids in lateral subquery parse tree during SJE
Reported-by: Alexander Lakhin Discussion: https://postgr.es/m/56ee4520-e9d1-d519-54fe-c8bff880ce9b%40gmail.com Author: Alexander Korotkov, Andrei Lepikhov
1 parent 74563f6 commit 489072a

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

src/backend/optimizer/plan/analyzejoins.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,34 @@ remove_rel_from_query(PlannerInfo *root, RelOptInfo *rel,
395395
}
396396

397397
/* Update lateral references. */
398-
replace_varno((Node *) otherrel->lateral_vars, relid, subst);
398+
if (root->hasLateralRTEs)
399+
{
400+
RangeTblEntry *rte = root->simple_rte_array[rti];
401+
ReplaceVarnoContext ctx = {.from = relid,.to = subst};
402+
403+
if (rte->lateral)
404+
{
405+
replace_varno((Node *) otherrel->lateral_vars, relid, subst);
406+
407+
/*
408+
* Although we pass root->parse through cleanup procedure,
409+
* but parse->rtable and rte contains refs to different copies
410+
* of the subquery.
411+
*/
412+
if (otherrel->rtekind == RTE_SUBQUERY)
413+
query_tree_walker(rte->subquery, replace_varno_walker, &ctx,
414+
QTW_EXAMINE_SORTGROUP);
415+
#ifdef USE_ASSERT_CHECKING
416+
/* Just check possibly hidden non-replaced relids */
417+
Assert(!bms_is_member(relid, pull_varnos(root, (Node *) rte->tablesample)));
418+
Assert(!bms_is_member(relid, pull_varnos(root, (Node *) rte->functions)));
419+
Assert(!bms_is_member(relid, pull_varnos(root, (Node *) rte->tablefunc)));
420+
Assert(!bms_is_member(relid, pull_varnos(root, (Node *) rte->values_lists)));
421+
#endif
422+
}
423+
}
424+
425+
399426
}
400427

401428
/*

src/test/regress/expected/join.out

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6349,6 +6349,50 @@ on true;
63496349
-> Seq Scan on int8_tbl y
63506350
(7 rows)
63516351

6352+
-- Test processing target lists in lateral subqueries
6353+
explain (verbose, costs off)
6354+
SELECT t3.a FROM sj t1, sj t2,
6355+
LATERAL (SELECT t1.a WHERE t1.a <> 1
6356+
GROUP BY (t1.a) HAVING t1.a > 0 ORDER BY t1.a LIMIT 1) t3,
6357+
LATERAL (SELECT t1.a,t3.a WHERE t1.a <> t3.a+t2.a
6358+
GROUP BY (t3.a) HAVING t1.a > t3.a*t3.a+t2.a/t1.a LIMIT 2) t4,
6359+
LATERAL (SELECT * FROM sj TABLESAMPLE bernoulli(t1.a/t2.a)
6360+
REPEATABLE (t1.a+t2.a)) t5,
6361+
LATERAL generate_series(1, t1.a + t2.a) AS t6
6362+
WHERE t1.a = t2.a;
6363+
QUERY PLAN
6364+
-------------------------------------------------------------------------------------------------------------------------------
6365+
Nested Loop
6366+
Output: (t2.a)
6367+
-> Nested Loop
6368+
Output: t2.a, (t2.a)
6369+
-> Nested Loop
6370+
Output: t2.a, (t2.a)
6371+
-> Nested Loop
6372+
Output: t2.a, (t2.a)
6373+
-> Seq Scan on public.sj t2
6374+
Output: t2.a, t2.b, t2.c
6375+
Filter: (t2.a IS NOT NULL)
6376+
-> Limit
6377+
Output: (t2.a)
6378+
-> Group
6379+
Output: t2.a
6380+
-> Result
6381+
One-Time Filter: ((t2.a <> 1) AND (t2.a > 0))
6382+
-> Limit
6383+
Output: NULL::integer, ((t2.a))
6384+
-> Group
6385+
Output: NULL::integer, (t2.a)
6386+
-> Result
6387+
One-Time Filter: ((t2.a <> ((t2.a) + t2.a)) AND (t2.a > (((t2.a) * (t2.a)) + (t2.a / t2.a))))
6388+
-> Sample Scan on public.sj
6389+
Output: sj.a, sj.b, sj.c
6390+
Sampling: bernoulli ((t2.a / t2.a)) REPEATABLE ((t2.a + t2.a))
6391+
-> Function Scan on pg_catalog.generate_series t6
6392+
Output: t6.t6
6393+
Function Call: generate_series(1, (t2.a + t2.a))
6394+
(29 rows)
6395+
63526396
-- Check updating of Lateral links from top-level query to the removing relation
63536397
explain (COSTS OFF)
63546398
SELECT * FROM pg_am am WHERE am.amname IN (

src/test/regress/sql/join.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2406,6 +2406,18 @@ left join (select coalesce(y.q1, 1) from int8_tbl y
24062406
on true) z
24072407
on true;
24082408

2409+
-- Test processing target lists in lateral subqueries
2410+
explain (verbose, costs off)
2411+
SELECT t3.a FROM sj t1, sj t2,
2412+
LATERAL (SELECT t1.a WHERE t1.a <> 1
2413+
GROUP BY (t1.a) HAVING t1.a > 0 ORDER BY t1.a LIMIT 1) t3,
2414+
LATERAL (SELECT t1.a,t3.a WHERE t1.a <> t3.a+t2.a
2415+
GROUP BY (t3.a) HAVING t1.a > t3.a*t3.a+t2.a/t1.a LIMIT 2) t4,
2416+
LATERAL (SELECT * FROM sj TABLESAMPLE bernoulli(t1.a/t2.a)
2417+
REPEATABLE (t1.a+t2.a)) t5,
2418+
LATERAL generate_series(1, t1.a + t2.a) AS t6
2419+
WHERE t1.a = t2.a;
2420+
24092421
-- Check updating of Lateral links from top-level query to the removing relation
24102422
explain (COSTS OFF)
24112423
SELECT * FROM pg_am am WHERE am.amname IN (

0 commit comments

Comments
 (0)