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.22 1998/08/02 07:10:38 momjian Exp $
13 *-------------------------------------------------------------------------
19 #include "access/attnum.h"
20 #include "access/heapam.h"
21 #include "access/nbtree.h"
22 #include "catalog/catname.h"
23 #include "catalog/pg_amop.h"
24 #include "catalog/pg_type.h"
25 #include "executor/executor.h"
27 #include "nodes/makefuncs.h"
28 #include "nodes/nodeFuncs.h"
29 #include "nodes/pg_list.h"
30 #include "nodes/relation.h"
31 #include "optimizer/clauses.h"
32 #include "optimizer/clauseinfo.h"
33 #include "optimizer/cost.h"
34 #include "optimizer/internal.h"
35 #include "optimizer/keys.h"
36 #include "optimizer/ordering.h"
37 #include "optimizer/paths.h"
38 #include "optimizer/plancat.h"
39 #include "optimizer/pathnode.h"
40 #include "optimizer/xfunc.h"
41 #include "parser/parsetree.h" /* for getrelid() */
42 #include "utils/lsyscache.h"
46 match_index_orclauses(RelOptInfo *rel, RelOptInfo *index, int indexkey,
47 int xclass, List *clauseinfo_list);
49 match_index_to_operand(int indexkey, Expr *operand,
50 RelOptInfo *rel, RelOptInfo *index);
52 match_index_orclause(RelOptInfo *rel, RelOptInfo *index, int indexkey,
53 int xclass, List *or_clauses, List *other_matching_indices);
55 group_clauses_by_indexkey(RelOptInfo *rel, RelOptInfo *index,
56 int *indexkeys, Oid *classes, List *clauseinfo_list);
58 group_clauses_by_ikey_for_joins(RelOptInfo *rel, RelOptInfo *index,
59 int *indexkeys, Oid *classes, List *join_cinfo_list, List *restr_cinfo_list);
61 match_clause_to_indexkey(RelOptInfo *rel, RelOptInfo *index, int indexkey,
62 int xclass, CInfo *clauseInfo, bool join);
64 pred_test(List *predicate_list, List *clauseinfo_list,
66 static bool one_pred_test(Expr *predicate, List *clauseinfo_list);
67 static bool one_pred_clause_expr_test(Expr *predicate, Node *clause);
68 static bool one_pred_clause_test(Expr *predicate, Node *clause);
69 static bool clause_pred_clause_test(Expr *predicate, Node *clause);
71 indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
72 List *joininfo_list, List *clauseinfo_list);
74 index_innerjoin(Query *root, RelOptInfo *rel,
75 List *clausegroup_list, RelOptInfo *index);
77 create_index_paths(Query *root, RelOptInfo *rel, RelOptInfo *index,
78 List *clausegroup_list, bool join);
79 static List *add_index_paths(List *indexpaths, List *new_indexpaths);
80 static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index);
85 * Finds all possible index paths by determining which indices in the
86 * list 'indices' are usable.
88 * To be usable, an index must match against either a set of
89 * restriction clauses or join clauses.
91 * Note that the current implementation requires that there exist
92 * matching clauses for every key in the index (i.e., no partial
93 * matches are allowed).
95 * If an index can't be used with restriction clauses, but its keys
96 * match those of the result sort order (according to information stored
97 * within 'sortkeys'), then the index is also considered.
99 * 'rel' is the relation entry to which these index paths correspond
100 * 'indices' is a list of possible index paths
101 * 'clauseinfo-list' is a list of restriction clauseinfo nodes for 'rel'
102 * 'joininfo-list' is a list of joininfo nodes for 'rel'
103 * 'sortkeys' is a node describing the result sort order (from
106 * Returns a list of index nodes.
110 find_index_paths(Query *root,
113 List *clauseinfo_list,
116 List *scanclausegroups = NIL;
117 List *scanpaths = NIL;
118 RelOptInfo *index = (RelOptInfo *) NULL;
119 List *joinclausegroups = NIL;
120 List *joinpaths = NIL;
124 foreach(ilist, indices)
126 index = (RelOptInfo *) lfirst(ilist);
128 /* If this is a partial index, return if it fails the predicate test */
129 if (index->indpred != NIL)
130 if (!pred_test(index->indpred, clauseinfo_list, joininfo_list))
134 * 1. Try matching the index against subclauses of an 'or' clause.
135 * The fields of the clauseinfo nodes are marked with lists of the
136 * matching indices. No path are actually created. We currently
137 * only look to match the first key. We don't find multi-key index
138 * cases where an AND matches the first key, and the OR matches the
141 match_index_orclauses(rel,
148 * 2. If the keys of this index match any of the available restriction
149 * clauses, then create pathnodes corresponding to each group of
152 scanclausegroups = group_clauses_by_indexkey(rel,
159 if (scanclausegroups != NIL)
160 scanpaths = create_index_paths(root,
167 * 3. If this index can be used with any join clause, then create
168 * pathnodes for each group of usable clauses. An index can be used
169 * with a join clause if its ordering is useful for a mergejoin, or if
170 * the index can possibly be used for scanning the inner relation of a
173 joinclausegroups = indexable_joinclauses(rel, index, joininfo_list, clauseinfo_list);
176 if (joinclausegroups != NIL)
178 List *new_join_paths = create_index_paths(root, rel,
182 List *innerjoin_paths = index_innerjoin(root, rel, joinclausegroups, index);
184 rel->innerjoin = nconc(rel->innerjoin, innerjoin_paths);
185 joinpaths = new_join_paths;
189 * Some sanity checks to make sure that the indexpath is valid.
191 if (joinpaths != NULL)
192 retval = add_index_paths(joinpaths, retval);
193 if (scanpaths != NULL)
194 retval = add_index_paths(scanpaths, retval);
202 /****************************************************************************
203 * ---- ROUTINES TO MATCH 'OR' CLAUSES ----
204 ****************************************************************************/
208 * match-index-orclauses--
209 * Attempt to match an index against subclauses within 'or' clauses.
210 * If the index does match, then the clause is marked with information
213 * Essentially, this adds 'index' to the list of indices in the
214 * ClauseInfo field of each of the clauses which it matches.
216 * 'rel' is the node of the relation on which the index is defined.
217 * 'index' is the index node.
218 * 'indexkey' is the (single) key of the index
219 * 'class' is the class of the operator corresponding to 'indexkey'.
220 * 'clauseinfo-list' is the list of available restriction clauses.
226 match_index_orclauses(RelOptInfo *rel,
230 List *clauseinfo_list)
232 CInfo *clauseinfo = (CInfo *) NULL;
235 foreach(i, clauseinfo_list)
237 clauseinfo = (CInfo *) lfirst(i);
238 if (valid_or_clause(clauseinfo))
242 * Mark the 'or' clause with a list of indices which match
243 * each of its subclauses. The list is generated by adding
244 * 'index' to the existing list where appropriate.
246 clauseinfo->indexids =
247 match_index_orclause(rel, index, indexkey,
249 clauseinfo->clause->args,
250 clauseinfo->indexids);
256 * match_index_operand--
257 * Generalize test for a match between an existing index's key
258 * and the operand on the rhs of a restriction clause. Now check
259 * for functional indices as well.
262 match_index_to_operand(int indexkey,
271 if (index->indproc == InvalidOid)
272 return match_indexkey_operand(indexkey, (Var *) operand, rel);
275 * functional index check
277 return (function_index_operand(operand, rel, index));
281 * match-index-orclause--
282 * Attempts to match an index against the subclauses of an 'or' clause.
284 * A match means that:
285 * (1) the operator within the subclause can be used with one
286 * of the index's operator classes, and
287 * (2) there is a usable key that matches the variable within a
290 * 'or-clauses' are the remaining subclauses within the 'or' clause
291 * 'other-matching-indices' is the list of information on other indices
292 * that have already been matched to subclauses within this
293 * particular 'or' clause (i.e., a list previously generated by
296 * Returns a list of the form ((a b c) (d e f) nil (g h) ...) where
297 * a,b,c are nodes of indices that match the first subclause in
298 * 'or-clauses', d,e,f match the second subclause, no indices
299 * match the third, g,h match the fourth, etc.
302 match_index_orclause(RelOptInfo *rel,
307 List *other_matching_indices)
310 List *matched_indices;
311 List *index_list = NIL;
314 foreach(clist, or_clauses)
316 clause = lfirst(clist);
317 if (other_matching_indices)
318 matched_indices = lfirst(other_matching_indices);
320 matched_indices = NIL;
322 if (is_opclause(clause) &&
323 op_class(((Oper *) ((Expr *) clause)->oper)->opno,
324 xclass, index->relam) &&
325 ((match_index_to_operand(indexkey,
326 (Expr *) get_leftop((Expr *) clause),
329 IsA(get_rightop((Expr *) clause), Const)) ||
330 (match_index_to_operand(indexkey,
331 (Expr *) get_leftop((Expr *) clause),
334 IsA(get_rightop((Expr *) clause), Const))))
336 matched_indices = lcons(index, matched_indices);
339 /* for the first index, we are creating the indexids list */
340 index_list = lappend(index_list, matched_indices);
342 if (other_matching_indices)
343 other_matching_indices = lnext(other_matching_indices);
349 /****************************************************************************
350 * ---- ROUTINES TO CHECK RESTRICTIONS ----
351 ****************************************************************************/
355 * DoneMatchingIndexKeys() - MACRO
357 * Determine whether we should continue matching index keys in a clause.
358 * Depends on if there are more to match or if this is a functional index.
359 * In the latter case we stop after the first match since the there can
360 * be only key (i.e. the function's return value) and the attributes in
361 * keys list represent the arguments to the function. -mer 3 Oct. 1991
363 #define DoneMatchingIndexKeys(indexkeys, index) \
364 (indexkeys[0] == 0 || \
365 (index->indproc != InvalidOid))
368 * group-clauses-by-indexkey--
369 * Determines whether there are clauses which will match each and every
370 * one of the remaining keys of an index.
372 * 'rel' is the node of the relation corresponding to the index.
373 * 'indexkeys' are the remaining index keys to be matched.
374 * 'classes' are the classes of the index operators on those keys.
375 * 'clauses' is either:
376 * (1) the list of available restriction clauses on a single
378 * (2) a list of join clauses between 'rel' and a fixed set of
380 * depending on the value of 'join'.
382 * NOTE: it works now for restriction clauses only. - vadim 03/18/97
384 * Returns all possible groups of clauses that will match (given that
385 * one or more clauses can match any of the remaining keys).
386 * E.g., if you have clauses A, B, and C, ((A B) (A C)) might be
387 * returned for an index with 2 keys.
391 group_clauses_by_indexkey(RelOptInfo *rel,
395 List *clauseinfo_list)
397 List *curCinfo = NIL;
398 CInfo *matched_clause = (CInfo *) NULL;
399 List *clausegroup = NIL;
403 if (clauseinfo_list == NIL || indexkeys[0] == 0)
408 List *tempgroup = NIL;
410 curIndxKey = indexkeys[0];
411 curClass = classes[0];
413 foreach(curCinfo, clauseinfo_list)
415 CInfo *temp = (CInfo *) lfirst(curCinfo);
417 matched_clause = match_clause_to_indexkey(rel,
426 tempgroup = lappend(tempgroup, matched_clause);
428 if (tempgroup == NIL)
431 clausegroup = nconc(clausegroup, tempgroup);
436 } while (!DoneMatchingIndexKeys(indexkeys, index));
438 /* clausegroup holds all matched clauses ordered by indexkeys */
440 if (clausegroup != NIL)
441 return (lcons(clausegroup, NIL));
446 * group-clauses-by-ikey-for-joins--
447 * special edition of group-clauses-by-indexkey - will
448 * match join & restriction clauses. See comment in indexable_joinclauses.
453 group_clauses_by_ikey_for_joins(RelOptInfo *rel,
457 List *join_cinfo_list,
458 List *restr_cinfo_list)
460 List *curCinfo = NIL;
461 CInfo *matched_clause = (CInfo *) NULL;
462 List *clausegroup = NIL;
467 if (join_cinfo_list == NIL || indexkeys[0] == 0)
472 List *tempgroup = NIL;
474 curIndxKey = indexkeys[0];
475 curClass = classes[0];
477 foreach(curCinfo, join_cinfo_list)
479 CInfo *temp = (CInfo *) lfirst(curCinfo);
481 matched_clause = match_clause_to_indexkey(rel,
490 tempgroup = lappend(tempgroup, matched_clause);
493 foreach(curCinfo, restr_cinfo_list)
495 CInfo *temp = (CInfo *) lfirst(curCinfo);
497 matched_clause = match_clause_to_indexkey(rel,
506 tempgroup = lappend(tempgroup, matched_clause);
508 if (tempgroup == NIL)
511 clausegroup = nconc(clausegroup, tempgroup);
516 } while (!DoneMatchingIndexKeys(indexkeys, index));
518 /* clausegroup holds all matched clauses ordered by indexkeys */
520 if (clausegroup != NIL)
524 * if no one join clause was matched then there ain't clauses for
529 freeList(clausegroup);
532 return (lcons(clausegroup, NIL));
538 * IndexScanableClause () MACRO
540 * Generalize condition on which we match a clause with an index.
541 * Now we can match with functional indices.
543 #define IndexScanableOperand(opnd, indkeys, rel, index) \
544 ((index->indproc == InvalidOid) ? \
545 match_indexkey_operand(indkeys, opnd, rel) : \
546 function_index_operand((Expr*)opnd,rel,index))
550 * equal_indexkey_var(indkeys,opnd) : \
552 * match_indexkey_operand(indkeys, opnd, rel) : \
557 * match_clause_to-indexkey--
558 * Finds the first of a relation's available restriction clauses that
559 * matches a key of an index.
561 * To match, the clause must:
562 * (1) be in the form (op var const) if the clause is a single-
563 * relation clause, and
564 * (2) contain an operator which is in the same class as the index
565 * operator for this key.
567 * If the clause being matched is a join clause, then 'join' is t.
569 * Returns a single clauseinfo node corresponding to the matching
572 * NOTE: returns nil if clause is an or_clause.
576 match_clause_to_indexkey(RelOptInfo *rel,
583 Expr *clause = clauseInfo->clause;
586 Oid join_op = InvalidOid;
587 Oid restrict_op = InvalidOid;
588 bool isIndexable = false;
590 if (or_clause((Node *) clause) ||
591 not_clause((Node *) clause) || single_node((Node *) clause))
592 return ((CInfo *) NULL);
594 leftop = get_leftop(clause);
595 rightop = get_rightop(clause);
598 * If this is not a join clause, check for clauses of the form:
599 * (operator var/func constant) and (operator constant var/func)
605 * Check for standard s-argable clause
607 if ((rightop && IsA(rightop, Const)) ||
608 (rightop && IsA(rightop, Param)))
610 restrict_op = ((Oper *) ((Expr *) clause)->oper)->opno;
612 (op_class(restrict_op, xclass, index->relam) &&
613 IndexScanableOperand(leftop,
620 * Must try to commute the clause to standard s-arg format.
622 else if ((leftop && IsA(leftop, Const)) ||
623 (leftop && IsA(leftop, Param)))
626 get_commutator(((Oper *) ((Expr *) clause)->oper)->opno);
628 if ((restrict_op != InvalidOid) &&
629 op_class(restrict_op, xclass, index->relam) &&
630 IndexScanableOperand(rightop,
631 indexkey, rel, index))
636 * In place list modification. (op const var/func) -> (op
639 CommuteClause((Node *) clause);
645 * Check for an indexable scan on one of the join relations. clause is
646 * of the form (operator var/func var/func)
651 && match_index_to_operand(indexkey, (Expr *) rightop, rel, index))
654 join_op = get_commutator(((Oper *) ((Expr *) clause)->oper)->opno);
658 && match_index_to_operand(indexkey,
659 (Expr *) leftop, rel, index))
660 join_op = ((Oper *) ((Expr *) clause)->oper)->opno;
662 if (join_op && op_class(join_op, xclass, index->relam) &&
663 join_clause_p((Node *) clause))
668 * If we're using the operand's commutator we must commute the
671 if (join_op != ((Oper *) ((Expr *) clause)->oper)->opno)
672 CommuteClause((Node *) clause);
682 /****************************************************************************
683 * ---- ROUTINES TO DO PARTIAL INDEX PREDICATE TESTS ----
684 ****************************************************************************/
688 * Does the "predicate inclusion test" for partial indexes.
690 * Recursively checks whether the clauses in clauseinfo_list imply
691 * that the given predicate is true.
693 * This routine (together with the routines it calls) iterates over
694 * ANDs in the predicate first, then reduces the qualification
695 * clauses down to their constituent terms, and iterates over ORs
696 * in the predicate last. This order is important to make the test
697 * succeed whenever possible (assuming the predicate has been
698 * successfully cnfify()-ed). --Nels, Jan '93
701 pred_test(List *predicate_list, List *clauseinfo_list, List *joininfo_list)
708 * Note: if Postgres tried to optimize queries by forming equivalence
709 * classes over equi-joined attributes (i.e., if it recognized that a
710 * qualification such as "where a.b=c.d and a.b=5" could make use of
711 * an index on c.d), then we could use that equivalence class info
712 * here with joininfo_list to do more complete tests for the usability
713 * of a partial index. For now, the test only uses restriction
714 * clauses (those in clauseinfo_list). --Nels, Dec '92
717 if (predicate_list == NULL)
718 return true; /* no predicate: the index is usable */
719 if (clauseinfo_list == NULL)
720 return false; /* no restriction clauses: the test must
723 foreach(pred, predicate_list)
727 * if any clause is not implied, the whole predicate is not
730 if (and_clause(lfirst(pred)))
732 items = ((Expr *) lfirst(pred))->args;
735 if (!one_pred_test(lfirst(item), clauseinfo_list))
739 else if (!one_pred_test(lfirst(pred), clauseinfo_list))
748 * Does the "predicate inclusion test" for one conjunct of a predicate
752 one_pred_test(Expr *predicate, List *clauseinfo_list)
757 Assert(predicate != NULL);
758 foreach(item, clauseinfo_list)
760 clauseinfo = (CInfo *) lfirst(item);
761 /* if any clause implies the predicate, return true */
762 if (one_pred_clause_expr_test(predicate, (Node *) clauseinfo->clause))
770 * one_pred_clause_expr_test--
771 * Does the "predicate inclusion test" for a general restriction-clause
775 one_pred_clause_expr_test(Expr *predicate, Node *clause)
780 if (is_opclause(clause))
781 return one_pred_clause_test(predicate, clause);
782 else if (or_clause(clause))
784 items = ((Expr *) clause)->args;
787 /* if any OR item doesn't imply the predicate, clause doesn't */
788 if (!one_pred_clause_expr_test(predicate, lfirst(item)))
793 else if (and_clause(clause))
795 items = ((Expr *) clause)->args;
800 * if any AND item implies the predicate, the whole clause
803 if (one_pred_clause_expr_test(predicate, lfirst(item)))
810 /* unknown clause type never implies the predicate */
817 * one_pred_clause_test--
818 * Does the "predicate inclusion test" for one conjunct of a predicate
819 * expression for a simple restriction clause.
822 one_pred_clause_test(Expr *predicate, Node *clause)
827 if (is_opclause((Node *) predicate))
828 return clause_pred_clause_test(predicate, clause);
829 else if (or_clause((Node *) predicate))
831 items = predicate->args;
834 /* if any item is implied, the whole predicate is implied */
835 if (one_pred_clause_test(lfirst(item), clause))
840 else if (and_clause((Node *) predicate))
842 items = predicate->args;
847 * if any item is not implied, the whole predicate is not
850 if (!one_pred_clause_test(lfirst(item), clause))
857 elog(DEBUG, "Unsupported predicate type, index will not be used");
864 * Define an "operator implication table" for btree operators ("strategies").
865 * The "strategy numbers" are: (1) < (2) <= (3) = (4) >= (5) >
867 * The interpretation of:
869 * test_op = BT_implic_table[given_op-1][target_op-1]
871 * where test_op, given_op and target_op are strategy numbers (from 1 to 5)
872 * of btree operators, is as follows:
874 * If you know, for some ATTR, that "ATTR given_op CONST1" is true, and you
875 * want to determine whether "ATTR target_op CONST2" must also be true, then
876 * you can use "CONST1 test_op CONST2" as a test. If this test returns true,
877 * then the target expression must be true; if the test returns false, then
878 * the target expression may be false.
880 * An entry where test_op==0 means the implication cannot be determined, i.e.,
881 * this test should always be considered false.
884 StrategyNumber BT_implic_table[BTMaxStrategyNumber][BTMaxStrategyNumber] = {
894 * clause_pred_clause_test--
895 * Use operator class info to check whether clause implies predicate.
897 * Does the "predicate inclusion test" for a "simple clause" predicate
898 * for a single "simple clause" restriction. Currently, this only handles
899 * (binary boolean) operators that are in some btree operator class.
900 * Eventually, rtree operators could also be handled by defining an
901 * appropriate "RT_implic_table" array.
904 clause_pred_clause_test(Expr *predicate, Node *clause)
914 StrategyNumber pred_strategy,
924 ScanKeyData entry[3];
927 pred_var = (Var *) get_leftop(predicate);
928 pred_const = (Const *) get_rightop(predicate);
929 clause_var = (Var *) get_leftop((Expr *) clause);
930 clause_const = (Const *) get_rightop((Expr *) clause);
932 /* Check the basic form; for now, only allow the simplest case */
933 if (!is_opclause(clause) ||
934 !IsA(clause_var, Var) ||
935 !IsA(clause_const, Const) ||
936 !IsA(predicate->oper, Oper) ||
937 !IsA(pred_var, Var) ||
938 !IsA(pred_const, Const))
942 * The implication can't be determined unless the predicate and the
943 * clause refer to the same attribute.
945 if (clause_var->varattno != pred_var->varattno)
948 /* Get the operators for the two clauses we're comparing */
949 pred_op = ((Oper *) ((Expr *) predicate)->oper)->opno;
950 clause_op = ((Oper *) ((Expr *) clause)->oper)->opno;
954 * 1. Find a "btree" strategy number for the pred_op
956 /* XXX - hardcoded amopid value 403 to find "btree" operator classes */
957 ScanKeyEntryInitialize(&entry[0], 0,
960 ObjectIdGetDatum(403));
962 ScanKeyEntryInitialize(&entry[1], 0,
963 Anum_pg_amop_amopopr,
965 ObjectIdGetDatum(pred_op));
967 relation = heap_openr(AccessMethodOperatorRelationName);
970 * The following assumes that any given operator will only be in a
971 * single btree operator class. This is true at least for all the
972 * pre-defined operator classes. If it isn't true, then whichever
973 * operator class happens to be returned first for the given operator
974 * will be used to find the associated strategy numbers for the test.
977 scan = heap_beginscan(relation, false, SnapshotNow, 2, entry);
978 tuple = heap_getnext(scan, false, (Buffer *) NULL);
979 if (!HeapTupleIsValid(tuple))
981 elog(DEBUG, "clause_pred_clause_test: unknown pred_op");
984 form = (Form_pg_amop) GETSTRUCT(tuple);
986 /* Get the predicate operator's strategy number (1 to 5) */
987 pred_strategy = (StrategyNumber) form->amopstrategy;
989 /* Remember which operator class this strategy number came from */
990 opclass_id = form->amopclaid;
996 * 2. From the same opclass, find a strategy num for the clause_op
998 ScanKeyEntryInitialize(&entry[1], 0,
999 Anum_pg_amop_amopclaid,
1001 ObjectIdGetDatum(opclass_id));
1003 ScanKeyEntryInitialize(&entry[2], 0,
1004 Anum_pg_amop_amopopr,
1006 ObjectIdGetDatum(clause_op));
1008 scan = heap_beginscan(relation, false, SnapshotNow, 3, entry);
1009 tuple = heap_getnext(scan, false, (Buffer *) NULL);
1010 if (!HeapTupleIsValid(tuple))
1012 elog(DEBUG, "clause_pred_clause_test: unknown clause_op");
1015 form = (Form_pg_amop) GETSTRUCT(tuple);
1017 /* Get the restriction clause operator's strategy number (1 to 5) */
1018 clause_strategy = (StrategyNumber) form->amopstrategy;
1023 * 3. Look up the "test" strategy number in the implication table
1026 test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
1027 if (test_strategy == 0)
1028 return false; /* the implication cannot be determined */
1032 * 4. From the same opclass, find the operator for the test strategy
1035 ScanKeyEntryInitialize(&entry[2], 0,
1036 Anum_pg_amop_amopstrategy,
1038 Int16GetDatum(test_strategy));
1040 scan = heap_beginscan(relation, false, SnapshotNow, 3, entry);
1041 tuple = heap_getnext(scan, false, (Buffer *) NULL);
1042 if (!HeapTupleIsValid(tuple))
1044 elog(DEBUG, "clause_pred_clause_test: unknown test_op");
1047 form = (Form_pg_amop) GETSTRUCT(tuple);
1049 /* Get the test operator */
1050 test_op = form->amopopr;
1055 * 5. Evaluate the test
1057 test_oper = makeOper(test_op, /* opno */
1058 InvalidOid, /* opid */
1059 BOOLOID, /* opresulttype */
1061 NULL); /* op_fcache */
1062 replace_opid(test_oper);
1064 test_expr = make_opclause(test_oper,
1065 copyObject(clause_const),
1066 copyObject(pred_const));
1068 #ifndef OMIT_PARTIAL_INDEX
1069 test_result = ExecEvalExpr((Node *) test_expr, NULL, &isNull, NULL);
1070 #endif /* OMIT_PARTIAL_INDEX */
1073 elog(DEBUG, "clause_pred_clause_test: null test result");
1080 /****************************************************************************
1081 * ---- ROUTINES TO CHECK JOIN CLAUSES ----
1082 ****************************************************************************/
1085 * indexable-joinclauses--
1086 * Finds all groups of join clauses from among 'joininfo-list' that can
1087 * be used in conjunction with 'index'.
1089 * The first clause in the group is marked as having the other relation
1090 * in the join clause as its outer join relation.
1092 * Returns a list of these clause groups.
1094 * Added: clauseinfo_list - list of restriction CInfos. It's to
1095 * support multi-column indices in joins and for cases
1096 * when a key is in both join & restriction clauses. - vadim 03/18/97
1100 indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
1101 List *joininfo_list, List *clauseinfo_list)
1103 JInfo *joininfo = (JInfo *) NULL;
1104 List *cg_list = NIL;
1106 List *clausegroups = NIL;
1108 foreach(i, joininfo_list)
1110 joininfo = (JInfo *) lfirst(i);
1112 if (joininfo->jinfoclauseinfo == NIL)
1115 group_clauses_by_ikey_for_joins(rel,
1119 joininfo->jinfoclauseinfo,
1122 if (clausegroups != NIL)
1124 List *clauses = lfirst(clausegroups);
1126 ((CInfo *) lfirst(clauses))->cinfojoinid =
1127 joininfo->otherrels;
1129 cg_list = nconc(cg_list, clausegroups);
1134 /****************************************************************************
1135 * ---- PATH CREATION UTILITIES ----
1136 ****************************************************************************/
1139 * extract_restrict_clauses -
1140 * the list of clause info contains join clauses and restriction clauses.
1141 * This routine returns the restriction clauses only.
1145 extract_restrict_clauses(List *clausegroup)
1147 List *restrict_cls = NIL;
1150 foreach(l, clausegroup)
1152 CInfo *cinfo = lfirst(l);
1154 if (!join_clause_p((Node *) cinfo->clause))
1155 restrict_cls = lappend(restrict_cls, cinfo);
1157 return restrict_cls;
1164 * Creates index path nodes corresponding to paths to be used as inner
1165 * relations in nestloop joins.
1167 * 'clausegroup-list' is a list of list of clauseinfo nodes which can use
1168 * 'index' on their inner relation.
1170 * Returns a list of index pathnodes.
1174 index_innerjoin(Query *root, RelOptInfo *rel, List *clausegroup_list,
1177 List *clausegroup = NIL;
1178 List *cg_list = NIL;
1180 IndexPath *pathnode = (IndexPath *) NULL;
1184 foreach(i, clausegroup_list)
1190 clausegroup = lfirst(i);
1191 pathnode = makeNode(IndexPath);
1193 get_joinvars(lfirsti(rel->relids), clausegroup,
1194 &attnos, &values, &flags);
1195 index_selectivity(lfirsti(index->relids),
1197 get_opnos(clausegroup),
1198 getrelid(lfirsti(rel->relids),
1203 length(clausegroup),
1206 pathnode->path.pathtype = T_IndexScan;
1207 pathnode->path.parent = rel;
1208 pathnode->indexid = index->relids;
1209 pathnode->indexkeys = index->indexkeys;
1210 pathnode->indexqual = clausegroup;
1212 pathnode->path.joinid = ((CInfo *) lfirst(clausegroup))->cinfojoinid;
1214 pathnode->path.path_cost =
1215 cost_index((Oid) lfirsti(index->relids),
1225 * copy clauseinfo list into path for expensive function
1226 * processing -- JMH, 7/7/92
1228 pathnode->path.locclauseinfo =
1229 set_difference(copyObject((Node *) rel->clauseinfo),
1232 #if 0 /* fix xfunc */
1233 /* add in cost for expensive functions! -- JMH, 7/7/92 */
1234 if (XfuncMode != XFUNC_OFF)
1236 ((Path *) pathnode)->path_cost +=
1237 xfunc_get_path_cost((Path *) pathnode);
1240 cg_list = lappend(cg_list, pathnode);
1246 * create-index-paths--
1247 * Creates a list of index path nodes for each group of clauses
1248 * (restriction or join) that can be used in conjunction with an index.
1250 * 'rel' is the relation for which 'index' is defined
1251 * 'clausegroup-list' is the list of clause groups (lists of clauseinfo
1252 * nodes) grouped by mergesortorder
1253 * 'join' is a flag indicating whether or not the clauses are join
1256 * Returns a list of new index path nodes.
1260 create_index_paths(Query *root,
1263 List *clausegroup_list,
1266 List *clausegroup = NIL;
1267 List *ip_list = NIL;
1270 IndexPath *temp_path;
1272 foreach(i, clausegroup_list)
1275 List *temp_node = NIL;
1278 clausegroup = lfirst(i);
1280 foreach(j, clausegroup)
1282 clauseinfo = (CInfo *) lfirst(j);
1283 if (!(join_clause_p((Node *) clauseinfo->clause) &&
1284 equal_path_merge_ordering(index->ordering,
1285 clauseinfo->mergesortorder)))
1290 { /* restriction, ordering scan */
1291 temp_path = create_index_path(root, rel, index, clausegroup, join);
1293 lcons(temp_path, NIL);
1294 ip_list = nconc(ip_list, temp_node);
1301 add_index_paths(List *indexpaths, List *new_indexpaths)
1303 return append(indexpaths, new_indexpaths);
1307 function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index)
1309 Oid heapRelid = (Oid) lfirsti(rel->relids);
1312 int *indexKeys = index->indexkeys;
1317 * sanity check, make sure we know what we're dealing with here.
1319 if (funcOpnd == NULL ||
1320 nodeTag(funcOpnd) != T_Expr || funcOpnd->opType != FUNC_EXPR ||
1321 funcOpnd->oper == NULL || indexKeys == NULL)
1324 function = (Func *) funcOpnd->oper;
1325 funcargs = funcOpnd->args;
1327 if (function->funcid != index->indproc)
1331 * Check that the arguments correspond to the same arguments used to
1332 * create the functional index. To do this we must check that 1.
1333 * refer to the right relatiion. 2. the args have the right attr.
1334 * numbers in the right order.
1337 * Check all args refer to the correct relation (i.e. the one with the
1338 * functional index defined on it (rel). To do this we can simply
1339 * compare range table entry numbers, they must be the same.
1341 foreach(arg, funcargs)
1343 if (heapRelid != ((Var *) lfirst(arg))->varno)
1348 * check attr numbers and order.
1351 foreach(arg, funcargs)
1354 if (indexKeys[i] == 0)
1357 if (((Var *) lfirst(arg))->varattno != indexKeys[i])