99 *
1010 *
1111 * IDENTIFICATION
12- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.88 2000/07/25 04:30:42 tgl Exp $
12+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.89 2000/07/26 23:46:22 tgl Exp $
1313 *
1414 *-------------------------------------------------------------------------
1515 */
4040#include "utils/syscache.h"
4141
4242
43+ /*
44+ * DoneMatchingIndexKeys() - MACRO
45+ *
46+ * Determine whether we should continue matching index keys in a clause.
47+ * Depends on if there are more to match or if this is a functional index.
48+ * In the latter case we stop after the first match since the there can
49+ * be only key (i.e. the function's return value) and the attributes in
50+ * keys list represent the arguments to the function. -mer 3 Oct. 1991
51+ */
52+ #define DoneMatchingIndexKeys (indexkeys ,index ) \
53+ (indexkeys[0] == 0 || \
54+ (index->indproc != InvalidOid))
55+
4356#define is_indexable_operator (clause ,opclass ,relam ,indexkey_on_left ) \
4457(indexable_operator(clause,opclass,relam,indexkey_on_left) != InvalidOid)
4558
59+
4660static void match_index_orclauses (RelOptInfo * rel ,IndexOptInfo * index ,
4761List * restrictinfo_list );
4862static List * match_index_orclause (RelOptInfo * rel ,IndexOptInfo * index ,
@@ -354,10 +368,11 @@ match_index_orclause(RelOptInfo *rel,
354368 * index, or if it is an AND clause any of whose members is an opclause
355369 * that matches the index.
356370 *
357- * We currently only look to match the first key of an index against
358- * 'or' subclauses. There are cases where a later key of a multi-key
359- * index could be used (if other top-level clauses match earlier keys
360- * of the index), but our poor brains are hurting already...
371+ * For multi-key indexes, we only look for matches to the first key;
372+ * without such a match the index is useless. If the clause is an AND
373+ * then we may be able to extract additional subclauses to use with the
374+ * later indexkeys, but we need not worry about that until
375+ * extract_or_indexqual_conditions() is called (if it ever is).
361376 */
362377static bool
363378match_or_subclause_to_indexkey (RelOptInfo * rel ,
@@ -404,19 +419,45 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
404419Expr * orsubclause )
405420{
406421List * quals = NIL ;
407- int indexkey = index -> indexkeys [0 ];
408- Oid opclass = index -> classlist [0 ];
409422
410423if (and_clause ((Node * )orsubclause ))
411424{
412- List * item ;
425+ /*
426+ * Extract relevant sub-subclauses in indexkey order. This is just
427+ * like group_clauses_by_indexkey() except that the input and output
428+ * are lists of bare clauses, not of RestrictInfo nodes.
429+ */
430+ int * indexkeys = index -> indexkeys ;
431+ Oid * classes = index -> classlist ;
413432
414- foreach ( item , orsubclause -> args )
433+ do
415434{
416- if (match_clause_to_indexkey (rel ,index ,indexkey ,opclass ,
417- lfirst (item ), false))
418- quals = lappend (quals ,lfirst (item ));
419- }
435+ int curIndxKey = indexkeys [0 ];
436+ Oid curClass = classes [0 ];
437+ List * clausegroup = NIL ;
438+ List * item ;
439+
440+ foreach (item ,orsubclause -> args )
441+ {
442+ if (match_clause_to_indexkey (rel ,index ,
443+ curIndxKey ,curClass ,
444+ lfirst (item ), false))
445+ clausegroup = lappend (clausegroup ,lfirst (item ));
446+ }
447+
448+ /*
449+ * If no clauses match this key, we're done; we don't want to look
450+ * at keys to its right.
451+ */
452+ if (clausegroup == NIL )
453+ break ;
454+
455+ quals = nconc (quals ,clausegroup );
456+
457+ indexkeys ++ ;
458+ classes ++ ;
459+ }while (!DoneMatchingIndexKeys (indexkeys ,index ));
460+
420461if (quals == NIL )
421462elog (ERROR ,"extract_or_indexqual_conditions: no matching clause" );
422463}
@@ -435,19 +476,6 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
435476 ****************************************************************************/
436477
437478
438- /*
439- * DoneMatchingIndexKeys() - MACRO
440- *
441- * Determine whether we should continue matching index keys in a clause.
442- * Depends on if there are more to match or if this is a functional index.
443- * In the latter case we stop after the first match since the there can
444- * be only key (i.e. the function's return value) and the attributes in
445- * keys list represent the arguments to the function. -mer 3 Oct. 1991
446- */
447- #define DoneMatchingIndexKeys (indexkeys ,index ) \
448- (indexkeys[0] == 0 || \
449- (index->indproc != InvalidOid))
450-
451479/*
452480 * group_clauses_by_indexkey
453481 * Generates a list of restriction clauses that can be used with an index.