When dealing with OR-of-ANDs quals, extract multiple subclauses of an AND

to use with a multiple-key index.  Formerly we would only extract clauses
that had to do with the first key of the index, which was correct but
didn't exploit the index fully.
This commit is contained in:
Tom Lane 2000-07-26 23:46:22 +00:00
parent 6d54070550
commit 90451fe7f3
1 changed files with 54 additions and 26 deletions

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.88 2000/07/25 04:30:42 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.89 2000/07/26 23:46:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -40,9 +40,23 @@
#include "utils/syscache.h"
/*
* DoneMatchingIndexKeys() - MACRO
*
* Determine whether we should continue matching index keys in a clause.
* Depends on if there are more to match or if this is a functional index.
* In the latter case we stop after the first match since the there can
* be only key (i.e. the function's return value) and the attributes in
* keys list represent the arguments to the function. -mer 3 Oct. 1991
*/
#define DoneMatchingIndexKeys(indexkeys, index) \
(indexkeys[0] == 0 || \
(index->indproc != InvalidOid))
#define is_indexable_operator(clause,opclass,relam,indexkey_on_left) \
(indexable_operator(clause,opclass,relam,indexkey_on_left) != InvalidOid)
static void match_index_orclauses(RelOptInfo *rel, IndexOptInfo *index,
List *restrictinfo_list);
static List *match_index_orclause(RelOptInfo *rel, IndexOptInfo *index,
@ -354,10 +368,11 @@ match_index_orclause(RelOptInfo *rel,
* index, or if it is an AND clause any of whose members is an opclause
* that matches the index.
*
* We currently only look to match the first key of an index against
* 'or' subclauses. There are cases where a later key of a multi-key
* index could be used (if other top-level clauses match earlier keys
* of the index), but our poor brains are hurting already...
* For multi-key indexes, we only look for matches to the first key;
* without such a match the index is useless. If the clause is an AND
* then we may be able to extract additional subclauses to use with the
* later indexkeys, but we need not worry about that until
* extract_or_indexqual_conditions() is called (if it ever is).
*/
static bool
match_or_subclause_to_indexkey(RelOptInfo *rel,
@ -404,19 +419,45 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
Expr *orsubclause)
{
List *quals = NIL;
int indexkey = index->indexkeys[0];
Oid opclass = index->classlist[0];
if (and_clause((Node *) orsubclause))
{
List *item;
/*
* Extract relevant sub-subclauses in indexkey order. This is just
* like group_clauses_by_indexkey() except that the input and output
* are lists of bare clauses, not of RestrictInfo nodes.
*/
int *indexkeys = index->indexkeys;
Oid *classes = index->classlist;
foreach(item, orsubclause->args)
do
{
if (match_clause_to_indexkey(rel, index, indexkey, opclass,
lfirst(item), false))
quals = lappend(quals, lfirst(item));
}
int curIndxKey = indexkeys[0];
Oid curClass = classes[0];
List *clausegroup = NIL;
List *item;
foreach(item, orsubclause->args)
{
if (match_clause_to_indexkey(rel, index,
curIndxKey, curClass,
lfirst(item), false))
clausegroup = lappend(clausegroup, lfirst(item));
}
/*
* If no clauses match this key, we're done; we don't want to look
* at keys to its right.
*/
if (clausegroup == NIL)
break;
quals = nconc(quals, clausegroup);
indexkeys++;
classes++;
} while (!DoneMatchingIndexKeys(indexkeys, index));
if (quals == NIL)
elog(ERROR, "extract_or_indexqual_conditions: no matching clause");
}
@ -435,19 +476,6 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
****************************************************************************/
/*
* DoneMatchingIndexKeys() - MACRO
*
* Determine whether we should continue matching index keys in a clause.
* Depends on if there are more to match or if this is a functional index.
* In the latter case we stop after the first match since the there can
* be only key (i.e. the function's return value) and the attributes in
* keys list represent the arguments to the function. -mer 3 Oct. 1991
*/
#define DoneMatchingIndexKeys(indexkeys, index) \
(indexkeys[0] == 0 || \
(index->indproc != InvalidOid))
/*
* group_clauses_by_indexkey
* Generates a list of restriction clauses that can be used with an index.