Skip to content

Commit 216977a

Browse files
committed
Fix an oversight in checking whether a join with LATERAL refs is legal.
In many cases, we can implement a semijoin as a plain innerjoin by first passing the righthand-side relation through a unique-ification step. However, one of the cases where this does NOT work is where the RHS has a LATERAL reference to the LHS; that makes the RHS dependent on the LHS so that unique-ification is meaningless. joinpath.c understood this, and so would not generate any join paths of this kind ... but join_is_legal neglected to check for the case, so it would think that we could do it. The upshot would be a "could not devise a query plan for the given query" failure once we had failed to generate any join paths at all for the bogus join pair. Back-patch to 9.3 where LATERAL was added.
1 parent 0efa0f6 commit 216977a

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

src/backend/optimizer/path/joinrels.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,9 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
536536
if (!bms_is_subset(ljinfo->lateral_lhs, rel1->relids))
537537
return false; /* rel1 can't compute the required parameter */
538538
if (match_sjinfo &&
539-
(reversed || match_sjinfo->jointype == JOIN_FULL))
539+
(reversed ||
540+
unique_ified ||
541+
match_sjinfo->jointype == JOIN_FULL))
540542
return false; /* not implementable as nestloop */
541543
}
542544
if (bms_is_subset(ljinfo->lateral_rhs, rel1->relids) &&
@@ -549,7 +551,9 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
549551
if (!bms_is_subset(ljinfo->lateral_lhs, rel2->relids))
550552
return false; /* rel2 can't compute the required parameter */
551553
if (match_sjinfo &&
552-
(!reversed || match_sjinfo->jointype == JOIN_FULL))
554+
(!reversed ||
555+
unique_ified ||
556+
match_sjinfo->jointype == JOIN_FULL))
553557
return false; /* not implementable as nestloop */
554558
}
555559
}

src/test/regress/expected/join.out

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4356,6 +4356,41 @@ select * from
43564356
Output: 3
43574357
(11 rows)
43584358

4359+
-- check we don't try to do a unique-ified semijoin with LATERAL
4360+
explain (verbose, costs off)
4361+
select * from
4362+
(values (0,9998), (1,1000)) v(id,x),
4363+
lateral (select f1 from int4_tbl
4364+
where f1 = any (select unique1 from tenk1
4365+
where unique2 = v.x offset 0)) ss;
4366+
QUERY PLAN
4367+
----------------------------------------------------------------------
4368+
Nested Loop
4369+
Output: "*VALUES*".column1, "*VALUES*".column2, int4_tbl.f1
4370+
-> Values Scan on "*VALUES*"
4371+
Output: "*VALUES*".column1, "*VALUES*".column2
4372+
-> Hash Semi Join
4373+
Output: int4_tbl.f1
4374+
Hash Cond: (int4_tbl.f1 = tenk1.unique1)
4375+
-> Seq Scan on public.int4_tbl
4376+
Output: int4_tbl.f1
4377+
-> Hash
4378+
Output: tenk1.unique1
4379+
-> Index Scan using tenk1_unique2 on public.tenk1
4380+
Output: tenk1.unique1
4381+
Index Cond: (tenk1.unique2 = "*VALUES*".column2)
4382+
(14 rows)
4383+
4384+
select * from
4385+
(values (0,9998), (1,1000)) v(id,x),
4386+
lateral (select f1 from int4_tbl
4387+
where f1 = any (select unique1 from tenk1
4388+
where unique2 = v.x offset 0)) ss;
4389+
id | x | f1
4390+
----+------+----
4391+
0 | 9998 | 0
4392+
(1 row)
4393+
43594394
-- test some error cases where LATERAL should have been used but wasn't
43604395
select f1,g from int4_tbl a, (select f1 as g) ss;
43614396
ERROR: column "f1" does not exist

src/test/regress/sql/join.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,19 @@ select * from
12861286
select * from (select 3 as z) z where z.z = x.x
12871287
) zz on zz.z = y.y;
12881288

1289+
-- check we don't try to do a unique-ified semijoin with LATERAL
1290+
explain (verbose, costs off)
1291+
select * from
1292+
(values (0,9998), (1,1000)) v(id,x),
1293+
lateral (select f1 from int4_tbl
1294+
where f1 = any (select unique1 from tenk1
1295+
where unique2 = v.x offset 0)) ss;
1296+
select * from
1297+
(values (0,9998), (1,1000)) v(id,x),
1298+
lateral (select f1 from int4_tbl
1299+
where f1 = any (select unique1 from tenk1
1300+
where unique2 = v.x offset 0)) ss;
1301+
12891302
-- test some error cases where LATERAL should have been used but wasn't
12901303
select f1,g from int4_tbl a, (select f1 as g) ss;
12911304
select f1,g from int4_tbl a, (select a.f1 as g) ss;

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