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.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c
index 9176ae1680c..ae114f65509 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.49 2006/10/04 00:29:55 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.49.2.1 2007/07/31 19:53:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -36,6 +36,8 @@ static Expr *make_sub_restrictinfos(Expr *clause,
static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
RestrictInfo *rinfo,
List *reference_list,
+ Relids outer_relids,
+ Relids inner_relids,
bool isouterjoin);
@@ -546,6 +548,8 @@ extract_actual_join_clauses(List *restrictinfo_list,
*/
List *
remove_redundant_join_clauses(PlannerInfo *root, List *restrictinfo_list,
+ Relids outer_relids,
+ Relids inner_relids,
bool isouterjoin)
{
List *result = NIL;
@@ -572,7 +576,9 @@ remove_redundant_join_clauses(PlannerInfo *root, List *restrictinfo_list,
RestrictInfo *prevrinfo;
/* is it redundant with any prior clause? */
- prevrinfo = join_clause_is_redundant(root, rinfo, result, isouterjoin);
+ prevrinfo = join_clause_is_redundant(root, rinfo, result,
+ outer_relids, inner_relids,
+ isouterjoin);
if (prevrinfo == NULL)
{
/* no, so add it to result list */
@@ -608,6 +614,8 @@ List *
select_nonredundant_join_clauses(PlannerInfo *root,
List *restrictinfo_list,
List *reference_list,
+ Relids outer_relids,
+ Relids inner_relids,
bool isouterjoin)
{
List *result = NIL;
@@ -618,7 +626,9 @@ 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, isouterjoin) != NULL)
+ if (join_clause_is_redundant(root, rinfo, reference_list,
+ outer_relids, inner_relids,
+ isouterjoin) != NULL)
continue;
/* otherwise, add it to result list */
@@ -651,6 +661,12 @@ select_nonredundant_join_clauses(PlannerInfo *root,
* of the latter, even though they might seem redundant by the pathkey
* membership test.
*
+ * Also, we cannot eliminate clauses wherein one side mentions vars from
+ * both relations, as in "WHERE t1.f1 = t2.f1 AND t1.f1 = t1.f2 - t2.f2".
+ * In this example, "t1.f2 - t2.f2" could not have been computed at all
+ * before forming the join of t1 and t2, so it certainly wasn't constrained
+ * earlier.
+ *
* Weird special case: if we have two clauses that seem redundant
* except one is pushed down into an outer join and the other isn't,
* then they're not really redundant, because one constrains the
@@ -660,6 +676,8 @@ static RestrictInfo *
join_clause_is_redundant(PlannerInfo *root,
RestrictInfo *rinfo,
List *reference_list,
+ Relids outer_relids,
+ Relids inner_relids,
bool isouterjoin)
{
ListCell *refitem;
@@ -681,6 +699,14 @@ join_clause_is_redundant(PlannerInfo *root,
bms_is_empty(rinfo->right_relids))
return NULL; /* var = const, so not redundant */
+ /* check for either side mentioning both rels */
+ if (bms_overlap(rinfo->left_relids, outer_relids) &&
+ bms_overlap(rinfo->left_relids, inner_relids))
+ return NULL; /* clause LHS uses both, so not redundant */
+ if (bms_overlap(rinfo->right_relids, outer_relids) &&
+ bms_overlap(rinfo->right_relids, inner_relids))
+ return NULL; /* clause RHS uses both, so not redundant */
+
cache_mergeclause_pathkeys(root, rinfo);
foreach(refitem, reference_list)