diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2014-07-15 21:12:43 -0400 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2014-07-15 21:12:43 -0400 |
| commit | f15821eefd70941d4ec5bd77d75c1da5534ba6b2 (patch) | |
| tree | e5700bb11d48a7c28871d144f0db548e982591d4 /src/test/regress/sql/join.sql | |
| parent | 5571caf42d62ea30c452b0ae5f1748289ae613b4 (diff) | |
| download | postgresql-f15821eefd70941d4ec5bd77d75c1da5534ba6b2.tar.gz | |
Allow join removal in some cases involving a left join to a subquery.
We can remove a left join to a relation if the relation's output is
provably distinct for the columns involved in the join clause (considering
only equijoin clauses) and the relation supplies no variables needed above
the join. Previously, the join removal logic could only prove distinctness
by reference to unique indexes of a table. This patch extends the logic
to consider subquery relations, wherein distinctness might be proven by
reference to GROUP BY, DISTINCT, etc.
We actually already had some code to check that a subquery's output was
provably distinct, but it was hidden inside pathnode.c; which was a pretty
bad place for it really, since that file is mostly boilerplate Path
construction and comparison. Move that code to analyzejoins.c, which is
arguably a more appropriate location, and is certainly the site of the
new usage for it.
David Rowley, reviewed by Simon Riggs
Diffstat (limited to 'src/test/regress/sql/join.sql')
| -rw-r--r-- | src/test/regress/sql/join.sql | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index 1031f26b31..fa3e068626 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -919,9 +919,11 @@ begin; CREATE TEMP TABLE a (id int PRIMARY KEY, b_id int); CREATE TEMP TABLE b (id int PRIMARY KEY, c_id int); CREATE TEMP TABLE c (id int PRIMARY KEY); +CREATE TEMP TABLE d (a int, b int); INSERT INTO a VALUES (0, 0), (1, NULL); INSERT INTO b VALUES (0, 0), (1, NULL); INSERT INTO c VALUES (0), (1); +INSERT INTO d VALUES (1,3), (2,2), (3,1); -- all three cases should be optimizable into a simple seqscan explain (costs off) SELECT a.* FROM a LEFT JOIN b ON a.b_id = b.id; @@ -936,6 +938,39 @@ select id from a where id in ( select b.id from b left join c on b.id = c.id ); +-- check that join removal works for a left join when joining a subquery +-- that is guaranteed to be unique by its GROUP BY clause +explain (costs off) +select d.* from d left join (select * from b group by b.id, b.c_id) s + on d.a = s.id and d.b = s.c_id; + +-- similarly, but keying off a DISTINCT clause +explain (costs off) +select d.* from d left join (select distinct * from b) s + on d.a = s.id and d.b = s.c_id; + +-- join removal is not possible when the GROUP BY contains a column that is +-- not in the join condition +explain (costs off) +select d.* from d left join (select * from b group by b.id, b.c_id) s + on d.a = s.id; + +-- similarly, but keying off a DISTINCT clause +explain (costs off) +select d.* from d left join (select distinct * from b) s + on d.a = s.id; + +-- check join removal works when uniqueness of the join condition is enforced +-- by a UNION +explain (costs off) +select d.* from d left join (select id from a union select id from b) s + on d.a = s.id; + +-- check join removal with a cross-type comparison operator +explain (costs off) +select i8.* from int8_tbl i8 left join (select f1 from int4_tbl group by f1) i4 + on i8.q1 = i4.f1; + rollback; create temp table parent (k int primary key, pd int); |
