diff options
Diffstat (limited to 'src/backend/optimizer/util/restrictinfo.c')
-rw-r--r-- | src/backend/optimizer/util/restrictinfo.c | 91 |
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; |