aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/restrictinfo.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-07-31 19:53:50 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-07-31 19:53:50 +0000
commit1be62b532b441aaff4b2d9c9dc028b96c4b7a8c7 (patch)
treef2a9ab9ff05c13f759bf58945166027c0f4bc030 /src/backend/optimizer/util/restrictinfo.c
parent5bd7b8342685a7d6d5ab134b321f8e4ccfdeaa16 (diff)
downloadpostgresql-1be62b532b441aaff4b2d9c9dc028b96c4b7a8c7.tar.gz
postgresql-1be62b532b441aaff4b2d9c9dc028b96c4b7a8c7.zip
Fix a bug in the original implementation of redundant-join-clause removal:
clauses in which one side or the other references both sides of the join cannot be removed as redundant, because that expression won't have been constrained below the join. Per report from Sergey Burladyan.
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)