|
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 | ****************************************************************************/
|
|