aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-10-14 13:07:29 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2018-10-14 13:07:29 -0400
commit7d4a10e260083bc571ea05592884084eabcc7afa (patch)
tree132bec3d0ce4e8e6bbd0c58811e1291effb006aa /src
parente9f42d529f990f94e1b7bdcec4a1111465c85326 (diff)
downloadpostgresql-7d4a10e260083bc571ea05592884084eabcc7afa.tar.gz
postgresql-7d4a10e260083bc571ea05592884084eabcc7afa.zip
Use PlaceHolderVars within the quals of a FULL JOIN.
This prevents failures in cases where we pull up a constant or var-free expression from a subquery and put it into a full join's qual. That can result in not recognizing the qual as containing a mergejoin-able or hashjoin-able condition. A PHV prevents the problem because it is still recognized as belonging to the side of the join the subquery is in. I'm not very sure about the net effect of this change on plan quality. In "typical" cases where the join keys are Vars, nothing changes. In an affected case, the PHV-wrapped expression is less likely to be seen as equal to PHV-less instances below the join, but more likely to be seen as equal to similar expressions above the join, so it may end up being a wash. In the one existing case where there's any visible change in a regression-test plan, it amounts to referencing a lower computation of a COALESCE result instead of recomputing it, which seems like a win. Given my uncertainty about that and the lack of field complaints, no back-patch, even though this is a very ancient problem. Discussion: https://postgr.es/m/32090.1539378124@sss.pgh.pa.us
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/prep/prepjointree.c12
-rw-r--r--src/test/regress/expected/join.out16
-rw-r--r--src/test/regress/sql/join.sql7
3 files changed, 34 insertions, 1 deletions
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 688b3a1c396..cd6e11904ee 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2044,6 +2044,18 @@ replace_vars_in_jointree(Node *jtnode,
}
replace_vars_in_jointree(j->larg, context, lowest_nulling_outer_join);
replace_vars_in_jointree(j->rarg, context, lowest_nulling_outer_join);
+
+ /*
+ * Use PHVs within the join quals of a full join, even when it's the
+ * lowest nulling outer join. Otherwise, we cannot identify which
+ * side of the join a pulled-up var-free expression came from, which
+ * can lead to failure to make a plan at all because none of the quals
+ * appear to be mergeable or hashable conditions. For this purpose we
+ * don't care about the state of wrap_non_vars, so leave it alone.
+ */
+ if (j->jointype == JOIN_FULL)
+ context->need_phvs = true;
+
j->quals = pullup_replace_vars(j->quals, context);
/*
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index dc6262be43a..1f5378080d3 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2024,6 +2024,20 @@ NATURAL FULL JOIN
ee | | 42 | 2 |
(4 rows)
+-- Constants as join keys can also be problematic
+SELECT * FROM
+ (SELECT name, n as s1_n FROM t1) as s1
+FULL JOIN
+ (SELECT name, 2 as s2_n FROM t2) as s2
+ON (s1_n = s2_n);
+ name | s1_n | name | s2_n
+------+------+------+------
+ | | bb | 2
+ | | cc | 2
+ | | ee | 2
+ bb | 11 | |
+(4 rows)
+
-- Test for propagation of nullability constraints into sub-joins
create temp table x (x1 int, x2 int);
insert into x values (1,11);
@@ -2854,7 +2868,7 @@ SELECT qq, unique1
---------------------------------------------------------------------------------------------------------
Nested Loop
-> Hash Full Join
- Hash Cond: (COALESCE(a.q1, '0'::bigint) = COALESCE(b.q2, '-1'::bigint))
+ Hash Cond: ((COALESCE(a.q1, '0'::bigint)) = (COALESCE(b.q2, '-1'::bigint)))
-> Seq Scan on int8_tbl a
-> Hash
-> Seq Scan on int8_tbl b
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index d3ba2a1c339..334a4dce2d0 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -297,6 +297,13 @@ NATURAL FULL JOIN
(SELECT name, n as s3_n FROM t3) as s3
) ss2;
+-- Constants as join keys can also be problematic
+SELECT * FROM
+ (SELECT name, n as s1_n FROM t1) as s1
+FULL JOIN
+ (SELECT name, 2 as s2_n FROM t2) as s2
+ON (s1_n = s2_n);
+
-- Test for propagation of nullability constraints into sub-joins