From ab76208e3df6841b3770edeece57d0f048392237 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 9 Jun 2014 21:37:18 -0400 Subject: [PATCH] Forward-port regression test for bug #10587 into 9.3 and HEAD. Although this bug is already fixed in post-9.2 branches, the case triggering it is quite different from what was under consideration at the time. It seems worth memorializing this example in HEAD just to make sure it doesn't get broken again in future. Extracted from commit 187ae17300776f48b2bd9d0737923b1bf70f606e. --- src/test/regress/expected/join.out | 71 ++++++++++++++++++++++++++++++ src/test/regress/sql/join.sql | 58 ++++++++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 934488a6b59..c62a63f6740 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -2564,6 +2564,77 @@ SELECT qq, unique1 456 | 7318 (3 rows) +-- +-- nested nestloops can require nested PlaceHolderVars +-- +create temp table nt1 ( + id int primary key, + a1 boolean, + a2 boolean +); +create temp table nt2 ( + id int primary key, + nt1_id int, + b1 boolean, + b2 boolean, + foreign key (nt1_id) references nt1(id) +); +create temp table nt3 ( + id int primary key, + nt2_id int, + c1 boolean, + foreign key (nt2_id) references nt2(id) +); +insert into nt1 values (1,true,true); +insert into nt1 values (2,true,false); +insert into nt1 values (3,false,false); +insert into nt2 values (1,1,true,true); +insert into nt2 values (2,2,true,false); +insert into nt2 values (3,3,false,false); +insert into nt3 values (1,1,true); +insert into nt3 values (2,2,false); +insert into nt3 values (3,3,true); +explain (costs off) +select nt3.id +from nt3 as nt3 + left join + (select nt2.*, (nt2.b1 and ss1.a3) AS b3 + from nt2 as nt2 + left join + (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1 + on ss1.id = nt2.nt1_id + ) as ss2 + on ss2.id = nt3.nt2_id +where nt3.id = 1 and ss2.b3; + QUERY PLAN +----------------------------------------------- + Nested Loop + -> Nested Loop + -> Index Scan using nt3_pkey on nt3 + Index Cond: (id = 1) + -> Index Scan using nt2_pkey on nt2 + Index Cond: (id = nt3.nt2_id) + -> Index Only Scan using nt1_pkey on nt1 + Index Cond: (id = nt2.nt1_id) + Filter: (nt2.b1 AND (id IS NOT NULL)) +(9 rows) + +select nt3.id +from nt3 as nt3 + left join + (select nt2.*, (nt2.b1 and ss1.a3) AS b3 + from nt2 as nt2 + left join + (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1 + on ss1.id = nt2.nt1_id + ) as ss2 + on ss2.id = nt3.nt2_id +where nt3.id = 1 and ss2.b3; + id +---- + 1 +(1 row) + -- -- test case where a PlaceHolderVar is propagated into a subquery -- diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index 275cb11fdfc..1031f26b314 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -660,6 +660,64 @@ SELECT qq, unique1 USING (qq) INNER JOIN tenk1 c ON qq = unique2; +-- +-- nested nestloops can require nested PlaceHolderVars +-- + +create temp table nt1 ( + id int primary key, + a1 boolean, + a2 boolean +); +create temp table nt2 ( + id int primary key, + nt1_id int, + b1 boolean, + b2 boolean, + foreign key (nt1_id) references nt1(id) +); +create temp table nt3 ( + id int primary key, + nt2_id int, + c1 boolean, + foreign key (nt2_id) references nt2(id) +); + +insert into nt1 values (1,true,true); +insert into nt1 values (2,true,false); +insert into nt1 values (3,false,false); +insert into nt2 values (1,1,true,true); +insert into nt2 values (2,2,true,false); +insert into nt2 values (3,3,false,false); +insert into nt3 values (1,1,true); +insert into nt3 values (2,2,false); +insert into nt3 values (3,3,true); + +explain (costs off) +select nt3.id +from nt3 as nt3 + left join + (select nt2.*, (nt2.b1 and ss1.a3) AS b3 + from nt2 as nt2 + left join + (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1 + on ss1.id = nt2.nt1_id + ) as ss2 + on ss2.id = nt3.nt2_id +where nt3.id = 1 and ss2.b3; + +select nt3.id +from nt3 as nt3 + left join + (select nt2.*, (nt2.b1 and ss1.a3) AS b3 + from nt2 as nt2 + left join + (select nt1.*, (nt1.id is not null) as a3 from nt1) as ss1 + on ss1.id = nt2.nt1_id + ) as ss2 + on ss2.id = nt3.nt2_id +where nt3.id = 1 and ss2.b3; + -- -- test case where a PlaceHolderVar is propagated into a subquery --