1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Fix bogus Assert in find_var_for_subquery_tle

find_var_for_subquery_tle() searches a subquery rel's targetlist for a
Var referencing a given subquery output column, and asserted that any
Var it finds there belongs to that rel.  That does not hold for an
appendrel child.  set_append_rel_size() builds the child's targetlist
by translating the parent's, and as noted there the result can contain
arbitrary expressions.  In particular, when a member of a LATERAL UNION
ALL subquery is pulled up and its output is a lateral reference, the
translated expression is a Var of the laterally referenced rel.  If the
child is itself a subquery with sorted paths, convert_subquery_pathkeys()
would trip the Assert.

In non-assert builds, the function went on to compare such a Var's
varattno with the subquery column's resno, and so could match a Var of
an unrelated rel.

To fix, ignore Vars that do not belong to the subquery rel, the same
way set_rel_width() already does.  Also correct the adjacent comment,
which claimed that the only non-Var entries are placeholders.

Back-patch to all supported branches.

Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: shihao zhong <zhong950419@gmail.com>
Discussion: https://postgr.es/m/CAMbWs48fFiPi7Q5yJCoM_nAs47zd5XgvPHd9nZyM_ewq+k_jpQ@mail.gmail.com
Backpatch-through: 14
This commit is contained in:
Richard Guo
2026-10-16 16:45:03 +09:00
parent eb7cc1d09e
commit 11b56ee273
3 changed files with 35 additions and 2 deletions

View File

@@ -1262,10 +1262,18 @@ find_var_for_subquery_tle(RelOptInfo *rel, TargetEntry *tle)
{
Var *var = (Var *) lfirst(lc);
/* Ignore placeholders */
/* Ignore placeholders and other non-Var expressions */
if (!IsA(var, Var))
continue;
Assert(var->varno == rel->relid);
/*
* Ordinarily, a Var in a rel's targetlist must belong to that rel;
* but there are corner cases involving LATERAL references where that
* isn't so. If the Var has the wrong varno, ignore it, since it
* cannot be referencing the subquery's output.
*/
if (var->varno != rel->relid)
continue;
/* If we find a Var referencing this TLE, we're good */
if (var->varattno == tle->resno)

View File

@@ -10364,6 +10364,24 @@ select * from generate_series(100,200) g,
123 | 4567890123456789 | 123
(3 rows)
-- lateral with UNION ALL subselect, where a member is a subquery whose
-- output contains a lateral reference
explain (costs off)
select ss.v from int8_tbl x,
lateral (select x.q1 from (select distinct q2 from int8_tbl) s union all
select q2 from int8_tbl) ss(v);
QUERY PLAN
---------------------------------------------------------
Nested Loop
-> Seq Scan on int8_tbl x
-> Append
-> Subquery Scan on s
-> HashAggregate
Group Key: int8_tbl_1.q2
-> Seq Scan on int8_tbl int8_tbl_1
-> Seq Scan on int8_tbl
(8 rows)
-- lateral with VALUES
explain (costs off)
select count(*) from tenk1 a,

View File

@@ -4043,6 +4043,13 @@ select * from generate_series(100,200) g,
lateral (select * from int8_tbl a where g = q1 union all
select * from int8_tbl b where g = q2) ss;
-- lateral with UNION ALL subselect, where a member is a subquery whose
-- output contains a lateral reference
explain (costs off)
select ss.v from int8_tbl x,
lateral (select x.q1 from (select distinct q2 from int8_tbl) s union all
select q2 from int8_tbl) ss(v);
-- lateral with VALUES
explain (costs off)
select count(*) from tenk1 a,