* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.269 2003/11/29 19:51:49 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.270 2003/12/30 23:53:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
COPY_NODE_FIELD(clause);
COPY_SCALAR_FIELD(ispusheddown);
+ COPY_SCALAR_FIELD(canjoin);
+ COPY_BITMAPSET_FIELD(left_relids);
+ COPY_BITMAPSET_FIELD(right_relids);
COPY_NODE_FIELD(subclauseindices); /* XXX probably bad */
COPY_SCALAR_FIELD(eval_cost);
COPY_SCALAR_FIELD(this_selec);
- COPY_BITMAPSET_FIELD(left_relids);
- COPY_BITMAPSET_FIELD(right_relids);
COPY_SCALAR_FIELD(mergejoinoperator);
COPY_SCALAR_FIELD(left_sortop);
COPY_SCALAR_FIELD(right_sortop);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.210 2003/11/29 19:51:49 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.211 2003/12/30 23:53:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
COMPARE_SCALAR_FIELD(ispusheddown);
/*
- * We ignore subclauseindices, eval_cost, this_selec,
- * left/right_relids, left/right_pathkey, and left/right_bucketsize,
- * since they may not be set yet, and should be derivable from the
- * clause anyway. Probably it's not really necessary to compare any
- * of these remaining fields ...
+ * We ignore all the remaining fields, since they may not be set yet,
+ * and should be derivable from the clause anyway.
*/
- COMPARE_SCALAR_FIELD(mergejoinoperator);
- COMPARE_SCALAR_FIELD(left_sortop);
- COMPARE_SCALAR_FIELD(right_sortop);
- COMPARE_SCALAR_FIELD(hashjoinoperator);
return true;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.222 2003/11/29 19:51:49 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.223 2003/12/30 23:53:14 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
/* NB: this isn't a complete set of fields */
WRITE_NODE_FIELD(clause);
WRITE_BOOL_FIELD(ispusheddown);
- WRITE_NODE_FIELD(subclauseindices);
+ WRITE_BOOL_FIELD(canjoin);
WRITE_BITMAPSET_FIELD(left_relids);
WRITE_BITMAPSET_FIELD(right_relids);
+ WRITE_NODE_FIELD(subclauseindices);
WRITE_OID_FIELD(mergejoinoperator);
WRITE_OID_FIELD(left_sortop);
WRITE_OID_FIELD(right_sortop);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
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);
}
/*----------
if (match_clause_to_indexcol(rel, index,
indexcol, curClass,
- subsubclause))
+ subsubclause, NULL))
FastConc(&clausegroup,
expand_indexqual_condition(subsubclause,
curClass));
}
else if (match_clause_to_indexcol(rel, index,
indexcol, curClass,
- orsubclause))
+ orsubclause, NULL))
FastConc(&clausegroup,
expand_indexqual_condition(orsubclause,
curClass));
if (match_clause_to_indexcol(rel, index,
indexcol, curClass,
- rinfo->clause))
+ rinfo->clause, rinfo))
FastConc(&clausegroup,
expand_indexqual_condition(rinfo->clause,
curClass));
index,
indexcol,
curClass,
- rinfo->clause))
+ rinfo->clause,
+ rinfo))
FastAppend(&clausegroup, rinfo);
}
index,
indexcol,
curClass,
- rinfo->clause))
+ rinfo->clause,
+ rinfo))
FastAppend(&clausegroup, rinfo);
}
index,
indexcol,
curClass,
- rinfo->clause))
+ rinfo))
{
FastAppend(&clausegroup, rinfo);
if (!jfoundhere)
* '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.
*
IndexOptInfo *index,
int indexcol,
Oid opclass,
- Expr *clause)
+ Expr *clause,
+ RestrictInfo *rinfo)
{
Node *leftop,
*rightop;
* 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;
}
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;
* '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.
*
IndexOptInfo *index,
int indexcol,
Oid opclass,
- Expr *clause)
+ RestrictInfo *rinfo)
{
+ Expr *clause = rinfo->clause;
Node *leftop,
*rightop;
*/
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;
}
foreach(j, joininfo->jinfo_restrictinfo)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(j);
- Expr *clause = rinfo->clause;
int indexcol = 0;
Oid *classes = index->classlist;
index,
indexcol,
curClass,
- clause))
+ rinfo))
{
match_found = true;
break;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(i);
- if (restrictinfo->left_relids == NULL ||
+ if (!restrictinfo->canjoin ||
restrictinfo->hashjoinoperator == InvalidOid)
continue; /* not hashjoinable */
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),
}
}
- if (restrictinfo->left_relids == NULL ||
+ if (!restrictinfo->canjoin ||
restrictinfo->mergejoinoperator == InvalidOid)
continue; /* not mergejoinable */
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
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:
*/
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;
}
/*
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.
*
*
* 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
return false;
}
+/*
+ * 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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 */
}
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.87 2003/12/28 21:57:37 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.88 2003/12/30 23:53:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
bool ispusheddown; /* TRUE if clause was pushed down in level */
+ /*
+ * This flag is set true if the clause looks potentially useful as a
+ * merge or hash join clause, that is if it is a binary opclause with
+ * nonoverlapping sets of relids referenced in the left and right sides.
+ * (Whether the operator is actually merge or hash joinable isn't
+ * checked, however.)
+ */
+ bool canjoin;
+
+ /* These fields are set for any binary opclause: */
+ Relids left_relids; /* relids in left side of clause */
+ Relids right_relids; /* relids in right side of clause */
+
/* only used if clause is an OR clause: */
List *subclauseindices; /* indexes matching subclauses */
/* subclauseindices is a List of Lists of IndexOptInfos */
QualCost eval_cost; /* eval cost of clause; -1 if not yet set */
Selectivity this_selec; /* selectivity; -1 if not yet set */
- /*
- * If the clause looks useful for joining --- that is, it is a binary
- * opclause with nonoverlapping sets of relids referenced in the left
- * and right sides --- then these two fields are set to sets of the
- * referenced relids. Otherwise they are both NULL.
- */
- Relids left_relids; /* relids in left side of join clause */
- Relids right_relids; /* relids in right side of join clause */
-
/* valid if clause is mergejoinable, else InvalidOid: */
Oid mergejoinoperator; /* copy of clause operator */
Oid left_sortop; /* leftside sortop needed for mergejoin */
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.69 2003/11/29 22:41:07 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.70 2003/12/30 23:53:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern bool contain_nonstrict_functions(Node *clause);
extern bool is_pseudo_constant_clause(Node *clause);
+extern bool is_pseudo_constant_clause_relids(Node *clause, Relids relids);
extern List *pull_constant_clauses(List *quals, List **constantQual);
extern bool has_distinct_on_clause(Query *query);