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.42 1999/02/10 21:02: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/restrictinfo.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 "parser/parse_expr.h" /* for exprType() */
43 #include "parser/parse_oper.h" /* for oprid() and oper() */
44 #include "parser/parse_coerce.h"/* for IS_BINARY_COMPATIBLE() */
45 #include "utils/lsyscache.h"
48 static void match_index_orclauses(RelOptInfo *rel, RelOptInfo *index, int indexkey,
49 int xclass, List *restrictinfo_list);
50 static bool match_index_to_operand(int indexkey, Expr *operand,
51 RelOptInfo *rel, RelOptInfo *index);
52 static List *match_index_orclause(RelOptInfo *rel, RelOptInfo *index, int indexkey,
53 int xclass, List *or_clauses, List *other_matching_indices);
54 static List *group_clauses_by_indexkey(RelOptInfo *rel, RelOptInfo *index,
55 int *indexkeys, Oid *classes, List *restrictinfo_list);
56 static List *group_clauses_by_ikey_for_joins(RelOptInfo *rel, RelOptInfo *index,
57 int *indexkeys, Oid *classes, List *join_cinfo_list, List *restr_cinfo_list);
58 static RestrictInfo *match_clause_to_indexkey(RelOptInfo *rel, RelOptInfo *index, int indexkey,
59 int xclass, RestrictInfo * restrictInfo, bool join);
60 static bool pred_test(List *predicate_list, List *restrictinfo_list,
62 static bool one_pred_test(Expr *predicate, List *restrictinfo_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(RelOptInfo *rel, RelOptInfo *index,
67 List *joininfo_list, List *restrictinfo_list);
68 static List *index_innerjoin(Query *root, RelOptInfo *rel,
69 List *clausegroup_list, RelOptInfo *index);
70 static List *create_index_paths(Query *root, RelOptInfo *rel, RelOptInfo *index,
71 List *clausegroup_list, bool join);
72 static List *add_index_paths(List *indexpaths, List *new_indexpaths);
73 static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index);
77 * Finds all possible index paths by determining which indices in the
78 * list 'indices' are usable.
80 * To be usable, an index must match against either a set of
81 * restriction clauses or join clauses.
83 * Note that the current implementation requires that there exist
84 * matching clauses for every key in the index (i.e., no partial
85 * matches are allowed).
87 * If an index can't be used with restriction clauses, but its keys
88 * match those of the result sort order (according to information stored
89 * within 'sortkeys'), then the index is also considered.
91 * 'rel' is the relation entry to which these index paths correspond
92 * 'indices' is a list of possible index paths
93 * 'restrictinfo-list' is a list of restriction restrictinfo nodes for 'rel'
94 * 'joininfo-list' is a list of joininfo nodes for 'rel'
95 * 'sortkeys' is a node describing the result sort order (from
98 * Returns a list of index nodes.
102 find_index_paths(Query *root,
105 List *restrictinfo_list,
108 List *scanclausegroups = NIL;
109 List *scanpaths = NIL;
110 RelOptInfo *index = (RelOptInfo *) NULL;
111 List *joinclausegroups = NIL;
112 List *joinpaths = NIL;
116 foreach(ilist, indices)
118 index = (RelOptInfo *) lfirst(ilist);
121 * If this is a partial index, return if it fails the predicate
124 if (index->indpred != NIL)
125 if (!pred_test(index->indpred, restrictinfo_list, joininfo_list))
129 * 1. Try matching the index against subclauses of an 'or' clause.
130 * The fields of the restrictinfo nodes are marked with lists of the
131 * matching indices. No path are actually created. We currently
132 * only look to match the first key. We don't find multi-key
133 * index cases where an AND matches the first key, and the OR
134 * matches the second key.
136 match_index_orclauses(rel,
143 * 2. If the keys of this index match any of the available
144 * restriction clauses, then create pathnodes corresponding to
145 * each group of usable clauses.
147 scanclausegroups = group_clauses_by_indexkey(rel,
154 if (scanclausegroups != NIL)
155 scanpaths = create_index_paths(root,
162 * 3. If this index can be used with any join clause, then create
163 * pathnodes for each group of usable clauses. An index can be
164 * used with a join clause if its ordering is useful for a
165 * mergejoin, or if the index can possibly be used for scanning
166 * the inner relation of a nestloop join.
168 joinclausegroups = indexable_joinclauses(rel, index, joininfo_list, restrictinfo_list);
171 if (joinclausegroups != NIL)
173 List *new_join_paths = create_index_paths(root, rel,
177 List *innerjoin_paths = index_innerjoin(root, rel, joinclausegroups, index);
179 rel->innerjoin = nconc(rel->innerjoin, innerjoin_paths);
180 joinpaths = new_join_paths;
184 * Some sanity checks to make sure that the indexpath is valid.
186 if (joinpaths != NULL)
187 retval = add_index_paths(joinpaths, retval);
188 if (scanpaths != NULL)
189 retval = add_index_paths(scanpaths, retval);
197 /****************************************************************************
198 * ---- ROUTINES TO MATCH 'OR' CLAUSES ----
199 ****************************************************************************/
203 * match-index-orclauses--
204 * Attempt to match an index against subclauses within 'or' clauses.
205 * If the index does match, then the clause is marked with information
208 * Essentially, this adds 'index' to the list of indices in the
209 * RestrictInfo field of each of the clauses which it matches.
211 * 'rel' is the node of the relation on which the index is defined.
212 * 'index' is the index node.
213 * 'indexkey' is the (single) key of the index
214 * 'class' is the class of the operator corresponding to 'indexkey'.
215 * 'restrictinfo-list' is the list of available restriction clauses.
221 match_index_orclauses(RelOptInfo *rel,
225 List *restrictinfo_list)
227 RestrictInfo *restrictinfo = (RestrictInfo *) NULL;
230 foreach(i, restrictinfo_list)
232 restrictinfo = (RestrictInfo *) lfirst(i);
233 if (valid_or_clause(restrictinfo))
237 * Mark the 'or' clause with a list of indices which match
238 * each of its subclauses. The list is generated by adding
239 * 'index' to the existing list where appropriate.
241 restrictinfo->indexids = match_index_orclause(rel, index, indexkey,
243 restrictinfo->clause->args,
244 restrictinfo->indexids);
249 /* match_index_to_operand()
250 * Generalize test for a match between an existing index's key
251 * and the operand on the rhs of a restriction clause. Now check
252 * for functional indices as well.
255 match_index_to_operand(int indexkey,
265 if (index->indproc == InvalidOid)
267 result = match_indexkey_operand(indexkey, (Var *) operand, rel);
272 * functional index check
274 result = function_index_operand(operand, rel, index);
279 * match-index-orclause--
280 * Attempts to match an index against the subclauses of an 'or' clause.
282 * A match means that:
283 * (1) the operator within the subclause can be used with one
284 * of the index's operator classes, and
285 * (2) there is a usable key that matches the variable within a
288 * 'or-clauses' are the remaining subclauses within the 'or' clause
289 * 'other-matching-indices' is the list of information on other indices
290 * that have already been matched to subclauses within this
291 * particular 'or' clause (i.e., a list previously generated by
294 * Returns a list of the form ((a b c) (d e f) nil (g h) ...) where
295 * a,b,c are nodes of indices that match the first subclause in
296 * 'or-clauses', d,e,f match the second subclause, no indices
297 * match the third, g,h match the fourth, etc.
300 match_index_orclause(RelOptInfo *rel,
305 List *other_matching_indices)
308 List *matching_indices = other_matching_indices;
309 List *index_list = NIL;
312 /* first time through, we create index list */
313 if (!other_matching_indices)
315 foreach(clist, or_clauses)
316 matching_indices = lcons(NIL, matching_indices);
319 matching_indices = other_matching_indices;
321 index_list = matching_indices;
323 foreach(clist, or_clauses)
325 clause = lfirst(clist);
327 if (is_opclause(clause) &&
328 op_class(((Oper *) ((Expr *) clause)->oper)->opno,
329 xclass, index->relam) &&
330 ((match_index_to_operand(indexkey,
331 (Expr *) get_leftop((Expr *) clause),
334 IsA(get_rightop((Expr *) clause), Const)) ||
335 (match_index_to_operand(indexkey,
336 (Expr *) get_rightop((Expr *) clause),
339 IsA(get_leftop((Expr *) clause), Const))))
340 lfirst(matching_indices) = lcons(index, lfirst(matching_indices));
342 matching_indices = lnext(matching_indices);
348 /****************************************************************************
349 * ---- ROUTINES TO CHECK RESTRICTIONS ----
350 ****************************************************************************/
354 * DoneMatchingIndexKeys() - MACRO
356 * Determine whether we should continue matching index keys in a clause.
357 * Depends on if there are more to match or if this is a functional index.
358 * In the latter case we stop after the first match since the there can
359 * be only key (i.e. the function's return value) and the attributes in
360 * keys list represent the arguments to the function. -mer 3 Oct. 1991
362 #define DoneMatchingIndexKeys(indexkeys, index) \
363 (indexkeys[0] == 0 || \
364 (index->indproc != InvalidOid))
367 * group-clauses-by-indexkey--
368 * Determines whether there are clauses which will match each and every
369 * one of the remaining keys of an index.
371 * 'rel' is the node of the relation corresponding to the index.
372 * 'indexkeys' are the remaining index keys to be matched.
373 * 'classes' are the classes of the index operators on those keys.
374 * 'clauses' is either:
375 * (1) the list of available restriction clauses on a single
377 * (2) a list of join clauses between 'rel' and a fixed set of
379 * depending on the value of 'join'.
381 * NOTE: it works now for restriction clauses only. - vadim 03/18/97
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(RelOptInfo *rel,
394 List *restrictinfo_list)
396 List *curCinfo = NIL;
397 RestrictInfo *matched_clause = (RestrictInfo *) NULL;
398 List *clausegroup = NIL;
402 if (restrictinfo_list == NIL || indexkeys[0] == 0)
407 List *tempgroup = NIL;
409 curIndxKey = indexkeys[0];
410 curClass = classes[0];
412 foreach(curCinfo, restrictinfo_list)
414 RestrictInfo *temp = (RestrictInfo *) lfirst(curCinfo);
416 matched_clause = match_clause_to_indexkey(rel,
425 tempgroup = lappend(tempgroup, matched_clause);
427 if (tempgroup == NIL)
430 clausegroup = nconc(clausegroup, tempgroup);
435 } while (!DoneMatchingIndexKeys(indexkeys, index));
437 /* clausegroup holds all matched clauses ordered by indexkeys */
439 if (clausegroup != NIL)
440 return lcons(clausegroup, NIL);
445 * group-clauses-by-ikey-for-joins--
446 * special edition of group-clauses-by-indexkey - will
447 * match join & restriction clauses. See comment in indexable_joinclauses.
452 group_clauses_by_ikey_for_joins(RelOptInfo *rel,
456 List *join_cinfo_list,
457 List *restr_cinfo_list)
459 List *curCinfo = NIL;
460 RestrictInfo *matched_clause = (RestrictInfo *) NULL;
461 List *clausegroup = NIL;
466 if (join_cinfo_list == NIL || indexkeys[0] == 0)
471 List *tempgroup = NIL;
473 curIndxKey = indexkeys[0];
474 curClass = classes[0];
476 foreach(curCinfo, join_cinfo_list)
478 RestrictInfo *temp = (RestrictInfo *) lfirst(curCinfo);
480 matched_clause = match_clause_to_indexkey(rel,
489 tempgroup = lappend(tempgroup, matched_clause);
492 foreach(curCinfo, restr_cinfo_list)
494 RestrictInfo *temp = (RestrictInfo *) lfirst(curCinfo);
496 matched_clause = match_clause_to_indexkey(rel,
505 tempgroup = lappend(tempgroup, matched_clause);
507 if (tempgroup == NIL)
510 clausegroup = nconc(clausegroup, tempgroup);
515 } while (!DoneMatchingIndexKeys(indexkeys, index));
517 /* clausegroup holds all matched clauses ordered by indexkeys */
519 if (clausegroup != NIL)
523 * if no one join clause was matched then there ain't clauses for
528 freeList(clausegroup);
531 return lcons(clausegroup, NIL);
537 * IndexScanableClause () MACRO
539 * Generalize condition on which we match a clause with an index.
540 * Now we can match with functional indices.
542 #define IndexScanableOperand(opnd, indkeys, rel, index) \
543 ((index->indproc == InvalidOid) ? \
544 match_indexkey_operand(indkeys, opnd, rel) : \
545 function_index_operand((Expr*)opnd,rel,index))
549 * equal_indexkey_var(indkeys,opnd) : \
551 * match_indexkey_operand(indkeys, opnd, rel) : \
555 /* match_clause_to_indexkey()
556 * Finds the first of a relation's available restriction clauses that
557 * matches a key of an index.
559 * To match, the clause must:
560 * (1) be in the form (op var const) if the clause is a single-
561 * relation clause, and
562 * (2) contain an operator which is in the same class as the index
563 * operator for this key.
565 * If the clause being matched is a join clause, then 'join' is t.
567 * Returns a single restrictinfo node corresponding to the matching
570 * NOTE: returns nil if clause is an or_clause.
573 static RestrictInfo *
574 match_clause_to_indexkey(RelOptInfo *rel,
578 RestrictInfo *restrictInfo,
581 Expr *clause = restrictInfo->clause;
584 Oid join_op = InvalidOid;
585 Oid restrict_op = InvalidOid;
586 bool isIndexable = false;
588 if (or_clause((Node *) clause) ||
589 not_clause((Node *) clause) || single_node((Node *) clause))
590 return (RestrictInfo *) NULL;
592 leftop = get_leftop(clause);
593 rightop = get_rightop(clause);
596 * If this is not a join clause, check for clauses of the form:
597 * (operator var/func constant) and (operator constant var/func)
603 * Check for standard s-argable clause
605 if ((rightop && IsA(rightop, Const)) ||
606 (rightop && IsA(rightop, Param)))
608 restrict_op = ((Oper *) ((Expr *) clause)->oper)->opno;
610 isIndexable = (op_class(restrict_op, xclass, index->relam) &&
611 IndexScanableOperand(leftop,
616 #ifndef IGNORE_BINARY_COMPATIBLE_INDICES
619 * Didn't find an index? Then maybe we can find another
620 * binary-compatible index instead... thomas 1998-08-14
627 ltype = exprType((Node *) leftop);
628 rtype = exprType((Node *) rightop);
631 * make sure we have two different binary-compatible
635 && IS_BINARY_COMPATIBLE(ltype, rtype))
640 opname = get_opname(restrict_op);
642 newop = oper(opname, ltype, ltype, TRUE);
646 /* actually have a different operator to try? */
647 if (HeapTupleIsValid(newop) && (oprid(newop) != restrict_op))
649 restrict_op = oprid(newop);
651 isIndexable = (op_class(restrict_op, xclass, index->relam) &&
652 IndexScanableOperand(leftop,
658 ((Oper *) ((Expr *) clause)->oper)->opno = restrict_op;
666 * Must try to commute the clause to standard s-arg format.
668 else if ((leftop && IsA(leftop, Const)) ||
669 (leftop && IsA(leftop, Param)))
671 restrict_op = get_commutator(((Oper *) ((Expr *) clause)->oper)->opno);
673 isIndexable = ((restrict_op != InvalidOid) &&
674 op_class(restrict_op, xclass, index->relam) &&
675 IndexScanableOperand(rightop,
676 indexkey, rel, index));
678 #ifndef IGNORE_BINARY_COMPATIBLE_INDICES
684 ltype = exprType((Node *) leftop);
685 rtype = exprType((Node *) rightop);
688 && IS_BINARY_COMPATIBLE(ltype, rtype))
693 restrict_op = ((Oper *) ((Expr *) clause)->oper)->opno;
695 opname = get_opname(restrict_op);
697 newop = oper(opname, rtype, rtype, TRUE);
701 if (HeapTupleIsValid(newop) && (oprid(newop) != restrict_op))
703 restrict_op = get_commutator(oprid(newop));
705 isIndexable = ((restrict_op != InvalidOid) &&
706 op_class(restrict_op, xclass, index->relam) &&
707 IndexScanableOperand(rightop,
713 ((Oper *) ((Expr *) clause)->oper)->opno = oprid(newop);
723 * In place list modification. (op const var/func) -> (op
726 CommuteClause((Node *) clause);
732 * Check for an indexable scan on one of the join relations. clause is
733 * of the form (operator var/func var/func)
738 && match_index_to_operand(indexkey, (Expr *) rightop, rel, index))
741 join_op = get_commutator(((Oper *) ((Expr *) clause)->oper)->opno);
745 && match_index_to_operand(indexkey,
746 (Expr *) leftop, rel, index))
747 join_op = ((Oper *) ((Expr *) clause)->oper)->opno;
749 if (join_op && op_class(join_op, xclass, index->relam) &&
750 is_joinable((Node *) clause))
755 * If we're using the operand's commutator we must commute the
758 if (join_op != ((Oper *) ((Expr *) clause)->oper)->opno)
759 CommuteClause((Node *) clause);
769 /****************************************************************************
770 * ---- ROUTINES TO DO PARTIAL INDEX PREDICATE TESTS ----
771 ****************************************************************************/
775 * Does the "predicate inclusion test" for partial indexes.
777 * Recursively checks whether the clauses in restrictinfo_list imply
778 * that the given predicate is true.
780 * This routine (together with the routines it calls) iterates over
781 * ANDs in the predicate first, then reduces the qualification
782 * clauses down to their constituent terms, and iterates over ORs
783 * in the predicate last. This order is important to make the test
784 * succeed whenever possible (assuming the predicate has been
785 * successfully cnfify()-ed). --Nels, Jan '93
788 pred_test(List *predicate_list, List *restrictinfo_list, List *joininfo_list)
795 * Note: if Postgres tried to optimize queries by forming equivalence
796 * classes over equi-joined attributes (i.e., if it recognized that a
797 * qualification such as "where a.b=c.d and a.b=5" could make use of
798 * an index on c.d), then we could use that equivalence class info
799 * here with joininfo_list to do more complete tests for the usability
800 * of a partial index. For now, the test only uses restriction
801 * clauses (those in restrictinfo_list). --Nels, Dec '92
804 if (predicate_list == NULL)
805 return true; /* no predicate: the index is usable */
806 if (restrictinfo_list == NULL)
807 return false; /* no restriction clauses: the test must
810 foreach(pred, predicate_list)
814 * if any clause is not implied, the whole predicate is not
817 if (and_clause(lfirst(pred)))
819 items = ((Expr *) lfirst(pred))->args;
822 if (!one_pred_test(lfirst(item), restrictinfo_list))
826 else if (!one_pred_test(lfirst(pred), restrictinfo_list))
835 * Does the "predicate inclusion test" for one conjunct of a predicate
839 one_pred_test(Expr *predicate, List *restrictinfo_list)
841 RestrictInfo *restrictinfo;
844 Assert(predicate != NULL);
845 foreach(item, restrictinfo_list)
847 restrictinfo = (RestrictInfo *) lfirst(item);
848 /* if any clause implies the predicate, return true */
849 if (one_pred_clause_expr_test(predicate, (Node *) restrictinfo->clause))
857 * one_pred_clause_expr_test--
858 * Does the "predicate inclusion test" for a general restriction-clause
862 one_pred_clause_expr_test(Expr *predicate, Node *clause)
867 if (is_opclause(clause))
868 return one_pred_clause_test(predicate, clause);
869 else if (or_clause(clause))
871 items = ((Expr *) clause)->args;
874 /* if any OR item doesn't imply the predicate, clause doesn't */
875 if (!one_pred_clause_expr_test(predicate, lfirst(item)))
880 else if (and_clause(clause))
882 items = ((Expr *) clause)->args;
887 * if any AND item implies the predicate, the whole clause
890 if (one_pred_clause_expr_test(predicate, lfirst(item)))
897 /* unknown clause type never implies the predicate */
904 * one_pred_clause_test--
905 * Does the "predicate inclusion test" for one conjunct of a predicate
906 * expression for a simple restriction clause.
909 one_pred_clause_test(Expr *predicate, Node *clause)
914 if (is_opclause((Node *) predicate))
915 return clause_pred_clause_test(predicate, clause);
916 else if (or_clause((Node *) predicate))
918 items = predicate->args;
921 /* if any item is implied, the whole predicate is implied */
922 if (one_pred_clause_test(lfirst(item), clause))
927 else if (and_clause((Node *) predicate))
929 items = predicate->args;
934 * if any item is not implied, the whole predicate is not
937 if (!one_pred_clause_test(lfirst(item), clause))
944 elog(DEBUG, "Unsupported predicate type, index will not be used");
951 * Define an "operator implication table" for btree operators ("strategies").
952 * The "strategy numbers" are: (1) < (2) <= (3) = (4) >= (5) >
954 * The interpretation of:
956 * test_op = BT_implic_table[given_op-1][target_op-1]
958 * where test_op, given_op and target_op are strategy numbers (from 1 to 5)
959 * of btree operators, is as follows:
961 * If you know, for some ATTR, that "ATTR given_op CONST1" is true, and you
962 * want to determine whether "ATTR target_op CONST2" must also be true, then
963 * you can use "CONST1 test_op CONST2" as a test. If this test returns true,
964 * then the target expression must be true; if the test returns false, then
965 * the target expression may be false.
967 * An entry where test_op==0 means the implication cannot be determined, i.e.,
968 * this test should always be considered false.
971 StrategyNumber BT_implic_table[BTMaxStrategyNumber][BTMaxStrategyNumber] = {
981 * clause_pred_clause_test--
982 * Use operator class info to check whether clause implies predicate.
984 * Does the "predicate inclusion test" for a "simple clause" predicate
985 * for a single "simple clause" restriction. Currently, this only handles
986 * (binary boolean) operators that are in some btree operator class.
987 * Eventually, rtree operators could also be handled by defining an
988 * appropriate "RT_implic_table" array.
991 clause_pred_clause_test(Expr *predicate, Node *clause)
1001 StrategyNumber pred_strategy,
1011 ScanKeyData entry[3];
1014 pred_var = (Var *) get_leftop(predicate);
1015 pred_const = (Const *) get_rightop(predicate);
1016 clause_var = (Var *) get_leftop((Expr *) clause);
1017 clause_const = (Const *) get_rightop((Expr *) clause);
1019 /* Check the basic form; for now, only allow the simplest case */
1020 if (!is_opclause(clause) ||
1021 !IsA(clause_var, Var) ||
1022 !IsA(clause_const, Const) ||
1023 !IsA(predicate->oper, Oper) ||
1024 !IsA(pred_var, Var) ||
1025 !IsA(pred_const, Const))
1029 * The implication can't be determined unless the predicate and the
1030 * clause refer to the same attribute.
1032 if (clause_var->varattno != pred_var->varattno)
1035 /* Get the operators for the two clauses we're comparing */
1036 pred_op = ((Oper *) ((Expr *) predicate)->oper)->opno;
1037 clause_op = ((Oper *) ((Expr *) clause)->oper)->opno;
1041 * 1. Find a "btree" strategy number for the pred_op
1043 ScanKeyEntryInitialize(&entry[0], 0,
1044 Anum_pg_amop_amopid,
1046 ObjectIdGetDatum(BTREE_AM_OID));
1048 ScanKeyEntryInitialize(&entry[1], 0,
1049 Anum_pg_amop_amopopr,
1051 ObjectIdGetDatum(pred_op));
1053 relation = heap_openr(AccessMethodOperatorRelationName);
1056 * The following assumes that any given operator will only be in a
1057 * single btree operator class. This is true at least for all the
1058 * pre-defined operator classes. If it isn't true, then whichever
1059 * operator class happens to be returned first for the given operator
1060 * will be used to find the associated strategy numbers for the test.
1063 scan = heap_beginscan(relation, false, SnapshotNow, 2, entry);
1064 tuple = heap_getnext(scan, 0);
1065 if (!HeapTupleIsValid(tuple))
1067 elog(DEBUG, "clause_pred_clause_test: unknown pred_op");
1070 form = (Form_pg_amop) GETSTRUCT(tuple);
1072 /* Get the predicate operator's strategy number (1 to 5) */
1073 pred_strategy = (StrategyNumber) form->amopstrategy;
1075 /* Remember which operator class this strategy number came from */
1076 opclass_id = form->amopclaid;
1082 * 2. From the same opclass, find a strategy num for the clause_op
1084 ScanKeyEntryInitialize(&entry[1], 0,
1085 Anum_pg_amop_amopclaid,
1087 ObjectIdGetDatum(opclass_id));
1089 ScanKeyEntryInitialize(&entry[2], 0,
1090 Anum_pg_amop_amopopr,
1092 ObjectIdGetDatum(clause_op));
1094 scan = heap_beginscan(relation, false, SnapshotNow, 3, entry);
1095 tuple = heap_getnext(scan, 0);
1096 if (!HeapTupleIsValid(tuple))
1098 elog(DEBUG, "clause_pred_clause_test: unknown clause_op");
1101 form = (Form_pg_amop) GETSTRUCT(tuple);
1103 /* Get the restriction clause operator's strategy number (1 to 5) */
1104 clause_strategy = (StrategyNumber) form->amopstrategy;
1109 * 3. Look up the "test" strategy number in the implication table
1112 test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
1113 if (test_strategy == 0)
1114 return false; /* the implication cannot be determined */
1118 * 4. From the same opclass, find the operator for the test strategy
1121 ScanKeyEntryInitialize(&entry[2], 0,
1122 Anum_pg_amop_amopstrategy,
1124 Int16GetDatum(test_strategy));
1126 scan = heap_beginscan(relation, false, SnapshotNow, 3, entry);
1127 tuple = heap_getnext(scan, 0);
1128 if (!HeapTupleIsValid(tuple))
1130 elog(DEBUG, "clause_pred_clause_test: unknown test_op");
1133 form = (Form_pg_amop) GETSTRUCT(tuple);
1135 /* Get the test operator */
1136 test_op = form->amopopr;
1141 * 5. Evaluate the test
1143 test_oper = makeOper(test_op, /* opno */
1144 InvalidOid, /* opid */
1145 BOOLOID, /* opresulttype */
1147 NULL); /* op_fcache */
1148 replace_opid(test_oper);
1150 test_expr = make_opclause(test_oper,
1151 copyObject(clause_const),
1152 copyObject(pred_const));
1154 #ifndef OMIT_PARTIAL_INDEX
1155 test_result = ExecEvalExpr((Node *) test_expr, NULL, &isNull, NULL);
1156 #endif /* OMIT_PARTIAL_INDEX */
1159 elog(DEBUG, "clause_pred_clause_test: null test result");
1166 /****************************************************************************
1167 * ---- ROUTINES TO CHECK JOIN CLAUSES ----
1168 ****************************************************************************/
1171 * indexable-joinclauses--
1172 * Finds all groups of join clauses from among 'joininfo-list' that can
1173 * be used in conjunction with 'index'.
1175 * The first clause in the group is marked as having the other relation
1176 * in the join clause as its outer join relation.
1178 * Returns a list of these clause groups.
1180 * Added: restrictinfo_list - list of restriction RestrictInfos. It's to
1181 * support multi-column indices in joins and for cases
1182 * when a key is in both join & restriction clauses. - vadim 03/18/97
1186 indexable_joinclauses(RelOptInfo *rel, RelOptInfo *index,
1187 List *joininfo_list, List *restrictinfo_list)
1189 JoinInfo *joininfo = (JoinInfo *) NULL;
1190 List *cg_list = NIL;
1192 List *clausegroups = NIL;
1194 foreach(i, joininfo_list)
1196 joininfo = (JoinInfo *) lfirst(i);
1198 if (joininfo->jinfo_restrictinfo == NIL)
1200 clausegroups = group_clauses_by_ikey_for_joins(rel,
1204 joininfo->jinfo_restrictinfo,
1207 if (clausegroups != NIL)
1209 List *clauses = lfirst(clausegroups);
1211 ((RestrictInfo *) lfirst(clauses))->restrictinfojoinid = joininfo->otherrels;
1213 cg_list = nconc(cg_list, clausegroups);
1218 /****************************************************************************
1219 * ---- PATH CREATION UTILITIES ----
1220 ****************************************************************************/
1223 * extract_restrict_clauses -
1224 * the list of clause info contains join clauses and restriction clauses.
1225 * This routine returns the restriction clauses only.
1229 extract_restrict_clauses(List *clausegroup)
1231 List *restrict_cls = NIL;
1234 foreach(l, clausegroup)
1236 RestrictInfo *cinfo = lfirst(l);
1238 if (!is_joinable((Node *) cinfo->clause))
1239 restrict_cls = lappend(restrict_cls, cinfo);
1241 return restrict_cls;
1248 * Creates index path nodes corresponding to paths to be used as inner
1249 * relations in nestloop joins.
1251 * 'clausegroup-list' is a list of list of restrictinfo nodes which can use
1252 * 'index' on their inner relation.
1254 * Returns a list of index pathnodes.
1258 index_innerjoin(Query *root, RelOptInfo *rel, List *clausegroup_list,
1261 List *clausegroup = NIL;
1262 List *cg_list = NIL;
1264 IndexPath *pathnode = (IndexPath *) NULL;
1268 foreach(i, clausegroup_list)
1274 clausegroup = lfirst(i);
1275 pathnode = makeNode(IndexPath);
1277 get_joinvars(lfirsti(rel->relids), clausegroup,
1278 &attnos, &values, &flags);
1279 index_selectivity(lfirsti(index->relids),
1281 get_opnos(clausegroup),
1282 getrelid(lfirsti(rel->relids),
1287 length(clausegroup),
1291 pathnode->path.pathtype = T_IndexScan;
1292 pathnode->path.parent = rel;
1293 pathnode->path.path_order = makeNode(PathOrder);
1294 pathnode->path.path_order->ordtype = SORTOP_ORDER;
1295 pathnode->path.path_order->ord.sortop = index->ordering;
1296 pathnode->path.pathkeys = NIL;
1298 pathnode->indexid = index->relids;
1299 pathnode->indexkeys = index->indexkeys;
1300 pathnode->indexqual = clausegroup;
1302 pathnode->path.joinid = ((RestrictInfo *) lfirst(clausegroup))->restrictinfojoinid;
1304 pathnode->path.path_cost = cost_index((Oid) lfirsti(index->relids),
1314 * copy restrictinfo list into path for expensive function
1315 * processing -- JMH, 7/7/92
1317 pathnode->path.loc_restrictinfo = set_difference(copyObject((Node *) rel->restrictinfo),
1320 #if 0 /* fix xfunc */
1321 /* add in cost for expensive functions! -- JMH, 7/7/92 */
1322 if (XfuncMode != XFUNC_OFF)
1324 ((Path *) pathnode)->path_cost += xfunc_get_path_cost((Path *) pathnode);
1327 cg_list = lappend(cg_list, pathnode);
1333 * create-index-paths--
1334 * Creates a list of index path nodes for each group of clauses
1335 * (restriction or join) that can be used in conjunction with an index.
1337 * 'rel' is the relation for which 'index' is defined
1338 * 'clausegroup-list' is the list of clause groups (lists of restrictinfo
1339 * nodes) grouped by mergejoinorder
1340 * 'join' is a flag indicating whether or not the clauses are join
1343 * Returns a list of new index path nodes.
1347 create_index_paths(Query *root,
1350 List *clausegroup_list,
1353 List *clausegroup = NIL;
1354 List *ip_list = NIL;
1357 IndexPath *temp_path;
1359 foreach(i, clausegroup_list)
1361 RestrictInfo *restrictinfo;
1362 List *temp_node = NIL;
1365 clausegroup = lfirst(i);
1367 foreach(j, clausegroup)
1369 restrictinfo = (RestrictInfo *) lfirst(j);
1370 if (!(is_joinable((Node *) restrictinfo->clause) &&
1371 equal_path_merge_ordering(index->ordering,
1372 restrictinfo->mergejoinorder)))
1377 { /* restriction, ordering scan */
1378 temp_path = create_index_path(root, rel, index, clausegroup, join);
1379 temp_node = lcons(temp_path, NIL);
1380 ip_list = nconc(ip_list, temp_node);
1387 add_index_paths(List *indexpaths, List *new_indexpaths)
1389 return append(indexpaths, new_indexpaths);
1393 function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index)
1395 Oid heapRelid = (Oid) lfirsti(rel->relids);
1398 int *indexKeys = index->indexkeys;
1403 * sanity check, make sure we know what we're dealing with here.
1405 if (funcOpnd == NULL ||
1406 nodeTag(funcOpnd) != T_Expr || funcOpnd->opType != FUNC_EXPR ||
1407 funcOpnd->oper == NULL || indexKeys == NULL)
1410 function = (Func *) funcOpnd->oper;
1411 funcargs = funcOpnd->args;
1413 if (function->funcid != index->indproc)
1417 * Check that the arguments correspond to the same arguments used to
1418 * create the functional index. To do this we must check that 1.
1419 * refer to the right relatiion. 2. the args have the right attr.
1420 * numbers in the right order.
1423 * Check all args refer to the correct relation (i.e. the one with the
1424 * functional index defined on it (rel). To do this we can simply
1425 * compare range table entry numbers, they must be the same.
1427 foreach(arg, funcargs)
1429 if (heapRelid != ((Var *) lfirst(arg))->varno)
1434 * check attr numbers and order.
1437 foreach(arg, funcargs)
1440 if (indexKeys[i] == 0)
1443 if (((Var *) lfirst(arg))->varattno != indexKeys[i])