aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-02-10 17:08:50 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-02-10 17:08:50 +0000
commit8a4fdce9f277fe1f02654091e89e96180af9c4cb (patch)
treed55143b4f8782ad8f710573191ce50a688d1e1bd /src/backend
parentec8f0e82ef63927e48615b2684258eb8ce84c599 (diff)
downloadpostgresql-8a4fdce9f277fe1f02654091e89e96180af9c4cb.tar.gz
postgresql-8a4fdce9f277fe1f02654091e89e96180af9c4cb.zip
Fix thinko in new logic about pushing down non-nullability constraints:
constraints appearing in outer-join qualification clauses are restricted as to when and where they can be pushed down. Add regression test to catch future errors in this area.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/optimizer/prep/prepjointree.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 54fd393df59..207a813e8e0 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -16,7 +16,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.5 2003/02/09 23:57:19 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.6 2003/02/10 17:08:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -694,23 +694,45 @@ reduce_outer_joins_pass2(Node *jtnode,
/* Only recurse if there's more to do below here */
if (left_state->contains_outer || right_state->contains_outer)
{
+ Relids local_nonnullable;
Relids pass_nonnullable;
/*
- * Scan join quals to see if we can add any nonnullability
- * constraints. (Okay to do this even if join is still outer.)
+ * If this join is (now) inner, we can add any nonnullability
+ * constraints its quals provide to those we got from above.
+ * But if it is outer, we can only pass down the local constraints
+ * into the nullable side, because an outer join never eliminates
+ * any rows from its non-nullable side. If it's a FULL join then
+ * it doesn't eliminate anything from either side.
*/
- pass_nonnullable = find_nonnullable_rels(j->quals, true);
- pass_nonnullable = bms_add_members(pass_nonnullable,
- nonnullable_rels);
- /* And recurse as needed */
+ if (jointype != JOIN_FULL)
+ {
+ local_nonnullable = find_nonnullable_rels(j->quals, true);
+ local_nonnullable = bms_add_members(local_nonnullable,
+ nonnullable_rels);
+ }
+ else
+ local_nonnullable = NULL; /* no use in calculating it */
+
if (left_state->contains_outer)
+ {
+ if (jointype == JOIN_INNER || jointype == JOIN_RIGHT)
+ pass_nonnullable = local_nonnullable;
+ else
+ pass_nonnullable = nonnullable_rels;
reduce_outer_joins_pass2(j->larg, left_state, parse,
pass_nonnullable);
+ }
if (right_state->contains_outer)
+ {
+ if (jointype == JOIN_INNER || jointype == JOIN_LEFT)
+ pass_nonnullable = local_nonnullable;
+ else
+ pass_nonnullable = nonnullable_rels;
reduce_outer_joins_pass2(j->rarg, right_state, parse,
pass_nonnullable);
- bms_free(pass_nonnullable);
+ }
+ bms_free(local_nonnullable);
}
}
else