aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/restrictinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/restrictinfo.c')
-rw-r--r--src/backend/optimizer/util/restrictinfo.c91
1 files changed, 78 insertions, 13 deletions
diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c
index 0fcfd0ed509..5b75d2de3bd 100644
--- a/src/backend/optimizer/util/restrictinfo.c
+++ b/src/backend/optimizer/util/restrictinfo.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.58 2009/04/16 20:42:16 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.59 2009/05/09 22:51:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -35,8 +35,9 @@ static Expr *make_sub_restrictinfos(Expr *clause,
bool pseudoconstant,
Relids required_relids,
Relids nullable_relids);
-static bool join_clause_is_redundant(PlannerInfo *root,
- RestrictInfo *rinfo,
+static List *select_nonredundant_join_list(List *restrictinfo_list,
+ List *reference_list);
+static bool join_clause_is_redundant(RestrictInfo *rinfo,
List *reference_list);
@@ -545,26 +546,91 @@ extract_actual_join_clauses(List *restrictinfo_list,
}
}
+
/*
* select_nonredundant_join_clauses
*
* Given a list of RestrictInfo clauses that are to be applied in a join,
- * select the ones that are not redundant with any clause in the
- * reference_list. This is used only for nestloop-with-inner-indexscan
- * joins: any clauses being checked by the index should be removed from
- * the qpquals list.
+ * select the ones that are not redundant with any clause that's enforced
+ * by the inner_path. This is used for nestloop joins, wherein any clause
+ * being used in an inner indexscan need not be checked again at the join.
*
* "Redundant" means either equal() or derived from the same EquivalenceClass.
* We have to check the latter because indxqual.c may select different derived
* clauses than were selected by generate_join_implied_equalities().
*
- * Note that we assume the given restrictinfo_list has already been checked
- * for local redundancies, so we don't check again.
+ * Note that we are *not* checking for local redundancies within the given
+ * restrictinfo_list; that should have been handled elsewhere.
*/
List *
select_nonredundant_join_clauses(PlannerInfo *root,
List *restrictinfo_list,
- List *reference_list)
+ Path *inner_path)
+{
+ if (IsA(inner_path, IndexPath))
+ {
+ /*
+ * Check the index quals to see if any of them are join clauses.
+ *
+ * We can skip this if the index path is an ordinary indexpath and not
+ * a special innerjoin path, since it then wouldn't be using any join
+ * clauses.
+ */
+ IndexPath *innerpath = (IndexPath *) inner_path;
+
+ if (innerpath->isjoininner)
+ restrictinfo_list =
+ select_nonredundant_join_list(restrictinfo_list,
+ innerpath->indexclauses);
+ }
+ else if (IsA(inner_path, BitmapHeapPath))
+ {
+ /*
+ * Same deal for bitmapped index scans.
+ *
+ * Note: both here and above, we ignore any implicit index
+ * restrictions associated with the use of partial indexes. This is
+ * OK because we're only trying to prove we can dispense with some
+ * join quals; failing to prove that doesn't result in an incorrect
+ * plan. It's quite unlikely that a join qual could be proven
+ * redundant by an index predicate anyway. (Also, if we did manage
+ * to prove it, we'd have to have a special case for update targets;
+ * see notes about EvalPlanQual testing in create_indexscan_plan().)
+ */
+ BitmapHeapPath *innerpath = (BitmapHeapPath *) inner_path;
+
+ if (innerpath->isjoininner)
+ {
+ List *bitmapclauses;
+
+ bitmapclauses =
+ make_restrictinfo_from_bitmapqual(innerpath->bitmapqual,
+ true,
+ false);
+ restrictinfo_list =
+ select_nonredundant_join_list(restrictinfo_list,
+ bitmapclauses);
+ }
+ }
+
+ /*
+ * XXX the inner path of a nestloop could also be an append relation
+ * whose elements use join quals. However, they might each use different
+ * quals; we could only remove join quals that are enforced by all the
+ * appendrel members. For the moment we don't bother to try.
+ */
+
+ return restrictinfo_list;
+}
+
+/*
+ * select_nonredundant_join_list
+ * Select the members of restrictinfo_list that are not redundant with
+ * any member of reference_list. See above for more info.
+ */
+static List *
+select_nonredundant_join_list(List *restrictinfo_list,
+ List *reference_list)
{
List *result = NIL;
ListCell *item;
@@ -574,7 +640,7 @@ select_nonredundant_join_clauses(PlannerInfo *root,
RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
/* drop it if redundant with any reference clause */
- if (join_clause_is_redundant(root, rinfo, reference_list))
+ if (join_clause_is_redundant(rinfo, reference_list))
continue;
/* otherwise, add it to result list */
@@ -589,8 +655,7 @@ select_nonredundant_join_clauses(PlannerInfo *root,
* Test whether rinfo is redundant with any clause in reference_list.
*/
static bool
-join_clause_is_redundant(PlannerInfo *root,
- RestrictInfo *rinfo,
+join_clause_is_redundant(RestrictInfo *rinfo,
List *reference_list)
{
ListCell *refitem;