1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

Replace functional-index facility with expressional indexes. Any column

of an index can now be a computed expression instead of a simple variable.
Restrictions on expressions are the same as for predicates (only immutable
functions, no sub-selects).  This fixes problems recently introduced with
inlining SQL functions, because the inlining transformation is applied to
both expression trees so the planner can still match them up.  Along the
way, improve efficiency of handling index predicates (both predicates and
index expressions are now cached by the relcache) and fix 7.3 oversight
that didn't record dependencies of predicate expressions.
This commit is contained in:
Tom Lane
2003-05-28 16:04:02 +00:00
parent e5f19598e0
commit fc8d970cbc
50 changed files with 1351 additions and 1283 deletions

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.142 2003/05/12 00:17:03 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.143 2003/05/28 16:03:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1197,12 +1197,6 @@ static Node *
fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index,
Oid *opclass)
{
/*
* Remove any binary-compatible relabeling of the indexkey
*/
if (IsA(node, RelabelType))
node = (Node *) ((RelabelType *) node)->arg;
/*
* We represent index keys by Var nodes having the varno of the base
* table but varattno equal to the index's attribute number (index
@ -1210,48 +1204,68 @@ fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index,
* a special-purpose node type that could not be mistaken for a
* regular Var. But it will do for now.
*/
if (IsA(node, Var))
Var *result;
int pos;
List *indexprs;
/*
* Remove any binary-compatible relabeling of the indexkey
*/
if (IsA(node, RelabelType))
node = (Node *) ((RelabelType *) node)->arg;
if (IsA(node, Var) &&
((Var *) node)->varno == baserelid)
{
/* If it's a var, find which index key position it occupies */
Assert(index->indproc == InvalidOid);
/* Try to match against simple index columns */
int varatt = ((Var *) node)->varattno;
if (((Var *) node)->varno == baserelid)
if (varatt != 0)
{
int varatt = ((Var *) node)->varattno;
int pos;
for (pos = 0; pos < index->nkeys; pos++)
for (pos = 0; pos < index->ncolumns; pos++)
{
if (index->indexkeys[pos] == varatt)
{
Node *newnode = copyObject(node);
((Var *) newnode)->varattno = pos + 1;
result = (Var *) copyObject(node);
result->varattno = pos + 1;
/* return the correct opclass, too */
*opclass = index->classlist[pos];
return newnode;
return (Node *) result;
}
}
}
/*
* Oops, this Var isn't an indexkey!
*/
elog(ERROR, "fix_indxqual_operand: var is not index attribute");
}
/*
* Else, it must be a func expression matching a functional index.
* Since we currently only support single-column functional indexes,
* the returned varattno must be 1.
*/
Assert(index->indproc != InvalidOid);
Assert(is_funcclause(node)); /* not a very thorough check, but easy */
/* Try to match against index expressions */
indexprs = index->indexprs;
for (pos = 0; pos < index->ncolumns; pos++)
{
if (index->indexkeys[pos] == 0)
{
Node *indexkey;
/* classlist[0] is the only class of a functional index */
*opclass = index->classlist[0];
if (indexprs == NIL)
elog(ERROR, "too few entries in indexprs list");
indexkey = (Node *) lfirst(indexprs);
if (indexkey && IsA(indexkey, RelabelType))
indexkey = (Node *) ((RelabelType *) indexkey)->arg;
if (equal(node, indexkey))
{
/* Found a match */
result = makeVar(baserelid, pos + 1,
exprType(lfirst(indexprs)), -1,
0);
/* return the correct opclass, too */
*opclass = index->classlist[pos];
return (Node *) result;
}
indexprs = lnext(indexprs);
}
}
return (Node *) makeVar(baserelid, 1, exprType(node), -1, 0);
/* Ooops... */
elog(ERROR, "fix_indxqual_operand: node is not index attribute");
return NULL; /* keep compiler quiet */
}
/*