summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/indxpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path/indxpath.c')
-rw-r--r--src/backend/optimizer/path/indxpath.c247
1 files changed, 100 insertions, 147 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 454e9c92605..9319f8c1474 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.141 2003/05/27 17:49:46 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.142 2003/05/28 16:03:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -43,12 +43,8 @@
/*
* DoneMatchingIndexKeys() - MACRO
- *
- * Formerly this looked at indexkeys, but that's the wrong thing for a
- * functional index.
*/
-#define DoneMatchingIndexKeys(indexkeys, classes) \
- (classes[0] == InvalidOid)
+#define DoneMatchingIndexKeys(classes) (classes[0] == InvalidOid)
#define is_indexable_operator(clause,opclass,indexkey_on_left) \
(indexable_operator(clause,opclass,indexkey_on_left) != InvalidOid)
@@ -67,14 +63,14 @@ static List *group_clauses_by_indexkey_for_join(RelOptInfo *rel,
IndexOptInfo *index,
Relids outer_relids,
bool isouterjoin);
-static bool match_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index,
- int indexkey, Oid opclass, Expr *clause);
-static bool match_join_clause_to_indexkey(RelOptInfo *rel, IndexOptInfo *index,
- int indexkey, Oid opclass, Expr *clause);
+static bool match_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index,
+ int indexcol, Oid opclass, Expr *clause);
+static bool match_join_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index,
+ int indexcol, Oid opclass, Expr *clause);
static Oid indexable_operator(Expr *clause, Oid opclass,
bool indexkey_on_left);
static bool pred_test(List *predicate_list, List *restrictinfo_list,
- List *joininfo_list, int relvarno);
+ List *joininfo_list);
static bool pred_test_restrict_list(Expr *predicate, List *restrictinfo_list);
static bool pred_test_recurse_clause(Expr *predicate, Node *clause);
static bool pred_test_recurse_pred(Expr *predicate, Node *clause);
@@ -83,10 +79,8 @@ static Relids indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index);
static Path *make_innerjoin_index_path(Query *root,
RelOptInfo *rel, IndexOptInfo *index,
List *clausegroups);
-static bool match_index_to_operand(int indexkey, Node *operand,
+static bool match_index_to_operand(Node *operand, int indexcol,
RelOptInfo *rel, IndexOptInfo *index);
-static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel,
- IndexOptInfo *index);
static bool match_special_index_operator(Expr *clause, Oid opclass,
bool indexkey_on_left);
static List *expand_indexqual_condition(Expr *clause, Oid opclass);
@@ -149,8 +143,7 @@ create_index_paths(Query *root, RelOptInfo *rel)
* predicate test.
*/
if (index->indpred != NIL)
- if (!pred_test(index->indpred, restrictinfo_list, joininfo_list,
- rel->relid))
+ if (!pred_test(index->indpred, restrictinfo_list, joininfo_list))
continue;
/*
@@ -371,7 +364,6 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
IndexOptInfo *index,
Expr *clause)
{
- int indexkey = index->indexkeys[0];
Oid opclass = index->classlist[0];
if (and_clause((Node *) clause))
@@ -380,14 +372,14 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
foreach(item, ((BoolExpr *) clause)->args)
{
- if (match_clause_to_indexkey(rel, index, indexkey, opclass,
+ if (match_clause_to_indexcol(rel, index, 0, opclass,
lfirst(item)))
return true;
}
return false;
}
else
- return match_clause_to_indexkey(rel, index, indexkey, opclass,
+ return match_clause_to_indexcol(rel, index, 0, opclass,
clause);
}
@@ -426,7 +418,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
Expr *orsubclause)
{
List *quals = NIL;
- int *indexkeys = index->indexkeys;
+ int indexcol = 0;
Oid *classes = index->classlist;
/*
@@ -437,7 +429,6 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
*/
do
{
- int curIndxKey = indexkeys[0];
Oid curClass = classes[0];
List *clausegroup = NIL;
List *item;
@@ -448,16 +439,16 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
{
Expr *subsubclause = (Expr *) lfirst(item);
- if (match_clause_to_indexkey(rel, index,
- curIndxKey, curClass,
+ if (match_clause_to_indexcol(rel, index,
+ indexcol, curClass,
subsubclause))
clausegroup = nconc(clausegroup,
expand_indexqual_condition(subsubclause,
curClass));
}
}
- else if (match_clause_to_indexkey(rel, index,
- curIndxKey, curClass,
+ else if (match_clause_to_indexcol(rel, index,
+ indexcol, curClass,
orsubclause))
clausegroup = expand_indexqual_condition(orsubclause, curClass);
@@ -471,8 +462,8 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
- if (match_clause_to_indexkey(rel, index,
- curIndxKey, curClass,
+ if (match_clause_to_indexcol(rel, index,
+ indexcol, curClass,
rinfo->clause))
clausegroup = nconc(clausegroup,
expand_indexqual_condition(rinfo->clause,
@@ -489,10 +480,10 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
quals = nconc(quals, clausegroup);
- indexkeys++;
+ indexcol++;
classes++;
- } while (!DoneMatchingIndexKeys(indexkeys, classes));
+ } while (!DoneMatchingIndexKeys(classes));
if (quals == NIL)
elog(ERROR, "extract_or_indexqual_conditions: no matching clause");
@@ -531,7 +522,7 @@ group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index)
{
List *clausegroup_list = NIL;
List *restrictinfo_list = rel->baserestrictinfo;
- int *indexkeys = index->indexkeys;
+ int indexcol = 0;
Oid *classes = index->classlist;
if (restrictinfo_list == NIL)
@@ -539,7 +530,6 @@ group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index)
do
{
- int curIndxKey = indexkeys[0];
Oid curClass = classes[0];
List *clausegroup = NIL;
List *i;
@@ -548,9 +538,9 @@ group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(i);
- if (match_clause_to_indexkey(rel,
+ if (match_clause_to_indexcol(rel,
index,
- curIndxKey,
+ indexcol,
curClass,
rinfo->clause))
clausegroup = lappend(clausegroup, rinfo);
@@ -565,10 +555,10 @@ group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index)
clausegroup_list = lappend(clausegroup_list, clausegroup);
- indexkeys++;
+ indexcol++;
classes++;
- } while (!DoneMatchingIndexKeys(indexkeys, classes));
+ } while (!DoneMatchingIndexKeys(classes));
return clausegroup_list;
}
@@ -592,12 +582,11 @@ group_clauses_by_indexkey_for_join(RelOptInfo *rel, IndexOptInfo *index,
{
List *clausegroup_list = NIL;
bool jfound = false;
- int *indexkeys = index->indexkeys;
+ int indexcol = 0;
Oid *classes = index->classlist;
do
{
- int curIndxKey = indexkeys[0];
Oid curClass = classes[0];
List *clausegroup = NIL;
List *i;
@@ -619,9 +608,9 @@ group_clauses_by_indexkey_for_join(RelOptInfo *rel, IndexOptInfo *index,
if (isouterjoin && rinfo->ispusheddown)
continue;
- if (match_join_clause_to_indexkey(rel,
+ if (match_join_clause_to_indexcol(rel,
index,
- curIndxKey,
+ indexcol,
curClass,
rinfo->clause))
{
@@ -640,9 +629,9 @@ group_clauses_by_indexkey_for_join(RelOptInfo *rel, IndexOptInfo *index,
if (isouterjoin && rinfo->ispusheddown)
continue;
- if (match_clause_to_indexkey(rel,
+ if (match_clause_to_indexcol(rel,
index,
- curIndxKey,
+ indexcol,
curClass,
rinfo->clause))
clausegroup = lappend(clausegroup, rinfo);
@@ -657,10 +646,10 @@ group_clauses_by_indexkey_for_join(RelOptInfo *rel, IndexOptInfo *index,
clausegroup_list = lappend(clausegroup_list, clausegroup);
- indexkeys++;
+ indexcol++;
classes++;
- } while (!DoneMatchingIndexKeys(indexkeys, classes));
+ } while (!DoneMatchingIndexKeys(classes));
/* if no join clause was matched then forget it, per comments above */
if (!jfound)
@@ -674,15 +663,15 @@ group_clauses_by_indexkey_for_join(RelOptInfo *rel, IndexOptInfo *index,
/*
- * match_clause_to_indexkey()
- * Determines whether a restriction clause matches a key of an index.
+ * match_clause_to_indexcol()
+ * Determines whether a restriction clause matches a column of an index.
*
* To match, the clause:
*
* (1) must be in the form (indexkey op const) or (const op indexkey);
* and
* (2) must contain an operator which is in the same class as the index
- * operator for this key, or is a "special" operator as recognized
+ * operator for this column, or is a "special" operator as recognized
* by match_special_index_operator().
*
* Presently, the executor can only deal with indexquals that have the
@@ -693,7 +682,7 @@ group_clauses_by_indexkey_for_join(RelOptInfo *rel, IndexOptInfo *index,
*
* 'rel' is the relation of interest.
* 'index' is an index on 'rel'.
- * 'indexkey' is a key of 'index'.
+ * 'indexcol' is a column number of 'index' (counting from 0).
* 'opclass' is the corresponding operator class.
* 'clause' is the clause to be tested.
*
@@ -703,9 +692,9 @@ group_clauses_by_indexkey_for_join(RelOptInfo *rel, IndexOptInfo *index,
* responsibility of higher-level routines to cope with those.
*/
static bool
-match_clause_to_indexkey(RelOptInfo *rel,
+match_clause_to_indexcol(RelOptInfo *rel,
IndexOptInfo *index,
- int indexkey,
+ int indexcol,
Oid opclass,
Expr *clause)
{
@@ -725,7 +714,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
* (indexkey operator constant) or (constant operator indexkey).
* Anything that is a "pseudo constant" expression will do.
*/
- if (match_index_to_operand(indexkey, leftop, rel, index) &&
+ if (match_index_to_operand(leftop, indexcol, rel, index) &&
is_pseudo_constant_clause(rightop))
{
if (is_indexable_operator(clause, opclass, true))
@@ -740,7 +729,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
return false;
}
- if (match_index_to_operand(indexkey, rightop, rel, index) &&
+ if (match_index_to_operand(rightop, indexcol, rel, index) &&
is_pseudo_constant_clause(leftop))
{
if (is_indexable_operator(clause, opclass, false))
@@ -759,8 +748,8 @@ match_clause_to_indexkey(RelOptInfo *rel,
}
/*
- * match_join_clause_to_indexkey()
- * Determines whether a join clause matches a key of an index.
+ * match_join_clause_to_indexcol()
+ * Determines whether a join clause matches a column of an index.
*
* To match, the clause:
*
@@ -768,7 +757,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
* where others is an expression involving only vars of the other
* relation(s); and
* (2) must contain an operator which is in the same class as the index
- * operator for this key, or is a "special" operator as recognized
+ * operator for this column, or is a "special" operator as recognized
* by match_special_index_operator().
*
* As above, we must be able to commute the clause to put the indexkey
@@ -781,7 +770,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
*
* 'rel' is the relation of interest.
* 'index' is an index on 'rel'.
- * 'indexkey' is a key of 'index'.
+ * 'indexcol' is a column number of 'index' (counting from 0).
* 'opclass' is the corresponding operator class.
* 'clause' is the clause to be tested.
*
@@ -791,9 +780,9 @@ match_clause_to_indexkey(RelOptInfo *rel,
* responsibility of higher-level routines to cope with those.
*/
static bool
-match_join_clause_to_indexkey(RelOptInfo *rel,
+match_join_clause_to_indexcol(RelOptInfo *rel,
IndexOptInfo *index,
- int indexkey,
+ int indexcol,
Oid opclass,
Expr *clause)
{
@@ -814,7 +803,7 @@ match_join_clause_to_indexkey(RelOptInfo *rel,
* expression that uses none of the indexed relation's vars and
* contains no volatile functions.
*/
- if (match_index_to_operand(indexkey, leftop, rel, index))
+ if (match_index_to_operand(leftop, indexcol, rel, index))
{
Relids othervarnos = pull_varnos(rightop);
bool isIndexable;
@@ -827,7 +816,7 @@ match_join_clause_to_indexkey(RelOptInfo *rel,
return isIndexable;
}
- if (match_index_to_operand(indexkey, rightop, rel, index))
+ if (match_index_to_operand(rightop, indexcol, rel, index))
{
Relids othervarnos = pull_varnos(leftop);
bool isIndexable;
@@ -895,8 +884,7 @@ indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left)
* to CNF format). --Nels, Jan '93
*/
static bool
-pred_test(List *predicate_list, List *restrictinfo_list, List *joininfo_list,
- int relvarno)
+pred_test(List *predicate_list, List *restrictinfo_list, List *joininfo_list)
{
List *pred;
@@ -919,18 +907,6 @@ pred_test(List *predicate_list, List *restrictinfo_list, List *joininfo_list,
return false; /* no restriction clauses: the test must
* fail */
- /*
- * The predicate as stored in the index definition will use varno 1
- * for its Vars referencing the indexed relation. If the indexed
- * relation isn't varno 1 in the query, we must adjust the predicate
- * to make the Vars match, else equal() won't work.
- */
- if (relvarno != 1)
- {
- predicate_list = copyObject(predicate_list);
- ChangeVarNodes((Node *) predicate_list, 1, relvarno, 0);
- }
-
foreach(pred, predicate_list)
{
/*
@@ -1320,17 +1296,16 @@ indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(j);
Expr *clause = rinfo->clause;
- int *indexkeys = index->indexkeys;
+ int indexcol = 0;
Oid *classes = index->classlist;
do
{
- int curIndxKey = indexkeys[0];
Oid curClass = classes[0];
- if (match_join_clause_to_indexkey(rel,
+ if (match_join_clause_to_indexcol(rel,
index,
- curIndxKey,
+ indexcol,
curClass,
clause))
{
@@ -1338,10 +1313,10 @@ indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index)
break;
}
- indexkeys++;
+ indexcol++;
classes++;
- } while (!DoneMatchingIndexKeys(indexkeys, classes));
+ } while (!DoneMatchingIndexKeys(classes));
if (match_found)
break;
@@ -1611,16 +1586,22 @@ make_innerjoin_index_path(Query *root,
* match_index_to_operand()
* Generalized test for a match between an index's key
* and the operand on one side of a restriction or join clause.
- * Now check for functional indices as well.
+ *
+ * operand: the nodetree to be compared to the index
+ * indexcol: the column number of the index (counting from 0)
+ * rel: the parent relation
+ * index: the index of interest
*/
static bool
-match_index_to_operand(int indexkey,
- Node *operand,
+match_index_to_operand(Node *operand,
+ int indexcol,
RelOptInfo *rel,
IndexOptInfo *index)
{
+ int indkey;
+
/*
- * Ignore any RelabelType node above the indexkey. This is needed to
+ * Ignore any RelabelType node above the operand. This is needed to
* be able to apply indexscanning in binary-compatible-operator cases.
* Note: we can assume there is at most one RelabelType node;
* eval_const_expressions() will have simplified if more than one.
@@ -1628,77 +1609,52 @@ match_index_to_operand(int indexkey,
if (operand && IsA(operand, RelabelType))
operand = (Node *) ((RelabelType *) operand)->arg;
- if (index->indproc == InvalidOid)
+ indkey = index->indexkeys[indexcol];
+ if (indkey != 0)
{
/*
- * Simple index.
+ * Simple index column; operand must be a matching Var.
*/
if (operand && IsA(operand, Var) &&
rel->relid == ((Var *) operand)->varno &&
- indexkey == ((Var *) operand)->varattno)
+ indkey == ((Var *) operand)->varattno)
return true;
- else
- return false;
}
-
- /*
- * Functional index.
- */
- return function_index_operand((Expr *) operand, rel, index);
-}
-
-static bool
-function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
-{
- FuncExpr *function;
- List *funcargs;
- int *indexKeys = index->indexkeys;
- List *arg;
- int i;
-
- /*
- * sanity check, make sure we know what we're dealing with here.
- */
- if (funcOpnd == NULL || !IsA(funcOpnd, FuncExpr) ||
- indexKeys == NULL)
- return false;
-
- function = (FuncExpr *) funcOpnd;
- funcargs = function->args;
-
- if (function->funcid != index->indproc)
- return false;
-
- /*----------
- * Check that the arguments correspond to the same arguments used to
- * create the functional index. To do this we must check that
- * 1. they refer to the right relation.
- * 2. the args have the right attr. numbers in the right order.
- * We must ignore RelabelType nodes above the argument Vars in order
- * to recognize binary-compatible-function cases correctly.
- *----------
- */
- i = 0;
- foreach(arg, funcargs)
+ else
{
- Var *var = (Var *) lfirst(arg);
+ /*
+ * Index expression; find the correct expression. (This search could
+ * be avoided, at the cost of complicating all the callers of this
+ * routine; doesn't seem worth it.)
+ */
+ List *indexprs;
+ int i;
+ Node *indexkey;
- if (var && IsA(var, RelabelType))
- var = (Var *) ((RelabelType *) var)->arg;
- if (var == NULL || !IsA(var, Var))
- return false;
- if (indexKeys[i] == 0)
- return false;
- if (var->varno != rel->relid || var->varattno != indexKeys[i])
- return false;
+ indexprs = index->indexprs;
+ for (i = 0; i < indexcol; i++)
+ {
+ if (index->indexkeys[i] == 0)
+ {
+ if (indexprs == NIL)
+ elog(ERROR, "wrong number of index expressions");
+ indexprs = lnext(indexprs);
+ }
+ }
+ if (indexprs == NIL)
+ elog(ERROR, "wrong number of index expressions");
+ indexkey = (Node *) lfirst(indexprs);
+ /*
+ * Does it match the operand? Again, strip any relabeling.
+ */
+ if (indexkey && IsA(indexkey, RelabelType))
+ indexkey = (Node *) ((RelabelType *) indexkey)->arg;
- i++;
+ if (equal(indexkey, operand))
+ return true;
}
- if (indexKeys[i] != 0)
- return false; /* not enough arguments */
-
- return true;
+ return false;
}
/****************************************************************************
@@ -1728,7 +1684,7 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, IndexOptInfo *index)
*
* Two routines are provided here, match_special_index_operator() and
* expand_indexqual_conditions(). match_special_index_operator() is
- * just an auxiliary function for match_clause_to_indexkey(); after
+ * just an auxiliary function for match_clause_to_indexcol(); after
* the latter fails to recognize a restriction opclause's operator
* as a member of an index's opclass, it asks match_special_index_operator()
* whether the clause should be considered an indexqual anyway.
@@ -1915,7 +1871,6 @@ List *
expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
{
List *resultquals = NIL;
- int *indexkeys = index->indexkeys;
Oid *classes = index->classlist;
if (clausegroups == NIL)
@@ -1937,11 +1892,9 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
clausegroups = lnext(clausegroups);
- indexkeys++;
classes++;
- } while (clausegroups != NIL &&
- !DoneMatchingIndexKeys(indexkeys, classes));
+ } while (clausegroups != NIL && !DoneMatchingIndexKeys(classes));
Assert(clausegroups == NIL); /* else more groups than indexkeys... */