1 /*-------------------------------------------------------------------------
4 * Routines to determine which indices are usable for scanning a
7 * Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.1.1.1 1996/07/09 06:21:35 scrappy Exp $
13 *-------------------------------------------------------------------------
17 #include "access/attnum.h"
18 #include "access/heapam.h"
19 #include "access/nbtree.h"
21 #include "nodes/pg_list.h"
22 #include "nodes/relation.h"
23 #include "nodes/makefuncs.h"
24 #include "nodes/nodeFuncs.h"
26 #include "utils/lsyscache.h"
27 #include "utils/elog.h"
29 #include "optimizer/internal.h"
30 #include "optimizer/paths.h"
31 #include "optimizer/clauses.h"
32 #include "optimizer/clauseinfo.h"
33 #include "optimizer/plancat.h"
34 #include "optimizer/keys.h"
35 #include "optimizer/cost.h"
36 #include "optimizer/pathnode.h"
37 #include "optimizer/xfunc.h"
38 #include "optimizer/ordering.h"
41 #include "catalog/catname.h"
42 #include "catalog/pg_amop.h"
43 #include "catalog/pg_proc.h"
45 #include "executor/executor.h"
46 #include "parser/parsetree.h" /* for getrelid() */
49 static void match_index_orclauses(Rel *rel, Rel *index, int indexkey,
50 int xclass, List *clauseinfo_list);
51 static bool match_index_to_operand(int indexkey, Expr *operand,
52 Rel *rel, Rel *index);
53 static List *match_index_orclause(Rel *rel, Rel *index, int indexkey,
54 int xclass, List *or_clauses, List *other_matching_indices);
55 static List *group_clauses_by_indexkey(Rel *rel, Rel *index,
56 int *indexkeys, Oid *classes, List *clauseinfo_list,
58 static CInfo *match_clause_to_indexkey(Rel *rel, Rel *index, int indexkey,
59 int xclass, CInfo *clauseInfo, bool join);
60 static bool pred_test(List *predicate_list, List *clauseinfo_list,
62 static bool one_pred_test(Expr *predicate, List *clauseinfo_list);
63 static bool one_pred_clause_expr_test(Expr *predicate, Node *clause);
64 static bool one_pred_clause_test(Expr *predicate, Node *clause);
65 static bool clause_pred_clause_test(Expr *predicate, Node *clause);
66 static List *indexable_joinclauses(Rel *rel, Rel *index, List *joininfo_list);
67 static List *index_innerjoin(Query *root, Rel *rel,
68 List *clausegroup_list, Rel *index);
69 static List *create_index_paths(Query *root, Rel *rel, Rel *index,
70 List *clausegroup_list, bool join);
71 static List *add_index_paths(List *indexpaths, List *new_indexpaths);
72 static bool function_index_operand(Expr *funcOpnd, Rel *rel, Rel *index);
73 static bool SingleAttributeIndex(Rel *index);
75 /* If Spyros can use a constant PRS2_BOOL_TYPEID, I can use this */
76 #define BOOL_TYPEID ((Oid) 16)
80 * Finds all possible index paths by determining which indices in the
81 * list 'indices' are usable.
83 * To be usable, an index must match against either a set of
84 * restriction clauses or join clauses.
86 * Note that the current implementation requires that there exist
87 * matching clauses for every key in the index (i.e., no partial
88 * matches are allowed).
90 * If an index can't be used with restriction clauses, but its keys
91 * match those of the result sort order (according to information stored
92 * within 'sortkeys'), then the index is also considered.
94 * 'rel' is the relation entry to which these index paths correspond
95 * 'indices' is a list of possible index paths
96 * 'clauseinfo-list' is a list of restriction clauseinfo nodes for 'rel'
97 * 'joininfo-list' is a list of joininfo nodes for 'rel'
98 * 'sortkeys' is a node describing the result sort order (from
101 * Returns a list of index nodes.
105 find_index_paths (Query *root,
108 List *clauseinfo_list,
111 List *scanclausegroups = NIL;
112 List *scanpaths = NIL;
113 Rel *index = (Rel *)NULL;
114 List *joinclausegroups = NIL;
115 List *joinpaths = NIL;
117 extern List *add_index_paths();
122 index = (Rel*)lfirst (indices);
124 retval = find_index_paths(root,
130 /* If this is a partial index, return if it fails the predicate test */
131 if (index->indpred != NIL)
132 if (!pred_test(index->indpred, clauseinfo_list, joininfo_list))
135 /* 1. If this index has only one key, try matching it against
136 * subclauses of an 'or' clause. The fields of the clauseinfo
137 * nodes are marked with lists of the matching indices no path
138 * are actually created.
140 * XXX NOTE: Currently btrees dos not support indices with
141 * > 1 key, so the following test will always be true for
142 * now but we have decided not to support index-scans
143 * on disjunction . -- lp
145 if (SingleAttributeIndex(index))
147 match_index_orclauses (rel,
155 * 2. If the keys of this index match any of the available
156 * restriction clauses, then create pathnodes corresponding
157 * to each group of usable clauses.
159 scanclausegroups = group_clauses_by_indexkey(rel,
167 if (scanclausegroups != NIL)
168 scanpaths = create_index_paths (root,
175 * 3. If this index can be used with any join clause, then
176 * create pathnodes for each group of usable clauses. An
177 * index can be used with a join clause if its ordering is
178 * useful for a mergejoin, or if the index can possibly be
179 * used for scanning the inner relation of a nestloop join.
181 joinclausegroups = indexable_joinclauses(rel,index,joininfo_list);
184 if (joinclausegroups != NIL)
186 List *new_join_paths = create_index_paths(root, rel,
190 List *innerjoin_paths = index_innerjoin(root, rel,joinclausegroups,index);
192 rel->innerjoin = nconc (rel->innerjoin, innerjoin_paths);
193 joinpaths = new_join_paths;
197 * Some sanity checks to make sure that
198 * the indexpath is valid.
201 retval = add_index_paths(joinpaths,retval);
203 retval = add_index_paths(scanpaths,retval);
210 /****************************************************************************
211 * ---- ROUTINES TO MATCH 'OR' CLAUSES ----
212 ****************************************************************************/
216 * match-index-orclauses--
217 * Attempt to match an index against subclauses within 'or' clauses.
218 * If the index does match, then the clause is marked with information
221 * Essentially, this adds 'index' to the list of indices in the
222 * ClauseInfo field of each of the clauses which it matches.
224 * 'rel' is the node of the relation on which the index is defined.
225 * 'index' is the index node.
226 * 'indexkey' is the (single) key of the index
227 * 'class' is the class of the operator corresponding to 'indexkey'.
228 * 'clauseinfo-list' is the list of available restriction clauses.
234 match_index_orclauses(Rel *rel,
238 List *clauseinfo_list)
240 CInfo *clauseinfo = (CInfo*)NULL;
243 foreach (i, clauseinfo_list) {
244 clauseinfo = (CInfo*)lfirst(i);
245 if (valid_or_clause(clauseinfo)) {
247 /* Mark the 'or' clause with a list of indices which
248 * match each of its subclauses. The list is
249 * generated by adding 'index' to the existing
250 * list where appropriate.
252 clauseinfo->indexids =
253 match_index_orclause (rel,index,indexkey,
255 clauseinfo->clause->args,
256 clauseinfo->indexids);
262 * match_index_operand--
263 * Generalize test for a match between an existing index's key
264 * and the operand on the rhs of a restriction clause. Now check
265 * for functional indices as well.
268 match_index_to_operand(int indexkey,
276 if (index->indproc == InvalidOid)
277 return match_indexkey_operand(indexkey, (Var*)operand, rel);
280 * functional index check
282 return (function_index_operand(operand, rel, index));
286 * match-index-orclause--
287 * Attempts to match an index against the subclauses of an 'or' clause.
289 * A match means that:
290 * (1) the operator within the subclause can be used with one
291 * of the index's operator classes, and
292 * (2) there is a usable key that matches the variable within a
295 * 'or-clauses' are the remaining subclauses within the 'or' clause
296 * 'other-matching-indices' is the list of information on other indices
297 * that have already been matched to subclauses within this
298 * particular 'or' clause (i.e., a list previously generated by
301 * Returns a list of the form ((a b c) (d e f) nil (g h) ...) where
302 * a,b,c are nodes of indices that match the first subclause in
303 * 'or-clauses', d,e,f match the second subclause, no indices
304 * match the third, g,h match the fourth, etc.
307 match_index_orclause(Rel *rel,
312 List *other_matching_indices)
315 List *matched_indices = other_matching_indices;
316 List *index_list = NIL;
320 if (!matched_indices)
321 matched_indices = lcons(NIL, NIL);
323 for (clist = or_clauses, ind = matched_indices;
325 clist = lnext(clist), ind = lnext(ind))
327 clause = lfirst(clist);
328 if (is_opclause (clause) &&
329 op_class(((Oper*)((Expr*)clause)->oper)->opno,
330 xclass, index->relam) &&
331 match_index_to_operand(indexkey,
332 (Expr*)get_leftop((Expr*)clause),
335 IsA(get_rightop((Expr*)clause),Const)) {
337 matched_indices = lcons(index, matched_indices);
338 index_list = lappend(index_list,
346 /****************************************************************************
347 * ---- ROUTINES TO CHECK RESTRICTIONS ----
348 ****************************************************************************/
352 * DoneMatchingIndexKeys() - MACRO
354 * Determine whether we should continue matching index keys in a clause.
355 * Depends on if there are more to match or if this is a functional index.
356 * In the latter case we stop after the first match since the there can
357 * be only key (i.e. the function's return value) and the attributes in
358 * keys list represent the arguments to the function. -mer 3 Oct. 1991
360 #define DoneMatchingIndexKeys(indexkeys, index) \
361 (indexkeys[0] == 0 || \
362 (index->indproc != InvalidOid))
365 * group-clauses-by-indexkey--
366 * Determines whether there are clauses which will match each and every
367 * one of the remaining keys of an index.
369 * 'rel' is the node of the relation corresponding to the index.
370 * 'indexkeys' are the remaining index keys to be matched.
371 * 'classes' are the classes of the index operators on those keys.
372 * 'clauses' is either:
373 * (1) the list of available restriction clauses on a single
375 * (2) a list of join clauses between 'rel' and a fixed set of
377 * depending on the value of 'join'.
378 * 'startlist' is a list of those clause nodes that have matched the keys
379 * that have already been checked.
380 * 'join' is a flag indicating that the clauses being checked are join
383 * Returns all possible groups of clauses that will match (given that
384 * one or more clauses can match any of the remaining keys).
385 * E.g., if you have clauses A, B, and C, ((A B) (A C)) might be
386 * returned for an index with 2 keys.
390 group_clauses_by_indexkey(Rel *rel,
394 List *clauseinfo_list,
397 List *curCinfo = NIL;
398 CInfo *matched_clause = (CInfo*)NULL;
399 List *clausegroup = NIL;
402 if (clauseinfo_list == NIL)
405 foreach (curCinfo,clauseinfo_list) {
406 CInfo *temp = (CInfo*)lfirst(curCinfo);
407 int *curIndxKey = indexkeys;
408 Oid *curClass = classes;
412 * If we can't find any matching clauses for the first of
413 * the remaining keys, give up.
415 matched_clause = match_clause_to_indexkey (rel,
424 clausegroup = lcons(matched_clause, clausegroup);
428 } while ( !DoneMatchingIndexKeys(curIndxKey, index) );
431 if (clausegroup != NIL)
432 return(lcons(clausegroup, NIL));
437 * IndexScanableClause () MACRO
439 * Generalize condition on which we match a clause with an index.
440 * Now we can match with functional indices.
442 #define IndexScanableOperand(opnd, indkeys, rel, index) \
443 ((index->indproc == InvalidOid) ? \
444 equal_indexkey_var(indkeys,opnd) : \
445 function_index_operand((Expr*)opnd,rel,index))
448 * match_clause_to-indexkey--
449 * Finds the first of a relation's available restriction clauses that
450 * matches a key of an index.
452 * To match, the clause must:
453 * (1) be in the form (op var const) if the clause is a single-
454 * relation clause, and
455 * (2) contain an operator which is in the same class as the index
456 * operator for this key.
458 * If the clause being matched is a join clause, then 'join' is t.
460 * Returns a single clauseinfo node corresponding to the matching
463 * NOTE: returns nil if clause is an or_clause.
467 match_clause_to_indexkey(Rel *rel,
474 Expr *clause = clauseInfo->clause;
475 Var *leftop, *rightop;
476 Oid join_op = InvalidOid;
477 bool isIndexable = false;
479 if (or_clause((Node*)clause) ||
480 not_clause((Node*)clause) || single_node((Node*)clause))
481 return ((CInfo*)NULL);
483 leftop = get_leftop(clause);
484 rightop = get_rightop(clause);
486 * If this is not a join clause, check for clauses of the form:
487 * (operator var/func constant) and (operator constant var/func)
491 Oid restrict_op = InvalidOid;
494 * Check for standard s-argable clause
496 if (IsA(rightop,Const))
498 restrict_op = ((Oper*)((Expr*)clause)->oper)->opno;
500 ( op_class(restrict_op, xclass, index->relam) &&
501 IndexScanableOperand(leftop,
508 * Must try to commute the clause to standard s-arg format.
510 else if (IsA(leftop,Const))
513 get_commutator(((Oper*)((Expr*)clause)->oper)->opno);
515 if ( (restrict_op != InvalidOid) &&
516 op_class(restrict_op, xclass, index->relam) &&
517 IndexScanableOperand(rightop,
518 indexkey,rel,index) )
522 * In place list modification.
523 * (op const var/func) -> (op var/func const)
526 CommuteClause(clause, restrict_op);
528 CommuteClause((Node*)clause);
533 * Check for an indexable scan on one of the join relations.
534 * clause is of the form (operator var/func var/func)
538 if (match_index_to_operand(indexkey,(Expr*)rightop,rel,index)) {
540 join_op = get_commutator(((Oper*)((Expr*)clause)->oper)->opno);
542 } else if (match_index_to_operand(indexkey,
543 (Expr*)leftop,rel,index)) {
544 join_op = ((Oper*)((Expr*)clause)->oper)->opno;
547 if ( join_op && op_class(join_op,xclass,index->relam) &&
548 join_clause_p((Node*)clause))
553 * If we're using the operand's commutator we must
554 * commute the clause.
556 if (join_op != ((Oper*)((Expr*)clause)->oper)->opno)
557 CommuteClause((Node*)clause);
567 /****************************************************************************
568 * ---- ROUTINES TO DO PARTIAL INDEX PREDICATE TESTS ----
569 ****************************************************************************/
573 * Does the "predicate inclusion test" for partial indexes.
575 * Recursively checks whether the clauses in clauseinfo_list imply
576 * that the given predicate is true.
578 * This routine (together with the routines it calls) iterates over
579 * ANDs in the predicate first, then reduces the qualification
580 * clauses down to their constituent terms, and iterates over ORs
581 * in the predicate last. This order is important to make the test
582 * succeed whenever possible (assuming the predicate has been
583 * successfully cnfify()-ed). --Nels, Jan '93
586 pred_test(List *predicate_list, List *clauseinfo_list, List *joininfo_list)
588 List *pred, *items, *item;
591 * Note: if Postgres tried to optimize queries by forming equivalence
592 * classes over equi-joined attributes (i.e., if it recognized that a
593 * qualification such as "where a.b=c.d and a.b=5" could make use of
594 * an index on c.d), then we could use that equivalence class info
595 * here with joininfo_list to do more complete tests for the usability
596 * of a partial index. For now, the test only uses restriction
597 * clauses (those in clauseinfo_list). --Nels, Dec '92
600 if (predicate_list == NULL)
601 return true; /* no predicate: the index is usable */
602 if (clauseinfo_list == NULL)
603 return false; /* no restriction clauses: the test must fail */
605 foreach (pred, predicate_list) {
606 /* if any clause is not implied, the whole predicate is not implied */
607 if (and_clause(lfirst(pred))) {
608 items = ((Expr*)lfirst(pred))->args;
609 foreach (item, items) {
610 if (!one_pred_test(lfirst(item), clauseinfo_list))
614 else if (!one_pred_test(lfirst(pred), clauseinfo_list))
623 * Does the "predicate inclusion test" for one conjunct of a predicate
627 one_pred_test(Expr *predicate, List *clauseinfo_list)
632 Assert(predicate != NULL);
633 foreach (item, clauseinfo_list) {
634 clauseinfo = (CInfo *)lfirst(item);
635 /* if any clause implies the predicate, return true */
636 if (one_pred_clause_expr_test(predicate, (Node*)clauseinfo->clause))
644 * one_pred_clause_expr_test--
645 * Does the "predicate inclusion test" for a general restriction-clause
649 one_pred_clause_expr_test(Expr *predicate, Node *clause)
653 if (is_opclause(clause))
654 return one_pred_clause_test(predicate, clause);
655 else if (or_clause(clause)) {
656 items = ((Expr*)clause)->args;
657 foreach (item, items) {
658 /* if any OR item doesn't imply the predicate, clause doesn't */
659 if (!one_pred_clause_expr_test(predicate, lfirst(item)))
663 }else if (and_clause(clause)) {
664 items = ((Expr*)clause)->args;
665 foreach (item, items) {
666 /* if any AND item implies the predicate, the whole clause does */
667 if (one_pred_clause_expr_test(predicate, lfirst(item)))
672 /* unknown clause type never implies the predicate */
679 * one_pred_clause_test--
680 * Does the "predicate inclusion test" for one conjunct of a predicate
681 * expression for a simple restriction clause.
684 one_pred_clause_test(Expr *predicate, Node *clause)
688 if (is_opclause((Node*)predicate))
689 return clause_pred_clause_test(predicate, clause);
690 else if (or_clause((Node*)predicate)) {
691 items = predicate->args;
692 foreach (item, items) {
693 /* if any item is implied, the whole predicate is implied */
694 if (one_pred_clause_test(lfirst(item), clause))
698 }else if (and_clause((Node*)predicate)) {
699 items = predicate->args;
700 foreach (item, items) {
702 * if any item is not implied, the whole predicate is not
705 if (!one_pred_clause_test(lfirst(item), clause))
711 elog(DEBUG, "Unsupported predicate type, index will not be used");
718 * Define an "operator implication table" for btree operators ("strategies").
719 * The "strategy numbers" are: (1) < (2) <= (3) = (4) >= (5) >
721 * The interpretation of:
723 * test_op = BT_implic_table[given_op-1][target_op-1]
725 * where test_op, given_op and target_op are strategy numbers (from 1 to 5)
726 * of btree operators, is as follows:
728 * If you know, for some ATTR, that "ATTR given_op CONST1" is true, and you
729 * want to determine whether "ATTR target_op CONST2" must also be true, then
730 * you can use "CONST1 test_op CONST2" as a test. If this test returns true,
731 * then the target expression must be true; if the test returns false, then
732 * the target expression may be false.
734 * An entry where test_op==0 means the implication cannot be determined, i.e.,
735 * this test should always be considered false.
738 StrategyNumber BT_implic_table[BTMaxStrategyNumber][BTMaxStrategyNumber] = {
748 * clause_pred_clause_test--
749 * Use operator class info to check whether clause implies predicate.
751 * Does the "predicate inclusion test" for a "simple clause" predicate
752 * for a single "simple clause" restriction. Currently, this only handles
753 * (binary boolean) operators that are in some btree operator class.
754 * Eventually, rtree operators could also be handled by defining an
755 * appropriate "RT_implic_table" array.
758 clause_pred_clause_test(Expr *predicate, Node *clause)
760 Var *pred_var, *clause_var;
761 Const *pred_const, *clause_const;
762 Oid pred_op, clause_op, test_op;
764 StrategyNumber pred_strategy, clause_strategy, test_strategy;
767 bool test_result, isNull;
771 ScanKeyData entry[3];
774 pred_var = (Var*)get_leftop(predicate);
775 pred_const = (Const*)get_rightop(predicate);
776 clause_var = (Var*)get_leftop((Expr*)clause);
777 clause_const = (Const*)get_rightop((Expr*)clause);
779 /* Check the basic form; for now, only allow the simplest case */
780 if (!is_opclause(clause) ||
781 !IsA(clause_var,Var) ||
782 !IsA(clause_const,Const) ||
783 !IsA(predicate->oper,Oper) ||
784 !IsA(pred_var,Var) ||
785 !IsA(pred_const,Const)) {
790 * The implication can't be determined unless the predicate and the clause
791 * refer to the same attribute.
793 if (clause_var->varattno != pred_var->varattno)
796 /* Get the operators for the two clauses we're comparing */
797 pred_op = ((Oper*)((Expr*)predicate)->oper)->opno;
798 clause_op = ((Oper*)((Expr*)clause)->oper)->opno;
802 * 1. Find a "btree" strategy number for the pred_op
804 /* XXX - hardcoded amopid value 403 to find "btree" operator classes */
805 ScanKeyEntryInitialize(&entry[0], 0,
807 ObjectIdEqualRegProcedure,
808 ObjectIdGetDatum(403));
810 ScanKeyEntryInitialize(&entry[1], 0,
811 Anum_pg_amop_amopopr,
812 ObjectIdEqualRegProcedure,
813 ObjectIdGetDatum(pred_op));
815 relation = heap_openr(AccessMethodOperatorRelationName);
818 * The following assumes that any given operator will only be in a single
819 * btree operator class. This is true at least for all the pre-defined
820 * operator classes. If it isn't true, then whichever operator class
821 * happens to be returned first for the given operator will be used to
822 * find the associated strategy numbers for the test. --Nels, Jan '93
824 scan = heap_beginscan(relation, false, NowTimeQual, 2, entry);
825 tuple = heap_getnext(scan, false, (Buffer *)NULL);
826 if (! HeapTupleIsValid(tuple)) {
827 elog(DEBUG, "clause_pred_clause_test: unknown pred_op");
830 form = (Form_pg_amop) GETSTRUCT(tuple);
832 /* Get the predicate operator's strategy number (1 to 5) */
833 pred_strategy = (StrategyNumber)form->amopstrategy;
835 /* Remember which operator class this strategy number came from */
836 opclass_id = form->amopclaid;
842 * 2. From the same opclass, find a strategy num for the clause_op
844 ScanKeyEntryInitialize(&entry[1], 0,
845 Anum_pg_amop_amopclaid,
846 ObjectIdEqualRegProcedure,
847 ObjectIdGetDatum(opclass_id));
849 ScanKeyEntryInitialize(&entry[2], 0,
850 Anum_pg_amop_amopopr,
851 ObjectIdEqualRegProcedure,
852 ObjectIdGetDatum(clause_op));
854 scan = heap_beginscan(relation, false, NowTimeQual, 3, entry);
855 tuple = heap_getnext(scan, false, (Buffer *)NULL);
856 if (! HeapTupleIsValid(tuple)) {
857 elog(DEBUG, "clause_pred_clause_test: unknown clause_op");
860 form = (Form_pg_amop) GETSTRUCT(tuple);
862 /* Get the restriction clause operator's strategy number (1 to 5) */
863 clause_strategy = (StrategyNumber)form->amopstrategy;
868 * 3. Look up the "test" strategy number in the implication table
871 test_strategy = BT_implic_table[clause_strategy-1][pred_strategy-1];
872 if (test_strategy == 0)
873 return false; /* the implication cannot be determined */
877 * 4. From the same opclass, find the operator for the test strategy
880 ScanKeyEntryInitialize(&entry[2], 0,
881 Anum_pg_amop_amopstrategy,
882 Integer16EqualRegProcedure,
883 Int16GetDatum(test_strategy));
885 scan = heap_beginscan(relation, false, NowTimeQual, 3, entry);
886 tuple = heap_getnext(scan, false, (Buffer *)NULL);
887 if (! HeapTupleIsValid(tuple)) {
888 elog(DEBUG, "clause_pred_clause_test: unknown test_op");
891 form = (Form_pg_amop) GETSTRUCT(tuple);
893 /* Get the test operator */
894 test_op = form->amopopr;
899 * 5. Evaluate the test
901 test_oper = makeOper(test_op, /* opno */
902 InvalidOid, /* opid */
903 BOOL_TYPEID, /* opresulttype */
905 NULL); /* op_fcache */
906 (void) replace_opid(test_oper);
908 test_expr = make_opclause(test_oper,
909 copyObject(clause_const),
910 copyObject(pred_const));
912 #ifndef OMIT_PARTIAL_INDEX
913 test_result = ExecEvalExpr((Node*)test_expr, NULL, &isNull, NULL);
914 #endif /* OMIT_PARTIAL_INDEX */
916 elog(DEBUG, "clause_pred_clause_test: null test result");
923 /****************************************************************************
924 * ---- ROUTINES TO CHECK JOIN CLAUSES ----
925 ****************************************************************************/
928 * indexable-joinclauses--
929 * Finds all groups of join clauses from among 'joininfo-list' that can
930 * be used in conjunction with 'index'.
932 * The first clause in the group is marked as having the other relation
933 * in the join clause as its outer join relation.
935 * Returns a list of these clause groups.
939 indexable_joinclauses(Rel *rel, Rel *index, List *joininfo_list)
941 JInfo *joininfo = (JInfo*)NULL;
944 List *clausegroups = NIL;
946 foreach(i,joininfo_list) {
947 joininfo = (JInfo*)lfirst(i);
949 group_clauses_by_indexkey (rel,
953 joininfo->jinfoclauseinfo,
956 if (clausegroups != NIL) {
957 List *clauses = lfirst(clausegroups);
959 ((CInfo*)lfirst(clauses))->cinfojoinid =
962 cg_list = nconc(cg_list,clausegroups);
967 /****************************************************************************
968 * ---- PATH CREATION UTILITIES ----
969 ****************************************************************************/
972 * extract_restrict_clauses -
973 * the list of clause info contains join clauses and restriction clauses.
974 * This routine returns the restriction clauses only.
977 extract_restrict_clauses(List *clausegroup)
979 List *restrict_cls = NIL;
982 foreach (l, clausegroup) {
983 CInfo *cinfo = lfirst(l);
985 if (!join_clause_p((Node*)cinfo->clause)) {
986 restrict_cls = lappend(restrict_cls, cinfo);
994 * Creates index path nodes corresponding to paths to be used as inner
995 * relations in nestloop joins.
997 * 'clausegroup-list' is a list of list of clauseinfo nodes which can use
998 * 'index' on their inner relation.
1000 * Returns a list of index pathnodes.
1004 index_innerjoin(Query *root, Rel *rel, List *clausegroup_list, Rel *index)
1006 List *clausegroup = NIL;
1007 List *cg_list = NIL;
1009 IndexPath *pathnode = (IndexPath*)NULL;
1013 foreach(i,clausegroup_list) {
1014 List *attnos, *values, *flags;
1016 clausegroup = lfirst(i);
1017 pathnode = makeNode(IndexPath);
1019 get_joinvars(lfirsti(rel->relids),clausegroup,
1020 &attnos, &values, &flags);
1021 index_selectivity(lfirsti(index->relids),
1023 get_opnos(clausegroup),
1024 getrelid((int)lfirst(rel->relids),
1029 length(clausegroup),
1032 pathnode->path.pathtype = T_IndexScan;
1033 pathnode->path.parent = rel;
1034 pathnode->indexid = index->relids;
1035 pathnode->indexqual = clausegroup;
1037 pathnode->path.joinid = ((CInfo*)lfirst(clausegroup))->cinfojoinid;
1039 pathnode->path.path_cost =
1040 cost_index((Oid)lfirst(index->relids),
1049 /* copy clauseinfo list into path for expensive function processing
1051 pathnode->path.locclauseinfo =
1052 set_difference(copyObject((Node*)rel->clauseinfo),
1055 #if 0 /* fix xfunc */
1056 /* add in cost for expensive functions! -- JMH, 7/7/92 */
1057 if (XfuncMode != XFUNC_OFF) {
1058 ((Path*)pathnode)->path_cost +=
1059 xfunc_get_path_cost((Path*)pathnode);
1062 cg_list = lappend(cg_list,pathnode);
1068 * create-index-paths--
1069 * Creates a list of index path nodes for each group of clauses
1070 * (restriction or join) that can be used in conjunction with an index.
1072 * 'rel' is the relation for which 'index' is defined
1073 * 'clausegroup-list' is the list of clause groups (lists of clauseinfo
1074 * nodes) grouped by mergesortorder
1075 * 'join' is a flag indicating whether or not the clauses are join
1078 * Returns a list of new index path nodes.
1082 create_index_paths(Query *root,
1085 List *clausegroup_list,
1088 List *clausegroup = NIL;
1089 List *ip_list = NIL;
1092 IndexPath *temp_path;
1094 foreach(i, clausegroup_list) {
1096 List *temp_node = NIL;
1099 clausegroup = lfirst(i);
1101 foreach (j,clausegroup) {
1102 clauseinfo = (CInfo*)lfirst(j);
1103 if (!(join_clause_p((Node*)clauseinfo->clause) &&
1104 equal_path_merge_ordering(index->ordering,
1105 clauseinfo->mergesortorder))) {
1110 if (!join || temp) { /* restriction, ordering scan */
1111 temp_path = create_index_path (root, rel,index,clausegroup,join);
1113 lcons(temp_path, NIL);
1114 ip_list = nconc(ip_list,temp_node);
1121 add_index_paths(List *indexpaths, List *new_indexpaths)
1123 return append(indexpaths, new_indexpaths);
1127 function_index_operand(Expr *funcOpnd, Rel *rel, Rel *index)
1129 Oid heapRelid = (Oid)lfirst(rel->relids);
1132 int *indexKeys = index->indexkeys;
1137 * sanity check, make sure we know what we're dealing with here.
1139 if (funcOpnd==NULL ||
1140 nodeTag(funcOpnd)!=T_Expr || funcOpnd->opType!=FUNC_EXPR ||
1141 funcOpnd->oper==NULL || indexKeys==NULL)
1144 function = (Func*)funcOpnd->oper;
1145 funcargs = funcOpnd->args;
1147 if (function->funcid != index->indproc)
1151 * Check that the arguments correspond to the same arguments used
1152 * to create the functional index. To do this we must check that
1153 * 1. refer to the right relatiion.
1154 * 2. the args have the right attr. numbers in the right order.
1157 * Check all args refer to the correct relation (i.e. the one with
1158 * the functional index defined on it (rel). To do this we can
1159 * simply compare range table entry numbers, they must be the same.
1161 foreach (arg, funcargs) {
1162 if (heapRelid != ((Var*)lfirst(arg))->varno)
1167 * check attr numbers and order.
1170 foreach (arg, funcargs) {
1172 if (indexKeys[i]==0)
1175 if (((Var*)lfirst(arg))->varattno != indexKeys[i])
1185 SingleAttributeIndex(Rel *index)
1188 * return false for now as I don't know if we support index scans
1189 * on disjunction and the code doesn't work
1195 * Non-functional indices.
1197 if (index->indproc == InvalidOid)
1198 return (index->indexkeys[0] != 0 &&
1199 index->indexkeys[1] == 0);
1202 * We have a functional index which is a single attr index