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
This commit is contained in:
parent
74563f6b90
commit
489072ab7a
3 changed files with 84 additions and 1 deletions
|
@ -395,7 +395,34 @@ remove_rel_from_query(PlannerInfo *root, RelOptInfo *rel,
|
|||
}
|
||||
|
||||
/* Update lateral references. */
|
||||
replace_varno((Node *) otherrel->lateral_vars, relid, subst);
|
||||
if (root->hasLateralRTEs)
|
||||
{
|
||||
RangeTblEntry *rte = root->simple_rte_array[rti];
|
||||
ReplaceVarnoContext ctx = {.from = relid,.to = subst};
|
||||
|
||||
if (rte->lateral)
|
||||
{
|
||||
replace_varno((Node *) otherrel->lateral_vars, relid, subst);
|
||||
|
||||
/*
|
||||
* Although we pass root->parse through cleanup procedure,
|
||||
* but parse->rtable and rte contains refs to different copies
|
||||
* of the subquery.
|
||||
*/
|
||||
if (otherrel->rtekind == RTE_SUBQUERY)
|
||||
query_tree_walker(rte->subquery, replace_varno_walker, &ctx,
|
||||
QTW_EXAMINE_SORTGROUP);
|
||||
#ifdef USE_ASSERT_CHECKING
|
||||
/* Just check possibly hidden non-replaced relids */
|
||||
Assert(!bms_is_member(relid, pull_varnos(root, (Node *) rte->tablesample)));
|
||||
Assert(!bms_is_member(relid, pull_varnos(root, (Node *) rte->functions)));
|
||||
Assert(!bms_is_member(relid, pull_varnos(root, (Node *) rte->tablefunc)));
|
||||
Assert(!bms_is_member(relid, pull_varnos(root, (Node *) rte->values_lists)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -6349,6 +6349,50 @@ on true;
|
|||
-> Seq Scan on int8_tbl y
|
||||
(7 rows)
|
||||
|
||||
-- Test processing target lists in lateral subqueries
|
||||
explain (verbose, costs off)
|
||||
SELECT t3.a FROM sj t1, sj t2,
|
||||
LATERAL (SELECT t1.a WHERE t1.a <> 1
|
||||
GROUP BY (t1.a) HAVING t1.a > 0 ORDER BY t1.a LIMIT 1) t3,
|
||||
LATERAL (SELECT t1.a,t3.a WHERE t1.a <> t3.a+t2.a
|
||||
GROUP BY (t3.a) HAVING t1.a > t3.a*t3.a+t2.a/t1.a LIMIT 2) t4,
|
||||
LATERAL (SELECT * FROM sj TABLESAMPLE bernoulli(t1.a/t2.a)
|
||||
REPEATABLE (t1.a+t2.a)) t5,
|
||||
LATERAL generate_series(1, t1.a + t2.a) AS t6
|
||||
WHERE t1.a = t2.a;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------
|
||||
Nested Loop
|
||||
Output: (t2.a)
|
||||
-> Nested Loop
|
||||
Output: t2.a, (t2.a)
|
||||
-> Nested Loop
|
||||
Output: t2.a, (t2.a)
|
||||
-> Nested Loop
|
||||
Output: t2.a, (t2.a)
|
||||
-> Seq Scan on public.sj t2
|
||||
Output: t2.a, t2.b, t2.c
|
||||
Filter: (t2.a IS NOT NULL)
|
||||
-> Limit
|
||||
Output: (t2.a)
|
||||
-> Group
|
||||
Output: t2.a
|
||||
-> Result
|
||||
One-Time Filter: ((t2.a <> 1) AND (t2.a > 0))
|
||||
-> Limit
|
||||
Output: NULL::integer, ((t2.a))
|
||||
-> Group
|
||||
Output: NULL::integer, (t2.a)
|
||||
-> Result
|
||||
One-Time Filter: ((t2.a <> ((t2.a) + t2.a)) AND (t2.a > (((t2.a) * (t2.a)) + (t2.a / t2.a))))
|
||||
-> Sample Scan on public.sj
|
||||
Output: sj.a, sj.b, sj.c
|
||||
Sampling: bernoulli ((t2.a / t2.a)) REPEATABLE ((t2.a + t2.a))
|
||||
-> Function Scan on pg_catalog.generate_series t6
|
||||
Output: t6.t6
|
||||
Function Call: generate_series(1, (t2.a + t2.a))
|
||||
(29 rows)
|
||||
|
||||
-- Check updating of Lateral links from top-level query to the removing relation
|
||||
explain (COSTS OFF)
|
||||
SELECT * FROM pg_am am WHERE am.amname IN (
|
||||
|
|
|
@ -2406,6 +2406,18 @@ left join (select coalesce(y.q1, 1) from int8_tbl y
|
|||
on true) z
|
||||
on true;
|
||||
|
||||
-- Test processing target lists in lateral subqueries
|
||||
explain (verbose, costs off)
|
||||
SELECT t3.a FROM sj t1, sj t2,
|
||||
LATERAL (SELECT t1.a WHERE t1.a <> 1
|
||||
GROUP BY (t1.a) HAVING t1.a > 0 ORDER BY t1.a LIMIT 1) t3,
|
||||
LATERAL (SELECT t1.a,t3.a WHERE t1.a <> t3.a+t2.a
|
||||
GROUP BY (t3.a) HAVING t1.a > t3.a*t3.a+t2.a/t1.a LIMIT 2) t4,
|
||||
LATERAL (SELECT * FROM sj TABLESAMPLE bernoulli(t1.a/t2.a)
|
||||
REPEATABLE (t1.a+t2.a)) t5,
|
||||
LATERAL generate_series(1, t1.a + t2.a) AS t6
|
||||
WHERE t1.a = t2.a;
|
||||
|
||||
-- Check updating of Lateral links from top-level query to the removing relation
|
||||
explain (COSTS OFF)
|
||||
SELECT * FROM pg_am am WHERE am.amname IN (
|
||||
|
|
Loading…
Reference in a new issue