diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index d6a305aedac..50651813a11 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -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) diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 042060f3aa4..b9c791f3821 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -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, diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index c373cdeaa52..d51e702c3f6 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -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,