summaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
authorTom Lane2003-12-30 23:53:15 +0000
committerTom Lane2003-12-30 23:53:15 +0000
commitbe6c38b9033c546e2a8a9fab4329b89be57a263b (patch)
tree521c34b2c94d52614160a5582654751e089b226e /src/backend/optimizer
parent5e545151671fa4ab3cf0e62ffd1e207609ad1517 (diff)
Adjust the definition of RestrictInfo's left_relids and right_relids
fields: now they are valid whenever the clause is a binary opclause, not only when it is a potential join clause (there is a new boolean field canjoin to signal the latter condition). This lets us avoid recomputing the relid sets over and over while examining indexes. Still more work to do to make this as useful as it could be, because there are places that could use the info but don't have access to the RestrictInfo node.
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/path/indxpath.c53
-rw-r--r--src/backend/optimizer/path/joinpath.c10
-rw-r--r--src/backend/optimizer/plan/initsplan.c42
-rw-r--r--src/backend/optimizer/util/clauses.c16
-rw-r--r--src/backend/optimizer/util/restrictinfo.c14
5 files changed, 78 insertions, 57 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index b9ccc770a43..c2fe837db65 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.150 2003/12/18 00:22:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.151 2003/12/30 23:53:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -64,9 +64,11 @@ static List *group_clauses_by_indexkey_for_join(Query *root,
Relids outer_relids,
JoinType jointype, bool isouterjoin);
static bool match_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index,
- int indexcol, Oid opclass, Expr *clause);
+ int indexcol, Oid opclass,
+ Expr *clause, RestrictInfo *rinfo);
static bool match_join_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index,
- int indexcol, Oid opclass, Expr *clause);
+ int indexcol, Oid opclass,
+ RestrictInfo *rinfo);
static Oid indexable_operator(Expr *clause, Oid opclass,
bool indexkey_on_left);
static bool pred_test(List *predicate_list, List *restrictinfo_list,
@@ -374,14 +376,14 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
foreach(item, ((BoolExpr *) clause)->args)
{
if (match_clause_to_indexcol(rel, index, 0, opclass,
- lfirst(item)))
+ lfirst(item), NULL))
return true;
}
return false;
}
else
return match_clause_to_indexcol(rel, index, 0, opclass,
- clause);
+ clause, NULL);
}
/*----------
@@ -445,7 +447,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
if (match_clause_to_indexcol(rel, index,
indexcol, curClass,
- subsubclause))
+ subsubclause, NULL))
FastConc(&clausegroup,
expand_indexqual_condition(subsubclause,
curClass));
@@ -453,7 +455,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
}
else if (match_clause_to_indexcol(rel, index,
indexcol, curClass,
- orsubclause))
+ orsubclause, NULL))
FastConc(&clausegroup,
expand_indexqual_condition(orsubclause,
curClass));
@@ -470,7 +472,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
if (match_clause_to_indexcol(rel, index,
indexcol, curClass,
- rinfo->clause))
+ rinfo->clause, rinfo))
FastConc(&clausegroup,
expand_indexqual_condition(rinfo->clause,
curClass));
@@ -550,7 +552,8 @@ group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index)
index,
indexcol,
curClass,
- rinfo->clause))
+ rinfo->clause,
+ rinfo))
FastAppend(&clausegroup, rinfo);
}
@@ -625,7 +628,8 @@ group_clauses_by_indexkey_for_join(Query *root,
index,
indexcol,
curClass,
- rinfo->clause))
+ rinfo->clause,
+ rinfo))
FastAppend(&clausegroup, rinfo);
}
@@ -654,7 +658,7 @@ group_clauses_by_indexkey_for_join(Query *root,
index,
indexcol,
curClass,
- rinfo->clause))
+ rinfo))
{
FastAppend(&clausegroup, rinfo);
if (!jfoundhere)
@@ -726,6 +730,7 @@ group_clauses_by_indexkey_for_join(Query *root,
* 'indexcol' is a column number of 'index' (counting from 0).
* 'opclass' is the corresponding operator class.
* 'clause' is the clause to be tested.
+ * 'rinfo' is the clause's RestrictInfo, if available (NULL if not).
*
* Returns true if the clause can be used with this index key.
*
@@ -737,7 +742,8 @@ match_clause_to_indexcol(RelOptInfo *rel,
IndexOptInfo *index,
int indexcol,
Oid opclass,
- Expr *clause)
+ Expr *clause,
+ RestrictInfo *rinfo)
{
Node *leftop,
*rightop;
@@ -754,9 +760,13 @@ match_clause_to_indexcol(RelOptInfo *rel,
* Check for clauses of the form: (indexkey operator constant) or
* (constant operator indexkey). Anything that is a "pseudo constant"
* expression will do.
+ *
+ * If we have the RestrictInfo available, we can make a more efficient
+ * test for pseudo-constness.
*/
if (match_index_to_operand(leftop, indexcol, rel, index) &&
- is_pseudo_constant_clause(rightop))
+ (rinfo ? is_pseudo_constant_clause_relids(rightop, rinfo->right_relids)
+ : is_pseudo_constant_clause(rightop)))
{
if (is_indexable_operator(clause, opclass, true))
return true;
@@ -771,7 +781,8 @@ match_clause_to_indexcol(RelOptInfo *rel,
}
if (match_index_to_operand(rightop, indexcol, rel, index) &&
- is_pseudo_constant_clause(leftop))
+ (rinfo ? is_pseudo_constant_clause_relids(leftop, rinfo->left_relids)
+ : is_pseudo_constant_clause(leftop)))
{
if (is_indexable_operator(clause, opclass, false))
return true;
@@ -813,7 +824,7 @@ match_clause_to_indexcol(RelOptInfo *rel,
* 'index' is an index on 'rel'.
* 'indexcol' is a column number of 'index' (counting from 0).
* 'opclass' is the corresponding operator class.
- * 'clause' is the clause to be tested.
+ * 'rinfo' is the clause to be tested (as a RestrictInfo node).
*
* Returns true if the clause can be used with this index key.
*
@@ -825,8 +836,9 @@ match_join_clause_to_indexcol(RelOptInfo *rel,
IndexOptInfo *index,
int indexcol,
Oid opclass,
- Expr *clause)
+ RestrictInfo *rinfo)
{
+ Expr *clause = rinfo->clause;
Node *leftop,
*rightop;
@@ -846,27 +858,25 @@ match_join_clause_to_indexcol(RelOptInfo *rel,
*/
if (match_index_to_operand(leftop, indexcol, rel, index))
{
- Relids othervarnos = pull_varnos(rightop);
+ Relids othervarnos = rinfo->right_relids;
bool isIndexable;
isIndexable =
!bms_overlap(rel->relids, othervarnos) &&
!contain_volatile_functions(rightop) &&
is_indexable_operator(clause, opclass, true);
- bms_free(othervarnos);
return isIndexable;
}
if (match_index_to_operand(rightop, indexcol, rel, index))
{
- Relids othervarnos = pull_varnos(leftop);
+ Relids othervarnos = rinfo->left_relids;
bool isIndexable;
isIndexable =
!bms_overlap(rel->relids, othervarnos) &&
!contain_volatile_functions(leftop) &&
is_indexable_operator(clause, opclass, false);
- bms_free(othervarnos);
return isIndexable;
}
@@ -1351,7 +1361,6 @@ indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index)
foreach(j, joininfo->jinfo_restrictinfo)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(j);
- Expr *clause = rinfo->clause;
int indexcol = 0;
Oid *classes = index->classlist;
@@ -1363,7 +1372,7 @@ indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index)
index,
indexcol,
curClass,
- clause))
+ rinfo))
{
match_found = true;
break;
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index 5b95ec7c4dd..91cd0ab22a5 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.83 2003/11/29 19:51:50 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.84 2003/12/30 23:53:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -690,7 +690,7 @@ hash_inner_and_outer(Query *root,
{
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(i);
- if (restrictinfo->left_relids == NULL ||
+ if (!restrictinfo->canjoin ||
restrictinfo->hashjoinoperator == InvalidOid)
continue; /* not hashjoinable */
@@ -809,12 +809,12 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
switch (jointype)
{
case JOIN_RIGHT:
- if (restrictinfo->left_relids == NULL ||
+ if (!restrictinfo->canjoin ||
restrictinfo->mergejoinoperator == InvalidOid)
return NIL; /* not mergejoinable */
break;
case JOIN_FULL:
- if (restrictinfo->left_relids == NULL ||
+ if (!restrictinfo->canjoin ||
restrictinfo->mergejoinoperator == InvalidOid)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -826,7 +826,7 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
}
}
- if (restrictinfo->left_relids == NULL ||
+ if (!restrictinfo->canjoin ||
restrictinfo->mergejoinoperator == InvalidOid)
continue; /* not mergejoinable */
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 5612430a390..3da001e997a 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.93 2003/11/29 19:51:50 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.94 2003/12/30 23:53:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -380,12 +380,13 @@ distribute_qual_to_rels(Query *root, Node *clause,
bool can_be_equijoin;
restrictinfo->clause = (Expr *) clause;
+ restrictinfo->canjoin = false; /* set below, if join clause */
+ restrictinfo->left_relids = NULL;
+ restrictinfo->right_relids = NULL;
restrictinfo->subclauseindices = NIL;
restrictinfo->eval_cost.startup = -1; /* not computed until
* needed */
restrictinfo->this_selec = -1; /* not computed until needed */
- restrictinfo->left_relids = NULL; /* set below, if join clause */
- restrictinfo->right_relids = NULL;
restrictinfo->mergejoinoperator = InvalidOid;
restrictinfo->left_sortop = InvalidOid;
restrictinfo->right_sortop = InvalidOid;
@@ -510,6 +511,15 @@ distribute_qual_to_rels(Query *root, Node *clause,
restrictinfo->ispusheddown = ispusheddown || !bms_equal(relids,
qualscope);
+ /*
+ * If it's a binary opclause, set up left/right relids info.
+ */
+ if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2)
+ {
+ restrictinfo->left_relids = pull_varnos(get_leftop((Expr *) clause));
+ restrictinfo->right_relids = pull_varnos(get_rightop((Expr *) clause));
+ }
+
switch (bms_membership(relids))
{
case BMS_SINGLETON:
@@ -562,18 +572,11 @@ distribute_qual_to_rels(Query *root, Node *clause,
*/
if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2)
{
- Relids left_relids;
- Relids right_relids;
-
- left_relids = pull_varnos(get_leftop((Expr *) clause));
- right_relids = pull_varnos(get_rightop((Expr *) clause));
- if (!bms_is_empty(left_relids) &&
- !bms_is_empty(right_relids) &&
- !bms_overlap(left_relids, right_relids))
- {
- restrictinfo->left_relids = left_relids;
- restrictinfo->right_relids = right_relids;
- }
+ if (!bms_is_empty(restrictinfo->left_relids) &&
+ !bms_is_empty(restrictinfo->right_relids) &&
+ !bms_overlap(restrictinfo->left_relids,
+ restrictinfo->right_relids))
+ restrictinfo->canjoin = true;
}
/*
@@ -814,13 +817,14 @@ qual_is_redundant(Query *root,
List *equalexprs;
bool someadded;
- newleft = get_leftop(restrictinfo->clause);
- newright = get_rightop(restrictinfo->clause);
-
/* Never redundant unless vars appear on both sides */
- if (!contain_var_clause(newleft) || !contain_var_clause(newright))
+ if (bms_is_empty(restrictinfo->left_relids) ||
+ bms_is_empty(restrictinfo->right_relids))
return false;
+ newleft = get_leftop(restrictinfo->clause);
+ newright = get_rightop(restrictinfo->clause);
+
/*
* Set cached pathkeys. NB: it is okay to do this now because this
* routine is only invoked while we are generating implied equalities.
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index d6f0bb3ad2e..35efa6bc630 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.157 2003/12/28 21:57:37 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.158 2003/12/30 23:53:15 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -812,6 +812,20 @@ is_pseudo_constant_clause(Node *clause)
}
/*
+ * is_pseudo_constant_clause_relids
+ * Same as above, except caller already has available the var membership
+ * of the clause; this lets us avoid the contain_var_clause() scan.
+ */
+bool
+is_pseudo_constant_clause_relids(Node *clause, Relids relids)
+{
+ if (bms_is_empty(relids) &&
+ !contain_volatile_functions(clause))
+ return true;
+ return false;
+}
+
+/*
* pull_constant_clauses
* Scan through a list of qualifications and separate "constant" quals
* from those that are not.
diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c
index 2ae122e92a9..f77966a2262 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.20 2003/11/29 19:51:51 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.21 2003/12/30 23:53:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -227,15 +227,9 @@ join_clause_is_redundant(Query *root,
if (redundant)
{
- /*
- * It looks redundant, now check for "var = const" case. If
- * left_relids/right_relids are set, then there are definitely
- * vars on both sides; else we must check the hard way.
- */
- if (rinfo->left_relids)
- return true; /* var = var, so redundant */
- if (contain_var_clause(get_leftop(rinfo->clause)) &&
- contain_var_clause(get_rightop(rinfo->clause)))
+ /* It looks redundant, but check for "var = const" case */
+ if (!bms_is_empty(rinfo->left_relids) &&
+ !bms_is_empty(rinfo->right_relids))
return true; /* var = var, so redundant */
/* else var = const, not redundant */
}