Commit aa0fb530 authored by Tom Lane's avatar Tom Lane

Be a little smarter about qual handling for semi-joins: a qual that mentions

only the outer side can be pushed down rather than having to be evaluated
at the join.
parent ddbe8dca
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.143 2008/10/21 20:42:53 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.144 2008/10/25 19:51:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -48,6 +48,7 @@ static SpecialJoinInfo *make_outerjoininfo(PlannerInfo *root, ...@@ -48,6 +48,7 @@ static SpecialJoinInfo *make_outerjoininfo(PlannerInfo *root,
static void distribute_qual_to_rels(PlannerInfo *root, Node *clause, static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
bool is_deduced, bool is_deduced,
bool below_outer_join, bool below_outer_join,
JoinType jointype,
Relids qualscope, Relids qualscope,
Relids ojscope, Relids ojscope,
Relids outerjoin_nonnullable); Relids outerjoin_nonnullable);
...@@ -342,7 +343,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, ...@@ -342,7 +343,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
below_outer_join); below_outer_join);
else else
distribute_qual_to_rels(root, qual, distribute_qual_to_rels(root, qual,
false, below_outer_join, false, below_outer_join, JOIN_INNER,
*qualscope, NULL, NULL); *qualscope, NULL, NULL);
} }
} }
...@@ -452,7 +453,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, ...@@ -452,7 +453,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
below_outer_join); below_outer_join);
else else
distribute_qual_to_rels(root, qual, distribute_qual_to_rels(root, qual,
false, below_outer_join, false, below_outer_join, j->jointype,
*qualscope, *qualscope,
ojscope, nonnullable_rels); ojscope, nonnullable_rels);
} }
...@@ -712,6 +713,7 @@ make_outerjoininfo(PlannerInfo *root, ...@@ -712,6 +713,7 @@ make_outerjoininfo(PlannerInfo *root,
* 'is_deduced': TRUE if the qual came from implied-equality deduction * 'is_deduced': TRUE if the qual came from implied-equality deduction
* 'below_outer_join': TRUE if the qual is from a JOIN/ON that is below the * 'below_outer_join': TRUE if the qual is from a JOIN/ON that is below the
* nullable side of a higher-level outer join * nullable side of a higher-level outer join
* 'jointype': type of join the qual is from (JOIN_INNER for a WHERE clause)
* 'qualscope': set of baserels the qual's syntactic scope covers * 'qualscope': set of baserels the qual's syntactic scope covers
* 'ojscope': NULL if not an outer-join qual, else the minimum set of baserels * 'ojscope': NULL if not an outer-join qual, else the minimum set of baserels
* needed to form this join * needed to form this join
...@@ -728,6 +730,7 @@ static void ...@@ -728,6 +730,7 @@ static void
distribute_qual_to_rels(PlannerInfo *root, Node *clause, distribute_qual_to_rels(PlannerInfo *root, Node *clause,
bool is_deduced, bool is_deduced,
bool below_outer_join, bool below_outer_join,
JoinType jointype,
Relids qualscope, Relids qualscope,
Relids ojscope, Relids ojscope,
Relids outerjoin_nonnullable) Relids outerjoin_nonnullable)
...@@ -848,11 +851,16 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, ...@@ -848,11 +851,16 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
maybe_equivalence = false; maybe_equivalence = false;
maybe_outer_join = false; maybe_outer_join = false;
} }
else if (bms_overlap(relids, outerjoin_nonnullable)) else if (bms_overlap(relids, outerjoin_nonnullable) &&
(jointype != JOIN_SEMI ||
bms_nonempty_difference(relids, outerjoin_nonnullable)))
{ {
/* /*
* The qual is attached to an outer join and mentions (some of the) * The qual is attached to an outer join and mentions (some of the)
* rels on the nonnullable side, so it's not degenerate. * rels on the nonnullable side, so it's not degenerate. (For a
* JOIN_SEMI qual, we consider it non-degenerate only if it mentions
* both sides of the join --- if it mentions only one side, it can
* be pushed down.)
* *
* We can't use such a clause to deduce equivalence (the left and * We can't use such a clause to deduce equivalence (the left and
* right sides might be unequal above the join because one of them has * right sides might be unequal above the join because one of them has
...@@ -1024,7 +1032,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, ...@@ -1024,7 +1032,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
restrictinfo); restrictinfo);
return; return;
} }
if (bms_equal(outerjoin_nonnullable, qualscope)) if (jointype == JOIN_FULL)
{ {
/* FULL JOIN (above tests cannot match in this case) */ /* FULL JOIN (above tests cannot match in this case) */
root->full_join_clauses = lappend(root->full_join_clauses, root->full_join_clauses = lappend(root->full_join_clauses,
...@@ -1077,9 +1085,8 @@ distribute_sublink_quals_to_rels(PlannerInfo *root, ...@@ -1077,9 +1085,8 @@ distribute_sublink_quals_to_rels(PlannerInfo *root,
Node *qual = (Node *) lfirst(l); Node *qual = (Node *) lfirst(l);
distribute_qual_to_rels(root, qual, distribute_qual_to_rels(root, qual,
false, below_outer_join, false, below_outer_join, fslink->jointype,
qualscope, ojscope, qualscope, ojscope, fslink->lefthand);
fslink->lefthand);
} }
/* Now we can add the SpecialJoinInfo to join_info_list */ /* Now we can add the SpecialJoinInfo to join_info_list */
...@@ -1373,7 +1380,7 @@ process_implied_equality(PlannerInfo *root, ...@@ -1373,7 +1380,7 @@ process_implied_equality(PlannerInfo *root,
* Push the new clause into all the appropriate restrictinfo lists. * Push the new clause into all the appropriate restrictinfo lists.
*/ */
distribute_qual_to_rels(root, (Node *) clause, distribute_qual_to_rels(root, (Node *) clause,
true, below_outer_join, true, below_outer_join, JOIN_INNER,
qualscope, NULL, NULL); qualscope, NULL, NULL);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment