*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.75 1999/12/31 05:38:25 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.77 2000/01/22 23:50:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "utils/lsyscache.h"
#include "utils/syscache.h"
+
+#define is_indexable_operator(clause,opclass,relam,indexkey_on_left) \
+ (indexable_operator(clause,opclass,relam,indexkey_on_left) != InvalidOid)
+
typedef enum {
Prefix_None, Prefix_Partial, Prefix_Exact
} Prefix_Status;
-static void match_index_orclauses(RelOptInfo *rel, RelOptInfo *index,
+static void match_index_orclauses(RelOptInfo *rel, IndexOptInfo *index,
int indexkey, Oid opclass,
List *restrictinfo_list);
-static List *match_index_orclause(RelOptInfo *rel, RelOptInfo *index,
+static List *match_index_orclause(RelOptInfo *rel, IndexOptInfo *index,
int indexkey, Oid opclass,
List *or_clauses,
List *other_matching_indices);
-static bool match_or_subclause_to_indexkey(RelOptInfo *rel, RelOptInfo *index,
+static bool match_or_subclause_to_indexkey(RelOptInfo *rel,
+ IndexOptInfo *index,
int indexkey, Oid opclass,
Expr *clause);
-static List *group_clauses_by_indexkey(RelOptInfo *rel, RelOptInfo *index,
+static List *group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index,
int *indexkeys, Oid *classes,
List *restrictinfo_list);
-static List *group_clauses_by_ikey_for_joins(RelOptInfo *rel, RelOptInfo *index,
+static List *group_clauses_by_ikey_for_joins(RelOptInfo *rel,
+ IndexOptInfo *index,
int *indexkeys, Oid *classes,
List *join_cinfo_list,
List *restr_cinfo_list);
-static bool match_clause_to_indexkey(RelOptInfo *rel, RelOptInfo *index,
+static bool match_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index,
int indexkey, Oid opclass,
Expr *clause, bool join);
-static bool indexable_operator(Expr *clause, Oid opclass, Oid relam,
- bool indexkey_on_left);
static bool pred_test(List *predicate_list, List *restrictinfo_list,
List *joininfo_list);
static bool one_pred_test(Expr *predicate, List *restrictinfo_list);
static bool one_pred_clause_expr_test(Expr *predicate, Node *clause);
static bool one_pred_clause_test(Expr *predicate, Node *clause);
static bool clause_pred_clause_test(Expr *predicate, Node *clause);
-static void indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
+static void indexable_joinclauses(RelOptInfo *rel, IndexOptInfo *index,
List *joininfo_list, List *restrictinfo_list,
List **clausegroups, List **outerrelids);
-static List *index_innerjoin(Query *root, RelOptInfo *rel, RelOptInfo *index,
+static List *index_innerjoin(Query *root, RelOptInfo *rel, IndexOptInfo *index,
List *clausegroup_list, List *outerrelids_list);
-static bool useful_for_mergejoin(RelOptInfo *rel, RelOptInfo *index,
+static bool useful_for_mergejoin(RelOptInfo *rel, IndexOptInfo *index,
List *joininfo_list);
static bool useful_for_ordering(Query *root, RelOptInfo *rel,
- RelOptInfo *index);
+ IndexOptInfo *index);
static bool match_index_to_operand(int indexkey, Var *operand,
- RelOptInfo *rel, RelOptInfo *index);
+ RelOptInfo *rel, IndexOptInfo *index);
static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel,
- RelOptInfo *index);
+ IndexOptInfo *index);
static bool match_special_index_operator(Expr *clause, Oid opclass, Oid relam,
bool indexkey_on_left);
static Prefix_Status like_fixed_prefix(char *patt, char **prefix);
foreach(ilist, indices)
{
- RelOptInfo *index = (RelOptInfo *) lfirst(ilist);
+ IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);
List *restrictclauses;
List *joinclausegroups;
List *joinouterrelids;
*/
static void
match_index_orclauses(RelOptInfo *rel,
- RelOptInfo *index,
+ IndexOptInfo *index,
int indexkey,
Oid opclass,
List *restrictinfo_list)
*/
static List *
match_index_orclause(RelOptInfo *rel,
- RelOptInfo *index,
+ IndexOptInfo *index,
int indexkey,
Oid opclass,
List *or_clauses,
*/
static bool
match_or_subclause_to_indexkey(RelOptInfo *rel,
- RelOptInfo *index,
+ IndexOptInfo *index,
int indexkey,
Oid opclass,
Expr *clause)
*/
static List *
group_clauses_by_indexkey(RelOptInfo *rel,
- RelOptInfo *index,
+ IndexOptInfo *index,
int *indexkeys,
Oid *classes,
List *restrictinfo_list)
*/
static List *
group_clauses_by_ikey_for_joins(RelOptInfo *rel,
- RelOptInfo *index,
+ IndexOptInfo *index,
int *indexkeys,
Oid *classes,
List *join_cinfo_list,
*/
static bool
match_clause_to_indexkey(RelOptInfo *rel,
- RelOptInfo *index,
+ IndexOptInfo *index,
int indexkey,
Oid opclass,
Expr *clause,
if ((IsA(rightop, Const) || IsA(rightop, Param)) &&
match_index_to_operand(indexkey, leftop, rel, index))
{
- if (indexable_operator(clause, opclass, index->relam, true))
+ if (is_indexable_operator(clause, opclass, index->relam, true))
return true;
/*
* If we didn't find a member of the index's opclass,
if ((IsA(leftop, Const) || IsA(leftop, Param)) &&
match_index_to_operand(indexkey, rightop, rel, index))
{
- if (indexable_operator(clause, opclass, index->relam, false))
+ if (is_indexable_operator(clause, opclass, index->relam, false))
return true;
/*
* If we didn't find a member of the index's opclass,
isIndexable = ! intMember(lfirsti(rel->relids), othervarnos);
freeList(othervarnos);
if (isIndexable &&
- indexable_operator(clause, opclass, index->relam, true))
+ is_indexable_operator(clause, opclass, index->relam, true))
return true;
}
else if (match_index_to_operand(indexkey, rightop, rel, index))
isIndexable = ! intMember(lfirsti(rel->relids), othervarnos);
freeList(othervarnos);
if (isIndexable &&
- indexable_operator(clause, opclass, index->relam, false))
+ is_indexable_operator(clause, opclass, index->relam, false))
return true;
}
}
* Does a binary opclause contain an operator matching the index's
* access method?
*
- * If the indexkey is on the right, what we actually want to know
- * is whether the operator has a commutator operator that matches
- * the index's access method.
+ * If the indexkey is on the right, what we actually want to know
+ * is whether the operator has a commutator operator that matches
+ * the index's access method.
*
* We try both the straightforward match and matches that rely on
* recognizing binary-compatible datatypes. For example, if we have
* which we need to replace with oideq in order to recognize it as
* matching an oid_ops index on the oid field.
*
- * NOTE: if a binary-compatible match is made, we destructively modify
- * the given clause to use the binary-compatible substitute operator!
- * This should be safe even if we don't end up using the index, but it's
- * a tad ugly...
+ * Returns the OID of the matching operator, or InvalidOid if no match.
+ * Note that the returned OID will be different from the one in the given
+ * expression if we used a binary-compatible substitution. Also note that
+ * if indexkey_on_left is FALSE (meaning we need to commute), the returned
+ * OID is *not* commuted; it can be plugged directly into the given clause.
*/
-static bool
+Oid
indexable_operator(Expr *clause, Oid opclass, Oid relam,
bool indexkey_on_left)
{
else
commuted_op = get_commutator(expr_op);
if (commuted_op == InvalidOid)
- return false;
+ return InvalidOid;
/* Done if the (commuted) operator is a member of the index's AM */
if (op_class(commuted_op, opclass, relam))
- return true;
+ return expr_op;
/*
* Maybe the index uses a binary-compatible operator set.
Operator newop;
if (opname == NULL)
- return false; /* probably shouldn't happen */
+ return InvalidOid; /* probably shouldn't happen */
/* Use the datatype of the index key */
if (indexkey_on_left)
else
commuted_op = get_commutator(new_expr_op);
if (commuted_op == InvalidOid)
- return false;
+ return InvalidOid;
if (op_class(commuted_op, opclass, relam))
- {
- /*
- * Success! Change the opclause to use the
- * binary-compatible operator.
- */
- ((Oper *) clause->oper)->opno = new_expr_op;
- return true;
- }
+ return new_expr_op;
}
}
}
- return false;
+ return InvalidOid;
}
/*
*/
static bool
useful_for_mergejoin(RelOptInfo *rel,
- RelOptInfo *index,
+ IndexOptInfo *index,
List *joininfo_list)
{
int *indexkeys = index->indexkeys;
static bool
useful_for_ordering(Query *root,
RelOptInfo *rel,
- RelOptInfo *index)
+ IndexOptInfo *index)
{
List *index_pathkeys;
* '*outerrelids' receives a list of relid lists
*/
static void
-indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
+indexable_joinclauses(RelOptInfo *rel, IndexOptInfo *index,
List *joininfo_list, List *restrictinfo_list,
List **clausegroups, List **outerrelids)
{
* Returns a list of index pathnodes.
*/
static List *
-index_innerjoin(Query *root, RelOptInfo *rel, RelOptInfo *index,
+index_innerjoin(Query *root, RelOptInfo *rel, IndexOptInfo *index,
List *clausegroup_list, List *outerrelids_list)
{
List *path_list = NIL;
List *clausegroup = lfirst(i);
IndexPath *pathnode = makeNode(IndexPath);
List *indexquals;
- float npages;
- float selec;
-
- indexquals = get_actual_clauses(clausegroup);
- /* expand special operators to indexquals the executor can handle */
- indexquals = expand_indexqual_conditions(indexquals);
-
- index_selectivity(root,
- lfirsti(rel->relids),
- lfirsti(index->relids),
- indexquals,
- &npages,
- &selec);
/* XXX this code ought to be merged with create_index_path? */
pathnode->path.parent = rel;
pathnode->path.pathkeys = build_index_pathkeys(root, rel, index);
+ indexquals = get_actual_clauses(clausegroup);
+ /* expand special operators to indexquals the executor can handle */
+ indexquals = expand_indexqual_conditions(indexquals);
+
/* Note that we are making a pathnode for a single-scan indexscan;
* therefore, both indexid and indexqual should be single-element
* lists.
*/
- Assert(length(index->relids) == 1);
- pathnode->indexid = index->relids;
+ pathnode->indexid = lconsi(index->indexoid, NIL);
pathnode->indexqual = lcons(indexquals, NIL);
/* joinrelids saves the rels needed on the outer side of the join */
pathnode->joinrelids = lfirst(outerrelids_list);
- pathnode->path.path_cost = cost_index((Oid) lfirsti(index->relids),
- (int) npages,
- selec,
- rel->pages,
- rel->tuples,
- index->pages,
- index->tuples,
+ pathnode->path.path_cost = cost_index(root, rel, index, indexquals,
true);
path_list = lappend(path_list, pathnode);
match_index_to_operand(int indexkey,
Var *operand,
RelOptInfo *rel,
- RelOptInfo *index)
+ IndexOptInfo *index)
{
if (index->indproc == InvalidOid)
{
}
static bool
-function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index)
+function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
{
int relvarno = lfirsti(rel->relids);
Func *function;