|
9 | 9 | * |
10 | 10 | * |
11 | 11 | * IDENTIFICATION |
12 | | - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.99 2000/11/25 20:33:51 tgl Exp $ |
| 12 | + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.100 2000/12/14 22:30:43 tgl Exp $ |
13 | 13 | * |
14 | 14 | *------------------------------------------------------------------------- |
15 | 15 | */ |
@@ -87,11 +87,6 @@ static void indexable_joinclauses(RelOptInfo *rel, IndexOptInfo *index, |
87 | 87 | List**clausegroups,List**outerrelids); |
88 | 88 | staticList*index_innerjoin(Query*root,RelOptInfo*rel,IndexOptInfo*index, |
89 | 89 | List*clausegroup_list,List*outerrelids_list); |
90 | | -staticbooluseful_for_mergejoin(RelOptInfo*rel,IndexOptInfo*index, |
91 | | -List*joininfo_list); |
92 | | -staticbooluseful_for_ordering(Query*root,RelOptInfo*rel, |
93 | | -IndexOptInfo*index, |
94 | | -ScanDirectionscandir); |
95 | 90 | staticboolmatch_index_to_operand(intindexkey,Var*operand, |
96 | 91 | RelOptInfo*rel,IndexOptInfo*index); |
97 | 92 | staticboolfunction_index_operand(Expr*funcOpnd,RelOptInfo*rel, |
@@ -125,31 +120,31 @@ static Const *string_to_const(const char *str, Oid datatype); |
125 | 120 | * attributes are available and fixed during any one scan of the indexpath. |
126 | 121 | * |
127 | 122 | * An IndexPath is generated and submitted to add_path() for each index |
128 | | - * this routine deems potentially interesting for the current query |
129 | | - * (at most one IndexPath per index on the given relation). An innerjoin |
130 | | - * path is also generated for each interesting combination of outer join |
131 | | - * relations. The innerjoin paths are *not* passed to add_path(), but are |
132 | | - * appended to the "innerjoin" list of the relation for later consideration |
133 | | - * in nested-loop joins. |
| 123 | + * this routine deems potentially interesting for the current query. |
| 124 | + * An innerjoin path is also generated for each interesting combination of |
| 125 | + * outer join relations. The innerjoin paths are *not* passed to add_path(), |
| 126 | + * but are appended to the "innerjoin" list of the relation for later |
| 127 | + * consideration in nested-loop joins. |
134 | 128 | * |
135 | 129 | * 'rel' is the relation for which we want to generate index paths |
136 | 130 | * 'indices' is a list of available indexes for 'rel' |
137 | | - * 'restrictinfo_list' is a list of restrictinfo nodes for 'rel' |
138 | | - * 'joininfo_list' is a list of joininfo nodes for 'rel' |
139 | 131 | */ |
140 | 132 | void |
141 | 133 | create_index_paths(Query*root, |
142 | 134 | RelOptInfo*rel, |
143 | | -List*indices, |
144 | | -List*restrictinfo_list, |
145 | | -List*joininfo_list) |
| 135 | +List*indices) |
146 | 136 | { |
| 137 | +List*restrictinfo_list=rel->baserestrictinfo; |
| 138 | +List*joininfo_list=rel->joininfo; |
147 | 139 | List*ilist; |
148 | 140 |
|
149 | 141 | foreach(ilist,indices) |
150 | 142 | { |
151 | 143 | IndexOptInfo*index= (IndexOptInfo*)lfirst(ilist); |
152 | 144 | List*restrictclauses; |
| 145 | +List*index_pathkeys; |
| 146 | +List*useful_pathkeys; |
| 147 | +boolindex_is_ordered; |
153 | 148 | List*joinclausegroups; |
154 | 149 | List*joinouterrelids; |
155 | 150 |
|
@@ -179,53 +174,58 @@ create_index_paths(Query *root, |
179 | 174 | match_index_orclauses(rel,index,restrictinfo_list); |
180 | 175 |
|
181 | 176 | /* |
182 | | - * 2. If the keys of this index match any of the available |
183 | | - * non-'or' restriction clauses, then create a path using those |
184 | | - * clauses as indexquals. |
| 177 | + * 2. Match the index against non-'or' restriction clauses. |
185 | 178 | */ |
186 | 179 | restrictclauses=group_clauses_by_indexkey(rel, |
187 | 180 | index, |
188 | 181 | index->indexkeys, |
189 | 182 | index->classlist, |
190 | 183 | restrictinfo_list); |
191 | 184 |
|
192 | | -if (restrictclauses!=NIL) |
193 | | -add_path(rel, (Path*)create_index_path(root,rel,index, |
194 | | -restrictclauses, |
195 | | -NoMovementScanDirection)); |
196 | | - |
197 | 185 | /* |
198 | | - * 3. If this index can be used for a mergejoin, then create an |
199 | | - * index path for it even if there were no restriction clauses. |
200 | | - * (If there were, there is no need to make another index path.) |
201 | | - * This will allow the index to be considered as a base for a |
202 | | - * mergejoin in later processing. Similarly, if the index matches |
203 | | - * the ordering that is needed for the overall query result, make |
204 | | - * an index path for it even if there is no other reason to do so. |
| 186 | + * 3. Compute pathkeys describing index's ordering, if any, |
| 187 | + * then see how many of them are actually useful for this query. |
205 | 188 | */ |
206 | | -if (restrictclauses==NIL) |
207 | | -{ |
208 | | -if (useful_for_mergejoin(rel,index,joininfo_list)|| |
209 | | -useful_for_ordering(root,rel,index,ForwardScanDirection)) |
210 | | -add_path(rel, (Path*) |
211 | | -create_index_path(root,rel,index, |
212 | | -restrictclauses, |
213 | | -ForwardScanDirection)); |
214 | | -} |
| 189 | +index_pathkeys=build_index_pathkeys(root,rel,index, |
| 190 | +ForwardScanDirection); |
| 191 | +index_is_ordered= (index_pathkeys!=NIL); |
| 192 | +useful_pathkeys=truncate_useless_pathkeys(root,rel, |
| 193 | +index_pathkeys); |
215 | 194 |
|
216 | 195 | /* |
217 | | - *Currently, backwards scan is never considered except for the |
218 | | - *case of matching a query result ordering. Possibly should |
219 | | - *consider it in other places? |
| 196 | + *4. Generate an indexscan path if there are relevant restriction |
| 197 | + *clauses OR the index ordering is potentially useful for later |
| 198 | + *merging or final output ordering. |
220 | 199 | */ |
221 | | -if (useful_for_ordering(root,rel,index,BackwardScanDirection)) |
| 200 | +if (restrictclauses!=NIL||useful_pathkeys!=NIL) |
222 | 201 | add_path(rel, (Path*) |
223 | 202 | create_index_path(root,rel,index, |
224 | 203 | restrictclauses, |
225 | | -BackwardScanDirection)); |
| 204 | +useful_pathkeys, |
| 205 | +index_is_ordered ? |
| 206 | +ForwardScanDirection : |
| 207 | +NoMovementScanDirection)); |
| 208 | + |
| 209 | +/* |
| 210 | + * 5. If the index is ordered, a backwards scan might be interesting. |
| 211 | + * Currently this is only possible for a DESC query result ordering. |
| 212 | + */ |
| 213 | +if (index_is_ordered) |
| 214 | +{ |
| 215 | +index_pathkeys=build_index_pathkeys(root,rel,index, |
| 216 | +BackwardScanDirection); |
| 217 | +useful_pathkeys=truncate_useless_pathkeys(root,rel, |
| 218 | +index_pathkeys); |
| 219 | +if (useful_pathkeys!=NIL) |
| 220 | +add_path(rel, (Path*) |
| 221 | +create_index_path(root,rel,index, |
| 222 | +restrictclauses, |
| 223 | +useful_pathkeys, |
| 224 | +BackwardScanDirection)); |
| 225 | +} |
226 | 226 |
|
227 | 227 | /* |
228 | | - *4. Create an innerjoin index path for each combination of other |
| 228 | + *6. Create an innerjoin index path for each combination of other |
229 | 229 | * rels used in available join clauses. These paths will be |
230 | 230 | * considered as the inner side of nestloop joins against those |
231 | 231 | * sets of other rels.indexable_joinclauses() finds sets of |
@@ -904,88 +904,6 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam, |
904 | 904 | returnInvalidOid; |
905 | 905 | } |
906 | 906 |
|
907 | | -/* |
908 | | - * useful_for_mergejoin |
909 | | - * Determine whether the given index can support a mergejoin based |
910 | | - * on any available join clause. |
911 | | - * |
912 | | - * We look to see whether the first indexkey of the index matches the |
913 | | - * left or right sides of any of the mergejoinable clauses and provides |
914 | | - * the ordering needed for that side. If so, the index is useful. |
915 | | - * Matching a second or later indexkey is not useful unless there is |
916 | | - * also a mergeclause for the first indexkey, so we need not consider |
917 | | - * secondary indexkeys at this stage. |
918 | | - * |
919 | | - * 'rel' is the relation for which 'index' is defined |
920 | | - * 'joininfo_list' is the list of JoinInfo nodes for 'rel' |
921 | | - */ |
922 | | -staticbool |
923 | | -useful_for_mergejoin(RelOptInfo*rel, |
924 | | -IndexOptInfo*index, |
925 | | -List*joininfo_list) |
926 | | -{ |
927 | | -int*indexkeys=index->indexkeys; |
928 | | -Oid*ordering=index->ordering; |
929 | | -List*i; |
930 | | - |
931 | | -if (!indexkeys||indexkeys[0]==0|| |
932 | | -!ordering||ordering[0]==InvalidOid) |
933 | | -return false;/* unordered index is not useful */ |
934 | | - |
935 | | -foreach(i,joininfo_list) |
936 | | -{ |
937 | | -JoinInfo*joininfo= (JoinInfo*)lfirst(i); |
938 | | -List*j; |
939 | | - |
940 | | -foreach(j,joininfo->jinfo_restrictinfo) |
941 | | -{ |
942 | | -RestrictInfo*restrictinfo= (RestrictInfo*)lfirst(j); |
943 | | - |
944 | | -if (restrictinfo->mergejoinoperator) |
945 | | -{ |
946 | | -if (restrictinfo->left_sortop==ordering[0]&& |
947 | | -match_index_to_operand(indexkeys[0], |
948 | | -get_leftop(restrictinfo->clause), |
949 | | -rel,index)) |
950 | | -return true; |
951 | | -if (restrictinfo->right_sortop==ordering[0]&& |
952 | | -match_index_to_operand(indexkeys[0], |
953 | | -get_rightop(restrictinfo->clause), |
954 | | -rel,index)) |
955 | | -return true; |
956 | | -} |
957 | | -} |
958 | | -} |
959 | | -return false; |
960 | | -} |
961 | | - |
962 | | -/* |
963 | | - * useful_for_ordering |
964 | | - * Determine whether the given index can produce an ordering matching |
965 | | - * the order that is wanted for the query result. |
966 | | - * |
967 | | - * 'rel' is the relation for which 'index' is defined |
968 | | - * 'scandir' is the contemplated scan direction |
969 | | - */ |
970 | | -staticbool |
971 | | -useful_for_ordering(Query*root, |
972 | | -RelOptInfo*rel, |
973 | | -IndexOptInfo*index, |
974 | | -ScanDirectionscandir) |
975 | | -{ |
976 | | -List*index_pathkeys; |
977 | | - |
978 | | -if (root->query_pathkeys==NIL) |
979 | | -return false;/* no special ordering requested */ |
980 | | - |
981 | | -index_pathkeys=build_index_pathkeys(root,rel,index,scandir); |
982 | | - |
983 | | -if (index_pathkeys==NIL) |
984 | | -return false;/* unordered index */ |
985 | | - |
986 | | -returnpathkeys_contained_in(root->query_pathkeys,index_pathkeys); |
987 | | -} |
988 | | - |
989 | 907 | /**************************************************************************** |
990 | 908 | *---- ROUTINES TO DO PARTIAL INDEX PREDICATE TESTS---- |
991 | 909 | ****************************************************************************/ |
|