1 | /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. |
2 | Copyright (c) 2008, 2015, MariaDB |
3 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by |
6 | the Free Software Foundation; version 2 of the License. |
7 | |
8 | This program is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | GNU General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU General Public License |
14 | along with this program; if not, write to the Free Software |
15 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
16 | |
17 | /* |
18 | TODO: |
19 | Fix that MAYBE_KEY are stored in the tree so that we can detect use |
20 | of full hash keys for queries like: |
21 | |
22 | select s.id, kws.keyword_id from sites as s,kws where s.id=kws.site_id and kws.keyword_id in (204,205); |
23 | |
24 | */ |
25 | |
26 | /* |
27 | This file contains: |
28 | |
29 | RangeAnalysisModule |
30 | A module that accepts a condition, index (or partitioning) description, |
31 | and builds lists of intervals (in index/partitioning space), such that |
32 | all possible records that match the condition are contained within the |
33 | intervals. |
34 | The entry point for the range analysis module is get_mm_tree() function. |
35 | |
36 | The lists are returned in form of complicated structure of interlinked |
37 | SEL_TREE/SEL_IMERGE/SEL_ARG objects. |
38 | See quick_range_seq_next, find_used_partitions for examples of how to walk |
39 | this structure. |
40 | All direct "users" of this module are located within this file, too. |
41 | |
42 | |
43 | PartitionPruningModule |
44 | A module that accepts a partitioned table, condition, and finds which |
45 | partitions we will need to use in query execution. Search down for |
46 | "PartitionPruningModule" for description. |
47 | The module has single entry point - prune_partitions() function. |
48 | |
49 | |
50 | Range/index_merge/groupby-minmax optimizer module |
51 | A module that accepts a table, condition, and returns |
52 | - a QUICK_*_SELECT object that can be used to retrieve rows that match |
53 | the specified condition, or a "no records will match the condition" |
54 | statement. |
55 | |
56 | The module entry points are |
57 | test_quick_select() |
58 | get_quick_select_for_ref() |
59 | |
60 | |
61 | Record retrieval code for range/index_merge/groupby-min-max. |
62 | Implementations of QUICK_*_SELECT classes. |
63 | |
64 | KeyTupleFormat |
65 | ~~~~~~~~~~~~~~ |
66 | The code in this file (and elsewhere) makes operations on key value tuples. |
67 | Those tuples are stored in the following format: |
68 | |
69 | The tuple is a sequence of key part values. The length of key part value |
70 | depends only on its type (and not depends on the what value is stored) |
71 | |
72 | KeyTuple: keypart1-data, keypart2-data, ... |
73 | |
74 | The value of each keypart is stored in the following format: |
75 | |
76 | keypart_data: [isnull_byte] keypart-value-bytes |
77 | |
78 | If a keypart may have a NULL value (key_part->field->real_maybe_null() can |
79 | be used to check this), then the first byte is a NULL indicator with the |
80 | following valid values: |
81 | 1 - keypart has NULL value. |
82 | 0 - keypart has non-NULL value. |
83 | |
84 | <questionable-statement> If isnull_byte==1 (NULL value), then the following |
85 | keypart->length bytes must be 0. |
86 | </questionable-statement> |
87 | |
88 | keypart-value-bytes holds the value. Its format depends on the field type. |
89 | The length of keypart-value-bytes may or may not depend on the value being |
90 | stored. The default is that length is static and equal to |
91 | KEY_PART_INFO::length. |
92 | |
93 | Key parts with (key_part_flag & HA_BLOB_PART) have length depending of the |
94 | value: |
95 | |
96 | keypart-value-bytes: value_length value_bytes |
97 | |
98 | The value_length part itself occupies HA_KEY_BLOB_LENGTH=2 bytes. |
99 | |
100 | See key_copy() and key_restore() for code to move data between index tuple |
101 | and table record |
102 | |
103 | CAUTION: the above description is only sergefp's understanding of the |
104 | subject and may omit some details. |
105 | */ |
106 | |
107 | #ifdef USE_PRAGMA_IMPLEMENTATION |
108 | #pragma implementation // gcc: Class implementation |
109 | #endif |
110 | |
111 | #include "mariadb.h" |
112 | #include "sql_priv.h" |
113 | #include "key.h" // is_key_used, key_copy, key_cmp, key_restore |
114 | #include "sql_parse.h" // check_stack_overrun |
115 | #include "sql_partition.h" // get_part_id_func, PARTITION_ITERATOR, |
116 | // struct partition_info, NOT_A_PARTITION_ID |
117 | #include "records.h" // init_read_record, end_read_record |
118 | #include <m_ctype.h> |
119 | #include "sql_select.h" |
120 | #include "sql_statistics.h" |
121 | #include "uniques.h" |
122 | |
123 | #ifndef EXTRA_DEBUG |
124 | #define test_rb_tree(A,B) {} |
125 | #define test_use_count(A) {} |
126 | #endif |
127 | |
128 | /* |
129 | Convert double value to #rows. Currently this does floor(), and we |
130 | might consider using round() instead. |
131 | */ |
132 | #define double2rows(x) ((ha_rows)(x)) |
133 | |
134 | /* |
135 | this should be long enough so that any memcmp with a string that |
136 | starts from '\0' won't cross is_null_string boundaries, even |
137 | if the memcmp is optimized to compare 4- 8- or 16- bytes at once |
138 | */ |
139 | static uchar is_null_string[20]= {1,0}; |
140 | |
141 | /** |
142 | Helper function to compare two SEL_ARG's. |
143 | */ |
144 | static bool all_same(const SEL_ARG *sa1, const SEL_ARG *sa2) |
145 | { |
146 | if (sa1 == NULL && sa2 == NULL) |
147 | return true; |
148 | if ((sa1 != NULL && sa2 == NULL) || (sa1 == NULL && sa2 != NULL)) |
149 | return false; |
150 | return sa1->all_same(sa2); |
151 | } |
152 | |
153 | class SEL_IMERGE; |
154 | |
155 | #define CLONE_KEY1_MAYBE 1 |
156 | #define CLONE_KEY2_MAYBE 2 |
157 | #define swap_clone_flag(A) ((A & 1) << 1) | ((A & 2) >> 1) |
158 | |
159 | |
160 | /* |
161 | While objects of the class SEL_ARG represent ranges for indexes or |
162 | index infixes (including ranges for index prefixes and index suffixes), |
163 | objects of the class SEL_TREE represent AND/OR formulas of such ranges. |
164 | Currently an AND/OR formula represented by a SEL_TREE object can have |
165 | at most three levels: |
166 | |
167 | <SEL_TREE formula> ::= |
168 | [ <SEL_RANGE_TREE formula> AND ] |
169 | [ <SEL_IMERGE formula> [ AND <SEL_IMERGE formula> ...] ] |
170 | |
171 | <SEL_RANGE_TREE formula> ::= |
172 | <SEL_ARG formula> [ AND <SEL_ARG_formula> ... ] |
173 | |
174 | <SEL_IMERGE formula> ::= |
175 | <SEL_RANGE_TREE formula> [ OR <SEL_RANGE_TREE formula> ] |
176 | |
177 | As we can see from the above definitions: |
178 | - SEL_RANGE_TREE formula is a conjunction of SEL_ARG formulas |
179 | - SEL_IMERGE formula is a disjunction of SEL_RANGE_TREE formulas |
180 | - SEL_TREE formula is a conjunction of a SEL_RANGE_TREE formula |
181 | and SEL_IMERGE formulas. |
182 | It's required above that a SEL_TREE formula has at least one conjunct. |
183 | |
184 | Usually we will consider normalized SEL_RANGE_TREE formulas where we use |
185 | TRUE as conjunct members for those indexes whose SEL_ARG trees are empty. |
186 | |
187 | We will call an SEL_TREE object simply 'tree'. |
188 | The part of a tree that represents SEL_RANGE_TREE formula is called |
189 | 'range part' of the tree while the remaining part is called 'imerge part'. |
190 | If a tree contains only a range part then we call such a tree 'range tree'. |
191 | Components of a range tree that represent SEL_ARG formulas are called ranges. |
192 | If a tree does not contain any range part we call such a tree 'imerge tree'. |
193 | Components of the imerge part of a tree that represent SEL_IMERGE formula |
194 | are called imerges. |
195 | |
196 | Usually we'll designate: |
197 | SEL_TREE formulas by T_1,...,T_k |
198 | SEL_ARG formulas by R_1,...,R_k |
199 | SEL_RANGE_TREE formulas by RT_1,...,RT_k |
200 | SEL_IMERGE formulas by M_1,...,M_k |
201 | Accordingly we'll use: |
202 | t_1,...,t_k - to designate trees representing T_1,...,T_k |
203 | r_1,...,r_k - to designate ranges representing R_1,...,R_k |
204 | rt_1,...,r_tk - to designate range trees representing RT_1,...,RT_k |
205 | m_1,...,m_k - to designate imerges representing M_1,...,M_k |
206 | |
207 | SEL_TREE objects are usually built from WHERE conditions or |
208 | ON expressions. |
209 | A SEL_TREE object always represents an inference of the condition it is |
210 | built from. Therefore, if a row satisfies a SEL_TREE formula it also |
211 | satisfies the condition it is built from. |
212 | |
213 | The following transformations of tree t representing SEL_TREE formula T |
214 | yield a new tree t1 thar represents an inference of T: T=>T1. |
215 | (1) remove any of SEL_ARG tree from the range part of t |
216 | (2) remove any imerge from the tree t |
217 | (3) remove any of SEL_ARG tree from any range tree contained |
218 | in any imerge of tree |
219 | |
220 | Since the basic blocks of any SEL_TREE objects are ranges, SEL_TREE |
221 | objects in many cases can be effectively used to filter out a big part |
222 | of table rows that do not satisfy WHERE/IN conditions utilizing |
223 | only single or multiple range index scans. |
224 | |
225 | A single range index scan is constructed for a range tree that contains |
226 | only one SEL_ARG object for an index or an index prefix. |
227 | An index intersection scan can be constructed for a range tree |
228 | that contains several SEL_ARG objects. Currently index intersection |
229 | scans are constructed only for single-point ranges. |
230 | An index merge scan is constructed for a imerge tree that contains only |
231 | one imerge. If range trees of this imerge contain only single-point merges |
232 | than a union of index intersections can be built. |
233 | |
234 | Usually the tree built by the range optimizer for a query table contains |
235 | more than one range in the range part, and additionally may contain some |
236 | imerges in the imerge part. The range optimizer evaluates all of them one |
237 | by one and chooses the range or the imerge that provides the cheapest |
238 | single or multiple range index scan of the table. According to rules |
239 | (1)-(3) this scan always filter out only those rows that do not satisfy |
240 | the query conditions. |
241 | |
242 | For any condition the SEL_TREE object for it is built in a bottom up |
243 | manner starting from the range trees for the predicates. The tree_and |
244 | function builds a tree for any conjunction of formulas from the trees |
245 | for its conjuncts. The tree_or function builds a tree for any disjunction |
246 | of formulas from the trees for its disjuncts. |
247 | */ |
248 | |
249 | class SEL_TREE :public Sql_alloc |
250 | { |
251 | public: |
252 | /* |
253 | Starting an effort to document this field: |
254 | (for some i, keys[i]->type == SEL_ARG::IMPOSSIBLE) => |
255 | (type == SEL_TREE::IMPOSSIBLE) |
256 | */ |
257 | enum Type { IMPOSSIBLE, ALWAYS, MAYBE, KEY, KEY_SMALLER } type; |
258 | |
259 | SEL_TREE(enum Type type_arg, MEM_ROOT *root, size_t num_keys) |
260 | : type(type_arg), keys(root, num_keys), n_ror_scans(0) |
261 | { |
262 | keys_map.clear_all(); |
263 | } |
264 | |
265 | SEL_TREE(MEM_ROOT *root, size_t num_keys) : |
266 | type(KEY), keys(root, num_keys), n_ror_scans(0) |
267 | { |
268 | keys_map.clear_all(); |
269 | } |
270 | |
271 | SEL_TREE(SEL_TREE *arg, bool without_merges, RANGE_OPT_PARAM *param); |
272 | /* |
273 | Note: there may exist SEL_TREE objects with sel_tree->type=KEY and |
274 | keys[i]=0 for all i. (SergeyP: it is not clear whether there is any |
275 | merit in range analyzer functions (e.g. get_mm_parts) returning a |
276 | pointer to such SEL_TREE instead of NULL) |
277 | */ |
278 | Mem_root_array<SEL_ARG *, true> keys; |
279 | |
280 | key_map keys_map; /* bitmask of non-NULL elements in keys */ |
281 | |
282 | /* |
283 | Possible ways to read rows using index_merge. The list is non-empty only |
284 | if type==KEY. Currently can be non empty only if keys_map.is_clear_all(). |
285 | */ |
286 | List<SEL_IMERGE> merges; |
287 | |
288 | /* The members below are filled/used only after get_mm_tree is done */ |
289 | key_map ror_scans_map; /* bitmask of ROR scan-able elements in keys */ |
290 | uint n_ror_scans; /* number of set bits in ror_scans_map */ |
291 | |
292 | struct st_index_scan_info **index_scans; /* list of index scans */ |
293 | struct st_index_scan_info **index_scans_end; /* last index scan */ |
294 | |
295 | struct st_ror_scan_info **ror_scans; /* list of ROR key scans */ |
296 | struct st_ror_scan_info **ror_scans_end; /* last ROR scan */ |
297 | /* Note that #records for each key scan is stored in table->quick_rows */ |
298 | |
299 | bool without_ranges() { return keys_map.is_clear_all(); } |
300 | bool without_imerges() { return merges.is_empty(); } |
301 | }; |
302 | |
303 | |
304 | class PARAM : public RANGE_OPT_PARAM |
305 | { |
306 | public: |
307 | ha_rows quick_rows[MAX_KEY]; |
308 | |
309 | /* |
310 | This will collect 'possible keys' based on the range optimization. |
311 | |
312 | Queries with a JOIN object actually use ref optimizer (see add_key_field) |
313 | to collect possible_keys. This is used by single table UPDATE/DELETE. |
314 | */ |
315 | key_map possible_keys; |
316 | longlong baseflag; |
317 | uint max_key_part, range_count; |
318 | |
319 | bool quick; // Don't calulate possible keys |
320 | |
321 | uint fields_bitmap_size; |
322 | MY_BITMAP needed_fields; /* bitmask of fields needed by the query */ |
323 | MY_BITMAP tmp_covered_fields; |
324 | |
325 | key_map *needed_reg; /* ptr to SQL_SELECT::needed_reg */ |
326 | |
327 | uint *imerge_cost_buff; /* buffer for index_merge cost estimates */ |
328 | uint imerge_cost_buff_size; /* size of the buffer */ |
329 | |
330 | /* TRUE if last checked tree->key can be used for ROR-scan */ |
331 | bool is_ror_scan; |
332 | /* Number of ranges in the last checked tree->key */ |
333 | uint n_ranges; |
334 | uint8 first_null_comp; /* first null component if any, 0 - otherwise */ |
335 | }; |
336 | |
337 | |
338 | class TABLE_READ_PLAN; |
339 | class TRP_RANGE; |
340 | class TRP_ROR_INTERSECT; |
341 | class TRP_ROR_UNION; |
342 | class TRP_INDEX_INTERSECT; |
343 | class TRP_INDEX_MERGE; |
344 | class TRP_GROUP_MIN_MAX; |
345 | |
346 | struct st_index_scan_info; |
347 | struct st_ror_scan_info; |
348 | |
349 | static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts); |
350 | static ha_rows check_quick_select(PARAM *param, uint idx, bool index_only, |
351 | SEL_ARG *tree, bool update_tbl_stats, |
352 | uint *mrr_flags, uint *bufsize, |
353 | Cost_estimate *cost); |
354 | |
355 | QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index, |
356 | SEL_ARG *key_tree, uint mrr_flags, |
357 | uint mrr_buf_size, MEM_ROOT *alloc); |
358 | static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, |
359 | bool index_read_must_be_used, |
360 | bool update_tbl_stats, |
361 | double read_time); |
362 | static |
363 | TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree, |
364 | double read_time); |
365 | static |
366 | TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, |
367 | double read_time, |
368 | bool *are_all_covering); |
369 | static |
370 | TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, |
371 | SEL_TREE *tree, |
372 | double read_time); |
373 | static |
374 | TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, |
375 | double read_time); |
376 | static |
377 | TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge, |
378 | TRP_INDEX_MERGE *imerge_trp, |
379 | double read_time); |
380 | static |
381 | TRP_GROUP_MIN_MAX *get_best_group_min_max(PARAM *param, SEL_TREE *tree, |
382 | double read_time); |
383 | |
384 | #ifndef DBUG_OFF |
385 | static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map, |
386 | const char *msg); |
387 | static void print_ror_scans_arr(TABLE *table, const char *msg, |
388 | struct st_ror_scan_info **start, |
389 | struct st_ror_scan_info **end); |
390 | static void print_quick(QUICK_SELECT_I *quick, const key_map *needed_reg); |
391 | #endif |
392 | |
393 | static SEL_TREE *tree_and(RANGE_OPT_PARAM *param, |
394 | SEL_TREE *tree1, SEL_TREE *tree2); |
395 | static SEL_TREE *tree_or(RANGE_OPT_PARAM *param, |
396 | SEL_TREE *tree1,SEL_TREE *tree2); |
397 | static SEL_ARG *sel_add(SEL_ARG *key1,SEL_ARG *key2); |
398 | static SEL_ARG *key_or(RANGE_OPT_PARAM *param, |
399 | SEL_ARG *key1, SEL_ARG *key2); |
400 | static SEL_ARG *key_and(RANGE_OPT_PARAM *param, |
401 | SEL_ARG *key1, SEL_ARG *key2, |
402 | uint clone_flag); |
403 | static bool get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1); |
404 | bool get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, |
405 | SEL_ARG *key_tree, uchar *min_key,uint min_key_flag, |
406 | uchar *max_key,uint max_key_flag); |
407 | static bool eq_tree(SEL_ARG* a,SEL_ARG *b); |
408 | |
409 | static SEL_ARG null_element(SEL_ARG::IMPOSSIBLE); |
410 | static bool null_part_in_key(KEY_PART *key_part, const uchar *key, |
411 | uint length); |
412 | static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts); |
413 | |
414 | #include "opt_range_mrr.cc" |
415 | |
416 | static bool sel_trees_have_common_keys(SEL_TREE *tree1, SEL_TREE *tree2, |
417 | key_map *common_keys); |
418 | static void eliminate_single_tree_imerges(RANGE_OPT_PARAM *param, |
419 | SEL_TREE *tree); |
420 | |
421 | static bool sel_trees_can_be_ored(RANGE_OPT_PARAM* param, |
422 | SEL_TREE *tree1, SEL_TREE *tree2, |
423 | key_map *common_keys); |
424 | static bool sel_trees_must_be_ored(RANGE_OPT_PARAM* param, |
425 | SEL_TREE *tree1, SEL_TREE *tree2, |
426 | key_map common_keys); |
427 | static int and_range_trees(RANGE_OPT_PARAM *param, |
428 | SEL_TREE *tree1, SEL_TREE *tree2, |
429 | SEL_TREE *result); |
430 | static bool remove_nonrange_trees(RANGE_OPT_PARAM *param, SEL_TREE *tree); |
431 | |
432 | |
433 | /* |
434 | SEL_IMERGE is a list of possible ways to do index merge, i.e. it is |
435 | a condition in the following form: |
436 | (t_1||t_2||...||t_N) && (next) |
437 | |
438 | where all t_i are SEL_TREEs, next is another SEL_IMERGE and no pair |
439 | (t_i,t_j) contains SEL_ARGS for the same index. |
440 | |
441 | SEL_TREE contained in SEL_IMERGE always has merges=NULL. |
442 | |
443 | This class relies on memory manager to do the cleanup. |
444 | */ |
445 | |
446 | class SEL_IMERGE : public Sql_alloc |
447 | { |
448 | enum { PREALLOCED_TREES= 10}; |
449 | public: |
450 | SEL_TREE *trees_prealloced[PREALLOCED_TREES]; |
451 | SEL_TREE **trees; /* trees used to do index_merge */ |
452 | SEL_TREE **trees_next; /* last of these trees */ |
453 | SEL_TREE **trees_end; /* end of allocated space */ |
454 | |
455 | SEL_ARG ***best_keys; /* best keys to read in SEL_TREEs */ |
456 | |
457 | SEL_IMERGE() : |
458 | trees(&trees_prealloced[0]), |
459 | trees_next(trees), |
460 | trees_end(trees + PREALLOCED_TREES) |
461 | {} |
462 | SEL_IMERGE (SEL_IMERGE *arg, uint cnt, RANGE_OPT_PARAM *param); |
463 | int or_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree); |
464 | bool have_common_keys(RANGE_OPT_PARAM *param, SEL_TREE *tree); |
465 | int and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree, |
466 | SEL_IMERGE *new_imerge); |
467 | int or_sel_tree_with_checks(RANGE_OPT_PARAM *param, |
468 | uint n_init_trees, |
469 | SEL_TREE *new_tree, |
470 | bool is_first_check_pass, |
471 | bool *is_last_check_pass); |
472 | int or_sel_imerge_with_checks(RANGE_OPT_PARAM *param, |
473 | uint n_init_trees, |
474 | SEL_IMERGE* imerge, |
475 | bool is_first_check_pass, |
476 | bool *is_last_check_pass); |
477 | }; |
478 | |
479 | |
480 | /* |
481 | Add a range tree to the range trees of this imerge |
482 | |
483 | SYNOPSIS |
484 | or_sel_tree() |
485 | param Context info for the operation |
486 | tree SEL_TREE to add to this imerge |
487 | |
488 | DESCRIPTION |
489 | The function just adds the range tree 'tree' to the range trees |
490 | of this imerge. |
491 | |
492 | RETURN |
493 | 0 if the operation is success |
494 | -1 if the function runs out memory |
495 | */ |
496 | |
497 | int SEL_IMERGE::or_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree) |
498 | { |
499 | if (trees_next == trees_end) |
500 | { |
501 | const int realloc_ratio= 2; /* Double size for next round */ |
502 | size_t old_elements= (trees_end - trees); |
503 | size_t old_size= sizeof(SEL_TREE**) * old_elements; |
504 | size_t new_size= old_size * realloc_ratio; |
505 | SEL_TREE **new_trees; |
506 | if (!(new_trees= (SEL_TREE**)alloc_root(param->mem_root, new_size))) |
507 | return -1; |
508 | memcpy(new_trees, trees, old_size); |
509 | trees= new_trees; |
510 | trees_next= trees + old_elements; |
511 | trees_end= trees + old_elements * realloc_ratio; |
512 | } |
513 | *(trees_next++)= tree; |
514 | return 0; |
515 | } |
516 | |
517 | |
518 | /* |
519 | Check if any of the range trees of this imerge intersects with a given tree |
520 | |
521 | SYNOPSIS |
522 | have_common_keys() |
523 | param Context info for the function |
524 | tree SEL_TREE intersection with the imerge range trees is checked for |
525 | |
526 | DESCRIPTION |
527 | The function checks whether there is any range tree rt_i in this imerge |
528 | such that there are some indexes for which ranges are defined in both |
529 | rt_i and the range part of the SEL_TREE tree. |
530 | To check this the function calls the function sel_trees_have_common_keys. |
531 | |
532 | RETURN |
533 | TRUE if there are such range trees in this imerge |
534 | FALSE otherwise |
535 | */ |
536 | |
537 | bool SEL_IMERGE::have_common_keys(RANGE_OPT_PARAM *param, SEL_TREE *tree) |
538 | { |
539 | for (SEL_TREE** or_tree= trees, **bound= trees_next; |
540 | or_tree != bound; or_tree++) |
541 | { |
542 | key_map common_keys; |
543 | if (sel_trees_have_common_keys(*or_tree, tree, &common_keys)) |
544 | return TRUE; |
545 | } |
546 | return FALSE; |
547 | } |
548 | |
549 | |
550 | /* |
551 | Perform AND operation for this imerge and the range part of a tree |
552 | |
553 | SYNOPSIS |
554 | and_sel_tree() |
555 | param Context info for the operation |
556 | tree SEL_TREE for the second operand of the operation |
557 | new_imerge OUT imerge for the result of the operation |
558 | |
559 | DESCRIPTION |
560 | This function performs AND operation for this imerge m and the |
561 | range part of the SEL_TREE tree rt. In other words the function |
562 | pushes rt into this imerge. The resulting imerge is returned in |
563 | the parameter new_imerge. |
564 | If this imerge m represent the formula |
565 | RT_1 OR ... OR RT_k |
566 | then the resulting imerge of the function represents the formula |
567 | (RT_1 AND RT) OR ... OR (RT_k AND RT) |
568 | The function calls the function and_range_trees to construct the |
569 | range tree representing (RT_i AND RT). |
570 | |
571 | NOTE |
572 | The function may return an empty imerge without any range trees. |
573 | This happens when each call of and_range_trees returns an |
574 | impossible range tree (SEL_TREE::IMPOSSIBLE). |
575 | Example: (key1 < 2 AND key2 > 10) AND (key1 > 4 OR key2 < 6). |
576 | |
577 | RETURN |
578 | 0 if the operation is a success |
579 | -1 otherwise: there is not enough memory to perform the operation |
580 | */ |
581 | |
582 | int SEL_IMERGE::and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree, |
583 | SEL_IMERGE *new_imerge) |
584 | { |
585 | for (SEL_TREE** or_tree= trees; or_tree != trees_next; or_tree++) |
586 | { |
587 | SEL_TREE *res_or_tree= 0; |
588 | SEL_TREE *and_tree= 0; |
589 | if (!(res_or_tree= new SEL_TREE(param->mem_root, param->keys)) || |
590 | !(and_tree= new SEL_TREE(tree, TRUE, param))) |
591 | return (-1); |
592 | if (!and_range_trees(param, *or_tree, and_tree, res_or_tree)) |
593 | { |
594 | if (new_imerge->or_sel_tree(param, res_or_tree)) |
595 | return (-1); |
596 | } |
597 | } |
598 | return 0; |
599 | } |
600 | |
601 | |
602 | /* |
603 | Perform OR operation on this imerge and the range part of a tree |
604 | |
605 | SYNOPSIS |
606 | or_sel_tree_with_checks() |
607 | param Context info for the operation |
608 | n_trees Number of trees in this imerge to check for oring |
609 | tree SEL_TREE whose range part is to be ored |
610 | is_first_check_pass <=> the first call of the function for this imerge |
611 | is_last_check_pass OUT <=> no more calls of the function for this imerge |
612 | |
613 | DESCRIPTION |
614 | The function performs OR operation on this imerge m and the range part |
615 | of the SEL_TREE tree rt. It always replaces this imerge with the result |
616 | of the operation. |
617 | |
618 | The operation can be performed in two different modes: with |
619 | is_first_check_pass==TRUE and is_first_check_pass==FALSE, transforming |
620 | this imerge differently. |
621 | |
622 | Given this imerge represents the formula |
623 | RT_1 OR ... OR RT_k: |
624 | |
625 | 1. In the first mode, when is_first_check_pass==TRUE : |
626 | 1.1. If rt must be ored(see the function sel_trees_must_be_ored) with |
627 | some rt_j (there may be only one such range tree in the imerge) |
628 | then the function produces an imerge representing the formula |
629 | RT_1 OR ... OR (RT_j OR RT) OR ... OR RT_k, |
630 | where the tree for (RT_j OR RT) is built by oring the pairs |
631 | of SEL_ARG trees for the corresponding indexes |
632 | 1.2. Otherwise the function produces the imerge representing the formula: |
633 | RT_1 OR ... OR RT_k OR RT. |
634 | |
635 | 2. In the second mode, when is_first_check_pass==FALSE : |
636 | 2.1. For each rt_j in the imerge that can be ored (see the function |
637 | sel_trees_can_be_ored) with rt the function replaces rt_j for a |
638 | range tree such that for each index for which ranges are defined |
639 | in both in rt_j and rt the tree contains the result of oring of |
640 | these ranges. |
641 | 2.2. In other cases the function does not produce any imerge. |
642 | |
643 | When is_first_check==TRUE the function returns FALSE in the parameter |
644 | is_last_check_pass if there is no rt_j such that rt_j can be ored with rt, |
645 | but, at the same time, it's not true that rt_j must be ored with rt. |
646 | When is_first_check==FALSE the function always returns FALSE in the |
647 | parameter is_last_check_pass. |
648 | |
649 | RETURN |
650 | 1 The result of oring of rt_j and rt that must be ored returns the |
651 | the range tree with type==SEL_TREE::ALWAYS |
652 | (in this case the imerge m should be discarded) |
653 | -1 The function runs out of memory |
654 | 0 in all other cases |
655 | */ |
656 | |
657 | int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param, |
658 | uint n_trees, |
659 | SEL_TREE *tree, |
660 | bool is_first_check_pass, |
661 | bool *is_last_check_pass) |
662 | { |
663 | bool was_ored= FALSE; |
664 | *is_last_check_pass= is_first_check_pass; |
665 | SEL_TREE** or_tree = trees; |
666 | for (uint i= 0; i < n_trees; i++, or_tree++) |
667 | { |
668 | SEL_TREE *result= 0; |
669 | key_map result_keys; |
670 | key_map ored_keys; |
671 | if (sel_trees_can_be_ored(param, *or_tree, tree, &ored_keys)) |
672 | { |
673 | bool must_be_ored= sel_trees_must_be_ored(param, *or_tree, tree, |
674 | ored_keys); |
675 | if (must_be_ored || !is_first_check_pass) |
676 | { |
677 | result_keys.clear_all(); |
678 | result= *or_tree; |
679 | for (uint key_no= 0; key_no < param->keys; key_no++) |
680 | { |
681 | if (!ored_keys.is_set(key_no)) |
682 | { |
683 | result->keys[key_no]= 0; |
684 | continue; |
685 | } |
686 | SEL_ARG *key1= (*or_tree)->keys[key_no]; |
687 | SEL_ARG *key2= tree->keys[key_no]; |
688 | key2->incr_refs(); |
689 | if ((result->keys[key_no]= key_or(param, key1, key2))) |
690 | { |
691 | |
692 | result_keys.set_bit(key_no); |
693 | #ifdef EXTRA_DEBUG |
694 | if (param->alloced_sel_args < SEL_ARG::MAX_SEL_ARGS) |
695 | { |
696 | key1= result->keys[key_no]; |
697 | (key1)->test_use_count(key1); |
698 | } |
699 | #endif |
700 | } |
701 | } |
702 | } |
703 | else if(is_first_check_pass) |
704 | *is_last_check_pass= FALSE; |
705 | } |
706 | |
707 | if (result) |
708 | { |
709 | result->keys_map= result_keys; |
710 | if (result_keys.is_clear_all()) |
711 | result->type= SEL_TREE::ALWAYS; |
712 | if ((result->type == SEL_TREE::MAYBE) || |
713 | (result->type == SEL_TREE::ALWAYS)) |
714 | return 1; |
715 | /* SEL_TREE::IMPOSSIBLE is impossible here */ |
716 | *or_tree= result; |
717 | was_ored= TRUE; |
718 | } |
719 | } |
720 | if (was_ored) |
721 | return 0; |
722 | |
723 | if (is_first_check_pass && !*is_last_check_pass && |
724 | !(tree= new SEL_TREE(tree, FALSE, param))) |
725 | return (-1); |
726 | return or_sel_tree(param, tree); |
727 | } |
728 | |
729 | |
730 | /* |
731 | Perform OR operation on this imerge and and another imerge |
732 | |
733 | SYNOPSIS |
734 | or_sel_imerge_with_checks() |
735 | param Context info for the operation |
736 | n_trees Number of trees in this imerge to check for oring |
737 | imerge The second operand of the operation |
738 | is_first_check_pass <=> the first call of the function for this imerge |
739 | is_last_check_pass OUT <=> no more calls of the function for this imerge |
740 | |
741 | DESCRIPTION |
742 | For each range tree rt from 'imerge' the function calls the method |
743 | SEL_IMERGE::or_sel_tree_with_checks that performs OR operation on this |
744 | SEL_IMERGE object m and the tree rt. The mode of the operation is |
745 | specified by the parameter is_first_check_pass. Each call of |
746 | SEL_IMERGE::or_sel_tree_with_checks transforms this SEL_IMERGE object m. |
747 | The function returns FALSE in the prameter is_last_check_pass if |
748 | at least one of the calls of SEL_IMERGE::or_sel_tree_with_checks |
749 | returns FALSE as the value of its last parameter. |
750 | |
751 | RETURN |
752 | 1 One of the calls of SEL_IMERGE::or_sel_tree_with_checks returns 1. |
753 | (in this case the imerge m should be discarded) |
754 | -1 The function runs out of memory |
755 | 0 in all other cases |
756 | */ |
757 | |
758 | int SEL_IMERGE::or_sel_imerge_with_checks(RANGE_OPT_PARAM *param, |
759 | uint n_trees, |
760 | SEL_IMERGE* imerge, |
761 | bool is_first_check_pass, |
762 | bool *is_last_check_pass) |
763 | { |
764 | *is_last_check_pass= TRUE; |
765 | SEL_TREE** tree= imerge->trees; |
766 | SEL_TREE** tree_end= imerge->trees_next; |
767 | for ( ; tree < tree_end; tree++) |
768 | { |
769 | uint rc; |
770 | bool is_last= TRUE; |
771 | rc= or_sel_tree_with_checks(param, n_trees, *tree, |
772 | is_first_check_pass, &is_last); |
773 | if (!is_last) |
774 | *is_last_check_pass= FALSE; |
775 | if (rc) |
776 | return rc; |
777 | } |
778 | return 0; |
779 | } |
780 | |
781 | |
782 | /* |
783 | Copy constructor for SEL_TREE objects |
784 | |
785 | SYNOPSIS |
786 | SEL_TREE |
787 | arg The source tree for the constructor |
788 | without_merges <=> only the range part of the tree arg is copied |
789 | param Context info for the operation |
790 | |
791 | DESCRIPTION |
792 | The constructor creates a full copy of the SEL_TREE arg if |
793 | the prameter without_merges==FALSE. Otherwise a tree is created |
794 | that contains the copy only of the range part of the tree arg. |
795 | */ |
796 | |
797 | SEL_TREE::SEL_TREE(SEL_TREE *arg, bool without_merges, |
798 | RANGE_OPT_PARAM *param) |
799 | : Sql_alloc(), |
800 | keys(param->mem_root, param->keys), |
801 | n_ror_scans(0) |
802 | { |
803 | keys_map= arg->keys_map; |
804 | type= arg->type; |
805 | MEM_ROOT *mem_root; |
806 | |
807 | for (uint idx= 0; idx < param->keys; idx++) |
808 | { |
809 | if ((keys[idx]= arg->keys[idx])) |
810 | keys[idx]->incr_refs_all(); |
811 | } |
812 | |
813 | if (without_merges) |
814 | return; |
815 | |
816 | mem_root= current_thd->mem_root; |
817 | List_iterator<SEL_IMERGE> it(arg->merges); |
818 | for (SEL_IMERGE *el= it++; el; el= it++) |
819 | { |
820 | SEL_IMERGE *merge= new (mem_root) SEL_IMERGE(el, 0, param); |
821 | if (!merge || merge->trees == merge->trees_next) |
822 | { |
823 | merges.empty(); |
824 | return; |
825 | } |
826 | merges.push_back(merge, mem_root); |
827 | } |
828 | } |
829 | |
830 | |
831 | /* |
832 | Copy constructor for SEL_IMERGE objects |
833 | |
834 | SYNOPSIS |
835 | SEL_IMERGE |
836 | arg The source imerge for the constructor |
837 | cnt How many trees from arg are to be copied |
838 | param Context info for the operation |
839 | |
840 | DESCRIPTION |
841 | The cnt==0 then the constructor creates a full copy of the |
842 | imerge arg. Otherwise only the first cnt trees of the imerge |
843 | are copied. |
844 | */ |
845 | |
846 | SEL_IMERGE::SEL_IMERGE(SEL_IMERGE *arg, uint cnt, |
847 | RANGE_OPT_PARAM *param) : Sql_alloc() |
848 | { |
849 | size_t elements= (arg->trees_end - arg->trees); |
850 | if (elements > PREALLOCED_TREES) |
851 | { |
852 | size_t size= elements * sizeof (SEL_TREE **); |
853 | if (!(trees= (SEL_TREE **)alloc_root(param->mem_root, size))) |
854 | goto mem_err; |
855 | } |
856 | else |
857 | trees= &trees_prealloced[0]; |
858 | |
859 | trees_next= trees + (cnt ? cnt : arg->trees_next-arg->trees); |
860 | trees_end= trees + elements; |
861 | |
862 | for (SEL_TREE **tree = trees, **arg_tree= arg->trees; tree < trees_next; |
863 | tree++, arg_tree++) |
864 | { |
865 | if (!(*tree= new SEL_TREE(*arg_tree, TRUE, param))) |
866 | goto mem_err; |
867 | } |
868 | |
869 | return; |
870 | |
871 | mem_err: |
872 | trees= &trees_prealloced[0]; |
873 | trees_next= trees; |
874 | trees_end= trees; |
875 | } |
876 | |
877 | |
878 | /* |
879 | Perform AND operation on two imerge lists |
880 | |
881 | SYNOPSIS |
882 | imerge_list_and_list() |
883 | param Context info for the operation |
884 | im1 The first imerge list for the operation |
885 | im2 The second imerge list for the operation |
886 | |
887 | DESCRIPTION |
888 | The function just appends the imerge list im2 to the imerge list im1 |
889 | |
890 | RETURN VALUE |
891 | none |
892 | */ |
893 | |
894 | inline void imerge_list_and_list(List<SEL_IMERGE> *im1, List<SEL_IMERGE> *im2) |
895 | { |
896 | im1->append(im2); |
897 | } |
898 | |
899 | |
900 | /* |
901 | Perform OR operation on two imerge lists |
902 | |
903 | SYNOPSIS |
904 | imerge_list_or_list() |
905 | param Context info for the operation |
906 | im1 The first imerge list for the operation |
907 | im2 The second imerge list for the operation |
908 | |
909 | DESCRIPTION |
910 | Assuming that the first imerge list represents the formula |
911 | F1= M1_1 AND ... AND M1_k1 |
912 | while the second imerge list represents the formula |
913 | F2= M2_1 AND ... AND M2_k2, |
914 | where M1_i= RT1_i_1 OR ... OR RT1_i_l1i (i in [1..k1]) |
915 | and M2_i = RT2_i_1 OR ... OR RT2_i_l2i (i in [1..k2]), |
916 | the function builds a list of imerges for some formula that can be |
917 | inferred from the formula (F1 OR F2). |
918 | |
919 | More exactly the function builds imerges for the formula (M1_1 OR M2_1). |
920 | Note that |
921 | (F1 OR F2) = (M1_1 AND ... AND M1_k1) OR (M2_1 AND ... AND M2_k2) = |
922 | AND (M1_i OR M2_j) (i in [1..k1], j in [1..k2]) => |
923 | M1_1 OR M2_1. |
924 | So (M1_1 OR M2_1) is indeed an inference formula for (F1 OR F2). |
925 | |
926 | To build imerges for the formula (M1_1 OR M2_1) the function invokes, |
927 | possibly twice, the method SEL_IMERGE::or_sel_imerge_with_checks |
928 | for the imerge m1_1. |
929 | At its first invocation the method SEL_IMERGE::or_sel_imerge_with_checks |
930 | performs OR operation on the imerge m1_1 and the range tree rt2_1_1 by |
931 | calling SEL_IMERGE::or_sel_tree_with_checks with is_first_pass_check==TRUE. |
932 | The resulting imerge of the operation is ored with the next range tree of |
933 | the imerge m2_1. This oring continues until the last range tree from |
934 | m2_1 has been ored. |
935 | At its second invocation the method SEL_IMERGE::or_sel_imerge_with_checks |
936 | performs the same sequence of OR operations, but now calling |
937 | SEL_IMERGE::or_sel_tree_with_checks with is_first_pass_check==FALSE. |
938 | |
939 | The imerges that the operation produces replace those in the list im1 |
940 | |
941 | RETURN |
942 | 0 if the operation is a success |
943 | -1 if the function has run out of memory |
944 | */ |
945 | |
946 | int imerge_list_or_list(RANGE_OPT_PARAM *param, |
947 | List<SEL_IMERGE> *im1, |
948 | List<SEL_IMERGE> *im2) |
949 | { |
950 | |
951 | uint rc; |
952 | bool is_last_check_pass= FALSE; |
953 | SEL_IMERGE *imerge= im1->head(); |
954 | uint elems= (uint)(imerge->trees_next-imerge->trees); |
955 | MEM_ROOT *mem_root= current_thd->mem_root; |
956 | |
957 | im1->empty(); |
958 | im1->push_back(imerge, mem_root); |
959 | |
960 | rc= imerge->or_sel_imerge_with_checks(param, elems, im2->head(), |
961 | TRUE, &is_last_check_pass); |
962 | if (rc) |
963 | { |
964 | if (rc == 1) |
965 | { |
966 | im1->empty(); |
967 | rc= 0; |
968 | } |
969 | return rc; |
970 | } |
971 | |
972 | if (!is_last_check_pass) |
973 | { |
974 | SEL_IMERGE* new_imerge= new (mem_root) SEL_IMERGE(imerge, elems, param); |
975 | if (new_imerge) |
976 | { |
977 | is_last_check_pass= TRUE; |
978 | rc= new_imerge->or_sel_imerge_with_checks(param, elems, im2->head(), |
979 | FALSE, &is_last_check_pass); |
980 | if (!rc) |
981 | im1->push_back(new_imerge, mem_root); |
982 | } |
983 | } |
984 | return rc; |
985 | } |
986 | |
987 | |
988 | /* |
989 | Perform OR operation for each imerge from a list and the range part of a tree |
990 | |
991 | SYNOPSIS |
992 | imerge_list_or_tree() |
993 | param Context info for the operation |
994 | merges The list of imerges to be ored with the range part of tree |
995 | tree SEL_TREE whose range part is to be ored with the imerges |
996 | |
997 | DESCRIPTION |
998 | For each imerge mi from the list 'merges' the function performes OR |
999 | operation with mi and the range part of 'tree' rt, producing one or |
1000 | two imerges. |
1001 | |
1002 | Given the merge mi represent the formula RTi_1 OR ... OR RTi_k, |
1003 | the function forms the merges by the following rules: |
1004 | |
1005 | 1. If rt cannot be ored with any of the trees rti the function just |
1006 | produces an imerge that represents the formula |
1007 | RTi_1 OR ... RTi_k OR RT. |
1008 | 2. If there exist a tree rtj that must be ored with rt the function |
1009 | produces an imerge the represents the formula |
1010 | RTi_1 OR ... OR (RTi_j OR RT) OR ... OR RTi_k, |
1011 | where the range tree for (RTi_j OR RT) is constructed by oring the |
1012 | SEL_ARG trees that must be ored. |
1013 | 3. For each rti_j that can be ored with rt the function produces |
1014 | the new tree rti_j' and substitutes rti_j for this new range tree. |
1015 | |
1016 | In any case the function removes mi from the list and then adds all |
1017 | produced imerges. |
1018 | |
1019 | To build imerges by rules 1-3 the function calls the method |
1020 | SEL_IMERGE::or_sel_tree_with_checks, possibly twice. With the first |
1021 | call it passes TRUE for the third parameter of the function. |
1022 | At this first call imerges by rules 1-2 are built. If the call |
1023 | returns FALSE as the return value of its fourth parameter then the |
1024 | function are called for the second time. At this call the imerge |
1025 | of rule 3 is produced. |
1026 | |
1027 | If a call of SEL_IMERGE::or_sel_tree_with_checks returns 1 then |
1028 | then it means that the produced tree contains an always true |
1029 | range tree and the whole imerge can be discarded. |
1030 | |
1031 | RETURN |
1032 | 1 if no imerges are produced |
1033 | 0 otherwise |
1034 | */ |
1035 | |
1036 | static |
1037 | int imerge_list_or_tree(RANGE_OPT_PARAM *param, |
1038 | List<SEL_IMERGE> *merges, |
1039 | SEL_TREE *tree) |
1040 | { |
1041 | SEL_IMERGE *imerge; |
1042 | List<SEL_IMERGE> additional_merges; |
1043 | List_iterator<SEL_IMERGE> it(*merges); |
1044 | MEM_ROOT *mem_root= current_thd->mem_root; |
1045 | |
1046 | while ((imerge= it++)) |
1047 | { |
1048 | bool is_last_check_pass; |
1049 | int rc= 0; |
1050 | int rc1= 0; |
1051 | SEL_TREE *or_tree= new (mem_root) SEL_TREE (tree, FALSE, param); |
1052 | if (or_tree) |
1053 | { |
1054 | uint elems= (uint)(imerge->trees_next-imerge->trees); |
1055 | rc= imerge->or_sel_tree_with_checks(param, elems, or_tree, |
1056 | TRUE, &is_last_check_pass); |
1057 | if (!is_last_check_pass) |
1058 | { |
1059 | SEL_IMERGE *new_imerge= new (mem_root) SEL_IMERGE(imerge, elems, |
1060 | param); |
1061 | if (new_imerge) |
1062 | { |
1063 | rc1= new_imerge->or_sel_tree_with_checks(param, elems, or_tree, |
1064 | FALSE, &is_last_check_pass); |
1065 | if (!rc1) |
1066 | additional_merges.push_back(new_imerge, mem_root); |
1067 | } |
1068 | } |
1069 | } |
1070 | if (rc || rc1 || !or_tree) |
1071 | it.remove(); |
1072 | } |
1073 | |
1074 | merges->append(&additional_merges); |
1075 | return merges->is_empty(); |
1076 | } |
1077 | |
1078 | |
1079 | /* |
1080 | Perform pushdown operation of the range part of a tree into given imerges |
1081 | |
1082 | SYNOPSIS |
1083 | imerge_list_and_tree() |
1084 | param Context info for the operation |
1085 | merges IN/OUT List of imerges to push the range part of 'tree' into |
1086 | tree SEL_TREE whose range part is to be pushed into imerges |
1087 | replace if the pushdow operation for a imerge is a success |
1088 | then the original imerge is replaced for the result |
1089 | of the pushdown |
1090 | |
1091 | DESCRIPTION |
1092 | For each imerge from the list merges the function pushes the range part |
1093 | rt of 'tree' into the imerge. |
1094 | More exactly if the imerge mi from the list represents the formula |
1095 | RTi_1 OR ... OR RTi_k |
1096 | the function bulds a new imerge that represents the formula |
1097 | (RTi_1 AND RT) OR ... OR (RTi_k AND RT) |
1098 | and adds this imerge to the list merges. |
1099 | To perform this pushdown operation the function calls the method |
1100 | SEL_IMERGE::and_sel_tree. |
1101 | For any imerge mi the new imerge is not created if for each pair of |
1102 | trees rti_j and rt the intersection of the indexes with defined ranges |
1103 | is empty. |
1104 | If the result of the pushdown operation for the imerge mi returns an |
1105 | imerge with no trees then then not only nothing is added to the list |
1106 | merges but mi itself is removed from the list. |
1107 | |
1108 | TODO |
1109 | Optimize the code in order to not create new SEL_IMERGE and new SER_TREE |
1110 | objects when 'replace' is TRUE. (Currently this function is called always |
1111 | with this parameter equal to TRUE.) |
1112 | |
1113 | RETURN |
1114 | 1 if no imerges are left in the list merges |
1115 | 0 otherwise |
1116 | */ |
1117 | |
1118 | static |
1119 | int imerge_list_and_tree(RANGE_OPT_PARAM *param, |
1120 | List<SEL_IMERGE> *merges, |
1121 | SEL_TREE *tree, |
1122 | bool replace) |
1123 | { |
1124 | SEL_IMERGE *imerge; |
1125 | SEL_IMERGE *new_imerge= NULL; |
1126 | List<SEL_IMERGE> new_merges; |
1127 | List_iterator<SEL_IMERGE> it(*merges); |
1128 | MEM_ROOT *mem_root= current_thd->mem_root; |
1129 | |
1130 | while ((imerge= it++)) |
1131 | { |
1132 | if (!new_imerge) |
1133 | new_imerge= new (mem_root) SEL_IMERGE(); |
1134 | if (imerge->have_common_keys(param, tree) && |
1135 | new_imerge && !imerge->and_sel_tree(param, tree, new_imerge)) |
1136 | { |
1137 | if (new_imerge->trees == new_imerge->trees_next) |
1138 | it.remove(); |
1139 | else |
1140 | { |
1141 | if (replace) |
1142 | it.replace(new_imerge); |
1143 | else |
1144 | new_merges.push_back(new_imerge, mem_root); |
1145 | new_imerge= NULL; |
1146 | } |
1147 | } |
1148 | } |
1149 | imerge_list_and_list(&new_merges, merges); |
1150 | *merges= new_merges; |
1151 | return merges->is_empty(); |
1152 | } |
1153 | |
1154 | |
1155 | /*************************************************************************** |
1156 | ** Basic functions for SQL_SELECT and QUICK_RANGE_SELECT |
1157 | ***************************************************************************/ |
1158 | |
1159 | /* make a select from mysql info |
1160 | Error is set as following: |
1161 | 0 = ok |
1162 | 1 = Got some error (out of memory?) |
1163 | */ |
1164 | |
1165 | SQL_SELECT *make_select(TABLE *head, table_map const_tables, |
1166 | table_map read_tables, COND *conds, |
1167 | SORT_INFO *filesort, |
1168 | bool allow_null_cond, |
1169 | int *error) |
1170 | { |
1171 | SQL_SELECT *select; |
1172 | DBUG_ENTER("make_select" ); |
1173 | |
1174 | *error=0; |
1175 | |
1176 | if (!conds && !allow_null_cond) |
1177 | DBUG_RETURN(0); |
1178 | if (!(select= new (head->in_use->mem_root) SQL_SELECT)) |
1179 | { |
1180 | *error= 1; // out of memory |
1181 | DBUG_RETURN(0); /* purecov: inspected */ |
1182 | } |
1183 | select->read_tables=read_tables; |
1184 | select->const_tables=const_tables; |
1185 | select->head=head; |
1186 | select->cond= conds; |
1187 | |
1188 | if (filesort && my_b_inited(&filesort->io_cache)) |
1189 | { |
1190 | /* |
1191 | Hijack the filesort io_cache for make_select |
1192 | SQL_SELECT will be responsible for ensuring that it's properly freed. |
1193 | */ |
1194 | select->file= filesort->io_cache; |
1195 | select->records=(ha_rows) (select->file.end_of_file/ |
1196 | head->file->ref_length); |
1197 | my_b_clear(&filesort->io_cache); |
1198 | } |
1199 | DBUG_RETURN(select); |
1200 | } |
1201 | |
1202 | |
1203 | SQL_SELECT::SQL_SELECT() :quick(0),cond(0),pre_idx_push_select_cond(NULL),free_cond(0) |
1204 | { |
1205 | quick_keys.clear_all(); needed_reg.clear_all(); |
1206 | my_b_clear(&file); |
1207 | } |
1208 | |
1209 | |
1210 | void SQL_SELECT::cleanup() |
1211 | { |
1212 | delete quick; |
1213 | quick= 0; |
1214 | if (free_cond) |
1215 | { |
1216 | free_cond=0; |
1217 | delete cond; |
1218 | cond= 0; |
1219 | } |
1220 | close_cached_file(&file); |
1221 | } |
1222 | |
1223 | |
1224 | SQL_SELECT::~SQL_SELECT() |
1225 | { |
1226 | cleanup(); |
1227 | } |
1228 | |
1229 | #undef index // Fix for Unixware 7 |
1230 | |
1231 | QUICK_SELECT_I::QUICK_SELECT_I() |
1232 | :max_used_key_length(0), |
1233 | used_key_parts(0) |
1234 | {} |
1235 | |
1236 | QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, |
1237 | bool no_alloc, MEM_ROOT *parent_alloc, |
1238 | bool *create_error) |
1239 | :thd(thd), no_alloc(no_alloc), parent_alloc(parent_alloc), |
1240 | free_file(0),cur_range(NULL),last_range(0),dont_free(0) |
1241 | { |
1242 | my_bitmap_map *bitmap; |
1243 | DBUG_ENTER("QUICK_RANGE_SELECT::QUICK_RANGE_SELECT" ); |
1244 | |
1245 | in_ror_merged_scan= 0; |
1246 | index= key_nr; |
1247 | head= table; |
1248 | key_part_info= head->key_info[index].key_part; |
1249 | |
1250 | /* 'thd' is not accessible in QUICK_RANGE_SELECT::reset(). */ |
1251 | mrr_buf_size= thd->variables.mrr_buff_size; |
1252 | mrr_buf_desc= NULL; |
1253 | |
1254 | if (!no_alloc && !parent_alloc) |
1255 | { |
1256 | // Allocates everything through the internal memroot |
1257 | init_sql_alloc(&alloc, "QUICK_RANGE_SELECT" , |
1258 | thd->variables.range_alloc_block_size, 0, |
1259 | MYF(MY_THREAD_SPECIFIC)); |
1260 | thd->mem_root= &alloc; |
1261 | } |
1262 | else |
1263 | bzero((char*) &alloc,sizeof(alloc)); |
1264 | file= head->file; |
1265 | record= head->record[0]; |
1266 | |
1267 | my_init_dynamic_array2(&ranges, sizeof(QUICK_RANGE*), |
1268 | thd->alloc(sizeof(QUICK_RANGE*) * 16), 16, 16, |
1269 | MYF(MY_THREAD_SPECIFIC)); |
1270 | |
1271 | /* Allocate a bitmap for used columns */ |
1272 | if (!(bitmap= (my_bitmap_map*) thd->alloc(head->s->column_bitmap_size))) |
1273 | { |
1274 | column_bitmap.bitmap= 0; |
1275 | *create_error= 1; |
1276 | } |
1277 | else |
1278 | my_bitmap_init(&column_bitmap, bitmap, head->s->fields, FALSE); |
1279 | DBUG_VOID_RETURN; |
1280 | } |
1281 | |
1282 | |
1283 | void QUICK_RANGE_SELECT::need_sorted_output() |
1284 | { |
1285 | if (!(mrr_flags & HA_MRR_SORTED)) |
1286 | { |
1287 | /* |
1288 | Native implementation can't produce sorted output. We'll have to |
1289 | switch to default |
1290 | */ |
1291 | mrr_flags |= HA_MRR_USE_DEFAULT_IMPL; |
1292 | } |
1293 | mrr_flags |= HA_MRR_SORTED; |
1294 | } |
1295 | |
1296 | |
1297 | int QUICK_RANGE_SELECT::init() |
1298 | { |
1299 | DBUG_ENTER("QUICK_RANGE_SELECT::init" ); |
1300 | |
1301 | if (file->inited != handler::NONE) |
1302 | file->ha_index_or_rnd_end(); |
1303 | DBUG_RETURN(FALSE); |
1304 | } |
1305 | |
1306 | |
1307 | void QUICK_RANGE_SELECT::range_end() |
1308 | { |
1309 | if (file->inited != handler::NONE) |
1310 | file->ha_index_or_rnd_end(); |
1311 | } |
1312 | |
1313 | |
1314 | QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT() |
1315 | { |
1316 | DBUG_ENTER("QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT" ); |
1317 | if (!dont_free) |
1318 | { |
1319 | /* file is NULL for CPK scan on covering ROR-intersection */ |
1320 | if (file) |
1321 | { |
1322 | range_end(); |
1323 | file->ha_end_keyread(); |
1324 | if (free_file) |
1325 | { |
1326 | DBUG_PRINT("info" , ("Freeing separate handler %p (free: %d)" , file, |
1327 | free_file)); |
1328 | file->ha_external_lock(current_thd, F_UNLCK); |
1329 | file->ha_close(); |
1330 | delete file; |
1331 | } |
1332 | } |
1333 | delete_dynamic(&ranges); /* ranges are allocated in alloc */ |
1334 | free_root(&alloc,MYF(0)); |
1335 | } |
1336 | my_free(mrr_buf_desc); |
1337 | DBUG_VOID_RETURN; |
1338 | } |
1339 | |
1340 | /* |
1341 | QUICK_INDEX_SORT_SELECT works as follows: |
1342 | - Do index scans, accumulate rowids in the Unique object |
1343 | (Unique will also sort and de-duplicate rowids) |
1344 | - Use rowids from unique to run a disk-ordered sweep |
1345 | */ |
1346 | |
1347 | QUICK_INDEX_SORT_SELECT::QUICK_INDEX_SORT_SELECT(THD *thd_param, |
1348 | TABLE *table) |
1349 | :unique(NULL), pk_quick_select(NULL), thd(thd_param) |
1350 | { |
1351 | DBUG_ENTER("QUICK_INDEX_SORT_SELECT::QUICK_INDEX_SORT_SELECT" ); |
1352 | index= MAX_KEY; |
1353 | head= table; |
1354 | bzero(&read_record, sizeof(read_record)); |
1355 | init_sql_alloc(&alloc, "QUICK_INDEX_SORT_SELECT" , |
1356 | thd->variables.range_alloc_block_size, 0, |
1357 | MYF(MY_THREAD_SPECIFIC)); |
1358 | DBUG_VOID_RETURN; |
1359 | } |
1360 | |
1361 | int QUICK_INDEX_SORT_SELECT::init() |
1362 | { |
1363 | DBUG_ENTER("QUICK_INDEX_SORT_SELECT::init" ); |
1364 | DBUG_RETURN(0); |
1365 | } |
1366 | |
1367 | int QUICK_INDEX_SORT_SELECT::reset() |
1368 | { |
1369 | DBUG_ENTER("QUICK_INDEX_SORT_SELECT::reset" ); |
1370 | const int retval= read_keys_and_merge(); |
1371 | DBUG_RETURN(retval); |
1372 | } |
1373 | |
1374 | bool |
1375 | QUICK_INDEX_SORT_SELECT::push_quick_back(QUICK_RANGE_SELECT *quick_sel_range) |
1376 | { |
1377 | DBUG_ENTER("QUICK_INDEX_SORT_SELECT::push_quick_back" ); |
1378 | if (head->file->primary_key_is_clustered() && |
1379 | quick_sel_range->index == head->s->primary_key) |
1380 | { |
1381 | /* |
1382 | A quick_select over a clustered primary key is handled specifically |
1383 | Here we assume: |
1384 | - PK columns are included in any other merged index |
1385 | - Scan on the PK is disk-ordered. |
1386 | (not meeting #2 will only cause performance degradation) |
1387 | |
1388 | We could treat clustered PK as any other index, but that would |
1389 | be inefficient. There is no point in doing scan on |
1390 | CPK, remembering the rowid, then making rnd_pos() call with |
1391 | that rowid. |
1392 | */ |
1393 | pk_quick_select= quick_sel_range; |
1394 | DBUG_RETURN(0); |
1395 | } |
1396 | DBUG_RETURN(quick_selects.push_back(quick_sel_range, thd->mem_root)); |
1397 | } |
1398 | |
1399 | QUICK_INDEX_SORT_SELECT::~QUICK_INDEX_SORT_SELECT() |
1400 | { |
1401 | List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects); |
1402 | QUICK_RANGE_SELECT* quick; |
1403 | DBUG_ENTER("QUICK_INDEX_SORT_SELECT::~QUICK_INDEX_SORT_SELECT" ); |
1404 | delete unique; |
1405 | quick_it.rewind(); |
1406 | while ((quick= quick_it++)) |
1407 | quick->file= NULL; |
1408 | quick_selects.delete_elements(); |
1409 | delete pk_quick_select; |
1410 | /* It's ok to call the next two even if they are already deinitialized */ |
1411 | end_read_record(&read_record); |
1412 | free_root(&alloc,MYF(0)); |
1413 | DBUG_VOID_RETURN; |
1414 | } |
1415 | |
1416 | QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param, |
1417 | TABLE *table, |
1418 | bool retrieve_full_rows, |
1419 | MEM_ROOT *parent_alloc) |
1420 | : cpk_quick(NULL), thd(thd_param), need_to_fetch_row(retrieve_full_rows), |
1421 | scans_inited(FALSE) |
1422 | { |
1423 | index= MAX_KEY; |
1424 | head= table; |
1425 | record= head->record[0]; |
1426 | if (!parent_alloc) |
1427 | init_sql_alloc(&alloc, "QUICK_ROR_INTERSECT_SELECT" , |
1428 | thd->variables.range_alloc_block_size, 0, |
1429 | MYF(MY_THREAD_SPECIFIC)); |
1430 | else |
1431 | bzero(&alloc, sizeof(MEM_ROOT)); |
1432 | last_rowid= (uchar*) alloc_root(parent_alloc? parent_alloc : &alloc, |
1433 | head->file->ref_length); |
1434 | } |
1435 | |
1436 | |
1437 | /* |
1438 | Do post-constructor initialization. |
1439 | SYNOPSIS |
1440 | QUICK_ROR_INTERSECT_SELECT::init() |
1441 | |
1442 | RETURN |
1443 | 0 OK |
1444 | other Error code |
1445 | */ |
1446 | |
1447 | int QUICK_ROR_INTERSECT_SELECT::init() |
1448 | { |
1449 | DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init" ); |
1450 | /* Check if last_rowid was successfully allocated in ctor */ |
1451 | DBUG_RETURN(!last_rowid); |
1452 | } |
1453 | |
1454 | |
1455 | /* |
1456 | Initialize this quick select to be a ROR-merged scan. |
1457 | |
1458 | SYNOPSIS |
1459 | QUICK_RANGE_SELECT::init_ror_merged_scan() |
1460 | reuse_handler If TRUE, use head->file, otherwise create a separate |
1461 | handler object |
1462 | |
1463 | NOTES |
1464 | This function creates and prepares for subsequent use a separate handler |
1465 | object if it can't reuse head->file. The reason for this is that during |
1466 | ROR-merge several key scans are performed simultaneously, and a single |
1467 | handler is only capable of preserving context of a single key scan. |
1468 | |
1469 | In ROR-merge the quick select doing merge does full records retrieval, |
1470 | merged quick selects read only keys. |
1471 | |
1472 | RETURN |
1473 | 0 ROR child scan initialized, ok to use. |
1474 | 1 error |
1475 | */ |
1476 | |
1477 | int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler, |
1478 | MEM_ROOT *local_alloc) |
1479 | { |
1480 | handler *save_file= file, *org_file; |
1481 | THD *thd= head->in_use; |
1482 | MY_BITMAP * const save_vcol_set= head->vcol_set; |
1483 | MY_BITMAP * const save_read_set= head->read_set; |
1484 | MY_BITMAP * const save_write_set= head->write_set; |
1485 | DBUG_ENTER("QUICK_RANGE_SELECT::init_ror_merged_scan" ); |
1486 | |
1487 | in_ror_merged_scan= 1; |
1488 | if (reuse_handler) |
1489 | { |
1490 | DBUG_PRINT("info" , ("Reusing handler %p" , file)); |
1491 | if (init()) |
1492 | { |
1493 | DBUG_RETURN(1); |
1494 | } |
1495 | goto end; |
1496 | } |
1497 | |
1498 | /* Create a separate handler object for this quick select */ |
1499 | if (free_file) |
1500 | { |
1501 | /* already have own 'handler' object. */ |
1502 | DBUG_RETURN(0); |
1503 | } |
1504 | |
1505 | if (!(file= head->file->clone(head->s->normalized_path.str, local_alloc))) |
1506 | { |
1507 | /* |
1508 | Manually set the error flag. Note: there seems to be quite a few |
1509 | places where a failure could cause the server to "hang" the client by |
1510 | sending no response to a query. ATM those are not real errors because |
1511 | the storage engine calls in question happen to never fail with the |
1512 | existing storage engines. |
1513 | */ |
1514 | my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */ |
1515 | /* Caller will free the memory */ |
1516 | goto failure; /* purecov: inspected */ |
1517 | } |
1518 | |
1519 | if (file->ha_external_lock(thd, F_RDLCK)) |
1520 | goto failure; |
1521 | |
1522 | if (init()) |
1523 | { |
1524 | file->ha_external_lock(thd, F_UNLCK); |
1525 | file->ha_close(); |
1526 | goto failure; |
1527 | } |
1528 | free_file= TRUE; |
1529 | last_rowid= file->ref; |
1530 | |
1531 | end: |
1532 | /* |
1533 | We are only going to read key fields and call position() on 'file' |
1534 | The following sets head->read_set (== column_bitmap) to only use this |
1535 | key. The 'column_bitmap' is used in ::get_next() |
1536 | */ |
1537 | org_file= head->file; |
1538 | head->file= file; |
1539 | |
1540 | head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap, &column_bitmap); |
1541 | head->prepare_for_keyread(index, &column_bitmap); |
1542 | head->prepare_for_position(); |
1543 | |
1544 | head->file= org_file; |
1545 | |
1546 | /* Restore head->read_set (and write_set) to what they had before the call */ |
1547 | head->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set); |
1548 | |
1549 | if (reset()) |
1550 | { |
1551 | if (!reuse_handler) |
1552 | { |
1553 | file->ha_external_lock(thd, F_UNLCK); |
1554 | file->ha_close(); |
1555 | goto failure; |
1556 | } |
1557 | DBUG_RETURN(1); |
1558 | } |
1559 | DBUG_RETURN(0); |
1560 | |
1561 | failure: |
1562 | head->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set); |
1563 | delete file; |
1564 | file= save_file; |
1565 | DBUG_RETURN(1); |
1566 | } |
1567 | |
1568 | |
1569 | /* |
1570 | Initialize this quick select to be a part of a ROR-merged scan. |
1571 | SYNOPSIS |
1572 | QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan() |
1573 | reuse_handler If TRUE, use head->file, otherwise create separate |
1574 | handler object. |
1575 | RETURN |
1576 | 0 OK |
1577 | other error code |
1578 | */ |
1579 | int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler, |
1580 | MEM_ROOT *local_alloc) |
1581 | { |
1582 | List_iterator_fast<QUICK_SELECT_WITH_RECORD> quick_it(quick_selects); |
1583 | QUICK_SELECT_WITH_RECORD *cur; |
1584 | QUICK_RANGE_SELECT *quick; |
1585 | DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan" ); |
1586 | |
1587 | /* Initialize all merged "children" quick selects */ |
1588 | DBUG_ASSERT(!need_to_fetch_row || reuse_handler); |
1589 | if (!need_to_fetch_row && reuse_handler) |
1590 | { |
1591 | cur= quick_it++; |
1592 | quick= cur->quick; |
1593 | /* |
1594 | There is no use of this->file. Use it for the first of merged range |
1595 | selects. |
1596 | */ |
1597 | int error= quick->init_ror_merged_scan(TRUE, local_alloc); |
1598 | if (unlikely(error)) |
1599 | DBUG_RETURN(error); |
1600 | quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS); |
1601 | } |
1602 | while ((cur= quick_it++)) |
1603 | { |
1604 | quick= cur->quick; |
1605 | #ifndef DBUG_OFF |
1606 | const MY_BITMAP * const save_read_set= quick->head->read_set; |
1607 | const MY_BITMAP * const save_write_set= quick->head->write_set; |
1608 | #endif |
1609 | if (quick->init_ror_merged_scan(FALSE, local_alloc)) |
1610 | DBUG_RETURN(1); |
1611 | quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS); |
1612 | |
1613 | // Sets are shared by all members of "quick_selects" so must not change |
1614 | #ifndef DBUG_OFF |
1615 | DBUG_ASSERT(quick->head->read_set == save_read_set); |
1616 | DBUG_ASSERT(quick->head->write_set == save_write_set); |
1617 | #endif |
1618 | /* All merged scans share the same record buffer in intersection. */ |
1619 | quick->record= head->record[0]; |
1620 | } |
1621 | |
1622 | if (need_to_fetch_row && |
1623 | unlikely(head->file->ha_rnd_init_with_error(false))) |
1624 | { |
1625 | DBUG_PRINT("error" , ("ROR index_merge rnd_init call failed" )); |
1626 | DBUG_RETURN(1); |
1627 | } |
1628 | DBUG_RETURN(0); |
1629 | } |
1630 | |
1631 | |
1632 | /* |
1633 | Initialize quick select for row retrieval. |
1634 | SYNOPSIS |
1635 | reset() |
1636 | RETURN |
1637 | 0 OK |
1638 | other Error code |
1639 | */ |
1640 | |
1641 | int QUICK_ROR_INTERSECT_SELECT::reset() |
1642 | { |
1643 | DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::reset" ); |
1644 | if (!scans_inited && init_ror_merged_scan(TRUE, &alloc)) |
1645 | DBUG_RETURN(1); |
1646 | scans_inited= TRUE; |
1647 | List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects); |
1648 | QUICK_SELECT_WITH_RECORD *qr; |
1649 | while ((qr= it++)) |
1650 | qr->quick->reset(); |
1651 | DBUG_RETURN(0); |
1652 | } |
1653 | |
1654 | |
1655 | /* |
1656 | Add a merged quick select to this ROR-intersection quick select. |
1657 | |
1658 | SYNOPSIS |
1659 | QUICK_ROR_INTERSECT_SELECT::push_quick_back() |
1660 | alloc Mem root to create auxiliary structures on |
1661 | quick Quick select to be added. The quick select must return |
1662 | rows in rowid order. |
1663 | NOTES |
1664 | This call can only be made before init() is called. |
1665 | |
1666 | RETURN |
1667 | FALSE OK |
1668 | TRUE Out of memory. |
1669 | */ |
1670 | |
1671 | bool |
1672 | QUICK_ROR_INTERSECT_SELECT::push_quick_back(MEM_ROOT *local_alloc, |
1673 | QUICK_RANGE_SELECT *quick) |
1674 | { |
1675 | QUICK_SELECT_WITH_RECORD *qr; |
1676 | if (!(qr= new QUICK_SELECT_WITH_RECORD) || |
1677 | !(qr->key_tuple= (uchar*)alloc_root(local_alloc, |
1678 | quick->max_used_key_length))) |
1679 | return TRUE; |
1680 | qr->quick= quick; |
1681 | return quick_selects.push_back(qr); |
1682 | } |
1683 | |
1684 | |
1685 | QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT() |
1686 | { |
1687 | DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::~QUICK_ROR_INTERSECT_SELECT" ); |
1688 | quick_selects.delete_elements(); |
1689 | delete cpk_quick; |
1690 | free_root(&alloc,MYF(0)); |
1691 | if (need_to_fetch_row && head->file->inited != handler::NONE) |
1692 | head->file->ha_rnd_end(); |
1693 | DBUG_VOID_RETURN; |
1694 | } |
1695 | |
1696 | |
1697 | QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param, |
1698 | TABLE *table) |
1699 | : thd(thd_param), scans_inited(FALSE) |
1700 | { |
1701 | index= MAX_KEY; |
1702 | head= table; |
1703 | rowid_length= table->file->ref_length; |
1704 | record= head->record[0]; |
1705 | init_sql_alloc(&alloc, "QUICK_ROR_UNION_SELECT" , |
1706 | thd->variables.range_alloc_block_size, 0, |
1707 | MYF(MY_THREAD_SPECIFIC)); |
1708 | thd_param->mem_root= &alloc; |
1709 | } |
1710 | |
1711 | |
1712 | /* |
1713 | Comparison function to be used QUICK_ROR_UNION_SELECT::queue priority |
1714 | queue. |
1715 | |
1716 | SYNPOSIS |
1717 | QUICK_ROR_UNION_SELECT_queue_cmp() |
1718 | arg Pointer to QUICK_ROR_UNION_SELECT |
1719 | val1 First merged select |
1720 | val2 Second merged select |
1721 | */ |
1722 | |
1723 | C_MODE_START |
1724 | |
1725 | static int QUICK_ROR_UNION_SELECT_queue_cmp(void *arg, uchar *val1, uchar *val2) |
1726 | { |
1727 | QUICK_ROR_UNION_SELECT *self= (QUICK_ROR_UNION_SELECT*)arg; |
1728 | return self->head->file->cmp_ref(((QUICK_SELECT_I*)val1)->last_rowid, |
1729 | ((QUICK_SELECT_I*)val2)->last_rowid); |
1730 | } |
1731 | |
1732 | C_MODE_END |
1733 | |
1734 | |
1735 | /* |
1736 | Do post-constructor initialization. |
1737 | SYNOPSIS |
1738 | QUICK_ROR_UNION_SELECT::init() |
1739 | |
1740 | RETURN |
1741 | 0 OK |
1742 | other Error code |
1743 | */ |
1744 | |
1745 | int QUICK_ROR_UNION_SELECT::init() |
1746 | { |
1747 | DBUG_ENTER("QUICK_ROR_UNION_SELECT::init" ); |
1748 | if (init_queue(&queue, quick_selects.elements, 0, |
1749 | FALSE , QUICK_ROR_UNION_SELECT_queue_cmp, |
1750 | (void*) this, 0, 0)) |
1751 | { |
1752 | bzero(&queue, sizeof(QUEUE)); |
1753 | DBUG_RETURN(1); |
1754 | } |
1755 | |
1756 | if (!(cur_rowid= (uchar*) alloc_root(&alloc, 2*head->file->ref_length))) |
1757 | DBUG_RETURN(1); |
1758 | prev_rowid= cur_rowid + head->file->ref_length; |
1759 | DBUG_RETURN(0); |
1760 | } |
1761 | |
1762 | |
1763 | /* |
1764 | Initialize quick select for row retrieval. |
1765 | SYNOPSIS |
1766 | reset() |
1767 | |
1768 | RETURN |
1769 | 0 OK |
1770 | other Error code |
1771 | */ |
1772 | |
1773 | int QUICK_ROR_UNION_SELECT::reset() |
1774 | { |
1775 | QUICK_SELECT_I *quick; |
1776 | int error; |
1777 | DBUG_ENTER("QUICK_ROR_UNION_SELECT::reset" ); |
1778 | have_prev_rowid= FALSE; |
1779 | if (!scans_inited) |
1780 | { |
1781 | List_iterator_fast<QUICK_SELECT_I> it(quick_selects); |
1782 | while ((quick= it++)) |
1783 | { |
1784 | if (quick->init_ror_merged_scan(FALSE, &alloc)) |
1785 | DBUG_RETURN(1); |
1786 | } |
1787 | scans_inited= TRUE; |
1788 | } |
1789 | queue_remove_all(&queue); |
1790 | /* |
1791 | Initialize scans for merged quick selects and put all merged quick |
1792 | selects into the queue. |
1793 | */ |
1794 | List_iterator_fast<QUICK_SELECT_I> it(quick_selects); |
1795 | while ((quick= it++)) |
1796 | { |
1797 | if (unlikely((error= quick->reset()))) |
1798 | DBUG_RETURN(error); |
1799 | if (unlikely((error= quick->get_next()))) |
1800 | { |
1801 | if (error == HA_ERR_END_OF_FILE) |
1802 | continue; |
1803 | DBUG_RETURN(error); |
1804 | } |
1805 | quick->save_last_pos(); |
1806 | queue_insert(&queue, (uchar*)quick); |
1807 | } |
1808 | /* Prepare for ha_rnd_pos calls. */ |
1809 | if (head->file->inited && unlikely((error= head->file->ha_rnd_end()))) |
1810 | { |
1811 | DBUG_PRINT("error" , ("ROR index_merge rnd_end call failed" )); |
1812 | DBUG_RETURN(error); |
1813 | } |
1814 | if (unlikely((error= head->file->ha_rnd_init(false)))) |
1815 | { |
1816 | DBUG_PRINT("error" , ("ROR index_merge rnd_init call failed" )); |
1817 | DBUG_RETURN(error); |
1818 | } |
1819 | |
1820 | DBUG_RETURN(0); |
1821 | } |
1822 | |
1823 | |
1824 | bool |
1825 | QUICK_ROR_UNION_SELECT::push_quick_back(QUICK_SELECT_I *quick_sel_range) |
1826 | { |
1827 | return quick_selects.push_back(quick_sel_range); |
1828 | } |
1829 | |
1830 | QUICK_ROR_UNION_SELECT::~QUICK_ROR_UNION_SELECT() |
1831 | { |
1832 | DBUG_ENTER("QUICK_ROR_UNION_SELECT::~QUICK_ROR_UNION_SELECT" ); |
1833 | delete_queue(&queue); |
1834 | quick_selects.delete_elements(); |
1835 | if (head->file->inited != handler::NONE) |
1836 | head->file->ha_rnd_end(); |
1837 | free_root(&alloc,MYF(0)); |
1838 | DBUG_VOID_RETURN; |
1839 | } |
1840 | |
1841 | |
1842 | QUICK_RANGE::QUICK_RANGE() |
1843 | :min_key(0),max_key(0),min_length(0),max_length(0), |
1844 | flag(NO_MIN_RANGE | NO_MAX_RANGE), |
1845 | min_keypart_map(0), max_keypart_map(0) |
1846 | {} |
1847 | |
1848 | SEL_ARG::SEL_ARG(SEL_ARG &arg) :Sql_alloc() |
1849 | { |
1850 | type=arg.type; |
1851 | min_flag=arg.min_flag; |
1852 | max_flag=arg.max_flag; |
1853 | maybe_flag=arg.maybe_flag; |
1854 | maybe_null=arg.maybe_null; |
1855 | part=arg.part; |
1856 | field=arg.field; |
1857 | min_value=arg.min_value; |
1858 | max_value=arg.max_value; |
1859 | next_key_part=arg.next_key_part; |
1860 | max_part_no= arg.max_part_no; |
1861 | use_count=1; elements=1; |
1862 | } |
1863 | |
1864 | |
1865 | inline void SEL_ARG::make_root() |
1866 | { |
1867 | left=right= &null_element; |
1868 | color=BLACK; |
1869 | next=prev=0; |
1870 | use_count=0; elements=1; |
1871 | } |
1872 | |
1873 | SEL_ARG::SEL_ARG(Field *f,const uchar *min_value_arg, |
1874 | const uchar *max_value_arg) |
1875 | :min_flag(0), max_flag(0), maybe_flag(0), maybe_null(f->real_maybe_null()), |
1876 | elements(1), use_count(1), field(f), min_value((uchar*) min_value_arg), |
1877 | max_value((uchar*) max_value_arg), next(0),prev(0), |
1878 | next_key_part(0), color(BLACK), type(KEY_RANGE) |
1879 | { |
1880 | left=right= &null_element; |
1881 | max_part_no= 1; |
1882 | } |
1883 | |
1884 | SEL_ARG::SEL_ARG(Field *field_,uint8 part_, |
1885 | uchar *min_value_, uchar *max_value_, |
1886 | uint8 min_flag_,uint8 max_flag_,uint8 maybe_flag_) |
1887 | :min_flag(min_flag_),max_flag(max_flag_),maybe_flag(maybe_flag_), |
1888 | part(part_),maybe_null(field_->real_maybe_null()), elements(1),use_count(1), |
1889 | field(field_), min_value(min_value_), max_value(max_value_), |
1890 | next(0),prev(0),next_key_part(0),color(BLACK),type(KEY_RANGE) |
1891 | { |
1892 | max_part_no= part+1; |
1893 | left=right= &null_element; |
1894 | } |
1895 | |
1896 | SEL_ARG *SEL_ARG::clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent, |
1897 | SEL_ARG **next_arg) |
1898 | { |
1899 | SEL_ARG *tmp; |
1900 | |
1901 | /* Bail out if we have already generated too many SEL_ARGs */ |
1902 | if (++param->alloced_sel_args > MAX_SEL_ARGS) |
1903 | return 0; |
1904 | |
1905 | if (type != KEY_RANGE) |
1906 | { |
1907 | if (!(tmp= new (param->mem_root) SEL_ARG(type))) |
1908 | return 0; // out of memory |
1909 | tmp->prev= *next_arg; // Link into next/prev chain |
1910 | (*next_arg)->next=tmp; |
1911 | (*next_arg)= tmp; |
1912 | tmp->part= this->part; |
1913 | } |
1914 | else |
1915 | { |
1916 | if (!(tmp= new (param->mem_root) SEL_ARG(field,part, min_value,max_value, |
1917 | min_flag, max_flag, maybe_flag))) |
1918 | return 0; // OOM |
1919 | tmp->parent=new_parent; |
1920 | tmp->next_key_part=next_key_part; |
1921 | if (left != &null_element) |
1922 | if (!(tmp->left=left->clone(param, tmp, next_arg))) |
1923 | return 0; // OOM |
1924 | |
1925 | tmp->prev= *next_arg; // Link into next/prev chain |
1926 | (*next_arg)->next=tmp; |
1927 | (*next_arg)= tmp; |
1928 | |
1929 | if (right != &null_element) |
1930 | if (!(tmp->right= right->clone(param, tmp, next_arg))) |
1931 | return 0; // OOM |
1932 | } |
1933 | increment_use_count(1); |
1934 | tmp->color= color; |
1935 | tmp->elements= this->elements; |
1936 | tmp->max_part_no= max_part_no; |
1937 | return tmp; |
1938 | } |
1939 | |
1940 | /** |
1941 | This gives the first SEL_ARG in the interval list, and the minimal element |
1942 | in the red-black tree |
1943 | |
1944 | @return |
1945 | SEL_ARG first SEL_ARG in the interval list |
1946 | */ |
1947 | SEL_ARG *SEL_ARG::first() |
1948 | { |
1949 | SEL_ARG *next_arg=this; |
1950 | if (!next_arg->left) |
1951 | return 0; // MAYBE_KEY |
1952 | while (next_arg->left != &null_element) |
1953 | next_arg=next_arg->left; |
1954 | return next_arg; |
1955 | } |
1956 | |
1957 | const SEL_ARG *SEL_ARG::first() const |
1958 | { |
1959 | return const_cast<SEL_ARG*>(this)->first(); |
1960 | } |
1961 | |
1962 | SEL_ARG *SEL_ARG::last() |
1963 | { |
1964 | SEL_ARG *next_arg=this; |
1965 | if (!next_arg->right) |
1966 | return 0; // MAYBE_KEY |
1967 | while (next_arg->right != &null_element) |
1968 | next_arg=next_arg->right; |
1969 | return next_arg; |
1970 | } |
1971 | |
1972 | |
1973 | /* |
1974 | Check if a compare is ok, when one takes ranges in account |
1975 | Returns -2 or 2 if the ranges where 'joined' like < 2 and >= 2 |
1976 | */ |
1977 | |
1978 | int SEL_ARG::sel_cmp(Field *field, uchar *a, uchar *b, uint8 a_flag, |
1979 | uint8 b_flag) |
1980 | { |
1981 | int cmp; |
1982 | /* First check if there was a compare to a min or max element */ |
1983 | if (a_flag & (NO_MIN_RANGE | NO_MAX_RANGE)) |
1984 | { |
1985 | if ((a_flag & (NO_MIN_RANGE | NO_MAX_RANGE)) == |
1986 | (b_flag & (NO_MIN_RANGE | NO_MAX_RANGE))) |
1987 | return 0; |
1988 | return (a_flag & NO_MIN_RANGE) ? -1 : 1; |
1989 | } |
1990 | if (b_flag & (NO_MIN_RANGE | NO_MAX_RANGE)) |
1991 | return (b_flag & NO_MIN_RANGE) ? 1 : -1; |
1992 | |
1993 | if (field->real_maybe_null()) // If null is part of key |
1994 | { |
1995 | if (*a != *b) |
1996 | { |
1997 | return *a ? -1 : 1; |
1998 | } |
1999 | if (*a) |
2000 | goto end; // NULL where equal |
2001 | a++; b++; // Skip NULL marker |
2002 | } |
2003 | cmp=field->key_cmp(a , b); |
2004 | if (cmp) return cmp < 0 ? -1 : 1; // The values differed |
2005 | |
2006 | // Check if the compared equal arguments was defined with open/closed range |
2007 | end: |
2008 | if (a_flag & (NEAR_MIN | NEAR_MAX)) |
2009 | { |
2010 | if ((a_flag & (NEAR_MIN | NEAR_MAX)) == (b_flag & (NEAR_MIN | NEAR_MAX))) |
2011 | return 0; |
2012 | if (!(b_flag & (NEAR_MIN | NEAR_MAX))) |
2013 | return (a_flag & NEAR_MIN) ? 2 : -2; |
2014 | return (a_flag & NEAR_MIN) ? 1 : -1; |
2015 | } |
2016 | if (b_flag & (NEAR_MIN | NEAR_MAX)) |
2017 | return (b_flag & NEAR_MIN) ? -2 : 2; |
2018 | return 0; // The elements where equal |
2019 | } |
2020 | |
2021 | |
2022 | SEL_ARG *SEL_ARG::clone_tree(RANGE_OPT_PARAM *param) |
2023 | { |
2024 | SEL_ARG tmp_link,*next_arg,*root; |
2025 | next_arg= &tmp_link; |
2026 | if (!(root= clone(param, (SEL_ARG *) 0, &next_arg))) |
2027 | return 0; |
2028 | next_arg->next=0; // Fix last link |
2029 | tmp_link.next->prev=0; // Fix first link |
2030 | if (root) // If not OOM |
2031 | root->use_count= 0; |
2032 | return root; |
2033 | } |
2034 | |
2035 | |
2036 | /* |
2037 | Table rows retrieval plan. Range optimizer creates QUICK_SELECT_I-derived |
2038 | objects from table read plans. |
2039 | */ |
2040 | class TABLE_READ_PLAN |
2041 | { |
2042 | public: |
2043 | /* |
2044 | Plan read cost, with or without cost of full row retrieval, depending |
2045 | on plan creation parameters. |
2046 | */ |
2047 | double read_cost; |
2048 | ha_rows records; /* estimate of #rows to be examined */ |
2049 | |
2050 | /* |
2051 | If TRUE, the scan returns rows in rowid order. This is used only for |
2052 | scans that can be both ROR and non-ROR. |
2053 | */ |
2054 | bool is_ror; |
2055 | |
2056 | /* |
2057 | Create quick select for this plan. |
2058 | SYNOPSIS |
2059 | make_quick() |
2060 | param Parameter from test_quick_select |
2061 | retrieve_full_rows If TRUE, created quick select will do full record |
2062 | retrieval. |
2063 | parent_alloc Memory pool to use, if any. |
2064 | |
2065 | NOTES |
2066 | retrieve_full_rows is ignored by some implementations. |
2067 | |
2068 | RETURN |
2069 | created quick select |
2070 | NULL on any error. |
2071 | */ |
2072 | virtual QUICK_SELECT_I *make_quick(PARAM *param, |
2073 | bool retrieve_full_rows, |
2074 | MEM_ROOT *parent_alloc=NULL) = 0; |
2075 | |
2076 | /* Table read plans are allocated on MEM_ROOT and are never deleted */ |
2077 | static void *operator new(size_t size, MEM_ROOT *mem_root) |
2078 | { return (void*) alloc_root(mem_root, (uint) size); } |
2079 | static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } |
2080 | static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* Never called */ } |
2081 | virtual ~TABLE_READ_PLAN() {} /* Remove gcc warning */ |
2082 | |
2083 | }; |
2084 | |
2085 | class TRP_ROR_INTERSECT; |
2086 | class TRP_ROR_UNION; |
2087 | class TRP_INDEX_MERGE; |
2088 | |
2089 | |
2090 | /* |
2091 | Plan for a QUICK_RANGE_SELECT scan. |
2092 | TRP_RANGE::make_quick ignores retrieve_full_rows parameter because |
2093 | QUICK_RANGE_SELECT doesn't distinguish between 'index only' scans and full |
2094 | record retrieval scans. |
2095 | */ |
2096 | |
2097 | class TRP_RANGE : public TABLE_READ_PLAN |
2098 | { |
2099 | public: |
2100 | SEL_ARG *key; /* set of intervals to be used in "range" method retrieval */ |
2101 | uint key_idx; /* key number in PARAM::key */ |
2102 | uint mrr_flags; |
2103 | uint mrr_buf_size; |
2104 | |
2105 | TRP_RANGE(SEL_ARG *key_arg, uint idx_arg, uint mrr_flags_arg) |
2106 | : key(key_arg), key_idx(idx_arg), mrr_flags(mrr_flags_arg) |
2107 | {} |
2108 | virtual ~TRP_RANGE() {} /* Remove gcc warning */ |
2109 | |
2110 | QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows, |
2111 | MEM_ROOT *parent_alloc) |
2112 | { |
2113 | DBUG_ENTER("TRP_RANGE::make_quick" ); |
2114 | QUICK_RANGE_SELECT *quick; |
2115 | if ((quick= get_quick_select(param, key_idx, key, mrr_flags, |
2116 | mrr_buf_size, parent_alloc))) |
2117 | { |
2118 | quick->records= records; |
2119 | quick->read_time= read_cost; |
2120 | } |
2121 | DBUG_RETURN(quick); |
2122 | } |
2123 | }; |
2124 | |
2125 | |
2126 | /* Plan for QUICK_ROR_INTERSECT_SELECT scan. */ |
2127 | |
2128 | class TRP_ROR_INTERSECT : public TABLE_READ_PLAN |
2129 | { |
2130 | public: |
2131 | TRP_ROR_INTERSECT() {} /* Remove gcc warning */ |
2132 | virtual ~TRP_ROR_INTERSECT() {} /* Remove gcc warning */ |
2133 | QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows, |
2134 | MEM_ROOT *parent_alloc); |
2135 | |
2136 | /* Array of pointers to ROR range scans used in this intersection */ |
2137 | struct st_ror_scan_info **first_scan; |
2138 | struct st_ror_scan_info **last_scan; /* End of the above array */ |
2139 | struct st_ror_scan_info *cpk_scan; /* Clustered PK scan, if there is one */ |
2140 | bool is_covering; /* TRUE if no row retrieval phase is necessary */ |
2141 | double index_scan_costs; /* SUM(cost(index_scan)) */ |
2142 | }; |
2143 | |
2144 | |
2145 | /* |
2146 | Plan for QUICK_ROR_UNION_SELECT scan. |
2147 | QUICK_ROR_UNION_SELECT always retrieves full rows, so retrieve_full_rows |
2148 | is ignored by make_quick. |
2149 | */ |
2150 | |
2151 | class TRP_ROR_UNION : public TABLE_READ_PLAN |
2152 | { |
2153 | public: |
2154 | TRP_ROR_UNION() {} /* Remove gcc warning */ |
2155 | virtual ~TRP_ROR_UNION() {} /* Remove gcc warning */ |
2156 | QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows, |
2157 | MEM_ROOT *parent_alloc); |
2158 | TABLE_READ_PLAN **first_ror; /* array of ptrs to plans for merged scans */ |
2159 | TABLE_READ_PLAN **last_ror; /* end of the above array */ |
2160 | }; |
2161 | |
2162 | |
2163 | /* |
2164 | Plan for QUICK_INDEX_INTERSECT_SELECT scan. |
2165 | QUICK_INDEX_INTERSECT_SELECT always retrieves full rows, so retrieve_full_rows |
2166 | is ignored by make_quick. |
2167 | */ |
2168 | |
2169 | class TRP_INDEX_INTERSECT : public TABLE_READ_PLAN |
2170 | { |
2171 | public: |
2172 | TRP_INDEX_INTERSECT() {} /* Remove gcc warning */ |
2173 | virtual ~TRP_INDEX_INTERSECT() {} /* Remove gcc warning */ |
2174 | QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows, |
2175 | MEM_ROOT *parent_alloc); |
2176 | TRP_RANGE **range_scans; /* array of ptrs to plans of intersected scans */ |
2177 | TRP_RANGE **range_scans_end; /* end of the array */ |
2178 | /* keys whose scans are to be filtered by cpk conditions */ |
2179 | key_map filtered_scans; |
2180 | }; |
2181 | |
2182 | |
2183 | /* |
2184 | Plan for QUICK_INDEX_MERGE_SELECT scan. |
2185 | QUICK_ROR_INTERSECT_SELECT always retrieves full rows, so retrieve_full_rows |
2186 | is ignored by make_quick. |
2187 | */ |
2188 | |
2189 | class TRP_INDEX_MERGE : public TABLE_READ_PLAN |
2190 | { |
2191 | public: |
2192 | TRP_INDEX_MERGE() {} /* Remove gcc warning */ |
2193 | virtual ~TRP_INDEX_MERGE() {} /* Remove gcc warning */ |
2194 | QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows, |
2195 | MEM_ROOT *parent_alloc); |
2196 | TRP_RANGE **range_scans; /* array of ptrs to plans of merged scans */ |
2197 | TRP_RANGE **range_scans_end; /* end of the array */ |
2198 | }; |
2199 | |
2200 | |
2201 | /* |
2202 | Plan for a QUICK_GROUP_MIN_MAX_SELECT scan. |
2203 | */ |
2204 | |
2205 | class TRP_GROUP_MIN_MAX : public TABLE_READ_PLAN |
2206 | { |
2207 | private: |
2208 | bool have_min, have_max, have_agg_distinct; |
2209 | KEY_PART_INFO *min_max_arg_part; |
2210 | uint group_prefix_len; |
2211 | uint used_key_parts; |
2212 | uint group_key_parts; |
2213 | KEY *index_info; |
2214 | uint index; |
2215 | uint key_infix_len; |
2216 | uchar key_infix[MAX_KEY_LENGTH]; |
2217 | SEL_TREE *range_tree; /* Represents all range predicates in the query. */ |
2218 | SEL_ARG *index_tree; /* The SEL_ARG sub-tree corresponding to index_info. */ |
2219 | uint param_idx; /* Index of used key in param->key. */ |
2220 | bool is_index_scan; /* Use index_next() instead of random read */ |
2221 | public: |
2222 | /* Number of records selected by the ranges in index_tree. */ |
2223 | ha_rows quick_prefix_records; |
2224 | public: |
2225 | TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg, |
2226 | bool have_agg_distinct_arg, |
2227 | KEY_PART_INFO *min_max_arg_part_arg, |
2228 | uint group_prefix_len_arg, uint used_key_parts_arg, |
2229 | uint group_key_parts_arg, KEY *index_info_arg, |
2230 | uint index_arg, uint key_infix_len_arg, |
2231 | uchar *key_infix_arg, |
2232 | SEL_TREE *tree_arg, SEL_ARG *index_tree_arg, |
2233 | uint param_idx_arg, ha_rows quick_prefix_records_arg) |
2234 | : have_min(have_min_arg), have_max(have_max_arg), |
2235 | have_agg_distinct(have_agg_distinct_arg), |
2236 | min_max_arg_part(min_max_arg_part_arg), |
2237 | group_prefix_len(group_prefix_len_arg), used_key_parts(used_key_parts_arg), |
2238 | group_key_parts(group_key_parts_arg), index_info(index_info_arg), |
2239 | index(index_arg), key_infix_len(key_infix_len_arg), range_tree(tree_arg), |
2240 | index_tree(index_tree_arg), param_idx(param_idx_arg), is_index_scan(FALSE), |
2241 | quick_prefix_records(quick_prefix_records_arg) |
2242 | { |
2243 | if (key_infix_len) |
2244 | memcpy(this->key_infix, key_infix_arg, key_infix_len); |
2245 | } |
2246 | virtual ~TRP_GROUP_MIN_MAX() {} /* Remove gcc warning */ |
2247 | |
2248 | QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows, |
2249 | MEM_ROOT *parent_alloc); |
2250 | void use_index_scan() { is_index_scan= TRUE; } |
2251 | }; |
2252 | |
2253 | |
2254 | typedef struct st_index_scan_info |
2255 | { |
2256 | uint idx; /* # of used key in param->keys */ |
2257 | uint keynr; /* # of used key in table */ |
2258 | uint range_count; |
2259 | ha_rows records; /* estimate of # records this scan will return */ |
2260 | |
2261 | /* Set of intervals over key fields that will be used for row retrieval. */ |
2262 | SEL_ARG *sel_arg; |
2263 | |
2264 | KEY *key_info; |
2265 | uint used_key_parts; |
2266 | |
2267 | /* Estimate of # records filtered out by intersection with cpk */ |
2268 | ha_rows filtered_out; |
2269 | /* Bitmap of fields used in index intersection */ |
2270 | MY_BITMAP used_fields; |
2271 | |
2272 | /* Fields used in the query and covered by ROR scan. */ |
2273 | MY_BITMAP covered_fields; |
2274 | uint used_fields_covered; /* # of set bits in covered_fields */ |
2275 | int key_rec_length; /* length of key record (including rowid) */ |
2276 | |
2277 | /* |
2278 | Cost of reading all index records with values in sel_arg intervals set |
2279 | (assuming there is no need to access full table records) |
2280 | */ |
2281 | double index_read_cost; |
2282 | uint first_uncovered_field; /* first unused bit in covered_fields */ |
2283 | uint key_components; /* # of parts in the key */ |
2284 | } INDEX_SCAN_INFO; |
2285 | |
2286 | /* |
2287 | Fill param->needed_fields with bitmap of fields used in the query. |
2288 | SYNOPSIS |
2289 | fill_used_fields_bitmap() |
2290 | param Parameter from test_quick_select function. |
2291 | |
2292 | NOTES |
2293 | Clustered PK members are not put into the bitmap as they are implicitly |
2294 | present in all keys (and it is impossible to avoid reading them). |
2295 | RETURN |
2296 | 0 Ok |
2297 | 1 Out of memory. |
2298 | */ |
2299 | |
2300 | static int fill_used_fields_bitmap(PARAM *param) |
2301 | { |
2302 | TABLE *table= param->table; |
2303 | my_bitmap_map *tmp; |
2304 | uint pk; |
2305 | param->tmp_covered_fields.bitmap= 0; |
2306 | param->fields_bitmap_size= table->s->column_bitmap_size; |
2307 | if (!(tmp= (my_bitmap_map*) alloc_root(param->mem_root, |
2308 | param->fields_bitmap_size)) || |
2309 | my_bitmap_init(¶m->needed_fields, tmp, table->s->fields, FALSE)) |
2310 | return 1; |
2311 | |
2312 | bitmap_copy(¶m->needed_fields, table->read_set); |
2313 | bitmap_union(¶m->needed_fields, table->write_set); |
2314 | |
2315 | pk= param->table->s->primary_key; |
2316 | if (pk != MAX_KEY && param->table->file->primary_key_is_clustered()) |
2317 | { |
2318 | /* The table uses clustered PK and it is not internally generated */ |
2319 | KEY_PART_INFO *key_part= param->table->key_info[pk].key_part; |
2320 | KEY_PART_INFO *key_part_end= key_part + |
2321 | param->table->key_info[pk].user_defined_key_parts; |
2322 | for (;key_part != key_part_end; ++key_part) |
2323 | bitmap_clear_bit(¶m->needed_fields, key_part->fieldnr-1); |
2324 | } |
2325 | return 0; |
2326 | } |
2327 | |
2328 | |
2329 | /* |
2330 | Test if a key can be used in different ranges |
2331 | |
2332 | SYNOPSIS |
2333 | SQL_SELECT::test_quick_select() |
2334 | thd Current thread |
2335 | keys_to_use Keys to use for range retrieval |
2336 | prev_tables Tables assumed to be already read when the scan is |
2337 | performed (but not read at the moment of this call) |
2338 | limit Query limit |
2339 | force_quick_range Prefer to use range (instead of full table scan) even |
2340 | if it is more expensive. |
2341 | |
2342 | NOTES |
2343 | Updates the following in the select parameter: |
2344 | needed_reg - Bits for keys with may be used if all prev regs are read |
2345 | quick - Parameter to use when reading records. |
2346 | |
2347 | In the table struct the following information is updated: |
2348 | quick_keys - Which keys can be used |
2349 | quick_rows - How many rows the key matches |
2350 | quick_condition_rows - E(# rows that will satisfy the table condition) |
2351 | |
2352 | IMPLEMENTATION |
2353 | quick_condition_rows value is obtained as follows: |
2354 | |
2355 | It is a minimum of E(#output rows) for all considered table access |
2356 | methods (range and index_merge accesses over various indexes). |
2357 | |
2358 | The obtained value is not a true E(#rows that satisfy table condition) |
2359 | but rather a pessimistic estimate. To obtain a true E(#...) one would |
2360 | need to combine estimates of various access methods, taking into account |
2361 | correlations between sets of rows they will return. |
2362 | |
2363 | For example, if values of tbl.key1 and tbl.key2 are independent (a right |
2364 | assumption if we have no information about their correlation) then the |
2365 | correct estimate will be: |
2366 | |
2367 | E(#rows("tbl.key1 < c1 AND tbl.key2 < c2")) = |
2368 | = E(#rows(tbl.key1 < c1)) / total_rows(tbl) * E(#rows(tbl.key2 < c2) |
2369 | |
2370 | which is smaller than |
2371 | |
2372 | MIN(E(#rows(tbl.key1 < c1), E(#rows(tbl.key2 < c2))) |
2373 | |
2374 | which is currently produced. |
2375 | |
2376 | TODO |
2377 | * Change the value returned in quick_condition_rows from a pessimistic |
2378 | estimate to true E(#rows that satisfy table condition). |
2379 | (we can re-use some of E(#rows) calcuation code from index_merge/intersection |
2380 | for this) |
2381 | |
2382 | * Check if this function really needs to modify keys_to_use, and change the |
2383 | code to pass it by reference if it doesn't. |
2384 | |
2385 | * In addition to force_quick_range other means can be (an usually are) used |
2386 | to make this function prefer range over full table scan. Figure out if |
2387 | force_quick_range is really needed. |
2388 | |
2389 | RETURN |
2390 | -1 if impossible select (i.e. certainly no rows will be selected) |
2391 | 0 if can't use quick_select |
2392 | 1 if found usable ranges and quick select has been successfully created. |
2393 | */ |
2394 | |
2395 | int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, |
2396 | table_map prev_tables, |
2397 | ha_rows limit, bool force_quick_range, |
2398 | bool ordered_output, |
2399 | bool remove_false_parts_of_where) |
2400 | { |
2401 | uint idx; |
2402 | double scan_time; |
2403 | DBUG_ENTER("SQL_SELECT::test_quick_select" ); |
2404 | DBUG_PRINT("enter" ,("keys_to_use: %lu prev_tables: %lu const_tables: %lu" , |
2405 | (ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables, |
2406 | (ulong) const_tables)); |
2407 | DBUG_PRINT("info" , ("records: %lu" , (ulong) head->stat_records())); |
2408 | delete quick; |
2409 | quick=0; |
2410 | needed_reg.clear_all(); |
2411 | quick_keys.clear_all(); |
2412 | DBUG_ASSERT(!head->is_filled_at_execution()); |
2413 | if (keys_to_use.is_clear_all() || head->is_filled_at_execution()) |
2414 | DBUG_RETURN(0); |
2415 | records= head->stat_records(); |
2416 | if (!records) |
2417 | records++; /* purecov: inspected */ |
2418 | scan_time= (double) records / TIME_FOR_COMPARE + 1; |
2419 | read_time= (double) head->file->scan_time() + scan_time + 1.1; |
2420 | if (head->force_index) |
2421 | scan_time= read_time= DBL_MAX; |
2422 | if (limit < records) |
2423 | read_time= (double) records + scan_time + 1; // Force to use index |
2424 | |
2425 | possible_keys.clear_all(); |
2426 | |
2427 | DBUG_PRINT("info" ,("Time to scan table: %g" , read_time)); |
2428 | |
2429 | keys_to_use.intersect(head->keys_in_use_for_query); |
2430 | if (!keys_to_use.is_clear_all()) |
2431 | { |
2432 | uchar buff[STACK_BUFF_ALLOC]; |
2433 | MEM_ROOT alloc; |
2434 | SEL_TREE *tree= NULL; |
2435 | KEY_PART *key_parts; |
2436 | KEY *key_info; |
2437 | PARAM param; |
2438 | |
2439 | if (check_stack_overrun(thd, 2*STACK_MIN_SIZE + sizeof(PARAM), buff)) |
2440 | DBUG_RETURN(0); // Fatal error flag is set |
2441 | |
2442 | /* set up parameter that is passed to all functions */ |
2443 | param.thd= thd; |
2444 | param.baseflag= head->file->ha_table_flags(); |
2445 | param.prev_tables=prev_tables | const_tables; |
2446 | param.read_tables=read_tables; |
2447 | param.current_table= head->map; |
2448 | param.table=head; |
2449 | param.keys=0; |
2450 | param.mem_root= &alloc; |
2451 | param.old_root= thd->mem_root; |
2452 | param.needed_reg= &needed_reg; |
2453 | param.imerge_cost_buff_size= 0; |
2454 | param.using_real_indexes= TRUE; |
2455 | param.remove_jump_scans= TRUE; |
2456 | param.remove_false_where_parts= remove_false_parts_of_where; |
2457 | param.force_default_mrr= ordered_output; |
2458 | param.possible_keys.clear_all(); |
2459 | |
2460 | thd->no_errors=1; // Don't warn about NULL |
2461 | init_sql_alloc(&alloc, "test_quick_select" , |
2462 | thd->variables.range_alloc_block_size, 0, |
2463 | MYF(MY_THREAD_SPECIFIC)); |
2464 | if (!(param.key_parts= |
2465 | (KEY_PART*) alloc_root(&alloc, |
2466 | sizeof(KEY_PART) * |
2467 | head->s->actual_n_key_parts(thd))) || |
2468 | fill_used_fields_bitmap(¶m)) |
2469 | { |
2470 | thd->no_errors=0; |
2471 | free_root(&alloc,MYF(0)); // Return memory & allocator |
2472 | DBUG_RETURN(0); // Can't use range |
2473 | } |
2474 | key_parts= param.key_parts; |
2475 | |
2476 | /* |
2477 | Make an array with description of all key parts of all table keys. |
2478 | This is used in get_mm_parts function. |
2479 | */ |
2480 | key_info= head->key_info; |
2481 | uint max_key_len= 0; |
2482 | for (idx=0 ; idx < head->s->keys ; idx++, key_info++) |
2483 | { |
2484 | KEY_PART_INFO *key_part_info; |
2485 | uint n_key_parts= head->actual_n_key_parts(key_info); |
2486 | |
2487 | if (!keys_to_use.is_set(idx)) |
2488 | continue; |
2489 | if (key_info->flags & HA_FULLTEXT) |
2490 | continue; // ToDo: ft-keys in non-ft ranges, if possible SerG |
2491 | |
2492 | param.key[param.keys]=key_parts; |
2493 | key_part_info= key_info->key_part; |
2494 | uint cur_key_len= 0; |
2495 | for (uint part= 0 ; part < n_key_parts ; |
2496 | part++, key_parts++, key_part_info++) |
2497 | { |
2498 | key_parts->key= param.keys; |
2499 | key_parts->part= part; |
2500 | key_parts->length= key_part_info->length; |
2501 | key_parts->store_length= key_part_info->store_length; |
2502 | cur_key_len += key_part_info->store_length; |
2503 | key_parts->field= key_part_info->field; |
2504 | key_parts->null_bit= key_part_info->null_bit; |
2505 | key_parts->image_type = |
2506 | (key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW; |
2507 | /* Only HA_PART_KEY_SEG is used */ |
2508 | key_parts->flag= (uint8) key_part_info->key_part_flag; |
2509 | } |
2510 | param.real_keynr[param.keys++]=idx; |
2511 | if (cur_key_len > max_key_len) |
2512 | max_key_len= cur_key_len; |
2513 | } |
2514 | param.key_parts_end=key_parts; |
2515 | param.alloced_sel_args= 0; |
2516 | |
2517 | max_key_len++; /* Take into account the "+1" in QUICK_RANGE::QUICK_RANGE */ |
2518 | if (!(param.min_key= (uchar*)alloc_root(&alloc,max_key_len)) || |
2519 | !(param.max_key= (uchar*)alloc_root(&alloc,max_key_len))) |
2520 | { |
2521 | thd->no_errors=0; |
2522 | free_root(&alloc,MYF(0)); // Return memory & allocator |
2523 | DBUG_RETURN(0); // Can't use range |
2524 | } |
2525 | |
2526 | thd->mem_root= &alloc; |
2527 | /* Calculate cost of full index read for the shortest covering index */ |
2528 | if (!force_quick_range && !head->covering_keys.is_clear_all()) |
2529 | { |
2530 | int key_for_use= find_shortest_key(head, &head->covering_keys); |
2531 | double key_read_time= head->file->keyread_time(key_for_use, 1, records) + |
2532 | (double) records / TIME_FOR_COMPARE; |
2533 | DBUG_PRINT("info" , ("'all'+'using index' scan will be using key %d, " |
2534 | "read time %g" , key_for_use, key_read_time)); |
2535 | if (key_read_time < read_time) |
2536 | read_time= key_read_time; |
2537 | } |
2538 | |
2539 | TABLE_READ_PLAN *best_trp= NULL; |
2540 | TRP_GROUP_MIN_MAX *group_trp; |
2541 | double best_read_time= read_time; |
2542 | |
2543 | if (cond) |
2544 | { |
2545 | if ((tree= cond->get_mm_tree(¶m, &cond))) |
2546 | { |
2547 | if (tree->type == SEL_TREE::IMPOSSIBLE) |
2548 | { |
2549 | records=0L; /* Return -1 from this function. */ |
2550 | read_time= (double) HA_POS_ERROR; |
2551 | goto free_mem; |
2552 | } |
2553 | /* |
2554 | If the tree can't be used for range scans, proceed anyway, as we |
2555 | can construct a group-min-max quick select |
2556 | */ |
2557 | if (tree->type != SEL_TREE::KEY && tree->type != SEL_TREE::KEY_SMALLER) |
2558 | tree= NULL; |
2559 | } |
2560 | } |
2561 | |
2562 | /* |
2563 | Try to construct a QUICK_GROUP_MIN_MAX_SELECT. |
2564 | Notice that it can be constructed no matter if there is a range tree. |
2565 | */ |
2566 | group_trp= get_best_group_min_max(¶m, tree, best_read_time); |
2567 | if (group_trp) |
2568 | { |
2569 | param.table->quick_condition_rows= MY_MIN(group_trp->records, |
2570 | head->stat_records()); |
2571 | if (group_trp->read_cost < best_read_time) |
2572 | { |
2573 | best_trp= group_trp; |
2574 | best_read_time= best_trp->read_cost; |
2575 | } |
2576 | } |
2577 | |
2578 | if (tree) |
2579 | { |
2580 | /* |
2581 | It is possible to use a range-based quick select (but it might be |
2582 | slower than 'all' table scan). |
2583 | */ |
2584 | TRP_RANGE *range_trp; |
2585 | TRP_ROR_INTERSECT *rori_trp; |
2586 | TRP_INDEX_INTERSECT *intersect_trp; |
2587 | bool can_build_covering= FALSE; |
2588 | |
2589 | remove_nonrange_trees(¶m, tree); |
2590 | |
2591 | /* Get best 'range' plan and prepare data for making other plans */ |
2592 | if ((range_trp= get_key_scans_params(¶m, tree, FALSE, TRUE, |
2593 | best_read_time))) |
2594 | { |
2595 | best_trp= range_trp; |
2596 | best_read_time= best_trp->read_cost; |
2597 | } |
2598 | |
2599 | /* |
2600 | Simultaneous key scans and row deletes on several handler |
2601 | objects are not allowed so don't use ROR-intersection for |
2602 | table deletes. |
2603 | */ |
2604 | if ((thd->lex->sql_command != SQLCOM_DELETE) && |
2605 | optimizer_flag(thd, OPTIMIZER_SWITCH_INDEX_MERGE)) |
2606 | { |
2607 | /* |
2608 | Get best non-covering ROR-intersection plan and prepare data for |
2609 | building covering ROR-intersection. |
2610 | */ |
2611 | if ((rori_trp= get_best_ror_intersect(¶m, tree, best_read_time, |
2612 | &can_build_covering))) |
2613 | { |
2614 | best_trp= rori_trp; |
2615 | best_read_time= best_trp->read_cost; |
2616 | /* |
2617 | Try constructing covering ROR-intersect only if it looks possible |
2618 | and worth doing. |
2619 | */ |
2620 | if (!rori_trp->is_covering && can_build_covering && |
2621 | (rori_trp= get_best_covering_ror_intersect(¶m, tree, |
2622 | best_read_time))) |
2623 | best_trp= rori_trp; |
2624 | } |
2625 | } |
2626 | /* |
2627 | Do not look for an index intersection plan if there is a covering |
2628 | index. The scan by this covering index will be always cheaper than |
2629 | any index intersection. |
2630 | */ |
2631 | if (param.table->covering_keys.is_clear_all() && |
2632 | optimizer_flag(thd, OPTIMIZER_SWITCH_INDEX_MERGE) && |
2633 | optimizer_flag(thd, OPTIMIZER_SWITCH_INDEX_MERGE_SORT_INTERSECT)) |
2634 | { |
2635 | if ((intersect_trp= get_best_index_intersect(¶m, tree, |
2636 | best_read_time))) |
2637 | { |
2638 | best_trp= intersect_trp; |
2639 | best_read_time= best_trp->read_cost; |
2640 | set_if_smaller(param.table->quick_condition_rows, |
2641 | intersect_trp->records); |
2642 | } |
2643 | } |
2644 | |
2645 | if (optimizer_flag(thd, OPTIMIZER_SWITCH_INDEX_MERGE) && |
2646 | head->stat_records() != 0) |
2647 | { |
2648 | /* Try creating index_merge/ROR-union scan. */ |
2649 | SEL_IMERGE *imerge; |
2650 | TABLE_READ_PLAN *best_conj_trp= NULL, |
2651 | *UNINIT_VAR(new_conj_trp); /* no empty index_merge lists possible */ |
2652 | DBUG_PRINT("info" ,("No range reads possible," |
2653 | " trying to construct index_merge" )); |
2654 | List_iterator_fast<SEL_IMERGE> it(tree->merges); |
2655 | while ((imerge= it++)) |
2656 | { |
2657 | new_conj_trp= get_best_disjunct_quick(¶m, imerge, best_read_time); |
2658 | if (new_conj_trp) |
2659 | set_if_smaller(param.table->quick_condition_rows, |
2660 | new_conj_trp->records); |
2661 | if (new_conj_trp && |
2662 | (!best_conj_trp || |
2663 | new_conj_trp->read_cost < best_conj_trp->read_cost)) |
2664 | { |
2665 | best_conj_trp= new_conj_trp; |
2666 | best_read_time= best_conj_trp->read_cost; |
2667 | } |
2668 | } |
2669 | if (best_conj_trp) |
2670 | best_trp= best_conj_trp; |
2671 | } |
2672 | } |
2673 | |
2674 | thd->mem_root= param.old_root; |
2675 | |
2676 | /* If we got a read plan, create a quick select from it. */ |
2677 | if (best_trp) |
2678 | { |
2679 | records= best_trp->records; |
2680 | if (!(quick= best_trp->make_quick(¶m, TRUE)) || quick->init()) |
2681 | { |
2682 | delete quick; |
2683 | quick= NULL; |
2684 | } |
2685 | } |
2686 | possible_keys= param.possible_keys; |
2687 | |
2688 | free_mem: |
2689 | free_root(&alloc,MYF(0)); // Return memory & allocator |
2690 | thd->mem_root= param.old_root; |
2691 | thd->no_errors=0; |
2692 | } |
2693 | |
2694 | DBUG_EXECUTE("info" , print_quick(quick, &needed_reg);); |
2695 | |
2696 | /* |
2697 | Assume that if the user is using 'limit' we will only need to scan |
2698 | limit rows if we are using a key |
2699 | */ |
2700 | DBUG_RETURN(records ? MY_TEST(quick) : -1); |
2701 | } |
2702 | |
2703 | /**************************************************************************** |
2704 | * Condition selectivity module |
2705 | ****************************************************************************/ |
2706 | |
2707 | |
2708 | /* |
2709 | Build descriptors of pseudo-indexes over columns to perform range analysis |
2710 | |
2711 | SYNOPSIS |
2712 | create_key_parts_for_pseudo_indexes() |
2713 | param IN/OUT data structure for the descriptors to be built |
2714 | used_fields bitmap of columns for which the descriptors are to be built |
2715 | |
2716 | DESCRIPTION |
2717 | For each column marked in the bitmap used_fields the function builds |
2718 | a descriptor of a single-component pseudo-index over this column that |
2719 | can be used for the range analysis of the predicates over this columns. |
2720 | The descriptors are created in the memory of param->mem_root. |
2721 | |
2722 | RETURN |
2723 | FALSE in the case of success |
2724 | TRUE otherwise |
2725 | */ |
2726 | |
2727 | static |
2728 | bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param, |
2729 | MY_BITMAP *used_fields) |
2730 | { |
2731 | Field **field_ptr; |
2732 | TABLE *table= param->table; |
2733 | uint parts= 0; |
2734 | |
2735 | for (field_ptr= table->field; *field_ptr; field_ptr++) |
2736 | { |
2737 | if (bitmap_is_set(used_fields, (*field_ptr)->field_index)) |
2738 | parts++; |
2739 | } |
2740 | |
2741 | KEY_PART *key_part; |
2742 | uint keys= 0; |
2743 | |
2744 | if (!(key_part= (KEY_PART *) alloc_root(param->mem_root, |
2745 | sizeof(KEY_PART) * parts))) |
2746 | return TRUE; |
2747 | |
2748 | param->key_parts= key_part; |
2749 | uint max_key_len= 0; |
2750 | for (field_ptr= table->field; *field_ptr; field_ptr++) |
2751 | { |
2752 | if (bitmap_is_set(used_fields, (*field_ptr)->field_index)) |
2753 | { |
2754 | Field *field= *field_ptr; |
2755 | uint16 store_length; |
2756 | uint16 max_key_part_length= (uint16) table->file->max_key_part_length(); |
2757 | key_part->key= keys; |
2758 | key_part->part= 0; |
2759 | if (field->flags & BLOB_FLAG) |
2760 | key_part->length= max_key_part_length; |
2761 | else |
2762 | { |
2763 | key_part->length= (uint16) field->key_length(); |
2764 | set_if_smaller(key_part->length, max_key_part_length); |
2765 | } |
2766 | store_length= key_part->length; |
2767 | if (field->real_maybe_null()) |
2768 | store_length+= HA_KEY_NULL_LENGTH; |
2769 | if (field->real_type() == MYSQL_TYPE_VARCHAR) |
2770 | store_length+= HA_KEY_BLOB_LENGTH; |
2771 | if (max_key_len < store_length) |
2772 | max_key_len= store_length; |
2773 | key_part->store_length= store_length; |
2774 | key_part->field= field; |
2775 | key_part->image_type= Field::itRAW; |
2776 | key_part->flag= 0; |
2777 | param->key[keys]= key_part; |
2778 | keys++; |
2779 | key_part++; |
2780 | } |
2781 | } |
2782 | |
2783 | max_key_len++; /* Take into account the "+1" in QUICK_RANGE::QUICK_RANGE */ |
2784 | if (!(param->min_key= (uchar*)alloc_root(param->mem_root, max_key_len)) || |
2785 | !(param->max_key= (uchar*)alloc_root(param->mem_root, max_key_len))) |
2786 | { |
2787 | return true; |
2788 | } |
2789 | param->keys= keys; |
2790 | param->key_parts_end= key_part; |
2791 | |
2792 | return FALSE; |
2793 | } |
2794 | |
2795 | |
2796 | /* |
2797 | Estimate the number of rows in all ranges built for a column |
2798 | by the range optimizer |
2799 | |
2800 | SYNOPSIS |
2801 | records_in_column_ranges() |
2802 | param the data structure to access descriptors of pseudo indexes |
2803 | built over columns used in the condition of the processed query |
2804 | idx the index of the descriptor of interest in param |
2805 | tree the tree representing ranges built for the interesting column |
2806 | |
2807 | DESCRIPTION |
2808 | This function retrieves the ranges represented by the SEL_ARG 'tree' and |
2809 | for each of them r it calls the function get_column_range_cardinality() |
2810 | that estimates the number of expected rows in r. It is assumed that param |
2811 | is the data structure containing the descriptors of pseudo-indexes that |
2812 | has been built to perform range analysis of the range conditions imposed |
2813 | on the columns used in the processed query, while idx is the index of the |
2814 | descriptor created in 'param' exactly for the column for which 'tree' |
2815 | has been built by the range optimizer. |
2816 | |
2817 | RETURN |
2818 | the number of rows in the retrieved ranges |
2819 | */ |
2820 | |
2821 | static |
2822 | double records_in_column_ranges(PARAM *param, uint idx, |
2823 | SEL_ARG *tree) |
2824 | { |
2825 | SEL_ARG_RANGE_SEQ seq; |
2826 | KEY_MULTI_RANGE range; |
2827 | range_seq_t seq_it; |
2828 | double rows; |
2829 | Field *field; |
2830 | uint flags= 0; |
2831 | double total_rows= 0; |
2832 | RANGE_SEQ_IF seq_if = {NULL, sel_arg_range_seq_init, |
2833 | sel_arg_range_seq_next, 0, 0}; |
2834 | |
2835 | /* Handle cases when we don't have a valid non-empty list of range */ |
2836 | if (!tree) |
2837 | return DBL_MAX; |
2838 | if (tree->type == SEL_ARG::IMPOSSIBLE) |
2839 | return (0L); |
2840 | |
2841 | field= tree->field; |
2842 | |
2843 | seq.keyno= idx; |
2844 | seq.real_keyno= MAX_KEY; |
2845 | seq.param= param; |
2846 | seq.start= tree; |
2847 | |
2848 | seq_it= seq_if.init((void *) &seq, 0, flags); |
2849 | |
2850 | while (!seq_if.next(seq_it, &range)) |
2851 | { |
2852 | key_range *min_endp, *max_endp; |
2853 | min_endp= range.start_key.length? &range.start_key : NULL; |
2854 | max_endp= range.end_key.length? &range.end_key : NULL; |
2855 | rows= get_column_range_cardinality(field, min_endp, max_endp, |
2856 | range.range_flag); |
2857 | if (DBL_MAX == rows) |
2858 | { |
2859 | total_rows= DBL_MAX; |
2860 | break; |
2861 | } |
2862 | total_rows += rows; |
2863 | } |
2864 | return total_rows; |
2865 | } |
2866 | |
2867 | |
2868 | /* |
2869 | Calculate the selectivity of the condition imposed on the rows of a table |
2870 | |
2871 | SYNOPSIS |
2872 | calculate_cond_selectivity_for_table() |
2873 | thd the context handle |
2874 | table the table of interest |
2875 | cond conditions imposed on the rows of the table |
2876 | |
2877 | DESCRIPTION |
2878 | This function calculates the selectivity of range conditions cond imposed |
2879 | on the rows of 'table' in the processed query. |
2880 | The calculated selectivity is assigned to the field table->cond_selectivity. |
2881 | |
2882 | Selectivity is calculated as a product of selectivities imposed by: |
2883 | |
2884 | 1. possible range accesses. (if multiple range accesses use the same |
2885 | restrictions on the same field, we make adjustments for that) |
2886 | 2. Sargable conditions on fields for which we have column statistics (if |
2887 | a field is used in a possible range access, we assume that selectivity |
2888 | is already provided by the range access' estimates) |
2889 | 3. Reading a few records from the table pages and checking the condition |
2890 | selectivity (this is used for conditions like "column LIKE '%val%'" |
2891 | where approaches #1 and #2 do not provide selectivity data). |
2892 | |
2893 | NOTE |
2894 | Currently the selectivities of range conditions over different columns are |
2895 | considered independent. |
2896 | |
2897 | RETURN |
2898 | FALSE on success |
2899 | TRUE otherwise |
2900 | */ |
2901 | |
2902 | bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) |
2903 | { |
2904 | uint keynr; |
2905 | uint max_quick_key_parts= 0; |
2906 | MY_BITMAP *used_fields= &table->cond_set; |
2907 | double table_records= (double)table->stat_records(); |
2908 | DBUG_ENTER("calculate_cond_selectivity_for_table" ); |
2909 | |
2910 | table->cond_selectivity= 1.0; |
2911 | |
2912 | if (!*cond || table_records == 0) |
2913 | DBUG_RETURN(FALSE); |
2914 | |
2915 | if (table->pos_in_table_list->schema_table) |
2916 | DBUG_RETURN(FALSE); |
2917 | |
2918 | MY_BITMAP handled_columns; |
2919 | my_bitmap_map* buf; |
2920 | if (!(buf= (my_bitmap_map*)thd->alloc(table->s->column_bitmap_size))) |
2921 | DBUG_RETURN(TRUE); |
2922 | my_bitmap_init(&handled_columns, buf, table->s->fields, FALSE); |
2923 | |
2924 | /* |
2925 | Calculate the selectivity of the range conditions supported by indexes. |
2926 | |
2927 | First, take into account possible range accesses. |
2928 | range access estimates are the most precise, we prefer them to any other |
2929 | estimate sources. |
2930 | */ |
2931 | |
2932 | for (keynr= 0; keynr < table->s->keys; keynr++) |
2933 | { |
2934 | if (table->quick_keys.is_set(keynr)) |
2935 | set_if_bigger(max_quick_key_parts, table->quick_key_parts[keynr]); |
2936 | } |
2937 | |
2938 | /* |
2939 | Walk through all indexes, indexes where range access uses more keyparts |
2940 | go first. |
2941 | */ |
2942 | for (uint quick_key_parts= max_quick_key_parts; |
2943 | quick_key_parts; quick_key_parts--) |
2944 | { |
2945 | for (keynr= 0; keynr < table->s->keys; keynr++) |
2946 | { |
2947 | if (table->quick_keys.is_set(keynr) && |
2948 | table->quick_key_parts[keynr] == quick_key_parts) |
2949 | { |
2950 | uint i; |
2951 | uint used_key_parts= table->quick_key_parts[keynr]; |
2952 | double quick_cond_selectivity= table->quick_rows[keynr] / |
2953 | table_records; |
2954 | KEY *key_info= table->key_info + keynr; |
2955 | KEY_PART_INFO* key_part= key_info->key_part; |
2956 | /* |
2957 | Suppose, there are range conditions on two keys |
2958 | KEY1 (col1, col2) |
2959 | KEY2 (col3, col2) |
2960 | |
2961 | we don't want to count selectivity of condition on col2 twice. |
2962 | |
2963 | First, find the longest key prefix that's made of columns whose |
2964 | selectivity wasn't already accounted for. |
2965 | */ |
2966 | for (i= 0; i < used_key_parts; i++, key_part++) |
2967 | { |
2968 | if (bitmap_is_set(&handled_columns, key_part->fieldnr-1)) |
2969 | break; |
2970 | bitmap_set_bit(&handled_columns, key_part->fieldnr-1); |
2971 | } |
2972 | if (i) |
2973 | { |
2974 | double UNINIT_VAR(selectivity_mult); |
2975 | |
2976 | /* |
2977 | There is at least 1-column prefix of columns whose selectivity has |
2978 | not yet been accounted for. |
2979 | */ |
2980 | table->cond_selectivity*= quick_cond_selectivity; |
2981 | if (i != used_key_parts) |
2982 | { |
2983 | /* |
2984 | Range access got us estimate for #used_key_parts. |
2985 | We need estimate for #(i-1) key parts. |
2986 | */ |
2987 | double f1= key_info->actual_rec_per_key(i-1); |
2988 | double f2= key_info->actual_rec_per_key(i); |
2989 | if (f1 > 0 && f2 > 0) |
2990 | selectivity_mult= f1 / f2; |
2991 | else |
2992 | { |
2993 | /* |
2994 | No statistics available, assume the selectivity is proportional |
2995 | to the number of key parts. |
2996 | (i=0 means 1 keypart, i=1 means 2 keyparts, so use i+1) |
2997 | */ |
2998 | selectivity_mult= ((double)(i+1)) / i; |
2999 | } |
3000 | table->cond_selectivity*= selectivity_mult; |
3001 | } |
3002 | /* |
3003 | We need to set selectivity for fields supported by indexes. |
3004 | For single-component indexes and for some first components |
3005 | of other indexes we do it here. For the remaining fields |
3006 | we do it later in this function, in the same way as for the |
3007 | fields not used in any indexes. |
3008 | */ |
3009 | if (i == 1) |
3010 | { |
3011 | uint fieldnr= key_info->key_part[0].fieldnr; |
3012 | table->field[fieldnr-1]->cond_selectivity= quick_cond_selectivity; |
3013 | if (i != used_key_parts) |
3014 | table->field[fieldnr-1]->cond_selectivity*= selectivity_mult; |
3015 | bitmap_clear_bit(used_fields, fieldnr-1); |
3016 | } |
3017 | } |
3018 | } |
3019 | } |
3020 | } |
3021 | |
3022 | /* |
3023 | Second step: calculate the selectivity of the range conditions not |
3024 | supported by any index and selectivity of the range condition |
3025 | over the fields whose selectivity has not been set yet. |
3026 | */ |
3027 | |
3028 | if (thd->variables.optimizer_use_condition_selectivity > 2 && |
3029 | !bitmap_is_clear_all(used_fields)) |
3030 | { |
3031 | PARAM param; |
3032 | MEM_ROOT alloc; |
3033 | SEL_TREE *tree; |
3034 | double rows; |
3035 | |
3036 | init_sql_alloc(&alloc, "calculate_cond_selectivity_for_table" , |
3037 | thd->variables.range_alloc_block_size, 0, |
3038 | MYF(MY_THREAD_SPECIFIC)); |
3039 | param.thd= thd; |
3040 | param.mem_root= &alloc; |
3041 | param.old_root= thd->mem_root; |
3042 | param.table= table; |
3043 | param.is_ror_scan= FALSE; |
3044 | param.remove_false_where_parts= true; |
3045 | |
3046 | if (create_key_parts_for_pseudo_indexes(¶m, used_fields)) |
3047 | goto free_alloc; |
3048 | |
3049 | param.prev_tables= param.read_tables= 0; |
3050 | param.current_table= table->map; |
3051 | param.using_real_indexes= FALSE; |
3052 | param.real_keynr[0]= 0; |
3053 | param.alloced_sel_args= 0; |
3054 | |
3055 | thd->no_errors=1; |
3056 | |
3057 | tree= cond[0]->get_mm_tree(¶m, cond); |
3058 | |
3059 | if (!tree) |
3060 | goto free_alloc; |
3061 | |
3062 | table->reginfo.impossible_range= 0; |
3063 | if (tree->type == SEL_TREE::IMPOSSIBLE) |
3064 | { |
3065 | rows= 0; |
3066 | table->reginfo.impossible_range= 1; |
3067 | goto free_alloc; |
3068 | } |
3069 | else if (tree->type == SEL_TREE::ALWAYS) |
3070 | { |
3071 | rows= table_records; |
3072 | goto free_alloc; |
3073 | } |
3074 | else if (tree->type == SEL_TREE::MAYBE) |
3075 | { |
3076 | rows= table_records; |
3077 | goto free_alloc; |
3078 | } |
3079 | |
3080 | for (uint idx= 0; idx < param.keys; idx++) |
3081 | { |
3082 | SEL_ARG *key= tree->keys[idx]; |
3083 | if (key) |
3084 | { |
3085 | if (key->type == SEL_ARG::IMPOSSIBLE) |
3086 | { |
3087 | rows= 0; |
3088 | table->reginfo.impossible_range= 1; |
3089 | goto free_alloc; |
3090 | } |
3091 | else |
3092 | { |
3093 | rows= records_in_column_ranges(¶m, idx, key); |
3094 | if (rows != DBL_MAX) |
3095 | key->field->cond_selectivity= rows/table_records; |
3096 | } |
3097 | } |
3098 | } |
3099 | |
3100 | for (Field **field_ptr= table->field; *field_ptr; field_ptr++) |
3101 | { |
3102 | Field *table_field= *field_ptr; |
3103 | if (bitmap_is_set(used_fields, table_field->field_index) && |
3104 | table_field->cond_selectivity < 1.0) |
3105 | { |
3106 | if (!bitmap_is_set(&handled_columns, table_field->field_index)) |
3107 | table->cond_selectivity*= table_field->cond_selectivity; |
3108 | } |
3109 | } |
3110 | |
3111 | free_alloc: |
3112 | thd->no_errors= 0; |
3113 | thd->mem_root= param.old_root; |
3114 | free_root(&alloc, MYF(0)); |
3115 | |
3116 | } |
3117 | |
3118 | bitmap_union(used_fields, &handled_columns); |
3119 | |
3120 | /* Check if we can improve selectivity estimates by using sampling */ |
3121 | ulong check_rows= |
3122 | MY_MIN(thd->variables.optimizer_selectivity_sampling_limit, |
3123 | (ulong) (table_records * SELECTIVITY_SAMPLING_SHARE)); |
3124 | if (*cond && check_rows > SELECTIVITY_SAMPLING_THRESHOLD && |
3125 | thd->variables.optimizer_use_condition_selectivity > 4) |
3126 | { |
3127 | find_selective_predicates_list_processor_data *dt= |
3128 | (find_selective_predicates_list_processor_data *) |
3129 | alloc_root(thd->mem_root, |
3130 | sizeof(find_selective_predicates_list_processor_data)); |
3131 | if (!dt) |
3132 | DBUG_RETURN(TRUE); |
3133 | dt->list.empty(); |
3134 | dt->table= table; |
3135 | if ((*cond)->walk(&Item::find_selective_predicates_list_processor, 0, dt)) |
3136 | DBUG_RETURN(TRUE); |
3137 | if (dt->list.elements > 0) |
3138 | { |
3139 | check_rows= check_selectivity(thd, check_rows, table, &dt->list); |
3140 | if (check_rows > SELECTIVITY_SAMPLING_THRESHOLD) |
3141 | { |
3142 | COND_STATISTIC *stat; |
3143 | List_iterator_fast<COND_STATISTIC> it(dt->list); |
3144 | double examined_rows= check_rows; |
3145 | while ((stat= it++)) |
3146 | { |
3147 | if (!stat->positive) |
3148 | { |
3149 | DBUG_PRINT("info" , ("To avoid 0 assigned 1 to the counter" )); |
3150 | stat->positive= 1; // avoid 0 |
3151 | } |
3152 | DBUG_PRINT("info" , ("The predicate selectivity : %g" , |
3153 | (double)stat->positive / examined_rows)); |
3154 | double selectivity= ((double)stat->positive) / examined_rows; |
3155 | table->cond_selectivity*= selectivity; |
3156 | /* |
3157 | If a field is involved then we register its selectivity in case |
3158 | there in an equality with the field. |
3159 | For example in case |
3160 | t1.a LIKE "%bla%" and t1.a = t2.b |
3161 | the selectivity we have found could be used also for t2. |
3162 | */ |
3163 | if (stat->field_arg) |
3164 | { |
3165 | stat->field_arg->cond_selectivity*= selectivity; |
3166 | |
3167 | if (stat->field_arg->next_equal_field) |
3168 | { |
3169 | for (Field *next_field= stat->field_arg->next_equal_field; |
3170 | next_field != stat->field_arg; |
3171 | next_field= next_field->next_equal_field) |
3172 | { |
3173 | next_field->cond_selectivity*= selectivity; |
3174 | next_field->table->cond_selectivity*= selectivity; |
3175 | } |
3176 | } |
3177 | } |
3178 | } |
3179 | |
3180 | } |
3181 | /* This list and its elements put to mem_root so should not be freed */ |
3182 | table->cond_selectivity_sampling_explain= &dt->list; |
3183 | } |
3184 | } |
3185 | |
3186 | DBUG_RETURN(FALSE); |
3187 | } |
3188 | |
3189 | /**************************************************************************** |
3190 | * Condition selectivity code ends |
3191 | ****************************************************************************/ |
3192 | |
3193 | /**************************************************************************** |
3194 | * Partition pruning module |
3195 | ****************************************************************************/ |
3196 | |
3197 | /* |
3198 | Store field key image to table record |
3199 | |
3200 | SYNOPSIS |
3201 | store_key_image_to_rec() |
3202 | field Field which key image should be stored |
3203 | ptr Field value in key format |
3204 | len Length of the value, in bytes |
3205 | |
3206 | ATTENTION |
3207 | len is the length of the value not counting the NULL-byte (at the same |
3208 | time, ptr points to the key image, which starts with NULL-byte for |
3209 | nullable columns) |
3210 | |
3211 | DESCRIPTION |
3212 | Copy the field value from its key image to the table record. The source |
3213 | is the value in key image format, occupying len bytes in buffer pointed |
3214 | by ptr. The destination is table record, in "field value in table record" |
3215 | format. |
3216 | */ |
3217 | |
3218 | void store_key_image_to_rec(Field *field, uchar *ptr, uint len) |
3219 | { |
3220 | /* Do the same as print_key() does */ |
3221 | my_bitmap_map *old_map; |
3222 | |
3223 | if (field->real_maybe_null()) |
3224 | { |
3225 | if (*ptr) |
3226 | { |
3227 | field->set_null(); |
3228 | return; |
3229 | } |
3230 | field->set_notnull(); |
3231 | ptr++; |
3232 | } |
3233 | old_map= dbug_tmp_use_all_columns(field->table, |
3234 | field->table->write_set); |
3235 | field->set_key_image(ptr, len); |
3236 | dbug_tmp_restore_column_map(field->table->write_set, old_map); |
3237 | } |
3238 | |
3239 | #ifdef WITH_PARTITION_STORAGE_ENGINE |
3240 | |
3241 | /* |
3242 | PartitionPruningModule |
3243 | |
3244 | This part of the code does partition pruning. Partition pruning solves the |
3245 | following problem: given a query over partitioned tables, find partitions |
3246 | that we will not need to access (i.e. partitions that we can assume to be |
3247 | empty) when executing the query. |
3248 | The set of partitions to prune doesn't depend on which query execution |
3249 | plan will be used to execute the query. |
3250 | |
3251 | HOW IT WORKS |
3252 | |
3253 | Partition pruning module makes use of RangeAnalysisModule. The following |
3254 | examples show how the problem of partition pruning can be reduced to the |
3255 | range analysis problem: |
3256 | |
3257 | EXAMPLE 1 |
3258 | Consider a query: |
3259 | |
3260 | SELECT * FROM t1 WHERE (t1.a < 5 OR t1.a = 10) AND t1.a > 3 AND t1.b='z' |
3261 | |
3262 | where table t1 is partitioned using PARTITION BY RANGE(t1.a). An apparent |
3263 | way to find the used (i.e. not pruned away) partitions is as follows: |
3264 | |
3265 | 1. analyze the WHERE clause and extract the list of intervals over t1.a |
3266 | for the above query we will get this list: {(3 < t1.a < 5), (t1.a=10)} |
3267 | |
3268 | 2. for each interval I |
3269 | { |
3270 | find partitions that have non-empty intersection with I; |
3271 | mark them as used; |
3272 | } |
3273 | |
3274 | EXAMPLE 2 |
3275 | Suppose the table is partitioned by HASH(part_func(t1.a, t1.b)). Then |
3276 | we need to: |
3277 | |
3278 | 1. Analyze the WHERE clause and get a list of intervals over (t1.a, t1.b). |
3279 | The list of intervals we'll obtain will look like this: |
3280 | ((t1.a, t1.b) = (1,'foo')), |
3281 | ((t1.a, t1.b) = (2,'bar')), |
3282 | ((t1,a, t1.b) > (10,'zz')) |
3283 | |
3284 | 2. for each interval I |
3285 | { |
3286 | if (the interval has form "(t1.a, t1.b) = (const1, const2)" ) |
3287 | { |
3288 | calculate HASH(part_func(t1.a, t1.b)); |
3289 | find which partition has records with this hash value and mark |
3290 | it as used; |
3291 | } |
3292 | else |
3293 | { |
3294 | mark all partitions as used; |
3295 | break; |
3296 | } |
3297 | } |
3298 | |
3299 | For both examples the step #1 is exactly what RangeAnalysisModule could |
3300 | be used to do, if it was provided with appropriate index description |
3301 | (array of KEY_PART structures). |
3302 | In example #1, we need to provide it with description of index(t1.a), |
3303 | in example #2, we need to provide it with description of index(t1.a, t1.b). |
3304 | |
3305 | These index descriptions are further called "partitioning index |
3306 | descriptions". Note that it doesn't matter if such indexes really exist, |
3307 | as range analysis module only uses the description. |
3308 | |
3309 | Putting it all together, partitioning module works as follows: |
3310 | |
3311 | prune_partitions() { |
3312 | call create_partition_index_description(); |
3313 | |
3314 | call get_mm_tree(); // invoke the RangeAnalysisModule |
3315 | |
3316 | // analyze the obtained interval list and get used partitions |
3317 | call find_used_partitions(); |
3318 | } |
3319 | |
3320 | */ |
3321 | |
3322 | struct st_part_prune_param; |
3323 | struct st_part_opt_info; |
3324 | |
3325 | typedef void (*mark_full_part_func)(partition_info*, uint32); |
3326 | |
3327 | /* |
3328 | Partition pruning operation context |
3329 | */ |
3330 | typedef struct st_part_prune_param |
3331 | { |
3332 | RANGE_OPT_PARAM range_param; /* Range analyzer parameters */ |
3333 | |
3334 | /*************************************************************** |
3335 | Following fields are filled in based solely on partitioning |
3336 | definition and not modified after that: |
3337 | **************************************************************/ |
3338 | partition_info *part_info; /* Copy of table->part_info */ |
3339 | /* Function to get partition id from partitioning fields only */ |
3340 | get_part_id_func get_top_partition_id_func; |
3341 | /* Function to mark a partition as used (w/all subpartitions if they exist)*/ |
3342 | mark_full_part_func mark_full_partition_used; |
3343 | |
3344 | /* Partitioning 'index' description, array of key parts */ |
3345 | KEY_PART *key; |
3346 | |
3347 | /* |
3348 | Number of fields in partitioning 'index' definition created for |
3349 | partitioning (0 if partitioning 'index' doesn't include partitioning |
3350 | fields) |
3351 | */ |
3352 | uint part_fields; |
3353 | uint subpart_fields; /* Same as above for subpartitioning */ |
3354 | |
3355 | /* |
3356 | Number of the last partitioning field keypart in the index, or -1 if |
3357 | partitioning index definition doesn't include partitioning fields. |
3358 | */ |
3359 | int last_part_partno; |
3360 | int last_subpart_partno; /* Same as above for supartitioning */ |
3361 | |
3362 | /* |
3363 | is_part_keypart[i] == MY_TEST(keypart #i in partitioning index is a member |
3364 | used in partitioning) |
3365 | Used to maintain current values of cur_part_fields and cur_subpart_fields |
3366 | */ |
3367 | my_bool *is_part_keypart; |
3368 | /* Same as above for subpartitioning */ |
3369 | my_bool *is_subpart_keypart; |
3370 | |
3371 | my_bool ignore_part_fields; /* Ignore rest of partioning fields */ |
3372 | |
3373 | /*************************************************************** |
3374 | Following fields form find_used_partitions() recursion context: |
3375 | **************************************************************/ |
3376 | SEL_ARG **arg_stack; /* "Stack" of SEL_ARGs */ |
3377 | SEL_ARG **arg_stack_end; /* Top of the stack */ |
3378 | /* Number of partitioning fields for which we have a SEL_ARG* in arg_stack */ |
3379 | uint cur_part_fields; |
3380 | /* Same as cur_part_fields, but for subpartitioning */ |
3381 | uint cur_subpart_fields; |
3382 | |
3383 | /* Iterator to be used to obtain the "current" set of used partitions */ |
3384 | PARTITION_ITERATOR part_iter; |
3385 | |
3386 | /* Initialized bitmap of num_subparts size */ |
3387 | MY_BITMAP subparts_bitmap; |
3388 | |
3389 | uchar *cur_min_key; |
3390 | uchar *cur_max_key; |
3391 | |
3392 | uint cur_min_flag, cur_max_flag; |
3393 | } PART_PRUNE_PARAM; |
3394 | |
3395 | static bool create_partition_index_description(PART_PRUNE_PARAM *prune_par); |
3396 | static int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree); |
3397 | static int find_used_partitions_imerge(PART_PRUNE_PARAM *ppar, |
3398 | SEL_IMERGE *imerge); |
3399 | static int find_used_partitions_imerge_list(PART_PRUNE_PARAM *ppar, |
3400 | List<SEL_IMERGE> &merges); |
3401 | static void mark_all_partitions_as_used(partition_info *part_info); |
3402 | |
3403 | #ifndef DBUG_OFF |
3404 | static void print_partitioning_index(KEY_PART *parts, KEY_PART *parts_end); |
3405 | static void dbug_print_field(Field *field); |
3406 | static void dbug_print_segment_range(SEL_ARG *arg, KEY_PART *part); |
3407 | static void dbug_print_singlepoint_range(SEL_ARG **start, uint num); |
3408 | #endif |
3409 | |
3410 | |
3411 | /** |
3412 | Perform partition pruning for a given table and condition. |
3413 | |
3414 | @param thd Thread handle |
3415 | @param table Table to perform partition pruning for |
3416 | @param pprune_cond Condition to use for partition pruning |
3417 | |
3418 | @note This function assumes that lock_partitions are setup when it |
3419 | is invoked. The function analyzes the condition, finds partitions that |
3420 | need to be used to retrieve the records that match the condition, and |
3421 | marks them as used by setting appropriate bit in part_info->read_partitions |
3422 | In the worst case all partitions are marked as used. If the table is not |
3423 | yet locked, it will also unset bits in part_info->lock_partitions that is |
3424 | not set in read_partitions. |
3425 | |
3426 | This function returns promptly if called for non-partitioned table. |
3427 | |
3428 | @return Operation status |
3429 | @retval true Failure |
3430 | @retval false Success |
3431 | */ |
3432 | |
3433 | bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) |
3434 | { |
3435 | bool retval= FALSE; |
3436 | partition_info *part_info = table->part_info; |
3437 | DBUG_ENTER("prune_partitions" ); |
3438 | |
3439 | if (!part_info) |
3440 | DBUG_RETURN(FALSE); /* not a partitioned table */ |
3441 | |
3442 | if (!pprune_cond) |
3443 | { |
3444 | mark_all_partitions_as_used(part_info); |
3445 | DBUG_RETURN(FALSE); |
3446 | } |
3447 | |
3448 | PART_PRUNE_PARAM prune_param; |
3449 | MEM_ROOT alloc; |
3450 | RANGE_OPT_PARAM *range_par= &prune_param.range_param; |
3451 | my_bitmap_map *old_sets[2]; |
3452 | |
3453 | prune_param.part_info= part_info; |
3454 | init_sql_alloc(&alloc, "prune_partitions" , |
3455 | thd->variables.range_alloc_block_size, 0, |
3456 | MYF(MY_THREAD_SPECIFIC)); |
3457 | range_par->mem_root= &alloc; |
3458 | range_par->old_root= thd->mem_root; |
3459 | |
3460 | if (create_partition_index_description(&prune_param)) |
3461 | { |
3462 | mark_all_partitions_as_used(part_info); |
3463 | free_root(&alloc,MYF(0)); // Return memory & allocator |
3464 | DBUG_RETURN(FALSE); |
3465 | } |
3466 | |
3467 | dbug_tmp_use_all_columns(table, old_sets, |
3468 | table->read_set, table->write_set); |
3469 | range_par->thd= thd; |
3470 | range_par->table= table; |
3471 | /* range_par->cond doesn't need initialization */ |
3472 | range_par->prev_tables= range_par->read_tables= 0; |
3473 | range_par->current_table= table->map; |
3474 | /* It should be possible to switch the following ON: */ |
3475 | range_par->remove_false_where_parts= false; |
3476 | |
3477 | range_par->keys= 1; // one index |
3478 | range_par->using_real_indexes= FALSE; |
3479 | range_par->remove_jump_scans= FALSE; |
3480 | range_par->real_keynr[0]= 0; |
3481 | range_par->alloced_sel_args= 0; |
3482 | |
3483 | thd->no_errors=1; // Don't warn about NULL |
3484 | thd->mem_root=&alloc; |
3485 | |
3486 | bitmap_clear_all(&part_info->read_partitions); |
3487 | |
3488 | prune_param.key= prune_param.range_param.key_parts; |
3489 | SEL_TREE *tree; |
3490 | int res; |
3491 | |
3492 | tree= pprune_cond->get_mm_tree(range_par, &pprune_cond); |
3493 | if (!tree) |
3494 | goto all_used; |
3495 | |
3496 | if (tree->type == SEL_TREE::IMPOSSIBLE) |
3497 | { |
3498 | retval= TRUE; |
3499 | goto end; |
3500 | } |
3501 | |
3502 | if (tree->type != SEL_TREE::KEY && tree->type != SEL_TREE::KEY_SMALLER) |
3503 | goto all_used; |
3504 | |
3505 | if (tree->merges.is_empty()) |
3506 | { |
3507 | /* Range analysis has produced a single list of intervals. */ |
3508 | prune_param.arg_stack_end= prune_param.arg_stack; |
3509 | prune_param.cur_part_fields= 0; |
3510 | prune_param.cur_subpart_fields= 0; |
3511 | |
3512 | prune_param.cur_min_key= prune_param.range_param.min_key; |
3513 | prune_param.cur_max_key= prune_param.range_param.max_key; |
3514 | prune_param.cur_min_flag= prune_param.cur_max_flag= 0; |
3515 | |
3516 | init_all_partitions_iterator(part_info, &prune_param.part_iter); |
3517 | if (!tree->keys[0] || (-1 == (res= find_used_partitions(&prune_param, |
3518 | tree->keys[0])))) |
3519 | goto all_used; |
3520 | } |
3521 | else |
3522 | { |
3523 | if (tree->merges.elements == 1) |
3524 | { |
3525 | /* |
3526 | Range analysis has produced a "merge" of several intervals lists, a |
3527 | SEL_TREE that represents an expression in form |
3528 | sel_imerge = (tree1 OR tree2 OR ... OR treeN) |
3529 | that cannot be reduced to one tree. This can only happen when |
3530 | partitioning index has several keyparts and the condition is OR of |
3531 | conditions that refer to different key parts. For example, we'll get |
3532 | here for "partitioning_field=const1 OR subpartitioning_field=const2" |
3533 | */ |
3534 | if (-1 == (res= find_used_partitions_imerge(&prune_param, |
3535 | tree->merges.head()))) |
3536 | goto all_used; |
3537 | } |
3538 | else |
3539 | { |
3540 | /* |
3541 | Range analysis has produced a list of several imerges, i.e. a |
3542 | structure that represents a condition in form |
3543 | imerge_list= (sel_imerge1 AND sel_imerge2 AND ... AND sel_imergeN) |
3544 | This is produced for complicated WHERE clauses that range analyzer |
3545 | can't really analyze properly. |
3546 | */ |
3547 | if (-1 == (res= find_used_partitions_imerge_list(&prune_param, |
3548 | tree->merges))) |
3549 | goto all_used; |
3550 | } |
3551 | } |
3552 | |
3553 | /* |
3554 | res == 0 => no used partitions => retval=TRUE |
3555 | res == 1 => some used partitions => retval=FALSE |
3556 | res == -1 - we jump over this line to all_used: |
3557 | */ |
3558 | retval= MY_TEST(!res); |
3559 | goto end; |
3560 | |
3561 | all_used: |
3562 | retval= FALSE; // some partitions are used |
3563 | mark_all_partitions_as_used(prune_param.part_info); |
3564 | end: |
3565 | dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets); |
3566 | thd->no_errors=0; |
3567 | thd->mem_root= range_par->old_root; |
3568 | free_root(&alloc,MYF(0)); // Return memory & allocator |
3569 | /* |
3570 | Must be a subset of the locked partitions. |
3571 | lock_partitions contains the partitions marked by explicit partition |
3572 | selection (... t PARTITION (pX) ...) and we must only use partitions |
3573 | within that set. |
3574 | */ |
3575 | bitmap_intersect(&prune_param.part_info->read_partitions, |
3576 | &prune_param.part_info->lock_partitions); |
3577 | /* |
3578 | If not yet locked, also prune partitions to lock if not UPDATEing |
3579 | partition key fields. This will also prune lock_partitions if we are under |
3580 | LOCK TABLES, so prune away calls to start_stmt(). |
3581 | TODO: enhance this prune locking to also allow pruning of |
3582 | 'UPDATE t SET part_key = const WHERE cond_is_prunable' so it adds |
3583 | a lock for part_key partition. |
3584 | */ |
3585 | if (table->file->get_lock_type() == F_UNLCK && |
3586 | !partition_key_modified(table, table->write_set)) |
3587 | { |
3588 | bitmap_copy(&prune_param.part_info->lock_partitions, |
3589 | &prune_param.part_info->read_partitions); |
3590 | } |
3591 | if (bitmap_is_clear_all(&(prune_param.part_info->read_partitions))) |
3592 | { |
3593 | table->all_partitions_pruned_away= true; |
3594 | retval= TRUE; |
3595 | } |
3596 | DBUG_RETURN(retval); |
3597 | } |
3598 | |
3599 | |
3600 | /* |
3601 | For SEL_ARG* array, store sel_arg->min values into table record buffer |
3602 | |
3603 | SYNOPSIS |
3604 | store_selargs_to_rec() |
3605 | ppar Partition pruning context |
3606 | start Array of SEL_ARG* for which the minimum values should be stored |
3607 | num Number of elements in the array |
3608 | |
3609 | DESCRIPTION |
3610 | For each SEL_ARG* interval in the specified array, store the left edge |
3611 | field value (sel_arg->min, key image format) into the table record. |
3612 | */ |
3613 | |
3614 | static void store_selargs_to_rec(PART_PRUNE_PARAM *ppar, SEL_ARG **start, |
3615 | int num) |
3616 | { |
3617 | KEY_PART *parts= ppar->range_param.key_parts; |
3618 | for (SEL_ARG **end= start + num; start != end; start++) |
3619 | { |
3620 | SEL_ARG *sel_arg= (*start); |
3621 | store_key_image_to_rec(sel_arg->field, sel_arg->min_value, |
3622 | parts[sel_arg->part].length); |
3623 | } |
3624 | } |
3625 | |
3626 | |
3627 | /* Mark a partition as used in the case when there are no subpartitions */ |
3628 | static void mark_full_partition_used_no_parts(partition_info* part_info, |
3629 | uint32 part_id) |
3630 | { |
3631 | DBUG_ENTER("mark_full_partition_used_no_parts" ); |
3632 | DBUG_PRINT("enter" , ("Mark partition %u as used" , part_id)); |
3633 | bitmap_set_bit(&part_info->read_partitions, part_id); |
3634 | DBUG_VOID_RETURN; |
3635 | } |
3636 | |
3637 | |
3638 | /* Mark a partition as used in the case when there are subpartitions */ |
3639 | static void mark_full_partition_used_with_parts(partition_info *part_info, |
3640 | uint32 part_id) |
3641 | { |
3642 | uint32 start= part_id * part_info->num_subparts; |
3643 | uint32 end= start + part_info->num_subparts; |
3644 | DBUG_ENTER("mark_full_partition_used_with_parts" ); |
3645 | |
3646 | for (; start != end; start++) |
3647 | { |
3648 | DBUG_PRINT("info" , ("1:Mark subpartition %u as used" , start)); |
3649 | bitmap_set_bit(&part_info->read_partitions, start); |
3650 | } |
3651 | DBUG_VOID_RETURN; |
3652 | } |
3653 | |
3654 | /* |
3655 | Find the set of used partitions for List<SEL_IMERGE> |
3656 | SYNOPSIS |
3657 | find_used_partitions_imerge_list |
3658 | ppar Partition pruning context. |
3659 | key_tree Intervals tree to perform pruning for. |
3660 | |
3661 | DESCRIPTION |
3662 | List<SEL_IMERGE> represents "imerge1 AND imerge2 AND ...". |
3663 | The set of used partitions is an intersection of used partitions sets |
3664 | for imerge_{i}. |
3665 | We accumulate this intersection in a separate bitmap. |
3666 | |
3667 | RETURN |
3668 | See find_used_partitions() |
3669 | */ |
3670 | |
3671 | static int find_used_partitions_imerge_list(PART_PRUNE_PARAM *ppar, |
3672 | List<SEL_IMERGE> &merges) |
3673 | { |
3674 | MY_BITMAP all_merges; |
3675 | uint bitmap_bytes; |
3676 | my_bitmap_map *bitmap_buf; |
3677 | uint n_bits= ppar->part_info->read_partitions.n_bits; |
3678 | bitmap_bytes= bitmap_buffer_size(n_bits); |
3679 | if (!(bitmap_buf= (my_bitmap_map*) alloc_root(ppar->range_param.mem_root, |
3680 | bitmap_bytes))) |
3681 | { |
3682 | /* |
3683 | Fallback, process just the first SEL_IMERGE. This can leave us with more |
3684 | partitions marked as used then actually needed. |
3685 | */ |
3686 | return find_used_partitions_imerge(ppar, merges.head()); |
3687 | } |
3688 | my_bitmap_init(&all_merges, bitmap_buf, n_bits, FALSE); |
3689 | bitmap_set_prefix(&all_merges, n_bits); |
3690 | |
3691 | List_iterator<SEL_IMERGE> it(merges); |
3692 | SEL_IMERGE *imerge; |
3693 | while ((imerge=it++)) |
3694 | { |
3695 | int res= find_used_partitions_imerge(ppar, imerge); |
3696 | if (!res) |
3697 | { |
3698 | /* no used partitions on one ANDed imerge => no used partitions at all */ |
3699 | return 0; |
3700 | } |
3701 | |
3702 | if (res != -1) |
3703 | bitmap_intersect(&all_merges, &ppar->part_info->read_partitions); |
3704 | |
3705 | |
3706 | if (bitmap_is_clear_all(&all_merges)) |
3707 | return 0; |
3708 | |
3709 | bitmap_clear_all(&ppar->part_info->read_partitions); |
3710 | } |
3711 | memcpy(ppar->part_info->read_partitions.bitmap, all_merges.bitmap, |
3712 | bitmap_bytes); |
3713 | return 1; |
3714 | } |
3715 | |
3716 | |
3717 | /* |
3718 | Find the set of used partitions for SEL_IMERGE structure |
3719 | SYNOPSIS |
3720 | find_used_partitions_imerge() |
3721 | ppar Partition pruning context. |
3722 | key_tree Intervals tree to perform pruning for. |
3723 | |
3724 | DESCRIPTION |
3725 | SEL_IMERGE represents "tree1 OR tree2 OR ...". The implementation is |
3726 | trivial - just use mark used partitions for each tree and bail out early |
3727 | if for some tree_{i} all partitions are used. |
3728 | |
3729 | RETURN |
3730 | See find_used_partitions(). |
3731 | */ |
3732 | |
3733 | static |
3734 | int find_used_partitions_imerge(PART_PRUNE_PARAM *ppar, SEL_IMERGE *imerge) |
3735 | { |
3736 | int res= 0; |
3737 | for (SEL_TREE **ptree= imerge->trees; ptree < imerge->trees_next; ptree++) |
3738 | { |
3739 | ppar->arg_stack_end= ppar->arg_stack; |
3740 | ppar->cur_part_fields= 0; |
3741 | ppar->cur_subpart_fields= 0; |
3742 | |
3743 | ppar->cur_min_key= ppar->range_param.min_key; |
3744 | ppar->cur_max_key= ppar->range_param.max_key; |
3745 | ppar->cur_min_flag= ppar->cur_max_flag= 0; |
3746 | |
3747 | init_all_partitions_iterator(ppar->part_info, &ppar->part_iter); |
3748 | SEL_ARG *key_tree= (*ptree)->keys[0]; |
3749 | if (!key_tree || (-1 == (res |= find_used_partitions(ppar, key_tree)))) |
3750 | return -1; |
3751 | } |
3752 | return res; |
3753 | } |
3754 | |
3755 | |
3756 | /* |
3757 | Collect partitioning ranges for the SEL_ARG tree and mark partitions as used |
3758 | |
3759 | SYNOPSIS |
3760 | find_used_partitions() |
3761 | ppar Partition pruning context. |
3762 | key_tree SEL_ARG range tree to perform pruning for |
3763 | |
3764 | DESCRIPTION |
3765 | This function |
3766 | * recursively walks the SEL_ARG* tree collecting partitioning "intervals" |
3767 | * finds the partitions one needs to use to get rows in these intervals |
3768 | * marks these partitions as used. |
3769 | The next session desribes the process in greater detail. |
3770 | |
3771 | IMPLEMENTATION |
3772 | TYPES OF RESTRICTIONS THAT WE CAN OBTAIN PARTITIONS FOR |
3773 | We can find out which [sub]partitions to use if we obtain restrictions on |
3774 | [sub]partitioning fields in the following form: |
3775 | 1. "partition_field1=const1 AND ... AND partition_fieldN=constN" |
3776 | 1.1 Same as (1) but for subpartition fields |
3777 | |
3778 | If partitioning supports interval analysis (i.e. partitioning is a |
3779 | function of a single table field, and partition_info:: |
3780 | get_part_iter_for_interval != NULL), then we can also use condition in |
3781 | this form: |
3782 | 2. "const1 <=? partition_field <=? const2" |
3783 | 2.1 Same as (2) but for subpartition_field |
3784 | |
3785 | INFERRING THE RESTRICTIONS FROM SEL_ARG TREE |
3786 | |
3787 | The below is an example of what SEL_ARG tree may represent: |
3788 | |
3789 | (start) |
3790 | | $ |
3791 | | Partitioning keyparts $ subpartitioning keyparts |
3792 | | $ |
3793 | | ... ... $ |
3794 | | | | $ |
3795 | | +---------+ +---------+ $ +-----------+ +-----------+ |
3796 | \-| par1=c1 |--| par2=c2 |-----| subpar1=c3|--| subpar2=c5| |
3797 | +---------+ +---------+ $ +-----------+ +-----------+ |
3798 | | $ | | |
3799 | | $ | +-----------+ |
3800 | | $ | | subpar2=c6| |
3801 | | $ | +-----------+ |
3802 | | $ | |
3803 | | $ +-----------+ +-----------+ |
3804 | | $ | subpar1=c4|--| subpar2=c8| |
3805 | | $ +-----------+ +-----------+ |
3806 | | $ |
3807 | | $ |
3808 | +---------+ $ +------------+ +------------+ |
3809 | | par1=c2 |------------------| subpar1=c10|--| subpar2=c12| |
3810 | +---------+ $ +------------+ +------------+ |
3811 | | $ |
3812 | ... $ |
3813 | |
3814 | The up-down connections are connections via SEL_ARG::left and |
3815 | SEL_ARG::right. A horizontal connection to the right is the |
3816 | SEL_ARG::next_key_part connection. |
3817 | |
3818 | find_used_partitions() traverses the entire tree via recursion on |
3819 | * SEL_ARG::next_key_part (from left to right on the picture) |
3820 | * SEL_ARG::left|right (up/down on the pic). Left-right recursion is |
3821 | performed for each depth level. |
3822 | |
3823 | Recursion descent on SEL_ARG::next_key_part is used to accumulate (in |
3824 | ppar->arg_stack) constraints on partitioning and subpartitioning fields. |
3825 | For the example in the above picture, one of stack states is: |
3826 | in find_used_partitions(key_tree = "subpar2=c5") (***) |
3827 | in find_used_partitions(key_tree = "subpar1=c3") |
3828 | in find_used_partitions(key_tree = "par2=c2") (**) |
3829 | in find_used_partitions(key_tree = "par1=c1") |
3830 | in prune_partitions(...) |
3831 | We apply partitioning limits as soon as possible, e.g. when we reach the |
3832 | depth (**), we find which partition(s) correspond to "par1=c1 AND par2=c2", |
3833 | and save them in ppar->part_iter. |
3834 | When we reach the depth (***), we find which subpartition(s) correspond to |
3835 | "subpar1=c3 AND subpar2=c5", and then mark appropriate subpartitions in |
3836 | appropriate subpartitions as used. |
3837 | |
3838 | It is possible that constraints on some partitioning fields are missing. |
3839 | For the above example, consider this stack state: |
3840 | in find_used_partitions(key_tree = "subpar2=c12") (***) |
3841 | in find_used_partitions(key_tree = "subpar1=c10") |
3842 | in find_used_partitions(key_tree = "par1=c2") |
3843 | in prune_partitions(...) |
3844 | Here we don't have constraints for all partitioning fields. Since we've |
3845 | never set the ppar->part_iter to contain used set of partitions, we use |
3846 | its default "all partitions" value. We get subpartition id for |
3847 | "subpar1=c3 AND subpar2=c5", and mark that subpartition as used in every |
3848 | partition. |
3849 | |
3850 | The inverse is also possible: we may get constraints on partitioning |
3851 | fields, but not constraints on subpartitioning fields. In that case, |
3852 | calls to find_used_partitions() with depth below (**) will return -1, |
3853 | and we will mark entire partition as used. |
3854 | |
3855 | TODO |
3856 | Replace recursion on SEL_ARG::left and SEL_ARG::right with a loop |
3857 | |
3858 | RETURN |
3859 | 1 OK, one or more [sub]partitions are marked as used. |
3860 | 0 The passed condition doesn't match any partitions |
3861 | -1 Couldn't infer any partition pruning "intervals" from the passed |
3862 | SEL_ARG* tree (which means that all partitions should be marked as |
3863 | used) Marking partitions as used is the responsibility of the caller. |
3864 | */ |
3865 | |
3866 | static |
3867 | int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree) |
3868 | { |
3869 | int res, left_res=0, right_res=0; |
3870 | int key_tree_part= (int)key_tree->part; |
3871 | bool set_full_part_if_bad_ret= FALSE; |
3872 | bool ignore_part_fields= ppar->ignore_part_fields; |
3873 | bool did_set_ignore_part_fields= FALSE; |
3874 | RANGE_OPT_PARAM *range_par= &(ppar->range_param); |
3875 | |
3876 | if (check_stack_overrun(range_par->thd, 3*STACK_MIN_SIZE, NULL)) |
3877 | return -1; |
3878 | |
3879 | if (key_tree->left != &null_element) |
3880 | { |
3881 | if (-1 == (left_res= find_used_partitions(ppar,key_tree->left))) |
3882 | return -1; |
3883 | } |
3884 | |
3885 | /* Push SEL_ARG's to stack to enable looking backwards as well */ |
3886 | ppar->cur_part_fields+= ppar->is_part_keypart[key_tree_part]; |
3887 | ppar->cur_subpart_fields+= ppar->is_subpart_keypart[key_tree_part]; |
3888 | *(ppar->arg_stack_end++)= key_tree; |
3889 | |
3890 | if (ignore_part_fields) |
3891 | { |
3892 | /* |
3893 | We come here when a condition on the first partitioning |
3894 | fields led to evaluating the partitioning condition |
3895 | (due to finding a condition of the type a < const or |
3896 | b > const). Thus we must ignore the rest of the |
3897 | partitioning fields but we still want to analyse the |
3898 | subpartitioning fields. |
3899 | */ |
3900 | if (key_tree->next_key_part) |
3901 | res= find_used_partitions(ppar, key_tree->next_key_part); |
3902 | else |
3903 | res= -1; |
3904 | goto pop_and_go_right; |
3905 | } |
3906 | |
3907 | if (key_tree->type == SEL_ARG::KEY_RANGE) |
3908 | { |
3909 | if (ppar->part_info->get_part_iter_for_interval && |
3910 | key_tree->part <= ppar->last_part_partno) |
3911 | { |
3912 | /* Collect left and right bound, their lengths and flags */ |
3913 | uchar *min_key= ppar->cur_min_key; |
3914 | uchar *max_key= ppar->cur_max_key; |
3915 | uchar *tmp_min_key= min_key; |
3916 | uchar *tmp_max_key= max_key; |
3917 | key_tree->store_min(ppar->key[key_tree->part].store_length, |
3918 | &tmp_min_key, ppar->cur_min_flag); |
3919 | key_tree->store_max(ppar->key[key_tree->part].store_length, |
3920 | &tmp_max_key, ppar->cur_max_flag); |
3921 | uint flag; |
3922 | if (key_tree->next_key_part && |
3923 | key_tree->next_key_part->part == key_tree->part+1 && |
3924 | key_tree->next_key_part->part <= ppar->last_part_partno && |
3925 | key_tree->next_key_part->type == SEL_ARG::KEY_RANGE) |
3926 | { |
3927 | /* |
3928 | There are more key parts for partition pruning to handle |
3929 | This mainly happens when the condition is an equality |
3930 | condition. |
3931 | */ |
3932 | if ((tmp_min_key - min_key) == (tmp_max_key - max_key) && |
3933 | (memcmp(min_key, max_key, (uint)(tmp_max_key - max_key)) == 0) && |
3934 | !key_tree->min_flag && !key_tree->max_flag) |
3935 | { |
3936 | /* Set 'parameters' */ |
3937 | ppar->cur_min_key= tmp_min_key; |
3938 | ppar->cur_max_key= tmp_max_key; |
3939 | uint save_min_flag= ppar->cur_min_flag; |
3940 | uint save_max_flag= ppar->cur_max_flag; |
3941 | |
3942 | ppar->cur_min_flag|= key_tree->min_flag; |
3943 | ppar->cur_max_flag|= key_tree->max_flag; |
3944 | |
3945 | res= find_used_partitions(ppar, key_tree->next_key_part); |
3946 | |
3947 | /* Restore 'parameters' back */ |
3948 | ppar->cur_min_key= min_key; |
3949 | ppar->cur_max_key= max_key; |
3950 | |
3951 | ppar->cur_min_flag= save_min_flag; |
3952 | ppar->cur_max_flag= save_max_flag; |
3953 | goto pop_and_go_right; |
3954 | } |
3955 | /* We have arrived at the last field in the partition pruning */ |
3956 | uint tmp_min_flag= key_tree->min_flag, |
3957 | tmp_max_flag= key_tree->max_flag; |
3958 | if (!tmp_min_flag) |
3959 | key_tree->next_key_part->store_min_key(ppar->key, |
3960 | &tmp_min_key, |
3961 | &tmp_min_flag, |
3962 | ppar->last_part_partno); |
3963 | if (!tmp_max_flag) |
3964 | key_tree->next_key_part->store_max_key(ppar->key, |
3965 | &tmp_max_key, |
3966 | &tmp_max_flag, |
3967 | ppar->last_part_partno); |
3968 | flag= tmp_min_flag | tmp_max_flag; |
3969 | } |
3970 | else |
3971 | flag= key_tree->min_flag | key_tree->max_flag; |
3972 | |
3973 | if (tmp_min_key != range_par->min_key) |
3974 | flag&= ~NO_MIN_RANGE; |
3975 | else |
3976 | flag|= NO_MIN_RANGE; |
3977 | if (tmp_max_key != range_par->max_key) |
3978 | flag&= ~NO_MAX_RANGE; |
3979 | else |
3980 | flag|= NO_MAX_RANGE; |
3981 | |
3982 | /* |
3983 | We need to call the interval mapper if we have a condition which |
3984 | makes sense to prune on. In the example of COLUMNS on a and |
3985 | b it makes sense if we have a condition on a, or conditions on |
3986 | both a and b. If we only have conditions on b it might make sense |
3987 | but this is a harder case we will solve later. For the harder case |
3988 | this clause then turns into use of all partitions and thus we |
3989 | simply set res= -1 as if the mapper had returned that. |
3990 | TODO: What to do here is defined in WL#4065. |
3991 | */ |
3992 | if (ppar->arg_stack[0]->part == 0 || ppar->part_info->part_type == VERSIONING_PARTITION) |
3993 | { |
3994 | uint32 i; |
3995 | uint32 store_length_array[MAX_KEY]; |
3996 | uint32 num_keys= ppar->part_fields; |
3997 | |
3998 | for (i= 0; i < num_keys; i++) |
3999 | store_length_array[i]= ppar->key[i].store_length; |
4000 | res= ppar->part_info-> |
4001 | get_part_iter_for_interval(ppar->part_info, |
4002 | FALSE, |
4003 | store_length_array, |
4004 | range_par->min_key, |
4005 | range_par->max_key, |
4006 | (uint)(tmp_min_key - range_par->min_key), |
4007 | (uint)(tmp_max_key - range_par->max_key), |
4008 | flag, |
4009 | &ppar->part_iter); |
4010 | if (!res) |
4011 | goto pop_and_go_right; /* res==0 --> no satisfying partitions */ |
4012 | } |
4013 | else |
4014 | res= -1; |
4015 | |
4016 | if (res == -1) |
4017 | { |
4018 | /* get a full range iterator */ |
4019 | init_all_partitions_iterator(ppar->part_info, &ppar->part_iter); |
4020 | } |
4021 | /* |
4022 | Save our intent to mark full partition as used if we will not be able |
4023 | to obtain further limits on subpartitions |
4024 | */ |
4025 | if (key_tree_part < ppar->last_part_partno) |
4026 | { |
4027 | /* |
4028 | We need to ignore the rest of the partitioning fields in all |
4029 | evaluations after this |
4030 | */ |
4031 | did_set_ignore_part_fields= TRUE; |
4032 | ppar->ignore_part_fields= TRUE; |
4033 | } |
4034 | set_full_part_if_bad_ret= TRUE; |
4035 | goto process_next_key_part; |
4036 | } |
4037 | |
4038 | if (key_tree_part == ppar->last_subpart_partno && |
4039 | (NULL != ppar->part_info->get_subpart_iter_for_interval)) |
4040 | { |
4041 | PARTITION_ITERATOR subpart_iter; |
4042 | DBUG_EXECUTE("info" , dbug_print_segment_range(key_tree, |
4043 | range_par->key_parts);); |
4044 | res= ppar->part_info-> |
4045 | get_subpart_iter_for_interval(ppar->part_info, |
4046 | TRUE, |
4047 | NULL, /* Currently not used here */ |
4048 | key_tree->min_value, |
4049 | key_tree->max_value, |
4050 | 0, 0, /* Those are ignored here */ |
4051 | key_tree->min_flag | |
4052 | key_tree->max_flag, |
4053 | &subpart_iter); |
4054 | if (res == 0) |
4055 | { |
4056 | /* |
4057 | The only case where we can get "no satisfying subpartitions" |
4058 | returned from the above call is when an error has occurred. |
4059 | */ |
4060 | DBUG_ASSERT(range_par->thd->is_error()); |
4061 | return 0; |
4062 | } |
4063 | |
4064 | if (res == -1) |
4065 | goto pop_and_go_right; /* all subpartitions satisfy */ |
4066 | |
4067 | uint32 subpart_id; |
4068 | bitmap_clear_all(&ppar->subparts_bitmap); |
4069 | while ((subpart_id= subpart_iter.get_next(&subpart_iter)) != |
4070 | NOT_A_PARTITION_ID) |
4071 | bitmap_set_bit(&ppar->subparts_bitmap, subpart_id); |
4072 | |
4073 | /* Mark each partition as used in each subpartition. */ |
4074 | uint32 part_id; |
4075 | while ((part_id= ppar->part_iter.get_next(&ppar->part_iter)) != |
4076 | NOT_A_PARTITION_ID) |
4077 | { |
4078 | for (uint i= 0; i < ppar->part_info->num_subparts; i++) |
4079 | if (bitmap_is_set(&ppar->subparts_bitmap, i)) |
4080 | bitmap_set_bit(&ppar->part_info->read_partitions, |
4081 | part_id * ppar->part_info->num_subparts + i); |
4082 | } |
4083 | goto pop_and_go_right; |
4084 | } |
4085 | |
4086 | if (key_tree->is_singlepoint()) |
4087 | { |
4088 | if (key_tree_part == ppar->last_part_partno && |
4089 | ppar->cur_part_fields == ppar->part_fields && |
4090 | ppar->part_info->get_part_iter_for_interval == NULL) |
4091 | { |
4092 | /* |
4093 | Ok, we've got "fieldN<=>constN"-type SEL_ARGs for all partitioning |
4094 | fields. Save all constN constants into table record buffer. |
4095 | */ |
4096 | store_selargs_to_rec(ppar, ppar->arg_stack, ppar->part_fields); |
4097 | DBUG_EXECUTE("info" , dbug_print_singlepoint_range(ppar->arg_stack, |
4098 | ppar->part_fields);); |
4099 | uint32 part_id; |
4100 | longlong func_value; |
4101 | /* Find in which partition the {const1, ...,constN} tuple goes */ |
4102 | if (ppar->get_top_partition_id_func(ppar->part_info, &part_id, |
4103 | &func_value)) |
4104 | { |
4105 | res= 0; /* No satisfying partitions */ |
4106 | goto pop_and_go_right; |
4107 | } |
4108 | /* Rembember the limit we got - single partition #part_id */ |
4109 | init_single_partition_iterator(part_id, &ppar->part_iter); |
4110 | |
4111 | /* |
4112 | If there are no subpartitions/we fail to get any limit for them, |
4113 | then we'll mark full partition as used. |
4114 | */ |
4115 | set_full_part_if_bad_ret= TRUE; |
4116 | goto process_next_key_part; |
4117 | } |
4118 | |
4119 | if (key_tree_part == ppar->last_subpart_partno && |
4120 | ppar->cur_subpart_fields == ppar->subpart_fields) |
4121 | { |
4122 | /* |
4123 | Ok, we've got "fieldN<=>constN"-type SEL_ARGs for all subpartitioning |
4124 | fields. Save all constN constants into table record buffer. |
4125 | */ |
4126 | store_selargs_to_rec(ppar, ppar->arg_stack_end - ppar->subpart_fields, |
4127 | ppar->subpart_fields); |
4128 | DBUG_EXECUTE("info" , dbug_print_singlepoint_range(ppar->arg_stack_end- |
4129 | ppar->subpart_fields, |
4130 | ppar->subpart_fields);); |
4131 | /* Find the subpartition (it's HASH/KEY so we always have one) */ |
4132 | partition_info *part_info= ppar->part_info; |
4133 | uint32 part_id, subpart_id; |
4134 | |
4135 | if (part_info->get_subpartition_id(part_info, &subpart_id)) |
4136 | return 0; |
4137 | |
4138 | /* Mark this partition as used in each subpartition. */ |
4139 | while ((part_id= ppar->part_iter.get_next(&ppar->part_iter)) != |
4140 | NOT_A_PARTITION_ID) |
4141 | { |
4142 | bitmap_set_bit(&part_info->read_partitions, |
4143 | part_id * part_info->num_subparts + subpart_id); |
4144 | } |
4145 | res= 1; /* Some partitions were marked as used */ |
4146 | goto pop_and_go_right; |
4147 | } |
4148 | } |
4149 | else |
4150 | { |
4151 | /* |
4152 | Can't handle condition on current key part. If we're that deep that |
4153 | we're processing subpartititoning's key parts, this means we'll not be |
4154 | able to infer any suitable condition, so bail out. |
4155 | */ |
4156 | if (key_tree_part >= ppar->last_part_partno) |
4157 | { |
4158 | res= -1; |
4159 | goto pop_and_go_right; |
4160 | } |
4161 | /* |
4162 | No meaning in continuing with rest of partitioning key parts. |
4163 | Will try to continue with subpartitioning key parts. |
4164 | */ |
4165 | ppar->ignore_part_fields= true; |
4166 | did_set_ignore_part_fields= true; |
4167 | goto process_next_key_part; |
4168 | } |
4169 | } |
4170 | |
4171 | process_next_key_part: |
4172 | if (key_tree->next_key_part) |
4173 | res= find_used_partitions(ppar, key_tree->next_key_part); |
4174 | else |
4175 | res= -1; |
4176 | |
4177 | if (did_set_ignore_part_fields) |
4178 | { |
4179 | /* |
4180 | We have returned from processing all key trees linked to our next |
4181 | key part. We are ready to be moving down (using right pointers) and |
4182 | this tree is a new evaluation requiring its own decision on whether |
4183 | to ignore partitioning fields. |
4184 | */ |
4185 | ppar->ignore_part_fields= FALSE; |
4186 | } |
4187 | if (set_full_part_if_bad_ret) |
4188 | { |
4189 | if (res == -1) |
4190 | { |
4191 | /* Got "full range" for subpartitioning fields */ |
4192 | uint32 part_id; |
4193 | bool found= FALSE; |
4194 | while ((part_id= ppar->part_iter.get_next(&ppar->part_iter)) != |
4195 | NOT_A_PARTITION_ID) |
4196 | { |
4197 | ppar->mark_full_partition_used(ppar->part_info, part_id); |
4198 | found= TRUE; |
4199 | } |
4200 | res= MY_TEST(found); |
4201 | } |
4202 | /* |
4203 | Restore the "used partitions iterator" to the default setting that |
4204 | specifies iteration over all partitions. |
4205 | */ |
4206 | init_all_partitions_iterator(ppar->part_info, &ppar->part_iter); |
4207 | } |
4208 | |
4209 | pop_and_go_right: |
4210 | /* Pop this key part info off the "stack" */ |
4211 | ppar->arg_stack_end--; |
4212 | ppar->cur_part_fields-= ppar->is_part_keypart[key_tree_part]; |
4213 | ppar->cur_subpart_fields-= ppar->is_subpart_keypart[key_tree_part]; |
4214 | |
4215 | if (res == -1) |
4216 | return -1; |
4217 | if (key_tree->right != &null_element) |
4218 | { |
4219 | if (-1 == (right_res= find_used_partitions(ppar,key_tree->right))) |
4220 | return -1; |
4221 | } |
4222 | return (left_res || right_res || res); |
4223 | } |
4224 | |
4225 | |
4226 | static void mark_all_partitions_as_used(partition_info *part_info) |
4227 | { |
4228 | bitmap_copy(&(part_info->read_partitions), |
4229 | &(part_info->lock_partitions)); |
4230 | } |
4231 | |
4232 | |
4233 | /* |
4234 | Check if field types allow to construct partitioning index description |
4235 | |
4236 | SYNOPSIS |
4237 | fields_ok_for_partition_index() |
4238 | pfield NULL-terminated array of pointers to fields. |
4239 | |
4240 | DESCRIPTION |
4241 | For an array of fields, check if we can use all of the fields to create |
4242 | partitioning index description. |
4243 | |
4244 | We can't process GEOMETRY fields - for these fields singlepoint intervals |
4245 | cant be generated, and non-singlepoint are "special" kinds of intervals |
4246 | to which our processing logic can't be applied. |
4247 | |
4248 | It is not known if we could process ENUM fields, so they are disabled to be |
4249 | on the safe side. |
4250 | |
4251 | RETURN |
4252 | TRUE Yes, fields can be used in partitioning index |
4253 | FALSE Otherwise |
4254 | */ |
4255 | |
4256 | static bool fields_ok_for_partition_index(Field **pfield) |
4257 | { |
4258 | if (!pfield) |
4259 | return FALSE; |
4260 | for (; (*pfield); pfield++) |
4261 | { |
4262 | enum_field_types ftype= (*pfield)->real_type(); |
4263 | if (ftype == MYSQL_TYPE_ENUM || ftype == MYSQL_TYPE_GEOMETRY) |
4264 | return FALSE; |
4265 | } |
4266 | return TRUE; |
4267 | } |
4268 | |
4269 | |
4270 | /* |
4271 | Create partition index description and fill related info in the context |
4272 | struct |
4273 | |
4274 | SYNOPSIS |
4275 | create_partition_index_description() |
4276 | prune_par INOUT Partition pruning context |
4277 | |
4278 | DESCRIPTION |
4279 | Create partition index description. Partition index description is: |
4280 | |
4281 | part_index(used_fields_list(part_expr), used_fields_list(subpart_expr)) |
4282 | |
4283 | If partitioning/sub-partitioning uses BLOB or Geometry fields, then |
4284 | corresponding fields_list(...) is not included into index description |
4285 | and we don't perform partition pruning for partitions/subpartitions. |
4286 | |
4287 | RETURN |
4288 | TRUE Out of memory or can't do partition pruning at all |
4289 | FALSE OK |
4290 | */ |
4291 | |
4292 | static bool create_partition_index_description(PART_PRUNE_PARAM *ppar) |
4293 | { |
4294 | RANGE_OPT_PARAM *range_par= &(ppar->range_param); |
4295 | partition_info *part_info= ppar->part_info; |
4296 | uint used_part_fields, used_subpart_fields; |
4297 | |
4298 | used_part_fields= fields_ok_for_partition_index(part_info->part_field_array) ? |
4299 | part_info->num_part_fields : 0; |
4300 | used_subpart_fields= |
4301 | fields_ok_for_partition_index(part_info->subpart_field_array)? |
4302 | part_info->num_subpart_fields : 0; |
4303 | |
4304 | uint total_parts= used_part_fields + used_subpart_fields; |
4305 | |
4306 | ppar->ignore_part_fields= FALSE; |
4307 | ppar->part_fields= used_part_fields; |
4308 | ppar->last_part_partno= (int)used_part_fields - 1; |
4309 | |
4310 | ppar->subpart_fields= used_subpart_fields; |
4311 | ppar->last_subpart_partno= |
4312 | used_subpart_fields?(int)(used_part_fields + used_subpart_fields - 1): -1; |
4313 | |
4314 | if (part_info->is_sub_partitioned()) |
4315 | { |
4316 | ppar->mark_full_partition_used= mark_full_partition_used_with_parts; |
4317 | ppar->get_top_partition_id_func= part_info->get_part_partition_id; |
4318 | } |
4319 | else |
4320 | { |
4321 | ppar->mark_full_partition_used= mark_full_partition_used_no_parts; |
4322 | ppar->get_top_partition_id_func= part_info->get_partition_id; |
4323 | } |
4324 | |
4325 | KEY_PART *key_part; |
4326 | MEM_ROOT *alloc= range_par->mem_root; |
4327 | if (!total_parts || |
4328 | !(key_part= (KEY_PART*)alloc_root(alloc, sizeof(KEY_PART)* |
4329 | total_parts)) || |
4330 | !(ppar->arg_stack= (SEL_ARG**)alloc_root(alloc, sizeof(SEL_ARG*)* |
4331 | total_parts)) || |
4332 | !(ppar->is_part_keypart= (my_bool*)alloc_root(alloc, sizeof(my_bool)* |
4333 | total_parts)) || |
4334 | !(ppar->is_subpart_keypart= (my_bool*)alloc_root(alloc, sizeof(my_bool)* |
4335 | total_parts))) |
4336 | return TRUE; |
4337 | |
4338 | if (ppar->subpart_fields) |
4339 | { |
4340 | my_bitmap_map *buf; |
4341 | uint32 bufsize= bitmap_buffer_size(ppar->part_info->num_subparts); |
4342 | if (!(buf= (my_bitmap_map*) alloc_root(alloc, bufsize))) |
4343 | return TRUE; |
4344 | my_bitmap_init(&ppar->subparts_bitmap, buf, ppar->part_info->num_subparts, |
4345 | FALSE); |
4346 | } |
4347 | range_par->key_parts= key_part; |
4348 | Field **field= (ppar->part_fields)? part_info->part_field_array : |
4349 | part_info->subpart_field_array; |
4350 | bool in_subpart_fields= FALSE; |
4351 | uint total_key_len= 0; |
4352 | for (uint part= 0; part < total_parts; part++, key_part++) |
4353 | { |
4354 | key_part->key= 0; |
4355 | key_part->part= part; |
4356 | key_part->length= (uint16)(*field)->key_length(); |
4357 | key_part->store_length= (uint16)get_partition_field_store_length(*field); |
4358 | total_key_len += key_part->store_length; |
4359 | |
4360 | DBUG_PRINT("info" , ("part %u length %u store_length %u" , part, |
4361 | key_part->length, key_part->store_length)); |
4362 | |
4363 | key_part->field= (*field); |
4364 | key_part->image_type = Field::itRAW; |
4365 | /* |
4366 | We set keypart flag to 0 here as the only HA_PART_KEY_SEG is checked |
4367 | in the RangeAnalysisModule. |
4368 | */ |
4369 | key_part->flag= 0; |
4370 | /* We don't set key_parts->null_bit as it will not be used */ |
4371 | |
4372 | ppar->is_part_keypart[part]= !in_subpart_fields; |
4373 | ppar->is_subpart_keypart[part]= in_subpart_fields; |
4374 | |
4375 | /* |
4376 | Check if this was last field in this array, in this case we |
4377 | switch to subpartitioning fields. (This will only happens if |
4378 | there are subpartitioning fields to cater for). |
4379 | */ |
4380 | if (!*(++field)) |
4381 | { |
4382 | field= part_info->subpart_field_array; |
4383 | in_subpart_fields= TRUE; |
4384 | } |
4385 | } |
4386 | range_par->key_parts_end= key_part; |
4387 | |
4388 | total_key_len++; /* Take into account the "+1" in QUICK_RANGE::QUICK_RANGE */ |
4389 | if (!(range_par->min_key= (uchar*)alloc_root(alloc,total_key_len)) || |
4390 | !(range_par->max_key= (uchar*)alloc_root(alloc,total_key_len))) |
4391 | { |
4392 | return true; |
4393 | } |
4394 | |
4395 | DBUG_EXECUTE("info" , print_partitioning_index(range_par->key_parts, |
4396 | range_par->key_parts_end);); |
4397 | return FALSE; |
4398 | } |
4399 | |
4400 | |
4401 | #ifndef DBUG_OFF |
4402 | |
4403 | static void print_partitioning_index(KEY_PART *parts, KEY_PART *parts_end) |
4404 | { |
4405 | DBUG_ENTER("print_partitioning_index" ); |
4406 | DBUG_LOCK_FILE; |
4407 | fprintf(DBUG_FILE, "partitioning INDEX(" ); |
4408 | for (KEY_PART *p=parts; p != parts_end; p++) |
4409 | { |
4410 | fprintf(DBUG_FILE, "%s%s" , p==parts?"" :" ," , p->field->field_name.str); |
4411 | } |
4412 | fputs(");\n" , DBUG_FILE); |
4413 | DBUG_UNLOCK_FILE; |
4414 | DBUG_VOID_RETURN; |
4415 | } |
4416 | |
4417 | /* Print field value into debug trace, in NULL-aware way. */ |
4418 | static void dbug_print_field(Field *field) |
4419 | { |
4420 | if (field->is_real_null()) |
4421 | fprintf(DBUG_FILE, "NULL" ); |
4422 | else |
4423 | { |
4424 | char buf[256]; |
4425 | String str(buf, sizeof(buf), &my_charset_bin); |
4426 | str.length(0); |
4427 | String *pstr; |
4428 | pstr= field->val_str(&str); |
4429 | fprintf(DBUG_FILE, "'%s'" , pstr->c_ptr_safe()); |
4430 | } |
4431 | } |
4432 | |
4433 | |
4434 | /* Print a "c1 < keypartX < c2" - type interval into debug trace. */ |
4435 | static void dbug_print_segment_range(SEL_ARG *arg, KEY_PART *part) |
4436 | { |
4437 | DBUG_ENTER("dbug_print_segment_range" ); |
4438 | DBUG_LOCK_FILE; |
4439 | if (!(arg->min_flag & NO_MIN_RANGE)) |
4440 | { |
4441 | store_key_image_to_rec(part->field, arg->min_value, part->length); |
4442 | dbug_print_field(part->field); |
4443 | if (arg->min_flag & NEAR_MIN) |
4444 | fputs(" < " , DBUG_FILE); |
4445 | else |
4446 | fputs(" <= " , DBUG_FILE); |
4447 | } |
4448 | |
4449 | fprintf(DBUG_FILE, "%s" , part->field->field_name.str); |
4450 | |
4451 | if (!(arg->max_flag & NO_MAX_RANGE)) |
4452 | { |
4453 | if (arg->max_flag & NEAR_MAX) |
4454 | fputs(" < " , DBUG_FILE); |
4455 | else |
4456 | fputs(" <= " , DBUG_FILE); |
4457 | store_key_image_to_rec(part->field, arg->max_value, part->length); |
4458 | dbug_print_field(part->field); |
4459 | } |
4460 | fputs("\n" , DBUG_FILE); |
4461 | DBUG_UNLOCK_FILE; |
4462 | DBUG_VOID_RETURN; |
4463 | } |
4464 | |
4465 | |
4466 | /* |
4467 | Print a singlepoint multi-keypart range interval to debug trace |
4468 | |
4469 | SYNOPSIS |
4470 | dbug_print_singlepoint_range() |
4471 | start Array of SEL_ARG* ptrs representing conditions on key parts |
4472 | num Number of elements in the array. |
4473 | |
4474 | DESCRIPTION |
4475 | This function prints a "keypartN=constN AND ... AND keypartK=constK"-type |
4476 | interval to debug trace. |
4477 | */ |
4478 | |
4479 | static void dbug_print_singlepoint_range(SEL_ARG **start, uint num) |
4480 | { |
4481 | DBUG_ENTER("dbug_print_singlepoint_range" ); |
4482 | DBUG_LOCK_FILE; |
4483 | SEL_ARG **end= start + num; |
4484 | |
4485 | for (SEL_ARG **arg= start; arg != end; arg++) |
4486 | { |
4487 | Field *field= (*arg)->field; |
4488 | fprintf(DBUG_FILE, "%s%s=" , (arg==start)?"" :", " , field->field_name.str); |
4489 | dbug_print_field(field); |
4490 | } |
4491 | fputs("\n" , DBUG_FILE); |
4492 | DBUG_UNLOCK_FILE; |
4493 | DBUG_VOID_RETURN; |
4494 | } |
4495 | #endif |
4496 | |
4497 | /**************************************************************************** |
4498 | * Partition pruning code ends |
4499 | ****************************************************************************/ |
4500 | #endif |
4501 | |
4502 | |
4503 | /* |
4504 | Get cost of 'sweep' full records retrieval. |
4505 | SYNOPSIS |
4506 | get_sweep_read_cost() |
4507 | param Parameter from test_quick_select |
4508 | records # of records to be retrieved |
4509 | RETURN |
4510 | cost of sweep |
4511 | */ |
4512 | |
4513 | double get_sweep_read_cost(const PARAM *param, ha_rows records) |
4514 | { |
4515 | double result; |
4516 | DBUG_ENTER("get_sweep_read_cost" ); |
4517 | if (param->table->file->primary_key_is_clustered()) |
4518 | { |
4519 | /* |
4520 | We are using the primary key to find the rows. |
4521 | Calculate the cost for this. |
4522 | */ |
4523 | result= param->table->file->read_time(param->table->s->primary_key, |
4524 | (uint)records, records); |
4525 | } |
4526 | else |
4527 | { |
4528 | /* |
4529 | Rows will be retreived with rnd_pos(). Caluclate the expected |
4530 | cost for this. |
4531 | */ |
4532 | double n_blocks= |
4533 | ceil(ulonglong2double(param->table->file->stats.data_file_length) / |
4534 | IO_SIZE); |
4535 | double busy_blocks= |
4536 | n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(records))); |
4537 | if (busy_blocks < 1.0) |
4538 | busy_blocks= 1.0; |
4539 | DBUG_PRINT("info" ,("sweep: nblocks: %g, busy_blocks: %g" , n_blocks, |
4540 | busy_blocks)); |
4541 | /* |
4542 | Disabled: Bail out if # of blocks to read is bigger than # of blocks in |
4543 | table data file. |
4544 | if (max_cost != DBL_MAX && (busy_blocks+index_reads_cost) >= n_blocks) |
4545 | return 1; |
4546 | */ |
4547 | JOIN *join= param->thd->lex->select_lex.join; |
4548 | if (!join || join->table_count == 1) |
4549 | { |
4550 | /* No join, assume reading is done in one 'sweep' */ |
4551 | result= busy_blocks*(DISK_SEEK_BASE_COST + |
4552 | DISK_SEEK_PROP_COST*n_blocks/busy_blocks); |
4553 | } |
4554 | else |
4555 | { |
4556 | /* |
4557 | Possibly this is a join with source table being non-last table, so |
4558 | assume that disk seeks are random here. |
4559 | */ |
4560 | result= busy_blocks; |
4561 | } |
4562 | } |
4563 | DBUG_PRINT("return" ,("cost: %g" , result)); |
4564 | DBUG_RETURN(result); |
4565 | } |
4566 | |
4567 | |
4568 | /* |
4569 | Get best plan for a SEL_IMERGE disjunctive expression. |
4570 | SYNOPSIS |
4571 | get_best_disjunct_quick() |
4572 | param Parameter from check_quick_select function |
4573 | imerge Expression to use |
4574 | read_time Don't create scans with cost > read_time |
4575 | |
4576 | NOTES |
4577 | index_merge cost is calculated as follows: |
4578 | index_merge_cost = |
4579 | cost(index_reads) + (see #1) |
4580 | cost(rowid_to_row_scan) + (see #2) |
4581 | cost(unique_use) (see #3) |
4582 | |
4583 | 1. cost(index_reads) =SUM_i(cost(index_read_i)) |
4584 | For non-CPK scans, |
4585 | cost(index_read_i) = {cost of ordinary 'index only' scan} |
4586 | For CPK scan, |
4587 | cost(index_read_i) = {cost of non-'index only' scan} |
4588 | |
4589 | 2. cost(rowid_to_row_scan) |
4590 | If table PK is clustered then |
4591 | cost(rowid_to_row_scan) = |
4592 | {cost of ordinary clustered PK scan with n_ranges=n_rows} |
4593 | |
4594 | Otherwise, we use the following model to calculate costs: |
4595 | We need to retrieve n_rows rows from file that occupies n_blocks blocks. |
4596 | We assume that offsets of rows we need are independent variates with |
4597 | uniform distribution in [0..max_file_offset] range. |
4598 | |
4599 | We'll denote block as "busy" if it contains row(s) we need to retrieve |
4600 | and "empty" if doesn't contain rows we need. |
4601 | |
4602 | Probability that a block is empty is (1 - 1/n_blocks)^n_rows (this |
4603 | applies to any block in file). Let x_i be a variate taking value 1 if |
4604 | block #i is empty and 0 otherwise. |
4605 | |
4606 | Then E(x_i) = (1 - 1/n_blocks)^n_rows; |
4607 | |
4608 | E(n_empty_blocks) = E(sum(x_i)) = sum(E(x_i)) = |
4609 | = n_blocks * ((1 - 1/n_blocks)^n_rows) = |
4610 | ~= n_blocks * exp(-n_rows/n_blocks). |
4611 | |
4612 | E(n_busy_blocks) = n_blocks*(1 - (1 - 1/n_blocks)^n_rows) = |
4613 | ~= n_blocks * (1 - exp(-n_rows/n_blocks)). |
4614 | |
4615 | Average size of "hole" between neighbor non-empty blocks is |
4616 | E(hole_size) = n_blocks/E(n_busy_blocks). |
4617 | |
4618 | The total cost of reading all needed blocks in one "sweep" is: |
4619 | |
4620 | E(n_busy_blocks)* |
4621 | (DISK_SEEK_BASE_COST + DISK_SEEK_PROP_COST*n_blocks/E(n_busy_blocks)). |
4622 | |
4623 | 3. Cost of Unique use is calculated in Unique::get_use_cost function. |
4624 | |
4625 | ROR-union cost is calculated in the same way index_merge, but instead of |
4626 | Unique a priority queue is used. |
4627 | |
4628 | RETURN |
4629 | Created read plan |
4630 | NULL - Out of memory or no read scan could be built. |
4631 | */ |
4632 | |
4633 | static |
4634 | TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, |
4635 | double read_time) |
4636 | { |
4637 | SEL_TREE **ptree; |
4638 | TRP_INDEX_MERGE *imerge_trp= NULL; |
4639 | TRP_RANGE **range_scans; |
4640 | TRP_RANGE **cur_child; |
4641 | TRP_RANGE **cpk_scan= NULL; |
4642 | bool imerge_too_expensive= FALSE; |
4643 | double imerge_cost= 0.0; |
4644 | ha_rows cpk_scan_records= 0; |
4645 | ha_rows non_cpk_scan_records= 0; |
4646 | bool pk_is_clustered= param->table->file->primary_key_is_clustered(); |
4647 | bool all_scans_ror_able= TRUE; |
4648 | bool all_scans_rors= TRUE; |
4649 | uint unique_calc_buff_size; |
4650 | TABLE_READ_PLAN **roru_read_plans; |
4651 | TABLE_READ_PLAN **cur_roru_plan; |
4652 | double roru_index_costs; |
4653 | ha_rows roru_total_records; |
4654 | double roru_intersect_part= 1.0; |
4655 | size_t n_child_scans; |
4656 | DBUG_ENTER("get_best_disjunct_quick" ); |
4657 | DBUG_PRINT("info" , ("Full table scan cost: %g" , read_time)); |
4658 | |
4659 | /* |
4660 | In every tree of imerge remove SEL_ARG trees that do not make ranges. |
4661 | If after this removal some SEL_ARG tree becomes empty discard imerge. |
4662 | */ |
4663 | for (ptree= imerge->trees; ptree != imerge->trees_next; ptree++) |
4664 | { |
4665 | if (remove_nonrange_trees(param, *ptree)) |
4666 | { |
4667 | imerge->trees_next= imerge->trees; |
4668 | break; |
4669 | } |
4670 | } |
4671 | |
4672 | n_child_scans= imerge->trees_next - imerge->trees; |
4673 | |
4674 | if (!n_child_scans) |
4675 | DBUG_RETURN(NULL); |
4676 | |
4677 | if (!(range_scans= (TRP_RANGE**)alloc_root(param->mem_root, |
4678 | sizeof(TRP_RANGE*)* |
4679 | n_child_scans))) |
4680 | DBUG_RETURN(NULL); |
4681 | /* |
4682 | Collect best 'range' scan for each of disjuncts, and, while doing so, |
4683 | analyze possibility of ROR scans. Also calculate some values needed by |
4684 | other parts of the code. |
4685 | */ |
4686 | for (ptree= imerge->trees, cur_child= range_scans; |
4687 | ptree != imerge->trees_next; |
4688 | ptree++, cur_child++) |
4689 | { |
4690 | DBUG_EXECUTE("info" , print_sel_tree(param, *ptree, &(*ptree)->keys_map, |
4691 | "tree in SEL_IMERGE" );); |
4692 | if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time))) |
4693 | { |
4694 | /* |
4695 | One of index scans in this index_merge is more expensive than entire |
4696 | table read for another available option. The entire index_merge (and |
4697 | any possible ROR-union) will be more expensive then, too. We continue |
4698 | here only to update SQL_SELECT members. |
4699 | */ |
4700 | imerge_too_expensive= TRUE; |
4701 | } |
4702 | if (imerge_too_expensive) |
4703 | continue; |
4704 | |
4705 | imerge_cost += (*cur_child)->read_cost; |
4706 | all_scans_ror_able &= ((*ptree)->n_ror_scans > 0); |
4707 | all_scans_rors &= (*cur_child)->is_ror; |
4708 | if (pk_is_clustered && |
4709 | param->real_keynr[(*cur_child)->key_idx] == |
4710 | param->table->s->primary_key) |
4711 | { |
4712 | cpk_scan= cur_child; |
4713 | cpk_scan_records= (*cur_child)->records; |
4714 | } |
4715 | else |
4716 | non_cpk_scan_records += (*cur_child)->records; |
4717 | } |
4718 | |
4719 | DBUG_PRINT("info" , ("index_merge scans cost %g" , imerge_cost)); |
4720 | if (imerge_too_expensive || (imerge_cost > read_time) || |
4721 | ((non_cpk_scan_records+cpk_scan_records >= |
4722 | param->table->stat_records()) && |
4723 | read_time != DBL_MAX)) |
4724 | { |
4725 | /* |
4726 | Bail out if it is obvious that both index_merge and ROR-union will be |
4727 | more expensive |
4728 | */ |
4729 | DBUG_PRINT("info" , ("Sum of index_merge scans is more expensive than " |
4730 | "full table scan, bailing out" )); |
4731 | DBUG_RETURN(NULL); |
4732 | } |
4733 | |
4734 | /* |
4735 | If all scans happen to be ROR, proceed to generate a ROR-union plan (it's |
4736 | guaranteed to be cheaper than non-ROR union), unless ROR-unions are |
4737 | disabled in @@optimizer_switch |
4738 | */ |
4739 | if (all_scans_rors && |
4740 | optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_UNION)) |
4741 | { |
4742 | roru_read_plans= (TABLE_READ_PLAN**)range_scans; |
4743 | goto skip_to_ror_scan; |
4744 | } |
4745 | |
4746 | if (cpk_scan) |
4747 | { |
4748 | /* |
4749 | Add one ROWID comparison for each row retrieved on non-CPK scan. (it |
4750 | is done in QUICK_RANGE_SELECT::row_in_ranges) |
4751 | */ |
4752 | imerge_cost += non_cpk_scan_records / TIME_FOR_COMPARE_ROWID; |
4753 | } |
4754 | |
4755 | /* Calculate cost(rowid_to_row_scan) */ |
4756 | imerge_cost += get_sweep_read_cost(param, non_cpk_scan_records); |
4757 | DBUG_PRINT("info" ,("index_merge cost with rowid-to-row scan: %g" , |
4758 | imerge_cost)); |
4759 | if (imerge_cost > read_time || |
4760 | !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION)) |
4761 | { |
4762 | goto build_ror_index_merge; |
4763 | } |
4764 | |
4765 | /* Add Unique operations cost */ |
4766 | unique_calc_buff_size= |
4767 | Unique::get_cost_calc_buff_size((ulong)non_cpk_scan_records, |
4768 | param->table->file->ref_length, |
4769 | (size_t)param->thd->variables.sortbuff_size); |
4770 | if (param->imerge_cost_buff_size < unique_calc_buff_size) |
4771 | { |
4772 | if (!(param->imerge_cost_buff= (uint*)alloc_root(param->mem_root, |
4773 | unique_calc_buff_size))) |
4774 | DBUG_RETURN(NULL); |
4775 | param->imerge_cost_buff_size= unique_calc_buff_size; |
4776 | } |
4777 | |
4778 | imerge_cost += |
4779 | Unique::get_use_cost(param->imerge_cost_buff, (uint)non_cpk_scan_records, |
4780 | param->table->file->ref_length, |
4781 | (size_t)param->thd->variables.sortbuff_size, |
4782 | TIME_FOR_COMPARE_ROWID, |
4783 | FALSE, NULL); |
4784 | DBUG_PRINT("info" ,("index_merge total cost: %g (wanted: less then %g)" , |
4785 | imerge_cost, read_time)); |
4786 | if (imerge_cost < read_time) |
4787 | { |
4788 | if ((imerge_trp= new (param->mem_root)TRP_INDEX_MERGE)) |
4789 | { |
4790 | imerge_trp->read_cost= imerge_cost; |
4791 | imerge_trp->records= non_cpk_scan_records + cpk_scan_records; |
4792 | imerge_trp->records= MY_MIN(imerge_trp->records, |
4793 | param->table->stat_records()); |
4794 | imerge_trp->range_scans= range_scans; |
4795 | imerge_trp->range_scans_end= range_scans + n_child_scans; |
4796 | read_time= imerge_cost; |
4797 | } |
4798 | if (imerge_trp) |
4799 | { |
4800 | TABLE_READ_PLAN *trp= merge_same_index_scans(param, imerge, imerge_trp, |
4801 | read_time); |
4802 | if (trp != imerge_trp) |
4803 | DBUG_RETURN(trp); |
4804 | } |
4805 | } |
4806 | |
4807 | build_ror_index_merge: |
4808 | if (!all_scans_ror_able || |
4809 | param->thd->lex->sql_command == SQLCOM_DELETE || |
4810 | !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_UNION)) |
4811 | DBUG_RETURN(imerge_trp); |
4812 | |
4813 | /* Ok, it is possible to build a ROR-union, try it. */ |
4814 | bool dummy; |
4815 | if (!(roru_read_plans= |
4816 | (TABLE_READ_PLAN**)alloc_root(param->mem_root, |
4817 | sizeof(TABLE_READ_PLAN*)* |
4818 | n_child_scans))) |
4819 | DBUG_RETURN(imerge_trp); |
4820 | |
4821 | skip_to_ror_scan: |
4822 | roru_index_costs= 0.0; |
4823 | roru_total_records= 0; |
4824 | cur_roru_plan= roru_read_plans; |
4825 | |
4826 | /* Find 'best' ROR scan for each of trees in disjunction */ |
4827 | for (ptree= imerge->trees, cur_child= range_scans; |
4828 | ptree != imerge->trees_next; |
4829 | ptree++, cur_child++, cur_roru_plan++) |
4830 | { |
4831 | /* |
4832 | Assume the best ROR scan is the one that has cheapest full-row-retrieval |
4833 | scan cost. |
4834 | Also accumulate index_only scan costs as we'll need them to calculate |
4835 | overall index_intersection cost. |
4836 | */ |
4837 | double cost; |
4838 | if ((*cur_child)->is_ror) |
4839 | { |
4840 | /* Ok, we have index_only cost, now get full rows scan cost */ |
4841 | cost= param->table->file-> |
4842 | read_time(param->real_keynr[(*cur_child)->key_idx], 1, |
4843 | (*cur_child)->records) + |
4844 | rows2double((*cur_child)->records) / TIME_FOR_COMPARE; |
4845 | } |
4846 | else |
4847 | cost= read_time; |
4848 | |
4849 | TABLE_READ_PLAN *prev_plan= *cur_child; |
4850 | if (!(*cur_roru_plan= get_best_ror_intersect(param, *ptree, cost, |
4851 | &dummy))) |
4852 | { |
4853 | if (prev_plan->is_ror) |
4854 | *cur_roru_plan= prev_plan; |
4855 | else |
4856 | DBUG_RETURN(imerge_trp); |
4857 | roru_index_costs += (*cur_roru_plan)->read_cost; |
4858 | } |
4859 | else |
4860 | roru_index_costs += |
4861 | ((TRP_ROR_INTERSECT*)(*cur_roru_plan))->index_scan_costs; |
4862 | roru_total_records += (*cur_roru_plan)->records; |
4863 | roru_intersect_part *= (*cur_roru_plan)->records / |
4864 | param->table->stat_records(); |
4865 | } |
4866 | |
4867 | /* |
4868 | rows to retrieve= |
4869 | SUM(rows_in_scan_i) - table_rows * PROD(rows_in_scan_i / table_rows). |
4870 | This is valid because index_merge construction guarantees that conditions |
4871 | in disjunction do not share key parts. |
4872 | */ |
4873 | roru_total_records -= (ha_rows)(roru_intersect_part* |
4874 | param->table->stat_records()); |
4875 | /* ok, got a ROR read plan for each of the disjuncts |
4876 | Calculate cost: |
4877 | cost(index_union_scan(scan_1, ... scan_n)) = |
4878 | SUM_i(cost_of_index_only_scan(scan_i)) + |
4879 | queue_use_cost(rowid_len, n) + |
4880 | cost_of_row_retrieval |
4881 | See get_merge_buffers_cost function for queue_use_cost formula derivation. |
4882 | */ |
4883 | |
4884 | double roru_total_cost; |
4885 | roru_total_cost= roru_index_costs + |
4886 | rows2double(roru_total_records)*log((double)n_child_scans) / |
4887 | (TIME_FOR_COMPARE_ROWID * M_LN2) + |
4888 | get_sweep_read_cost(param, roru_total_records); |
4889 | |
4890 | DBUG_PRINT("info" , ("ROR-union: cost %g, %zu members" , |
4891 | roru_total_cost, n_child_scans)); |
4892 | TRP_ROR_UNION* roru; |
4893 | if (roru_total_cost < read_time) |
4894 | { |
4895 | if ((roru= new (param->mem_root) TRP_ROR_UNION)) |
4896 | { |
4897 | roru->first_ror= roru_read_plans; |
4898 | roru->last_ror= roru_read_plans + n_child_scans; |
4899 | roru->read_cost= roru_total_cost; |
4900 | roru->records= roru_total_records; |
4901 | DBUG_RETURN(roru); |
4902 | } |
4903 | } |
4904 | DBUG_RETURN(imerge_trp); |
4905 | } |
4906 | |
4907 | |
4908 | /* |
4909 | Merge index scans for the same indexes in an index merge plan |
4910 | |
4911 | SYNOPSIS |
4912 | merge_same_index_scans() |
4913 | param Context info for the operation |
4914 | imerge IN/OUT SEL_IMERGE from which imerge_trp has been extracted |
4915 | imerge_trp The index merge plan where index scans for the same |
4916 | indexes are to be merges |
4917 | read_time The upper bound for the cost of the plan to be evaluated |
4918 | |
4919 | DESRIPTION |
4920 | For the given index merge plan imerge_trp extracted from the SEL_MERGE |
4921 | imerge the function looks for range scans with the same indexes and merges |
4922 | them into SEL_ARG trees. Then for each such SEL_ARG tree r_i the function |
4923 | creates a range tree rt_i that contains only r_i. All rt_i are joined |
4924 | into one index merge that replaces the original index merge imerge. |
4925 | The function calls get_best_disjunct_quick for the new index merge to |
4926 | get a new index merge plan that contains index scans only for different |
4927 | indexes. |
4928 | If there are no index scans for the same index in the original index |
4929 | merge plan the function does not change the original imerge and returns |
4930 | imerge_trp as its result. |
4931 | |
4932 | RETURN |
4933 | The original or or improved index merge plan |
4934 | */ |
4935 | |
4936 | static |
4937 | TABLE_READ_PLAN *merge_same_index_scans(PARAM *param, SEL_IMERGE *imerge, |
4938 | TRP_INDEX_MERGE *imerge_trp, |
4939 | double read_time) |
4940 | { |
4941 | uint16 first_scan_tree_idx[MAX_KEY]; |
4942 | SEL_TREE **tree; |
4943 | TRP_RANGE **cur_child; |
4944 | uint removed_cnt= 0; |
4945 | |
4946 | DBUG_ENTER("merge_same_index_scans" ); |
4947 | |
4948 | bzero(first_scan_tree_idx, sizeof(first_scan_tree_idx[0])*param->keys); |
4949 | |
4950 | for (tree= imerge->trees, cur_child= imerge_trp->range_scans; |
4951 | tree != imerge->trees_next; |
4952 | tree++, cur_child++) |
4953 | { |
4954 | DBUG_ASSERT(tree); |
4955 | uint key_idx= (*cur_child)->key_idx; |
4956 | uint16 *tree_idx_ptr= &first_scan_tree_idx[key_idx]; |
4957 | if (!*tree_idx_ptr) |
4958 | *tree_idx_ptr= (uint16) (tree-imerge->trees+1); |
4959 | else |
4960 | { |
4961 | SEL_TREE **changed_tree= imerge->trees+(*tree_idx_ptr-1); |
4962 | SEL_ARG *key= (*changed_tree)->keys[key_idx]; |
4963 | for (uint i= 0; i < param->keys; i++) |
4964 | (*changed_tree)->keys[i]= NULL; |
4965 | (*changed_tree)->keys_map.clear_all(); |
4966 | if (key) |
4967 | key->incr_refs(); |
4968 | if ((*tree)->keys[key_idx]) |
4969 | (*tree)->keys[key_idx]->incr_refs(); |
4970 | if (((*changed_tree)->keys[key_idx]= |
4971 | key_or(param, key, (*tree)->keys[key_idx]))) |
4972 | (*changed_tree)->keys_map.set_bit(key_idx); |
4973 | *tree= NULL; |
4974 | removed_cnt++; |
4975 | } |
4976 | } |
4977 | if (!removed_cnt) |
4978 | DBUG_RETURN(imerge_trp); |
4979 | |
4980 | TABLE_READ_PLAN *trp= NULL; |
4981 | SEL_TREE **new_trees_next= imerge->trees; |
4982 | for (tree= new_trees_next; tree != imerge->trees_next; tree++) |
4983 | { |
4984 | if (!*tree) |
4985 | continue; |
4986 | if (tree > new_trees_next) |
4987 | *new_trees_next= *tree; |
4988 | new_trees_next++; |
4989 | } |
4990 | imerge->trees_next= new_trees_next; |
4991 | |
4992 | DBUG_ASSERT(imerge->trees_next>imerge->trees); |
4993 | |
4994 | if (imerge->trees_next-imerge->trees > 1) |
4995 | trp= get_best_disjunct_quick(param, imerge, read_time); |
4996 | else |
4997 | { |
4998 | /* |
4999 | This alternative theoretically can be reached when the cost |
5000 | of the index merge for such a formula as |
5001 | (key1 BETWEEN c1_1 AND c1_2) AND key2 > c2 OR |
5002 | (key1 BETWEEN c1_3 AND c1_4) AND key3 > c3 |
5003 | is estimated as being cheaper than the cost of index scan for |
5004 | the formula |
5005 | (key1 BETWEEN c1_1 AND c1_2) OR (key1 BETWEEN c1_3 AND c1_4) |
5006 | |
5007 | In the current code this may happen for two reasons: |
5008 | 1. for a single index range scan data records are accessed in |
5009 | a random order |
5010 | 2. the functions that estimate the cost of a range scan and an |
5011 | index merge retrievals are not well calibrated |
5012 | */ |
5013 | trp= get_key_scans_params(param, *imerge->trees, FALSE, TRUE, |
5014 | read_time); |
5015 | } |
5016 | |
5017 | DBUG_RETURN(trp); |
5018 | } |
5019 | |
5020 | |
5021 | /* |
5022 | This structure contains the info common for all steps of a partial |
5023 | index intersection plan. Morever it contains also the info common |
5024 | for index intersect plans. This info is filled in by the function |
5025 | prepare_search_best just before searching for the best index |
5026 | intersection plan. |
5027 | */ |
5028 | |
5029 | typedef struct st_common_index_intersect_info |
5030 | { |
5031 | PARAM *param; /* context info for range optimizations */ |
5032 | uint key_size; /* size of a ROWID element stored in Unique object */ |
5033 | uint compare_factor; /* 1/compare - cost to compare two ROWIDs */ |
5034 | size_t max_memory_size; /* maximum space allowed for Unique objects */ |
5035 | ha_rows table_cardinality; /* estimate of the number of records in table */ |
5036 | double cutoff_cost; /* discard index intersects with greater costs */ |
5037 | INDEX_SCAN_INFO *cpk_scan; /* clustered primary key used in intersection */ |
5038 | |
5039 | bool in_memory; /* unique object for intersection is completely in memory */ |
5040 | |
5041 | INDEX_SCAN_INFO **search_scans; /* scans possibly included in intersect */ |
5042 | uint n_search_scans; /* number of elements in search_scans */ |
5043 | |
5044 | bool best_uses_cpk; /* current best intersect uses clustered primary key */ |
5045 | double best_cost; /* cost of the current best index intersection */ |
5046 | /* estimate of the number of records in the current best intersection */ |
5047 | ha_rows best_records; |
5048 | uint best_length; /* number of indexes in the current best intersection */ |
5049 | INDEX_SCAN_INFO **best_intersect; /* the current best index intersection */ |
5050 | /* scans from the best intersect to be filtrered by cpk conditions */ |
5051 | key_map filtered_scans; |
5052 | |
5053 | uint *buff_elems; /* buffer to calculate cost of index intersection */ |
5054 | |
5055 | } COMMON_INDEX_INTERSECT_INFO; |
5056 | |
5057 | |
5058 | /* |
5059 | This structure contains the info specific for one step of an index |
5060 | intersection plan. The structure is filled in by the function |
5061 | check_index_intersect_extension. |
5062 | */ |
5063 | |
5064 | typedef struct st_partial_index_intersect_info |
5065 | { |
5066 | COMMON_INDEX_INTERSECT_INFO *common_info; /* shared by index intersects */ |
5067 | uint length; /* number of index scans in the partial intersection */ |
5068 | ha_rows records; /* estimate of the number of records in intersection */ |
5069 | double cost; /* cost of the partial index intersection */ |
5070 | |
5071 | /* estimate of total number of records of all scans of the partial index |
5072 | intersect sent to the Unique object used for the intersection */ |
5073 | ha_rows records_sent_to_unique; |
5074 | |
5075 | /* total cost of the scans of indexes from the partial index intersection */ |
5076 | double index_read_cost; |
5077 | |
5078 | bool use_cpk_filter; /* cpk filter is to be used for this scan */ |
5079 | bool in_memory; /* uses unique object in memory */ |
5080 | double in_memory_cost; /* cost of using unique object in memory */ |
5081 | |
5082 | key_map filtered_scans; /* scans to be filtered by cpk conditions */ |
5083 | |
5084 | MY_BITMAP *intersect_fields; /* bitmap of fields used in intersection */ |
5085 | } PARTIAL_INDEX_INTERSECT_INFO; |
5086 | |
5087 | |
5088 | /* Check whether two indexes have the same first n components */ |
5089 | |
5090 | static |
5091 | bool same_index_prefix(KEY *key1, KEY *key2, uint used_parts) |
5092 | { |
5093 | KEY_PART_INFO *part1= key1->key_part; |
5094 | KEY_PART_INFO *part2= key2->key_part; |
5095 | for(uint i= 0; i < used_parts; i++, part1++, part2++) |
5096 | { |
5097 | if (part1->fieldnr != part2->fieldnr) |
5098 | return FALSE; |
5099 | } |
5100 | return TRUE; |
5101 | } |
5102 | |
5103 | |
5104 | /* Create a bitmap for all fields of a table */ |
5105 | |
5106 | static |
5107 | bool create_fields_bitmap(PARAM *param, MY_BITMAP *fields_bitmap) |
5108 | { |
5109 | my_bitmap_map *bitmap_buf; |
5110 | |
5111 | if (!(bitmap_buf= (my_bitmap_map *) alloc_root(param->mem_root, |
5112 | param->fields_bitmap_size))) |
5113 | return TRUE; |
5114 | if (my_bitmap_init(fields_bitmap, bitmap_buf, param->table->s->fields, FALSE)) |
5115 | return TRUE; |
5116 | |
5117 | return FALSE; |
5118 | } |
5119 | |
5120 | /* Compare two indexes scans for sort before search for the best intersection */ |
5121 | |
5122 | static |
5123 | int cmp_intersect_index_scan(INDEX_SCAN_INFO **a, INDEX_SCAN_INFO **b) |
5124 | { |
5125 | return (*a)->records < (*b)->records ? |
5126 | -1 : (*a)->records == (*b)->records ? 0 : 1; |
5127 | } |
5128 | |
5129 | |
5130 | static inline |
5131 | void set_field_bitmap_for_index_prefix(MY_BITMAP *field_bitmap, |
5132 | KEY_PART_INFO *key_part, |
5133 | uint used_key_parts) |
5134 | { |
5135 | bitmap_clear_all(field_bitmap); |
5136 | for (KEY_PART_INFO *key_part_end= key_part+used_key_parts; |
5137 | key_part < key_part_end; key_part++) |
5138 | { |
5139 | bitmap_set_bit(field_bitmap, key_part->fieldnr-1); |
5140 | } |
5141 | } |
5142 | |
5143 | |
5144 | /* |
5145 | Round up table cardinality read from statistics provided by engine. |
5146 | This function should go away when mysql test will allow to handle |
5147 | more or less easily in the test suites deviations of InnoDB |
5148 | statistical data. |
5149 | */ |
5150 | |
5151 | static inline |
5152 | ha_rows get_table_cardinality_for_index_intersect(TABLE *table) |
5153 | { |
5154 | if (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) |
5155 | return table->stat_records(); |
5156 | else |
5157 | { |
5158 | ha_rows d; |
5159 | double q; |
5160 | for (q= (double)table->stat_records(), d= 1 ; q >= 10; q/= 10, d*= 10 ) ; |
5161 | return (ha_rows) (floor(q+0.5) * d); |
5162 | } |
5163 | } |
5164 | |
5165 | |
5166 | static |
5167 | ha_rows records_in_index_intersect_extension(PARTIAL_INDEX_INTERSECT_INFO *curr, |
5168 | INDEX_SCAN_INFO *ext_index_scan); |
5169 | |
5170 | /* |
5171 | Prepare to search for the best index intersection |
5172 | |
5173 | SYNOPSIS |
5174 | prepare_search_best_index_intersect() |
5175 | param common info about index ranges |
5176 | tree tree of ranges for indexes than can be intersected |
5177 | common OUT info needed for search to be filled by the function |
5178 | init OUT info for an initial pseudo step of the intersection plans |
5179 | cutoff_cost cut off cost of the interesting index intersection |
5180 | |
5181 | DESCRIPTION |
5182 | The function initializes all fields of the structure 'common' to be used |
5183 | when searching for the best intersection plan. It also allocates |
5184 | memory to store the most cheap index intersection. |
5185 | |
5186 | NOTES |
5187 | When selecting candidates for index intersection we always take only |
5188 | one representative out of any set of indexes that share the same range |
5189 | conditions. These indexes always have the same prefixes and the |
5190 | components of this prefixes are exactly those used in these range |
5191 | conditions. |
5192 | Range conditions over clustered primary key (cpk) is always used only |
5193 | as the condition that filters out some rowids retrieved by the scans |
5194 | for secondary indexes. The cpk index will be handled in special way by |
5195 | the function that search for the best index intersection. |
5196 | |
5197 | RETURN |
5198 | FALSE in the case of success |
5199 | TRUE otherwise |
5200 | */ |
5201 | |
5202 | static |
5203 | bool prepare_search_best_index_intersect(PARAM *param, |
5204 | SEL_TREE *tree, |
5205 | COMMON_INDEX_INTERSECT_INFO *common, |
5206 | PARTIAL_INDEX_INTERSECT_INFO *init, |
5207 | double cutoff_cost) |
5208 | { |
5209 | uint i; |
5210 | uint n_search_scans; |
5211 | double cost; |
5212 | INDEX_SCAN_INFO **index_scan; |
5213 | INDEX_SCAN_INFO **scan_ptr; |
5214 | INDEX_SCAN_INFO *cpk_scan= NULL; |
5215 | TABLE *table= param->table; |
5216 | uint n_index_scans= (uint)(tree->index_scans_end - tree->index_scans); |
5217 | |
5218 | if (!n_index_scans) |
5219 | return 1; |
5220 | |
5221 | bzero(init, sizeof(*init)); |
5222 | init->filtered_scans.init(); |
5223 | init->common_info= common; |
5224 | init->cost= cutoff_cost; |
5225 | |
5226 | common->param= param; |
5227 | common->key_size= table->file->ref_length; |
5228 | common->compare_factor= TIME_FOR_COMPARE_ROWID; |
5229 | common->max_memory_size= (size_t)param->thd->variables.sortbuff_size; |
5230 | common->cutoff_cost= cutoff_cost; |
5231 | common->cpk_scan= NULL; |
5232 | common->table_cardinality= |
5233 | get_table_cardinality_for_index_intersect(table); |
5234 | |
5235 | if (n_index_scans <= 1) |
5236 | return TRUE; |
5237 | |
5238 | if (table->file->primary_key_is_clustered()) |
5239 | { |
5240 | INDEX_SCAN_INFO **index_scan_end; |
5241 | index_scan= tree->index_scans; |
5242 | index_scan_end= index_scan+n_index_scans; |
5243 | for ( ; index_scan < index_scan_end; index_scan++) |
5244 | { |
5245 | if ((*index_scan)->keynr == table->s->primary_key) |
5246 | { |
5247 | common->cpk_scan= cpk_scan= *index_scan; |
5248 | break; |
5249 | } |
5250 | } |
5251 | } |
5252 | |
5253 | i= n_index_scans - MY_TEST(cpk_scan != NULL) + 1; |
5254 | |
5255 | if (!(common->search_scans = |
5256 | (INDEX_SCAN_INFO **) alloc_root (param->mem_root, |
5257 | sizeof(INDEX_SCAN_INFO *) * i))) |
5258 | return TRUE; |
5259 | bzero(common->search_scans, sizeof(INDEX_SCAN_INFO *) * i); |
5260 | |
5261 | INDEX_SCAN_INFO **selected_index_scans= common->search_scans; |
5262 | |
5263 | for (i=0, index_scan= tree->index_scans; i < n_index_scans; i++, index_scan++) |
5264 | { |
5265 | uint used_key_parts= (*index_scan)->used_key_parts; |
5266 | KEY *key_info= (*index_scan)->key_info; |
5267 | |
5268 | if (*index_scan == cpk_scan) |
5269 | continue; |
5270 | if (cpk_scan && cpk_scan->used_key_parts >= used_key_parts && |
5271 | same_index_prefix(cpk_scan->key_info, key_info, used_key_parts)) |
5272 | continue; |
5273 | |
5274 | cost= table->file->keyread_time((*index_scan)->keynr, |
5275 | (*index_scan)->range_count, |
5276 | (*index_scan)->records); |
5277 | if (cost >= cutoff_cost) |
5278 | continue; |
5279 | |
5280 | for (scan_ptr= selected_index_scans; *scan_ptr ; scan_ptr++) |
5281 | { |
5282 | /* |
5283 | When we have range conditions for two different indexes with the same |
5284 | beginning it does not make sense to consider both of them for index |
5285 | intersection if the range conditions are covered by common initial |
5286 | components of the indexes. Actually in this case the indexes are |
5287 | guaranteed to have the same range conditions. |
5288 | */ |
5289 | if ((*scan_ptr)->used_key_parts == used_key_parts && |
5290 | same_index_prefix((*scan_ptr)->key_info, key_info, used_key_parts)) |
5291 | break; |
5292 | } |
5293 | if (!*scan_ptr || cost < (*scan_ptr)->index_read_cost) |
5294 | { |
5295 | *scan_ptr= *index_scan; |
5296 | (*scan_ptr)->index_read_cost= cost; |
5297 | } |
5298 | } |
5299 | |
5300 | ha_rows records_in_scans= 0; |
5301 | |
5302 | for (scan_ptr=selected_index_scans, i= 0; *scan_ptr; scan_ptr++, i++) |
5303 | { |
5304 | if (create_fields_bitmap(param, &(*scan_ptr)->used_fields)) |
5305 | return TRUE; |
5306 | records_in_scans+= (*scan_ptr)->records; |
5307 | } |
5308 | n_search_scans= i; |
5309 | |
5310 | if (cpk_scan && create_fields_bitmap(param, &cpk_scan->used_fields)) |
5311 | return TRUE; |
5312 | |
5313 | if (!(common->n_search_scans= n_search_scans)) |
5314 | return TRUE; |
5315 | |
5316 | common->best_uses_cpk= FALSE; |
5317 | common->best_cost= cutoff_cost + COST_EPS; |
5318 | common->best_length= 0; |
5319 | |
5320 | if (!(common->best_intersect= |
5321 | (INDEX_SCAN_INFO **) alloc_root (param->mem_root, |
5322 | sizeof(INDEX_SCAN_INFO *) * |
5323 | (i + MY_TEST(cpk_scan != NULL))))) |
5324 | return TRUE; |
5325 | |
5326 | size_t calc_cost_buff_size= |
5327 | Unique::get_cost_calc_buff_size((size_t)records_in_scans, |
5328 | common->key_size, |
5329 | common->max_memory_size); |
5330 | if (!(common->buff_elems= (uint *) alloc_root(param->mem_root, |
5331 | calc_cost_buff_size))) |
5332 | return TRUE; |
5333 | |
5334 | my_qsort(selected_index_scans, n_search_scans, sizeof(INDEX_SCAN_INFO *), |
5335 | (qsort_cmp) cmp_intersect_index_scan); |
5336 | |
5337 | if (cpk_scan) |
5338 | { |
5339 | PARTIAL_INDEX_INTERSECT_INFO curr; |
5340 | set_field_bitmap_for_index_prefix(&cpk_scan->used_fields, |
5341 | cpk_scan->key_info->key_part, |
5342 | cpk_scan->used_key_parts); |
5343 | curr.common_info= common; |
5344 | curr.intersect_fields= &cpk_scan->used_fields; |
5345 | curr.records= cpk_scan->records; |
5346 | curr.length= 1; |
5347 | for (scan_ptr=selected_index_scans; *scan_ptr; scan_ptr++) |
5348 | { |
5349 | ha_rows scan_records= (*scan_ptr)->records; |
5350 | ha_rows records= records_in_index_intersect_extension(&curr, *scan_ptr); |
5351 | (*scan_ptr)->filtered_out= records >= scan_records ? |
5352 | 0 : scan_records-records; |
5353 | } |
5354 | } |
5355 | else |
5356 | { |
5357 | for (scan_ptr=selected_index_scans; *scan_ptr; scan_ptr++) |
5358 | (*scan_ptr)->filtered_out= 0; |
5359 | } |
5360 | |
5361 | return FALSE; |
5362 | } |
5363 | |
5364 | |
5365 | /* |
5366 | On Estimation of the Number of Records in an Index Intersection |
5367 | =============================================================== |
5368 | |
5369 | Consider query Q over table t. Let C be the WHERE condition of this query, |
5370 | and, idx1(a1_1,...,a1_k1) and idx2(a2_1,...,a2_k2) be some indexes defined |
5371 | on table t. |
5372 | Let rt1 and rt2 be the range trees extracted by the range optimizer from C |
5373 | for idx1 and idx2 respectively. |
5374 | Let #t be the estimate of the number of records in table t provided for the |
5375 | optimizer. |
5376 | Let #r1 and #r2 be the estimates of the number of records in the range trees |
5377 | rt1 and rt2, respectively, obtained by the range optimizer. |
5378 | |
5379 | We need to get an estimate for the number of records in the index |
5380 | intersection of rt1 and rt2. In other words, we need to estimate the |
5381 | cardinality of the set of records that are in both trees. Let's designate |
5382 | this number by #r. |
5383 | |
5384 | If we do not make any assumptions then we can only state that |
5385 | #r<=MY_MIN(#r1,#r2). |
5386 | With this estimate we can't say that the index intersection scan will be |
5387 | cheaper than the cheapest index scan. |
5388 | |
5389 | Let Rt1 and Rt2 be AND/OR conditions representing rt and rt2 respectively. |
5390 | The probability that a record belongs to rt1 is sel(Rt1)=#r1/#t. |
5391 | The probability that a record belongs to rt2 is sel(Rt2)=#r2/#t. |
5392 | |
5393 | If we assume that the values in columns of idx1 and idx2 are independent |
5394 | then #r/#t=sel(Rt1&Rt2)=sel(Rt1)*sel(Rt2)=(#r1/#t)*(#r2/#t). |
5395 | So in this case we have: #r=#r1*#r2/#t. |
5396 | |
5397 | The above assumption of independence of the columns in idx1 and idx2 means |
5398 | that: |
5399 | - all columns are different |
5400 | - values from one column do not correlate with values from any other column. |
5401 | |
5402 | We can't help with the case when column correlate with each other. |
5403 | Yet, if they are assumed to be uncorrelated the value of #r theoretically can |
5404 | be evaluated . Unfortunately this evaluation, in general, is rather complex. |
5405 | |
5406 | Let's consider two indexes idx1:(dept, manager), idx2:(dept, building) |
5407 | over table 'employee' and two range conditions over these indexes: |
5408 | Rt1: dept=10 AND manager LIKE 'S%' |
5409 | Rt2: dept=10 AND building LIKE 'L%'. |
5410 | We can state that: |
5411 | sel(Rt1&Rt2)=sel(dept=10)*sel(manager LIKE 'S%')*sel(building LIKE 'L%') |
5412 | =sel(Rt1)*sel(Rt2)/sel(dept=10). |
5413 | sel(Rt1/2_0:dept=10) can be estimated if we know the cardinality #r1_0 of |
5414 | the range for sub-index idx1_0 (dept) of the index idx1 or the cardinality |
5415 | #rt2_0 of the same range for sub-index idx2_0(dept) of the index idx2. |
5416 | The current code does not make an estimate either for #rt1_0, or for #rt2_0, |
5417 | but it can be adjusted to provide those numbers. |
5418 | Alternatively, MY_MIN(rec_per_key) for (dept) could be used to get an upper |
5419 | bound for the value of sel(Rt1&Rt2). Yet this statistics is not provided |
5420 | now. |
5421 | |
5422 | Let's consider two other indexes idx1:(dept, last_name), |
5423 | idx2:(first_name, last_name) and two range conditions over these indexes: |
5424 | Rt1: dept=5 AND last_name='Sm%' |
5425 | Rt2: first_name='Robert' AND last_name='Sm%'. |
5426 | |
5427 | sel(Rt1&Rt2)=sel(dept=5)*sel(last_name='Sm5')*sel(first_name='Robert') |
5428 | =sel(Rt2)*sel(dept=5) |
5429 | Here MY_MAX(rec_per_key) for (dept) could be used to get an upper bound for |
5430 | the value of sel(Rt1&Rt2). |
5431 | |
5432 | When the intersected indexes have different major columns, but some |
5433 | minor column are common the picture may be more complicated. |
5434 | |
5435 | Let's consider the following range conditions for the same indexes as in |
5436 | the previous example: |
5437 | Rt1: (Rt11: dept=5 AND last_name='So%') |
5438 | OR |
5439 | (Rt12: dept=7 AND last_name='Saw%') |
5440 | Rt2: (Rt21: first_name='Robert' AND last_name='Saw%') |
5441 | OR |
5442 | (Rt22: first_name='Bob' AND last_name='So%') |
5443 | Here we have: |
5444 | sel(Rt1&Rt2)= sel(Rt11)*sel(Rt21)+sel(Rt22)*sel(dept=5) + |
5445 | sel(Rt21)*sel(dept=7)+sel(Rt12)*sel(Rt22) |
5446 | Now consider the range condition: |
5447 | Rt1_0: (dept=5 OR dept=7) |
5448 | For this condition we can state that: |
5449 | sel(Rt1_0&Rt2)=(sel(dept=5)+sel(dept=7))*(sel(Rt21)+sel(Rt22))= |
5450 | sel(dept=5)*sel(Rt21)+sel(dept=7)*sel(Rt21)+ |
5451 | sel(dept=5)*sel(Rt22)+sel(dept=7)*sel(Rt22)= |
5452 | sel(dept=5)*sel(Rt21)+sel(Rt21)*sel(dept=7)+ |
5453 | sel(Rt22)*sel(dept=5)+sel(dept=7)*sel(Rt22) > |
5454 | sel(Rt11)*sel(Rt21)+sel(Rt22)*sel(dept=5)+ |
5455 | sel(Rt21)*sel(dept=7)+sel(Rt12)*sel(Rt22) > |
5456 | sel(Rt1 & Rt2) |
5457 | |
5458 | We've just demonstrated for an example what is intuitively almost obvious |
5459 | in general. We can remove the ending parts fromrange trees getting less |
5460 | selective range conditions for sub-indexes. |
5461 | So if not a most major component with the number k of an index idx is |
5462 | encountered in the index with which we intersect we can use the sub-index |
5463 | idx_k-1 that includes the components of idx up to the i-th component and |
5464 | the range tree for idx_k-1 to make an upper bound estimate for the number |
5465 | of records in the index intersection. |
5466 | The range tree for idx_k-1 we use here is the subtree of the original range |
5467 | tree for idx that contains only parts from the first k-1 components. |
5468 | |
5469 | As it was mentioned above the range optimizer currently does not provide |
5470 | an estimate for the number of records in the ranges for sub-indexes. |
5471 | However, some reasonable upper bound estimate can be obtained. |
5472 | |
5473 | Let's consider the following range tree: |
5474 | Rt: (first_name='Robert' AND last_name='Saw%') |
5475 | OR |
5476 | (first_name='Bob' AND last_name='So%') |
5477 | Let #r be the number of records in Rt. Let f_1 be the fan-out of column |
5478 | last_name: |
5479 | f_1 = rec_per_key[first_name]/rec_per_key[last_name]. |
5480 | The the number of records in the range tree: |
5481 | Rt_0: (first_name='Robert' OR first_name='Bob') |
5482 | for the sub-index (first_name) is not greater than MY_MAX(#r*f_1, #t). |
5483 | Strictly speaking, we can state only that it's not greater than |
5484 | MY_MAX(#r*max_f_1, #t), where |
5485 | max_f_1= max_rec_per_key[first_name]/min_rec_per_key[last_name]. |
5486 | Yet, if #r/#t is big enough (and this is the case of an index intersection, |
5487 | because using this index range with a single index scan is cheaper than |
5488 | the cost of the intersection when #r/#t is small) then almost safely we |
5489 | can use here f_1 instead of max_f_1. |
5490 | |
5491 | The above considerations can be used in future development. Now, they are |
5492 | used partly in the function that provides a rough upper bound estimate for |
5493 | the number of records in an index intersection that follow below. |
5494 | */ |
5495 | |
5496 | /* |
5497 | Estimate the number of records selected by an extension a partial intersection |
5498 | |
5499 | SYNOPSIS |
5500 | records_in_index_intersect_extension() |
5501 | curr partial intersection plan to be extended |
5502 | ext_index_scan the evaluated extension of this partial plan |
5503 | |
5504 | DESCRIPTION |
5505 | The function provides an estimate for the number of records in the |
5506 | intersection of the partial index intersection curr with the index |
5507 | ext_index_scan. If all intersected indexes does not have common columns |
5508 | then the function returns an exact estimate (assuming there are no |
5509 | correlations between values in the columns). If the intersected indexes |
5510 | have common columns the function returns an upper bound for the number |
5511 | of records in the intersection provided that the intersection of curr |
5512 | with ext_index_scan can is expected to have less records than the expected |
5513 | number of records in the partial intersection curr. In this case the |
5514 | function also assigns the bitmap of the columns in the extended |
5515 | intersection to ext_index_scan->used_fields. |
5516 | If the function cannot expect that the number of records in the extended |
5517 | intersection is less that the expected number of records #r in curr then |
5518 | the function returns a number bigger than #r. |
5519 | |
5520 | NOTES |
5521 | See the comment before the desription of the function that explains the |
5522 | reasoning used by this function. |
5523 | |
5524 | RETURN |
5525 | The expected number of rows in the extended index intersection |
5526 | */ |
5527 | |
5528 | static |
5529 | ha_rows records_in_index_intersect_extension(PARTIAL_INDEX_INTERSECT_INFO *curr, |
5530 | INDEX_SCAN_INFO *ext_index_scan) |
5531 | { |
5532 | KEY *key_info= ext_index_scan->key_info; |
5533 | KEY_PART_INFO* key_part= key_info->key_part; |
5534 | uint used_key_parts= ext_index_scan->used_key_parts; |
5535 | MY_BITMAP *used_fields= &ext_index_scan->used_fields; |
5536 | |
5537 | if (!curr->length) |
5538 | { |
5539 | /* |
5540 | If this the first index in the intersection just mark the |
5541 | fields in the used_fields bitmap and return the expected |
5542 | number of records in the range scan for the index provided |
5543 | by the range optimizer. |
5544 | */ |
5545 | set_field_bitmap_for_index_prefix(used_fields, key_part, used_key_parts); |
5546 | return ext_index_scan->records; |
5547 | } |
5548 | |
5549 | uint i; |
5550 | bool better_selectivity= FALSE; |
5551 | ha_rows records= curr->records; |
5552 | MY_BITMAP *curr_intersect_fields= curr->intersect_fields; |
5553 | for (i= 0; i < used_key_parts; i++, key_part++) |
5554 | { |
5555 | if (bitmap_is_set(curr_intersect_fields, key_part->fieldnr-1)) |
5556 | break; |
5557 | } |
5558 | if (i) |
5559 | { |
5560 | ha_rows table_cardinality= curr->common_info->table_cardinality; |
5561 | ha_rows ext_records= ext_index_scan->records; |
5562 | if (i < used_key_parts) |
5563 | { |
5564 | double f1= key_info->actual_rec_per_key(i-1); |
5565 | double f2= key_info->actual_rec_per_key(i); |
5566 | ext_records= (ha_rows) ((double) ext_records / f2 * f1); |
5567 | } |
5568 | if (ext_records < table_cardinality) |
5569 | { |
5570 | better_selectivity= TRUE; |
5571 | records= (ha_rows) ((double) records / table_cardinality * |
5572 | ext_records); |
5573 | bitmap_copy(used_fields, curr_intersect_fields); |
5574 | key_part= key_info->key_part; |
5575 | for (uint j= 0; j < used_key_parts; j++, key_part++) |
5576 | bitmap_set_bit(used_fields, key_part->fieldnr-1); |
5577 | } |
5578 | } |
5579 | return !better_selectivity ? records+1 : |
5580 | !records ? 1 : records; |
5581 | } |
5582 | |
5583 | |
5584 | /* |
5585 | Estimate the cost a binary search within disjoint cpk range intervals |
5586 | |
5587 | Number of comparisons to check whether a cpk value satisfies |
5588 | the cpk range condition = log2(cpk_scan->range_count). |
5589 | */ |
5590 | |
5591 | static inline |
5592 | double get_cpk_filter_cost(ha_rows filtered_records, |
5593 | INDEX_SCAN_INFO *cpk_scan, |
5594 | double compare_factor) |
5595 | { |
5596 | return log((double) (cpk_scan->range_count+1)) / (compare_factor * M_LN2) * |
5597 | filtered_records; |
5598 | } |
5599 | |
5600 | |
5601 | /* |
5602 | Check whether a patial index intersection plan can be extended |
5603 | |
5604 | SYNOPSIS |
5605 | check_index_intersect_extension() |
5606 | curr partial intersection plan to be extended |
5607 | ext_index_scan a possible extension of this plan to be checked |
5608 | next OUT the structure to be filled for the extended plan |
5609 | |
5610 | DESCRIPTION |
5611 | The function checks whether it makes sense to extend the index |
5612 | intersection plan adding the index ext_index_scan, and, if this |
5613 | the case, the function fills in the structure for the extended plan. |
5614 | |
5615 | RETURN |
5616 | TRUE if it makes sense to extend the given plan |
5617 | FALSE otherwise |
5618 | */ |
5619 | |
5620 | static |
5621 | bool check_index_intersect_extension(PARTIAL_INDEX_INTERSECT_INFO *curr, |
5622 | INDEX_SCAN_INFO *ext_index_scan, |
5623 | PARTIAL_INDEX_INTERSECT_INFO *next) |
5624 | { |
5625 | ha_rows records; |
5626 | ha_rows records_sent_to_unique; |
5627 | double cost; |
5628 | ha_rows ext_index_scan_records= ext_index_scan->records; |
5629 | ha_rows records_filtered_out_by_cpk= ext_index_scan->filtered_out; |
5630 | COMMON_INDEX_INTERSECT_INFO *common_info= curr->common_info; |
5631 | double cutoff_cost= common_info->cutoff_cost; |
5632 | uint idx= curr->length; |
5633 | next->index_read_cost= curr->index_read_cost+ext_index_scan->index_read_cost; |
5634 | if (next->index_read_cost > cutoff_cost) |
5635 | return FALSE; |
5636 | |
5637 | if ((next->in_memory= curr->in_memory)) |
5638 | next->in_memory_cost= curr->in_memory_cost; |
5639 | |
5640 | next->intersect_fields= &ext_index_scan->used_fields; |
5641 | next->filtered_scans= curr->filtered_scans; |
5642 | |
5643 | records_sent_to_unique= curr->records_sent_to_unique; |
5644 | |
5645 | next->use_cpk_filter= FALSE; |
5646 | |
5647 | /* Calculate the cost of using a Unique object for index intersection */ |
5648 | if (idx && next->in_memory) |
5649 | { |
5650 | /* |
5651 | All rowids received from the first scan are expected in one unique tree |
5652 | */ |
5653 | ha_rows elems_in_tree= common_info->search_scans[0]->records- |
5654 | common_info->search_scans[0]->filtered_out ; |
5655 | next->in_memory_cost+= Unique::get_search_cost(elems_in_tree, |
5656 | common_info->compare_factor)* |
5657 | ext_index_scan_records; |
5658 | cost= next->in_memory_cost; |
5659 | } |
5660 | else |
5661 | { |
5662 | uint *buff_elems= common_info->buff_elems; |
5663 | uint key_size= common_info->key_size; |
5664 | uint compare_factor= common_info->compare_factor; |
5665 | size_t max_memory_size= common_info->max_memory_size; |
5666 | |
5667 | records_sent_to_unique+= ext_index_scan_records; |
5668 | cost= Unique::get_use_cost(buff_elems, (size_t) records_sent_to_unique, key_size, |
5669 | max_memory_size, compare_factor, TRUE, |
5670 | &next->in_memory); |
5671 | if (records_filtered_out_by_cpk) |
5672 | { |
5673 | /* Check whether using cpk filter for this scan is beneficial */ |
5674 | |
5675 | double cost2; |
5676 | bool in_memory2; |
5677 | ha_rows records2= records_sent_to_unique-records_filtered_out_by_cpk; |
5678 | cost2= Unique::get_use_cost(buff_elems, (size_t) records2, key_size, |
5679 | max_memory_size, compare_factor, TRUE, |
5680 | &in_memory2); |
5681 | cost2+= get_cpk_filter_cost(ext_index_scan_records, common_info->cpk_scan, |
5682 | compare_factor); |
5683 | if (cost > cost2 + COST_EPS) |
5684 | { |
5685 | cost= cost2; |
5686 | next->in_memory= in_memory2; |
5687 | next->use_cpk_filter= TRUE; |
5688 | records_sent_to_unique= records2; |
5689 | } |
5690 | |
5691 | } |
5692 | if (next->in_memory) |
5693 | next->in_memory_cost= cost; |
5694 | } |
5695 | |
5696 | if (next->use_cpk_filter) |
5697 | { |
5698 | next->filtered_scans.set_bit(ext_index_scan->keynr); |
5699 | bitmap_union(&ext_index_scan->used_fields, |
5700 | &common_info->cpk_scan->used_fields); |
5701 | } |
5702 | next->records_sent_to_unique= records_sent_to_unique; |
5703 | |
5704 | records= records_in_index_intersect_extension(curr, ext_index_scan); |
5705 | if (idx && records > curr->records) |
5706 | return FALSE; |
5707 | if (next->use_cpk_filter && curr->filtered_scans.is_clear_all()) |
5708 | records-= records_filtered_out_by_cpk; |
5709 | next->records= records; |
5710 | |
5711 | cost+= next->index_read_cost; |
5712 | if (cost >= cutoff_cost) |
5713 | return FALSE; |
5714 | |
5715 | cost+= get_sweep_read_cost(common_info->param, records); |
5716 | |
5717 | next->cost= cost; |
5718 | next->length= curr->length+1; |
5719 | |
5720 | return TRUE; |
5721 | } |
5722 | |
5723 | |
5724 | /* |
5725 | Search for the cheapest extensions of range scans used to access a table |
5726 | |
5727 | SYNOPSIS |
5728 | find_index_intersect_best_extension() |
5729 | curr partial intersection to evaluate all possible extension for |
5730 | |
5731 | DESCRIPTION |
5732 | The function tries to extend the partial plan curr in all possible ways |
5733 | to look for a cheapest index intersection whose cost less than the |
5734 | cut off value set in curr->common_info.cutoff_cost. |
5735 | */ |
5736 | |
5737 | static |
5738 | void find_index_intersect_best_extension(PARTIAL_INDEX_INTERSECT_INFO *curr) |
5739 | { |
5740 | PARTIAL_INDEX_INTERSECT_INFO next; |
5741 | COMMON_INDEX_INTERSECT_INFO *common_info= curr->common_info; |
5742 | INDEX_SCAN_INFO **index_scans= common_info->search_scans; |
5743 | uint idx= curr->length; |
5744 | INDEX_SCAN_INFO **rem_first_index_scan_ptr= &index_scans[idx]; |
5745 | double cost= curr->cost; |
5746 | |
5747 | if (cost + COST_EPS < common_info->best_cost) |
5748 | { |
5749 | common_info->best_cost= cost; |
5750 | common_info->best_length= curr->length; |
5751 | common_info->best_records= curr->records; |
5752 | common_info->filtered_scans= curr->filtered_scans; |
5753 | /* common_info->best_uses_cpk <=> at least one scan uses a cpk filter */ |
5754 | common_info->best_uses_cpk= !curr->filtered_scans.is_clear_all(); |
5755 | uint sz= sizeof(INDEX_SCAN_INFO *) * curr->length; |
5756 | memcpy(common_info->best_intersect, common_info->search_scans, sz); |
5757 | common_info->cutoff_cost= cost; |
5758 | } |
5759 | |
5760 | if (!(*rem_first_index_scan_ptr)) |
5761 | return; |
5762 | |
5763 | next.common_info= common_info; |
5764 | |
5765 | INDEX_SCAN_INFO *rem_first_index_scan= *rem_first_index_scan_ptr; |
5766 | for (INDEX_SCAN_INFO **index_scan_ptr= rem_first_index_scan_ptr; |
5767 | *index_scan_ptr; index_scan_ptr++) |
5768 | { |
5769 | *rem_first_index_scan_ptr= *index_scan_ptr; |
5770 | *index_scan_ptr= rem_first_index_scan; |
5771 | if (check_index_intersect_extension(curr, *rem_first_index_scan_ptr, &next)) |
5772 | find_index_intersect_best_extension(&next); |
5773 | *index_scan_ptr= *rem_first_index_scan_ptr; |
5774 | *rem_first_index_scan_ptr= rem_first_index_scan; |
5775 | } |
5776 | } |
5777 | |
5778 | |
5779 | /* |
5780 | Get the plan of the best intersection of range scans used to access a table |
5781 | |
5782 | SYNOPSIS |
5783 | get_best_index_intersect() |
5784 | param common info about index ranges |
5785 | tree tree of ranges for indexes than can be intersected |
5786 | read_time cut off value for the evaluated plans |
5787 | |
5788 | DESCRIPTION |
5789 | The function looks for the cheapest index intersection of the range |
5790 | scans to access a table. The info about the ranges for all indexes |
5791 | is provided by the range optimizer and is passed through the |
5792 | parameters param and tree. Any plan whose cost is greater than read_time |
5793 | is rejected. |
5794 | After the best index intersection is found the function constructs |
5795 | the structure that manages the execution by the chosen plan. |
5796 | |
5797 | RETURN |
5798 | Pointer to the generated execution structure if a success, |
5799 | 0 - otherwise. |
5800 | */ |
5801 | |
5802 | static |
5803 | TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree, |
5804 | double read_time) |
5805 | { |
5806 | uint i; |
5807 | uint count; |
5808 | TRP_RANGE **cur_range; |
5809 | TRP_RANGE **range_scans; |
5810 | INDEX_SCAN_INFO *index_scan; |
5811 | COMMON_INDEX_INTERSECT_INFO common; |
5812 | PARTIAL_INDEX_INTERSECT_INFO init; |
5813 | TRP_INDEX_INTERSECT *intersect_trp= NULL; |
5814 | TABLE *table= param->table; |
5815 | |
5816 | |
5817 | DBUG_ENTER("get_best_index_intersect" ); |
5818 | |
5819 | if (prepare_search_best_index_intersect(param, tree, &common, &init, |
5820 | read_time)) |
5821 | DBUG_RETURN(NULL); |
5822 | |
5823 | find_index_intersect_best_extension(&init); |
5824 | |
5825 | if (common.best_length <= 1 && !common.best_uses_cpk) |
5826 | DBUG_RETURN(NULL); |
5827 | |
5828 | if (common.best_uses_cpk) |
5829 | { |
5830 | memmove((char *) (common.best_intersect+1), (char *) common.best_intersect, |
5831 | sizeof(INDEX_SCAN_INFO *) * common.best_length); |
5832 | common.best_intersect[0]= common.cpk_scan; |
5833 | common.best_length++; |
5834 | } |
5835 | |
5836 | count= common.best_length; |
5837 | |
5838 | if (!(range_scans= (TRP_RANGE**)alloc_root(param->mem_root, |
5839 | sizeof(TRP_RANGE *)* |
5840 | count))) |
5841 | DBUG_RETURN(NULL); |
5842 | |
5843 | for (i= 0, cur_range= range_scans; i < count; i++) |
5844 | { |
5845 | index_scan= common.best_intersect[i]; |
5846 | if ((*cur_range= new (param->mem_root) TRP_RANGE(index_scan->sel_arg, |
5847 | index_scan->idx, 0))) |
5848 | { |
5849 | TRP_RANGE *trp= *cur_range; |
5850 | trp->read_cost= index_scan->index_read_cost; |
5851 | trp->records= index_scan->records; |
5852 | trp->is_ror= FALSE; |
5853 | trp->mrr_buf_size= 0; |
5854 | table->intersect_keys.set_bit(index_scan->keynr); |
5855 | cur_range++; |
5856 | } |
5857 | } |
5858 | |
5859 | count= (uint)(tree->index_scans_end - tree->index_scans); |
5860 | for (i= 0; i < count; i++) |
5861 | { |
5862 | index_scan= tree->index_scans[i]; |
5863 | if (!table->intersect_keys.is_set(index_scan->keynr)) |
5864 | { |
5865 | for (uint j= 0; j < common.best_length; j++) |
5866 | { |
5867 | INDEX_SCAN_INFO *scan= common.best_intersect[j]; |
5868 | if (same_index_prefix(index_scan->key_info, scan->key_info, |
5869 | scan->used_key_parts)) |
5870 | { |
5871 | table->intersect_keys.set_bit(index_scan->keynr); |
5872 | break; |
5873 | } |
5874 | } |
5875 | } |
5876 | } |
5877 | |
5878 | if ((intersect_trp= new (param->mem_root)TRP_INDEX_INTERSECT)) |
5879 | { |
5880 | intersect_trp->read_cost= common.best_cost; |
5881 | intersect_trp->records= common.best_records; |
5882 | intersect_trp->range_scans= range_scans; |
5883 | intersect_trp->range_scans_end= cur_range; |
5884 | intersect_trp->filtered_scans= common.filtered_scans; |
5885 | } |
5886 | DBUG_RETURN(intersect_trp); |
5887 | } |
5888 | |
5889 | |
5890 | typedef struct st_ror_scan_info : INDEX_SCAN_INFO |
5891 | { |
5892 | } ROR_SCAN_INFO; |
5893 | |
5894 | |
5895 | /* |
5896 | Create ROR_SCAN_INFO* structure with a single ROR scan on index idx using |
5897 | sel_arg set of intervals. |
5898 | |
5899 | SYNOPSIS |
5900 | make_ror_scan() |
5901 | param Parameter from test_quick_select function |
5902 | idx Index of key in param->keys |
5903 | sel_arg Set of intervals for a given key |
5904 | |
5905 | RETURN |
5906 | NULL - out of memory |
5907 | ROR scan structure containing a scan for {idx, sel_arg} |
5908 | */ |
5909 | |
5910 | static |
5911 | ROR_SCAN_INFO *make_ror_scan(const PARAM *param, int idx, SEL_ARG *sel_arg) |
5912 | { |
5913 | ROR_SCAN_INFO *ror_scan; |
5914 | my_bitmap_map *bitmap_buf; |
5915 | uint keynr; |
5916 | DBUG_ENTER("make_ror_scan" ); |
5917 | |
5918 | if (!(ror_scan= (ROR_SCAN_INFO*)alloc_root(param->mem_root, |
5919 | sizeof(ROR_SCAN_INFO)))) |
5920 | DBUG_RETURN(NULL); |
5921 | |
5922 | ror_scan->idx= idx; |
5923 | ror_scan->keynr= keynr= param->real_keynr[idx]; |
5924 | ror_scan->key_rec_length= (param->table->key_info[keynr].key_length + |
5925 | param->table->file->ref_length); |
5926 | ror_scan->sel_arg= sel_arg; |
5927 | ror_scan->records= param->quick_rows[keynr]; |
5928 | |
5929 | if (!(bitmap_buf= (my_bitmap_map*) alloc_root(param->mem_root, |
5930 | param->fields_bitmap_size))) |
5931 | DBUG_RETURN(NULL); |
5932 | |
5933 | if (my_bitmap_init(&ror_scan->covered_fields, bitmap_buf, |
5934 | param->table->s->fields, FALSE)) |
5935 | DBUG_RETURN(NULL); |
5936 | bitmap_clear_all(&ror_scan->covered_fields); |
5937 | |
5938 | KEY_PART_INFO *key_part= param->table->key_info[keynr].key_part; |
5939 | KEY_PART_INFO *key_part_end= key_part + |
5940 | param->table->key_info[keynr].user_defined_key_parts; |
5941 | for (;key_part != key_part_end; ++key_part) |
5942 | { |
5943 | if (bitmap_is_set(¶m->needed_fields, key_part->fieldnr-1)) |
5944 | bitmap_set_bit(&ror_scan->covered_fields, key_part->fieldnr-1); |
5945 | } |
5946 | ror_scan->index_read_cost= |
5947 | param->table->file->keyread_time(ror_scan->keynr, 1, ror_scan->records); |
5948 | DBUG_RETURN(ror_scan); |
5949 | } |
5950 | |
5951 | |
5952 | /* |
5953 | Compare two ROR_SCAN_INFO** by E(#records_matched) * key_record_length. |
5954 | SYNOPSIS |
5955 | cmp_ror_scan_info() |
5956 | a ptr to first compared value |
5957 | b ptr to second compared value |
5958 | |
5959 | RETURN |
5960 | -1 a < b |
5961 | 0 a = b |
5962 | 1 a > b |
5963 | */ |
5964 | |
5965 | static int cmp_ror_scan_info(ROR_SCAN_INFO** a, ROR_SCAN_INFO** b) |
5966 | { |
5967 | double val1= rows2double((*a)->records) * (*a)->key_rec_length; |
5968 | double val2= rows2double((*b)->records) * (*b)->key_rec_length; |
5969 | return (val1 < val2)? -1: (val1 == val2)? 0 : 1; |
5970 | } |
5971 | |
5972 | /* |
5973 | Compare two ROR_SCAN_INFO** by |
5974 | (#covered fields in F desc, |
5975 | #components asc, |
5976 | number of first not covered component asc) |
5977 | |
5978 | SYNOPSIS |
5979 | cmp_ror_scan_info_covering() |
5980 | a ptr to first compared value |
5981 | b ptr to second compared value |
5982 | |
5983 | RETURN |
5984 | -1 a < b |
5985 | 0 a = b |
5986 | 1 a > b |
5987 | */ |
5988 | |
5989 | static int cmp_ror_scan_info_covering(ROR_SCAN_INFO** a, ROR_SCAN_INFO** b) |
5990 | { |
5991 | if ((*a)->used_fields_covered > (*b)->used_fields_covered) |
5992 | return -1; |
5993 | if ((*a)->used_fields_covered < (*b)->used_fields_covered) |
5994 | return 1; |
5995 | if ((*a)->key_components < (*b)->key_components) |
5996 | return -1; |
5997 | if ((*a)->key_components > (*b)->key_components) |
5998 | return 1; |
5999 | if ((*a)->first_uncovered_field < (*b)->first_uncovered_field) |
6000 | return -1; |
6001 | if ((*a)->first_uncovered_field > (*b)->first_uncovered_field) |
6002 | return 1; |
6003 | return 0; |
6004 | } |
6005 | |
6006 | |
6007 | /* Auxiliary structure for incremental ROR-intersection creation */ |
6008 | typedef struct |
6009 | { |
6010 | const PARAM *param; |
6011 | MY_BITMAP covered_fields; /* union of fields covered by all scans */ |
6012 | /* |
6013 | Fraction of table records that satisfies conditions of all scans. |
6014 | This is the number of full records that will be retrieved if a |
6015 | non-index_only index intersection will be employed. |
6016 | */ |
6017 | double out_rows; |
6018 | /* TRUE if covered_fields is a superset of needed_fields */ |
6019 | bool is_covering; |
6020 | |
6021 | ha_rows index_records; /* sum(#records to look in indexes) */ |
6022 | double index_scan_costs; /* SUM(cost of 'index-only' scans) */ |
6023 | double total_cost; |
6024 | } ROR_INTERSECT_INFO; |
6025 | |
6026 | |
6027 | /* |
6028 | Allocate a ROR_INTERSECT_INFO and initialize it to contain zero scans. |
6029 | |
6030 | SYNOPSIS |
6031 | ror_intersect_init() |
6032 | param Parameter from test_quick_select |
6033 | |
6034 | RETURN |
6035 | allocated structure |
6036 | NULL on error |
6037 | */ |
6038 | |
6039 | static |
6040 | ROR_INTERSECT_INFO* ror_intersect_init(const PARAM *param) |
6041 | { |
6042 | ROR_INTERSECT_INFO *info; |
6043 | my_bitmap_map* buf; |
6044 | if (!(info= (ROR_INTERSECT_INFO*)alloc_root(param->mem_root, |
6045 | sizeof(ROR_INTERSECT_INFO)))) |
6046 | return NULL; |
6047 | info->param= param; |
6048 | if (!(buf= (my_bitmap_map*) alloc_root(param->mem_root, |
6049 | param->fields_bitmap_size))) |
6050 | return NULL; |
6051 | if (my_bitmap_init(&info->covered_fields, buf, param->table->s->fields, |
6052 | FALSE)) |
6053 | return NULL; |
6054 | info->is_covering= FALSE; |
6055 | info->index_scan_costs= 0.0; |
6056 | info->index_records= 0; |
6057 | info->out_rows= (double) param->table->stat_records(); |
6058 | bitmap_clear_all(&info->covered_fields); |
6059 | return info; |
6060 | } |
6061 | |
6062 | void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src) |
6063 | { |
6064 | dst->param= src->param; |
6065 | memcpy(dst->covered_fields.bitmap, src->covered_fields.bitmap, |
6066 | no_bytes_in_map(&src->covered_fields)); |
6067 | dst->out_rows= src->out_rows; |
6068 | dst->is_covering= src->is_covering; |
6069 | dst->index_records= src->index_records; |
6070 | dst->index_scan_costs= src->index_scan_costs; |
6071 | dst->total_cost= src->total_cost; |
6072 | } |
6073 | |
6074 | |
6075 | /* |
6076 | Get selectivity of a ROR scan wrt ROR-intersection. |
6077 | |
6078 | SYNOPSIS |
6079 | ror_scan_selectivity() |
6080 | info ROR-interection |
6081 | scan ROR scan |
6082 | |
6083 | NOTES |
6084 | Suppose we have a condition on several keys |
6085 | cond=k_11=c_11 AND k_12=c_12 AND ... // parts of first key |
6086 | k_21=c_21 AND k_22=c_22 AND ... // parts of second key |
6087 | ... |
6088 | k_n1=c_n1 AND k_n3=c_n3 AND ... (1) //parts of the key used by *scan |
6089 | |
6090 | where k_ij may be the same as any k_pq (i.e. keys may have common parts). |
6091 | |
6092 | A full row is retrieved if entire condition holds. |
6093 | |
6094 | The recursive procedure for finding P(cond) is as follows: |
6095 | |
6096 | First step: |
6097 | Pick 1st part of 1st key and break conjunction (1) into two parts: |
6098 | cond= (k_11=c_11 AND R) |
6099 | |
6100 | Here R may still contain condition(s) equivalent to k_11=c_11. |
6101 | Nevertheless, the following holds: |
6102 | |
6103 | P(k_11=c_11 AND R) = P(k_11=c_11) * P(R | k_11=c_11). |
6104 | |
6105 | Mark k_11 as fixed field (and satisfied condition) F, save P(F), |
6106 | save R to be cond and proceed to recursion step. |
6107 | |
6108 | Recursion step: |
6109 | We have a set of fixed fields/satisfied conditions) F, probability P(F), |
6110 | and remaining conjunction R |
6111 | Pick next key part on current key and its condition "k_ij=c_ij". |
6112 | We will add "k_ij=c_ij" into F and update P(F). |
6113 | Lets denote k_ij as t, R = t AND R1, where R1 may still contain t. Then |
6114 | |
6115 | P((t AND R1)|F) = P(t|F) * P(R1|t|F) = P(t|F) * P(R1|(t AND F)) (2) |
6116 | |
6117 | (where '|' mean conditional probability, not "or") |
6118 | |
6119 | Consider the first multiplier in (2). One of the following holds: |
6120 | a) F contains condition on field used in t (i.e. t AND F = F). |
6121 | Then P(t|F) = 1 |
6122 | |
6123 | b) F doesn't contain condition on field used in t. Then F and t are |
6124 | considered independent. |
6125 | |
6126 | P(t|F) = P(t|(fields_before_t_in_key AND other_fields)) = |
6127 | = P(t|fields_before_t_in_key). |
6128 | |
6129 | P(t|fields_before_t_in_key) = #records(fields_before_t_in_key) / |
6130 | #records(fields_before_t_in_key, t) |
6131 | |
6132 | The second multiplier is calculated by applying this step recursively. |
6133 | |
6134 | IMPLEMENTATION |
6135 | This function calculates the result of application of the "recursion step" |
6136 | described above for all fixed key members of a single key, accumulating set |
6137 | of covered fields, selectivity, etc. |
6138 | |
6139 | The calculation is conducted as follows: |
6140 | Lets denote #records(keypart1, ... keypartK) as n_k. We need to calculate |
6141 | |
6142 | n_{k1} n_{k2} |
6143 | --------- * --------- * .... (3) |
6144 | n_{k1-1} n_{k2-1} |
6145 | |
6146 | where k1,k2,... are key parts which fields were not yet marked as fixed |
6147 | ( this is result of application of option b) of the recursion step for |
6148 | parts of a single key). |
6149 | Since it is reasonable to expect that most of the fields are not marked |
6150 | as fixed, we calculate (3) as |
6151 | |
6152 | n_{i1} n_{i2} |
6153 | (3) = n_{max_key_part} / ( --------- * --------- * .... ) |
6154 | n_{i1-1} n_{i2-1} |
6155 | |
6156 | where i1,i2, .. are key parts that were already marked as fixed. |
6157 | |
6158 | In order to minimize number of expensive records_in_range calls we group |
6159 | and reduce adjacent fractions. |
6160 | |
6161 | RETURN |
6162 | Selectivity of given ROR scan. |
6163 | */ |
6164 | |
6165 | static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info, |
6166 | const ROR_SCAN_INFO *scan) |
6167 | { |
6168 | double selectivity_mult= 1.0; |
6169 | KEY_PART_INFO *key_part= info->param->table->key_info[scan->keynr].key_part; |
6170 | uchar key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */ |
6171 | uchar *key_ptr= key_val; |
6172 | SEL_ARG *sel_arg, *tuple_arg= NULL; |
6173 | key_part_map keypart_map= 0; |
6174 | bool cur_covered; |
6175 | bool prev_covered= MY_TEST(bitmap_is_set(&info->covered_fields, |
6176 | key_part->fieldnr - 1)); |
6177 | key_range min_range; |
6178 | key_range max_range; |
6179 | min_range.key= key_val; |
6180 | min_range.flag= HA_READ_KEY_EXACT; |
6181 | max_range.key= key_val; |
6182 | max_range.flag= HA_READ_AFTER_KEY; |
6183 | ha_rows prev_records= info->param->table->stat_records(); |
6184 | DBUG_ENTER("ror_scan_selectivity" ); |
6185 | |
6186 | for (sel_arg= scan->sel_arg; sel_arg; |
6187 | sel_arg= sel_arg->next_key_part) |
6188 | { |
6189 | DBUG_PRINT("info" ,("sel_arg step" )); |
6190 | cur_covered= MY_TEST(bitmap_is_set(&info->covered_fields, |
6191 | key_part[sel_arg->part].fieldnr - 1)); |
6192 | if (cur_covered != prev_covered) |
6193 | { |
6194 | /* create (part1val, ..., part{n-1}val) tuple. */ |
6195 | ha_rows records; |
6196 | if (!tuple_arg) |
6197 | { |
6198 | tuple_arg= scan->sel_arg; |
6199 | /* Here we use the length of the first key part */ |
6200 | tuple_arg->store_min(key_part->store_length, &key_ptr, 0); |
6201 | keypart_map= 1; |
6202 | } |
6203 | while (tuple_arg->next_key_part != sel_arg) |
6204 | { |
6205 | tuple_arg= tuple_arg->next_key_part; |
6206 | tuple_arg->store_min(key_part[tuple_arg->part].store_length, |
6207 | &key_ptr, 0); |
6208 | keypart_map= (keypart_map << 1) | 1; |
6209 | } |
6210 | min_range.length= max_range.length= (uint) (key_ptr - key_val); |
6211 | min_range.keypart_map= max_range.keypart_map= keypart_map; |
6212 | records= (info->param->table->file-> |
6213 | records_in_range(scan->keynr, &min_range, &max_range)); |
6214 | if (cur_covered) |
6215 | { |
6216 | /* uncovered -> covered */ |
6217 | double tmp= rows2double(records)/rows2double(prev_records); |
6218 | DBUG_PRINT("info" , ("Selectivity multiplier: %g" , tmp)); |
6219 | selectivity_mult *= tmp; |
6220 | prev_records= HA_POS_ERROR; |
6221 | } |
6222 | else |
6223 | { |
6224 | /* covered -> uncovered */ |
6225 | prev_records= records; |
6226 | } |
6227 | } |
6228 | prev_covered= cur_covered; |
6229 | } |
6230 | if (!prev_covered) |
6231 | { |
6232 | double tmp= rows2double(info->param->quick_rows[scan->keynr]) / |
6233 | rows2double(prev_records); |
6234 | DBUG_PRINT("info" , ("Selectivity multiplier: %g" , tmp)); |
6235 | selectivity_mult *= tmp; |
6236 | } |
6237 | DBUG_PRINT("info" , ("Returning multiplier: %g" , selectivity_mult)); |
6238 | DBUG_RETURN(selectivity_mult); |
6239 | } |
6240 | |
6241 | |
6242 | /* |
6243 | Check if adding a ROR scan to a ROR-intersection reduces its cost of |
6244 | ROR-intersection and if yes, update parameters of ROR-intersection, |
6245 | including its cost. |
6246 | |
6247 | SYNOPSIS |
6248 | ror_intersect_add() |
6249 | param Parameter from test_quick_select |
6250 | info ROR-intersection structure to add the scan to. |
6251 | ror_scan ROR scan info to add. |
6252 | is_cpk_scan If TRUE, add the scan as CPK scan (this can be inferred |
6253 | from other parameters and is passed separately only to |
6254 | avoid duplicating the inference code) |
6255 | |
6256 | NOTES |
6257 | Adding a ROR scan to ROR-intersect "makes sense" iff the cost of ROR- |
6258 | intersection decreases. The cost of ROR-intersection is calculated as |
6259 | follows: |
6260 | |
6261 | cost= SUM_i(key_scan_cost_i) + cost_of_full_rows_retrieval |
6262 | |
6263 | When we add a scan the first increases and the second decreases. |
6264 | |
6265 | cost_of_full_rows_retrieval= |
6266 | (union of indexes used covers all needed fields) ? |
6267 | cost_of_sweep_read(E(rows_to_retrieve), rows_in_table) : |
6268 | 0 |
6269 | |
6270 | E(rows_to_retrieve) = #rows_in_table * ror_scan_selectivity(null, scan1) * |
6271 | ror_scan_selectivity({scan1}, scan2) * ... * |
6272 | ror_scan_selectivity({scan1,...}, scanN). |
6273 | RETURN |
6274 | TRUE ROR scan added to ROR-intersection, cost updated. |
6275 | FALSE It doesn't make sense to add this ROR scan to this ROR-intersection. |
6276 | */ |
6277 | |
6278 | static bool ror_intersect_add(ROR_INTERSECT_INFO *info, |
6279 | ROR_SCAN_INFO* ror_scan, bool is_cpk_scan) |
6280 | { |
6281 | double selectivity_mult= 1.0; |
6282 | |
6283 | DBUG_ENTER("ror_intersect_add" ); |
6284 | DBUG_PRINT("info" , ("Current out_rows= %g" , info->out_rows)); |
6285 | DBUG_PRINT("info" , ("Adding scan on %s" , |
6286 | info->param->table->key_info[ror_scan->keynr].name.str)); |
6287 | DBUG_PRINT("info" , ("is_cpk_scan: %d" ,is_cpk_scan)); |
6288 | |
6289 | selectivity_mult = ror_scan_selectivity(info, ror_scan); |
6290 | if (selectivity_mult == 1.0) |
6291 | { |
6292 | /* Don't add this scan if it doesn't improve selectivity. */ |
6293 | DBUG_PRINT("info" , ("The scan doesn't improve selectivity." )); |
6294 | DBUG_RETURN(FALSE); |
6295 | } |
6296 | |
6297 | info->out_rows *= selectivity_mult; |
6298 | |
6299 | if (is_cpk_scan) |
6300 | { |
6301 | /* |
6302 | CPK scan is used to filter out rows. We apply filtering for |
6303 | each record of every scan. Assuming 1/TIME_FOR_COMPARE_ROWID |
6304 | per check this gives us: |
6305 | */ |
6306 | info->index_scan_costs += rows2double(info->index_records) / |
6307 | TIME_FOR_COMPARE_ROWID; |
6308 | } |
6309 | else |
6310 | { |
6311 | info->index_records += info->param->quick_rows[ror_scan->keynr]; |
6312 | info->index_scan_costs += ror_scan->index_read_cost; |
6313 | bitmap_union(&info->covered_fields, &ror_scan->covered_fields); |
6314 | if (!info->is_covering && bitmap_is_subset(&info->param->needed_fields, |
6315 | &info->covered_fields)) |
6316 | { |
6317 | DBUG_PRINT("info" , ("ROR-intersect is covering now" )); |
6318 | info->is_covering= TRUE; |
6319 | } |
6320 | } |
6321 | |
6322 | info->total_cost= info->index_scan_costs; |
6323 | DBUG_PRINT("info" , ("info->total_cost: %g" , info->total_cost)); |
6324 | if (!info->is_covering) |
6325 | { |
6326 | info->total_cost += |
6327 | get_sweep_read_cost(info->param, double2rows(info->out_rows)); |
6328 | DBUG_PRINT("info" , ("info->total_cost= %g" , info->total_cost)); |
6329 | } |
6330 | DBUG_PRINT("info" , ("New out_rows: %g" , info->out_rows)); |
6331 | DBUG_PRINT("info" , ("New cost: %g, %scovering" , info->total_cost, |
6332 | info->is_covering?"" : "non-" )); |
6333 | DBUG_RETURN(TRUE); |
6334 | } |
6335 | |
6336 | |
6337 | /* |
6338 | Get best ROR-intersection plan using non-covering ROR-intersection search |
6339 | algorithm. The returned plan may be covering. |
6340 | |
6341 | SYNOPSIS |
6342 | get_best_ror_intersect() |
6343 | param Parameter from test_quick_select function. |
6344 | tree Transformed restriction condition to be used to look |
6345 | for ROR scans. |
6346 | read_time Do not return read plans with cost > read_time. |
6347 | are_all_covering [out] set to TRUE if union of all scans covers all |
6348 | fields needed by the query (and it is possible to build |
6349 | a covering ROR-intersection) |
6350 | |
6351 | NOTES |
6352 | get_key_scans_params must be called before this function can be called. |
6353 | |
6354 | When this function is called by ROR-union construction algorithm it |
6355 | assumes it is building an uncovered ROR-intersection (and thus # of full |
6356 | records to be retrieved is wrong here). This is a hack. |
6357 | |
6358 | IMPLEMENTATION |
6359 | The approximate best non-covering plan search algorithm is as follows: |
6360 | |
6361 | find_min_ror_intersection_scan() |
6362 | { |
6363 | R= select all ROR scans; |
6364 | order R by (E(#records_matched) * key_record_length). |
6365 | |
6366 | S= first(R); -- set of scans that will be used for ROR-intersection |
6367 | R= R-first(S); |
6368 | min_cost= cost(S); |
6369 | min_scan= make_scan(S); |
6370 | while (R is not empty) |
6371 | { |
6372 | firstR= R - first(R); |
6373 | if (!selectivity(S + firstR < selectivity(S))) |
6374 | continue; |
6375 | |
6376 | S= S + first(R); |
6377 | if (cost(S) < min_cost) |
6378 | { |
6379 | min_cost= cost(S); |
6380 | min_scan= make_scan(S); |
6381 | } |
6382 | } |
6383 | return min_scan; |
6384 | } |
6385 | |
6386 | See ror_intersect_add function for ROR intersection costs. |
6387 | |
6388 | Special handling for Clustered PK scans |
6389 | Clustered PK contains all table fields, so using it as a regular scan in |
6390 | index intersection doesn't make sense: a range scan on CPK will be less |
6391 | expensive in this case. |
6392 | Clustered PK scan has special handling in ROR-intersection: it is not used |
6393 | to retrieve rows, instead its condition is used to filter row references |
6394 | we get from scans on other keys. |
6395 | |
6396 | RETURN |
6397 | ROR-intersection table read plan |
6398 | NULL if out of memory or no suitable plan found. |
6399 | */ |
6400 | |
6401 | static |
6402 | TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, |
6403 | double read_time, |
6404 | bool *are_all_covering) |
6405 | { |
6406 | uint idx; |
6407 | double min_cost= DBL_MAX; |
6408 | DBUG_ENTER("get_best_ror_intersect" ); |
6409 | |
6410 | if ((tree->n_ror_scans < 2) || !param->table->stat_records() || |
6411 | !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT)) |
6412 | DBUG_RETURN(NULL); |
6413 | |
6414 | /* |
6415 | Step1: Collect ROR-able SEL_ARGs and create ROR_SCAN_INFO for each of |
6416 | them. Also find and save clustered PK scan if there is one. |
6417 | */ |
6418 | ROR_SCAN_INFO **cur_ror_scan; |
6419 | ROR_SCAN_INFO *cpk_scan= NULL; |
6420 | uint cpk_no; |
6421 | |
6422 | if (!(tree->ror_scans= (ROR_SCAN_INFO**)alloc_root(param->mem_root, |
6423 | sizeof(ROR_SCAN_INFO*)* |
6424 | param->keys))) |
6425 | return NULL; |
6426 | cpk_no= ((param->table->file->primary_key_is_clustered()) ? |
6427 | param->table->s->primary_key : MAX_KEY); |
6428 | |
6429 | for (idx= 0, cur_ror_scan= tree->ror_scans; idx < param->keys; idx++) |
6430 | { |
6431 | ROR_SCAN_INFO *scan; |
6432 | uint key_no; |
6433 | if (!tree->ror_scans_map.is_set(idx)) |
6434 | continue; |
6435 | key_no= param->real_keynr[idx]; |
6436 | if (key_no != cpk_no && |
6437 | param->table->file->index_flags(key_no,0,0) & HA_CLUSTERED_INDEX) |
6438 | { |
6439 | /* Ignore clustering keys */ |
6440 | tree->n_ror_scans--; |
6441 | continue; |
6442 | } |
6443 | if (!(scan= make_ror_scan(param, idx, tree->keys[idx]))) |
6444 | return NULL; |
6445 | if (key_no == cpk_no) |
6446 | { |
6447 | cpk_scan= scan; |
6448 | tree->n_ror_scans--; |
6449 | } |
6450 | else |
6451 | *(cur_ror_scan++)= scan; |
6452 | } |
6453 | |
6454 | tree->ror_scans_end= cur_ror_scan; |
6455 | DBUG_EXECUTE("info" ,print_ror_scans_arr(param->table, "original" , |
6456 | tree->ror_scans, |
6457 | tree->ror_scans_end);); |
6458 | /* |
6459 | Ok, [ror_scans, ror_scans_end) is array of ptrs to initialized |
6460 | ROR_SCAN_INFO's. |
6461 | Step 2: Get best ROR-intersection using an approximate algorithm. |
6462 | */ |
6463 | my_qsort(tree->ror_scans, tree->n_ror_scans, sizeof(ROR_SCAN_INFO*), |
6464 | (qsort_cmp)cmp_ror_scan_info); |
6465 | DBUG_EXECUTE("info" ,print_ror_scans_arr(param->table, "ordered" , |
6466 | tree->ror_scans, |
6467 | tree->ror_scans_end);); |
6468 | |
6469 | ROR_SCAN_INFO **intersect_scans; /* ROR scans used in index intersection */ |
6470 | ROR_SCAN_INFO **intersect_scans_end; |
6471 | if (!(intersect_scans= (ROR_SCAN_INFO**)alloc_root(param->mem_root, |
6472 | sizeof(ROR_SCAN_INFO*)* |
6473 | tree->n_ror_scans))) |
6474 | return NULL; |
6475 | intersect_scans_end= intersect_scans; |
6476 | |
6477 | /* Create and incrementally update ROR intersection. */ |
6478 | ROR_INTERSECT_INFO *intersect, *intersect_best; |
6479 | if (!(intersect= ror_intersect_init(param)) || |
6480 | !(intersect_best= ror_intersect_init(param))) |
6481 | return NULL; |
6482 | |
6483 | /* [intersect_scans,intersect_scans_best) will hold the best intersection */ |
6484 | ROR_SCAN_INFO **intersect_scans_best; |
6485 | cur_ror_scan= tree->ror_scans; |
6486 | intersect_scans_best= intersect_scans; |
6487 | while (cur_ror_scan != tree->ror_scans_end && !intersect->is_covering) |
6488 | { |
6489 | /* S= S + first(R); R= R - first(R); */ |
6490 | if (!ror_intersect_add(intersect, *cur_ror_scan, FALSE)) |
6491 | { |
6492 | cur_ror_scan++; |
6493 | continue; |
6494 | } |
6495 | |
6496 | *(intersect_scans_end++)= *(cur_ror_scan++); |
6497 | |
6498 | if (intersect->total_cost < min_cost) |
6499 | { |
6500 | /* Local minimum found, save it */ |
6501 | ror_intersect_cpy(intersect_best, intersect); |
6502 | intersect_scans_best= intersect_scans_end; |
6503 | min_cost = intersect->total_cost; |
6504 | } |
6505 | } |
6506 | |
6507 | if (intersect_scans_best == intersect_scans) |
6508 | { |
6509 | DBUG_PRINT("info" , ("None of scans increase selectivity" )); |
6510 | DBUG_RETURN(NULL); |
6511 | } |
6512 | |
6513 | DBUG_EXECUTE("info" ,print_ror_scans_arr(param->table, |
6514 | "best ROR-intersection" , |
6515 | intersect_scans, |
6516 | intersect_scans_best);); |
6517 | |
6518 | *are_all_covering= intersect->is_covering; |
6519 | uint best_num= (uint)(intersect_scans_best - intersect_scans); |
6520 | ror_intersect_cpy(intersect, intersect_best); |
6521 | |
6522 | /* |
6523 | Ok, found the best ROR-intersection of non-CPK key scans. |
6524 | Check if we should add a CPK scan. If the obtained ROR-intersection is |
6525 | covering, it doesn't make sense to add CPK scan. |
6526 | */ |
6527 | if (cpk_scan && !intersect->is_covering) |
6528 | { |
6529 | if (ror_intersect_add(intersect, cpk_scan, TRUE) && |
6530 | (intersect->total_cost < min_cost)) |
6531 | intersect_best= intersect; //just set pointer here |
6532 | } |
6533 | else |
6534 | cpk_scan= 0; // Don't use cpk_scan |
6535 | |
6536 | /* Ok, return ROR-intersect plan if we have found one */ |
6537 | TRP_ROR_INTERSECT *trp= NULL; |
6538 | if (min_cost < read_time && (cpk_scan || best_num > 1)) |
6539 | { |
6540 | if (!(trp= new (param->mem_root) TRP_ROR_INTERSECT)) |
6541 | DBUG_RETURN(trp); |
6542 | if (!(trp->first_scan= |
6543 | (ROR_SCAN_INFO**)alloc_root(param->mem_root, |
6544 | sizeof(ROR_SCAN_INFO*)*best_num))) |
6545 | DBUG_RETURN(NULL); |
6546 | memcpy(trp->first_scan, intersect_scans, best_num*sizeof(ROR_SCAN_INFO*)); |
6547 | trp->last_scan= trp->first_scan + best_num; |
6548 | trp->is_covering= intersect_best->is_covering; |
6549 | trp->read_cost= intersect_best->total_cost; |
6550 | /* Prevent divisons by zero */ |
6551 | ha_rows best_rows = double2rows(intersect_best->out_rows); |
6552 | if (!best_rows) |
6553 | best_rows= 1; |
6554 | set_if_smaller(param->table->quick_condition_rows, best_rows); |
6555 | trp->records= best_rows; |
6556 | trp->index_scan_costs= intersect_best->index_scan_costs; |
6557 | trp->cpk_scan= cpk_scan; |
6558 | DBUG_PRINT("info" , ("Returning non-covering ROR-intersect plan:" |
6559 | "cost %g, records %lu" , |
6560 | trp->read_cost, (ulong) trp->records)); |
6561 | } |
6562 | DBUG_RETURN(trp); |
6563 | } |
6564 | |
6565 | |
6566 | /* |
6567 | Get best covering ROR-intersection. |
6568 | SYNOPSIS |
6569 | get_best_ntersectcovering_ror_intersect() |
6570 | param Parameter from test_quick_select function. |
6571 | tree SEL_TREE with sets of intervals for different keys. |
6572 | read_time Don't return table read plans with cost > read_time. |
6573 | |
6574 | RETURN |
6575 | Best covering ROR-intersection plan |
6576 | NULL if no plan found. |
6577 | |
6578 | NOTES |
6579 | get_best_ror_intersect must be called for a tree before calling this |
6580 | function for it. |
6581 | This function invalidates tree->ror_scans member values. |
6582 | |
6583 | The following approximate algorithm is used: |
6584 | I=set of all covering indexes |
6585 | F=set of all fields to cover |
6586 | S={} |
6587 | |
6588 | do |
6589 | { |
6590 | Order I by (#covered fields in F desc, |
6591 | #components asc, |
6592 | number of first not covered component asc); |
6593 | F=F-covered by first(I); |
6594 | S=S+first(I); |
6595 | I=I-first(I); |
6596 | } while F is not empty. |
6597 | */ |
6598 | |
6599 | static |
6600 | TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, |
6601 | SEL_TREE *tree, |
6602 | double read_time) |
6603 | { |
6604 | ROR_SCAN_INFO **ror_scan_mark; |
6605 | ROR_SCAN_INFO **ror_scans_end= tree->ror_scans_end; |
6606 | DBUG_ENTER("get_best_covering_ror_intersect" ); |
6607 | |
6608 | if (!optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT)) |
6609 | DBUG_RETURN(NULL); |
6610 | |
6611 | for (ROR_SCAN_INFO **scan= tree->ror_scans; scan != ror_scans_end; ++scan) |
6612 | (*scan)->key_components= |
6613 | param->table->key_info[(*scan)->keynr].user_defined_key_parts; |
6614 | |
6615 | /* |
6616 | Run covering-ROR-search algorithm. |
6617 | Assume set I is [ror_scan .. ror_scans_end) |
6618 | */ |
6619 | |
6620 | /*I=set of all covering indexes */ |
6621 | ror_scan_mark= tree->ror_scans; |
6622 | |
6623 | MY_BITMAP *covered_fields= ¶m->tmp_covered_fields; |
6624 | if (!covered_fields->bitmap) |
6625 | covered_fields->bitmap= (my_bitmap_map*)alloc_root(param->mem_root, |
6626 | param->fields_bitmap_size); |
6627 | if (!covered_fields->bitmap || |
6628 | my_bitmap_init(covered_fields, covered_fields->bitmap, |
6629 | param->table->s->fields, FALSE)) |
6630 | DBUG_RETURN(0); |
6631 | bitmap_clear_all(covered_fields); |
6632 | |
6633 | double total_cost= 0.0f; |
6634 | ha_rows records=0; |
6635 | bool all_covered; |
6636 | |
6637 | DBUG_PRINT("info" , ("Building covering ROR-intersection" )); |
6638 | DBUG_EXECUTE("info" , print_ror_scans_arr(param->table, |
6639 | "building covering ROR-I" , |
6640 | ror_scan_mark, ror_scans_end);); |
6641 | do |
6642 | { |
6643 | /* |
6644 | Update changed sorting info: |
6645 | #covered fields, |
6646 | number of first not covered component |
6647 | Calculate and save these values for each of remaining scans. |
6648 | */ |
6649 | for (ROR_SCAN_INFO **scan= ror_scan_mark; scan != ror_scans_end; ++scan) |
6650 | { |
6651 | bitmap_subtract(&(*scan)->covered_fields, covered_fields); |
6652 | (*scan)->used_fields_covered= |
6653 | bitmap_bits_set(&(*scan)->covered_fields); |
6654 | (*scan)->first_uncovered_field= |
6655 | bitmap_get_first(&(*scan)->covered_fields); |
6656 | } |
6657 | |
6658 | my_qsort(ror_scan_mark, ror_scans_end-ror_scan_mark, sizeof(ROR_SCAN_INFO*), |
6659 | (qsort_cmp)cmp_ror_scan_info_covering); |
6660 | |
6661 | DBUG_EXECUTE("info" , print_ror_scans_arr(param->table, |
6662 | "remaining scans" , |
6663 | ror_scan_mark, ror_scans_end);); |
6664 | |
6665 | /* I=I-first(I) */ |
6666 | total_cost += (*ror_scan_mark)->index_read_cost; |
6667 | records += (*ror_scan_mark)->records; |
6668 | DBUG_PRINT("info" , ("Adding scan on %s" , |
6669 | param->table->key_info[(*ror_scan_mark)->keynr].name.str)); |
6670 | if (total_cost > read_time) |
6671 | DBUG_RETURN(NULL); |
6672 | /* F=F-covered by first(I) */ |
6673 | bitmap_union(covered_fields, &(*ror_scan_mark)->covered_fields); |
6674 | all_covered= bitmap_is_subset(¶m->needed_fields, covered_fields); |
6675 | } while ((++ror_scan_mark < ror_scans_end) && !all_covered); |
6676 | |
6677 | if (!all_covered || (ror_scan_mark - tree->ror_scans) == 1) |
6678 | DBUG_RETURN(NULL); |
6679 | |
6680 | /* |
6681 | Ok, [tree->ror_scans .. ror_scan) holds covering index_intersection with |
6682 | cost total_cost. |
6683 | */ |
6684 | DBUG_PRINT("info" , ("Covering ROR-intersect scans cost: %g" , total_cost)); |
6685 | DBUG_EXECUTE("info" , print_ror_scans_arr(param->table, |
6686 | "creating covering ROR-intersect" , |
6687 | tree->ror_scans, ror_scan_mark);); |
6688 | |
6689 | /* Add priority queue use cost. */ |
6690 | total_cost += rows2double(records)* |
6691 | log((double)(ror_scan_mark - tree->ror_scans)) / |
6692 | (TIME_FOR_COMPARE_ROWID * M_LN2); |
6693 | DBUG_PRINT("info" , ("Covering ROR-intersect full cost: %g" , total_cost)); |
6694 | |
6695 | if (total_cost > read_time) |
6696 | DBUG_RETURN(NULL); |
6697 | |
6698 | TRP_ROR_INTERSECT *trp; |
6699 | if (!(trp= new (param->mem_root) TRP_ROR_INTERSECT)) |
6700 | DBUG_RETURN(trp); |
6701 | uint best_num= (uint)(ror_scan_mark - tree->ror_scans); |
6702 | if (!(trp->first_scan= (ROR_SCAN_INFO**)alloc_root(param->mem_root, |
6703 | sizeof(ROR_SCAN_INFO*)* |
6704 | best_num))) |
6705 | DBUG_RETURN(NULL); |
6706 | memcpy(trp->first_scan, tree->ror_scans, best_num*sizeof(ROR_SCAN_INFO*)); |
6707 | trp->last_scan= trp->first_scan + best_num; |
6708 | trp->is_covering= TRUE; |
6709 | trp->read_cost= total_cost; |
6710 | trp->records= records; |
6711 | trp->cpk_scan= NULL; |
6712 | set_if_smaller(param->table->quick_condition_rows, records); |
6713 | |
6714 | DBUG_PRINT("info" , |
6715 | ("Returning covering ROR-intersect plan: cost %g, records %lu" , |
6716 | trp->read_cost, (ulong) trp->records)); |
6717 | DBUG_RETURN(trp); |
6718 | } |
6719 | |
6720 | |
6721 | /* |
6722 | Get best "range" table read plan for given SEL_TREE. |
6723 | Also update PARAM members and store ROR scans info in the SEL_TREE. |
6724 | SYNOPSIS |
6725 | get_key_scans_params |
6726 | param parameters from test_quick_select |
6727 | tree make range select for this SEL_TREE |
6728 | index_read_must_be_used if TRUE, assume 'index only' option will be set |
6729 | (except for clustered PK indexes) |
6730 | read_time don't create read plans with cost > read_time. |
6731 | RETURN |
6732 | Best range read plan |
6733 | NULL if no plan found or error occurred |
6734 | */ |
6735 | |
6736 | static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, |
6737 | bool index_read_must_be_used, |
6738 | bool update_tbl_stats, |
6739 | double read_time) |
6740 | { |
6741 | uint idx, UNINIT_VAR(best_idx); |
6742 | SEL_ARG *key_to_read= NULL; |
6743 | ha_rows UNINIT_VAR(best_records); /* protected by key_to_read */ |
6744 | uint UNINIT_VAR(best_mrr_flags), /* protected by key_to_read */ |
6745 | UNINIT_VAR(best_buf_size); /* protected by key_to_read */ |
6746 | TRP_RANGE* read_plan= NULL; |
6747 | DBUG_ENTER("get_key_scans_params" ); |
6748 | /* |
6749 | Note that there may be trees that have type SEL_TREE::KEY but contain no |
6750 | key reads at all, e.g. tree for expression "key1 is not null" where key1 |
6751 | is defined as "not null". |
6752 | */ |
6753 | DBUG_EXECUTE("info" , print_sel_tree(param, tree, &tree->keys_map, |
6754 | "tree scans" );); |
6755 | tree->ror_scans_map.clear_all(); |
6756 | tree->n_ror_scans= 0; |
6757 | tree->index_scans= 0; |
6758 | if (!tree->keys_map.is_clear_all()) |
6759 | { |
6760 | tree->index_scans= |
6761 | (INDEX_SCAN_INFO **) alloc_root(param->mem_root, |
6762 | sizeof(INDEX_SCAN_INFO *) * param->keys); |
6763 | } |
6764 | tree->index_scans_end= tree->index_scans; |
6765 | for (idx= 0; idx < param->keys; idx++) |
6766 | { |
6767 | SEL_ARG *key= tree->keys[idx]; |
6768 | if (key) |
6769 | { |
6770 | ha_rows found_records; |
6771 | Cost_estimate cost; |
6772 | double found_read_time; |
6773 | uint mrr_flags, buf_size; |
6774 | INDEX_SCAN_INFO *index_scan; |
6775 | uint keynr= param->real_keynr[idx]; |
6776 | if (key->type == SEL_ARG::MAYBE_KEY || |
6777 | key->maybe_flag) |
6778 | param->needed_reg->set_bit(keynr); |
6779 | |
6780 | bool read_index_only= index_read_must_be_used ? TRUE : |
6781 | (bool) param->table->covering_keys.is_set(keynr); |
6782 | |
6783 | found_records= check_quick_select(param, idx, read_index_only, key, |
6784 | update_tbl_stats, &mrr_flags, |
6785 | &buf_size, &cost); |
6786 | |
6787 | if (found_records != HA_POS_ERROR && tree->index_scans && |
6788 | (index_scan= (INDEX_SCAN_INFO *)alloc_root(param->mem_root, |
6789 | sizeof(INDEX_SCAN_INFO)))) |
6790 | { |
6791 | index_scan->idx= idx; |
6792 | index_scan->keynr= keynr; |
6793 | index_scan->key_info= ¶m->table->key_info[keynr]; |
6794 | index_scan->used_key_parts= param->max_key_part+1; |
6795 | index_scan->range_count= param->range_count; |
6796 | index_scan->records= found_records; |
6797 | index_scan->sel_arg= key; |
6798 | *tree->index_scans_end++= index_scan; |
6799 | } |
6800 | if ((found_records != HA_POS_ERROR) && param->is_ror_scan) |
6801 | { |
6802 | tree->n_ror_scans++; |
6803 | tree->ror_scans_map.set_bit(idx); |
6804 | } |
6805 | if (found_records != HA_POS_ERROR && |
6806 | read_time > (found_read_time= cost.total_cost())) |
6807 | { |
6808 | read_time= found_read_time; |
6809 | best_records= found_records; |
6810 | key_to_read= key; |
6811 | best_idx= idx; |
6812 | best_mrr_flags= mrr_flags; |
6813 | best_buf_size= buf_size; |
6814 | } |
6815 | } |
6816 | } |
6817 | |
6818 | DBUG_EXECUTE("info" , print_sel_tree(param, tree, &tree->ror_scans_map, |
6819 | "ROR scans" );); |
6820 | if (key_to_read) |
6821 | { |
6822 | if ((read_plan= new (param->mem_root) TRP_RANGE(key_to_read, best_idx, |
6823 | best_mrr_flags))) |
6824 | { |
6825 | read_plan->records= best_records; |
6826 | read_plan->is_ror= tree->ror_scans_map.is_set(best_idx); |
6827 | read_plan->read_cost= read_time; |
6828 | read_plan->mrr_buf_size= best_buf_size; |
6829 | DBUG_PRINT("info" , |
6830 | ("Returning range plan for key %s, cost %g, records %lu" , |
6831 | param->table->key_info[param->real_keynr[best_idx]].name.str, |
6832 | read_plan->read_cost, (ulong) read_plan->records)); |
6833 | } |
6834 | } |
6835 | else |
6836 | DBUG_PRINT("info" , ("No 'range' table read plan found" )); |
6837 | |
6838 | DBUG_RETURN(read_plan); |
6839 | } |
6840 | |
6841 | |
6842 | QUICK_SELECT_I *TRP_INDEX_MERGE::make_quick(PARAM *param, |
6843 | bool retrieve_full_rows, |
6844 | MEM_ROOT *parent_alloc) |
6845 | { |
6846 | QUICK_INDEX_MERGE_SELECT *quick_imerge; |
6847 | QUICK_RANGE_SELECT *quick; |
6848 | /* index_merge always retrieves full rows, ignore retrieve_full_rows */ |
6849 | if (!(quick_imerge= new QUICK_INDEX_MERGE_SELECT(param->thd, param->table))) |
6850 | return NULL; |
6851 | |
6852 | quick_imerge->records= records; |
6853 | quick_imerge->read_time= read_cost; |
6854 | for (TRP_RANGE **range_scan= range_scans; range_scan != range_scans_end; |
6855 | range_scan++) |
6856 | { |
6857 | if (!(quick= (QUICK_RANGE_SELECT*) |
6858 | ((*range_scan)->make_quick(param, FALSE, &quick_imerge->alloc)))|| |
6859 | quick_imerge->push_quick_back(quick)) |
6860 | { |
6861 | delete quick; |
6862 | delete quick_imerge; |
6863 | return NULL; |
6864 | } |
6865 | } |
6866 | return quick_imerge; |
6867 | } |
6868 | |
6869 | |
6870 | QUICK_SELECT_I *TRP_INDEX_INTERSECT::make_quick(PARAM *param, |
6871 | bool retrieve_full_rows, |
6872 | MEM_ROOT *parent_alloc) |
6873 | { |
6874 | QUICK_INDEX_INTERSECT_SELECT *quick_intersect; |
6875 | QUICK_RANGE_SELECT *quick; |
6876 | /* index_merge always retrieves full rows, ignore retrieve_full_rows */ |
6877 | if (!(quick_intersect= new QUICK_INDEX_INTERSECT_SELECT(param->thd, param->table))) |
6878 | return NULL; |
6879 | |
6880 | quick_intersect->records= records; |
6881 | quick_intersect->read_time= read_cost; |
6882 | quick_intersect->filtered_scans= filtered_scans; |
6883 | for (TRP_RANGE **range_scan= range_scans; range_scan != range_scans_end; |
6884 | range_scan++) |
6885 | { |
6886 | if (!(quick= (QUICK_RANGE_SELECT*) |
6887 | ((*range_scan)->make_quick(param, FALSE, &quick_intersect->alloc)))|| |
6888 | quick_intersect->push_quick_back(quick)) |
6889 | { |
6890 | delete quick; |
6891 | delete quick_intersect; |
6892 | return NULL; |
6893 | } |
6894 | } |
6895 | return quick_intersect; |
6896 | } |
6897 | |
6898 | |
6899 | QUICK_SELECT_I *TRP_ROR_INTERSECT::make_quick(PARAM *param, |
6900 | bool retrieve_full_rows, |
6901 | MEM_ROOT *parent_alloc) |
6902 | { |
6903 | QUICK_ROR_INTERSECT_SELECT *quick_intrsect; |
6904 | QUICK_RANGE_SELECT *quick; |
6905 | DBUG_ENTER("TRP_ROR_INTERSECT::make_quick" ); |
6906 | MEM_ROOT *alloc; |
6907 | |
6908 | if ((quick_intrsect= |
6909 | new QUICK_ROR_INTERSECT_SELECT(param->thd, param->table, |
6910 | (retrieve_full_rows? (!is_covering) : |
6911 | FALSE), |
6912 | parent_alloc))) |
6913 | { |
6914 | DBUG_EXECUTE("info" , print_ror_scans_arr(param->table, |
6915 | "creating ROR-intersect" , |
6916 | first_scan, last_scan);); |
6917 | alloc= parent_alloc? parent_alloc: &quick_intrsect->alloc; |
6918 | for (; first_scan != last_scan;++first_scan) |
6919 | { |
6920 | if (!(quick= get_quick_select(param, (*first_scan)->idx, |
6921 | (*first_scan)->sel_arg, |
6922 | HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED, |
6923 | 0, alloc)) || |
6924 | quick_intrsect->push_quick_back(alloc, quick)) |
6925 | { |
6926 | delete quick_intrsect; |
6927 | DBUG_RETURN(NULL); |
6928 | } |
6929 | } |
6930 | if (cpk_scan) |
6931 | { |
6932 | if (!(quick= get_quick_select(param, cpk_scan->idx, |
6933 | cpk_scan->sel_arg, |
6934 | HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED, |
6935 | 0, alloc))) |
6936 | { |
6937 | delete quick_intrsect; |
6938 | DBUG_RETURN(NULL); |
6939 | } |
6940 | quick->file= NULL; |
6941 | quick_intrsect->cpk_quick= quick; |
6942 | } |
6943 | quick_intrsect->records= records; |
6944 | quick_intrsect->read_time= read_cost; |
6945 | } |
6946 | DBUG_RETURN(quick_intrsect); |
6947 | } |
6948 | |
6949 | |
6950 | QUICK_SELECT_I *TRP_ROR_UNION::make_quick(PARAM *param, |
6951 | bool retrieve_full_rows, |
6952 | MEM_ROOT *parent_alloc) |
6953 | { |
6954 | QUICK_ROR_UNION_SELECT *quick_roru; |
6955 | TABLE_READ_PLAN **scan; |
6956 | QUICK_SELECT_I *quick; |
6957 | DBUG_ENTER("TRP_ROR_UNION::make_quick" ); |
6958 | /* |
6959 | It is impossible to construct a ROR-union that will not retrieve full |
6960 | rows, ignore retrieve_full_rows parameter. |
6961 | */ |
6962 | if ((quick_roru= new QUICK_ROR_UNION_SELECT(param->thd, param->table))) |
6963 | { |
6964 | for (scan= first_ror; scan != last_ror; scan++) |
6965 | { |
6966 | if (!(quick= (*scan)->make_quick(param, FALSE, &quick_roru->alloc)) || |
6967 | quick_roru->push_quick_back(quick)) |
6968 | { |
6969 | delete quick_roru; |
6970 | DBUG_RETURN(NULL); |
6971 | } |
6972 | } |
6973 | quick_roru->records= records; |
6974 | quick_roru->read_time= read_cost; |
6975 | } |
6976 | DBUG_RETURN(quick_roru); |
6977 | } |
6978 | |
6979 | |
6980 | /* |
6981 | Build a SEL_TREE for <> or NOT BETWEEN predicate |
6982 | |
6983 | SYNOPSIS |
6984 | get_ne_mm_tree() |
6985 | param PARAM from SQL_SELECT::test_quick_select |
6986 | cond_func item for the predicate |
6987 | field field in the predicate |
6988 | lt_value constant that field should be smaller |
6989 | gt_value constant that field should be greaterr |
6990 | |
6991 | RETURN |
6992 | # Pointer to tree built tree |
6993 | 0 on error |
6994 | */ |
6995 | |
6996 | SEL_TREE *Item_bool_func::get_ne_mm_tree(RANGE_OPT_PARAM *param, |
6997 | Field *field, |
6998 | Item *lt_value, Item *gt_value) |
6999 | { |
7000 | SEL_TREE *tree; |
7001 | tree= get_mm_parts(param, field, Item_func::LT_FUNC, lt_value); |
7002 | if (tree) |
7003 | tree= tree_or(param, tree, get_mm_parts(param, field, Item_func::GT_FUNC, |
7004 | gt_value)); |
7005 | return tree; |
7006 | } |
7007 | |
7008 | |
7009 | SEL_TREE *Item_func_between::get_func_mm_tree(RANGE_OPT_PARAM *param, |
7010 | Field *field, Item *value) |
7011 | { |
7012 | SEL_TREE *tree; |
7013 | DBUG_ENTER("Item_func_between::get_func_mm_tree" ); |
7014 | if (!value) |
7015 | { |
7016 | if (negated) |
7017 | { |
7018 | tree= get_ne_mm_tree(param, field, args[1], args[2]); |
7019 | } |
7020 | else |
7021 | { |
7022 | tree= get_mm_parts(param, field, Item_func::GE_FUNC, args[1]); |
7023 | if (tree) |
7024 | { |
7025 | tree= tree_and(param, tree, get_mm_parts(param, field, |
7026 | Item_func::LE_FUNC, |
7027 | args[2])); |
7028 | } |
7029 | } |
7030 | } |
7031 | else |
7032 | { |
7033 | tree= get_mm_parts(param, field, |
7034 | (negated ? |
7035 | (value == (Item*)1 ? Item_func::GT_FUNC : |
7036 | Item_func::LT_FUNC): |
7037 | (value == (Item*)1 ? Item_func::LE_FUNC : |
7038 | Item_func::GE_FUNC)), |
7039 | args[0]); |
7040 | } |
7041 | DBUG_RETURN(tree); |
7042 | } |
7043 | |
7044 | |
7045 | SEL_TREE *Item_func_in::get_func_mm_tree(RANGE_OPT_PARAM *param, |
7046 | Field *field, Item *value) |
7047 | { |
7048 | SEL_TREE *tree= 0; |
7049 | DBUG_ENTER("Item_func_in::get_func_mm_tree" ); |
7050 | /* |
7051 | Array for IN() is constructed when all values have the same result |
7052 | type. Tree won't be built for values with different result types, |
7053 | so we check it here to avoid unnecessary work. |
7054 | */ |
7055 | if (!arg_types_compatible) |
7056 | DBUG_RETURN(0); |
7057 | |
7058 | if (negated) |
7059 | { |
7060 | if (array && array->type_handler()->result_type() != ROW_RESULT) |
7061 | { |
7062 | /* |
7063 | We get here for conditions in form "t.key NOT IN (c1, c2, ...)", |
7064 | where c{i} are constants. Our goal is to produce a SEL_TREE that |
7065 | represents intervals: |
7066 | |
7067 | ($MIN<t.key<c1) OR (c1<t.key<c2) OR (c2<t.key<c3) OR ... (*) |
7068 | |
7069 | where $MIN is either "-inf" or NULL. |
7070 | |
7071 | The most straightforward way to produce it is to convert NOT IN |
7072 | into "(t.key != c1) AND (t.key != c2) AND ... " and let the range |
7073 | analyzer to build SEL_TREE from that. The problem is that the |
7074 | range analyzer will use O(N^2) memory (which is probably a bug), |
7075 | and people do use big NOT IN lists (e.g. see BUG#15872, BUG#21282), |
7076 | will run out of memory. |
7077 | |
7078 | Another problem with big lists like (*) is that a big list is |
7079 | unlikely to produce a good "range" access, while considering that |
7080 | range access will require expensive CPU calculations (and for |
7081 | MyISAM even index accesses). In short, big NOT IN lists are rarely |
7082 | worth analyzing. |
7083 | |
7084 | Considering the above, we'll handle NOT IN as follows: |
7085 | * if the number of entries in the NOT IN list is less than |
7086 | NOT_IN_IGNORE_THRESHOLD, construct the SEL_TREE (*) manually. |
7087 | * Otherwise, don't produce a SEL_TREE. |
7088 | */ |
7089 | #define NOT_IN_IGNORE_THRESHOLD 1000 |
7090 | MEM_ROOT *tmp_root= param->mem_root; |
7091 | param->thd->mem_root= param->old_root; |
7092 | /* |
7093 | Create one Item_type constant object. We'll need it as |
7094 | get_mm_parts only accepts constant values wrapped in Item_Type |
7095 | objects. |
7096 | We create the Item on param->mem_root which points to |
7097 | per-statement mem_root (while thd->mem_root is currently pointing |
7098 | to mem_root local to range optimizer). |
7099 | */ |
7100 | Item *value_item= array->create_item(param->thd); |
7101 | param->thd->mem_root= tmp_root; |
7102 | |
7103 | if (array->count > NOT_IN_IGNORE_THRESHOLD || !value_item) |
7104 | DBUG_RETURN(0); |
7105 | |
7106 | /* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */ |
7107 | uint i=0; |
7108 | do |
7109 | { |
7110 | array->value_to_item(i, value_item); |
7111 | tree= get_mm_parts(param, field, Item_func::LT_FUNC, value_item); |
7112 | if (!tree) |
7113 | break; |
7114 | i++; |
7115 | } while (i < array->count && tree->type == SEL_TREE::IMPOSSIBLE); |
7116 | |
7117 | if (!tree || tree->type == SEL_TREE::IMPOSSIBLE) |
7118 | { |
7119 | /* We get here in cases like "t.unsigned NOT IN (-1,-2,-3) */ |
7120 | DBUG_RETURN(NULL); |
7121 | } |
7122 | SEL_TREE *tree2; |
7123 | for (; i < array->used_count; i++) |
7124 | { |
7125 | if (array->compare_elems(i, i-1)) |
7126 | { |
7127 | /* Get a SEL_TREE for "-inf < X < c_i" interval */ |
7128 | array->value_to_item(i, value_item); |
7129 | tree2= get_mm_parts(param, field, Item_func::LT_FUNC, value_item); |
7130 | if (!tree2) |
7131 | { |
7132 | tree= NULL; |
7133 | break; |
7134 | } |
7135 | |
7136 | /* Change all intervals to be "c_{i-1} < X < c_i" */ |
7137 | for (uint idx= 0; idx < param->keys; idx++) |
7138 | { |
7139 | SEL_ARG *new_interval, *last_val; |
7140 | if (((new_interval= tree2->keys[idx])) && |
7141 | (tree->keys[idx]) && |
7142 | ((last_val= tree->keys[idx]->last()))) |
7143 | { |
7144 | new_interval->min_value= last_val->max_value; |
7145 | new_interval->min_flag= NEAR_MIN; |
7146 | |
7147 | /* |
7148 | If the interval is over a partial keypart, the |
7149 | interval must be "c_{i-1} <= X < c_i" instead of |
7150 | "c_{i-1} < X < c_i". Reason: |
7151 | |
7152 | Consider a table with a column "my_col VARCHAR(3)", |
7153 | and an index with definition |
7154 | "INDEX my_idx my_col(1)". If the table contains rows |
7155 | with my_col values "f" and "foo", the index will not |
7156 | distinguish the two rows. |
7157 | |
7158 | Note that tree_or() below will effectively merge |
7159 | this range with the range created for c_{i-1} and |
7160 | we'll eventually end up with only one range: |
7161 | "NULL < X". |
7162 | |
7163 | Partitioning indexes are never partial. |
7164 | */ |
7165 | if (param->using_real_indexes) |
7166 | { |
7167 | const KEY key= |
7168 | param->table->key_info[param->real_keynr[idx]]; |
7169 | const KEY_PART_INFO *kpi= key.key_part + new_interval->part; |
7170 | |
7171 | if (kpi->key_part_flag & HA_PART_KEY_SEG) |
7172 | new_interval->min_flag= 0; |
7173 | } |
7174 | } |
7175 | } |
7176 | /* |
7177 | The following doesn't try to allocate memory so no need to |
7178 | check for NULL. |
7179 | */ |
7180 | tree= tree_or(param, tree, tree2); |
7181 | } |
7182 | } |
7183 | |
7184 | if (tree && tree->type != SEL_TREE::IMPOSSIBLE) |
7185 | { |
7186 | /* |
7187 | Get the SEL_TREE for the last "c_last < X < +inf" interval |
7188 | (value_item cotains c_last already) |
7189 | */ |
7190 | tree2= get_mm_parts(param, field, Item_func::GT_FUNC, value_item); |
7191 | tree= tree_or(param, tree, tree2); |
7192 | } |
7193 | } |
7194 | else |
7195 | { |
7196 | tree= get_ne_mm_tree(param, field, args[1], args[1]); |
7197 | if (tree) |
7198 | { |
7199 | Item **arg, **end; |
7200 | for (arg= args + 2, end= arg + arg_count - 2; arg < end ; arg++) |
7201 | { |
7202 | tree= tree_and(param, tree, get_ne_mm_tree(param, field, |
7203 | *arg, *arg)); |
7204 | } |
7205 | } |
7206 | } |
7207 | } |
7208 | else |
7209 | { |
7210 | tree= get_mm_parts(param, field, Item_func::EQ_FUNC, args[1]); |
7211 | if (tree) |
7212 | { |
7213 | Item **arg, **end; |
7214 | for (arg= args + 2, end= arg + arg_count - 2; |
7215 | arg < end ; arg++) |
7216 | { |
7217 | tree= tree_or(param, tree, get_mm_parts(param, field, |
7218 | Item_func::EQ_FUNC, *arg)); |
7219 | } |
7220 | } |
7221 | } |
7222 | DBUG_RETURN(tree); |
7223 | } |
7224 | |
7225 | |
7226 | /* |
7227 | The structure Key_col_info is purely auxiliary and is used |
7228 | only in the method Item_func_in::get_func_row_mm_tree |
7229 | */ |
7230 | struct Key_col_info { |
7231 | Field *field; /* If != NULL the column can be used for keys */ |
7232 | cmp_item *comparator; /* If != 0 the column can be evaluated */ |
7233 | }; |
7234 | |
7235 | /** |
7236 | Build SEL_TREE for the IN predicate whose arguments are rows |
7237 | |
7238 | @param param PARAM from SQL_SELECT::test_quick_select |
7239 | @param key_row First operand of the IN predicate |
7240 | |
7241 | @note |
7242 | The function builds a SEL_TREE for in IN predicate in the case |
7243 | when the predicate uses row arguments. First the function |
7244 | detects among the components of the key_row (c[1],...,c[n]) taken |
7245 | from in the left part the predicate those that can be usable |
7246 | for building SEL_TREE (c[i1],...,c[ik]). They have to contain |
7247 | items whose real items are field items referring to the current |
7248 | table or equal to the items referring to the current table. |
7249 | For the remaining components of the row it checks whether they |
7250 | can be evaluated. The result of the analysis is put into the |
7251 | array of structures of the type Key_row_col_info. |
7252 | |
7253 | After this the function builds the SEL_TREE for the following |
7254 | formula that can be inferred from the given IN predicate: |
7255 | c[i11]=a[1][i11] AND ... AND c[i1k1]=a[1][i1k1] |
7256 | OR |
7257 | ... |
7258 | OR |
7259 | c[im1]=a[m][im1] AND ... AND c[imkm]=a[m][imkm]. |
7260 | Here a[1],...,a[m] are all arguments of the IN predicate from |
7261 | the right part and for each j ij1,...,ijkj is a subset of |
7262 | i1,...,ik such that a[j][ij1],...,a[j][ijkj] can be evaluated. |
7263 | |
7264 | If for some j there no a[j][i1],...,a[j][ik] can be evaluated |
7265 | then no SEL_TREE can be built for this predicate and the |
7266 | function immediately returns 0. |
7267 | |
7268 | If for some j by using evaluated values of key_row it can be |
7269 | proven that c[ij1]=a[j][ij1] AND ... AND c[ijkj]=a[j][ijkj] |
7270 | is always FALSE then this disjunct is omitted. |
7271 | |
7272 | @returns |
7273 | the built SEL_TREE if it can be constructed |
7274 | 0 - otherwise. |
7275 | */ |
7276 | |
7277 | SEL_TREE *Item_func_in::get_func_row_mm_tree(RANGE_OPT_PARAM *param, |
7278 | Item_row *key_row) |
7279 | { |
7280 | DBUG_ENTER("Item_func_in::get_func_row_mm_tree" ); |
7281 | |
7282 | if (negated) |
7283 | DBUG_RETURN(0); |
7284 | |
7285 | SEL_TREE *res_tree= 0; |
7286 | uint used_key_cols= 0; |
7287 | uint col_comparators= 0; |
7288 | table_map param_comp= ~(param->prev_tables | param->read_tables | |
7289 | param->current_table); |
7290 | uint row_cols= key_row->cols(); |
7291 | Dynamic_array <Key_col_info> key_cols_info(row_cols); |
7292 | cmp_item_row *row_cmp_item; |
7293 | |
7294 | if (array) |
7295 | { |
7296 | in_row *row= static_cast<in_row*>(array); |
7297 | row_cmp_item= static_cast<cmp_item_row*>(row->get_cmp_item()); |
7298 | } |
7299 | else |
7300 | { |
7301 | DBUG_ASSERT(get_comparator_type_handler(0) == &type_handler_row); |
7302 | row_cmp_item= static_cast<cmp_item_row*>(get_comparator_cmp_item(0)); |
7303 | } |
7304 | DBUG_ASSERT(row_cmp_item); |
7305 | |
7306 | Item **key_col_ptr= key_row->addr(0); |
7307 | for(uint i= 0; i < row_cols; i++, key_col_ptr++) |
7308 | { |
7309 | Key_col_info key_col_info= {0, NULL}; |
7310 | Item *key_col= *key_col_ptr; |
7311 | if (key_col->real_item()->type() == Item::FIELD_ITEM) |
7312 | { |
7313 | /* |
7314 | The i-th component of key_row can be used for key access if |
7315 | key_col->real_item() points to a field of the current table or |
7316 | if it is equal to a field item pointing to such a field. |
7317 | */ |
7318 | Item_field *col_field_item= (Item_field *) (key_col->real_item()); |
7319 | Field *key_col_field= col_field_item->field; |
7320 | if (key_col_field->table->map != param->current_table) |
7321 | { |
7322 | Item_equal *item_equal= col_field_item->item_equal; |
7323 | if (item_equal) |
7324 | { |
7325 | Item_equal_fields_iterator it(*item_equal); |
7326 | while (it++) |
7327 | { |
7328 | key_col_field= it.get_curr_field(); |
7329 | if (key_col_field->table->map == param->current_table) |
7330 | break; |
7331 | } |
7332 | } |
7333 | } |
7334 | if (key_col_field->table->map == param->current_table) |
7335 | { |
7336 | key_col_info.field= key_col_field; |
7337 | used_key_cols++; |
7338 | } |
7339 | } |
7340 | else if (!(key_col->used_tables() & (param_comp | param->current_table)) |
7341 | && !key_col->is_expensive()) |
7342 | { |
7343 | /* The i-th component of key_row can be evaluated */ |
7344 | |
7345 | /* See the comment in Item::get_mm_tree_for_const */ |
7346 | MEM_ROOT *tmp_root= param->mem_root; |
7347 | param->thd->mem_root= param->old_root; |
7348 | |
7349 | key_col->bring_value(); |
7350 | key_col_info.comparator= row_cmp_item->get_comparator(i); |
7351 | DBUG_ASSERT(key_col_info.comparator); |
7352 | key_col_info.comparator->store_value(key_col); |
7353 | col_comparators++; |
7354 | |
7355 | param->thd->mem_root= tmp_root; |
7356 | } |
7357 | key_cols_info.push(key_col_info); |
7358 | } |
7359 | |
7360 | if (!used_key_cols) |
7361 | DBUG_RETURN(0); |
7362 | |
7363 | uint omitted_tuples= 0; |
7364 | Item **arg_start= arguments() + 1; |
7365 | Item **arg_end= arg_start + argument_count() - 1; |
7366 | for (Item **arg= arg_start ; arg < arg_end; arg++) |
7367 | { |
7368 | uint i; |
7369 | |
7370 | /* |
7371 | First check whether the disjunct constructed for *arg |
7372 | is really needed |
7373 | */ |
7374 | Item_row *arg_tuple= (Item_row *) (*arg); |
7375 | if (col_comparators) |
7376 | { |
7377 | MEM_ROOT *tmp_root= param->mem_root; |
7378 | param->thd->mem_root= param->old_root; |
7379 | for (i= 0; i < row_cols; i++) |
7380 | { |
7381 | Key_col_info *key_col_info= &key_cols_info.at(i); |
7382 | if (key_col_info->comparator) |
7383 | { |
7384 | Item *arg_col= arg_tuple->element_index(i); |
7385 | if (!(arg_col->used_tables() & (param_comp | param->current_table)) && |
7386 | !arg_col->is_expensive() && |
7387 | key_col_info->comparator->cmp(arg_col)) |
7388 | { |
7389 | omitted_tuples++; |
7390 | break; |
7391 | } |
7392 | } |
7393 | } |
7394 | param->thd->mem_root= tmp_root; |
7395 | if (i < row_cols) |
7396 | continue; |
7397 | } |
7398 | |
7399 | /* The disjunct for *arg is needed: build it. */ |
7400 | SEL_TREE *and_tree= 0; |
7401 | Item **arg_col_ptr= arg_tuple->addr(0); |
7402 | for (uint i= 0; i < row_cols; i++, arg_col_ptr++) |
7403 | { |
7404 | Key_col_info *key_col_info= &key_cols_info.at(i); |
7405 | if (!key_col_info->field) |
7406 | continue; |
7407 | Item *arg_col= *arg_col_ptr; |
7408 | if (!(arg_col->used_tables() & (param_comp | param->current_table)) && |
7409 | !arg_col->is_expensive()) |
7410 | { |
7411 | and_tree= tree_and(param, and_tree, |
7412 | get_mm_parts(param, |
7413 | key_col_info->field, |
7414 | Item_func::EQ_FUNC, |
7415 | arg_col->real_item())); |
7416 | } |
7417 | } |
7418 | if (!and_tree) |
7419 | { |
7420 | res_tree= 0; |
7421 | break; |
7422 | } |
7423 | /* Join the disjunct the the OR tree that is being constructed */ |
7424 | res_tree= !res_tree ? and_tree : tree_or(param, res_tree, and_tree); |
7425 | } |
7426 | if (omitted_tuples == argument_count() - 1) |
7427 | { |
7428 | /* It's turned out that all disjuncts are always FALSE */ |
7429 | res_tree= new (param->mem_root) SEL_TREE(SEL_TREE::IMPOSSIBLE, |
7430 | param->mem_root, param->keys); |
7431 | } |
7432 | DBUG_RETURN(res_tree); |
7433 | } |
7434 | |
7435 | |
7436 | /* |
7437 | Build conjunction of all SEL_TREEs for a simple predicate applying equalities |
7438 | |
7439 | SYNOPSIS |
7440 | get_full_func_mm_tree() |
7441 | param PARAM from SQL_SELECT::test_quick_select |
7442 | field_item field in the predicate |
7443 | value constant in the predicate (or a field already read from |
7444 | a table in the case of dynamic range access) |
7445 | (for BETWEEN it contains the number of the field argument, |
7446 | for IN it's always 0) |
7447 | inv TRUE <> NOT cond_func is considered |
7448 | (makes sense only when cond_func is BETWEEN or IN) |
7449 | |
7450 | DESCRIPTION |
7451 | For a simple SARGable predicate of the form (f op c), where f is a field and |
7452 | c is a constant, the function builds a conjunction of all SEL_TREES that can |
7453 | be obtained by the substitution of f for all different fields equal to f. |
7454 | |
7455 | NOTES |
7456 | If the WHERE condition contains a predicate (fi op c), |
7457 | then not only SELL_TREE for this predicate is built, but |
7458 | the trees for the results of substitution of fi for |
7459 | each fj belonging to the same multiple equality as fi |
7460 | are built as well. |
7461 | E.g. for WHERE t1.a=t2.a AND t2.a > 10 |
7462 | a SEL_TREE for t2.a > 10 will be built for quick select from t2 |
7463 | and |
7464 | a SEL_TREE for t1.a > 10 will be built for quick select from t1. |
7465 | |
7466 | A BETWEEN predicate of the form (fi [NOT] BETWEEN c1 AND c2) is treated |
7467 | in a similar way: we build a conjuction of trees for the results |
7468 | of all substitutions of fi for equal fj. |
7469 | Yet a predicate of the form (c BETWEEN f1i AND f2i) is processed |
7470 | differently. It is considered as a conjuction of two SARGable |
7471 | predicates (f1i <= c) and (f2i <=c) and the function get_full_func_mm_tree |
7472 | is called for each of them separately producing trees for |
7473 | AND j (f1j <=c ) and AND j (f2j <= c) |
7474 | After this these two trees are united in one conjunctive tree. |
7475 | It's easy to see that the same tree is obtained for |
7476 | AND j,k (f1j <=c AND f2k<=c) |
7477 | which is equivalent to |
7478 | AND j,k (c BETWEEN f1j AND f2k). |
7479 | The validity of the processing of the predicate (c NOT BETWEEN f1i AND f2i) |
7480 | which equivalent to (f1i > c OR f2i < c) is not so obvious. Here the |
7481 | function get_full_func_mm_tree is called for (f1i > c) and (f2i < c) |
7482 | producing trees for AND j (f1j > c) and AND j (f2j < c). Then this two |
7483 | trees are united in one OR-tree. The expression |
7484 | (AND j (f1j > c) OR AND j (f2j < c) |
7485 | is equivalent to the expression |
7486 | AND j,k (f1j > c OR f2k < c) |
7487 | which is just a translation of |
7488 | AND j,k (c NOT BETWEEN f1j AND f2k) |
7489 | |
7490 | In the cases when one of the items f1, f2 is a constant c1 we do not create |
7491 | a tree for it at all. It works for BETWEEN predicates but does not |
7492 | work for NOT BETWEEN predicates as we have to evaluate the expression |
7493 | with it. If it is TRUE then the other tree can be completely ignored. |
7494 | We do not do it now and no trees are built in these cases for |
7495 | NOT BETWEEN predicates. |
7496 | |
7497 | As to IN predicates only ones of the form (f IN (c1,...,cn)), |
7498 | where f1 is a field and c1,...,cn are constant, are considered as |
7499 | SARGable. We never try to narrow the index scan using predicates of |
7500 | the form (c IN (c1,...,f,...,cn)). |
7501 | |
7502 | RETURN |
7503 | Pointer to the tree representing the built conjunction of SEL_TREEs |
7504 | */ |
7505 | |
7506 | SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param, |
7507 | Item_field *field_item, |
7508 | Item *value) |
7509 | { |
7510 | DBUG_ENTER("Item_bool_func::get_full_func_mm_tree" ); |
7511 | SEL_TREE *tree= 0; |
7512 | SEL_TREE *ftree= 0; |
7513 | table_map ref_tables= 0; |
7514 | table_map param_comp= ~(param->prev_tables | param->read_tables | |
7515 | param->current_table); |
7516 | #ifdef HAVE_SPATIAL |
7517 | Field::geometry_type sav_geom_type; |
7518 | LINT_INIT_STRUCT(sav_geom_type); |
7519 | |
7520 | if (field_item->field->type() == MYSQL_TYPE_GEOMETRY) |
7521 | { |
7522 | sav_geom_type= ((Field_geom*) field_item->field)->geom_type; |
7523 | /* We have to be able to store all sorts of spatial features here */ |
7524 | ((Field_geom*) field_item->field)->geom_type= Field::GEOM_GEOMETRY; |
7525 | } |
7526 | #endif /*HAVE_SPATIAL*/ |
7527 | |
7528 | for (uint i= 0; i < arg_count; i++) |
7529 | { |
7530 | Item *arg= arguments()[i]->real_item(); |
7531 | if (arg != field_item) |
7532 | ref_tables|= arg->used_tables(); |
7533 | } |
7534 | Field *field= field_item->field; |
7535 | if (!((ref_tables | field->table->map) & param_comp)) |
7536 | ftree= get_func_mm_tree(param, field, value); |
7537 | Item_equal *item_equal= field_item->item_equal; |
7538 | if (item_equal) |
7539 | { |
7540 | Item_equal_fields_iterator it(*item_equal); |
7541 | while (it++) |
7542 | { |
7543 | Field *f= it.get_curr_field(); |
7544 | if (field->eq(f)) |
7545 | continue; |
7546 | if (!((ref_tables | f->table->map) & param_comp)) |
7547 | { |
7548 | tree= get_func_mm_tree(param, f, value); |
7549 | ftree= !ftree ? tree : tree_and(param, ftree, tree); |
7550 | } |
7551 | } |
7552 | } |
7553 | |
7554 | #ifdef HAVE_SPATIAL |
7555 | if (field_item->field->type() == MYSQL_TYPE_GEOMETRY) |
7556 | { |
7557 | ((Field_geom*) field_item->field)->geom_type= sav_geom_type; |
7558 | } |
7559 | #endif /*HAVE_SPATIAL*/ |
7560 | DBUG_RETURN(ftree); |
7561 | } |
7562 | |
7563 | |
7564 | /* |
7565 | make a select tree of all keys in condition |
7566 | |
7567 | @param param Context |
7568 | @param cond INOUT condition to perform range analysis on. |
7569 | |
7570 | @detail |
7571 | Range analysis may infer that some conditions are never true. |
7572 | - If the condition is never true, SEL_TREE(type=IMPOSSIBLE) is returned |
7573 | - if parts of condition are never true, the function may remove these parts |
7574 | from the condition 'cond'. Sometimes, this will cause the condition to |
7575 | be substituted for something else. |
7576 | |
7577 | |
7578 | @return |
7579 | NULL - Could not infer anything from condition cond. |
7580 | SEL_TREE with type=IMPOSSIBLE - condition can never be true. |
7581 | */ |
7582 | SEL_TREE *Item_cond_and::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) |
7583 | { |
7584 | DBUG_ENTER("Item_cond_and::get_mm_tree" ); |
7585 | SEL_TREE *tree= NULL; |
7586 | List_iterator<Item> li(*argument_list()); |
7587 | Item *item; |
7588 | while ((item= li++)) |
7589 | { |
7590 | SEL_TREE *new_tree= li.ref()[0]->get_mm_tree(param,li.ref()); |
7591 | if (param->statement_should_be_aborted()) |
7592 | DBUG_RETURN(NULL); |
7593 | tree= tree_and(param, tree, new_tree); |
7594 | if (tree && tree->type == SEL_TREE::IMPOSSIBLE) |
7595 | { |
7596 | /* |
7597 | Do not remove 'item' from 'cond'. We return a SEL_TREE::IMPOSSIBLE |
7598 | and that is sufficient for the caller to see that the whole |
7599 | condition is never true. |
7600 | */ |
7601 | break; |
7602 | } |
7603 | } |
7604 | DBUG_RETURN(tree); |
7605 | } |
7606 | |
7607 | |
7608 | SEL_TREE *Item_cond::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) |
7609 | { |
7610 | DBUG_ENTER("Item_cond::get_mm_tree" ); |
7611 | List_iterator<Item> li(*argument_list()); |
7612 | bool replace_cond= false; |
7613 | Item *replacement_item= li++; |
7614 | SEL_TREE *tree= li.ref()[0]->get_mm_tree(param, li.ref()); |
7615 | if (param->statement_should_be_aborted()) |
7616 | DBUG_RETURN(NULL); |
7617 | if (tree) |
7618 | { |
7619 | if (tree->type == SEL_TREE::IMPOSSIBLE && |
7620 | param->remove_false_where_parts) |
7621 | { |
7622 | /* See the other li.remove() call below */ |
7623 | li.remove(); |
7624 | if (argument_list()->elements <= 1) |
7625 | replace_cond= true; |
7626 | } |
7627 | |
7628 | Item *item; |
7629 | while ((item= li++)) |
7630 | { |
7631 | SEL_TREE *new_tree= li.ref()[0]->get_mm_tree(param, li.ref()); |
7632 | if (new_tree == NULL || param->statement_should_be_aborted()) |
7633 | DBUG_RETURN(NULL); |
7634 | tree= tree_or(param, tree, new_tree); |
7635 | if (tree == NULL || tree->type == SEL_TREE::ALWAYS) |
7636 | { |
7637 | replacement_item= *li.ref(); |
7638 | break; |
7639 | } |
7640 | |
7641 | if (new_tree && new_tree->type == SEL_TREE::IMPOSSIBLE && |
7642 | param->remove_false_where_parts) |
7643 | { |
7644 | /* |
7645 | This is a condition in form |
7646 | |
7647 | cond = item1 OR ... OR item_i OR ... itemN |
7648 | |
7649 | and item_i produces SEL_TREE(IMPOSSIBLE). We should remove item_i |
7650 | from cond. This may cause 'cond' to become a degenerate, |
7651 | one-way OR. In that case, we replace 'cond' with the remaining |
7652 | item_i. |
7653 | */ |
7654 | li.remove(); |
7655 | if (argument_list()->elements <= 1) |
7656 | replace_cond= true; |
7657 | } |
7658 | else |
7659 | replacement_item= *li.ref(); |
7660 | } |
7661 | |
7662 | if (replace_cond) |
7663 | *cond_ptr= replacement_item; |
7664 | } |
7665 | DBUG_RETURN(tree); |
7666 | } |
7667 | |
7668 | |
7669 | SEL_TREE *Item::get_mm_tree_for_const(RANGE_OPT_PARAM *param) |
7670 | { |
7671 | DBUG_ENTER("get_mm_tree_for_const" ); |
7672 | if (is_expensive()) |
7673 | DBUG_RETURN(0); |
7674 | /* |
7675 | During the cond->val_int() evaluation we can come across a subselect |
7676 | item which may allocate memory on the thd->mem_root and assumes |
7677 | all the memory allocated has the same life span as the subselect |
7678 | item itself. So we have to restore the thread's mem_root here. |
7679 | */ |
7680 | MEM_ROOT *tmp_root= param->mem_root; |
7681 | param->thd->mem_root= param->old_root; |
7682 | SEL_TREE *tree; |
7683 | |
7684 | const SEL_TREE::Type type= val_int()? SEL_TREE::ALWAYS: SEL_TREE::IMPOSSIBLE; |
7685 | param->thd->mem_root= tmp_root; |
7686 | |
7687 | tree= new (tmp_root) SEL_TREE(type, tmp_root, param->keys); |
7688 | DBUG_RETURN(tree); |
7689 | } |
7690 | |
7691 | |
7692 | SEL_TREE *Item::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) |
7693 | { |
7694 | DBUG_ENTER("Item::get_mm_tree" ); |
7695 | if (const_item()) |
7696 | DBUG_RETURN(get_mm_tree_for_const(param)); |
7697 | |
7698 | /* |
7699 | Here we have a not-constant non-function Item. |
7700 | |
7701 | Item_field should not appear, as normalize_cond() replaces |
7702 | "WHERE field" to "WHERE field<>0". |
7703 | |
7704 | Item_exists_subselect is possible, e.g. in this query: |
7705 | SELECT id, st FROM t1 |
7706 | WHERE st IN ('GA','FL') AND EXISTS (SELECT 1 FROM t2 WHERE t2.id=t1.id) |
7707 | GROUP BY id; |
7708 | */ |
7709 | table_map ref_tables= used_tables(); |
7710 | if ((ref_tables & param->current_table) || |
7711 | (ref_tables & ~(param->prev_tables | param->read_tables))) |
7712 | DBUG_RETURN(0); |
7713 | DBUG_RETURN(new (param->mem_root) SEL_TREE(SEL_TREE::MAYBE, param->mem_root, |
7714 | param->keys)); |
7715 | } |
7716 | |
7717 | |
7718 | SEL_TREE * |
7719 | Item_func_between::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) |
7720 | { |
7721 | DBUG_ENTER("Item_func_between::get_mm_tree" ); |
7722 | if (const_item()) |
7723 | DBUG_RETURN(get_mm_tree_for_const(param)); |
7724 | |
7725 | SEL_TREE *tree= 0; |
7726 | SEL_TREE *ftree= 0; |
7727 | |
7728 | if (arguments()[0]->real_item()->type() == Item::FIELD_ITEM) |
7729 | { |
7730 | Item_field *field_item= (Item_field*) (arguments()[0]->real_item()); |
7731 | ftree= get_full_func_mm_tree(param, field_item, NULL); |
7732 | } |
7733 | |
7734 | /* |
7735 | Concerning the code below see the NOTES section in |
7736 | the comments for the function get_full_func_mm_tree() |
7737 | */ |
7738 | for (uint i= 1 ; i < arg_count ; i++) |
7739 | { |
7740 | if (arguments()[i]->real_item()->type() == Item::FIELD_ITEM) |
7741 | { |
7742 | Item_field *field_item= (Item_field*) (arguments()[i]->real_item()); |
7743 | SEL_TREE *tmp= get_full_func_mm_tree(param, field_item, |
7744 | (Item*)(intptr) i); |
7745 | if (negated) |
7746 | { |
7747 | tree= !tree ? tmp : tree_or(param, tree, tmp); |
7748 | if (tree == NULL) |
7749 | break; |
7750 | } |
7751 | else |
7752 | tree= tree_and(param, tree, tmp); |
7753 | } |
7754 | else if (negated) |
7755 | { |
7756 | tree= 0; |
7757 | break; |
7758 | } |
7759 | } |
7760 | |
7761 | ftree= tree_and(param, ftree, tree); |
7762 | DBUG_RETURN(ftree); |
7763 | } |
7764 | |
7765 | |
7766 | SEL_TREE *Item_func_in::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) |
7767 | { |
7768 | DBUG_ENTER("Item_func_in::get_mm_tree" ); |
7769 | if (const_item()) |
7770 | DBUG_RETURN(get_mm_tree_for_const(param)); |
7771 | |
7772 | SEL_TREE *tree= 0; |
7773 | switch (key_item()->real_item()->type()) { |
7774 | case Item::FIELD_ITEM: |
7775 | tree= get_full_func_mm_tree(param, |
7776 | (Item_field*) (key_item()->real_item()), |
7777 | NULL); |
7778 | break; |
7779 | case Item::ROW_ITEM: |
7780 | tree= get_func_row_mm_tree(param, |
7781 | (Item_row *) (key_item()->real_item())); |
7782 | break; |
7783 | default: |
7784 | DBUG_RETURN(0); |
7785 | } |
7786 | DBUG_RETURN(tree); |
7787 | } |
7788 | |
7789 | |
7790 | SEL_TREE *Item_equal::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) |
7791 | { |
7792 | DBUG_ENTER("Item_equal::get_mm_tree" ); |
7793 | if (const_item()) |
7794 | DBUG_RETURN(get_mm_tree_for_const(param)); |
7795 | |
7796 | SEL_TREE *tree= 0; |
7797 | SEL_TREE *ftree= 0; |
7798 | |
7799 | Item *value; |
7800 | if (!(value= get_const()) || value->is_expensive()) |
7801 | DBUG_RETURN(0); |
7802 | |
7803 | Item_equal_fields_iterator it(*this); |
7804 | table_map ref_tables= value->used_tables(); |
7805 | table_map param_comp= ~(param->prev_tables | param->read_tables | |
7806 | param->current_table); |
7807 | while (it++) |
7808 | { |
7809 | Field *field= it.get_curr_field(); |
7810 | if (!((ref_tables | field->table->map) & param_comp)) |
7811 | { |
7812 | tree= get_mm_parts(param, field, Item_func::EQ_FUNC, value); |
7813 | ftree= !ftree ? tree : tree_and(param, ftree, tree); |
7814 | } |
7815 | } |
7816 | |
7817 | DBUG_RETURN(ftree); |
7818 | } |
7819 | |
7820 | |
7821 | SEL_TREE * |
7822 | Item_bool_func::get_mm_parts(RANGE_OPT_PARAM *param, Field *field, |
7823 | Item_func::Functype type, Item *value) |
7824 | { |
7825 | DBUG_ENTER("get_mm_parts" ); |
7826 | if (field->table != param->table) |
7827 | DBUG_RETURN(0); |
7828 | |
7829 | KEY_PART *key_part = param->key_parts; |
7830 | KEY_PART *end = param->key_parts_end; |
7831 | SEL_TREE *tree=0; |
7832 | table_map value_used_tables= 0; |
7833 | if (value && |
7834 | (value_used_tables= value->used_tables()) & |
7835 | ~(param->prev_tables | param->read_tables)) |
7836 | DBUG_RETURN(0); |
7837 | for (; key_part != end ; key_part++) |
7838 | { |
7839 | if (field->eq(key_part->field)) |
7840 | { |
7841 | SEL_ARG *sel_arg=0; |
7842 | if (!tree && !(tree=new (param->thd->mem_root) SEL_TREE(param->mem_root, |
7843 | param->keys))) |
7844 | DBUG_RETURN(0); // OOM |
7845 | if (!value || !(value_used_tables & ~param->read_tables)) |
7846 | { |
7847 | /* |
7848 | We need to restore the runtime mem_root of the thread in this |
7849 | function because it evaluates the value of its argument, while |
7850 | the argument can be any, e.g. a subselect. The subselect |
7851 | items, in turn, assume that all the memory allocated during |
7852 | the evaluation has the same life span as the item itself. |
7853 | TODO: opt_range.cc should not reset thd->mem_root at all. |
7854 | */ |
7855 | MEM_ROOT *tmp_root= param->mem_root; |
7856 | param->thd->mem_root= param->old_root; |
7857 | sel_arg= get_mm_leaf(param, key_part->field, key_part, type, value); |
7858 | param->thd->mem_root= tmp_root; |
7859 | |
7860 | if (!sel_arg) |
7861 | continue; |
7862 | if (sel_arg->type == SEL_ARG::IMPOSSIBLE) |
7863 | { |
7864 | tree->type=SEL_TREE::IMPOSSIBLE; |
7865 | DBUG_RETURN(tree); |
7866 | } |
7867 | } |
7868 | else |
7869 | { |
7870 | // This key may be used later |
7871 | if (!(sel_arg= new SEL_ARG(SEL_ARG::MAYBE_KEY))) |
7872 | DBUG_RETURN(0); // OOM |
7873 | } |
7874 | sel_arg->part=(uchar) key_part->part; |
7875 | sel_arg->max_part_no= sel_arg->part+1; |
7876 | tree->keys[key_part->key]=sel_add(tree->keys[key_part->key],sel_arg); |
7877 | tree->keys_map.set_bit(key_part->key); |
7878 | } |
7879 | } |
7880 | |
7881 | if (tree && tree->merges.is_empty() && tree->keys_map.is_clear_all()) |
7882 | tree= NULL; |
7883 | DBUG_RETURN(tree); |
7884 | } |
7885 | |
7886 | |
7887 | SEL_ARG * |
7888 | Item_func_null_predicate::get_mm_leaf(RANGE_OPT_PARAM *param, |
7889 | Field *field, KEY_PART *key_part, |
7890 | Item_func::Functype type, |
7891 | Item *value) |
7892 | { |
7893 | MEM_ROOT *alloc= param->mem_root; |
7894 | DBUG_ENTER("Item_func_null_predicate::get_mm_leaf" ); |
7895 | DBUG_ASSERT(!value); |
7896 | /* |
7897 | No check for field->table->maybe_null. It's perfecly fine to use range |
7898 | access for cases like |
7899 | |
7900 | SELECT * FROM t1 LEFT JOIN t2 ON t2.key IS [NOT] NULL |
7901 | |
7902 | ON expression is evaluated before considering NULL-complemented rows, so |
7903 | IS [NOT] NULL has regular semantics. |
7904 | */ |
7905 | if (!field->real_maybe_null()) |
7906 | DBUG_RETURN(type == ISNULL_FUNC ? &null_element : NULL); |
7907 | SEL_ARG *tree; |
7908 | if (!(tree= new (alloc) SEL_ARG(field, is_null_string, is_null_string))) |
7909 | DBUG_RETURN(0); |
7910 | if (type == Item_func::ISNOTNULL_FUNC) |
7911 | { |
7912 | tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */ |
7913 | tree->max_flag=NO_MAX_RANGE; |
7914 | } |
7915 | DBUG_RETURN(tree); |
7916 | } |
7917 | |
7918 | |
7919 | SEL_ARG * |
7920 | Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param, |
7921 | Field *field, KEY_PART *key_part, |
7922 | Item_func::Functype type, Item *value) |
7923 | { |
7924 | DBUG_ENTER("Item_func_like::get_mm_leaf" ); |
7925 | DBUG_ASSERT(value); |
7926 | |
7927 | if (key_part->image_type != Field::itRAW) |
7928 | DBUG_RETURN(0); |
7929 | |
7930 | if (param->using_real_indexes && |
7931 | !field->optimize_range(param->real_keynr[key_part->key], |
7932 | key_part->part)) |
7933 | DBUG_RETURN(0); |
7934 | |
7935 | if (field->result_type() == STRING_RESULT && |
7936 | field->charset() != compare_collation()) |
7937 | DBUG_RETURN(0); |
7938 | |
7939 | StringBuffer<MAX_FIELD_WIDTH> tmp(value->collation.collation); |
7940 | String *res; |
7941 | |
7942 | if (!(res= value->val_str(&tmp))) |
7943 | DBUG_RETURN(&null_element); |
7944 | |
7945 | if (field->cmp_type() != STRING_RESULT || |
7946 | field->type_handler() == &type_handler_enum || |
7947 | field->type_handler() == &type_handler_set) |
7948 | DBUG_RETURN(0); |
7949 | |
7950 | /* |
7951 | TODO: |
7952 | Check if this was a function. This should have be optimized away |
7953 | in the sql_select.cc |
7954 | */ |
7955 | if (res != &tmp) |
7956 | { |
7957 | tmp.copy(*res); // Get own copy |
7958 | res= &tmp; |
7959 | } |
7960 | |
7961 | uint maybe_null= (uint) field->real_maybe_null(); |
7962 | size_t field_length= field->pack_length() + maybe_null; |
7963 | size_t offset= maybe_null; |
7964 | size_t length= key_part->store_length; |
7965 | |
7966 | if (length != key_part->length + maybe_null) |
7967 | { |
7968 | /* key packed with length prefix */ |
7969 | offset+= HA_KEY_BLOB_LENGTH; |
7970 | field_length= length - HA_KEY_BLOB_LENGTH; |
7971 | } |
7972 | else |
7973 | { |
7974 | if (unlikely(length < field_length)) |
7975 | { |
7976 | /* |
7977 | This can only happen in a table created with UNIREG where one key |
7978 | overlaps many fields |
7979 | */ |
7980 | length= field_length; |
7981 | } |
7982 | else |
7983 | field_length= length; |
7984 | } |
7985 | length+= offset; |
7986 | uchar *min_str,*max_str; |
7987 | if (!(min_str= (uchar*) alloc_root(param->mem_root, length*2))) |
7988 | DBUG_RETURN(0); |
7989 | max_str= min_str + length; |
7990 | if (maybe_null) |
7991 | max_str[0]= min_str[0]=0; |
7992 | |
7993 | size_t min_length, max_length; |
7994 | field_length-= maybe_null; |
7995 | if (my_like_range(field->charset(), |
7996 | res->ptr(), res->length(), |
7997 | escape, wild_one, wild_many, |
7998 | field_length, |
7999 | (char*) min_str + offset, |
8000 | (char*) max_str + offset, |
8001 | &min_length, &max_length)) |
8002 | DBUG_RETURN(0); // Can't optimize with LIKE |
8003 | |
8004 | if (offset != maybe_null) // BLOB or VARCHAR |
8005 | { |
8006 | int2store(min_str + maybe_null, min_length); |
8007 | int2store(max_str + maybe_null, max_length); |
8008 | } |
8009 | SEL_ARG *tree= new (param->mem_root) SEL_ARG(field, min_str, max_str); |
8010 | DBUG_RETURN(tree); |
8011 | } |
8012 | |
8013 | |
8014 | SEL_ARG * |
8015 | Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param, |
8016 | Field *field, KEY_PART *key_part, |
8017 | Item_func::Functype type, Item *value) |
8018 | { |
8019 | uint maybe_null=(uint) field->real_maybe_null(); |
8020 | SEL_ARG *tree= 0; |
8021 | MEM_ROOT *alloc= param->mem_root; |
8022 | uchar *str; |
8023 | int err; |
8024 | DBUG_ENTER("Item_bool_func::get_mm_leaf" ); |
8025 | |
8026 | DBUG_ASSERT(value); // IS NULL and IS NOT NULL are handled separately |
8027 | |
8028 | if (key_part->image_type != Field::itRAW) |
8029 | DBUG_RETURN(0); // e.g. SPATIAL index |
8030 | |
8031 | if (param->using_real_indexes && |
8032 | !field->optimize_range(param->real_keynr[key_part->key], |
8033 | key_part->part) && |
8034 | type != EQ_FUNC && |
8035 | type != EQUAL_FUNC) |
8036 | goto end; // Can't optimize this |
8037 | |
8038 | if (!field->can_optimize_range(this, value, |
8039 | type == EQUAL_FUNC || type == EQ_FUNC)) |
8040 | goto end; |
8041 | |
8042 | err= value->save_in_field_no_warnings(field, 1); |
8043 | if (err > 0) |
8044 | { |
8045 | if (field->type_handler() == &type_handler_enum || |
8046 | field->type_handler() == &type_handler_set) |
8047 | { |
8048 | if (type == EQ_FUNC || type == EQUAL_FUNC) |
8049 | tree= new (alloc) SEL_ARG_IMPOSSIBLE(field); |
8050 | goto end; |
8051 | } |
8052 | |
8053 | if (err == 2 && field->cmp_type() == STRING_RESULT) |
8054 | { |
8055 | if (type == EQ_FUNC || type == EQUAL_FUNC) |
8056 | tree= new (alloc) SEL_ARG_IMPOSSIBLE(field); |
8057 | else |
8058 | tree= NULL; /* Cannot infer anything */ |
8059 | goto end; |
8060 | } |
8061 | |
8062 | if (err == 3 && field->type() == FIELD_TYPE_DATE) |
8063 | { |
8064 | /* |
8065 | We were saving DATETIME into a DATE column, the conversion went ok |
8066 | but a non-zero time part was cut off. |
8067 | |
8068 | In MySQL's SQL dialect, DATE and DATETIME are compared as datetime |
8069 | values. Index over a DATE column uses DATE comparison. Changing |
8070 | from one comparison to the other is possible: |
8071 | |
8072 | datetime(date_col)< '2007-12-10 12:34:55' -> date_col<='2007-12-10' |
8073 | datetime(date_col)<='2007-12-10 12:34:55' -> date_col<='2007-12-10' |
8074 | |
8075 | datetime(date_col)> '2007-12-10 12:34:55' -> date_col>='2007-12-10' |
8076 | datetime(date_col)>='2007-12-10 12:34:55' -> date_col>='2007-12-10' |
8077 | |
8078 | but we'll need to convert '>' to '>=' and '<' to '<='. This will |
8079 | be done together with other types at the end of this function |
8080 | (grep for stored_field_cmp_to_item) |
8081 | */ |
8082 | if (type == EQ_FUNC || type == EQUAL_FUNC) |
8083 | { |
8084 | tree= new (alloc) SEL_ARG_IMPOSSIBLE(field); |
8085 | goto end; |
8086 | } |
8087 | // Continue with processing non-equality ranges |
8088 | } |
8089 | else if (field->cmp_type() != value->result_type()) |
8090 | { |
8091 | if ((type == EQ_FUNC || type == EQUAL_FUNC) && |
8092 | value->result_type() == item_cmp_type(field->result_type(), |
8093 | value->result_type())) |
8094 | { |
8095 | tree= new (alloc) SEL_ARG_IMPOSSIBLE(field); |
8096 | goto end; |
8097 | } |
8098 | else |
8099 | { |
8100 | /* |
8101 | TODO: We should return trees of the type SEL_ARG::IMPOSSIBLE |
8102 | for the cases like int_field > 999999999999999999999999 as well. |
8103 | */ |
8104 | tree= 0; |
8105 | goto end; |
8106 | } |
8107 | } |
8108 | |
8109 | /* |
8110 | guaranteed at this point: err > 0; field and const of same type |
8111 | If an integer got bounded (e.g. to within 0..255 / -128..127) |
8112 | for < or >, set flags as for <= or >= (no NEAR_MAX / NEAR_MIN) |
8113 | */ |
8114 | else if (err == 1 && field->result_type() == INT_RESULT) |
8115 | { |
8116 | if (type == LT_FUNC && (value->val_int() > 0)) |
8117 | type= LE_FUNC; |
8118 | else if (type == GT_FUNC && |
8119 | (field->type() != FIELD_TYPE_BIT) && |
8120 | !((Field_num*)field)->unsigned_flag && |
8121 | !((Item_int*)value)->unsigned_flag && |
8122 | (value->val_int() < 0)) |
8123 | type= GE_FUNC; |
8124 | } |
8125 | } |
8126 | else if (err < 0) |
8127 | { |
8128 | /* This happens when we try to insert a NULL field in a not null column */ |
8129 | tree= &null_element; // cmp with NULL is never TRUE |
8130 | goto end; |
8131 | } |
8132 | |
8133 | /* |
8134 | Any sargable predicate except "<=>" involving NULL as a constant is always |
8135 | FALSE |
8136 | */ |
8137 | if (type != EQUAL_FUNC && field->is_real_null()) |
8138 | { |
8139 | tree= &null_element; |
8140 | goto end; |
8141 | } |
8142 | |
8143 | str= (uchar*) alloc_root(alloc, key_part->store_length+1); |
8144 | if (!str) |
8145 | goto end; |
8146 | if (maybe_null) |
8147 | *str= (uchar) field->is_real_null(); // Set to 1 if null |
8148 | field->get_key_image(str+maybe_null, key_part->length, |
8149 | key_part->image_type); |
8150 | if (!(tree= new (alloc) SEL_ARG(field, str, str))) |
8151 | goto end; // out of memory |
8152 | |
8153 | /* |
8154 | Check if we are comparing an UNSIGNED integer with a negative constant. |
8155 | In this case we know that: |
8156 | (a) (unsigned_int [< | <=] negative_constant) == FALSE |
8157 | (b) (unsigned_int [> | >=] negative_constant) == TRUE |
8158 | In case (a) the condition is false for all values, and in case (b) it |
8159 | is true for all values, so we can avoid unnecessary retrieval and condition |
8160 | testing, and we also get correct comparison of unsinged integers with |
8161 | negative integers (which otherwise fails because at query execution time |
8162 | negative integers are cast to unsigned if compared with unsigned). |
8163 | */ |
8164 | if (field->result_type() == INT_RESULT && |
8165 | value->result_type() == INT_RESULT && |
8166 | ((field->type() == FIELD_TYPE_BIT || |
8167 | ((Field_num *) field)->unsigned_flag) && |
8168 | !((Item_int*) value)->unsigned_flag)) |
8169 | { |
8170 | longlong item_val= value->val_int(); |
8171 | if (item_val < 0) |
8172 | { |
8173 | if (type == LT_FUNC || type == LE_FUNC) |
8174 | { |
8175 | tree->type= SEL_ARG::IMPOSSIBLE; |
8176 | goto end; |
8177 | } |
8178 | if (type == GT_FUNC || type == GE_FUNC) |
8179 | { |
8180 | tree= 0; |
8181 | goto end; |
8182 | } |
8183 | } |
8184 | } |
8185 | |
8186 | switch (type) { |
8187 | case LT_FUNC: |
8188 | if (stored_field_cmp_to_item(param->thd, field, value) == 0) |
8189 | tree->max_flag=NEAR_MAX; |
8190 | /* fall through */ |
8191 | case LE_FUNC: |
8192 | if (!maybe_null) |
8193 | tree->min_flag=NO_MIN_RANGE; /* From start */ |
8194 | else |
8195 | { // > NULL |
8196 | tree->min_value=is_null_string; |
8197 | tree->min_flag=NEAR_MIN; |
8198 | } |
8199 | break; |
8200 | case GT_FUNC: |
8201 | /* Don't use open ranges for partial key_segments */ |
8202 | if ((!(key_part->flag & HA_PART_KEY_SEG)) && |
8203 | (stored_field_cmp_to_item(param->thd, field, value) <= 0)) |
8204 | tree->min_flag=NEAR_MIN; |
8205 | tree->max_flag= NO_MAX_RANGE; |
8206 | break; |
8207 | case GE_FUNC: |
8208 | /* Don't use open ranges for partial key_segments */ |
8209 | if ((!(key_part->flag & HA_PART_KEY_SEG)) && |
8210 | (stored_field_cmp_to_item(param->thd, field, value) < 0)) |
8211 | tree->min_flag= NEAR_MIN; |
8212 | tree->max_flag=NO_MAX_RANGE; |
8213 | break; |
8214 | case EQ_FUNC: |
8215 | case EQUAL_FUNC: |
8216 | break; |
8217 | default: |
8218 | DBUG_ASSERT(0); |
8219 | break; |
8220 | } |
8221 | |
8222 | end: |
8223 | DBUG_RETURN(tree); |
8224 | } |
8225 | |
8226 | |
8227 | /****************************************************************************** |
8228 | ** Tree manipulation functions |
8229 | ** If tree is 0 it means that the condition can't be tested. It refers |
8230 | ** to a non existent table or to a field in current table with isn't a key. |
8231 | ** The different tree flags: |
8232 | ** IMPOSSIBLE: Condition is never TRUE |
8233 | ** ALWAYS: Condition is always TRUE |
8234 | ** MAYBE: Condition may exists when tables are read |
8235 | ** MAYBE_KEY: Condition refers to a key that may be used in join loop |
8236 | ** KEY_RANGE: Condition uses a key |
8237 | ******************************************************************************/ |
8238 | |
8239 | /* |
8240 | Add a new key test to a key when scanning through all keys |
8241 | This will never be called for same key parts. |
8242 | */ |
8243 | |
8244 | static SEL_ARG * |
8245 | sel_add(SEL_ARG *key1,SEL_ARG *key2) |
8246 | { |
8247 | SEL_ARG *root,**key_link; |
8248 | |
8249 | if (!key1) |
8250 | return key2; |
8251 | if (!key2) |
8252 | return key1; |
8253 | |
8254 | key_link= &root; |
8255 | while (key1 && key2) |
8256 | { |
8257 | if (key1->part < key2->part) |
8258 | { |
8259 | *key_link= key1; |
8260 | key_link= &key1->next_key_part; |
8261 | key1=key1->next_key_part; |
8262 | } |
8263 | else |
8264 | { |
8265 | *key_link= key2; |
8266 | key_link= &key2->next_key_part; |
8267 | key2=key2->next_key_part; |
8268 | } |
8269 | } |
8270 | *key_link=key1 ? key1 : key2; |
8271 | return root; |
8272 | } |
8273 | |
8274 | |
8275 | /* |
8276 | Build a range tree for the conjunction of the range parts of two trees |
8277 | |
8278 | SYNOPSIS |
8279 | and_range_trees() |
8280 | param Context info for the operation |
8281 | tree1 SEL_TREE for the first conjunct |
8282 | tree2 SEL_TREE for the second conjunct |
8283 | result SEL_TREE for the result |
8284 | |
8285 | DESCRIPTION |
8286 | This function takes range parts of two trees tree1 and tree2 and builds |
8287 | a range tree for the conjunction of the formulas that these two range parts |
8288 | represent. |
8289 | More exactly: |
8290 | if the range part of tree1 represents the normalized formula |
8291 | R1_1 AND ... AND R1_k, |
8292 | and the range part of tree2 represents the normalized formula |
8293 | R2_1 AND ... AND R2_k, |
8294 | then the range part of the result represents the formula: |
8295 | RT = R_1 AND ... AND R_k, where R_i=(R1_i AND R2_i) for each i from [1..k] |
8296 | |
8297 | The function assumes that tree1 is never equal to tree2. At the same |
8298 | time the tree result can be the same as tree1 (but never as tree2). |
8299 | If result==tree1 then rt replaces the range part of tree1 leaving |
8300 | imerges as they are. |
8301 | if result!=tree1 than it is assumed that the SEL_ARG trees in tree1 and |
8302 | tree2 should be preserved. Otherwise they can be destroyed. |
8303 | |
8304 | RETURN |
8305 | 1 if the type the result tree is SEL_TREE::IMPOSSIBLE |
8306 | 0 otherwise |
8307 | */ |
8308 | |
8309 | static |
8310 | int and_range_trees(RANGE_OPT_PARAM *param, SEL_TREE *tree1, SEL_TREE *tree2, |
8311 | SEL_TREE *result) |
8312 | { |
8313 | DBUG_ENTER("and_ranges" ); |
8314 | key_map result_keys; |
8315 | result_keys.clear_all(); |
8316 | key_map anded_keys= tree1->keys_map; |
8317 | anded_keys.merge(tree2->keys_map); |
8318 | int key_no; |
8319 | key_map::Iterator it(anded_keys); |
8320 | while ((key_no= it++) != key_map::Iterator::BITMAP_END) |
8321 | { |
8322 | uint flag=0; |
8323 | SEL_ARG *key1= tree1->keys[key_no]; |
8324 | SEL_ARG *key2= tree2->keys[key_no]; |
8325 | if (key1 && !key1->simple_key()) |
8326 | flag|= CLONE_KEY1_MAYBE; |
8327 | if (key2 && !key2->simple_key()) |
8328 | flag|=CLONE_KEY2_MAYBE; |
8329 | if (result != tree1) |
8330 | { |
8331 | if (key1) |
8332 | key1->incr_refs(); |
8333 | if (key2) |
8334 | key2->incr_refs(); |
8335 | } |
8336 | SEL_ARG *key; |
8337 | if ((result->keys[key_no]= key =key_and(param, key1, key2, flag))) |
8338 | { |
8339 | if (key && key->type == SEL_ARG::IMPOSSIBLE) |
8340 | { |
8341 | result->type= SEL_TREE::IMPOSSIBLE; |
8342 | DBUG_RETURN(1); |
8343 | } |
8344 | result_keys.set_bit(key_no); |
8345 | #ifdef EXTRA_DEBUG |
8346 | if (param->alloced_sel_args < SEL_ARG::MAX_SEL_ARGS) |
8347 | key->test_use_count(key); |
8348 | #endif |
8349 | } |
8350 | } |
8351 | result->keys_map= result_keys; |
8352 | DBUG_RETURN(0); |
8353 | } |
8354 | |
8355 | |
8356 | /* |
8357 | Build a SEL_TREE for a conjunction out of such trees for the conjuncts |
8358 | |
8359 | SYNOPSIS |
8360 | tree_and() |
8361 | param Context info for the operation |
8362 | tree1 SEL_TREE for the first conjunct |
8363 | tree2 SEL_TREE for the second conjunct |
8364 | |
8365 | DESCRIPTION |
8366 | This function builds a tree for the formula (A AND B) out of the trees |
8367 | tree1 and tree2 that has been built for the formulas A and B respectively. |
8368 | |
8369 | In a general case |
8370 | tree1 represents the formula RT1 AND MT1, |
8371 | where RT1 = R1_1 AND ... AND R1_k1, MT1=M1_1 AND ... AND M1_l1; |
8372 | tree2 represents the formula RT2 AND MT2 |
8373 | where RT2 = R2_1 AND ... AND R2_k2, MT2=M2_1 AND ... AND M2_l2. |
8374 | |
8375 | The result tree will represent the formula of the the following structure: |
8376 | RT AND RT1MT2 AND RT2MT1, such that |
8377 | rt is a tree obtained by range intersection of trees tree1 and tree2, |
8378 | RT1MT2 = RT1M2_1 AND ... AND RT1M2_l2, |
8379 | RT2MT1 = RT2M1_1 AND ... AND RT2M1_l1, |
8380 | where rt1m2_i (i=1,...,l2) is the result of the pushdown operation |
8381 | of range tree rt1 into imerge m2_i, while rt2m1_j (j=1,...,l1) is the |
8382 | result of the pushdown operation of range tree rt2 into imerge m1_j. |
8383 | |
8384 | RT1MT2/RT2MT is empty if MT2/MT1 is empty. |
8385 | |
8386 | The range intersection of two range trees is produced by the function |
8387 | and_range_trees. The pushdown of a range tree to a imerge is performed |
8388 | by the function imerge_list_and_tree. This function may produce imerges |
8389 | containing only one range tree. Such trees are intersected with rt and |
8390 | the result of intersection is returned as the range part of the result |
8391 | tree, while the corresponding imerges are removed altogether from its |
8392 | imerge part. |
8393 | |
8394 | NOTE |
8395 | The pushdown operation of range trees into imerges is needed to be able |
8396 | to construct valid imerges for the condition like this: |
8397 | key1_p1=c1 AND (key1_p2 BETWEEN c21 AND c22 OR key2 < c2) |
8398 | |
8399 | NOTE |
8400 | Currently we do not support intersection between indexes and index merges. |
8401 | When this will be supported the list of imerges for the result tree |
8402 | should include also imerges from M1 and M2. That's why an extra parameter |
8403 | is added to the function imerge_list_and_tree. If we call the function |
8404 | with the last parameter equal to FALSE then MT1 and MT2 will be preserved |
8405 | in the imerge list of the result tree. This can lead to the exponential |
8406 | growth of the imerge list though. |
8407 | Currently the last parameter of imerge_list_and_tree calls is always |
8408 | TRUE. |
8409 | |
8410 | RETURN |
8411 | The result tree, if a success |
8412 | 0 - otherwise. |
8413 | */ |
8414 | |
8415 | static |
8416 | SEL_TREE *tree_and(RANGE_OPT_PARAM *param, SEL_TREE *tree1, SEL_TREE *tree2) |
8417 | { |
8418 | DBUG_ENTER("tree_and" ); |
8419 | if (!tree1) |
8420 | DBUG_RETURN(tree2); |
8421 | if (!tree2) |
8422 | DBUG_RETURN(tree1); |
8423 | if (tree1->type == SEL_TREE::IMPOSSIBLE || tree2->type == SEL_TREE::ALWAYS) |
8424 | DBUG_RETURN(tree1); |
8425 | if (tree2->type == SEL_TREE::IMPOSSIBLE || tree1->type == SEL_TREE::ALWAYS) |
8426 | DBUG_RETURN(tree2); |
8427 | if (tree1->type == SEL_TREE::MAYBE) |
8428 | { |
8429 | if (tree2->type == SEL_TREE::KEY) |
8430 | tree2->type=SEL_TREE::KEY_SMALLER; |
8431 | DBUG_RETURN(tree2); |
8432 | } |
8433 | if (tree2->type == SEL_TREE::MAYBE) |
8434 | { |
8435 | tree1->type=SEL_TREE::KEY_SMALLER; |
8436 | DBUG_RETURN(tree1); |
8437 | } |
8438 | |
8439 | if (!tree1->merges.is_empty()) |
8440 | imerge_list_and_tree(param, &tree1->merges, tree2, TRUE); |
8441 | if (!tree2->merges.is_empty()) |
8442 | imerge_list_and_tree(param, &tree2->merges, tree1, TRUE); |
8443 | if (and_range_trees(param, tree1, tree2, tree1)) |
8444 | DBUG_RETURN(tree1); |
8445 | imerge_list_and_list(&tree1->merges, &tree2->merges); |
8446 | eliminate_single_tree_imerges(param, tree1); |
8447 | DBUG_RETURN(tree1); |
8448 | } |
8449 | |
8450 | |
8451 | /* |
8452 | Eliminate single tree imerges in a SEL_TREE objects |
8453 | |
8454 | SYNOPSIS |
8455 | eliminate_single_tree_imerges() |
8456 | param Context info for the function |
8457 | tree SEL_TREE where single tree imerges are to be eliminated |
8458 | |
8459 | DESCRIPTION |
8460 | For each imerge in 'tree' that contains only one disjunct tree, i.e. |
8461 | for any imerge of the form m=rt, the function performs and operation |
8462 | the range part of tree, replaces rt the with the result of anding and |
8463 | removes imerge m from the the merge part of 'tree'. |
8464 | |
8465 | RETURN VALUE |
8466 | none |
8467 | */ |
8468 | |
8469 | static |
8470 | void eliminate_single_tree_imerges(RANGE_OPT_PARAM *param, SEL_TREE *tree) |
8471 | { |
8472 | SEL_IMERGE *imerge; |
8473 | List<SEL_IMERGE> merges= tree->merges; |
8474 | List_iterator<SEL_IMERGE> it(merges); |
8475 | tree->merges.empty(); |
8476 | while ((imerge= it++)) |
8477 | { |
8478 | if (imerge->trees+1 == imerge->trees_next) |
8479 | { |
8480 | tree= tree_and(param, tree, *imerge->trees); |
8481 | it.remove(); |
8482 | } |
8483 | } |
8484 | tree->merges= merges; |
8485 | } |
8486 | |
8487 | |
8488 | /* |
8489 | For two trees check that there are indexes with ranges in both of them |
8490 | |
8491 | SYNOPSIS |
8492 | sel_trees_have_common_keys() |
8493 | tree1 SEL_TREE for the first tree |
8494 | tree2 SEL_TREE for the second tree |
8495 | common_keys OUT bitmap of all indexes with ranges in both trees |
8496 | |
8497 | DESCRIPTION |
8498 | For two trees tree1 and tree1 the function checks if there are indexes |
8499 | in their range parts such that SEL_ARG trees are defined for them in the |
8500 | range parts of both trees. The function returns the bitmap of such |
8501 | indexes in the parameter common_keys. |
8502 | |
8503 | RETURN |
8504 | TRUE if there are such indexes (common_keys is nor empty) |
8505 | FALSE otherwise |
8506 | */ |
8507 | |
8508 | static |
8509 | bool sel_trees_have_common_keys(SEL_TREE *tree1, SEL_TREE *tree2, |
8510 | key_map *common_keys) |
8511 | { |
8512 | *common_keys= tree1->keys_map; |
8513 | common_keys->intersect(tree2->keys_map); |
8514 | return !common_keys->is_clear_all(); |
8515 | } |
8516 | |
8517 | |
8518 | /* |
8519 | Check whether range parts of two trees can be ored for some indexes |
8520 | |
8521 | SYNOPSIS |
8522 | sel_trees_can_be_ored() |
8523 | param Context info for the function |
8524 | tree1 SEL_TREE for the first tree |
8525 | tree2 SEL_TREE for the second tree |
8526 | common_keys IN/OUT IN: bitmap of all indexes with SEL_ARG in both trees |
8527 | OUT: bitmap of all indexes that can be ored |
8528 | |
8529 | DESCRIPTION |
8530 | For two trees tree1 and tree2 and the bitmap common_keys containing |
8531 | bits for indexes that have SEL_ARG trees in range parts of both trees |
8532 | the function checks if there are indexes for which SEL_ARG trees can |
8533 | be ored. Two SEL_ARG trees for the same index can be ored if the most |
8534 | major components of the index used in these trees coincide. If the |
8535 | SEL_ARG trees for an index cannot be ored the function clears the bit |
8536 | for this index in the bitmap common_keys. |
8537 | |
8538 | The function does not verify that indexes marked in common_keys really |
8539 | have SEL_ARG trees in both tree1 and tree2. It assumes that this is true. |
8540 | |
8541 | NOTE |
8542 | The function sel_trees_can_be_ored is usually used in pair with the |
8543 | function sel_trees_have_common_keys. |
8544 | |
8545 | RETURN |
8546 | TRUE if there are indexes for which SEL_ARG trees can be ored |
8547 | FALSE otherwise |
8548 | */ |
8549 | |
8550 | static |
8551 | bool sel_trees_can_be_ored(RANGE_OPT_PARAM* param, |
8552 | SEL_TREE *tree1, SEL_TREE *tree2, |
8553 | key_map *common_keys) |
8554 | { |
8555 | DBUG_ENTER("sel_trees_can_be_ored" ); |
8556 | if (!sel_trees_have_common_keys(tree1, tree2, common_keys)) |
8557 | DBUG_RETURN(FALSE); |
8558 | int key_no; |
8559 | key_map::Iterator it(*common_keys); |
8560 | while ((key_no= it++) != key_map::Iterator::BITMAP_END) |
8561 | { |
8562 | DBUG_ASSERT(tree1->keys[key_no] && tree2->keys[key_no]); |
8563 | /* Trees have a common key, check if they refer to the same key part */ |
8564 | if (tree1->keys[key_no]->part != tree2->keys[key_no]->part) |
8565 | common_keys->clear_bit(key_no); |
8566 | } |
8567 | DBUG_RETURN(!common_keys->is_clear_all()); |
8568 | } |
8569 | |
8570 | /* |
8571 | Check whether the key parts inf_init..inf_end-1 of one index can compose |
8572 | an infix for the key parts key_init..key_end-1 of another index |
8573 | */ |
8574 | |
8575 | static |
8576 | bool is_key_infix(KEY_PART *key_init, KEY_PART *key_end, |
8577 | KEY_PART *inf_init, KEY_PART *inf_end) |
8578 | { |
8579 | KEY_PART *key_part, *inf_part; |
8580 | for (key_part= key_init; key_part < key_end; key_part++) |
8581 | { |
8582 | if (key_part->field->eq(inf_init->field)) |
8583 | break; |
8584 | } |
8585 | if (key_part == key_end) |
8586 | return false; |
8587 | for (key_part++, inf_part= inf_init + 1; |
8588 | key_part < key_end && inf_part < inf_end; |
8589 | key_part++, inf_part++) |
8590 | { |
8591 | if (!key_part->field->eq(inf_part->field)) |
8592 | return false; |
8593 | } |
8594 | return inf_part == inf_end; |
8595 | } |
8596 | |
8597 | |
8598 | /* |
8599 | Check whether range parts of two trees must be ored for some indexes |
8600 | |
8601 | SYNOPSIS |
8602 | sel_trees_must_be_ored() |
8603 | param Context info for the function |
8604 | tree1 SEL_TREE for the first tree |
8605 | tree2 SEL_TREE for the second tree |
8606 | ordable_keys bitmap of SEL_ARG trees that can be ored |
8607 | |
8608 | DESCRIPTION |
8609 | For two trees tree1 and tree2 the function checks whether they must be |
8610 | ored. The function assumes that the bitmap ordable_keys contains bits for |
8611 | those corresponding pairs of SEL_ARG trees from tree1 and tree2 that can |
8612 | be ored. |
8613 | We believe that tree1 and tree2 must be ored if any pair of SEL_ARG trees |
8614 | r1 and r2, such that r1 is from tree1 and r2 is from tree2 and both |
8615 | of them are marked in ordable_keys, can be merged. |
8616 | |
8617 | NOTE |
8618 | The function sel_trees_must_be_ored as a rule is used in pair with the |
8619 | function sel_trees_can_be_ored. |
8620 | |
8621 | RETURN |
8622 | TRUE if there are indexes for which SEL_ARG trees must be ored |
8623 | FALSE otherwise |
8624 | */ |
8625 | |
8626 | static |
8627 | bool sel_trees_must_be_ored(RANGE_OPT_PARAM* param, |
8628 | SEL_TREE *tree1, SEL_TREE *tree2, |
8629 | key_map oredable_keys) |
8630 | { |
8631 | key_map tmp; |
8632 | DBUG_ENTER("sel_trees_must_be_ored" ); |
8633 | |
8634 | tmp= tree1->keys_map; |
8635 | tmp.merge(tree2->keys_map); |
8636 | tmp.subtract(oredable_keys); |
8637 | if (!tmp.is_clear_all()) |
8638 | DBUG_RETURN(FALSE); |
8639 | |
8640 | int idx1, idx2; |
8641 | key_map::Iterator it1(oredable_keys); |
8642 | while ((idx1= it1++) != key_map::Iterator::BITMAP_END) |
8643 | { |
8644 | KEY_PART *key1_init= param->key[idx1]+tree1->keys[idx1]->part; |
8645 | KEY_PART *key1_end= param->key[idx1]+tree1->keys[idx1]->max_part_no; |
8646 | key_map::Iterator it2(oredable_keys); |
8647 | while ((idx2= it2++) != key_map::Iterator::BITMAP_END) |
8648 | { |
8649 | if (idx2 <= idx1) |
8650 | continue; |
8651 | |
8652 | KEY_PART *key2_init= param->key[idx2]+tree2->keys[idx2]->part; |
8653 | KEY_PART *key2_end= param->key[idx2]+tree2->keys[idx2]->max_part_no; |
8654 | if (!is_key_infix(key1_init, key1_end, key2_init, key2_end) && |
8655 | !is_key_infix(key2_init, key2_end, key1_init, key1_end)) |
8656 | DBUG_RETURN(FALSE); |
8657 | } |
8658 | } |
8659 | |
8660 | DBUG_RETURN(TRUE); |
8661 | } |
8662 | |
8663 | |
8664 | /* |
8665 | Remove the trees that are not suitable for record retrieval |
8666 | |
8667 | SYNOPSIS |
8668 | remove_nonrange_trees() |
8669 | param Context info for the function |
8670 | tree Tree to be processed, tree->type is KEY or KEY_SMALLER |
8671 | |
8672 | DESCRIPTION |
8673 | This function walks through tree->keys[] and removes the SEL_ARG* trees |
8674 | that are not "maybe" trees (*) and cannot be used to construct quick range |
8675 | selects. |
8676 | (*) - have type MAYBE or MAYBE_KEY. Perhaps we should remove trees of |
8677 | these types here as well. |
8678 | |
8679 | A SEL_ARG* tree cannot be used to construct quick select if it has |
8680 | tree->part != 0. (e.g. it could represent "keypart2 < const"). |
8681 | |
8682 | Normally we allow construction of SEL_TREE objects that have SEL_ARG |
8683 | trees that do not allow quick range select construction. |
8684 | For example: |
8685 | for " keypart1=1 AND keypart2=2 " the execution will proceed as follows: |
8686 | tree1= SEL_TREE { SEL_ARG{keypart1=1} } |
8687 | tree2= SEL_TREE { SEL_ARG{keypart2=2} } -- can't make quick range select |
8688 | from this |
8689 | call tree_and(tree1, tree2) -- this joins SEL_ARGs into a usable SEL_ARG |
8690 | tree. |
8691 | |
8692 | Another example: |
8693 | tree3= SEL_TREE { SEL_ARG{key1part1 = 1} } |
8694 | tree4= SEL_TREE { SEL_ARG{key2part2 = 2} } -- can't make quick range select |
8695 | from this |
8696 | call tree_or(tree3, tree4) -- creates a SEL_MERGE ot of which no index |
8697 | merge can be constructed, but it is potentially useful, as anding it with |
8698 | tree5= SEL_TREE { SEL_ARG{key2part1 = 3} } creates an index merge that |
8699 | represents the formula |
8700 | key1part1=1 AND key2part1=3 OR key2part1=3 AND key2part2=2 |
8701 | for which an index merge can be built. |
8702 | |
8703 | Any final SEL_TREE may contain SEL_ARG trees for which no quick select |
8704 | can be built. Such SEL_ARG trees should be removed from the range part |
8705 | before different range scans are evaluated. Such SEL_ARG trees also should |
8706 | be removed from all range trees of each index merge before different |
8707 | possible index merge plans are evaluated. If after this removal one |
8708 | of the range trees in the index merge becomes empty the whole index merge |
8709 | must be discarded. |
8710 | |
8711 | RETURN |
8712 | 0 Ok, some suitable trees left |
8713 | 1 No tree->keys[] left. |
8714 | */ |
8715 | |
8716 | static bool remove_nonrange_trees(RANGE_OPT_PARAM *param, SEL_TREE *tree) |
8717 | { |
8718 | bool res= FALSE; |
8719 | for (uint i=0; i < param->keys; i++) |
8720 | { |
8721 | if (tree->keys[i]) |
8722 | { |
8723 | if (tree->keys[i]->part) |
8724 | { |
8725 | tree->keys[i]= NULL; |
8726 | tree->keys_map.clear_bit(i); |
8727 | } |
8728 | else |
8729 | res= TRUE; |
8730 | } |
8731 | } |
8732 | return !res; |
8733 | } |
8734 | |
8735 | |
8736 | /* |
8737 | Build a SEL_TREE for a disjunction out of such trees for the disjuncts |
8738 | |
8739 | SYNOPSIS |
8740 | tree_or() |
8741 | param Context info for the operation |
8742 | tree1 SEL_TREE for the first disjunct |
8743 | tree2 SEL_TREE for the second disjunct |
8744 | |
8745 | DESCRIPTION |
8746 | This function builds a tree for the formula (A OR B) out of the trees |
8747 | tree1 and tree2 that has been built for the formulas A and B respectively. |
8748 | |
8749 | In a general case |
8750 | tree1 represents the formula RT1 AND MT1, |
8751 | where RT1=R1_1 AND ... AND R1_k1, MT1=M1_1 AND ... AND M1_l1; |
8752 | tree2 represents the formula RT2 AND MT2 |
8753 | where RT2=R2_1 AND ... AND R2_k2, MT2=M2_1 and ... and M2_l2. |
8754 | |
8755 | The function constructs the result tree according the formula |
8756 | (RT1 OR RT2) AND (MT1 OR RT1) AND (MT2 OR RT2) AND (MT1 OR MT2) |
8757 | that is equivalent to the formula (RT1 AND MT1) OR (RT2 AND MT2). |
8758 | |
8759 | To limit the number of produced imerges the function considers |
8760 | a weaker formula than the original one: |
8761 | (RT1 AND M1_1) OR (RT2 AND M2_1) |
8762 | that is equivalent to: |
8763 | (RT1 OR RT2) (1) |
8764 | AND |
8765 | (M1_1 OR M2_1) (2) |
8766 | AND |
8767 | (M1_1 OR RT2) (3) |
8768 | AND |
8769 | (M2_1 OR RT1) (4) |
8770 | |
8771 | For the first conjunct (1) the function builds a tree with a range part |
8772 | and, possibly, one imerge. For the other conjuncts (2-4)the function |
8773 | produces sets of imerges. All constructed imerges are included into the |
8774 | result tree. |
8775 | |
8776 | For the formula (1) the function produces the tree representing a formula |
8777 | of the structure RT [AND M], such that: |
8778 | - the range tree rt contains the result of oring SEL_ARG trees from rt1 |
8779 | and rt2 |
8780 | - the imerge m consists of two range trees rt1 and rt2. |
8781 | The imerge m is added if it's not true that rt1 and rt2 must be ored |
8782 | If rt1 and rt2 can't be ored rt is empty and only m is produced for (1). |
8783 | |
8784 | To produce imerges for the formula (2) the function calls the function |
8785 | imerge_list_or_list passing it the merge parts of tree1 and tree2 as |
8786 | parameters. |
8787 | |
8788 | To produce imerges for the formula (3) the function calls the function |
8789 | imerge_list_or_tree passing it the imerge m1_1 and the range tree rt2 as |
8790 | parameters. Similarly, to produce imerges for the formula (4) the function |
8791 | calls the function imerge_list_or_tree passing it the imerge m2_1 and the |
8792 | range tree rt1. |
8793 | |
8794 | If rt1 is empty then the trees for (1) and (4) are empty. |
8795 | If rt2 is empty then the trees for (1) and (3) are empty. |
8796 | If mt1 is empty then the trees for (2) and (3) are empty. |
8797 | If mt2 is empty then the trees for (2) and (4) are empty. |
8798 | |
8799 | RETURN |
8800 | The result tree for the operation if a success |
8801 | 0 - otherwise |
8802 | */ |
8803 | |
8804 | static SEL_TREE * |
8805 | tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2) |
8806 | { |
8807 | DBUG_ENTER("tree_or" ); |
8808 | if (!tree1 || !tree2) |
8809 | DBUG_RETURN(0); |
8810 | if (tree1->type == SEL_TREE::IMPOSSIBLE || tree2->type == SEL_TREE::ALWAYS) |
8811 | DBUG_RETURN(tree2); |
8812 | if (tree2->type == SEL_TREE::IMPOSSIBLE || tree1->type == SEL_TREE::ALWAYS) |
8813 | DBUG_RETURN(tree1); |
8814 | if (tree1->type == SEL_TREE::MAYBE) |
8815 | DBUG_RETURN(tree1); // Can't use this |
8816 | if (tree2->type == SEL_TREE::MAYBE) |
8817 | DBUG_RETURN(tree2); |
8818 | |
8819 | SEL_TREE *result= NULL; |
8820 | key_map result_keys; |
8821 | key_map ored_keys; |
8822 | SEL_TREE *rtree[2]= {NULL,NULL}; |
8823 | SEL_IMERGE *imerge[2]= {NULL, NULL}; |
8824 | bool no_ranges1= tree1->without_ranges(); |
8825 | bool no_ranges2= tree2->without_ranges(); |
8826 | bool no_merges1= tree1->without_imerges(); |
8827 | bool no_merges2= tree2->without_imerges(); |
8828 | if (!no_ranges1 && !no_merges2) |
8829 | { |
8830 | rtree[0]= new SEL_TREE(tree1, TRUE, param); |
8831 | imerge[1]= new SEL_IMERGE(tree2->merges.head(), 0, param); |
8832 | } |
8833 | if (!no_ranges2 && !no_merges1) |
8834 | { |
8835 | rtree[1]= new SEL_TREE(tree2, TRUE, param); |
8836 | imerge[0]= new SEL_IMERGE(tree1->merges.head(), 0, param); |
8837 | } |
8838 | bool no_imerge_from_ranges= FALSE; |
8839 | |
8840 | /* Build the range part of the tree for the formula (1) */ |
8841 | if (sel_trees_can_be_ored(param, tree1, tree2, &ored_keys)) |
8842 | { |
8843 | bool must_be_ored= sel_trees_must_be_ored(param, tree1, tree2, ored_keys); |
8844 | no_imerge_from_ranges= must_be_ored; |
8845 | |
8846 | if (no_imerge_from_ranges && no_merges1 && no_merges2) |
8847 | { |
8848 | /* |
8849 | Reuse tree1 as the result in simple cases. This reduces memory usage |
8850 | for e.g. "key IN (c1, ..., cN)" which produces a lot of ranges. |
8851 | */ |
8852 | result= tree1; |
8853 | result->keys_map.clear_all(); |
8854 | } |
8855 | else |
8856 | { |
8857 | if (!(result= new (param->mem_root) SEL_TREE(param->mem_root, |
8858 | param->keys))) |
8859 | { |
8860 | DBUG_RETURN(result); |
8861 | } |
8862 | } |
8863 | |
8864 | key_map::Iterator it(ored_keys); |
8865 | int key_no; |
8866 | while ((key_no= it++) != key_map::Iterator::BITMAP_END) |
8867 | { |
8868 | SEL_ARG *key1= tree1->keys[key_no]; |
8869 | SEL_ARG *key2= tree2->keys[key_no]; |
8870 | if (!must_be_ored) |
8871 | { |
8872 | key1->incr_refs(); |
8873 | key2->incr_refs(); |
8874 | } |
8875 | if ((result->keys[key_no]= key_or(param, key1, key2))) |
8876 | result->keys_map.set_bit(key_no); |
8877 | } |
8878 | result->type= tree1->type; |
8879 | } |
8880 | else |
8881 | { |
8882 | if (!result && !(result= new (param->mem_root) SEL_TREE(param->mem_root, |
8883 | param->keys))) |
8884 | DBUG_RETURN(result); |
8885 | } |
8886 | |
8887 | if (no_imerge_from_ranges && no_merges1 && no_merges2) |
8888 | { |
8889 | if (result->keys_map.is_clear_all()) |
8890 | result->type= SEL_TREE::ALWAYS; |
8891 | DBUG_RETURN(result); |
8892 | } |
8893 | |
8894 | SEL_IMERGE *imerge_from_ranges; |
8895 | if (!(imerge_from_ranges= new SEL_IMERGE())) |
8896 | result= NULL; |
8897 | else if (!no_ranges1 && !no_ranges2 && !no_imerge_from_ranges) |
8898 | { |
8899 | /* Build the imerge part of the tree for the formula (1) */ |
8900 | SEL_TREE *rt1= tree1; |
8901 | SEL_TREE *rt2= tree2; |
8902 | if (no_merges1) |
8903 | rt1= new SEL_TREE(tree1, TRUE, param); |
8904 | if (no_merges2) |
8905 | rt2= new SEL_TREE(tree2, TRUE, param); |
8906 | if (!rt1 || !rt2 || |
8907 | result->merges.push_back(imerge_from_ranges) || |
8908 | imerge_from_ranges->or_sel_tree(param, rt1) || |
8909 | imerge_from_ranges->or_sel_tree(param, rt2)) |
8910 | result= NULL; |
8911 | } |
8912 | if (!result) |
8913 | DBUG_RETURN(result); |
8914 | |
8915 | result->type= tree1->type; |
8916 | |
8917 | if (!no_merges1 && !no_merges2 && |
8918 | !imerge_list_or_list(param, &tree1->merges, &tree2->merges)) |
8919 | { |
8920 | /* Build the imerges for the formula (2) */ |
8921 | imerge_list_and_list(&result->merges, &tree1->merges); |
8922 | } |
8923 | |
8924 | /* Build the imerges for the formulas (3) and (4) */ |
8925 | for (uint i=0; i < 2; i++) |
8926 | { |
8927 | List<SEL_IMERGE> merges; |
8928 | SEL_TREE *rt= rtree[i]; |
8929 | SEL_IMERGE *im= imerge[1-i]; |
8930 | |
8931 | if (rt && im && !merges.push_back(im) && |
8932 | !imerge_list_or_tree(param, &merges, rt)) |
8933 | imerge_list_and_list(&result->merges, &merges); |
8934 | } |
8935 | |
8936 | DBUG_RETURN(result); |
8937 | } |
8938 | |
8939 | |
8940 | /* And key trees where key1->part < key2 -> part */ |
8941 | |
8942 | static SEL_ARG * |
8943 | and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, |
8944 | uint clone_flag) |
8945 | { |
8946 | SEL_ARG *next; |
8947 | ulong use_count=key1->use_count; |
8948 | |
8949 | if (key1->elements != 1) |
8950 | { |
8951 | key2->use_count+=key1->elements-1; //psergey: why we don't count that key1 has n-k-p? |
8952 | key2->increment_use_count((int) key1->elements-1); |
8953 | } |
8954 | if (key1->type == SEL_ARG::MAYBE_KEY) |
8955 | { |
8956 | key1->right= key1->left= &null_element; |
8957 | key1->next= key1->prev= 0; |
8958 | } |
8959 | for (next=key1->first(); next ; next=next->next) |
8960 | { |
8961 | if (next->next_key_part) |
8962 | { |
8963 | SEL_ARG *tmp= key_and(param, next->next_key_part, key2, clone_flag); |
8964 | if (tmp && tmp->type == SEL_ARG::IMPOSSIBLE) |
8965 | { |
8966 | key1=key1->tree_delete(next); |
8967 | continue; |
8968 | } |
8969 | next->next_key_part=tmp; |
8970 | if (use_count) |
8971 | next->increment_use_count(use_count); |
8972 | if (param->alloced_sel_args > SEL_ARG::MAX_SEL_ARGS) |
8973 | break; |
8974 | } |
8975 | else |
8976 | next->next_key_part=key2; |
8977 | } |
8978 | if (!key1) |
8979 | return &null_element; // Impossible ranges |
8980 | key1->use_count++; |
8981 | key1->max_part_no= MY_MAX(key2->max_part_no, key2->part+1); |
8982 | return key1; |
8983 | } |
8984 | |
8985 | |
8986 | /* |
8987 | Produce a SEL_ARG graph that represents "key1 AND key2" |
8988 | |
8989 | SYNOPSIS |
8990 | key_and() |
8991 | param Range analysis context (needed to track if we have allocated |
8992 | too many SEL_ARGs) |
8993 | key1 First argument, root of its RB-tree |
8994 | key2 Second argument, root of its RB-tree |
8995 | |
8996 | RETURN |
8997 | RB-tree root of the resulting SEL_ARG graph. |
8998 | NULL if the result of AND operation is an empty interval {0}. |
8999 | */ |
9000 | |
9001 | static SEL_ARG * |
9002 | key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag) |
9003 | { |
9004 | if (!key1) |
9005 | return key2; |
9006 | if (!key2) |
9007 | return key1; |
9008 | if (key1->part != key2->part) |
9009 | { |
9010 | if (key1->part > key2->part) |
9011 | { |
9012 | swap_variables(SEL_ARG *, key1, key2); |
9013 | clone_flag=swap_clone_flag(clone_flag); |
9014 | } |
9015 | // key1->part < key2->part |
9016 | key1->use_count--; |
9017 | if (key1->use_count > 0) |
9018 | if (!(key1= key1->clone_tree(param))) |
9019 | return 0; // OOM |
9020 | return and_all_keys(param, key1, key2, clone_flag); |
9021 | } |
9022 | |
9023 | if (((clone_flag & CLONE_KEY2_MAYBE) && |
9024 | !(clone_flag & CLONE_KEY1_MAYBE) && |
9025 | key2->type != SEL_ARG::MAYBE_KEY) || |
9026 | key1->type == SEL_ARG::MAYBE_KEY) |
9027 | { // Put simple key in key2 |
9028 | swap_variables(SEL_ARG *, key1, key2); |
9029 | clone_flag=swap_clone_flag(clone_flag); |
9030 | } |
9031 | |
9032 | /* If one of the key is MAYBE_KEY then the found region may be smaller */ |
9033 | if (key2->type == SEL_ARG::MAYBE_KEY) |
9034 | { |
9035 | if (key1->use_count > 1) |
9036 | { |
9037 | key1->use_count--; |
9038 | if (!(key1=key1->clone_tree(param))) |
9039 | return 0; // OOM |
9040 | key1->use_count++; |
9041 | } |
9042 | if (key1->type == SEL_ARG::MAYBE_KEY) |
9043 | { // Both are maybe key |
9044 | key1->next_key_part=key_and(param, key1->next_key_part, |
9045 | key2->next_key_part, clone_flag); |
9046 | if (key1->next_key_part && |
9047 | key1->next_key_part->type == SEL_ARG::IMPOSSIBLE) |
9048 | return key1; |
9049 | } |
9050 | else |
9051 | { |
9052 | key1->maybe_smaller(); |
9053 | if (key2->next_key_part) |
9054 | { |
9055 | key1->use_count--; // Incremented in and_all_keys |
9056 | return and_all_keys(param, key1, key2, clone_flag); |
9057 | } |
9058 | key2->use_count--; // Key2 doesn't have a tree |
9059 | } |
9060 | return key1; |
9061 | } |
9062 | |
9063 | if ((key1->min_flag | key2->min_flag) & GEOM_FLAG) |
9064 | { |
9065 | /* TODO: why not leave one of the trees? */ |
9066 | key1->free_tree(); |
9067 | key2->free_tree(); |
9068 | return 0; // Can't optimize this |
9069 | } |
9070 | |
9071 | key1->use_count--; |
9072 | key2->use_count--; |
9073 | SEL_ARG *e1=key1->first(), *e2=key2->first(), *new_tree=0; |
9074 | uint max_part_no= MY_MAX(key1->max_part_no, key2->max_part_no); |
9075 | |
9076 | while (e1 && e2) |
9077 | { |
9078 | int cmp=e1->cmp_min_to_min(e2); |
9079 | if (cmp < 0) |
9080 | { |
9081 | if (get_range(&e1,&e2,key1)) |
9082 | continue; |
9083 | } |
9084 | else if (get_range(&e2,&e1,key2)) |
9085 | continue; |
9086 | SEL_ARG *next=key_and(param, e1->next_key_part, e2->next_key_part, |
9087 | clone_flag); |
9088 | e1->incr_refs(); |
9089 | e2->incr_refs(); |
9090 | if (!next || next->type != SEL_ARG::IMPOSSIBLE) |
9091 | { |
9092 | SEL_ARG *new_arg= e1->clone_and(param->thd, e2); |
9093 | if (!new_arg) |
9094 | return &null_element; // End of memory |
9095 | new_arg->next_key_part=next; |
9096 | if (!new_tree) |
9097 | { |
9098 | new_tree=new_arg; |
9099 | } |
9100 | else |
9101 | new_tree=new_tree->insert(new_arg); |
9102 | } |
9103 | if (e1->cmp_max_to_max(e2) < 0) |
9104 | e1=e1->next; // e1 can't overlapp next e2 |
9105 | else |
9106 | e2=e2->next; |
9107 | } |
9108 | key1->free_tree(); |
9109 | key2->free_tree(); |
9110 | if (!new_tree) |
9111 | return &null_element; // Impossible range |
9112 | new_tree->max_part_no= max_part_no; |
9113 | return new_tree; |
9114 | } |
9115 | |
9116 | |
9117 | static bool |
9118 | get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1) |
9119 | { |
9120 | (*e1)=root1->find_range(*e2); // first e1->min < e2->min |
9121 | if ((*e1)->cmp_max_to_min(*e2) < 0) |
9122 | { |
9123 | if (!((*e1)=(*e1)->next)) |
9124 | return 1; |
9125 | if ((*e1)->cmp_min_to_max(*e2) > 0) |
9126 | { |
9127 | (*e2)=(*e2)->next; |
9128 | return 1; |
9129 | } |
9130 | } |
9131 | return 0; |
9132 | } |
9133 | |
9134 | |
9135 | /** |
9136 | Combine two range expression under a common OR. On a logical level, the |
9137 | transformation is key_or( expr1, expr2 ) => expr1 OR expr2. |
9138 | |
9139 | Both expressions are assumed to be in the SEL_ARG format. In a logic sense, |
9140 | theformat is reminiscent of DNF, since an expression such as the following |
9141 | |
9142 | ( 1 < kp1 < 10 AND p1 ) OR ( 10 <= kp2 < 20 AND p2 ) |
9143 | |
9144 | where there is a key consisting of keyparts ( kp1, kp2, ..., kpn ) and p1 |
9145 | and p2 are valid SEL_ARG expressions over keyparts kp2 ... kpn, is a valid |
9146 | SEL_ARG condition. The disjuncts appear ordered by the minimum endpoint of |
9147 | the first range and ranges must not overlap. It follows that they are also |
9148 | ordered by maximum endpoints. Thus |
9149 | |
9150 | ( 1 < kp1 <= 2 AND ( kp2 = 2 OR kp2 = 3 ) ) OR kp1 = 3 |
9151 | |
9152 | Is a a valid SER_ARG expression for a key of at least 2 keyparts. |
9153 | |
9154 | For simplicity, we will assume that expr2 is a single range predicate, |
9155 | i.e. on the form ( a < x < b AND ... ). It is easy to generalize to a |
9156 | disjunction of several predicates by subsequently call key_or for each |
9157 | disjunct. |
9158 | |
9159 | The algorithm iterates over each disjunct of expr1, and for each disjunct |
9160 | where the first keypart's range overlaps with the first keypart's range in |
9161 | expr2: |
9162 | |
9163 | If the predicates are equal for the rest of the keyparts, or if there are |
9164 | no more, the range in expr2 has its endpoints copied in, and the SEL_ARG |
9165 | node in expr2 is deallocated. If more ranges became connected in expr1, the |
9166 | surplus is also dealocated. If they differ, two ranges are created. |
9167 | |
9168 | - The range leading up to the overlap. Empty if endpoints are equal. |
9169 | |
9170 | - The overlapping sub-range. May be the entire range if they are equal. |
9171 | |
9172 | Finally, there may be one more range if expr2's first keypart's range has a |
9173 | greater maximum endpoint than the last range in expr1. |
9174 | |
9175 | For the overlapping sub-range, we recursively call key_or. Thus in order to |
9176 | compute key_or of |
9177 | |
9178 | (1) ( 1 < kp1 < 10 AND 1 < kp2 < 10 ) |
9179 | |
9180 | (2) ( 2 < kp1 < 20 AND 4 < kp2 < 20 ) |
9181 | |
9182 | We create the ranges 1 < kp <= 2, 2 < kp1 < 10, 10 <= kp1 < 20. For the |
9183 | first one, we simply hook on the condition for the second keypart from (1) |
9184 | : 1 < kp2 < 10. For the second range 2 < kp1 < 10, key_or( 1 < kp2 < 10, 4 |
9185 | < kp2 < 20 ) is called, yielding 1 < kp2 < 20. For the last range, we reuse |
9186 | the range 4 < kp2 < 20 from (2) for the second keypart. The result is thus |
9187 | |
9188 | ( 1 < kp1 <= 2 AND 1 < kp2 < 10 ) OR |
9189 | ( 2 < kp1 < 10 AND 1 < kp2 < 20 ) OR |
9190 | ( 10 <= kp1 < 20 AND 4 < kp2 < 20 ) |
9191 | */ |
9192 | static SEL_ARG * |
9193 | key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) |
9194 | { |
9195 | if (!key1) |
9196 | { |
9197 | if (key2) |
9198 | { |
9199 | key2->use_count--; |
9200 | key2->free_tree(); |
9201 | } |
9202 | return 0; |
9203 | } |
9204 | if (!key2) |
9205 | { |
9206 | key1->use_count--; |
9207 | key1->free_tree(); |
9208 | return 0; |
9209 | } |
9210 | key1->use_count--; |
9211 | key2->use_count--; |
9212 | |
9213 | if (key1->part != key2->part || |
9214 | (key1->min_flag | key2->min_flag) & GEOM_FLAG) |
9215 | { |
9216 | key1->free_tree(); |
9217 | key2->free_tree(); |
9218 | return 0; // Can't optimize this |
9219 | } |
9220 | |
9221 | // If one of the key is MAYBE_KEY then the found region may be bigger |
9222 | if (key1->type == SEL_ARG::MAYBE_KEY) |
9223 | { |
9224 | key2->free_tree(); |
9225 | key1->use_count++; |
9226 | return key1; |
9227 | } |
9228 | if (key2->type == SEL_ARG::MAYBE_KEY) |
9229 | { |
9230 | key1->free_tree(); |
9231 | key2->use_count++; |
9232 | return key2; |
9233 | } |
9234 | |
9235 | if (key1->use_count > 0) |
9236 | { |
9237 | if (key2->use_count == 0 || key1->elements > key2->elements) |
9238 | { |
9239 | swap_variables(SEL_ARG *,key1,key2); |
9240 | } |
9241 | if (key1->use_count > 0 && !(key1=key1->clone_tree(param))) |
9242 | return 0; // OOM |
9243 | } |
9244 | |
9245 | // Add tree at key2 to tree at key1 |
9246 | bool key2_shared=key2->use_count != 0; |
9247 | key1->maybe_flag|=key2->maybe_flag; |
9248 | |
9249 | /* |
9250 | Notation for illustrations used in the rest of this function: |
9251 | |
9252 | Range: [--------] |
9253 | ^ ^ |
9254 | start stop |
9255 | |
9256 | Two overlapping ranges: |
9257 | [-----] [----] [--] |
9258 | [---] or [---] or [-------] |
9259 | |
9260 | Ambiguity: *** |
9261 | The range starts or stops somewhere in the "***" range. |
9262 | Example: a starts before b and may end before/the same plase/after b |
9263 | a: [----***] |
9264 | b: [---] |
9265 | |
9266 | Adjacent ranges: |
9267 | Ranges that meet but do not overlap. Example: a = "x < 3", b = "x >= 3" |
9268 | a: ----] |
9269 | b: [---- |
9270 | */ |
9271 | |
9272 | uint max_part_no= MY_MAX(key1->max_part_no, key2->max_part_no); |
9273 | |
9274 | for (key2=key2->first(); key2; ) |
9275 | { |
9276 | /* |
9277 | key1 consists of one or more ranges. tmp is the range currently |
9278 | being handled. |
9279 | |
9280 | initialize tmp to the latest range in key1 that starts the same |
9281 | place or before the range in key2 starts |
9282 | |
9283 | key2: [------] |
9284 | key1: [---] [-----] [----] |
9285 | ^ |
9286 | tmp |
9287 | */ |
9288 | SEL_ARG *tmp=key1->find_range(key2); |
9289 | |
9290 | /* |
9291 | Used to describe how two key values are positioned compared to |
9292 | each other. Consider key_value_a.<cmp_func>(key_value_b): |
9293 | |
9294 | -2: key_value_a is smaller than key_value_b, and they are adjacent |
9295 | -1: key_value_a is smaller than key_value_b (not adjacent) |
9296 | 0: the key values are equal |
9297 | 1: key_value_a is bigger than key_value_b (not adjacent) |
9298 | -2: key_value_a is bigger than key_value_b, and they are adjacent |
9299 | |
9300 | Example: "cmp= tmp->cmp_max_to_min(key2)" |
9301 | |
9302 | key2: [-------- (10 <= x ...) |
9303 | tmp: -----] (... x < 10) => cmp==-2 |
9304 | tmp: ----] (... x <= 9) => cmp==-1 |
9305 | tmp: ------] (... x = 10) => cmp== 0 |
9306 | tmp: --------] (... x <= 12) => cmp== 1 |
9307 | (cmp == 2 does not make sense for cmp_max_to_min()) |
9308 | */ |
9309 | int cmp= 0; |
9310 | |
9311 | if (!tmp) |
9312 | { |
9313 | /* |
9314 | The range in key2 starts before the first range in key1. Use |
9315 | the first range in key1 as tmp. |
9316 | |
9317 | key2: [--------] |
9318 | key1: [****--] [----] [-------] |
9319 | ^ |
9320 | tmp |
9321 | */ |
9322 | tmp=key1->first(); |
9323 | cmp= -1; |
9324 | } |
9325 | else if ((cmp= tmp->cmp_max_to_min(key2)) < 0) |
9326 | { |
9327 | /* |
9328 | This is the case: |
9329 | key2: [-------] |
9330 | tmp: [----**] |
9331 | */ |
9332 | SEL_ARG *next=tmp->next; |
9333 | if (cmp == -2 && eq_tree(tmp->next_key_part,key2->next_key_part)) |
9334 | { |
9335 | /* |
9336 | Adjacent (cmp==-2) and equal next_key_parts => ranges can be merged |
9337 | |
9338 | This is the case: |
9339 | key2: [-------] |
9340 | tmp: [----] |
9341 | |
9342 | Result: |
9343 | key2: [-------------] => inserted into key1 below |
9344 | tmp: => deleted |
9345 | */ |
9346 | SEL_ARG *key2_next=key2->next; |
9347 | if (key2_shared) |
9348 | { |
9349 | if (!(key2=new SEL_ARG(*key2))) |
9350 | return 0; // out of memory |
9351 | key2->increment_use_count(key1->use_count+1); |
9352 | key2->next=key2_next; // New copy of key2 |
9353 | } |
9354 | |
9355 | key2->copy_min(tmp); |
9356 | if (!(key1=key1->tree_delete(tmp))) |
9357 | { // Only one key in tree |
9358 | key1=key2; |
9359 | key1->make_root(); |
9360 | key2=key2_next; |
9361 | break; |
9362 | } |
9363 | } |
9364 | if (!(tmp=next)) // Move to next range in key1. Now tmp.min > key2.min |
9365 | break; // No more ranges in key1. Copy rest of key2 |
9366 | } |
9367 | |
9368 | if (cmp < 0) |
9369 | { |
9370 | /* |
9371 | This is the case: |
9372 | key2: [--***] |
9373 | tmp: [----] |
9374 | */ |
9375 | int tmp_cmp; |
9376 | if ((tmp_cmp=tmp->cmp_min_to_max(key2)) > 0) |
9377 | { |
9378 | /* |
9379 | This is the case: |
9380 | key2: [------**] |
9381 | tmp: [----] |
9382 | */ |
9383 | if (tmp_cmp == 2 && eq_tree(tmp->next_key_part,key2->next_key_part)) |
9384 | { |
9385 | /* |
9386 | Adjacent ranges with equal next_key_part. Merge like this: |
9387 | |
9388 | This is the case: |
9389 | key2: [------] |
9390 | tmp: [-----] |
9391 | |
9392 | Result: |
9393 | key2: [------] |
9394 | tmp: [-------------] |
9395 | |
9396 | Then move on to next key2 range. |
9397 | */ |
9398 | tmp->copy_min_to_min(key2); |
9399 | key1->merge_flags(key2); |
9400 | if (tmp->min_flag & NO_MIN_RANGE && |
9401 | tmp->max_flag & NO_MAX_RANGE) |
9402 | { |
9403 | if (key1->maybe_flag) |
9404 | return new SEL_ARG(SEL_ARG::MAYBE_KEY); |
9405 | return 0; |
9406 | } |
9407 | key2->increment_use_count(-1); // Free not used tree |
9408 | key2=key2->next; |
9409 | continue; |
9410 | } |
9411 | else |
9412 | { |
9413 | /* |
9414 | key2 not adjacent to tmp or has different next_key_part. |
9415 | Insert into key1 and move to next range in key2 |
9416 | |
9417 | This is the case: |
9418 | key2: [------**] |
9419 | tmp: [----] |
9420 | |
9421 | Result: |
9422 | key1_ [------**][----] |
9423 | ^ ^ |
9424 | insert tmp |
9425 | */ |
9426 | SEL_ARG *next=key2->next; |
9427 | if (key2_shared) |
9428 | { |
9429 | SEL_ARG *cpy= new SEL_ARG(*key2); // Must make copy |
9430 | if (!cpy) |
9431 | return 0; // OOM |
9432 | key1=key1->insert(cpy); |
9433 | key2->increment_use_count(key1->use_count+1); |
9434 | } |
9435 | else |
9436 | key1=key1->insert(key2); // Will destroy key2_root |
9437 | key2=next; |
9438 | continue; |
9439 | } |
9440 | } |
9441 | } |
9442 | |
9443 | /* |
9444 | The ranges in tmp and key2 are overlapping: |
9445 | |
9446 | key2: [----------] |
9447 | tmp: [*****-----*****] |
9448 | |
9449 | Corollary: tmp.min <= key2.max |
9450 | */ |
9451 | if (eq_tree(tmp->next_key_part,key2->next_key_part)) |
9452 | { |
9453 | // Merge overlapping ranges with equal next_key_part |
9454 | if (tmp->is_same(key2)) |
9455 | { |
9456 | /* |
9457 | Found exact match of key2 inside key1. |
9458 | Use the relevant range in key1. |
9459 | */ |
9460 | tmp->merge_flags(key2); // Copy maybe flags |
9461 | key2->increment_use_count(-1); // Free not used tree |
9462 | } |
9463 | else |
9464 | { |
9465 | SEL_ARG *last= tmp; |
9466 | SEL_ARG *first= tmp; |
9467 | |
9468 | /* |
9469 | Find the last range in key1 that overlaps key2 and |
9470 | where all ranges first...last have the same next_key_part as |
9471 | key2. |
9472 | |
9473 | key2: [****----------------------*******] |
9474 | key1: [--] [----] [---] [-----] [xxxx] |
9475 | ^ ^ ^ |
9476 | first last different next_key_part |
9477 | |
9478 | Since key2 covers them, the ranges between first and last |
9479 | are merged into one range by deleting first...last-1 from |
9480 | the key1 tree. In the figure, this applies to first and the |
9481 | two consecutive ranges. The range of last is then extended: |
9482 | * last.min: Set to MY_MIN(key2.min, first.min) |
9483 | * last.max: If there is a last->next that overlaps key2 (i.e., |
9484 | last->next has a different next_key_part): |
9485 | Set adjacent to last->next.min |
9486 | Otherwise: Set to MY_MAX(key2.max, last.max) |
9487 | |
9488 | Result: |
9489 | key2: [****----------------------*******] |
9490 | [--] [----] [---] => deleted from key1 |
9491 | key1: [**------------------------***][xxxx] |
9492 | ^ ^ |
9493 | tmp=last different next_key_part |
9494 | */ |
9495 | while (last->next && last->next->cmp_min_to_max(key2) <= 0 && |
9496 | eq_tree(last->next->next_key_part,key2->next_key_part)) |
9497 | { |
9498 | /* |
9499 | last->next is covered by key2 and has same next_key_part. |
9500 | last can be deleted |
9501 | */ |
9502 | SEL_ARG *save=last; |
9503 | last=last->next; |
9504 | key1=key1->tree_delete(save); |
9505 | } |
9506 | // Redirect tmp to last which will cover the entire range |
9507 | tmp= last; |
9508 | |
9509 | /* |
9510 | We need the minimum endpoint of first so we can compare it |
9511 | with the minimum endpoint of the enclosing key2 range. |
9512 | */ |
9513 | last->copy_min(first); |
9514 | bool full_range= last->copy_min(key2); |
9515 | if (!full_range) |
9516 | { |
9517 | if (last->next && key2->cmp_max_to_min(last->next) >= 0) |
9518 | { |
9519 | /* |
9520 | This is the case: |
9521 | key2: [-------------] |
9522 | key1: [***------] [xxxx] |
9523 | ^ ^ |
9524 | last different next_key_part |
9525 | |
9526 | Extend range of last up to last->next: |
9527 | key2: [-------------] |
9528 | key1: [***--------][xxxx] |
9529 | */ |
9530 | last->copy_min_to_max(last->next); |
9531 | } |
9532 | else |
9533 | /* |
9534 | This is the case: |
9535 | key2: [--------*****] |
9536 | key1: [***---------] [xxxx] |
9537 | ^ ^ |
9538 | last different next_key_part |
9539 | |
9540 | Extend range of last up to MY_MAX(last.max, key2.max): |
9541 | key2: [--------*****] |
9542 | key1: [***----------**] [xxxx] |
9543 | */ |
9544 | full_range= last->copy_max(key2); |
9545 | } |
9546 | if (full_range) |
9547 | { // Full range |
9548 | key1->free_tree(); |
9549 | for (; key2 ; key2=key2->next) |
9550 | key2->increment_use_count(-1); // Free not used tree |
9551 | if (key1->maybe_flag) |
9552 | return new SEL_ARG(SEL_ARG::MAYBE_KEY); |
9553 | return 0; |
9554 | } |
9555 | } |
9556 | } |
9557 | |
9558 | if (cmp >= 0 && tmp->cmp_min_to_min(key2) < 0) |
9559 | { |
9560 | /* |
9561 | This is the case ("cmp>=0" means that tmp.max >= key2.min): |
9562 | key2: [----] |
9563 | tmp: [------------*****] |
9564 | */ |
9565 | |
9566 | if (!tmp->next_key_part) |
9567 | { |
9568 | if (key2->use_count) |
9569 | { |
9570 | SEL_ARG *key2_cpy= new SEL_ARG(*key2); |
9571 | if (key2_cpy) |
9572 | return 0; |
9573 | key2= key2_cpy; |
9574 | } |
9575 | /* |
9576 | tmp->next_key_part is empty: cut the range that is covered |
9577 | by tmp from key2. |
9578 | Reason: (key2->next_key_part OR tmp->next_key_part) will be |
9579 | empty and therefore equal to tmp->next_key_part. Thus, this |
9580 | part of the key2 range is completely covered by tmp. |
9581 | */ |
9582 | if (tmp->cmp_max_to_max(key2) >= 0) |
9583 | { |
9584 | /* |
9585 | tmp covers the entire range in key2. |
9586 | key2: [----] |
9587 | tmp: [-----------------] |
9588 | |
9589 | Move on to next range in key2 |
9590 | */ |
9591 | key2->increment_use_count(-1); // Free not used tree |
9592 | key2=key2->next; |
9593 | continue; |
9594 | } |
9595 | else |
9596 | { |
9597 | /* |
9598 | This is the case: |
9599 | key2: [-------] |
9600 | tmp: [---------] |
9601 | |
9602 | Result: |
9603 | key2: [---] |
9604 | tmp: [---------] |
9605 | */ |
9606 | key2->copy_max_to_min(tmp); |
9607 | continue; |
9608 | } |
9609 | } |
9610 | |
9611 | /* |
9612 | The ranges are overlapping but have not been merged because |
9613 | next_key_part of tmp and key2 differ. |
9614 | key2: [----] |
9615 | tmp: [------------*****] |
9616 | |
9617 | Split tmp in two where key2 starts: |
9618 | key2: [----] |
9619 | key1: [--------][--*****] |
9620 | ^ ^ |
9621 | insert tmp |
9622 | */ |
9623 | SEL_ARG *new_arg=tmp->clone_first(key2); |
9624 | if (!new_arg) |
9625 | return 0; // OOM |
9626 | if ((new_arg->next_key_part= tmp->next_key_part)) |
9627 | new_arg->increment_use_count(key1->use_count+1); |
9628 | tmp->copy_min_to_min(key2); |
9629 | key1=key1->insert(new_arg); |
9630 | } // tmp.min >= key2.min due to this if() |
9631 | |
9632 | /* |
9633 | Now key2.min <= tmp.min <= key2.max: |
9634 | key2: [---------] |
9635 | tmp: [****---*****] |
9636 | */ |
9637 | SEL_ARG key2_cpy(*key2); // Get copy we can modify |
9638 | for (;;) |
9639 | { |
9640 | if (tmp->cmp_min_to_min(&key2_cpy) > 0) |
9641 | { |
9642 | /* |
9643 | This is the case: |
9644 | key2_cpy: [------------] |
9645 | key1: [-*****] |
9646 | ^ |
9647 | tmp |
9648 | |
9649 | Result: |
9650 | key2_cpy: [---] |
9651 | key1: [-------][-*****] |
9652 | ^ ^ |
9653 | insert tmp |
9654 | */ |
9655 | SEL_ARG *new_arg=key2_cpy.clone_first(tmp); |
9656 | if (!new_arg) |
9657 | return 0; // OOM |
9658 | if ((new_arg->next_key_part=key2_cpy.next_key_part)) |
9659 | new_arg->increment_use_count(key1->use_count+1); |
9660 | key1=key1->insert(new_arg); |
9661 | key2_cpy.copy_min_to_min(tmp); |
9662 | } |
9663 | // Now key2_cpy.min == tmp.min |
9664 | |
9665 | if ((cmp= tmp->cmp_max_to_max(&key2_cpy)) <= 0) |
9666 | { |
9667 | /* |
9668 | tmp.max <= key2_cpy.max: |
9669 | key2_cpy: a) [-------] or b) [----] |
9670 | tmp: [----] [----] |
9671 | |
9672 | Steps: |
9673 | 1) Update next_key_part of tmp: OR it with key2_cpy->next_key_part. |
9674 | 2) If case a: Insert range [tmp.max, key2_cpy.max] into key1 using |
9675 | next_key_part of key2_cpy |
9676 | |
9677 | Result: |
9678 | key1: a) [----][-] or b) [----] |
9679 | */ |
9680 | tmp->maybe_flag|= key2_cpy.maybe_flag; |
9681 | key2_cpy.increment_use_count(key1->use_count+1); |
9682 | tmp->next_key_part= key_or(param, tmp->next_key_part, |
9683 | key2_cpy.next_key_part); |
9684 | |
9685 | if (!cmp) |
9686 | break; // case b: done with this key2 range |
9687 | |
9688 | // Make key2_cpy the range [tmp.max, key2_cpy.max] |
9689 | key2_cpy.copy_max_to_min(tmp); |
9690 | if (!(tmp=tmp->next)) |
9691 | { |
9692 | /* |
9693 | No more ranges in key1. Insert key2_cpy and go to "end" |
9694 | label to insert remaining ranges in key2 if any. |
9695 | */ |
9696 | SEL_ARG *tmp2= new SEL_ARG(key2_cpy); |
9697 | if (!tmp2) |
9698 | return 0; // OOM |
9699 | key1=key1->insert(tmp2); |
9700 | key2=key2->next; |
9701 | goto end; |
9702 | } |
9703 | if (tmp->cmp_min_to_max(&key2_cpy) > 0) |
9704 | { |
9705 | /* |
9706 | The next range in key1 does not overlap with key2_cpy. |
9707 | Insert this range into key1 and move on to the next range |
9708 | in key2. |
9709 | */ |
9710 | SEL_ARG *tmp2= new SEL_ARG(key2_cpy); |
9711 | if (!tmp2) |
9712 | return 0; // OOM |
9713 | key1=key1->insert(tmp2); |
9714 | break; |
9715 | } |
9716 | /* |
9717 | key2_cpy overlaps with the next range in key1 and the case |
9718 | is now "key2.min <= tmp.min <= key2.max". Go back to for(;;) |
9719 | to handle this situation. |
9720 | */ |
9721 | continue; |
9722 | } |
9723 | else |
9724 | { |
9725 | /* |
9726 | This is the case: |
9727 | key2_cpy: [-------] |
9728 | tmp: [------------] |
9729 | |
9730 | Result: |
9731 | key1: [-------][---] |
9732 | ^ ^ |
9733 | new_arg tmp |
9734 | Steps: |
9735 | 0) If tmp->next_key_part is empty: do nothing. Reason: |
9736 | (key2_cpy->next_key_part OR tmp->next_key_part) will be |
9737 | empty and therefore equal to tmp->next_key_part. Thus, |
9738 | the range in key2_cpy is completely covered by tmp |
9739 | 1) Make new_arg with range [tmp.min, key2_cpy.max]. |
9740 | new_arg->next_key_part is OR between next_key_part |
9741 | of tmp and key2_cpy |
9742 | 2) Make tmp the range [key2.max, tmp.max] |
9743 | 3) Insert new_arg into key1 |
9744 | */ |
9745 | if (!tmp->next_key_part) // Step 0 |
9746 | { |
9747 | key2_cpy.increment_use_count(-1); // Free not used tree |
9748 | break; |
9749 | } |
9750 | SEL_ARG *new_arg=tmp->clone_last(&key2_cpy); |
9751 | if (!new_arg) |
9752 | return 0; // OOM |
9753 | tmp->copy_max_to_min(&key2_cpy); |
9754 | tmp->increment_use_count(key1->use_count+1); |
9755 | /* Increment key count as it may be used for next loop */ |
9756 | key2_cpy.increment_use_count(1); |
9757 | new_arg->next_key_part= key_or(param, tmp->next_key_part, |
9758 | key2_cpy.next_key_part); |
9759 | key1=key1->insert(new_arg); |
9760 | break; |
9761 | } |
9762 | } |
9763 | // Move on to next range in key2 |
9764 | key2=key2->next; |
9765 | } |
9766 | |
9767 | end: |
9768 | /* |
9769 | Add key2 ranges that are non-overlapping with and higher than the |
9770 | highest range in key1. |
9771 | */ |
9772 | while (key2) |
9773 | { |
9774 | SEL_ARG *next=key2->next; |
9775 | if (key2_shared) |
9776 | { |
9777 | SEL_ARG *tmp=new SEL_ARG(*key2); // Must make copy |
9778 | if (!tmp) |
9779 | return 0; |
9780 | key2->increment_use_count(key1->use_count+1); |
9781 | key1=key1->insert(tmp); |
9782 | } |
9783 | else |
9784 | key1=key1->insert(key2); // Will destroy key2_root |
9785 | key2=next; |
9786 | } |
9787 | key1->use_count++; |
9788 | |
9789 | key1->max_part_no= max_part_no; |
9790 | return key1; |
9791 | } |
9792 | |
9793 | |
9794 | /* Compare if two trees are equal */ |
9795 | |
9796 | static bool eq_tree(SEL_ARG* a,SEL_ARG *b) |
9797 | { |
9798 | if (a == b) |
9799 | return 1; |
9800 | if (!a || !b || !a->is_same(b)) |
9801 | return 0; |
9802 | if (a->left != &null_element && b->left != &null_element) |
9803 | { |
9804 | if (!eq_tree(a->left,b->left)) |
9805 | return 0; |
9806 | } |
9807 | else if (a->left != &null_element || b->left != &null_element) |
9808 | return 0; |
9809 | if (a->right != &null_element && b->right != &null_element) |
9810 | { |
9811 | if (!eq_tree(a->right,b->right)) |
9812 | return 0; |
9813 | } |
9814 | else if (a->right != &null_element || b->right != &null_element) |
9815 | return 0; |
9816 | if (a->next_key_part != b->next_key_part) |
9817 | { // Sub range |
9818 | if (!a->next_key_part != !b->next_key_part || |
9819 | !eq_tree(a->next_key_part, b->next_key_part)) |
9820 | return 0; |
9821 | } |
9822 | return 1; |
9823 | } |
9824 | |
9825 | |
9826 | SEL_ARG * |
9827 | SEL_ARG::insert(SEL_ARG *key) |
9828 | { |
9829 | SEL_ARG *element,**UNINIT_VAR(par),*UNINIT_VAR(last_element); |
9830 | |
9831 | for (element= this; element != &null_element ; ) |
9832 | { |
9833 | last_element=element; |
9834 | if (key->cmp_min_to_min(element) > 0) |
9835 | { |
9836 | par= &element->right; element= element->right; |
9837 | } |
9838 | else |
9839 | { |
9840 | par = &element->left; element= element->left; |
9841 | } |
9842 | } |
9843 | *par=key; |
9844 | key->parent=last_element; |
9845 | /* Link in list */ |
9846 | if (par == &last_element->left) |
9847 | { |
9848 | key->next=last_element; |
9849 | if ((key->prev=last_element->prev)) |
9850 | key->prev->next=key; |
9851 | last_element->prev=key; |
9852 | } |
9853 | else |
9854 | { |
9855 | if ((key->next=last_element->next)) |
9856 | key->next->prev=key; |
9857 | key->prev=last_element; |
9858 | last_element->next=key; |
9859 | } |
9860 | key->left=key->right= &null_element; |
9861 | SEL_ARG *root=rb_insert(key); // rebalance tree |
9862 | root->use_count=this->use_count; // copy root info |
9863 | root->elements= this->elements+1; |
9864 | root->maybe_flag=this->maybe_flag; |
9865 | return root; |
9866 | } |
9867 | |
9868 | |
9869 | /* |
9870 | ** Find best key with min <= given key |
9871 | ** Because the call context this should never return 0 to get_range |
9872 | */ |
9873 | |
9874 | SEL_ARG * |
9875 | SEL_ARG::find_range(SEL_ARG *key) |
9876 | { |
9877 | SEL_ARG *element=this,*found=0; |
9878 | |
9879 | for (;;) |
9880 | { |
9881 | if (element == &null_element) |
9882 | return found; |
9883 | int cmp=element->cmp_min_to_min(key); |
9884 | if (cmp == 0) |
9885 | return element; |
9886 | if (cmp < 0) |
9887 | { |
9888 | found=element; |
9889 | element=element->right; |
9890 | } |
9891 | else |
9892 | element=element->left; |
9893 | } |
9894 | } |
9895 | |
9896 | |
9897 | /* |
9898 | Remove a element from the tree |
9899 | |
9900 | SYNOPSIS |
9901 | tree_delete() |
9902 | key Key that is to be deleted from tree (this) |
9903 | |
9904 | NOTE |
9905 | This also frees all sub trees that is used by the element |
9906 | |
9907 | RETURN |
9908 | root of new tree (with key deleted) |
9909 | */ |
9910 | |
9911 | SEL_ARG * |
9912 | SEL_ARG::tree_delete(SEL_ARG *key) |
9913 | { |
9914 | enum leaf_color remove_color; |
9915 | SEL_ARG *root,*nod,**par,*fix_par; |
9916 | DBUG_ENTER("tree_delete" ); |
9917 | |
9918 | root=this; |
9919 | this->parent= 0; |
9920 | |
9921 | /* Unlink from list */ |
9922 | if (key->prev) |
9923 | key->prev->next=key->next; |
9924 | if (key->next) |
9925 | key->next->prev=key->prev; |
9926 | key->increment_use_count(-1); |
9927 | if (!key->parent) |
9928 | par= &root; |
9929 | else |
9930 | par=key->parent_ptr(); |
9931 | |
9932 | if (key->left == &null_element) |
9933 | { |
9934 | *par=nod=key->right; |
9935 | fix_par=key->parent; |
9936 | if (nod != &null_element) |
9937 | nod->parent=fix_par; |
9938 | remove_color= key->color; |
9939 | } |
9940 | else if (key->right == &null_element) |
9941 | { |
9942 | *par= nod=key->left; |
9943 | nod->parent=fix_par=key->parent; |
9944 | remove_color= key->color; |
9945 | } |
9946 | else |
9947 | { |
9948 | SEL_ARG *tmp=key->next; // next bigger key (exist!) |
9949 | nod= *tmp->parent_ptr()= tmp->right; // unlink tmp from tree |
9950 | fix_par=tmp->parent; |
9951 | if (nod != &null_element) |
9952 | nod->parent=fix_par; |
9953 | remove_color= tmp->color; |
9954 | |
9955 | tmp->parent=key->parent; // Move node in place of key |
9956 | (tmp->left=key->left)->parent=tmp; |
9957 | if ((tmp->right=key->right) != &null_element) |
9958 | tmp->right->parent=tmp; |
9959 | tmp->color=key->color; |
9960 | *par=tmp; |
9961 | if (fix_par == key) // key->right == key->next |
9962 | fix_par=tmp; // new parent of nod |
9963 | } |
9964 | |
9965 | if (root == &null_element) |
9966 | DBUG_RETURN(0); // Maybe root later |
9967 | if (remove_color == BLACK) |
9968 | root=rb_delete_fixup(root,nod,fix_par); |
9969 | test_rb_tree(root,root->parent); |
9970 | |
9971 | root->use_count=this->use_count; // Fix root counters |
9972 | root->elements=this->elements-1; |
9973 | root->maybe_flag=this->maybe_flag; |
9974 | DBUG_RETURN(root); |
9975 | } |
9976 | |
9977 | |
9978 | /* Functions to fix up the tree after insert and delete */ |
9979 | |
9980 | static void left_rotate(SEL_ARG **root,SEL_ARG *leaf) |
9981 | { |
9982 | SEL_ARG *y=leaf->right; |
9983 | leaf->right=y->left; |
9984 | if (y->left != &null_element) |
9985 | y->left->parent=leaf; |
9986 | if (!(y->parent=leaf->parent)) |
9987 | *root=y; |
9988 | else |
9989 | *leaf->parent_ptr()=y; |
9990 | y->left=leaf; |
9991 | leaf->parent=y; |
9992 | } |
9993 | |
9994 | static void right_rotate(SEL_ARG **root,SEL_ARG *leaf) |
9995 | { |
9996 | SEL_ARG *y=leaf->left; |
9997 | leaf->left=y->right; |
9998 | if (y->right != &null_element) |
9999 | y->right->parent=leaf; |
10000 | if (!(y->parent=leaf->parent)) |
10001 | *root=y; |
10002 | else |
10003 | *leaf->parent_ptr()=y; |
10004 | y->right=leaf; |
10005 | leaf->parent=y; |
10006 | } |
10007 | |
10008 | |
10009 | SEL_ARG * |
10010 | SEL_ARG::rb_insert(SEL_ARG *leaf) |
10011 | { |
10012 | SEL_ARG *y,*par,*par2,*root; |
10013 | root= this; root->parent= 0; |
10014 | |
10015 | leaf->color=RED; |
10016 | while (leaf != root && (par= leaf->parent)->color == RED) |
10017 | { // This can't be root or 1 level under |
10018 | if (par == (par2= leaf->parent->parent)->left) |
10019 | { |
10020 | y= par2->right; |
10021 | if (y->color == RED) |
10022 | { |
10023 | par->color=BLACK; |
10024 | y->color=BLACK; |
10025 | leaf=par2; |
10026 | leaf->color=RED; /* And the loop continues */ |
10027 | } |
10028 | else |
10029 | { |
10030 | if (leaf == par->right) |
10031 | { |
10032 | left_rotate(&root,leaf->parent); |
10033 | par=leaf; /* leaf is now parent to old leaf */ |
10034 | } |
10035 | par->color=BLACK; |
10036 | par2->color=RED; |
10037 | right_rotate(&root,par2); |
10038 | break; |
10039 | } |
10040 | } |
10041 | else |
10042 | { |
10043 | y= par2->left; |
10044 | if (y->color == RED) |
10045 | { |
10046 | par->color=BLACK; |
10047 | y->color=BLACK; |
10048 | leaf=par2; |
10049 | leaf->color=RED; /* And the loop continues */ |
10050 | } |
10051 | else |
10052 | { |
10053 | if (leaf == par->left) |
10054 | { |
10055 | right_rotate(&root,par); |
10056 | par=leaf; |
10057 | } |
10058 | par->color=BLACK; |
10059 | par2->color=RED; |
10060 | left_rotate(&root,par2); |
10061 | break; |
10062 | } |
10063 | } |
10064 | } |
10065 | root->color=BLACK; |
10066 | test_rb_tree(root,root->parent); |
10067 | return root; |
10068 | } |
10069 | |
10070 | |
10071 | SEL_ARG *rb_delete_fixup(SEL_ARG *root,SEL_ARG *key,SEL_ARG *par) |
10072 | { |
10073 | SEL_ARG *x,*w; |
10074 | root->parent=0; |
10075 | |
10076 | x= key; |
10077 | while (x != root && x->color == SEL_ARG::BLACK) |
10078 | { |
10079 | if (x == par->left) |
10080 | { |
10081 | w=par->right; |
10082 | if (w->color == SEL_ARG::RED) |
10083 | { |
10084 | w->color=SEL_ARG::BLACK; |
10085 | par->color=SEL_ARG::RED; |
10086 | left_rotate(&root,par); |
10087 | w=par->right; |
10088 | } |
10089 | if (w->left->color == SEL_ARG::BLACK && w->right->color == SEL_ARG::BLACK) |
10090 | { |
10091 | w->color=SEL_ARG::RED; |
10092 | x=par; |
10093 | } |
10094 | else |
10095 | { |
10096 | if (w->right->color == SEL_ARG::BLACK) |
10097 | { |
10098 | w->left->color=SEL_ARG::BLACK; |
10099 | w->color=SEL_ARG::RED; |
10100 | right_rotate(&root,w); |
10101 | w=par->right; |
10102 | } |
10103 | w->color=par->color; |
10104 | par->color=SEL_ARG::BLACK; |
10105 | w->right->color=SEL_ARG::BLACK; |
10106 | left_rotate(&root,par); |
10107 | x=root; |
10108 | break; |
10109 | } |
10110 | } |
10111 | else |
10112 | { |
10113 | w=par->left; |
10114 | if (w->color == SEL_ARG::RED) |
10115 | { |
10116 | w->color=SEL_ARG::BLACK; |
10117 | par->color=SEL_ARG::RED; |
10118 | right_rotate(&root,par); |
10119 | w=par->left; |
10120 | } |
10121 | if (w->right->color == SEL_ARG::BLACK && w->left->color == SEL_ARG::BLACK) |
10122 | { |
10123 | w->color=SEL_ARG::RED; |
10124 | x=par; |
10125 | } |
10126 | else |
10127 | { |
10128 | if (w->left->color == SEL_ARG::BLACK) |
10129 | { |
10130 | w->right->color=SEL_ARG::BLACK; |
10131 | w->color=SEL_ARG::RED; |
10132 | left_rotate(&root,w); |
10133 | w=par->left; |
10134 | } |
10135 | w->color=par->color; |
10136 | par->color=SEL_ARG::BLACK; |
10137 | w->left->color=SEL_ARG::BLACK; |
10138 | right_rotate(&root,par); |
10139 | x=root; |
10140 | break; |
10141 | } |
10142 | } |
10143 | par=x->parent; |
10144 | } |
10145 | x->color=SEL_ARG::BLACK; |
10146 | return root; |
10147 | } |
10148 | |
10149 | |
10150 | /* Test that the properties for a red-black tree hold */ |
10151 | |
10152 | #ifdef EXTRA_DEBUG |
10153 | int test_rb_tree(SEL_ARG *element,SEL_ARG *parent) |
10154 | { |
10155 | int count_l,count_r; |
10156 | |
10157 | if (element == &null_element) |
10158 | return 0; // Found end of tree |
10159 | if (element->parent != parent) |
10160 | { |
10161 | sql_print_error("Wrong tree: Parent doesn't point at parent" ); |
10162 | return -1; |
10163 | } |
10164 | if (element->color == SEL_ARG::RED && |
10165 | (element->left->color == SEL_ARG::RED || |
10166 | element->right->color == SEL_ARG::RED)) |
10167 | { |
10168 | sql_print_error("Wrong tree: Found two red in a row" ); |
10169 | return -1; |
10170 | } |
10171 | if (element->left == element->right && element->left != &null_element) |
10172 | { // Dummy test |
10173 | sql_print_error("Wrong tree: Found right == left" ); |
10174 | return -1; |
10175 | } |
10176 | count_l=test_rb_tree(element->left,element); |
10177 | count_r=test_rb_tree(element->right,element); |
10178 | if (count_l >= 0 && count_r >= 0) |
10179 | { |
10180 | if (count_l == count_r) |
10181 | return count_l+(element->color == SEL_ARG::BLACK); |
10182 | sql_print_error("Wrong tree: Incorrect black-count: %d - %d" , |
10183 | count_l,count_r); |
10184 | } |
10185 | return -1; // Error, no more warnings |
10186 | } |
10187 | |
10188 | |
10189 | /** |
10190 | Count how many times SEL_ARG graph "root" refers to its part "key" via |
10191 | transitive closure. |
10192 | |
10193 | @param root An RB-Root node in a SEL_ARG graph. |
10194 | @param key Another RB-Root node in that SEL_ARG graph. |
10195 | |
10196 | The passed "root" node may refer to "key" node via root->next_key_part, |
10197 | root->next->n |
10198 | |
10199 | This function counts how many times the node "key" is referred (via |
10200 | SEL_ARG::next_key_part) by |
10201 | - intervals of RB-tree pointed by "root", |
10202 | - intervals of RB-trees that are pointed by SEL_ARG::next_key_part from |
10203 | intervals of RB-tree pointed by "root", |
10204 | - and so on. |
10205 | |
10206 | Here is an example (horizontal links represent next_key_part pointers, |
10207 | vertical links - next/prev prev pointers): |
10208 | |
10209 | +----+ $ |
10210 | |root|-----------------+ |
10211 | +----+ $ | |
10212 | | $ | |
10213 | | $ | |
10214 | +----+ +---+ $ | +---+ Here the return value |
10215 | | |- ... -| |---$-+--+->|key| will be 4. |
10216 | +----+ +---+ $ | | +---+ |
10217 | | $ | | |
10218 | ... $ | | |
10219 | | $ | | |
10220 | +----+ +---+ $ | | |
10221 | | |---| |---------+ | |
10222 | +----+ +---+ $ | |
10223 | | | $ | |
10224 | ... +---+ $ | |
10225 | | |------------+ |
10226 | +---+ $ |
10227 | @return |
10228 | Number of links to "key" from nodes reachable from "root". |
10229 | */ |
10230 | |
10231 | static ulong count_key_part_usage(SEL_ARG *root, SEL_ARG *key) |
10232 | { |
10233 | ulong count= 0; |
10234 | for (root=root->first(); root ; root=root->next) |
10235 | { |
10236 | if (root->next_key_part) |
10237 | { |
10238 | if (root->next_key_part == key) |
10239 | count++; |
10240 | if (root->next_key_part->part < key->part) |
10241 | count+=count_key_part_usage(root->next_key_part,key); |
10242 | } |
10243 | } |
10244 | return count; |
10245 | } |
10246 | |
10247 | |
10248 | /* |
10249 | Check if SEL_ARG::use_count value is correct |
10250 | |
10251 | SYNOPSIS |
10252 | SEL_ARG::test_use_count() |
10253 | root The root node of the SEL_ARG graph (an RB-tree root node that |
10254 | has the least value of sel_arg->part in the entire graph, and |
10255 | thus is the "origin" of the graph) |
10256 | |
10257 | DESCRIPTION |
10258 | Check if SEL_ARG::use_count value is correct. See the definition of |
10259 | use_count for what is "correct". |
10260 | */ |
10261 | |
10262 | void SEL_ARG::test_use_count(SEL_ARG *root) |
10263 | { |
10264 | uint e_count=0; |
10265 | |
10266 | if (this->type != SEL_ARG::KEY_RANGE) |
10267 | return; |
10268 | for (SEL_ARG *pos=first(); pos ; pos=pos->next) |
10269 | { |
10270 | e_count++; |
10271 | if (pos->next_key_part) |
10272 | { |
10273 | ulong count=count_key_part_usage(root,pos->next_key_part); |
10274 | if (count > pos->next_key_part->use_count) |
10275 | { |
10276 | sql_print_information("Use_count: Wrong count for key at %p: %lu " |
10277 | "should be %lu" , pos, |
10278 | pos->next_key_part->use_count, count); |
10279 | return; |
10280 | } |
10281 | pos->next_key_part->test_use_count(root); |
10282 | } |
10283 | } |
10284 | if (e_count != elements) |
10285 | sql_print_warning("Wrong use count: %u (should be %u) for tree at %p" , |
10286 | e_count, elements, this); |
10287 | } |
10288 | #endif |
10289 | |
10290 | /* |
10291 | Calculate cost and E(#rows) for a given index and intervals tree |
10292 | |
10293 | SYNOPSIS |
10294 | check_quick_select() |
10295 | param Parameter from test_quick_select |
10296 | idx Number of index to use in PARAM::key SEL_TREE::key |
10297 | index_only TRUE - assume only index tuples will be accessed |
10298 | FALSE - assume full table rows will be read |
10299 | tree Transformed selection condition, tree->key[idx] holds |
10300 | the intervals for the given index. |
10301 | update_tbl_stats TRUE <=> update table->quick_* with information |
10302 | about range scan we've evaluated. |
10303 | mrr_flags INOUT MRR access flags |
10304 | cost OUT Scan cost |
10305 | |
10306 | NOTES |
10307 | param->is_ror_scan is set to reflect if the key scan is a ROR (see |
10308 | is_key_scan_ror function for more info) |
10309 | param->table->quick_*, param->range_count (and maybe others) are |
10310 | updated with data of given key scan, see quick_range_seq_next for details. |
10311 | |
10312 | RETURN |
10313 | Estimate # of records to be retrieved. |
10314 | HA_POS_ERROR if estimate calculation failed due to table handler problems. |
10315 | */ |
10316 | |
10317 | static |
10318 | ha_rows check_quick_select(PARAM *param, uint idx, bool index_only, |
10319 | SEL_ARG *tree, bool update_tbl_stats, |
10320 | uint *mrr_flags, uint *bufsize, Cost_estimate *cost) |
10321 | { |
10322 | SEL_ARG_RANGE_SEQ seq; |
10323 | RANGE_SEQ_IF seq_if = {NULL, sel_arg_range_seq_init, sel_arg_range_seq_next, 0, 0}; |
10324 | handler *file= param->table->file; |
10325 | ha_rows rows= HA_POS_ERROR; |
10326 | uint keynr= param->real_keynr[idx]; |
10327 | DBUG_ENTER("check_quick_select" ); |
10328 | |
10329 | /* Handle cases when we don't have a valid non-empty list of range */ |
10330 | if (!tree) |
10331 | DBUG_RETURN(HA_POS_ERROR); |
10332 | if (tree->type == SEL_ARG::IMPOSSIBLE) |
10333 | DBUG_RETURN(0L); |
10334 | if (tree->type != SEL_ARG::KEY_RANGE || tree->part != 0) |
10335 | DBUG_RETURN(HA_POS_ERROR); |
10336 | |
10337 | seq.keyno= idx; |
10338 | seq.real_keyno= keynr; |
10339 | seq.param= param; |
10340 | seq.start= tree; |
10341 | |
10342 | param->range_count=0; |
10343 | param->max_key_part=0; |
10344 | |
10345 | param->is_ror_scan= TRUE; |
10346 | if (file->index_flags(keynr, 0, TRUE) & HA_KEY_SCAN_NOT_ROR) |
10347 | param->is_ror_scan= FALSE; |
10348 | |
10349 | *mrr_flags= param->force_default_mrr? HA_MRR_USE_DEFAULT_IMPL: 0; |
10350 | /* |
10351 | Pass HA_MRR_SORTED to see if MRR implementation can handle sorting. |
10352 | */ |
10353 | *mrr_flags|= HA_MRR_NO_ASSOCIATION | HA_MRR_SORTED; |
10354 | |
10355 | bool pk_is_clustered= file->primary_key_is_clustered(); |
10356 | if (index_only && |
10357 | (file->index_flags(keynr, param->max_key_part, 1) & HA_KEYREAD_ONLY) && |
10358 | !(file->index_flags(keynr, param->max_key_part, 1) & HA_CLUSTERED_INDEX)) |
10359 | *mrr_flags |= HA_MRR_INDEX_ONLY; |
10360 | |
10361 | if (param->thd->lex->sql_command != SQLCOM_SELECT) |
10362 | *mrr_flags |= HA_MRR_USE_DEFAULT_IMPL; |
10363 | |
10364 | *bufsize= param->thd->variables.mrr_buff_size; |
10365 | /* |
10366 | Skip materialized derived table/view result table from MRR check as |
10367 | they aren't contain any data yet. |
10368 | */ |
10369 | if (param->table->pos_in_table_list->is_non_derived()) |
10370 | rows= file->multi_range_read_info_const(keynr, &seq_if, (void*)&seq, 0, |
10371 | bufsize, mrr_flags, cost); |
10372 | if (rows != HA_POS_ERROR) |
10373 | { |
10374 | param->quick_rows[keynr]= rows; |
10375 | param->possible_keys.set_bit(keynr); |
10376 | if (update_tbl_stats) |
10377 | { |
10378 | param->table->quick_keys.set_bit(keynr); |
10379 | param->table->quick_key_parts[keynr]= param->max_key_part+1; |
10380 | param->table->quick_n_ranges[keynr]= param->range_count; |
10381 | param->table->quick_condition_rows= |
10382 | MY_MIN(param->table->quick_condition_rows, rows); |
10383 | param->table->quick_rows[keynr]= rows; |
10384 | param->table->quick_costs[keynr]= cost->total_cost(); |
10385 | } |
10386 | } |
10387 | /* Figure out if the key scan is ROR (returns rows in ROWID order) or not */ |
10388 | enum ha_key_alg key_alg= param->table->key_info[seq.real_keyno].algorithm; |
10389 | if ((key_alg != HA_KEY_ALG_BTREE) && (key_alg!= HA_KEY_ALG_UNDEF)) |
10390 | { |
10391 | /* |
10392 | All scans are non-ROR scans for those index types. |
10393 | TODO: Don't have this logic here, make table engines return |
10394 | appropriate flags instead. |
10395 | */ |
10396 | param->is_ror_scan= FALSE; |
10397 | } |
10398 | else if (param->table->s->primary_key == keynr && pk_is_clustered) |
10399 | { |
10400 | /* Clustered PK scan is always a ROR scan (TODO: same as above) */ |
10401 | param->is_ror_scan= TRUE; |
10402 | } |
10403 | else if (param->range_count > 1) |
10404 | { |
10405 | /* |
10406 | Scaning multiple key values in the index: the records are ROR |
10407 | for each value, but not between values. E.g, "SELECT ... x IN |
10408 | (1,3)" returns ROR order for all records with x=1, then ROR |
10409 | order for records with x=3 |
10410 | */ |
10411 | param->is_ror_scan= FALSE; |
10412 | } |
10413 | |
10414 | DBUG_PRINT("exit" , ("Records: %lu" , (ulong) rows)); |
10415 | DBUG_RETURN(rows); //psergey-merge:todo: maintain first_null_comp. |
10416 | } |
10417 | |
10418 | |
10419 | /* |
10420 | Check if key scan on given index with equality conditions on first n key |
10421 | parts is a ROR scan. |
10422 | |
10423 | SYNOPSIS |
10424 | is_key_scan_ror() |
10425 | param Parameter from test_quick_select |
10426 | keynr Number of key in the table. The key must not be a clustered |
10427 | primary key. |
10428 | nparts Number of first key parts for which equality conditions |
10429 | are present. |
10430 | |
10431 | NOTES |
10432 | ROR (Rowid Ordered Retrieval) key scan is a key scan that produces |
10433 | ordered sequence of rowids (ha_xxx::cmp_ref is the comparison function) |
10434 | |
10435 | This function is needed to handle a practically-important special case: |
10436 | an index scan is a ROR scan if it is done using a condition in form |
10437 | |
10438 | "key1_1=c_1 AND ... AND key1_n=c_n" |
10439 | |
10440 | where the index is defined on (key1_1, ..., key1_N [,a_1, ..., a_n]) |
10441 | |
10442 | and the table has a clustered Primary Key defined as |
10443 | PRIMARY KEY(a_1, ..., a_n, b1, ..., b_k) |
10444 | |
10445 | i.e. the first key parts of it are identical to uncovered parts ot the |
10446 | key being scanned. This function assumes that the index flags do not |
10447 | include HA_KEY_SCAN_NOT_ROR flag (that is checked elsewhere). |
10448 | |
10449 | Check (1) is made in quick_range_seq_next() |
10450 | |
10451 | RETURN |
10452 | TRUE The scan is ROR-scan |
10453 | FALSE Otherwise |
10454 | */ |
10455 | |
10456 | static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts) |
10457 | { |
10458 | KEY *table_key= param->table->key_info + keynr; |
10459 | KEY_PART_INFO *key_part= table_key->key_part + nparts; |
10460 | KEY_PART_INFO *key_part_end= (table_key->key_part + |
10461 | table_key->user_defined_key_parts); |
10462 | uint pk_number; |
10463 | |
10464 | for (KEY_PART_INFO *kp= table_key->key_part; kp < key_part; kp++) |
10465 | { |
10466 | uint16 fieldnr= param->table->key_info[keynr]. |
10467 | key_part[kp - table_key->key_part].fieldnr - 1; |
10468 | if (param->table->field[fieldnr]->key_length() != kp->length) |
10469 | return FALSE; |
10470 | } |
10471 | |
10472 | /* |
10473 | If there are equalities for all key parts, it is a ROR scan. If there are |
10474 | equalities all keyparts and even some of key parts from "Extended Key" |
10475 | index suffix, it is a ROR-scan, too. |
10476 | */ |
10477 | if (key_part >= key_part_end) |
10478 | return TRUE; |
10479 | |
10480 | key_part= table_key->key_part + nparts; |
10481 | pk_number= param->table->s->primary_key; |
10482 | if (!param->table->file->primary_key_is_clustered() || pk_number == MAX_KEY) |
10483 | return FALSE; |
10484 | |
10485 | KEY_PART_INFO *pk_part= param->table->key_info[pk_number].key_part; |
10486 | KEY_PART_INFO *pk_part_end= pk_part + |
10487 | param->table->key_info[pk_number].user_defined_key_parts; |
10488 | for (;(key_part!=key_part_end) && (pk_part != pk_part_end); |
10489 | ++key_part, ++pk_part) |
10490 | { |
10491 | if ((key_part->field != pk_part->field) || |
10492 | (key_part->length != pk_part->length)) |
10493 | return FALSE; |
10494 | } |
10495 | return (key_part == key_part_end); |
10496 | } |
10497 | |
10498 | |
10499 | /* |
10500 | Create a QUICK_RANGE_SELECT from given key and SEL_ARG tree for that key. |
10501 | |
10502 | SYNOPSIS |
10503 | get_quick_select() |
10504 | param |
10505 | idx Index of used key in param->key. |
10506 | key_tree SEL_ARG tree for the used key |
10507 | mrr_flags MRR parameter for quick select |
10508 | mrr_buf_size MRR parameter for quick select |
10509 | parent_alloc If not NULL, use it to allocate memory for |
10510 | quick select data. Otherwise use quick->alloc. |
10511 | NOTES |
10512 | The caller must call QUICK_SELECT::init for returned quick select. |
10513 | |
10514 | CAUTION! This function may change thd->mem_root to a MEM_ROOT which will be |
10515 | deallocated when the returned quick select is deleted. |
10516 | |
10517 | RETURN |
10518 | NULL on error |
10519 | otherwise created quick select |
10520 | */ |
10521 | |
10522 | QUICK_RANGE_SELECT * |
10523 | get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree, uint mrr_flags, |
10524 | uint mrr_buf_size, MEM_ROOT *parent_alloc) |
10525 | { |
10526 | QUICK_RANGE_SELECT *quick; |
10527 | bool create_err= FALSE; |
10528 | DBUG_ENTER("get_quick_select" ); |
10529 | |
10530 | if (param->table->key_info[param->real_keynr[idx]].flags & HA_SPATIAL) |
10531 | quick=new QUICK_RANGE_SELECT_GEOM(param->thd, param->table, |
10532 | param->real_keynr[idx], |
10533 | MY_TEST(parent_alloc), |
10534 | parent_alloc, &create_err); |
10535 | else |
10536 | quick=new QUICK_RANGE_SELECT(param->thd, param->table, |
10537 | param->real_keynr[idx], |
10538 | MY_TEST(parent_alloc), NULL, &create_err); |
10539 | |
10540 | if (quick) |
10541 | { |
10542 | if (create_err || |
10543 | get_quick_keys(param,quick,param->key[idx],key_tree,param->min_key,0, |
10544 | param->max_key,0)) |
10545 | { |
10546 | delete quick; |
10547 | quick=0; |
10548 | } |
10549 | else |
10550 | { |
10551 | KEY *keyinfo= param->table->key_info+param->real_keynr[idx]; |
10552 | quick->mrr_flags= mrr_flags; |
10553 | quick->mrr_buf_size= mrr_buf_size; |
10554 | quick->key_parts=(KEY_PART*) |
10555 | memdup_root(parent_alloc? parent_alloc : &quick->alloc, |
10556 | (char*) param->key[idx], |
10557 | sizeof(KEY_PART)* |
10558 | param->table->actual_n_key_parts(keyinfo)); |
10559 | } |
10560 | } |
10561 | DBUG_RETURN(quick); |
10562 | } |
10563 | |
10564 | |
10565 | /* |
10566 | ** Fix this to get all possible sub_ranges |
10567 | */ |
10568 | bool |
10569 | get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, |
10570 | SEL_ARG *key_tree, uchar *min_key,uint min_key_flag, |
10571 | uchar *max_key, uint max_key_flag) |
10572 | { |
10573 | QUICK_RANGE *range; |
10574 | uint flag; |
10575 | int min_part= key_tree->part-1, // # of keypart values in min_key buffer |
10576 | max_part= key_tree->part-1; // # of keypart values in max_key buffer |
10577 | |
10578 | if (key_tree->left != &null_element) |
10579 | { |
10580 | if (get_quick_keys(param,quick,key,key_tree->left, |
10581 | min_key,min_key_flag, max_key, max_key_flag)) |
10582 | return 1; |
10583 | } |
10584 | uchar *tmp_min_key=min_key,*tmp_max_key=max_key; |
10585 | min_part+= key_tree->store_min(key[key_tree->part].store_length, |
10586 | &tmp_min_key,min_key_flag); |
10587 | max_part+= key_tree->store_max(key[key_tree->part].store_length, |
10588 | &tmp_max_key,max_key_flag); |
10589 | |
10590 | if (key_tree->next_key_part && |
10591 | key_tree->next_key_part->type == SEL_ARG::KEY_RANGE && |
10592 | key_tree->next_key_part->part == key_tree->part+1) |
10593 | { // const key as prefix |
10594 | if ((tmp_min_key - min_key) == (tmp_max_key - max_key) && |
10595 | memcmp(min_key, max_key, (uint)(tmp_max_key - max_key))==0 && |
10596 | key_tree->min_flag==0 && key_tree->max_flag==0) |
10597 | { |
10598 | if (get_quick_keys(param,quick,key,key_tree->next_key_part, |
10599 | tmp_min_key, min_key_flag | key_tree->min_flag, |
10600 | tmp_max_key, max_key_flag | key_tree->max_flag)) |
10601 | return 1; |
10602 | goto end; // Ugly, but efficient |
10603 | } |
10604 | { |
10605 | uint tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag; |
10606 | if (!tmp_min_flag) |
10607 | min_part+= key_tree->next_key_part->store_min_key(key, |
10608 | &tmp_min_key, |
10609 | &tmp_min_flag, |
10610 | MAX_KEY); |
10611 | if (!tmp_max_flag) |
10612 | max_part+= key_tree->next_key_part->store_max_key(key, |
10613 | &tmp_max_key, |
10614 | &tmp_max_flag, |
10615 | MAX_KEY); |
10616 | flag=tmp_min_flag | tmp_max_flag; |
10617 | } |
10618 | } |
10619 | else |
10620 | { |
10621 | flag = (key_tree->min_flag & GEOM_FLAG) ? |
10622 | key_tree->min_flag : key_tree->min_flag | key_tree->max_flag; |
10623 | } |
10624 | |
10625 | /* |
10626 | Ensure that some part of min_key and max_key are used. If not, |
10627 | regard this as no lower/upper range |
10628 | */ |
10629 | if ((flag & GEOM_FLAG) == 0) |
10630 | { |
10631 | if (tmp_min_key != param->min_key) |
10632 | flag&= ~NO_MIN_RANGE; |
10633 | else |
10634 | flag|= NO_MIN_RANGE; |
10635 | if (tmp_max_key != param->max_key) |
10636 | flag&= ~NO_MAX_RANGE; |
10637 | else |
10638 | flag|= NO_MAX_RANGE; |
10639 | } |
10640 | if (flag == 0) |
10641 | { |
10642 | uint length= (uint) (tmp_min_key - param->min_key); |
10643 | if (length == (uint) (tmp_max_key - param->max_key) && |
10644 | !memcmp(param->min_key,param->max_key,length)) |
10645 | { |
10646 | KEY *table_key=quick->head->key_info+quick->index; |
10647 | flag=EQ_RANGE; |
10648 | if ((table_key->flags & HA_NOSAME) && |
10649 | min_part == key_tree->part && |
10650 | key_tree->part == table_key->user_defined_key_parts-1) |
10651 | { |
10652 | DBUG_ASSERT(min_part == max_part); |
10653 | if ((table_key->flags & HA_NULL_PART_KEY) && |
10654 | null_part_in_key(key, |
10655 | param->min_key, |
10656 | (uint) (tmp_min_key - param->min_key))) |
10657 | flag|= NULL_RANGE; |
10658 | else |
10659 | flag|= UNIQUE_RANGE; |
10660 | } |
10661 | } |
10662 | } |
10663 | |
10664 | /* Get range for retrieving rows in QUICK_SELECT::get_next */ |
10665 | if (!(range= new (param->thd->mem_root) QUICK_RANGE( |
10666 | param->thd, |
10667 | param->min_key, |
10668 | (uint) (tmp_min_key - param->min_key), |
10669 | min_part >=0 ? make_keypart_map(min_part) : 0, |
10670 | param->max_key, |
10671 | (uint) (tmp_max_key - param->max_key), |
10672 | max_part >=0 ? make_keypart_map(max_part) : 0, |
10673 | flag))) |
10674 | return 1; // out of memory |
10675 | |
10676 | set_if_bigger(quick->max_used_key_length, range->min_length); |
10677 | set_if_bigger(quick->max_used_key_length, range->max_length); |
10678 | set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1); |
10679 | if (insert_dynamic(&quick->ranges, (uchar*) &range)) |
10680 | return 1; |
10681 | |
10682 | end: |
10683 | if (key_tree->right != &null_element) |
10684 | return get_quick_keys(param,quick,key,key_tree->right, |
10685 | min_key,min_key_flag, |
10686 | max_key,max_key_flag); |
10687 | return 0; |
10688 | } |
10689 | |
10690 | /* |
10691 | Return 1 if there is only one range and this uses the whole unique key |
10692 | */ |
10693 | |
10694 | bool QUICK_RANGE_SELECT::unique_key_range() |
10695 | { |
10696 | if (ranges.elements == 1) |
10697 | { |
10698 | QUICK_RANGE *tmp= *((QUICK_RANGE**)ranges.buffer); |
10699 | if ((tmp->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE) |
10700 | { |
10701 | KEY *key=head->key_info+index; |
10702 | return (key->flags & HA_NOSAME) && key->key_length == tmp->min_length; |
10703 | } |
10704 | } |
10705 | return 0; |
10706 | } |
10707 | |
10708 | |
10709 | |
10710 | /* |
10711 | Return TRUE if any part of the key is NULL |
10712 | |
10713 | SYNOPSIS |
10714 | null_part_in_key() |
10715 | key_part Array of key parts (index description) |
10716 | key Key values tuple |
10717 | length Length of key values tuple in bytes. |
10718 | |
10719 | RETURN |
10720 | TRUE The tuple has at least one "keypartX is NULL" |
10721 | FALSE Otherwise |
10722 | */ |
10723 | |
10724 | static bool null_part_in_key(KEY_PART *key_part, const uchar *key, uint length) |
10725 | { |
10726 | for (const uchar *end=key+length ; |
10727 | key < end; |
10728 | key+= key_part++->store_length) |
10729 | { |
10730 | if (key_part->null_bit && *key) |
10731 | return 1; |
10732 | } |
10733 | return 0; |
10734 | } |
10735 | |
10736 | |
10737 | bool QUICK_SELECT_I::is_keys_used(const MY_BITMAP *fields) |
10738 | { |
10739 | return is_key_used(head, index, fields); |
10740 | } |
10741 | |
10742 | bool QUICK_INDEX_SORT_SELECT::is_keys_used(const MY_BITMAP *fields) |
10743 | { |
10744 | QUICK_RANGE_SELECT *quick; |
10745 | List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); |
10746 | while ((quick= it++)) |
10747 | { |
10748 | if (is_key_used(head, quick->index, fields)) |
10749 | return 1; |
10750 | } |
10751 | return 0; |
10752 | } |
10753 | |
10754 | bool QUICK_ROR_INTERSECT_SELECT::is_keys_used(const MY_BITMAP *fields) |
10755 | { |
10756 | QUICK_SELECT_WITH_RECORD *qr; |
10757 | List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects); |
10758 | while ((qr= it++)) |
10759 | { |
10760 | if (is_key_used(head, qr->quick->index, fields)) |
10761 | return 1; |
10762 | } |
10763 | return 0; |
10764 | } |
10765 | |
10766 | bool QUICK_ROR_UNION_SELECT::is_keys_used(const MY_BITMAP *fields) |
10767 | { |
10768 | QUICK_SELECT_I *quick; |
10769 | List_iterator_fast<QUICK_SELECT_I> it(quick_selects); |
10770 | while ((quick= it++)) |
10771 | { |
10772 | if (quick->is_keys_used(fields)) |
10773 | return 1; |
10774 | } |
10775 | return 0; |
10776 | } |
10777 | |
10778 | |
10779 | FT_SELECT *get_ft_select(THD *thd, TABLE *table, uint key) |
10780 | { |
10781 | bool create_err= FALSE; |
10782 | FT_SELECT *fts= new FT_SELECT(thd, table, key, &create_err); |
10783 | if (create_err) |
10784 | { |
10785 | delete fts; |
10786 | return NULL; |
10787 | } |
10788 | else |
10789 | return fts; |
10790 | } |
10791 | |
10792 | /* |
10793 | Create quick select from ref/ref_or_null scan. |
10794 | |
10795 | SYNOPSIS |
10796 | get_quick_select_for_ref() |
10797 | thd Thread handle |
10798 | table Table to access |
10799 | ref ref[_or_null] scan parameters |
10800 | records Estimate of number of records (needed only to construct |
10801 | quick select) |
10802 | NOTES |
10803 | This allocates things in a new memory root, as this may be called many |
10804 | times during a query. |
10805 | |
10806 | RETURN |
10807 | Quick select that retrieves the same rows as passed ref scan |
10808 | NULL on error. |
10809 | */ |
10810 | |
10811 | QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, |
10812 | TABLE_REF *ref, ha_rows records) |
10813 | { |
10814 | MEM_ROOT *old_root, *alloc; |
10815 | QUICK_RANGE_SELECT *quick; |
10816 | KEY *key_info = &table->key_info[ref->key]; |
10817 | KEY_PART *key_part; |
10818 | QUICK_RANGE *range; |
10819 | uint part; |
10820 | bool create_err= FALSE; |
10821 | Cost_estimate cost; |
10822 | uint max_used_key_len; |
10823 | |
10824 | old_root= thd->mem_root; |
10825 | /* The following call may change thd->mem_root */ |
10826 | quick= new QUICK_RANGE_SELECT(thd, table, ref->key, 0, 0, &create_err); |
10827 | /* save mem_root set by QUICK_RANGE_SELECT constructor */ |
10828 | alloc= thd->mem_root; |
10829 | /* |
10830 | return back default mem_root (thd->mem_root) changed by |
10831 | QUICK_RANGE_SELECT constructor |
10832 | */ |
10833 | thd->mem_root= old_root; |
10834 | |
10835 | if (!quick || create_err || quick->init()) |
10836 | goto err; |
10837 | quick->records= records; |
10838 | |
10839 | if ((cp_buffer_from_ref(thd, table, ref) && |
10840 | unlikely(thd->is_fatal_error)) || |
10841 | unlikely(!(range= new(alloc) QUICK_RANGE()))) |
10842 | goto err; // out of memory |
10843 | |
10844 | range->min_key= range->max_key= ref->key_buff; |
10845 | range->min_length= range->max_length= ref->key_length; |
10846 | range->min_keypart_map= range->max_keypart_map= |
10847 | make_prev_keypart_map(ref->key_parts); |
10848 | range->flag= EQ_RANGE; |
10849 | |
10850 | if (unlikely(!(quick->key_parts=key_part=(KEY_PART *) |
10851 | alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts)))) |
10852 | goto err; |
10853 | |
10854 | max_used_key_len=0; |
10855 | for (part=0 ; part < ref->key_parts ;part++,key_part++) |
10856 | { |
10857 | key_part->part=part; |
10858 | key_part->field= key_info->key_part[part].field; |
10859 | key_part->length= key_info->key_part[part].length; |
10860 | key_part->store_length= key_info->key_part[part].store_length; |
10861 | key_part->null_bit= key_info->key_part[part].null_bit; |
10862 | key_part->flag= (uint8) key_info->key_part[part].key_part_flag; |
10863 | |
10864 | max_used_key_len +=key_info->key_part[part].store_length; |
10865 | } |
10866 | |
10867 | quick->max_used_key_length= max_used_key_len; |
10868 | |
10869 | if (insert_dynamic(&quick->ranges,(uchar*)&range)) |
10870 | goto err; |
10871 | |
10872 | /* |
10873 | Add a NULL range if REF_OR_NULL optimization is used. |
10874 | For example: |
10875 | if we have "WHERE A=2 OR A IS NULL" we created the (A=2) range above |
10876 | and have ref->null_ref_key set. Will create a new NULL range here. |
10877 | */ |
10878 | if (ref->null_ref_key) |
10879 | { |
10880 | QUICK_RANGE *null_range; |
10881 | |
10882 | *ref->null_ref_key= 1; // Set null byte then create a range |
10883 | if (!(null_range= new (alloc) |
10884 | QUICK_RANGE(thd, ref->key_buff, ref->key_length, |
10885 | make_prev_keypart_map(ref->key_parts), |
10886 | ref->key_buff, ref->key_length, |
10887 | make_prev_keypart_map(ref->key_parts), EQ_RANGE))) |
10888 | goto err; |
10889 | *ref->null_ref_key= 0; // Clear null byte |
10890 | if (insert_dynamic(&quick->ranges,(uchar*)&null_range)) |
10891 | goto err; |
10892 | } |
10893 | |
10894 | /* Call multi_range_read_info() to get the MRR flags and buffer size */ |
10895 | quick->mrr_flags= HA_MRR_NO_ASSOCIATION | |
10896 | (table->file->keyread_enabled() ? HA_MRR_INDEX_ONLY : 0); |
10897 | if (thd->lex->sql_command != SQLCOM_SELECT) |
10898 | quick->mrr_flags |= HA_MRR_USE_DEFAULT_IMPL; |
10899 | |
10900 | quick->mrr_buf_size= thd->variables.mrr_buff_size; |
10901 | if (table->file->multi_range_read_info(quick->index, 1, (uint)records, |
10902 | ~0, |
10903 | &quick->mrr_buf_size, |
10904 | &quick->mrr_flags, &cost)) |
10905 | goto err; |
10906 | |
10907 | return quick; |
10908 | err: |
10909 | delete quick; |
10910 | return 0; |
10911 | } |
10912 | |
10913 | |
10914 | /* |
10915 | Perform key scans for all used indexes (except CPK), get rowids and merge |
10916 | them into an ordered non-recurrent sequence of rowids. |
10917 | |
10918 | The merge/duplicate removal is performed using Unique class. We put all |
10919 | rowids into Unique, get the sorted sequence and destroy the Unique. |
10920 | |
10921 | If table has a clustered primary key that covers all rows (TRUE for bdb |
10922 | and innodb currently) and one of the index_merge scans is a scan on PK, |
10923 | then rows that will be retrieved by PK scan are not put into Unique and |
10924 | primary key scan is not performed here, it is performed later separately. |
10925 | |
10926 | RETURN |
10927 | 0 OK |
10928 | other error |
10929 | */ |
10930 | |
10931 | int read_keys_and_merge_scans(THD *thd, |
10932 | TABLE *head, |
10933 | List<QUICK_RANGE_SELECT> quick_selects, |
10934 | QUICK_RANGE_SELECT *pk_quick_select, |
10935 | READ_RECORD *read_record, |
10936 | bool intersection, |
10937 | key_map *filtered_scans, |
10938 | Unique **unique_ptr) |
10939 | { |
10940 | List_iterator_fast<QUICK_RANGE_SELECT> cur_quick_it(quick_selects); |
10941 | QUICK_RANGE_SELECT* cur_quick; |
10942 | int result; |
10943 | Unique *unique= *unique_ptr; |
10944 | handler *file= head->file; |
10945 | bool with_cpk_filter= pk_quick_select != NULL; |
10946 | DBUG_ENTER("read_keys_and_merge" ); |
10947 | |
10948 | /* We're going to just read rowids. */ |
10949 | head->prepare_for_position(); |
10950 | |
10951 | cur_quick_it.rewind(); |
10952 | cur_quick= cur_quick_it++; |
10953 | bool first_quick= TRUE; |
10954 | DBUG_ASSERT(cur_quick != 0); |
10955 | head->file->ha_start_keyread(cur_quick->index); |
10956 | |
10957 | /* |
10958 | We reuse the same instance of handler so we need to call both init and |
10959 | reset here. |
10960 | */ |
10961 | if (cur_quick->init() || cur_quick->reset()) |
10962 | goto err; |
10963 | |
10964 | if (unique == NULL) |
10965 | { |
10966 | DBUG_EXECUTE_IF("index_merge_may_not_create_a_Unique" , DBUG_SUICIDE(); ); |
10967 | DBUG_EXECUTE_IF("only_one_Unique_may_be_created" , |
10968 | DBUG_SET("+d,index_merge_may_not_create_a_Unique" ); ); |
10969 | |
10970 | unique= new Unique(refpos_order_cmp, (void *)file, |
10971 | file->ref_length, |
10972 | (size_t)thd->variables.sortbuff_size, |
10973 | intersection ? quick_selects.elements : 0); |
10974 | if (!unique) |
10975 | goto err; |
10976 | *unique_ptr= unique; |
10977 | } |
10978 | else |
10979 | { |
10980 | unique->reset(); |
10981 | } |
10982 | |
10983 | DBUG_ASSERT(file->ref_length == unique->get_size()); |
10984 | DBUG_ASSERT(thd->variables.sortbuff_size == unique->get_max_in_memory_size()); |
10985 | |
10986 | for (;;) |
10987 | { |
10988 | while ((result= cur_quick->get_next()) == HA_ERR_END_OF_FILE) |
10989 | { |
10990 | if (intersection) |
10991 | with_cpk_filter= filtered_scans->is_set(cur_quick->index); |
10992 | if (first_quick) |
10993 | { |
10994 | first_quick= FALSE; |
10995 | if (intersection && unique->is_in_memory()) |
10996 | unique->close_for_expansion(); |
10997 | } |
10998 | cur_quick->range_end(); |
10999 | cur_quick= cur_quick_it++; |
11000 | if (!cur_quick) |
11001 | break; |
11002 | |
11003 | if (cur_quick->file->inited != handler::NONE) |
11004 | cur_quick->file->ha_index_end(); |
11005 | if (cur_quick->init() || cur_quick->reset()) |
11006 | goto err; |
11007 | } |
11008 | |
11009 | if (result) |
11010 | { |
11011 | if (result != HA_ERR_END_OF_FILE) |
11012 | { |
11013 | cur_quick->range_end(); |
11014 | goto err; |
11015 | } |
11016 | break; |
11017 | } |
11018 | |
11019 | if (thd->killed) |
11020 | goto err; |
11021 | |
11022 | if (with_cpk_filter && |
11023 | pk_quick_select->row_in_ranges() != intersection ) |
11024 | continue; |
11025 | |
11026 | cur_quick->file->position(cur_quick->record); |
11027 | if (unique->unique_add((char*)cur_quick->file->ref)) |
11028 | goto err; |
11029 | } |
11030 | |
11031 | /* |
11032 | Ok all rowids are in the Unique now. The next call will initialize |
11033 | the unique structure so it can be used to iterate through the rowids |
11034 | sequence. |
11035 | */ |
11036 | result= unique->get(head); |
11037 | /* |
11038 | index merge currently doesn't support "using index" at all |
11039 | */ |
11040 | head->file->ha_end_keyread(); |
11041 | if (init_read_record(read_record, thd, head, (SQL_SELECT*) 0, |
11042 | &unique->sort, 1 , 1, TRUE)) |
11043 | result= 1; |
11044 | DBUG_RETURN(result); |
11045 | |
11046 | err: |
11047 | head->file->ha_end_keyread(); |
11048 | DBUG_RETURN(1); |
11049 | } |
11050 | |
11051 | |
11052 | int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() |
11053 | |
11054 | { |
11055 | int result; |
11056 | DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::read_keys_and_merge" ); |
11057 | result= read_keys_and_merge_scans(thd, head, quick_selects, pk_quick_select, |
11058 | &read_record, FALSE, NULL, &unique); |
11059 | doing_pk_scan= FALSE; |
11060 | DBUG_RETURN(result); |
11061 | } |
11062 | |
11063 | /* |
11064 | Get next row for index_merge. |
11065 | NOTES |
11066 | The rows are read from |
11067 | 1. rowids stored in Unique. |
11068 | 2. QUICK_RANGE_SELECT with clustered primary key (if any). |
11069 | The sets of rows retrieved in 1) and 2) are guaranteed to be disjoint. |
11070 | */ |
11071 | |
11072 | int QUICK_INDEX_MERGE_SELECT::get_next() |
11073 | { |
11074 | int result; |
11075 | DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::get_next" ); |
11076 | |
11077 | if (doing_pk_scan) |
11078 | DBUG_RETURN(pk_quick_select->get_next()); |
11079 | |
11080 | if ((result= read_record.read_record()) == -1) |
11081 | { |
11082 | result= HA_ERR_END_OF_FILE; |
11083 | end_read_record(&read_record); |
11084 | // Free things used by sort early. Shouldn't be strictly necessary |
11085 | unique->sort.reset(); |
11086 | /* All rows from Unique have been retrieved, do a clustered PK scan */ |
11087 | if (pk_quick_select) |
11088 | { |
11089 | doing_pk_scan= TRUE; |
11090 | if ((result= pk_quick_select->init()) || |
11091 | (result= pk_quick_select->reset())) |
11092 | DBUG_RETURN(result); |
11093 | DBUG_RETURN(pk_quick_select->get_next()); |
11094 | } |
11095 | } |
11096 | |
11097 | DBUG_RETURN(result); |
11098 | } |
11099 | |
11100 | int QUICK_INDEX_INTERSECT_SELECT::read_keys_and_merge() |
11101 | |
11102 | { |
11103 | int result; |
11104 | DBUG_ENTER("QUICK_INDEX_INTERSECT_SELECT::read_keys_and_merge" ); |
11105 | result= read_keys_and_merge_scans(thd, head, quick_selects, pk_quick_select, |
11106 | &read_record, TRUE, &filtered_scans, |
11107 | &unique); |
11108 | DBUG_RETURN(result); |
11109 | } |
11110 | |
11111 | int QUICK_INDEX_INTERSECT_SELECT::get_next() |
11112 | { |
11113 | int result; |
11114 | DBUG_ENTER("QUICK_INDEX_INTERSECT_SELECT::get_next" ); |
11115 | |
11116 | if ((result= read_record.read_record()) == -1) |
11117 | { |
11118 | result= HA_ERR_END_OF_FILE; |
11119 | end_read_record(&read_record); |
11120 | unique->sort.reset(); // Free things early |
11121 | } |
11122 | |
11123 | DBUG_RETURN(result); |
11124 | } |
11125 | |
11126 | |
11127 | /* |
11128 | Retrieve next record. |
11129 | SYNOPSIS |
11130 | QUICK_ROR_INTERSECT_SELECT::get_next() |
11131 | |
11132 | NOTES |
11133 | Invariant on enter/exit: all intersected selects have retrieved all index |
11134 | records with rowid <= some_rowid_val and no intersected select has |
11135 | retrieved any index records with rowid > some_rowid_val. |
11136 | We start fresh and loop until we have retrieved the same rowid in each of |
11137 | the key scans or we got an error. |
11138 | |
11139 | If a Clustered PK scan is present, it is used only to check if row |
11140 | satisfies its condition (and never used for row retrieval). |
11141 | |
11142 | Locking: to ensure that exclusive locks are only set on records that |
11143 | are included in the final result we must release the lock |
11144 | on all rows we read but do not include in the final result. This |
11145 | must be done on each index that reads the record and the lock |
11146 | must be released using the same handler (the same quick object) as |
11147 | used when reading the record. |
11148 | |
11149 | RETURN |
11150 | 0 - Ok |
11151 | other - Error code if any error occurred. |
11152 | */ |
11153 | |
11154 | int QUICK_ROR_INTERSECT_SELECT::get_next() |
11155 | { |
11156 | List_iterator_fast<QUICK_SELECT_WITH_RECORD> quick_it(quick_selects); |
11157 | QUICK_SELECT_WITH_RECORD *qr; |
11158 | QUICK_RANGE_SELECT* quick; |
11159 | |
11160 | /* quick that reads the given rowid first. This is needed in order |
11161 | to be able to unlock the row using the same handler object that locked |
11162 | it */ |
11163 | QUICK_RANGE_SELECT* quick_with_last_rowid; |
11164 | |
11165 | int error, cmp; |
11166 | uint last_rowid_count=0; |
11167 | DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::get_next" ); |
11168 | |
11169 | /* Get a rowid for first quick and save it as a 'candidate' */ |
11170 | qr= quick_it++; |
11171 | quick= qr->quick; |
11172 | error= quick->get_next(); |
11173 | if (cpk_quick) |
11174 | { |
11175 | while (!error && !cpk_quick->row_in_ranges()) |
11176 | { |
11177 | quick->file->unlock_row(); /* row not in range; unlock */ |
11178 | error= quick->get_next(); |
11179 | } |
11180 | } |
11181 | if (unlikely(error)) |
11182 | DBUG_RETURN(error); |
11183 | |
11184 | /* Save the read key tuple */ |
11185 | key_copy(qr->key_tuple, record, head->key_info + quick->index, |
11186 | quick->max_used_key_length); |
11187 | |
11188 | quick->file->position(quick->record); |
11189 | memcpy(last_rowid, quick->file->ref, head->file->ref_length); |
11190 | last_rowid_count= 1; |
11191 | quick_with_last_rowid= quick; |
11192 | |
11193 | while (last_rowid_count < quick_selects.elements) |
11194 | { |
11195 | if (!(qr= quick_it++)) |
11196 | { |
11197 | quick_it.rewind(); |
11198 | qr= quick_it++; |
11199 | } |
11200 | quick= qr->quick; |
11201 | |
11202 | do |
11203 | { |
11204 | DBUG_EXECUTE_IF("innodb_quick_report_deadlock" , |
11205 | DBUG_SET("+d,innodb_report_deadlock" );); |
11206 | if (unlikely((error= quick->get_next()))) |
11207 | { |
11208 | /* On certain errors like deadlock, trx might be rolled back.*/ |
11209 | if (!thd->transaction_rollback_request) |
11210 | quick_with_last_rowid->file->unlock_row(); |
11211 | DBUG_RETURN(error); |
11212 | } |
11213 | quick->file->position(quick->record); |
11214 | cmp= head->file->cmp_ref(quick->file->ref, last_rowid); |
11215 | if (cmp < 0) |
11216 | { |
11217 | /* This row is being skipped. Release lock on it. */ |
11218 | quick->file->unlock_row(); |
11219 | } |
11220 | } while (cmp < 0); |
11221 | |
11222 | key_copy(qr->key_tuple, record, head->key_info + quick->index, |
11223 | quick->max_used_key_length); |
11224 | |
11225 | /* Ok, current select 'caught up' and returned ref >= cur_ref */ |
11226 | if (cmp > 0) |
11227 | { |
11228 | /* Found a row with ref > cur_ref. Make it a new 'candidate' */ |
11229 | if (cpk_quick) |
11230 | { |
11231 | while (!cpk_quick->row_in_ranges()) |
11232 | { |
11233 | quick->file->unlock_row(); /* row not in range; unlock */ |
11234 | if (unlikely((error= quick->get_next()))) |
11235 | { |
11236 | /* On certain errors like deadlock, trx might be rolled back.*/ |
11237 | if (!thd->transaction_rollback_request) |
11238 | quick_with_last_rowid->file->unlock_row(); |
11239 | DBUG_RETURN(error); |
11240 | } |
11241 | } |
11242 | quick->file->position(quick->record); |
11243 | } |
11244 | memcpy(last_rowid, quick->file->ref, head->file->ref_length); |
11245 | quick_with_last_rowid->file->unlock_row(); |
11246 | last_rowid_count= 1; |
11247 | quick_with_last_rowid= quick; |
11248 | |
11249 | //save the fields here |
11250 | key_copy(qr->key_tuple, record, head->key_info + quick->index, |
11251 | quick->max_used_key_length); |
11252 | } |
11253 | else |
11254 | { |
11255 | /* current 'candidate' row confirmed by this select */ |
11256 | last_rowid_count++; |
11257 | } |
11258 | } |
11259 | |
11260 | /* We get here if we got the same row ref in all scans. */ |
11261 | if (need_to_fetch_row) |
11262 | error= head->file->ha_rnd_pos(head->record[0], last_rowid); |
11263 | |
11264 | if (!need_to_fetch_row) |
11265 | { |
11266 | /* Restore the columns we've read/saved with other quick selects */ |
11267 | quick_it.rewind(); |
11268 | while ((qr= quick_it++)) |
11269 | { |
11270 | if (qr->quick != quick) |
11271 | { |
11272 | key_restore(record, qr->key_tuple, head->key_info + qr->quick->index, |
11273 | qr->quick->max_used_key_length); |
11274 | } |
11275 | } |
11276 | } |
11277 | |
11278 | DBUG_RETURN(error); |
11279 | } |
11280 | |
11281 | |
11282 | /* |
11283 | Retrieve next record. |
11284 | SYNOPSIS |
11285 | QUICK_ROR_UNION_SELECT::get_next() |
11286 | |
11287 | NOTES |
11288 | Enter/exit invariant: |
11289 | For each quick select in the queue a {key,rowid} tuple has been |
11290 | retrieved but the corresponding row hasn't been passed to output. |
11291 | |
11292 | RETURN |
11293 | 0 - Ok |
11294 | other - Error code if any error occurred. |
11295 | */ |
11296 | |
11297 | int QUICK_ROR_UNION_SELECT::get_next() |
11298 | { |
11299 | int error, dup_row; |
11300 | QUICK_SELECT_I *quick; |
11301 | uchar *tmp; |
11302 | DBUG_ENTER("QUICK_ROR_UNION_SELECT::get_next" ); |
11303 | |
11304 | do |
11305 | { |
11306 | if (!queue.elements) |
11307 | DBUG_RETURN(HA_ERR_END_OF_FILE); |
11308 | /* Ok, we have a queue with >= 1 scans */ |
11309 | |
11310 | quick= (QUICK_SELECT_I*)queue_top(&queue); |
11311 | memcpy(cur_rowid, quick->last_rowid, rowid_length); |
11312 | |
11313 | /* put into queue rowid from the same stream as top element */ |
11314 | if ((error= quick->get_next())) |
11315 | { |
11316 | if (error != HA_ERR_END_OF_FILE) |
11317 | DBUG_RETURN(error); |
11318 | queue_remove_top(&queue); |
11319 | } |
11320 | else |
11321 | { |
11322 | quick->save_last_pos(); |
11323 | queue_replace_top(&queue); |
11324 | } |
11325 | |
11326 | if (!have_prev_rowid) |
11327 | { |
11328 | /* No rows have been returned yet */ |
11329 | dup_row= FALSE; |
11330 | have_prev_rowid= TRUE; |
11331 | } |
11332 | else |
11333 | dup_row= !head->file->cmp_ref(cur_rowid, prev_rowid); |
11334 | } while (dup_row); |
11335 | |
11336 | tmp= cur_rowid; |
11337 | cur_rowid= prev_rowid; |
11338 | prev_rowid= tmp; |
11339 | |
11340 | error= head->file->ha_rnd_pos(quick->record, prev_rowid); |
11341 | DBUG_RETURN(error); |
11342 | } |
11343 | |
11344 | |
11345 | int QUICK_RANGE_SELECT::reset() |
11346 | { |
11347 | uint buf_size; |
11348 | uchar *mrange_buff; |
11349 | int error; |
11350 | HANDLER_BUFFER empty_buf; |
11351 | MY_BITMAP * const save_read_set= head->read_set; |
11352 | MY_BITMAP * const save_write_set= head->write_set; |
11353 | MY_BITMAP * const save_vcol_set= head->vcol_set; |
11354 | DBUG_ENTER("QUICK_RANGE_SELECT::reset" ); |
11355 | last_range= NULL; |
11356 | cur_range= (QUICK_RANGE**) ranges.buffer; |
11357 | RANGE_SEQ_IF seq_funcs= {NULL, quick_range_seq_init, quick_range_seq_next, 0, 0}; |
11358 | |
11359 | if (file->inited == handler::RND) |
11360 | { |
11361 | /* Handler could be left in this state by MRR */ |
11362 | if (unlikely((error= file->ha_rnd_end()))) |
11363 | DBUG_RETURN(error); |
11364 | } |
11365 | |
11366 | if (in_ror_merged_scan) |
11367 | head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap, |
11368 | &column_bitmap); |
11369 | |
11370 | if (file->inited == handler::NONE) |
11371 | { |
11372 | DBUG_EXECUTE_IF("bug14365043_2" , |
11373 | DBUG_SET("+d,ha_index_init_fail" );); |
11374 | if (unlikely((error= file->ha_index_init(index,1)))) |
11375 | { |
11376 | file->print_error(error, MYF(0)); |
11377 | goto err; |
11378 | } |
11379 | } |
11380 | |
11381 | /* Allocate buffer if we need one but haven't allocated it yet */ |
11382 | if (mrr_buf_size && !mrr_buf_desc) |
11383 | { |
11384 | buf_size= mrr_buf_size; |
11385 | while (buf_size && !my_multi_malloc(MYF(MY_WME), |
11386 | &mrr_buf_desc, sizeof(*mrr_buf_desc), |
11387 | &mrange_buff, buf_size, |
11388 | NullS)) |
11389 | { |
11390 | /* Try to shrink the buffers until both are 0. */ |
11391 | buf_size/= 2; |
11392 | } |
11393 | if (!mrr_buf_desc) |
11394 | { |
11395 | error= HA_ERR_OUT_OF_MEM; |
11396 | goto err; |
11397 | } |
11398 | |
11399 | /* Initialize the handler buffer. */ |
11400 | mrr_buf_desc->buffer= mrange_buff; |
11401 | mrr_buf_desc->buffer_end= mrange_buff + buf_size; |
11402 | mrr_buf_desc->end_of_used_area= mrange_buff; |
11403 | } |
11404 | |
11405 | if (!mrr_buf_desc) |
11406 | empty_buf.buffer= empty_buf.buffer_end= empty_buf.end_of_used_area= NULL; |
11407 | |
11408 | error= file->multi_range_read_init(&seq_funcs, (void*)this, ranges.elements, |
11409 | mrr_flags, mrr_buf_desc? mrr_buf_desc: |
11410 | &empty_buf); |
11411 | err: |
11412 | /* Restore bitmaps set on entry */ |
11413 | if (in_ror_merged_scan) |
11414 | head->column_bitmaps_set_no_signal(save_read_set, save_write_set, |
11415 | save_vcol_set); |
11416 | DBUG_RETURN(error); |
11417 | } |
11418 | |
11419 | |
11420 | /* |
11421 | Get next possible record using quick-struct. |
11422 | |
11423 | SYNOPSIS |
11424 | QUICK_RANGE_SELECT::get_next() |
11425 | |
11426 | NOTES |
11427 | Record is read into table->record[0] |
11428 | |
11429 | RETURN |
11430 | 0 Found row |
11431 | HA_ERR_END_OF_FILE No (more) rows in range |
11432 | # Error code |
11433 | */ |
11434 | |
11435 | int QUICK_RANGE_SELECT::get_next() |
11436 | { |
11437 | range_id_t dummy; |
11438 | int result; |
11439 | DBUG_ENTER("QUICK_RANGE_SELECT::get_next" ); |
11440 | |
11441 | if (!in_ror_merged_scan) |
11442 | DBUG_RETURN(file->multi_range_read_next(&dummy)); |
11443 | |
11444 | MY_BITMAP * const save_read_set= head->read_set; |
11445 | MY_BITMAP * const save_write_set= head->write_set; |
11446 | MY_BITMAP * const save_vcol_set= head->vcol_set; |
11447 | /* |
11448 | We don't need to signal the bitmap change as the bitmap is always the |
11449 | same for this head->file |
11450 | */ |
11451 | head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap, |
11452 | &column_bitmap); |
11453 | result= file->multi_range_read_next(&dummy); |
11454 | head->column_bitmaps_set_no_signal(save_read_set, save_write_set, |
11455 | save_vcol_set); |
11456 | DBUG_RETURN(result); |
11457 | } |
11458 | |
11459 | |
11460 | /* |
11461 | Get the next record with a different prefix. |
11462 | |
11463 | @param prefix_length length of cur_prefix |
11464 | @param group_key_parts The number of key parts in the group prefix |
11465 | @param cur_prefix prefix of a key to be searched for |
11466 | |
11467 | Each subsequent call to the method retrieves the first record that has a |
11468 | prefix with length prefix_length and which is different from cur_prefix, |
11469 | such that the record with the new prefix is within the ranges described by |
11470 | this->ranges. The record found is stored into the buffer pointed by |
11471 | this->record. The method is useful for GROUP-BY queries with range |
11472 | conditions to discover the prefix of the next group that satisfies the range |
11473 | conditions. |
11474 | |
11475 | @todo |
11476 | |
11477 | This method is a modified copy of QUICK_RANGE_SELECT::get_next(), so both |
11478 | methods should be unified into a more general one to reduce code |
11479 | duplication. |
11480 | |
11481 | @retval 0 on success |
11482 | @retval HA_ERR_END_OF_FILE if returned all keys |
11483 | @retval other if some error occurred |
11484 | */ |
11485 | |
11486 | int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, |
11487 | uint group_key_parts, |
11488 | uchar *cur_prefix) |
11489 | { |
11490 | DBUG_ENTER("QUICK_RANGE_SELECT::get_next_prefix" ); |
11491 | const key_part_map keypart_map= make_prev_keypart_map(group_key_parts); |
11492 | |
11493 | for (;;) |
11494 | { |
11495 | int result; |
11496 | if (last_range) |
11497 | { |
11498 | /* Read the next record in the same range with prefix after cur_prefix. */ |
11499 | DBUG_ASSERT(cur_prefix != NULL); |
11500 | result= file->ha_index_read_map(record, cur_prefix, keypart_map, |
11501 | HA_READ_AFTER_KEY); |
11502 | if (result || last_range->max_keypart_map == 0) |
11503 | DBUG_RETURN(result); |
11504 | |
11505 | key_range previous_endpoint; |
11506 | last_range->make_max_endpoint(&previous_endpoint, prefix_length, keypart_map); |
11507 | if (file->compare_key(&previous_endpoint) <= 0) |
11508 | DBUG_RETURN(0); |
11509 | } |
11510 | |
11511 | uint count= ranges.elements - (uint)(cur_range - (QUICK_RANGE**) ranges.buffer); |
11512 | if (count == 0) |
11513 | { |
11514 | /* Ranges have already been used up before. None is left for read. */ |
11515 | last_range= 0; |
11516 | DBUG_RETURN(HA_ERR_END_OF_FILE); |
11517 | } |
11518 | last_range= *(cur_range++); |
11519 | |
11520 | key_range start_key, end_key; |
11521 | last_range->make_min_endpoint(&start_key, prefix_length, keypart_map); |
11522 | last_range->make_max_endpoint(&end_key, prefix_length, keypart_map); |
11523 | |
11524 | result= file->read_range_first(last_range->min_keypart_map ? &start_key : 0, |
11525 | last_range->max_keypart_map ? &end_key : 0, |
11526 | MY_TEST(last_range->flag & EQ_RANGE), |
11527 | TRUE); |
11528 | if (last_range->flag == (UNIQUE_RANGE | EQ_RANGE)) |
11529 | last_range= 0; // Stop searching |
11530 | |
11531 | if (result != HA_ERR_END_OF_FILE) |
11532 | DBUG_RETURN(result); |
11533 | last_range= 0; // No matching rows; go to next range |
11534 | } |
11535 | } |
11536 | |
11537 | |
11538 | /* Get next for geometrical indexes */ |
11539 | |
11540 | int QUICK_RANGE_SELECT_GEOM::get_next() |
11541 | { |
11542 | DBUG_ENTER("QUICK_RANGE_SELECT_GEOM::get_next" ); |
11543 | |
11544 | for (;;) |
11545 | { |
11546 | int result; |
11547 | if (last_range) |
11548 | { |
11549 | // Already read through key |
11550 | result= file->ha_index_next_same(record, last_range->min_key, |
11551 | last_range->min_length); |
11552 | if (result != HA_ERR_END_OF_FILE) |
11553 | DBUG_RETURN(result); |
11554 | } |
11555 | |
11556 | uint count= ranges.elements - (uint)(cur_range - (QUICK_RANGE**) ranges.buffer); |
11557 | if (count == 0) |
11558 | { |
11559 | /* Ranges have already been used up before. None is left for read. */ |
11560 | last_range= 0; |
11561 | DBUG_RETURN(HA_ERR_END_OF_FILE); |
11562 | } |
11563 | last_range= *(cur_range++); |
11564 | |
11565 | result= file->ha_index_read_map(record, last_range->min_key, |
11566 | last_range->min_keypart_map, |
11567 | (ha_rkey_function)(last_range->flag ^ |
11568 | GEOM_FLAG)); |
11569 | if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE) |
11570 | DBUG_RETURN(result); |
11571 | last_range= 0; // Not found, to next range |
11572 | } |
11573 | } |
11574 | |
11575 | |
11576 | /* |
11577 | Check if current row will be retrieved by this QUICK_RANGE_SELECT |
11578 | |
11579 | NOTES |
11580 | It is assumed that currently a scan is being done on another index |
11581 | which reads all necessary parts of the index that is scanned by this |
11582 | quick select. |
11583 | The implementation does a binary search on sorted array of disjoint |
11584 | ranges, without taking size of range into account. |
11585 | |
11586 | This function is used to filter out clustered PK scan rows in |
11587 | index_merge quick select. |
11588 | |
11589 | RETURN |
11590 | TRUE if current row will be retrieved by this quick select |
11591 | FALSE if not |
11592 | */ |
11593 | |
11594 | bool QUICK_RANGE_SELECT::row_in_ranges() |
11595 | { |
11596 | QUICK_RANGE *res; |
11597 | uint min= 0; |
11598 | uint max= ranges.elements - 1; |
11599 | uint mid= (max + min)/2; |
11600 | |
11601 | while (min != max) |
11602 | { |
11603 | if (cmp_next(*(QUICK_RANGE**)dynamic_array_ptr(&ranges, mid))) |
11604 | { |
11605 | /* current row value > mid->max */ |
11606 | min= mid + 1; |
11607 | } |
11608 | else |
11609 | max= mid; |
11610 | mid= (min + max) / 2; |
11611 | } |
11612 | res= *(QUICK_RANGE**)dynamic_array_ptr(&ranges, mid); |
11613 | return (!cmp_next(res) && !cmp_prev(res)); |
11614 | } |
11615 | |
11616 | /* |
11617 | This is a hack: we inherit from QUICK_RANGE_SELECT so that we can use the |
11618 | get_next() interface, but we have to hold a pointer to the original |
11619 | QUICK_RANGE_SELECT because its data are used all over the place. What |
11620 | should be done is to factor out the data that is needed into a base |
11621 | class (QUICK_SELECT), and then have two subclasses (_ASC and _DESC) |
11622 | which handle the ranges and implement the get_next() function. But |
11623 | for now, this seems to work right at least. |
11624 | */ |
11625 | |
11626 | QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, |
11627 | uint used_key_parts_arg) |
11628 | :QUICK_RANGE_SELECT(*q), rev_it(rev_ranges), |
11629 | used_key_parts (used_key_parts_arg) |
11630 | { |
11631 | QUICK_RANGE *r; |
11632 | /* |
11633 | Use default MRR implementation for reverse scans. No table engine |
11634 | currently can do an MRR scan with output in reverse index order. |
11635 | */ |
11636 | mrr_buf_desc= NULL; |
11637 | mrr_flags |= HA_MRR_USE_DEFAULT_IMPL; |
11638 | mrr_buf_size= 0; |
11639 | |
11640 | QUICK_RANGE **pr= (QUICK_RANGE**)ranges.buffer; |
11641 | QUICK_RANGE **end_range= pr + ranges.elements; |
11642 | for (; pr!=end_range; pr++) |
11643 | rev_ranges.push_front(*pr); |
11644 | |
11645 | /* Remove EQ_RANGE flag for keys that are not using the full key */ |
11646 | for (r = rev_it++; r; r = rev_it++) |
11647 | { |
11648 | if ((r->flag & EQ_RANGE) && |
11649 | head->key_info[index].key_length != r->max_length) |
11650 | r->flag&= ~EQ_RANGE; |
11651 | } |
11652 | rev_it.rewind(); |
11653 | q->dont_free=1; // Don't free shared mem |
11654 | } |
11655 | |
11656 | |
11657 | int QUICK_SELECT_DESC::get_next() |
11658 | { |
11659 | DBUG_ENTER("QUICK_SELECT_DESC::get_next" ); |
11660 | |
11661 | /* The max key is handled as follows: |
11662 | * - if there is NO_MAX_RANGE, start at the end and move backwards |
11663 | * - if it is an EQ_RANGE, which means that max key covers the entire |
11664 | * key, go directly to the key and read through it (sorting backwards is |
11665 | * same as sorting forwards) |
11666 | * - if it is NEAR_MAX, go to the key or next, step back once, and |
11667 | * move backwards |
11668 | * - otherwise (not NEAR_MAX == include the key), go after the key, |
11669 | * step back once, and move backwards |
11670 | */ |
11671 | |
11672 | for (;;) |
11673 | { |
11674 | int result; |
11675 | if (last_range) |
11676 | { // Already read through key |
11677 | result = ((last_range->flag & EQ_RANGE && |
11678 | used_key_parts <= head->key_info[index].user_defined_key_parts) ? |
11679 | file->ha_index_next_same(record, last_range->min_key, |
11680 | last_range->min_length) : |
11681 | file->ha_index_prev(record)); |
11682 | if (!result) |
11683 | { |
11684 | if (cmp_prev(*rev_it.ref()) == 0) |
11685 | DBUG_RETURN(0); |
11686 | } |
11687 | else if (result != HA_ERR_END_OF_FILE) |
11688 | DBUG_RETURN(result); |
11689 | } |
11690 | |
11691 | if (!(last_range= rev_it++)) |
11692 | DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used |
11693 | |
11694 | key_range start_key; |
11695 | start_key.key= (const uchar*) last_range->min_key; |
11696 | start_key.length= last_range->min_length; |
11697 | start_key.flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY : |
11698 | (last_range->flag & EQ_RANGE) ? |
11699 | HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT); |
11700 | start_key.keypart_map= last_range->min_keypart_map; |
11701 | key_range end_key; |
11702 | end_key.key= (const uchar*) last_range->max_key; |
11703 | end_key.length= last_range->max_length; |
11704 | end_key.flag= (last_range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY : |
11705 | HA_READ_AFTER_KEY); |
11706 | end_key.keypart_map= last_range->max_keypart_map; |
11707 | result= file->prepare_range_scan((last_range->flag & NO_MIN_RANGE) ? NULL : &start_key, |
11708 | (last_range->flag & NO_MAX_RANGE) ? NULL : &end_key); |
11709 | if (result) |
11710 | { |
11711 | DBUG_RETURN(result); |
11712 | } |
11713 | |
11714 | if (last_range->flag & NO_MAX_RANGE) // Read last record |
11715 | { |
11716 | int local_error; |
11717 | if (unlikely((local_error= file->ha_index_last(record)))) |
11718 | DBUG_RETURN(local_error); // Empty table |
11719 | if (cmp_prev(last_range) == 0) |
11720 | DBUG_RETURN(0); |
11721 | last_range= 0; // No match; go to next range |
11722 | continue; |
11723 | } |
11724 | |
11725 | if (last_range->flag & EQ_RANGE && |
11726 | used_key_parts <= head->key_info[index].user_defined_key_parts) |
11727 | |
11728 | { |
11729 | result= file->ha_index_read_map(record, last_range->max_key, |
11730 | last_range->max_keypart_map, |
11731 | HA_READ_KEY_EXACT); |
11732 | } |
11733 | else |
11734 | { |
11735 | DBUG_ASSERT(last_range->flag & NEAR_MAX || |
11736 | (last_range->flag & EQ_RANGE && |
11737 | used_key_parts > head->key_info[index].user_defined_key_parts) || |
11738 | range_reads_after_key(last_range)); |
11739 | result= file->ha_index_read_map(record, last_range->max_key, |
11740 | last_range->max_keypart_map, |
11741 | ((last_range->flag & NEAR_MAX) ? |
11742 | HA_READ_BEFORE_KEY : |
11743 | HA_READ_PREFIX_LAST_OR_PREV)); |
11744 | } |
11745 | if (result) |
11746 | { |
11747 | if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE) |
11748 | DBUG_RETURN(result); |
11749 | last_range= 0; // Not found, to next range |
11750 | continue; |
11751 | } |
11752 | if (cmp_prev(last_range) == 0) |
11753 | { |
11754 | if (last_range->flag == (UNIQUE_RANGE | EQ_RANGE)) |
11755 | last_range= 0; // Stop searching |
11756 | DBUG_RETURN(0); // Found key is in range |
11757 | } |
11758 | last_range= 0; // To next range |
11759 | } |
11760 | } |
11761 | |
11762 | |
11763 | /** |
11764 | Create a compatible quick select with the result ordered in an opposite way |
11765 | |
11766 | @param used_key_parts_arg Number of used key parts |
11767 | |
11768 | @retval NULL in case of errors (OOM etc) |
11769 | @retval pointer to a newly created QUICK_SELECT_DESC if success |
11770 | */ |
11771 | |
11772 | QUICK_SELECT_I *QUICK_RANGE_SELECT::make_reverse(uint used_key_parts_arg) |
11773 | { |
11774 | QUICK_SELECT_DESC *new_quick= new QUICK_SELECT_DESC(this, used_key_parts_arg); |
11775 | if (new_quick == NULL) |
11776 | { |
11777 | delete new_quick; |
11778 | return NULL; |
11779 | } |
11780 | return new_quick; |
11781 | } |
11782 | |
11783 | |
11784 | /* |
11785 | Compare if found key is over max-value |
11786 | Returns 0 if key <= range->max_key |
11787 | TODO: Figure out why can't this function be as simple as cmp_prev(). |
11788 | */ |
11789 | |
11790 | int QUICK_RANGE_SELECT::cmp_next(QUICK_RANGE *range_arg) |
11791 | { |
11792 | if (range_arg->flag & NO_MAX_RANGE) |
11793 | return 0; /* key can't be to large */ |
11794 | |
11795 | KEY_PART *key_part=key_parts; |
11796 | uint store_length; |
11797 | |
11798 | for (uchar *key=range_arg->max_key, *end=key+range_arg->max_length; |
11799 | key < end; |
11800 | key+= store_length, key_part++) |
11801 | { |
11802 | int cmp; |
11803 | store_length= key_part->store_length; |
11804 | if (key_part->null_bit) |
11805 | { |
11806 | if (*key) |
11807 | { |
11808 | if (!key_part->field->is_null()) |
11809 | return 1; |
11810 | continue; |
11811 | } |
11812 | else if (key_part->field->is_null()) |
11813 | return 0; |
11814 | key++; // Skip null byte |
11815 | store_length--; |
11816 | } |
11817 | if ((cmp=key_part->field->key_cmp(key, key_part->length)) < 0) |
11818 | return 0; |
11819 | if (cmp > 0) |
11820 | return 1; |
11821 | } |
11822 | return (range_arg->flag & NEAR_MAX) ? 1 : 0; // Exact match |
11823 | } |
11824 | |
11825 | |
11826 | /* |
11827 | Returns 0 if found key is inside range (found key >= range->min_key). |
11828 | */ |
11829 | |
11830 | int QUICK_RANGE_SELECT::cmp_prev(QUICK_RANGE *range_arg) |
11831 | { |
11832 | int cmp; |
11833 | if (range_arg->flag & NO_MIN_RANGE) |
11834 | return 0; /* key can't be to small */ |
11835 | |
11836 | cmp= key_cmp(key_part_info, range_arg->min_key, |
11837 | range_arg->min_length); |
11838 | if (cmp > 0 || (cmp == 0 && !(range_arg->flag & NEAR_MIN))) |
11839 | return 0; |
11840 | return 1; // outside of range |
11841 | } |
11842 | |
11843 | |
11844 | /* |
11845 | * TRUE if this range will require using HA_READ_AFTER_KEY |
11846 | See comment in get_next() about this |
11847 | */ |
11848 | |
11849 | bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg) |
11850 | { |
11851 | return ((range_arg->flag & (NO_MAX_RANGE | NEAR_MAX)) || |
11852 | !(range_arg->flag & EQ_RANGE) || |
11853 | head->key_info[index].key_length != range_arg->max_length) ? 1 : 0; |
11854 | } |
11855 | |
11856 | |
11857 | void QUICK_SELECT_I::add_key_name(String *str, bool *first) |
11858 | { |
11859 | KEY *key_info= head->key_info + index; |
11860 | |
11861 | if (*first) |
11862 | *first= FALSE; |
11863 | else |
11864 | str->append(','); |
11865 | str->append(&key_info->name); |
11866 | } |
11867 | |
11868 | |
11869 | Explain_quick_select* QUICK_RANGE_SELECT::get_explain(MEM_ROOT *local_alloc) |
11870 | { |
11871 | Explain_quick_select *res; |
11872 | if ((res= new (local_alloc) Explain_quick_select(QS_TYPE_RANGE))) |
11873 | res->range.set(local_alloc, &head->key_info[index], max_used_key_length); |
11874 | return res; |
11875 | } |
11876 | |
11877 | |
11878 | Explain_quick_select* |
11879 | QUICK_GROUP_MIN_MAX_SELECT::get_explain(MEM_ROOT *local_alloc) |
11880 | { |
11881 | Explain_quick_select *res; |
11882 | if ((res= new (local_alloc) Explain_quick_select(QS_TYPE_GROUP_MIN_MAX))) |
11883 | res->range.set(local_alloc, &head->key_info[index], max_used_key_length); |
11884 | return res; |
11885 | } |
11886 | |
11887 | |
11888 | Explain_quick_select* |
11889 | QUICK_INDEX_SORT_SELECT::get_explain(MEM_ROOT *local_alloc) |
11890 | { |
11891 | Explain_quick_select *res; |
11892 | if (!(res= new (local_alloc) Explain_quick_select(get_type()))) |
11893 | return NULL; |
11894 | |
11895 | QUICK_RANGE_SELECT *quick; |
11896 | Explain_quick_select *child_explain; |
11897 | List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); |
11898 | while ((quick= it++)) |
11899 | { |
11900 | if ((child_explain= quick->get_explain(local_alloc))) |
11901 | res->children.push_back(child_explain); |
11902 | else |
11903 | return NULL; |
11904 | } |
11905 | |
11906 | if (pk_quick_select) |
11907 | { |
11908 | if ((child_explain= pk_quick_select->get_explain(local_alloc))) |
11909 | res->children.push_back(child_explain); |
11910 | else |
11911 | return NULL; |
11912 | } |
11913 | return res; |
11914 | } |
11915 | |
11916 | |
11917 | /* |
11918 | Same as QUICK_INDEX_SORT_SELECT::get_explain(), but primary key is printed |
11919 | first |
11920 | */ |
11921 | |
11922 | Explain_quick_select* |
11923 | QUICK_INDEX_INTERSECT_SELECT::get_explain(MEM_ROOT *local_alloc) |
11924 | { |
11925 | Explain_quick_select *res; |
11926 | Explain_quick_select *child_explain; |
11927 | |
11928 | if (!(res= new (local_alloc) Explain_quick_select(get_type()))) |
11929 | return NULL; |
11930 | |
11931 | if (pk_quick_select) |
11932 | { |
11933 | if ((child_explain= pk_quick_select->get_explain(local_alloc))) |
11934 | res->children.push_back(child_explain); |
11935 | else |
11936 | return NULL; |
11937 | } |
11938 | |
11939 | QUICK_RANGE_SELECT *quick; |
11940 | List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); |
11941 | while ((quick= it++)) |
11942 | { |
11943 | if ((child_explain= quick->get_explain(local_alloc))) |
11944 | res->children.push_back(child_explain); |
11945 | else |
11946 | return NULL; |
11947 | } |
11948 | return res; |
11949 | } |
11950 | |
11951 | |
11952 | Explain_quick_select* |
11953 | QUICK_ROR_INTERSECT_SELECT::get_explain(MEM_ROOT *local_alloc) |
11954 | { |
11955 | Explain_quick_select *res; |
11956 | Explain_quick_select *child_explain; |
11957 | |
11958 | if (!(res= new (local_alloc) Explain_quick_select(get_type()))) |
11959 | return NULL; |
11960 | |
11961 | QUICK_SELECT_WITH_RECORD *qr; |
11962 | List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects); |
11963 | while ((qr= it++)) |
11964 | { |
11965 | if ((child_explain= qr->quick->get_explain(local_alloc))) |
11966 | res->children.push_back(child_explain); |
11967 | else |
11968 | return NULL; |
11969 | } |
11970 | |
11971 | if (cpk_quick) |
11972 | { |
11973 | if ((child_explain= cpk_quick->get_explain(local_alloc))) |
11974 | res->children.push_back(child_explain); |
11975 | else |
11976 | return NULL; |
11977 | } |
11978 | return res; |
11979 | } |
11980 | |
11981 | |
11982 | Explain_quick_select* |
11983 | QUICK_ROR_UNION_SELECT::get_explain(MEM_ROOT *local_alloc) |
11984 | { |
11985 | Explain_quick_select *res; |
11986 | Explain_quick_select *child_explain; |
11987 | |
11988 | if (!(res= new (local_alloc) Explain_quick_select(get_type()))) |
11989 | return NULL; |
11990 | |
11991 | QUICK_SELECT_I *quick; |
11992 | List_iterator_fast<QUICK_SELECT_I> it(quick_selects); |
11993 | while ((quick= it++)) |
11994 | { |
11995 | if ((child_explain= quick->get_explain(local_alloc))) |
11996 | res->children.push_back(child_explain); |
11997 | else |
11998 | return NULL; |
11999 | } |
12000 | |
12001 | return res; |
12002 | } |
12003 | |
12004 | |
12005 | void QUICK_SELECT_I::add_key_and_length(String *key_names, |
12006 | String *used_lengths, |
12007 | bool *first) |
12008 | { |
12009 | char buf[64]; |
12010 | size_t length; |
12011 | KEY *key_info= head->key_info + index; |
12012 | |
12013 | if (*first) |
12014 | *first= FALSE; |
12015 | else |
12016 | { |
12017 | key_names->append(','); |
12018 | used_lengths->append(','); |
12019 | } |
12020 | key_names->append(&key_info->name); |
12021 | length= longlong10_to_str(max_used_key_length, buf, 10) - buf; |
12022 | used_lengths->append(buf, length); |
12023 | } |
12024 | |
12025 | |
12026 | void QUICK_RANGE_SELECT::add_keys_and_lengths(String *key_names, |
12027 | String *used_lengths) |
12028 | { |
12029 | bool first= TRUE; |
12030 | |
12031 | add_key_and_length(key_names, used_lengths, &first); |
12032 | } |
12033 | |
12034 | void QUICK_INDEX_MERGE_SELECT::add_keys_and_lengths(String *key_names, |
12035 | String *used_lengths) |
12036 | { |
12037 | QUICK_RANGE_SELECT *quick; |
12038 | bool first= TRUE; |
12039 | |
12040 | List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); |
12041 | |
12042 | while ((quick= it++)) |
12043 | { |
12044 | quick->add_key_and_length(key_names, used_lengths, &first); |
12045 | } |
12046 | |
12047 | if (pk_quick_select) |
12048 | pk_quick_select->add_key_and_length(key_names, used_lengths, &first); |
12049 | } |
12050 | |
12051 | |
12052 | void QUICK_INDEX_INTERSECT_SELECT::add_keys_and_lengths(String *key_names, |
12053 | String *used_lengths) |
12054 | { |
12055 | QUICK_RANGE_SELECT *quick; |
12056 | bool first= TRUE; |
12057 | |
12058 | List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); |
12059 | |
12060 | if (pk_quick_select) |
12061 | pk_quick_select->add_key_and_length(key_names, used_lengths, &first); |
12062 | |
12063 | while ((quick= it++)) |
12064 | { |
12065 | quick->add_key_and_length(key_names, used_lengths, &first); |
12066 | } |
12067 | } |
12068 | |
12069 | void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names, |
12070 | String *used_lengths) |
12071 | { |
12072 | QUICK_SELECT_WITH_RECORD *qr; |
12073 | bool first= TRUE; |
12074 | |
12075 | List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects); |
12076 | |
12077 | while ((qr= it++)) |
12078 | { |
12079 | qr->quick->add_key_and_length(key_names, used_lengths, &first); |
12080 | } |
12081 | if (cpk_quick) |
12082 | cpk_quick->add_key_and_length(key_names, used_lengths, &first); |
12083 | } |
12084 | |
12085 | void QUICK_ROR_UNION_SELECT::add_keys_and_lengths(String *key_names, |
12086 | String *used_lengths) |
12087 | { |
12088 | QUICK_SELECT_I *quick; |
12089 | bool first= TRUE; |
12090 | |
12091 | List_iterator_fast<QUICK_SELECT_I> it(quick_selects); |
12092 | |
12093 | while ((quick= it++)) |
12094 | { |
12095 | if (first) |
12096 | first= FALSE; |
12097 | else |
12098 | { |
12099 | used_lengths->append(','); |
12100 | key_names->append(','); |
12101 | } |
12102 | quick->add_keys_and_lengths(key_names, used_lengths); |
12103 | } |
12104 | } |
12105 | |
12106 | |
12107 | void QUICK_RANGE_SELECT::add_used_key_part_to_set() |
12108 | { |
12109 | uint key_len; |
12110 | KEY_PART *part= key_parts; |
12111 | for (key_len=0; key_len < max_used_key_length; |
12112 | key_len += (part++)->store_length) |
12113 | { |
12114 | /* |
12115 | We have to use field_index instead of part->field |
12116 | as for partial fields, part->field points to |
12117 | a temporary field that is only part of the original |
12118 | field. field_index always points to the original field |
12119 | */ |
12120 | Field *field= head->field[part->field->field_index]; |
12121 | field->register_field_in_read_map(); |
12122 | } |
12123 | } |
12124 | |
12125 | |
12126 | void QUICK_GROUP_MIN_MAX_SELECT::add_used_key_part_to_set() |
12127 | { |
12128 | uint key_len; |
12129 | KEY_PART_INFO *part= index_info->key_part; |
12130 | for (key_len=0; key_len < max_used_key_length; |
12131 | key_len += (part++)->store_length) |
12132 | { |
12133 | /* |
12134 | We have to use field_index instead of part->field |
12135 | as for partial fields, part->field points to |
12136 | a temporary field that is only part of the original |
12137 | field. field_index always points to the original field |
12138 | */ |
12139 | Field *field= head->field[part->field->field_index]; |
12140 | field->register_field_in_read_map(); |
12141 | } |
12142 | } |
12143 | |
12144 | |
12145 | void QUICK_ROR_INTERSECT_SELECT::add_used_key_part_to_set() |
12146 | { |
12147 | List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects); |
12148 | QUICK_SELECT_WITH_RECORD *quick; |
12149 | while ((quick= it++)) |
12150 | { |
12151 | quick->quick->add_used_key_part_to_set(); |
12152 | } |
12153 | } |
12154 | |
12155 | |
12156 | void QUICK_INDEX_SORT_SELECT::add_used_key_part_to_set() |
12157 | { |
12158 | QUICK_RANGE_SELECT *quick; |
12159 | List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); |
12160 | while ((quick= it++)) |
12161 | { |
12162 | quick->add_used_key_part_to_set(); |
12163 | } |
12164 | if (pk_quick_select) |
12165 | pk_quick_select->add_used_key_part_to_set(); |
12166 | } |
12167 | |
12168 | |
12169 | void QUICK_ROR_UNION_SELECT::add_used_key_part_to_set() |
12170 | { |
12171 | QUICK_SELECT_I *quick; |
12172 | List_iterator_fast<QUICK_SELECT_I> it(quick_selects); |
12173 | |
12174 | while ((quick= it++)) |
12175 | { |
12176 | quick->add_used_key_part_to_set(); |
12177 | } |
12178 | } |
12179 | |
12180 | |
12181 | /******************************************************************************* |
12182 | * Implementation of QUICK_GROUP_MIN_MAX_SELECT |
12183 | *******************************************************************************/ |
12184 | |
12185 | static inline uint get_field_keypart(KEY *index, Field *field); |
12186 | static bool get_sel_arg_for_keypart(Field *field, SEL_ARG *index_range_tree, |
12187 | SEL_ARG **cur_range); |
12188 | static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree, |
12189 | KEY_PART_INFO *first_non_group_part, |
12190 | KEY_PART_INFO *min_max_arg_part, |
12191 | KEY_PART_INFO *last_part, THD *thd, |
12192 | uchar *key_infix, uint *key_infix_len, |
12193 | KEY_PART_INFO **first_non_infix_part); |
12194 | static bool |
12195 | check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item, |
12196 | Field::imagetype image_type, |
12197 | bool *has_min_max_fld, bool *has_other_fld); |
12198 | |
12199 | static void |
12200 | cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, |
12201 | uint group_key_parts, SEL_TREE *range_tree, |
12202 | SEL_ARG *index_tree, ha_rows quick_prefix_records, |
12203 | bool have_min, bool have_max, |
12204 | double *read_cost, ha_rows *records); |
12205 | |
12206 | |
12207 | /** |
12208 | Test if this access method is applicable to a GROUP query with MIN/MAX |
12209 | functions, and if so, construct a new TRP object. |
12210 | |
12211 | DESCRIPTION |
12212 | Test whether a query can be computed via a QUICK_GROUP_MIN_MAX_SELECT. |
12213 | Queries computable via a QUICK_GROUP_MIN_MAX_SELECT must satisfy the |
12214 | following conditions: |
12215 | A) Table T has at least one compound index I of the form: |
12216 | I = <A_1, ...,A_k, [B_1,..., B_m], C, [D_1,...,D_n]> |
12217 | B) Query conditions: |
12218 | B0. Q is over a single table T. |
12219 | B1. The attributes referenced by Q are a subset of the attributes of I. |
12220 | B2. All attributes QA in Q can be divided into 3 overlapping groups: |
12221 | - SA = {S_1, ..., S_l, [C]} - from the SELECT clause, where C is |
12222 | referenced by any number of MIN and/or MAX functions if present. |
12223 | - WA = {W_1, ..., W_p} - from the WHERE clause |
12224 | - GA = <G_1, ..., G_k> - from the GROUP BY clause (if any) |
12225 | = SA - if Q is a DISTINCT query (based on the |
12226 | equivalence of DISTINCT and GROUP queries. |
12227 | - NGA = QA - (GA union C) = {NG_1, ..., NG_m} - the ones not in |
12228 | GROUP BY and not referenced by MIN/MAX functions. |
12229 | with the following properties specified below. |
12230 | B3. If Q has a GROUP BY WITH ROLLUP clause the access method is not |
12231 | applicable. |
12232 | |
12233 | SA1. There is at most one attribute in SA referenced by any number of |
12234 | MIN and/or MAX functions which, which if present, is denoted as C. |
12235 | SA2. The position of the C attribute in the index is after the last A_k. |
12236 | SA3. The attribute C can be referenced in the WHERE clause only in |
12237 | predicates of the forms: |
12238 | - (C {< | <= | > | >= | =} const) |
12239 | - (const {< | <= | > | >= | =} C) |
12240 | - (C between const_i and const_j) |
12241 | - C IS NULL |
12242 | - C IS NOT NULL |
12243 | - C != const |
12244 | SA4. If Q has a GROUP BY clause, there are no other aggregate functions |
12245 | except MIN and MAX. For queries with DISTINCT, aggregate functions |
12246 | are allowed. |
12247 | SA5. The select list in DISTINCT queries should not contain expressions. |
12248 | SA6. Clustered index can not be used by GROUP_MIN_MAX quick select |
12249 | for AGG_FUNC(DISTINCT ...) optimization because cursor position is |
12250 | never stored after a unique key lookup in the clustered index and |
12251 | furhter index_next/prev calls can not be used. So loose index scan |
12252 | optimization can not be used in this case. |
12253 | SA7. If Q has both AGG_FUNC(DISTINCT ...) and MIN/MAX() functions then this |
12254 | access method is not used. |
12255 | For above queries MIN/MAX() aggregation has to be done at |
12256 | nested_loops_join (end_send_group). But with current design MIN/MAX() |
12257 | is always set as part of loose index scan. Because of this mismatch |
12258 | MIN() and MAX() values will be set incorrectly. For such queries to |
12259 | work we need a new interface for loose index scan. This new interface |
12260 | should only fetch records with min and max values and let |
12261 | end_send_group to do aggregation. Until then do not use |
12262 | loose_index_scan. |
12263 | GA1. If Q has a GROUP BY clause, then GA is a prefix of I. That is, if |
12264 | G_i = A_j => i = j. |
12265 | GA2. If Q has a DISTINCT clause, then there is a permutation of SA that |
12266 | forms a prefix of I. This permutation is used as the GROUP clause |
12267 | when the DISTINCT query is converted to a GROUP query. |
12268 | GA3. The attributes in GA may participate in arbitrary predicates, divided |
12269 | into two groups: |
12270 | - RNG(G_1,...,G_q ; where q <= k) is a range condition over the |
12271 | attributes of a prefix of GA |
12272 | - PA(G_i1,...G_iq) is an arbitrary predicate over an arbitrary subset |
12273 | of GA. Since P is applied to only GROUP attributes it filters some |
12274 | groups, and thus can be applied after the grouping. |
12275 | GA4. There are no expressions among G_i, just direct column references. |
12276 | NGA1.If in the index I there is a gap between the last GROUP attribute G_k, |
12277 | and the MIN/MAX attribute C, then NGA must consist of exactly the |
12278 | index attributes that constitute the gap. As a result there is a |
12279 | permutation of NGA, BA=<B_1,...,B_m>, that coincides with the gap |
12280 | in the index. |
12281 | NGA2.If BA <> {}, then the WHERE clause must contain a conjunction EQ of |
12282 | equality conditions for all NG_i of the form (NG_i = const) or |
12283 | (const = NG_i), such that each NG_i is referenced in exactly one |
12284 | conjunct. Informally, the predicates provide constants to fill the |
12285 | gap in the index. |
12286 | NGA3.If BA <> {}, there can only be one range. TODO: This is a code |
12287 | limitation and is not strictly needed. See BUG#15947433 |
12288 | WA1. There are no other attributes in the WHERE clause except the ones |
12289 | referenced in predicates RNG, PA, PC, EQ defined above. Therefore |
12290 | WA is subset of (GA union NGA union C) for GA,NGA,C that pass the |
12291 | above tests. By transitivity then it also follows that each WA_i |
12292 | participates in the index I (if this was already tested for GA, NGA |
12293 | and C). |
12294 | WA2. If there is a predicate on C, then it must be in conjunction |
12295 | to all predicates on all earlier keyparts in I. |
12296 | |
12297 | C) Overall query form: |
12298 | SELECT EXPR([A_1,...,A_k], [B_1,...,B_m], [MIN(C)], [MAX(C)]) |
12299 | FROM T |
12300 | WHERE [RNG(A_1,...,A_p ; where p <= k)] |
12301 | [AND EQ(B_1,...,B_m)] |
12302 | [AND PC(C)] |
12303 | [AND PA(A_i1,...,A_iq)] |
12304 | GROUP BY A_1,...,A_k |
12305 | [HAVING PH(A_1, ..., B_1,..., C)] |
12306 | where EXPR(...) is an arbitrary expression over some or all SELECT fields, |
12307 | or: |
12308 | SELECT DISTINCT A_i1,...,A_ik |
12309 | FROM T |
12310 | WHERE [RNG(A_1,...,A_p ; where p <= k)] |
12311 | [AND PA(A_i1,...,A_iq)]; |
12312 | |
12313 | NOTES |
12314 | If the current query satisfies the conditions above, and if |
12315 | (mem_root! = NULL), then the function constructs and returns a new TRP |
12316 | object, that is later used to construct a new QUICK_GROUP_MIN_MAX_SELECT. |
12317 | If (mem_root == NULL), then the function only tests whether the current |
12318 | query satisfies the conditions above, and, if so, sets |
12319 | is_applicable = TRUE. |
12320 | |
12321 | Queries with DISTINCT for which index access can be used are transformed |
12322 | into equivalent group-by queries of the form: |
12323 | |
12324 | SELECT A_1,...,A_k FROM T |
12325 | WHERE [RNG(A_1,...,A_p ; where p <= k)] |
12326 | [AND PA(A_i1,...,A_iq)] |
12327 | GROUP BY A_1,...,A_k; |
12328 | |
12329 | The group-by list is a permutation of the select attributes, according |
12330 | to their order in the index. |
12331 | |
12332 | TODO |
12333 | - What happens if the query groups by the MIN/MAX field, and there is no |
12334 | other field as in: "select MY_MIN(a) from t1 group by a" ? |
12335 | - We assume that the general correctness of the GROUP-BY query was checked |
12336 | before this point. Is this correct, or do we have to check it completely? |
12337 | - Lift the limitation in condition (B3), that is, make this access method |
12338 | applicable to ROLLUP queries. |
12339 | |
12340 | @param param Parameter from test_quick_select |
12341 | @param sel_tree Range tree generated by get_mm_tree |
12342 | @param read_time Best read time so far (=table/index scan time) |
12343 | @return table read plan |
12344 | @retval NULL Loose index scan not applicable or mem_root == NULL |
12345 | @retval !NULL Loose index scan table read plan |
12346 | */ |
12347 | |
12348 | static TRP_GROUP_MIN_MAX * |
12349 | get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) |
12350 | { |
12351 | THD *thd= param->thd; |
12352 | JOIN *join= thd->lex->current_select->join; |
12353 | TABLE *table= param->table; |
12354 | bool have_min= FALSE; /* TRUE if there is a MIN function. */ |
12355 | bool have_max= FALSE; /* TRUE if there is a MAX function. */ |
12356 | Item_field *min_max_arg_item= NULL; // The argument of all MIN/MAX functions |
12357 | KEY_PART_INFO *min_max_arg_part= NULL; /* The corresponding keypart. */ |
12358 | uint group_prefix_len= 0; /* Length (in bytes) of the key prefix. */ |
12359 | KEY *index_info= NULL; /* The index chosen for data access. */ |
12360 | uint index= 0; /* The id of the chosen index. */ |
12361 | uint group_key_parts= 0; // Number of index key parts in the group prefix. |
12362 | uint used_key_parts= 0; /* Number of index key parts used for access. */ |
12363 | uchar key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/ |
12364 | uint key_infix_len= 0; /* Length of key_infix. */ |
12365 | TRP_GROUP_MIN_MAX *read_plan= NULL; /* The eventually constructed TRP. */ |
12366 | uint key_part_nr; |
12367 | uint elements_in_group; |
12368 | ORDER *tmp_group; |
12369 | Item *item; |
12370 | Item_field *item_field; |
12371 | bool is_agg_distinct; |
12372 | List<Item_field> agg_distinct_flds; |
12373 | |
12374 | DBUG_ENTER("get_best_group_min_max" ); |
12375 | |
12376 | /* Perform few 'cheap' tests whether this access method is applicable. */ |
12377 | if (!join) |
12378 | DBUG_RETURN(NULL); /* This is not a select statement. */ |
12379 | if ((join->table_count != 1) || /* The query must reference one table. */ |
12380 | (join->select_lex->olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */ |
12381 | DBUG_RETURN(NULL); |
12382 | if (table->s->keys == 0) /* There are no indexes to use. */ |
12383 | DBUG_RETURN(NULL); |
12384 | if (join->conds && join->conds->used_tables() & OUTER_REF_TABLE_BIT) |
12385 | DBUG_RETURN(NULL); /* Cannot execute with correlated conditions. */ |
12386 | |
12387 | /* Check (SA1,SA4) and store the only MIN/MAX argument - the C attribute.*/ |
12388 | List_iterator<Item> select_items_it(join->fields_list); |
12389 | is_agg_distinct = is_indexed_agg_distinct(join, &agg_distinct_flds); |
12390 | |
12391 | if ((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */ |
12392 | (!join->select_distinct) && |
12393 | !is_agg_distinct) |
12394 | DBUG_RETURN(NULL); |
12395 | /* Analyze the query in more detail. */ |
12396 | |
12397 | if (join->sum_funcs[0]) |
12398 | { |
12399 | Item_sum *min_max_item; |
12400 | Item_sum **func_ptr= join->sum_funcs; |
12401 | while ((min_max_item= *(func_ptr++))) |
12402 | { |
12403 | if (min_max_item->sum_func() == Item_sum::MIN_FUNC) |
12404 | have_min= TRUE; |
12405 | else if (min_max_item->sum_func() == Item_sum::MAX_FUNC) |
12406 | have_max= TRUE; |
12407 | else if (is_agg_distinct && |
12408 | (min_max_item->sum_func() == Item_sum::COUNT_DISTINCT_FUNC || |
12409 | min_max_item->sum_func() == Item_sum::SUM_DISTINCT_FUNC || |
12410 | min_max_item->sum_func() == Item_sum::AVG_DISTINCT_FUNC)) |
12411 | continue; |
12412 | else |
12413 | DBUG_RETURN(NULL); |
12414 | |
12415 | /* The argument of MIN/MAX. */ |
12416 | Item *expr= min_max_item->get_arg(0)->real_item(); |
12417 | if (expr->type() == Item::FIELD_ITEM) /* Is it an attribute? */ |
12418 | { |
12419 | if (! min_max_arg_item) |
12420 | min_max_arg_item= (Item_field*) expr; |
12421 | else if (! min_max_arg_item->eq(expr, 1)) |
12422 | DBUG_RETURN(NULL); |
12423 | } |
12424 | else |
12425 | DBUG_RETURN(NULL); |
12426 | } |
12427 | } |
12428 | |
12429 | /* Check (SA7). */ |
12430 | if (is_agg_distinct && (have_max || have_min)) |
12431 | { |
12432 | DBUG_RETURN(NULL); |
12433 | } |
12434 | |
12435 | /* Check (SA5). */ |
12436 | if (join->select_distinct) |
12437 | { |
12438 | while ((item= select_items_it++)) |
12439 | { |
12440 | if (item->real_item()->type() != Item::FIELD_ITEM) |
12441 | DBUG_RETURN(NULL); |
12442 | } |
12443 | } |
12444 | |
12445 | /* Check (GA4) - that there are no expressions among the group attributes. */ |
12446 | elements_in_group= 0; |
12447 | for (tmp_group= join->group_list; tmp_group; tmp_group= tmp_group->next) |
12448 | { |
12449 | if ((*tmp_group->item)->real_item()->type() != Item::FIELD_ITEM) |
12450 | DBUG_RETURN(NULL); |
12451 | elements_in_group++; |
12452 | } |
12453 | |
12454 | /* |
12455 | Check that table has at least one compound index such that the conditions |
12456 | (GA1,GA2) are all TRUE. If there is more than one such index, select the |
12457 | first one. Here we set the variables: group_prefix_len and index_info. |
12458 | */ |
12459 | /* Cost-related variables for the best index so far. */ |
12460 | double best_read_cost= DBL_MAX; |
12461 | ha_rows best_records= 0; |
12462 | SEL_ARG *best_index_tree= NULL; |
12463 | ha_rows best_quick_prefix_records= 0; |
12464 | uint best_param_idx= 0; |
12465 | |
12466 | const uint pk= param->table->s->primary_key; |
12467 | uint max_key_part; |
12468 | SEL_ARG *cur_index_tree= NULL; |
12469 | ha_rows cur_quick_prefix_records= 0; |
12470 | |
12471 | // We go through allowed indexes |
12472 | for (uint cur_param_idx= 0; cur_param_idx < param->keys ; ++cur_param_idx) |
12473 | { |
12474 | const uint cur_index= param->real_keynr[cur_param_idx]; |
12475 | KEY *const cur_index_info= &table->key_info[cur_index]; |
12476 | KEY_PART_INFO *cur_part; |
12477 | KEY_PART_INFO *end_part; /* Last part for loops. */ |
12478 | /* Last index part. */ |
12479 | KEY_PART_INFO *last_part; |
12480 | KEY_PART_INFO *first_non_group_part; |
12481 | KEY_PART_INFO *first_non_infix_part; |
12482 | uint key_parts; |
12483 | uint key_infix_parts; |
12484 | uint cur_group_key_parts= 0; |
12485 | uint cur_group_prefix_len= 0; |
12486 | double cur_read_cost; |
12487 | ha_rows cur_records; |
12488 | key_map used_key_parts_map; |
12489 | uint cur_key_infix_len= 0; |
12490 | uchar cur_key_infix[MAX_KEY_LENGTH]; |
12491 | uint cur_used_key_parts; |
12492 | |
12493 | /* |
12494 | Check (B1) - if current index is covering. |
12495 | (was also: "Exclude UNIQUE indexes ..." but this was removed because |
12496 | there are cases Loose Scan over a multi-part index is useful). |
12497 | */ |
12498 | if (!table->covering_keys.is_set(cur_index) || |
12499 | !table->keys_in_use_for_group_by.is_set(cur_index)) |
12500 | continue; |
12501 | |
12502 | /* |
12503 | This function is called on the precondition that the index is covering. |
12504 | Therefore if the GROUP BY list contains more elements than the index, |
12505 | these are duplicates. The GROUP BY list cannot be a prefix of the index. |
12506 | */ |
12507 | if (elements_in_group > table->actual_n_key_parts(cur_index_info)) |
12508 | continue; |
12509 | |
12510 | /* |
12511 | Unless extended keys can be used for cur_index: |
12512 | If the current storage manager is such that it appends the primary key to |
12513 | each index, then the above condition is insufficient to check if the |
12514 | index is covering. In such cases it may happen that some fields are |
12515 | covered by the PK index, but not by the current index. Since we can't |
12516 | use the concatenation of both indexes for index lookup, such an index |
12517 | does not qualify as covering in our case. If this is the case, below |
12518 | we check that all query fields are indeed covered by 'cur_index'. |
12519 | */ |
12520 | if (cur_index_info->user_defined_key_parts == table->actual_n_key_parts(cur_index_info) |
12521 | && pk < MAX_KEY && cur_index != pk && |
12522 | (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX)) |
12523 | { |
12524 | /* For each table field */ |
12525 | for (uint i= 0; i < table->s->fields; i++) |
12526 | { |
12527 | Field *cur_field= table->field[i]; |
12528 | /* |
12529 | If the field is used in the current query ensure that it's |
12530 | part of 'cur_index' |
12531 | */ |
12532 | if (bitmap_is_set(table->read_set, cur_field->field_index) && |
12533 | !cur_field->part_of_key_not_clustered.is_set(cur_index)) |
12534 | goto next_index; // Field was not part of key |
12535 | } |
12536 | } |
12537 | |
12538 | max_key_part= 0; |
12539 | used_key_parts_map.clear_all(); |
12540 | |
12541 | /* |
12542 | Check (GA1) for GROUP BY queries. |
12543 | */ |
12544 | if (join->group_list) |
12545 | { |
12546 | cur_part= cur_index_info->key_part; |
12547 | end_part= cur_part + table->actual_n_key_parts(cur_index_info); |
12548 | /* Iterate in parallel over the GROUP list and the index parts. */ |
12549 | for (tmp_group= join->group_list; tmp_group && (cur_part != end_part); |
12550 | tmp_group= tmp_group->next, cur_part++) |
12551 | { |
12552 | /* |
12553 | TODO: |
12554 | tmp_group::item is an array of Item, is it OK to consider only the |
12555 | first Item? If so, then why? What is the array for? |
12556 | */ |
12557 | /* Above we already checked that all group items are fields. */ |
12558 | DBUG_ASSERT((*tmp_group->item)->real_item()->type() == Item::FIELD_ITEM); |
12559 | Item_field *group_field= (Item_field *) (*tmp_group->item)->real_item(); |
12560 | if (group_field->field->eq(cur_part->field)) |
12561 | { |
12562 | cur_group_prefix_len+= cur_part->store_length; |
12563 | ++cur_group_key_parts; |
12564 | max_key_part= (uint)(cur_part - cur_index_info->key_part) + 1; |
12565 | used_key_parts_map.set_bit(max_key_part); |
12566 | } |
12567 | else |
12568 | goto next_index; |
12569 | } |
12570 | } |
12571 | /* |
12572 | Check (GA2) if this is a DISTINCT query. |
12573 | If GA2, then Store a new ORDER object in group_fields_array at the |
12574 | position of the key part of item_field->field. Thus we get the ORDER |
12575 | objects for each field ordered as the corresponding key parts. |
12576 | Later group_fields_array of ORDER objects is used to convert the query |
12577 | to a GROUP query. |
12578 | */ |
12579 | if ((!join->group && join->select_distinct) || |
12580 | is_agg_distinct) |
12581 | { |
12582 | if (!is_agg_distinct) |
12583 | { |
12584 | select_items_it.rewind(); |
12585 | } |
12586 | |
12587 | List_iterator<Item_field> agg_distinct_flds_it (agg_distinct_flds); |
12588 | while (NULL != (item = (is_agg_distinct ? |
12589 | (Item *) agg_distinct_flds_it++ : select_items_it++))) |
12590 | { |
12591 | /* (SA5) already checked above. */ |
12592 | item_field= (Item_field*) item->real_item(); |
12593 | DBUG_ASSERT(item->real_item()->type() == Item::FIELD_ITEM); |
12594 | |
12595 | /* not doing loose index scan for derived tables */ |
12596 | if (!item_field->field) |
12597 | goto next_index; |
12598 | |
12599 | /* Find the order of the key part in the index. */ |
12600 | key_part_nr= get_field_keypart(cur_index_info, item_field->field); |
12601 | /* |
12602 | Check if this attribute was already present in the select list. |
12603 | If it was present, then its corresponding key part was alredy used. |
12604 | */ |
12605 | if (used_key_parts_map.is_set(key_part_nr)) |
12606 | continue; |
12607 | if (key_part_nr < 1 || |
12608 | (!is_agg_distinct && key_part_nr > join->fields_list.elements)) |
12609 | goto next_index; |
12610 | cur_part= cur_index_info->key_part + key_part_nr - 1; |
12611 | cur_group_prefix_len+= cur_part->store_length; |
12612 | used_key_parts_map.set_bit(key_part_nr); |
12613 | ++cur_group_key_parts; |
12614 | max_key_part= MY_MAX(max_key_part,key_part_nr); |
12615 | } |
12616 | /* |
12617 | Check that used key parts forms a prefix of the index. |
12618 | To check this we compare bits in all_parts and cur_parts. |
12619 | all_parts have all bits set from 0 to (max_key_part-1). |
12620 | cur_parts have bits set for only used keyparts. |
12621 | */ |
12622 | ulonglong all_parts, cur_parts; |
12623 | all_parts= (1ULL << max_key_part) - 1; |
12624 | cur_parts= used_key_parts_map.to_ulonglong() >> 1; |
12625 | if (all_parts != cur_parts) |
12626 | goto next_index; |
12627 | } |
12628 | |
12629 | /* Check (SA2). */ |
12630 | if (min_max_arg_item) |
12631 | { |
12632 | key_part_nr= get_field_keypart(cur_index_info, min_max_arg_item->field); |
12633 | if (key_part_nr <= cur_group_key_parts) |
12634 | goto next_index; |
12635 | min_max_arg_part= cur_index_info->key_part + key_part_nr - 1; |
12636 | } |
12637 | |
12638 | /* |
12639 | Aplly a heuristic: there is no point to use loose index scan when we're |
12640 | using the whole unique index. |
12641 | */ |
12642 | if (cur_index_info->flags & HA_NOSAME && |
12643 | cur_group_key_parts == cur_index_info->user_defined_key_parts) |
12644 | { |
12645 | goto next_index; |
12646 | } |
12647 | |
12648 | /* |
12649 | Check (NGA1, NGA2) and extract a sequence of constants to be used as part |
12650 | of all search keys. |
12651 | */ |
12652 | |
12653 | /* |
12654 | If there is MIN/MAX, each keypart between the last group part and the |
12655 | MIN/MAX part must participate in one equality with constants, and all |
12656 | keyparts after the MIN/MAX part must not be referenced in the query. |
12657 | |
12658 | If there is no MIN/MAX, the keyparts after the last group part can be |
12659 | referenced only in equalities with constants, and the referenced keyparts |
12660 | must form a sequence without any gaps that starts immediately after the |
12661 | last group keypart. |
12662 | */ |
12663 | key_parts= table->actual_n_key_parts(cur_index_info); |
12664 | last_part= cur_index_info->key_part + key_parts; |
12665 | first_non_group_part= (cur_group_key_parts < key_parts) ? |
12666 | cur_index_info->key_part + cur_group_key_parts : |
12667 | NULL; |
12668 | first_non_infix_part= min_max_arg_part ? |
12669 | (min_max_arg_part < last_part) ? |
12670 | min_max_arg_part : |
12671 | NULL : |
12672 | NULL; |
12673 | if (first_non_group_part && |
12674 | (!min_max_arg_part || (min_max_arg_part - first_non_group_part > 0))) |
12675 | { |
12676 | if (tree) |
12677 | { |
12678 | SEL_ARG *index_range_tree= tree->keys[cur_param_idx]; |
12679 | if (!get_constant_key_infix(cur_index_info, index_range_tree, |
12680 | first_non_group_part, min_max_arg_part, |
12681 | last_part, thd, cur_key_infix, |
12682 | &cur_key_infix_len, |
12683 | &first_non_infix_part)) |
12684 | goto next_index; |
12685 | } |
12686 | else if (min_max_arg_part && |
12687 | (min_max_arg_part - first_non_group_part > 0)) |
12688 | { |
12689 | /* |
12690 | There is a gap but no range tree, thus no predicates at all for the |
12691 | non-group keyparts. |
12692 | */ |
12693 | goto next_index; |
12694 | } |
12695 | else if (first_non_group_part && join->conds) |
12696 | { |
12697 | /* |
12698 | If there is no MIN/MAX function in the query, but some index |
12699 | key part is referenced in the WHERE clause, then this index |
12700 | cannot be used because the WHERE condition over the keypart's |
12701 | field cannot be 'pushed' to the index (because there is no |
12702 | range 'tree'), and the WHERE clause must be evaluated before |
12703 | GROUP BY/DISTINCT. |
12704 | */ |
12705 | /* |
12706 | Store the first and last keyparts that need to be analyzed |
12707 | into one array that can be passed as parameter. |
12708 | */ |
12709 | KEY_PART_INFO *key_part_range[2]; |
12710 | key_part_range[0]= first_non_group_part; |
12711 | key_part_range[1]= last_part; |
12712 | |
12713 | /* Check if cur_part is referenced in the WHERE clause. */ |
12714 | if (join->conds->walk(&Item::find_item_in_field_list_processor, 0, |
12715 | key_part_range)) |
12716 | goto next_index; |
12717 | } |
12718 | } |
12719 | |
12720 | /* |
12721 | Test (WA1) partially - that no other keypart after the last infix part is |
12722 | referenced in the query. |
12723 | */ |
12724 | if (first_non_infix_part) |
12725 | { |
12726 | cur_part= first_non_infix_part + |
12727 | (min_max_arg_part && (min_max_arg_part < last_part)); |
12728 | for (; cur_part != last_part; cur_part++) |
12729 | { |
12730 | if (bitmap_is_set(table->read_set, cur_part->field->field_index)) |
12731 | goto next_index; |
12732 | } |
12733 | } |
12734 | |
12735 | /** |
12736 | Test WA2:If there are conditions on a column C participating in |
12737 | MIN/MAX, those conditions must be conjunctions to all earlier |
12738 | keyparts. Otherwise, Loose Index Scan cannot be used. |
12739 | */ |
12740 | if (tree && min_max_arg_item) |
12741 | { |
12742 | SEL_ARG *index_range_tree= tree->keys[cur_param_idx]; |
12743 | SEL_ARG *cur_range= NULL; |
12744 | if (get_sel_arg_for_keypart(min_max_arg_part->field, |
12745 | index_range_tree, &cur_range) || |
12746 | (cur_range && cur_range->type != SEL_ARG::KEY_RANGE)) |
12747 | { |
12748 | goto next_index; |
12749 | } |
12750 | } |
12751 | |
12752 | /* If we got to this point, cur_index_info passes the test. */ |
12753 | key_infix_parts= cur_key_infix_len ? (uint) |
12754 | (first_non_infix_part - first_non_group_part) : 0; |
12755 | cur_used_key_parts= cur_group_key_parts + key_infix_parts; |
12756 | |
12757 | /* Compute the cost of using this index. */ |
12758 | if (tree) |
12759 | { |
12760 | cur_index_tree= tree->keys[cur_param_idx]; |
12761 | /* Check if this range tree can be used for prefix retrieval. */ |
12762 | Cost_estimate dummy_cost; |
12763 | uint mrr_flags= HA_MRR_USE_DEFAULT_IMPL; |
12764 | uint mrr_bufsize=0; |
12765 | cur_quick_prefix_records= check_quick_select(param, cur_param_idx, |
12766 | FALSE /*don't care*/, |
12767 | cur_index_tree, TRUE, |
12768 | &mrr_flags, &mrr_bufsize, |
12769 | &dummy_cost); |
12770 | } |
12771 | cost_group_min_max(table, cur_index_info, cur_used_key_parts, |
12772 | cur_group_key_parts, tree, cur_index_tree, |
12773 | cur_quick_prefix_records, have_min, have_max, |
12774 | &cur_read_cost, &cur_records); |
12775 | /* |
12776 | If cur_read_cost is lower than best_read_cost use cur_index. |
12777 | Do not compare doubles directly because they may have different |
12778 | representations (64 vs. 80 bits). |
12779 | */ |
12780 | if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost)) |
12781 | { |
12782 | index_info= cur_index_info; |
12783 | index= cur_index; |
12784 | best_read_cost= cur_read_cost; |
12785 | best_records= cur_records; |
12786 | best_index_tree= cur_index_tree; |
12787 | best_quick_prefix_records= cur_quick_prefix_records; |
12788 | best_param_idx= cur_param_idx; |
12789 | group_key_parts= cur_group_key_parts; |
12790 | group_prefix_len= cur_group_prefix_len; |
12791 | key_infix_len= cur_key_infix_len; |
12792 | if (key_infix_len) |
12793 | memcpy (key_infix, cur_key_infix, sizeof (key_infix)); |
12794 | used_key_parts= cur_used_key_parts; |
12795 | } |
12796 | |
12797 | next_index:; |
12798 | } |
12799 | if (!index_info) /* No usable index found. */ |
12800 | DBUG_RETURN(NULL); |
12801 | |
12802 | /* Check (SA3) for the where clause. */ |
12803 | bool has_min_max_fld= false, has_other_fld= false; |
12804 | if (join->conds && min_max_arg_item && |
12805 | !check_group_min_max_predicates(join->conds, min_max_arg_item, |
12806 | (index_info->flags & HA_SPATIAL) ? |
12807 | Field::itMBR : Field::itRAW, |
12808 | &has_min_max_fld, &has_other_fld)) |
12809 | DBUG_RETURN(NULL); |
12810 | |
12811 | /* |
12812 | Check (SA6) if clustered key is used |
12813 | */ |
12814 | if (is_agg_distinct && index == table->s->primary_key && |
12815 | table->file->primary_key_is_clustered()) |
12816 | DBUG_RETURN(NULL); |
12817 | |
12818 | /* The query passes all tests, so construct a new TRP object. */ |
12819 | read_plan= new (param->mem_root) |
12820 | TRP_GROUP_MIN_MAX(have_min, have_max, is_agg_distinct, |
12821 | min_max_arg_part, |
12822 | group_prefix_len, used_key_parts, |
12823 | group_key_parts, index_info, index, |
12824 | key_infix_len, |
12825 | (key_infix_len > 0) ? key_infix : NULL, |
12826 | tree, best_index_tree, best_param_idx, |
12827 | best_quick_prefix_records); |
12828 | if (read_plan) |
12829 | { |
12830 | if (tree && read_plan->quick_prefix_records == 0) |
12831 | DBUG_RETURN(NULL); |
12832 | |
12833 | read_plan->read_cost= best_read_cost; |
12834 | read_plan->records= best_records; |
12835 | if (read_time < best_read_cost && is_agg_distinct) |
12836 | { |
12837 | read_plan->read_cost= 0; |
12838 | read_plan->use_index_scan(); |
12839 | } |
12840 | |
12841 | DBUG_PRINT("info" , |
12842 | ("Returning group min/max plan: cost: %g, records: %lu" , |
12843 | read_plan->read_cost, (ulong) read_plan->records)); |
12844 | } |
12845 | |
12846 | DBUG_RETURN(read_plan); |
12847 | } |
12848 | |
12849 | |
12850 | /* |
12851 | Check that the MIN/MAX attribute participates only in range predicates |
12852 | with constants. |
12853 | |
12854 | SYNOPSIS |
12855 | check_group_min_max_predicates() |
12856 | cond [in] the expression tree being analyzed |
12857 | min_max_arg [in] the field referenced by the MIN/MAX function(s) |
12858 | image_type [in] |
12859 | has_min_max_arg [out] true if the subtree being analyzed references |
12860 | min_max_arg |
12861 | has_other_arg [out] true if the subtree being analyzed references a |
12862 | column other min_max_arg |
12863 | |
12864 | DESCRIPTION |
12865 | The function walks recursively over the cond tree representing a WHERE |
12866 | clause, and checks condition (SA3) - if a field is referenced by a MIN/MAX |
12867 | aggregate function, it is referenced only by one of the following |
12868 | predicates $FUNC$: |
12869 | {=, !=, <, <=, >, >=, between, is [not] null, multiple equal}. |
12870 | In addition the function checks that the WHERE condition is equivalent to |
12871 | "cond1 AND cond2" where : |
12872 | cond1 - does not use min_max_column at all. |
12873 | cond2 - is an AND/OR tree with leaves in form |
12874 | "$FUNC$(min_max_column[, const])". |
12875 | |
12876 | RETURN |
12877 | TRUE if cond passes the test |
12878 | FALSE o/w |
12879 | */ |
12880 | |
12881 | static bool |
12882 | check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item, |
12883 | Field::imagetype image_type, |
12884 | bool *has_min_max_arg, bool *has_other_arg) |
12885 | { |
12886 | DBUG_ENTER("check_group_min_max_predicates" ); |
12887 | DBUG_ASSERT(cond && min_max_arg_item); |
12888 | |
12889 | cond= cond->real_item(); |
12890 | Item::Type cond_type= cond->real_type(); |
12891 | if (cond_type == Item::COND_ITEM) /* 'AND' or 'OR' */ |
12892 | { |
12893 | DBUG_PRINT("info" , ("Analyzing: %s" , ((Item_func*) cond)->func_name())); |
12894 | List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list()); |
12895 | Item *and_or_arg; |
12896 | Item_func::Functype func_type= ((Item_cond*) cond)->functype(); |
12897 | bool has_min_max= false, has_other= false; |
12898 | while ((and_or_arg= li++)) |
12899 | { |
12900 | /* |
12901 | The WHERE clause doesn't pass the condition if: |
12902 | (1) any subtree doesn't pass the condition or |
12903 | (2) the subtree passes the test, but it is an OR and it references both |
12904 | the min/max argument and other columns. |
12905 | */ |
12906 | if (!check_group_min_max_predicates(and_or_arg, min_max_arg_item, //1 |
12907 | image_type, |
12908 | &has_min_max, &has_other) || |
12909 | (func_type == Item_func::COND_OR_FUNC && has_min_max && has_other))//2 |
12910 | DBUG_RETURN(FALSE); |
12911 | } |
12912 | *has_min_max_arg= has_min_max || *has_min_max_arg; |
12913 | *has_other_arg= has_other || *has_other_arg; |
12914 | DBUG_RETURN(TRUE); |
12915 | } |
12916 | |
12917 | /* |
12918 | Disallow loose index scan if the MIN/MAX argument field is referenced by |
12919 | a subquery in the WHERE clause. |
12920 | */ |
12921 | |
12922 | if (unlikely(cond_type == Item::SUBSELECT_ITEM)) |
12923 | { |
12924 | Item_subselect *subs_cond= (Item_subselect*) cond; |
12925 | if (subs_cond->is_correlated) |
12926 | { |
12927 | DBUG_ASSERT(subs_cond->upper_refs.elements > 0); |
12928 | List_iterator_fast<Item_subselect::Ref_to_outside> |
12929 | li(subs_cond->upper_refs); |
12930 | Item_subselect::Ref_to_outside *dep; |
12931 | while ((dep= li++)) |
12932 | { |
12933 | if (dep->item->eq(min_max_arg_item, FALSE)) |
12934 | DBUG_RETURN(FALSE); |
12935 | } |
12936 | } |
12937 | DBUG_RETURN(TRUE); |
12938 | } |
12939 | /* |
12940 | Subquery with IS [NOT] NULL |
12941 | TODO: Look into the cache_item and optimize it like we do for |
12942 | subselect's above |
12943 | */ |
12944 | if (unlikely(cond_type == Item::CACHE_ITEM)) |
12945 | DBUG_RETURN(cond->const_item()); |
12946 | |
12947 | /* |
12948 | Condition of the form 'field' is equivalent to 'field <> 0' and thus |
12949 | satisfies the SA3 condition. |
12950 | */ |
12951 | if (cond_type == Item::FIELD_ITEM) |
12952 | { |
12953 | DBUG_PRINT("info" , ("Analyzing: %s" , cond->full_name())); |
12954 | if (min_max_arg_item->eq((Item_field*)cond, 1)) |
12955 | *has_min_max_arg= true; |
12956 | else |
12957 | *has_other_arg= true; |
12958 | DBUG_RETURN(TRUE); |
12959 | } |
12960 | |
12961 | /* We presume that at this point there are no other Items than functions. */ |
12962 | DBUG_ASSERT(cond_type == Item::FUNC_ITEM); |
12963 | if (unlikely(cond_type != Item::FUNC_ITEM)) /* Safety */ |
12964 | DBUG_RETURN(FALSE); |
12965 | |
12966 | /* Test if cond references only group-by or non-group fields. */ |
12967 | Item_func *pred= (Item_func*) cond; |
12968 | Item_func::Functype pred_type= pred->functype(); |
12969 | DBUG_PRINT("info" , ("Analyzing: %s" , pred->func_name())); |
12970 | if (pred_type == Item_func::MULT_EQUAL_FUNC) |
12971 | { |
12972 | /* |
12973 | Check that each field in a multiple equality is either a constant or |
12974 | it is a reference to the min/max argument, or it doesn't contain the |
12975 | min/max argument at all. |
12976 | */ |
12977 | Item_equal_fields_iterator eq_it(*((Item_equal*)pred)); |
12978 | Item *eq_item; |
12979 | bool has_min_max= false, has_other= false; |
12980 | while ((eq_item= eq_it++)) |
12981 | { |
12982 | if (min_max_arg_item->eq(eq_item->real_item(), 1)) |
12983 | has_min_max= true; |
12984 | else |
12985 | has_other= true; |
12986 | } |
12987 | *has_min_max_arg= has_min_max || *has_min_max_arg; |
12988 | *has_other_arg= has_other || *has_other_arg; |
12989 | DBUG_RETURN(!(has_min_max && has_other)); |
12990 | } |
12991 | |
12992 | Item **arguments= pred->arguments(); |
12993 | Item *cur_arg; |
12994 | bool has_min_max= false, has_other= false; |
12995 | for (uint arg_idx= 0; arg_idx < pred->argument_count (); arg_idx++) |
12996 | { |
12997 | cur_arg= arguments[arg_idx]->real_item(); |
12998 | DBUG_PRINT("info" , ("cur_arg: %s" , cur_arg->full_name())); |
12999 | if (cur_arg->type() == Item::FIELD_ITEM) |
13000 | { |
13001 | if (min_max_arg_item->eq(cur_arg, 1)) |
13002 | { |
13003 | has_min_max= true; |
13004 | /* |
13005 | If pred references the MIN/MAX argument, check whether pred is a range |
13006 | condition that compares the MIN/MAX argument with a constant. |
13007 | */ |
13008 | if (pred_type != Item_func::EQUAL_FUNC && |
13009 | pred_type != Item_func::LT_FUNC && |
13010 | pred_type != Item_func::LE_FUNC && |
13011 | pred_type != Item_func::GT_FUNC && |
13012 | pred_type != Item_func::GE_FUNC && |
13013 | pred_type != Item_func::BETWEEN && |
13014 | pred_type != Item_func::ISNULL_FUNC && |
13015 | pred_type != Item_func::ISNOTNULL_FUNC && |
13016 | pred_type != Item_func::EQ_FUNC && |
13017 | pred_type != Item_func::NE_FUNC) |
13018 | DBUG_RETURN(FALSE); |
13019 | |
13020 | /* Check that pred compares min_max_arg_item with a constant. */ |
13021 | Item *args[3]; |
13022 | bzero(args, 3 * sizeof(Item*)); |
13023 | bool inv; |
13024 | /* Test if this is a comparison of a field and a constant. */ |
13025 | if (!simple_pred(pred, args, &inv)) |
13026 | DBUG_RETURN(FALSE); |
13027 | |
13028 | if (args[0] && args[1]) // this is a binary function or BETWEEN |
13029 | { |
13030 | DBUG_ASSERT(pred->is_bool_type()); |
13031 | Item_bool_func *bool_func= (Item_bool_func*) pred; |
13032 | Field *field= min_max_arg_item->field; |
13033 | if (!args[2]) // this is a binary function |
13034 | { |
13035 | if (!field->can_optimize_group_min_max(bool_func, args[1])) |
13036 | DBUG_RETURN(FALSE); |
13037 | } |
13038 | else // this is BETWEEN |
13039 | { |
13040 | if (!field->can_optimize_group_min_max(bool_func, args[1]) || |
13041 | !field->can_optimize_group_min_max(bool_func, args[2])) |
13042 | DBUG_RETURN(FALSE); |
13043 | } |
13044 | } |
13045 | } |
13046 | else |
13047 | has_other= true; |
13048 | } |
13049 | else if (cur_arg->type() == Item::FUNC_ITEM) |
13050 | { |
13051 | if (!check_group_min_max_predicates(cur_arg, min_max_arg_item, image_type, |
13052 | &has_min_max, &has_other)) |
13053 | DBUG_RETURN(FALSE); |
13054 | } |
13055 | else if (cur_arg->const_item() && !cur_arg->is_expensive()) |
13056 | { |
13057 | /* |
13058 | For predicates of the form "const OP expr" we also have to check 'expr' |
13059 | to make a decision. |
13060 | */ |
13061 | continue; |
13062 | } |
13063 | else |
13064 | DBUG_RETURN(FALSE); |
13065 | if(has_min_max && has_other) |
13066 | DBUG_RETURN(FALSE); |
13067 | } |
13068 | *has_min_max_arg= has_min_max || *has_min_max_arg; |
13069 | *has_other_arg= has_other || *has_other_arg; |
13070 | |
13071 | DBUG_RETURN(TRUE); |
13072 | } |
13073 | |
13074 | |
13075 | /* |
13076 | Get the SEL_ARG tree 'tree' for the keypart covering 'field', if |
13077 | any. 'tree' must be a unique conjunction to ALL predicates in earlier |
13078 | keyparts of 'keypart_tree'. |
13079 | |
13080 | E.g., if 'keypart_tree' is for a composite index (kp1,kp2) and kp2 |
13081 | covers 'field', all these conditions satisfies the requirement: |
13082 | |
13083 | 1. "(kp1=2 OR kp1=3) AND kp2=10" => returns "kp2=10" |
13084 | 2. "(kp1=2 AND kp2=10) OR (kp1=3 AND kp2=10)" => returns "kp2=10" |
13085 | 3. "(kp1=2 AND (kp2=10 OR kp2=11)) OR (kp1=3 AND (kp2=10 OR kp2=11))" |
13086 | => returns "kp2=10 OR kp2=11" |
13087 | |
13088 | whereas these do not |
13089 | 1. "(kp1=2 AND kp2=10) OR kp1=3" |
13090 | 2. "(kp1=2 AND kp2=10) OR (kp1=3 AND kp2=11)" |
13091 | 3. "(kp1=2 AND kp2=10) OR (kp1=3 AND (kp2=10 OR kp2=11))" |
13092 | |
13093 | This function effectively tests requirement WA2. In combination with |
13094 | a test that the returned tree has no more than one range it is also |
13095 | a test of NGA3. |
13096 | |
13097 | @param[in] field The field we want the SEL_ARG tree for |
13098 | @param[in] keypart_tree Root node of the SEL_ARG* tree for the index |
13099 | @param[out] cur_range The SEL_ARG tree, if any, for the keypart |
13100 | covering field 'keypart_field' |
13101 | @retval true 'keypart_tree' contained a predicate for 'field' that |
13102 | is not conjunction to all predicates on earlier keyparts |
13103 | @retval false otherwise |
13104 | */ |
13105 | |
13106 | static bool |
13107 | get_sel_arg_for_keypart(Field *field, |
13108 | SEL_ARG *keypart_tree, |
13109 | SEL_ARG **cur_range) |
13110 | { |
13111 | if (keypart_tree == NULL) |
13112 | return false; |
13113 | if (keypart_tree->field->eq(field)) |
13114 | { |
13115 | *cur_range= keypart_tree; |
13116 | return false; |
13117 | } |
13118 | |
13119 | SEL_ARG *tree_first_range= NULL; |
13120 | SEL_ARG *first_kp= keypart_tree->first(); |
13121 | |
13122 | for (SEL_ARG *cur_kp= first_kp; cur_kp; cur_kp= cur_kp->next) |
13123 | { |
13124 | SEL_ARG *curr_tree= NULL; |
13125 | if (cur_kp->next_key_part) |
13126 | { |
13127 | if (get_sel_arg_for_keypart(field, |
13128 | cur_kp->next_key_part, |
13129 | &curr_tree)) |
13130 | return true; |
13131 | } |
13132 | /* |
13133 | Check if the SEL_ARG tree for 'field' is identical for all ranges in |
13134 | 'keypart_tree |
13135 | */ |
13136 | if (cur_kp == first_kp) |
13137 | tree_first_range= curr_tree; |
13138 | else if (!all_same(tree_first_range, curr_tree)) |
13139 | return true; |
13140 | } |
13141 | *cur_range= tree_first_range; |
13142 | return false; |
13143 | } |
13144 | |
13145 | /* |
13146 | Extract a sequence of constants from a conjunction of equality predicates. |
13147 | |
13148 | SYNOPSIS |
13149 | get_constant_key_infix() |
13150 | index_info [in] Descriptor of the chosen index. |
13151 | index_range_tree [in] Range tree for the chosen index |
13152 | first_non_group_part [in] First index part after group attribute parts |
13153 | min_max_arg_part [in] The keypart of the MIN/MAX argument if any |
13154 | last_part [in] Last keypart of the index |
13155 | thd [in] Current thread |
13156 | key_infix [out] Infix of constants to be used for index lookup |
13157 | key_infix_len [out] Lenghth of the infix |
13158 | first_non_infix_part [out] The first keypart after the infix (if any) |
13159 | |
13160 | DESCRIPTION |
13161 | Test conditions (NGA1, NGA2, NGA3) from get_best_group_min_max(). Namely, |
13162 | for each keypart field NG_i not in GROUP-BY, check that there is exactly one |
13163 | constant equality predicate among conds with the form (NG_i = const_ci) or |
13164 | (const_ci = NG_i).. In addition, there can only be one range when there is |
13165 | such a gap. |
13166 | Thus all the NGF_i attributes must fill the 'gap' between the last group-by |
13167 | attribute and the MIN/MAX attribute in the index (if present). Also ensure |
13168 | that there is only a single range on NGF_i (NGA3). If these |
13169 | conditions hold, copy each constant from its corresponding predicate into |
13170 | key_infix, in the order its NG_i attribute appears in the index, and update |
13171 | key_infix_len with the total length of the key parts in key_infix. |
13172 | |
13173 | RETURN |
13174 | TRUE if the index passes the test |
13175 | FALSE o/w |
13176 | */ |
13177 | static bool |
13178 | get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree, |
13179 | KEY_PART_INFO *first_non_group_part, |
13180 | KEY_PART_INFO *min_max_arg_part, |
13181 | KEY_PART_INFO *last_part, THD *thd, |
13182 | uchar *key_infix, uint *key_infix_len, |
13183 | KEY_PART_INFO **first_non_infix_part) |
13184 | { |
13185 | SEL_ARG *cur_range; |
13186 | KEY_PART_INFO *cur_part; |
13187 | /* End part for the first loop below. */ |
13188 | KEY_PART_INFO *end_part= min_max_arg_part ? min_max_arg_part : last_part; |
13189 | |
13190 | *key_infix_len= 0; |
13191 | uchar *key_ptr= key_infix; |
13192 | for (cur_part= first_non_group_part; cur_part != end_part; cur_part++) |
13193 | { |
13194 | cur_range= NULL; |
13195 | /* |
13196 | Check NGA3: |
13197 | 1. get_sel_arg_for_keypart gets the range tree for the 'field' and also |
13198 | checks for a unique conjunction of this tree with all the predicates |
13199 | on the earlier keyparts in the index. |
13200 | 2. Check for multiple ranges on the found keypart tree. |
13201 | |
13202 | We assume that index_range_tree points to the leftmost keypart in |
13203 | the index. |
13204 | */ |
13205 | if (get_sel_arg_for_keypart(cur_part->field, index_range_tree, |
13206 | &cur_range)) |
13207 | return false; |
13208 | |
13209 | if (cur_range && cur_range->elements > 1) |
13210 | return false; |
13211 | |
13212 | if (!cur_range || cur_range->type != SEL_ARG::KEY_RANGE) |
13213 | { |
13214 | if (min_max_arg_part) |
13215 | return false; /* The current keypart has no range predicates at all. */ |
13216 | else |
13217 | { |
13218 | *first_non_infix_part= cur_part; |
13219 | return true; |
13220 | } |
13221 | } |
13222 | |
13223 | if ((cur_range->min_flag & NO_MIN_RANGE) || |
13224 | (cur_range->max_flag & NO_MAX_RANGE) || |
13225 | (cur_range->min_flag & NEAR_MIN) || (cur_range->max_flag & NEAR_MAX)) |
13226 | return false; |
13227 | |
13228 | uint field_length= cur_part->store_length; |
13229 | if (cur_range->maybe_null && |
13230 | cur_range->min_value[0] && cur_range->max_value[0]) |
13231 | { |
13232 | /* |
13233 | cur_range specifies 'IS NULL'. In this case the argument points |
13234 | to a "null value" (is_null_string) that may not always be long |
13235 | enough for a direct memcpy to a field. |
13236 | */ |
13237 | DBUG_ASSERT (field_length > 0); |
13238 | *key_ptr= 1; |
13239 | bzero(key_ptr+1,field_length-1); |
13240 | key_ptr+= field_length; |
13241 | *key_infix_len+= field_length; |
13242 | } |
13243 | else if (memcmp(cur_range->min_value, cur_range->max_value, field_length) == 0) |
13244 | { /* cur_range specifies an equality condition. */ |
13245 | memcpy(key_ptr, cur_range->min_value, field_length); |
13246 | key_ptr+= field_length; |
13247 | *key_infix_len+= field_length; |
13248 | } |
13249 | else |
13250 | return false; |
13251 | } |
13252 | |
13253 | if (!min_max_arg_part && (cur_part == last_part)) |
13254 | *first_non_infix_part= last_part; |
13255 | |
13256 | return TRUE; |
13257 | } |
13258 | |
13259 | |
13260 | /* |
13261 | Find the key part referenced by a field. |
13262 | |
13263 | SYNOPSIS |
13264 | get_field_keypart() |
13265 | index descriptor of an index |
13266 | field field that possibly references some key part in index |
13267 | |
13268 | NOTES |
13269 | The return value can be used to get a KEY_PART_INFO pointer by |
13270 | part= index->key_part + get_field_keypart(...) - 1; |
13271 | |
13272 | RETURN |
13273 | Positive number which is the consecutive number of the key part, or |
13274 | 0 if field does not reference any index field. |
13275 | */ |
13276 | |
13277 | static inline uint |
13278 | get_field_keypart(KEY *index, Field *field) |
13279 | { |
13280 | KEY_PART_INFO *part, *end; |
13281 | |
13282 | for (part= index->key_part, |
13283 | end= part + field->table->actual_n_key_parts(index); |
13284 | part < end; part++) |
13285 | { |
13286 | if (field->eq(part->field)) |
13287 | return (uint)(part - index->key_part + 1); |
13288 | } |
13289 | return 0; |
13290 | } |
13291 | |
13292 | |
13293 | /* |
13294 | Compute the cost of a quick_group_min_max_select for a particular index. |
13295 | |
13296 | SYNOPSIS |
13297 | cost_group_min_max() |
13298 | table [in] The table being accessed |
13299 | index_info [in] The index used to access the table |
13300 | used_key_parts [in] Number of key parts used to access the index |
13301 | group_key_parts [in] Number of index key parts in the group prefix |
13302 | range_tree [in] Tree of ranges for all indexes |
13303 | index_tree [in] The range tree for the current index |
13304 | quick_prefix_records [in] Number of records retrieved by the internally |
13305 | used quick range select if any |
13306 | have_min [in] True if there is a MIN function |
13307 | have_max [in] True if there is a MAX function |
13308 | read_cost [out] The cost to retrieve rows via this quick select |
13309 | records [out] The number of rows retrieved |
13310 | |
13311 | DESCRIPTION |
13312 | This method computes the access cost of a TRP_GROUP_MIN_MAX instance and |
13313 | the number of rows returned. |
13314 | |
13315 | NOTES |
13316 | The cost computation distinguishes several cases: |
13317 | 1) No equality predicates over non-group attributes (thus no key_infix). |
13318 | If groups are bigger than blocks on the average, then we assume that it |
13319 | is very unlikely that block ends are aligned with group ends, thus even |
13320 | if we look for both MIN and MAX keys, all pairs of neighbor MIN/MAX |
13321 | keys, except for the first MIN and the last MAX keys, will be in the |
13322 | same block. If groups are smaller than blocks, then we are going to |
13323 | read all blocks. |
13324 | 2) There are equality predicates over non-group attributes. |
13325 | In this case the group prefix is extended by additional constants, and |
13326 | as a result the min/max values are inside sub-groups of the original |
13327 | groups. The number of blocks that will be read depends on whether the |
13328 | ends of these sub-groups will be contained in the same or in different |
13329 | blocks. We compute the probability for the two ends of a subgroup to be |
13330 | in two different blocks as the ratio of: |
13331 | - the number of positions of the left-end of a subgroup inside a group, |
13332 | such that the right end of the subgroup is past the end of the buffer |
13333 | containing the left-end, and |
13334 | - the total number of possible positions for the left-end of the |
13335 | subgroup, which is the number of keys in the containing group. |
13336 | We assume it is very unlikely that two ends of subsequent subgroups are |
13337 | in the same block. |
13338 | 3) The are range predicates over the group attributes. |
13339 | Then some groups may be filtered by the range predicates. We use the |
13340 | selectivity of the range predicates to decide how many groups will be |
13341 | filtered. |
13342 | |
13343 | TODO |
13344 | - Take into account the optional range predicates over the MIN/MAX |
13345 | argument. |
13346 | - Check if we have a PK index and we use all cols - then each key is a |
13347 | group, and it will be better to use an index scan. |
13348 | |
13349 | RETURN |
13350 | None |
13351 | */ |
13352 | |
13353 | void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, |
13354 | uint group_key_parts, SEL_TREE *range_tree, |
13355 | SEL_ARG *index_tree, ha_rows quick_prefix_records, |
13356 | bool have_min, bool have_max, |
13357 | double *read_cost, ha_rows *records) |
13358 | { |
13359 | ha_rows table_records; |
13360 | ha_rows num_groups; |
13361 | ha_rows num_blocks; |
13362 | uint keys_per_block; |
13363 | ha_rows keys_per_group; |
13364 | ha_rows keys_per_subgroup; /* Average number of keys in sub-groups */ |
13365 | /* formed by a key infix. */ |
13366 | double p_overlap; /* Probability that a sub-group overlaps two blocks. */ |
13367 | double quick_prefix_selectivity; |
13368 | double io_cost; |
13369 | DBUG_ENTER("cost_group_min_max" ); |
13370 | |
13371 | table_records= table->stat_records(); |
13372 | keys_per_block= (uint) (table->file->stats.block_size / 2 / |
13373 | (index_info->key_length + table->file->ref_length) |
13374 | + 1); |
13375 | num_blocks= (ha_rows)(table_records / keys_per_block) + 1; |
13376 | |
13377 | /* Compute the number of keys in a group. */ |
13378 | if (!group_key_parts) |
13379 | { |
13380 | /* Summary over the whole table */ |
13381 | keys_per_group= table_records; |
13382 | } |
13383 | else |
13384 | { |
13385 | keys_per_group= (ha_rows) index_info->actual_rec_per_key(group_key_parts - |
13386 | 1); |
13387 | } |
13388 | |
13389 | if (keys_per_group == 0) /* If there is no statistics try to guess */ |
13390 | /* each group contains 10% of all records */ |
13391 | keys_per_group= (table_records / 10) + 1; |
13392 | num_groups= (table_records / keys_per_group) + 1; |
13393 | |
13394 | /* Apply the selectivity of the quick select for group prefixes. */ |
13395 | if (range_tree && (quick_prefix_records != HA_POS_ERROR)) |
13396 | { |
13397 | quick_prefix_selectivity= (double) quick_prefix_records / |
13398 | (double) table_records; |
13399 | num_groups= (ha_rows) rint(num_groups * quick_prefix_selectivity); |
13400 | set_if_bigger(num_groups, 1); |
13401 | } |
13402 | |
13403 | if (used_key_parts > group_key_parts) |
13404 | { /* |
13405 | Compute the probability that two ends of a subgroup are inside |
13406 | different blocks. |
13407 | */ |
13408 | keys_per_subgroup= (ha_rows) index_info->actual_rec_per_key(used_key_parts - 1); |
13409 | if (keys_per_subgroup >= keys_per_block) /* If a subgroup is bigger than */ |
13410 | p_overlap= 1.0; /* a block, it will overlap at least two blocks. */ |
13411 | else |
13412 | { |
13413 | double blocks_per_group= (double) num_blocks / (double) num_groups; |
13414 | p_overlap= (blocks_per_group * (keys_per_subgroup - 1)) / keys_per_group; |
13415 | p_overlap= MY_MIN(p_overlap, 1.0); |
13416 | } |
13417 | io_cost= (double) MY_MIN(num_groups * (1 + p_overlap), num_blocks); |
13418 | } |
13419 | else |
13420 | io_cost= (keys_per_group > keys_per_block) ? |
13421 | (have_min && have_max) ? (double) (num_groups + 1) : |
13422 | (double) num_groups : |
13423 | (double) num_blocks; |
13424 | |
13425 | /* |
13426 | CPU cost must be comparable to that of an index scan as computed |
13427 | in SQL_SELECT::test_quick_select(). When the groups are small, |
13428 | e.g. for a unique index, using index scan will be cheaper since it |
13429 | reads the next record without having to re-position to it on every |
13430 | group. To make the CPU cost reflect this, we estimate the CPU cost |
13431 | as the sum of: |
13432 | 1. Cost for evaluating the condition (similarly as for index scan). |
13433 | 2. Cost for navigating the index structure (assuming a b-tree). |
13434 | Note: We only add the cost for one comparision per block. For a |
13435 | b-tree the number of comparisons will be larger. |
13436 | TODO: This cost should be provided by the storage engine. |
13437 | */ |
13438 | const double tree_traversal_cost= |
13439 | ceil(log(static_cast<double>(table_records))/ |
13440 | log(static_cast<double>(keys_per_block))) * |
13441 | 1/double(2*TIME_FOR_COMPARE); |
13442 | |
13443 | const double cpu_cost= num_groups * |
13444 | (tree_traversal_cost + 1/double(TIME_FOR_COMPARE)); |
13445 | |
13446 | *read_cost= io_cost + cpu_cost; |
13447 | *records= num_groups; |
13448 | |
13449 | DBUG_PRINT("info" , |
13450 | ("table rows: %lu keys/block: %u keys/group: %lu result rows: %lu blocks: %lu" , |
13451 | (ulong)table_records, keys_per_block, (ulong) keys_per_group, |
13452 | (ulong) *records, (ulong) num_blocks)); |
13453 | DBUG_VOID_RETURN; |
13454 | } |
13455 | |
13456 | |
13457 | /* |
13458 | Construct a new quick select object for queries with group by with min/max. |
13459 | |
13460 | SYNOPSIS |
13461 | TRP_GROUP_MIN_MAX::make_quick() |
13462 | param Parameter from test_quick_select |
13463 | retrieve_full_rows ignored |
13464 | parent_alloc Memory pool to use, if any. |
13465 | |
13466 | NOTES |
13467 | Make_quick ignores the retrieve_full_rows parameter because |
13468 | QUICK_GROUP_MIN_MAX_SELECT always performs 'index only' scans. |
13469 | The other parameter are ignored as well because all necessary |
13470 | data to create the QUICK object is computed at this TRP creation |
13471 | time. |
13472 | |
13473 | RETURN |
13474 | New QUICK_GROUP_MIN_MAX_SELECT object if successfully created, |
13475 | NULL otherwise. |
13476 | */ |
13477 | |
13478 | QUICK_SELECT_I * |
13479 | TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows, |
13480 | MEM_ROOT *parent_alloc) |
13481 | { |
13482 | QUICK_GROUP_MIN_MAX_SELECT *quick; |
13483 | DBUG_ENTER("TRP_GROUP_MIN_MAX::make_quick" ); |
13484 | |
13485 | quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table, |
13486 | param->thd->lex->current_select->join, |
13487 | have_min, have_max, |
13488 | have_agg_distinct, min_max_arg_part, |
13489 | group_prefix_len, group_key_parts, |
13490 | used_key_parts, index_info, index, |
13491 | read_cost, records, key_infix_len, |
13492 | key_infix, parent_alloc, is_index_scan); |
13493 | if (!quick) |
13494 | DBUG_RETURN(NULL); |
13495 | |
13496 | if (quick->init()) |
13497 | { |
13498 | delete quick; |
13499 | DBUG_RETURN(NULL); |
13500 | } |
13501 | |
13502 | if (range_tree) |
13503 | { |
13504 | DBUG_ASSERT(quick_prefix_records > 0); |
13505 | if (quick_prefix_records == HA_POS_ERROR) |
13506 | quick->quick_prefix_select= NULL; /* Can't construct a quick select. */ |
13507 | else |
13508 | /* Make a QUICK_RANGE_SELECT to be used for group prefix retrieval. */ |
13509 | quick->quick_prefix_select= get_quick_select(param, param_idx, |
13510 | index_tree, |
13511 | HA_MRR_USE_DEFAULT_IMPL, 0, |
13512 | &quick->alloc); |
13513 | |
13514 | /* |
13515 | Extract the SEL_ARG subtree that contains only ranges for the MIN/MAX |
13516 | attribute, and create an array of QUICK_RANGES to be used by the |
13517 | new quick select. |
13518 | */ |
13519 | if (min_max_arg_part) |
13520 | { |
13521 | SEL_ARG *min_max_range= index_tree; |
13522 | while (min_max_range) /* Find the tree for the MIN/MAX key part. */ |
13523 | { |
13524 | if (min_max_range->field->eq(min_max_arg_part->field)) |
13525 | break; |
13526 | min_max_range= min_max_range->next_key_part; |
13527 | } |
13528 | /* Scroll to the leftmost interval for the MIN/MAX argument. */ |
13529 | while (min_max_range && min_max_range->prev) |
13530 | min_max_range= min_max_range->prev; |
13531 | /* Create an array of QUICK_RANGEs for the MIN/MAX argument. */ |
13532 | while (min_max_range) |
13533 | { |
13534 | if (quick->add_range(min_max_range)) |
13535 | { |
13536 | delete quick; |
13537 | quick= NULL; |
13538 | DBUG_RETURN(NULL); |
13539 | } |
13540 | min_max_range= min_max_range->next; |
13541 | } |
13542 | } |
13543 | } |
13544 | else |
13545 | quick->quick_prefix_select= NULL; |
13546 | |
13547 | quick->update_key_stat(); |
13548 | quick->adjust_prefix_ranges(); |
13549 | |
13550 | DBUG_RETURN(quick); |
13551 | } |
13552 | |
13553 | |
13554 | /* |
13555 | Construct new quick select for group queries with min/max. |
13556 | |
13557 | SYNOPSIS |
13558 | QUICK_GROUP_MIN_MAX_SELECT::QUICK_GROUP_MIN_MAX_SELECT() |
13559 | table The table being accessed |
13560 | join Descriptor of the current query |
13561 | have_min TRUE if the query selects a MIN function |
13562 | have_max TRUE if the query selects a MAX function |
13563 | min_max_arg_part The only argument field of all MIN/MAX functions |
13564 | group_prefix_len Length of all key parts in the group prefix |
13565 | prefix_key_parts All key parts in the group prefix |
13566 | index_info The index chosen for data access |
13567 | use_index The id of index_info |
13568 | read_cost Cost of this access method |
13569 | records Number of records returned |
13570 | key_infix_len Length of the key infix appended to the group prefix |
13571 | key_infix Infix of constants from equality predicates |
13572 | parent_alloc Memory pool for this and quick_prefix_select data |
13573 | is_index_scan get the next different key not by jumping on it via |
13574 | index read, but by scanning until the end of the |
13575 | rows with equal key value. |
13576 | |
13577 | RETURN |
13578 | None |
13579 | */ |
13580 | |
13581 | QUICK_GROUP_MIN_MAX_SELECT:: |
13582 | QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg, |
13583 | bool have_max_arg, bool have_agg_distinct_arg, |
13584 | KEY_PART_INFO *min_max_arg_part_arg, |
13585 | uint group_prefix_len_arg, uint group_key_parts_arg, |
13586 | uint used_key_parts_arg, KEY *index_info_arg, |
13587 | uint use_index, double read_cost_arg, |
13588 | ha_rows records_arg, uint key_infix_len_arg, |
13589 | uchar *key_infix_arg, MEM_ROOT *parent_alloc, |
13590 | bool is_index_scan_arg) |
13591 | :file(table->file), join(join_arg), index_info(index_info_arg), |
13592 | group_prefix_len(group_prefix_len_arg), |
13593 | group_key_parts(group_key_parts_arg), have_min(have_min_arg), |
13594 | have_max(have_max_arg), have_agg_distinct(have_agg_distinct_arg), |
13595 | seen_first_key(FALSE), min_max_arg_part(min_max_arg_part_arg), |
13596 | key_infix(key_infix_arg), key_infix_len(key_infix_len_arg), |
13597 | min_functions_it(NULL), max_functions_it(NULL), |
13598 | is_index_scan(is_index_scan_arg) |
13599 | { |
13600 | head= table; |
13601 | index= use_index; |
13602 | record= head->record[0]; |
13603 | tmp_record= head->record[1]; |
13604 | read_time= read_cost_arg; |
13605 | records= records_arg; |
13606 | used_key_parts= used_key_parts_arg; |
13607 | real_key_parts= used_key_parts_arg; |
13608 | real_prefix_len= group_prefix_len + key_infix_len; |
13609 | group_prefix= NULL; |
13610 | min_max_arg_len= min_max_arg_part ? min_max_arg_part->store_length : 0; |
13611 | |
13612 | /* |
13613 | We can't have parent_alloc set as the init function can't handle this case |
13614 | yet. |
13615 | */ |
13616 | DBUG_ASSERT(!parent_alloc); |
13617 | if (!parent_alloc) |
13618 | { |
13619 | init_sql_alloc(&alloc, "QUICK_GROUP_MIN_MAX_SELECT" , |
13620 | join->thd->variables.range_alloc_block_size, 0, |
13621 | MYF(MY_THREAD_SPECIFIC)); |
13622 | join->thd->mem_root= &alloc; |
13623 | } |
13624 | else |
13625 | bzero(&alloc, sizeof(MEM_ROOT)); // ensure that it's not used |
13626 | } |
13627 | |
13628 | |
13629 | /* |
13630 | Do post-constructor initialization. |
13631 | |
13632 | SYNOPSIS |
13633 | QUICK_GROUP_MIN_MAX_SELECT::init() |
13634 | |
13635 | DESCRIPTION |
13636 | The method performs initialization that cannot be done in the constructor |
13637 | such as memory allocations that may fail. It allocates memory for the |
13638 | group prefix and inifix buffers, and for the lists of MIN/MAX item to be |
13639 | updated during execution. |
13640 | |
13641 | RETURN |
13642 | 0 OK |
13643 | other Error code |
13644 | */ |
13645 | |
13646 | int QUICK_GROUP_MIN_MAX_SELECT::init() |
13647 | { |
13648 | if (group_prefix) /* Already initialized. */ |
13649 | return 0; |
13650 | |
13651 | /* |
13652 | We allocate one byte more to serve the case when the last field in |
13653 | the buffer is compared using uint3korr (e.g. a Field_newdate field) |
13654 | */ |
13655 | if (!(last_prefix= (uchar*) alloc_root(&alloc, group_prefix_len+1))) |
13656 | return 1; |
13657 | /* |
13658 | We may use group_prefix to store keys with all select fields, so allocate |
13659 | enough space for it. |
13660 | We allocate one byte more to serve the case when the last field in |
13661 | the buffer is compared using uint3korr (e.g. a Field_newdate field) |
13662 | */ |
13663 | if (!(group_prefix= (uchar*) alloc_root(&alloc, |
13664 | real_prefix_len+min_max_arg_len+1))) |
13665 | return 1; |
13666 | |
13667 | if (key_infix_len > 0) |
13668 | { |
13669 | /* |
13670 | The memory location pointed to by key_infix will be deleted soon, so |
13671 | allocate a new buffer and copy the key_infix into it. |
13672 | */ |
13673 | uchar *tmp_key_infix= (uchar*) alloc_root(&alloc, key_infix_len); |
13674 | if (!tmp_key_infix) |
13675 | return 1; |
13676 | memcpy(tmp_key_infix, this->key_infix, key_infix_len); |
13677 | this->key_infix= tmp_key_infix; |
13678 | } |
13679 | |
13680 | if (min_max_arg_part) |
13681 | { |
13682 | if (my_init_dynamic_array(&min_max_ranges, sizeof(QUICK_RANGE*), 16, 16, |
13683 | MYF(MY_THREAD_SPECIFIC))) |
13684 | return 1; |
13685 | |
13686 | if (have_min) |
13687 | { |
13688 | if (!(min_functions= new List<Item_sum>)) |
13689 | return 1; |
13690 | } |
13691 | else |
13692 | min_functions= NULL; |
13693 | if (have_max) |
13694 | { |
13695 | if (!(max_functions= new List<Item_sum>)) |
13696 | return 1; |
13697 | } |
13698 | else |
13699 | max_functions= NULL; |
13700 | |
13701 | Item_sum *min_max_item; |
13702 | Item_sum **func_ptr= join->sum_funcs; |
13703 | while ((min_max_item= *(func_ptr++))) |
13704 | { |
13705 | if (have_min && (min_max_item->sum_func() == Item_sum::MIN_FUNC)) |
13706 | min_functions->push_back(min_max_item); |
13707 | else if (have_max && (min_max_item->sum_func() == Item_sum::MAX_FUNC)) |
13708 | max_functions->push_back(min_max_item); |
13709 | } |
13710 | |
13711 | if (have_min) |
13712 | { |
13713 | if (!(min_functions_it= new List_iterator<Item_sum>(*min_functions))) |
13714 | return 1; |
13715 | } |
13716 | |
13717 | if (have_max) |
13718 | { |
13719 | if (!(max_functions_it= new List_iterator<Item_sum>(*max_functions))) |
13720 | return 1; |
13721 | } |
13722 | } |
13723 | else |
13724 | min_max_ranges.elements= 0; |
13725 | |
13726 | return 0; |
13727 | } |
13728 | |
13729 | |
13730 | QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT() |
13731 | { |
13732 | DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT" ); |
13733 | if (file->inited != handler::NONE) |
13734 | { |
13735 | DBUG_ASSERT(file == head->file); |
13736 | head->file->ha_end_keyread(); |
13737 | /* |
13738 | There may be a code path when the same table was first accessed by index, |
13739 | then the index is closed, and the table is scanned (order by + loose scan). |
13740 | */ |
13741 | file->ha_index_or_rnd_end(); |
13742 | } |
13743 | if (min_max_arg_part) |
13744 | delete_dynamic(&min_max_ranges); |
13745 | free_root(&alloc,MYF(0)); |
13746 | delete min_functions_it; |
13747 | delete max_functions_it; |
13748 | delete quick_prefix_select; |
13749 | DBUG_VOID_RETURN; |
13750 | } |
13751 | |
13752 | |
13753 | /* |
13754 | Eventually create and add a new quick range object. |
13755 | |
13756 | SYNOPSIS |
13757 | QUICK_GROUP_MIN_MAX_SELECT::add_range() |
13758 | sel_range Range object from which a |
13759 | |
13760 | NOTES |
13761 | Construct a new QUICK_RANGE object from a SEL_ARG object, and |
13762 | add it to the array min_max_ranges. If sel_arg is an infinite |
13763 | range, e.g. (x < 5 or x > 4), then skip it and do not construct |
13764 | a quick range. |
13765 | |
13766 | RETURN |
13767 | FALSE on success |
13768 | TRUE otherwise |
13769 | */ |
13770 | |
13771 | bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range) |
13772 | { |
13773 | QUICK_RANGE *range; |
13774 | uint range_flag= sel_range->min_flag | sel_range->max_flag; |
13775 | |
13776 | /* Skip (-inf,+inf) ranges, e.g. (x < 5 or x > 4). */ |
13777 | if ((range_flag & NO_MIN_RANGE) && (range_flag & NO_MAX_RANGE)) |
13778 | return FALSE; |
13779 | |
13780 | if (!(sel_range->min_flag & NO_MIN_RANGE) && |
13781 | !(sel_range->max_flag & NO_MAX_RANGE)) |
13782 | { |
13783 | if (sel_range->maybe_null && |
13784 | sel_range->min_value[0] && sel_range->max_value[0]) |
13785 | range_flag|= NULL_RANGE; /* IS NULL condition */ |
13786 | else if (memcmp(sel_range->min_value, sel_range->max_value, |
13787 | min_max_arg_len) == 0) |
13788 | range_flag|= EQ_RANGE; /* equality condition */ |
13789 | } |
13790 | range= new QUICK_RANGE(join->thd, sel_range->min_value, min_max_arg_len, |
13791 | make_keypart_map(sel_range->part), |
13792 | sel_range->max_value, min_max_arg_len, |
13793 | make_keypart_map(sel_range->part), |
13794 | range_flag); |
13795 | if (!range) |
13796 | return TRUE; |
13797 | if (insert_dynamic(&min_max_ranges, (uchar*)&range)) |
13798 | return TRUE; |
13799 | return FALSE; |
13800 | } |
13801 | |
13802 | |
13803 | /* |
13804 | Opens the ranges if there are more conditions in quick_prefix_select than |
13805 | the ones used for jumping through the prefixes. |
13806 | |
13807 | SYNOPSIS |
13808 | QUICK_GROUP_MIN_MAX_SELECT::adjust_prefix_ranges() |
13809 | |
13810 | NOTES |
13811 | quick_prefix_select is made over the conditions on the whole key. |
13812 | It defines a number of ranges of length x. |
13813 | However when jumping through the prefixes we use only the the first |
13814 | few most significant keyparts in the range key. However if there |
13815 | are more keyparts to follow the ones we are using we must make the |
13816 | condition on the key inclusive (because x < "ab" means |
13817 | x[0] < 'a' OR (x[0] == 'a' AND x[1] < 'b'). |
13818 | To achive the above we must turn off the NEAR_MIN/NEAR_MAX |
13819 | */ |
13820 | void QUICK_GROUP_MIN_MAX_SELECT::adjust_prefix_ranges () |
13821 | { |
13822 | if (quick_prefix_select && |
13823 | group_prefix_len < quick_prefix_select->max_used_key_length) |
13824 | { |
13825 | DYNAMIC_ARRAY *arr; |
13826 | uint inx; |
13827 | |
13828 | for (inx= 0, arr= &quick_prefix_select->ranges; inx < arr->elements; inx++) |
13829 | { |
13830 | QUICK_RANGE *range; |
13831 | |
13832 | get_dynamic(arr, (uchar*)&range, inx); |
13833 | range->flag &= ~(NEAR_MIN | NEAR_MAX); |
13834 | } |
13835 | } |
13836 | } |
13837 | |
13838 | |
13839 | /* |
13840 | Determine the total number and length of the keys that will be used for |
13841 | index lookup. |
13842 | |
13843 | SYNOPSIS |
13844 | QUICK_GROUP_MIN_MAX_SELECT::update_key_stat() |
13845 | |
13846 | DESCRIPTION |
13847 | The total length of the keys used for index lookup depends on whether |
13848 | there are any predicates referencing the min/max argument, and/or if |
13849 | the min/max argument field can be NULL. |
13850 | This function does an optimistic analysis whether the search key might |
13851 | be extended by a constant for the min/max keypart. It is 'optimistic' |
13852 | because during actual execution it may happen that a particular range |
13853 | is skipped, and then a shorter key will be used. However this is data |
13854 | dependent and can't be easily estimated here. |
13855 | |
13856 | RETURN |
13857 | None |
13858 | */ |
13859 | |
13860 | void QUICK_GROUP_MIN_MAX_SELECT::update_key_stat() |
13861 | { |
13862 | max_used_key_length= real_prefix_len; |
13863 | if (min_max_ranges.elements > 0) |
13864 | { |
13865 | QUICK_RANGE *cur_range; |
13866 | if (have_min) |
13867 | { /* Check if the right-most range has a lower boundary. */ |
13868 | get_dynamic(&min_max_ranges, (uchar*)&cur_range, |
13869 | min_max_ranges.elements - 1); |
13870 | if (!(cur_range->flag & NO_MIN_RANGE)) |
13871 | { |
13872 | max_used_key_length+= min_max_arg_len; |
13873 | used_key_parts++; |
13874 | return; |
13875 | } |
13876 | } |
13877 | if (have_max) |
13878 | { /* Check if the left-most range has an upper boundary. */ |
13879 | get_dynamic(&min_max_ranges, (uchar*)&cur_range, 0); |
13880 | if (!(cur_range->flag & NO_MAX_RANGE)) |
13881 | { |
13882 | max_used_key_length+= min_max_arg_len; |
13883 | used_key_parts++; |
13884 | return; |
13885 | } |
13886 | } |
13887 | } |
13888 | else if (have_min && min_max_arg_part && |
13889 | min_max_arg_part->field->real_maybe_null()) |
13890 | { |
13891 | /* |
13892 | If a MIN/MAX argument value is NULL, we can quickly determine |
13893 | that we're in the beginning of the next group, because NULLs |
13894 | are always < any other value. This allows us to quickly |
13895 | determine the end of the current group and jump to the next |
13896 | group (see next_min()) and thus effectively increases the |
13897 | usable key length. |
13898 | */ |
13899 | max_used_key_length+= min_max_arg_len; |
13900 | used_key_parts++; |
13901 | } |
13902 | } |
13903 | |
13904 | |
13905 | /* |
13906 | Initialize a quick group min/max select for key retrieval. |
13907 | |
13908 | SYNOPSIS |
13909 | QUICK_GROUP_MIN_MAX_SELECT::reset() |
13910 | |
13911 | DESCRIPTION |
13912 | Initialize the index chosen for access and find and store the prefix |
13913 | of the last group. The method is expensive since it performs disk access. |
13914 | |
13915 | RETURN |
13916 | 0 OK |
13917 | other Error code |
13918 | */ |
13919 | |
13920 | int QUICK_GROUP_MIN_MAX_SELECT::reset(void) |
13921 | { |
13922 | int result; |
13923 | DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::reset" ); |
13924 | |
13925 | seen_first_key= FALSE; |
13926 | head->file->ha_start_keyread(index); /* We need only the key attributes */ |
13927 | |
13928 | if ((result= file->ha_index_init(index,1))) |
13929 | { |
13930 | head->file->print_error(result, MYF(0)); |
13931 | DBUG_RETURN(result); |
13932 | } |
13933 | if (quick_prefix_select && quick_prefix_select->reset()) |
13934 | DBUG_RETURN(1); |
13935 | result= file->ha_index_last(record); |
13936 | if (result == HA_ERR_END_OF_FILE) |
13937 | DBUG_RETURN(0); |
13938 | /* Save the prefix of the last group. */ |
13939 | key_copy(last_prefix, record, index_info, group_prefix_len); |
13940 | |
13941 | DBUG_RETURN(0); |
13942 | } |
13943 | |
13944 | |
13945 | |
13946 | /* |
13947 | Get the next key containing the MIN and/or MAX key for the next group. |
13948 | |
13949 | SYNOPSIS |
13950 | QUICK_GROUP_MIN_MAX_SELECT::get_next() |
13951 | |
13952 | DESCRIPTION |
13953 | The method finds the next subsequent group of records that satisfies the |
13954 | query conditions and finds the keys that contain the MIN/MAX values for |
13955 | the key part referenced by the MIN/MAX function(s). Once a group and its |
13956 | MIN/MAX values are found, store these values in the Item_sum objects for |
13957 | the MIN/MAX functions. The rest of the values in the result row are stored |
13958 | in the Item_field::result_field of each select field. If the query does |
13959 | not contain MIN and/or MAX functions, then the function only finds the |
13960 | group prefix, which is a query answer itself. |
13961 | |
13962 | NOTES |
13963 | If both MIN and MAX are computed, then we use the fact that if there is |
13964 | no MIN key, there can't be a MAX key as well, so we can skip looking |
13965 | for a MAX key in this case. |
13966 | |
13967 | RETURN |
13968 | 0 on success |
13969 | HA_ERR_END_OF_FILE if returned all keys |
13970 | other if some error occurred |
13971 | */ |
13972 | |
13973 | int QUICK_GROUP_MIN_MAX_SELECT::get_next() |
13974 | { |
13975 | int min_res= 0; |
13976 | int max_res= 0; |
13977 | #ifdef HPUX11 |
13978 | /* |
13979 | volatile is required by a bug in the HP compiler due to which the |
13980 | last test of result fails. |
13981 | */ |
13982 | volatile int result; |
13983 | #else |
13984 | int result; |
13985 | #endif |
13986 | int is_last_prefix= 0; |
13987 | |
13988 | DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::get_next" ); |
13989 | |
13990 | /* |
13991 | Loop until a group is found that satisfies all query conditions or the last |
13992 | group is reached. |
13993 | */ |
13994 | do |
13995 | { |
13996 | result= next_prefix(); |
13997 | /* |
13998 | Check if this is the last group prefix. Notice that at this point |
13999 | this->record contains the current prefix in record format. |
14000 | */ |
14001 | if (!result) |
14002 | { |
14003 | is_last_prefix= key_cmp(index_info->key_part, last_prefix, |
14004 | group_prefix_len); |
14005 | DBUG_ASSERT(is_last_prefix <= 0); |
14006 | } |
14007 | else |
14008 | { |
14009 | if (result == HA_ERR_KEY_NOT_FOUND) |
14010 | continue; |
14011 | break; |
14012 | } |
14013 | |
14014 | if (have_min) |
14015 | { |
14016 | min_res= next_min(); |
14017 | if (min_res == 0) |
14018 | update_min_result(); |
14019 | } |
14020 | /* If there is no MIN in the group, there is no MAX either. */ |
14021 | if ((have_max && !have_min) || |
14022 | (have_max && have_min && (min_res == 0))) |
14023 | { |
14024 | max_res= next_max(); |
14025 | if (max_res == 0) |
14026 | update_max_result(); |
14027 | /* If a MIN was found, a MAX must have been found as well. */ |
14028 | DBUG_ASSERT((have_max && !have_min) || |
14029 | (have_max && have_min && (max_res == 0))); |
14030 | } |
14031 | /* |
14032 | If this is just a GROUP BY or DISTINCT without MIN or MAX and there |
14033 | are equality predicates for the key parts after the group, find the |
14034 | first sub-group with the extended prefix. |
14035 | */ |
14036 | if (!have_min && !have_max && key_infix_len > 0) |
14037 | result= file->ha_index_read_map(record, group_prefix, |
14038 | make_prev_keypart_map(real_key_parts), |
14039 | HA_READ_KEY_EXACT); |
14040 | |
14041 | result= have_min ? min_res : have_max ? max_res : result; |
14042 | } while ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) && |
14043 | is_last_prefix != 0); |
14044 | |
14045 | if (result == HA_ERR_KEY_NOT_FOUND) |
14046 | result= HA_ERR_END_OF_FILE; |
14047 | |
14048 | DBUG_RETURN(result); |
14049 | } |
14050 | |
14051 | |
14052 | /* |
14053 | Retrieve the minimal key in the next group. |
14054 | |
14055 | SYNOPSIS |
14056 | QUICK_GROUP_MIN_MAX_SELECT::next_min() |
14057 | |
14058 | DESCRIPTION |
14059 | Find the minimal key within this group such that the key satisfies the query |
14060 | conditions and NULL semantics. The found key is loaded into this->record. |
14061 | |
14062 | IMPLEMENTATION |
14063 | Depending on the values of min_max_ranges.elements, key_infix_len, and |
14064 | whether there is a NULL in the MIN field, this function may directly |
14065 | return without any data access. In this case we use the key loaded into |
14066 | this->record by the call to this->next_prefix() just before this call. |
14067 | |
14068 | RETURN |
14069 | 0 on success |
14070 | HA_ERR_KEY_NOT_FOUND if no MIN key was found that fulfills all conditions. |
14071 | HA_ERR_END_OF_FILE - "" - |
14072 | other if some error occurred |
14073 | */ |
14074 | |
14075 | int QUICK_GROUP_MIN_MAX_SELECT::next_min() |
14076 | { |
14077 | int result= 0; |
14078 | DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::next_min" ); |
14079 | |
14080 | /* Find the MIN key using the eventually extended group prefix. */ |
14081 | if (min_max_ranges.elements > 0) |
14082 | { |
14083 | if ((result= next_min_in_range())) |
14084 | DBUG_RETURN(result); |
14085 | } |
14086 | else |
14087 | { |
14088 | /* Apply the constant equality conditions to the non-group select fields */ |
14089 | if (key_infix_len > 0) |
14090 | { |
14091 | if ((result= |
14092 | file->ha_index_read_map(record, group_prefix, |
14093 | make_prev_keypart_map(real_key_parts), |
14094 | HA_READ_KEY_EXACT))) |
14095 | DBUG_RETURN(result); |
14096 | } |
14097 | |
14098 | /* |
14099 | If the min/max argument field is NULL, skip subsequent rows in the same |
14100 | group with NULL in it. Notice that: |
14101 | - if the first row in a group doesn't have a NULL in the field, no row |
14102 | in the same group has (because NULL < any other value), |
14103 | - min_max_arg_part->field->ptr points to some place in 'record'. |
14104 | */ |
14105 | if (min_max_arg_part && min_max_arg_part->field->is_null()) |
14106 | { |
14107 | uchar *tmp_key_buff= (uchar*)my_alloca(max_used_key_length); |
14108 | /* Find the first subsequent record without NULL in the MIN/MAX field. */ |
14109 | key_copy(tmp_key_buff, record, index_info, max_used_key_length); |
14110 | result= file->ha_index_read_map(record, tmp_key_buff, |
14111 | make_keypart_map(real_key_parts), |
14112 | HA_READ_AFTER_KEY); |
14113 | /* |
14114 | Check if the new record belongs to the current group by comparing its |
14115 | prefix with the group's prefix. If it is from the next group, then the |
14116 | whole group has NULLs in the MIN/MAX field, so use the first record in |
14117 | the group as a result. |
14118 | TODO: |
14119 | It is possible to reuse this new record as the result candidate for the |
14120 | next call to next_min(), and to save one lookup in the next call. For |
14121 | this add a new member 'this->next_group_prefix'. |
14122 | */ |
14123 | if (!result) |
14124 | { |
14125 | if (key_cmp(index_info->key_part, group_prefix, real_prefix_len)) |
14126 | key_restore(record, tmp_key_buff, index_info, 0); |
14127 | } |
14128 | else if (result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) |
14129 | result= 0; /* There is a result in any case. */ |
14130 | my_afree(tmp_key_buff); |
14131 | } |
14132 | } |
14133 | |
14134 | /* |
14135 | If the MIN attribute is non-nullable, this->record already contains the |
14136 | MIN key in the group, so just return. |
14137 | */ |
14138 | DBUG_RETURN(result); |
14139 | } |
14140 | |
14141 | |
14142 | /* |
14143 | Retrieve the maximal key in the next group. |
14144 | |
14145 | SYNOPSIS |
14146 | QUICK_GROUP_MIN_MAX_SELECT::next_max() |
14147 | |
14148 | DESCRIPTION |
14149 | Lookup the maximal key of the group, and store it into this->record. |
14150 | |
14151 | RETURN |
14152 | 0 on success |
14153 | HA_ERR_KEY_NOT_FOUND if no MAX key was found that fulfills all conditions. |
14154 | HA_ERR_END_OF_FILE - "" - |
14155 | other if some error occurred |
14156 | */ |
14157 | |
14158 | int QUICK_GROUP_MIN_MAX_SELECT::next_max() |
14159 | { |
14160 | int result; |
14161 | |
14162 | DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::next_max" ); |
14163 | |
14164 | /* Get the last key in the (possibly extended) group. */ |
14165 | if (min_max_ranges.elements > 0) |
14166 | result= next_max_in_range(); |
14167 | else |
14168 | result= file->ha_index_read_map(record, group_prefix, |
14169 | make_prev_keypart_map(real_key_parts), |
14170 | HA_READ_PREFIX_LAST); |
14171 | DBUG_RETURN(result); |
14172 | } |
14173 | |
14174 | |
14175 | /** |
14176 | Find the next different key value by skiping all the rows with the same key |
14177 | value. |
14178 | |
14179 | Implements a specialized loose index access method for queries |
14180 | containing aggregate functions with distinct of the form: |
14181 | SELECT [SUM|COUNT|AVG](DISTINCT a,...) FROM t |
14182 | This method comes to replace the index scan + Unique class |
14183 | (distinct selection) for loose index scan that visits all the rows of a |
14184 | covering index instead of jumping in the beginning of each group. |
14185 | TODO: Placeholder function. To be replaced by a handler API call |
14186 | |
14187 | @param is_index_scan hint to use index scan instead of random index read |
14188 | to find the next different value. |
14189 | @param file table handler |
14190 | @param key_part group key to compare |
14191 | @param record row data |
14192 | @param group_prefix current key prefix data |
14193 | @param group_prefix_len length of the current key prefix data |
14194 | @param group_key_parts number of the current key prefix columns |
14195 | @return status |
14196 | @retval 0 success |
14197 | @retval !0 failure |
14198 | */ |
14199 | |
14200 | static int index_next_different (bool is_index_scan, handler *file, |
14201 | KEY_PART_INFO *key_part, uchar * record, |
14202 | const uchar * group_prefix, |
14203 | uint group_prefix_len, |
14204 | uint group_key_parts) |
14205 | { |
14206 | if (is_index_scan) |
14207 | { |
14208 | int result= 0; |
14209 | |
14210 | while (!key_cmp (key_part, group_prefix, group_prefix_len)) |
14211 | { |
14212 | result= file->ha_index_next(record); |
14213 | if (result) |
14214 | return(result); |
14215 | } |
14216 | return result; |
14217 | } |
14218 | else |
14219 | return file->ha_index_read_map(record, group_prefix, |
14220 | make_prev_keypart_map(group_key_parts), |
14221 | HA_READ_AFTER_KEY); |
14222 | } |
14223 | |
14224 | |
14225 | /* |
14226 | Determine the prefix of the next group. |
14227 | |
14228 | SYNOPSIS |
14229 | QUICK_GROUP_MIN_MAX_SELECT::next_prefix() |
14230 | |
14231 | DESCRIPTION |
14232 | Determine the prefix of the next group that satisfies the query conditions. |
14233 | If there is a range condition referencing the group attributes, use a |
14234 | QUICK_RANGE_SELECT object to retrieve the *first* key that satisfies the |
14235 | condition. If there is a key infix of constants, append this infix |
14236 | immediately after the group attributes. The possibly extended prefix is |
14237 | stored in this->group_prefix. The first key of the found group is stored in |
14238 | this->record, on which relies this->next_min(). |
14239 | |
14240 | RETURN |
14241 | 0 on success |
14242 | HA_ERR_KEY_NOT_FOUND if there is no key with the formed prefix |
14243 | HA_ERR_END_OF_FILE if there are no more keys |
14244 | other if some error occurred |
14245 | */ |
14246 | int QUICK_GROUP_MIN_MAX_SELECT::next_prefix() |
14247 | { |
14248 | int result; |
14249 | DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::next_prefix" ); |
14250 | |
14251 | if (quick_prefix_select) |
14252 | { |
14253 | uchar *cur_prefix= seen_first_key ? group_prefix : NULL; |
14254 | if ((result= quick_prefix_select->get_next_prefix(group_prefix_len, |
14255 | group_key_parts, |
14256 | cur_prefix))) |
14257 | DBUG_RETURN(result); |
14258 | seen_first_key= TRUE; |
14259 | } |
14260 | else |
14261 | { |
14262 | if (!seen_first_key) |
14263 | { |
14264 | result= file->ha_index_first(record); |
14265 | if (result) |
14266 | DBUG_RETURN(result); |
14267 | seen_first_key= TRUE; |
14268 | } |
14269 | else |
14270 | { |
14271 | /* Load the first key in this group into record. */ |
14272 | result= index_next_different (is_index_scan, file, index_info->key_part, |
14273 | record, group_prefix, group_prefix_len, |
14274 | group_key_parts); |
14275 | if (result) |
14276 | DBUG_RETURN(result); |
14277 | } |
14278 | } |
14279 | |
14280 | /* Save the prefix of this group for subsequent calls. */ |
14281 | key_copy(group_prefix, record, index_info, group_prefix_len); |
14282 | /* Append key_infix to group_prefix. */ |
14283 | if (key_infix_len > 0) |
14284 | memcpy(group_prefix + group_prefix_len, |
14285 | key_infix, key_infix_len); |
14286 | |
14287 | DBUG_RETURN(0); |
14288 | } |
14289 | |
14290 | |
14291 | /** |
14292 | Allocate a temporary buffer, populate the buffer using the group prefix key |
14293 | and the min/max field key, and compare the result to the current key pointed |
14294 | by index_info. |
14295 | |
14296 | @param key - the min or max field key |
14297 | @param length - length of "key" |
14298 | */ |
14299 | int |
14300 | QUICK_GROUP_MIN_MAX_SELECT::cmp_min_max_key(const uchar *key, uint16 length) |
14301 | { |
14302 | /* |
14303 | Allocate a buffer. |
14304 | Note, we allocate one extra byte, because some of Field_xxx::cmp(), |
14305 | e.g. Field_newdate::cmp(), use uint3korr() which actually read four bytes |
14306 | and then bit-and the read value with 0xFFFFFF. |
14307 | See "MDEV-7920 main.group_min_max fails ... with valgrind" for details. |
14308 | */ |
14309 | uchar *buffer= (uchar*) my_alloca(real_prefix_len + min_max_arg_len + 1); |
14310 | /* Concatenate the group prefix key and the min/max field key */ |
14311 | memcpy(buffer, group_prefix, real_prefix_len); |
14312 | memcpy(buffer + real_prefix_len, key, length); |
14313 | /* Compare the key pointed by key_info to the created key */ |
14314 | int cmp_res= key_cmp(index_info->key_part, buffer, |
14315 | real_prefix_len + min_max_arg_len); |
14316 | my_afree(buffer); |
14317 | return cmp_res; |
14318 | } |
14319 | |
14320 | |
14321 | /* |
14322 | Find the minimal key in a group that satisfies some range conditions for the |
14323 | min/max argument field. |
14324 | |
14325 | SYNOPSIS |
14326 | QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range() |
14327 | |
14328 | DESCRIPTION |
14329 | Given the sequence of ranges min_max_ranges, find the minimal key that is |
14330 | in the left-most possible range. If there is no such key, then the current |
14331 | group does not have a MIN key that satisfies the WHERE clause. If a key is |
14332 | found, its value is stored in this->record. |
14333 | |
14334 | RETURN |
14335 | 0 on success |
14336 | HA_ERR_KEY_NOT_FOUND if there is no key with the given prefix in any of |
14337 | the ranges |
14338 | HA_ERR_END_OF_FILE - "" - |
14339 | other if some error |
14340 | */ |
14341 | |
14342 | int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range() |
14343 | { |
14344 | ha_rkey_function find_flag; |
14345 | key_part_map keypart_map; |
14346 | QUICK_RANGE *cur_range; |
14347 | bool found_null= FALSE; |
14348 | int result= HA_ERR_KEY_NOT_FOUND; |
14349 | |
14350 | DBUG_ASSERT(min_max_ranges.elements > 0); |
14351 | |
14352 | for (uint range_idx= 0; range_idx < min_max_ranges.elements; range_idx++) |
14353 | { /* Search from the left-most range to the right. */ |
14354 | get_dynamic(&min_max_ranges, (uchar*)&cur_range, range_idx); |
14355 | |
14356 | /* |
14357 | If the current value for the min/max argument is bigger than the right |
14358 | boundary of cur_range, there is no need to check this range. |
14359 | */ |
14360 | if (range_idx != 0 && !(cur_range->flag & NO_MAX_RANGE) && |
14361 | (key_cmp(min_max_arg_part, (const uchar*) cur_range->max_key, |
14362 | min_max_arg_len) == 1)) |
14363 | continue; |
14364 | |
14365 | if (cur_range->flag & NO_MIN_RANGE) |
14366 | { |
14367 | keypart_map= make_prev_keypart_map(real_key_parts); |
14368 | find_flag= HA_READ_KEY_EXACT; |
14369 | } |
14370 | else |
14371 | { |
14372 | /* Extend the search key with the lower boundary for this range. */ |
14373 | memcpy(group_prefix + real_prefix_len, cur_range->min_key, |
14374 | cur_range->min_length); |
14375 | keypart_map= make_keypart_map(real_key_parts); |
14376 | find_flag= (cur_range->flag & (EQ_RANGE | NULL_RANGE)) ? |
14377 | HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MIN) ? |
14378 | HA_READ_AFTER_KEY : HA_READ_KEY_OR_NEXT; |
14379 | } |
14380 | |
14381 | result= file->ha_index_read_map(record, group_prefix, keypart_map, |
14382 | find_flag); |
14383 | if (result) |
14384 | { |
14385 | if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) && |
14386 | (cur_range->flag & (EQ_RANGE | NULL_RANGE))) |
14387 | continue; /* Check the next range. */ |
14388 | |
14389 | /* |
14390 | In all other cases (HA_ERR_*, HA_READ_KEY_EXACT with NO_MIN_RANGE, |
14391 | HA_READ_AFTER_KEY, HA_READ_KEY_OR_NEXT) if the lookup failed for this |
14392 | range, it can't succeed for any other subsequent range. |
14393 | */ |
14394 | break; |
14395 | } |
14396 | |
14397 | /* A key was found. */ |
14398 | if (cur_range->flag & EQ_RANGE) |
14399 | break; /* No need to perform the checks below for equal keys. */ |
14400 | |
14401 | if (cur_range->flag & NULL_RANGE) |
14402 | { |
14403 | /* |
14404 | Remember this key, and continue looking for a non-NULL key that |
14405 | satisfies some other condition. |
14406 | */ |
14407 | memcpy(tmp_record, record, head->s->rec_buff_length); |
14408 | found_null= TRUE; |
14409 | continue; |
14410 | } |
14411 | |
14412 | /* Check if record belongs to the current group. */ |
14413 | if (key_cmp(index_info->key_part, group_prefix, real_prefix_len)) |
14414 | { |
14415 | result= HA_ERR_KEY_NOT_FOUND; |
14416 | continue; |
14417 | } |
14418 | |
14419 | /* If there is an upper limit, check if the found key is in the range. */ |
14420 | if ( !(cur_range->flag & NO_MAX_RANGE) ) |
14421 | { |
14422 | int cmp_res= cmp_min_max_key(cur_range->max_key, cur_range->max_length); |
14423 | /* |
14424 | The key is outside of the range if: |
14425 | the interval is open and the key is equal to the maximum boundry |
14426 | or |
14427 | the key is greater than the maximum |
14428 | */ |
14429 | if (((cur_range->flag & NEAR_MAX) && cmp_res == 0) || |
14430 | cmp_res > 0) |
14431 | { |
14432 | result= HA_ERR_KEY_NOT_FOUND; |
14433 | continue; |
14434 | } |
14435 | } |
14436 | /* If we got to this point, the current key qualifies as MIN. */ |
14437 | DBUG_ASSERT(result == 0); |
14438 | break; |
14439 | } |
14440 | /* |
14441 | If there was a key with NULL in the MIN/MAX field, and there was no other |
14442 | key without NULL from the same group that satisfies some other condition, |
14443 | then use the key with the NULL. |
14444 | */ |
14445 | if (found_null && result) |
14446 | { |
14447 | memcpy(record, tmp_record, head->s->rec_buff_length); |
14448 | result= 0; |
14449 | } |
14450 | return result; |
14451 | } |
14452 | |
14453 | |
14454 | /* |
14455 | Find the maximal key in a group that satisfies some range conditions for the |
14456 | min/max argument field. |
14457 | |
14458 | SYNOPSIS |
14459 | QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range() |
14460 | |
14461 | DESCRIPTION |
14462 | Given the sequence of ranges min_max_ranges, find the maximal key that is |
14463 | in the right-most possible range. If there is no such key, then the current |
14464 | group does not have a MAX key that satisfies the WHERE clause. If a key is |
14465 | found, its value is stored in this->record. |
14466 | |
14467 | RETURN |
14468 | 0 on success |
14469 | HA_ERR_KEY_NOT_FOUND if there is no key with the given prefix in any of |
14470 | the ranges |
14471 | HA_ERR_END_OF_FILE - "" - |
14472 | other if some error |
14473 | */ |
14474 | |
14475 | int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range() |
14476 | { |
14477 | ha_rkey_function find_flag; |
14478 | key_part_map keypart_map; |
14479 | QUICK_RANGE *cur_range; |
14480 | int result; |
14481 | |
14482 | DBUG_ASSERT(min_max_ranges.elements > 0); |
14483 | |
14484 | for (uint range_idx= min_max_ranges.elements; range_idx > 0; range_idx--) |
14485 | { /* Search from the right-most range to the left. */ |
14486 | get_dynamic(&min_max_ranges, (uchar*)&cur_range, range_idx - 1); |
14487 | |
14488 | /* |
14489 | If the current value for the min/max argument is smaller than the left |
14490 | boundary of cur_range, there is no need to check this range. |
14491 | */ |
14492 | if (range_idx != min_max_ranges.elements && |
14493 | !(cur_range->flag & NO_MIN_RANGE) && |
14494 | (key_cmp(min_max_arg_part, (const uchar*) cur_range->min_key, |
14495 | min_max_arg_len) == -1)) |
14496 | continue; |
14497 | |
14498 | if (cur_range->flag & NO_MAX_RANGE) |
14499 | { |
14500 | keypart_map= make_prev_keypart_map(real_key_parts); |
14501 | find_flag= HA_READ_PREFIX_LAST; |
14502 | } |
14503 | else |
14504 | { |
14505 | /* Extend the search key with the upper boundary for this range. */ |
14506 | memcpy(group_prefix + real_prefix_len, cur_range->max_key, |
14507 | cur_range->max_length); |
14508 | keypart_map= make_keypart_map(real_key_parts); |
14509 | find_flag= (cur_range->flag & EQ_RANGE) ? |
14510 | HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MAX) ? |
14511 | HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV; |
14512 | } |
14513 | |
14514 | result= file->ha_index_read_map(record, group_prefix, keypart_map, |
14515 | find_flag); |
14516 | |
14517 | if (result) |
14518 | { |
14519 | if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) && |
14520 | (cur_range->flag & EQ_RANGE)) |
14521 | continue; /* Check the next range. */ |
14522 | |
14523 | /* |
14524 | In no key was found with this upper bound, there certainly are no keys |
14525 | in the ranges to the left. |
14526 | */ |
14527 | return result; |
14528 | } |
14529 | /* A key was found. */ |
14530 | if (cur_range->flag & EQ_RANGE) |
14531 | return 0; /* No need to perform the checks below for equal keys. */ |
14532 | |
14533 | /* Check if record belongs to the current group. */ |
14534 | if (key_cmp(index_info->key_part, group_prefix, real_prefix_len)) |
14535 | continue; // Row not found |
14536 | |
14537 | /* If there is a lower limit, check if the found key is in the range. */ |
14538 | if ( !(cur_range->flag & NO_MIN_RANGE) ) |
14539 | { |
14540 | int cmp_res= cmp_min_max_key(cur_range->min_key, cur_range->min_length); |
14541 | /* |
14542 | The key is outside of the range if: |
14543 | the interval is open and the key is equal to the minimum boundry |
14544 | or |
14545 | the key is less than the minimum |
14546 | */ |
14547 | if (((cur_range->flag & NEAR_MIN) && cmp_res == 0) || |
14548 | cmp_res < 0) |
14549 | continue; |
14550 | } |
14551 | /* If we got to this point, the current key qualifies as MAX. */ |
14552 | return result; |
14553 | } |
14554 | return HA_ERR_KEY_NOT_FOUND; |
14555 | } |
14556 | |
14557 | |
14558 | /* |
14559 | Update all MIN function results with the newly found value. |
14560 | |
14561 | SYNOPSIS |
14562 | QUICK_GROUP_MIN_MAX_SELECT::update_min_result() |
14563 | |
14564 | DESCRIPTION |
14565 | The method iterates through all MIN functions and updates the result value |
14566 | of each function by calling Item_sum::reset(), which in turn picks the new |
14567 | result value from this->head->record[0], previously updated by |
14568 | next_min(). The updated value is stored in a member variable of each of the |
14569 | Item_sum objects, depending on the value type. |
14570 | |
14571 | IMPLEMENTATION |
14572 | The update must be done separately for MIN and MAX, immediately after |
14573 | next_min() was called and before next_max() is called, because both MIN and |
14574 | MAX take their result value from the same buffer this->head->record[0] |
14575 | (i.e. this->record). |
14576 | |
14577 | RETURN |
14578 | None |
14579 | */ |
14580 | |
14581 | void QUICK_GROUP_MIN_MAX_SELECT::update_min_result() |
14582 | { |
14583 | Item_sum *min_func; |
14584 | |
14585 | min_functions_it->rewind(); |
14586 | while ((min_func= (*min_functions_it)++)) |
14587 | min_func->reset_and_add(); |
14588 | } |
14589 | |
14590 | |
14591 | /* |
14592 | Update all MAX function results with the newly found value. |
14593 | |
14594 | SYNOPSIS |
14595 | QUICK_GROUP_MIN_MAX_SELECT::update_max_result() |
14596 | |
14597 | DESCRIPTION |
14598 | The method iterates through all MAX functions and updates the result value |
14599 | of each function by calling Item_sum::reset(), which in turn picks the new |
14600 | result value from this->head->record[0], previously updated by |
14601 | next_max(). The updated value is stored in a member variable of each of the |
14602 | Item_sum objects, depending on the value type. |
14603 | |
14604 | IMPLEMENTATION |
14605 | The update must be done separately for MIN and MAX, immediately after |
14606 | next_max() was called, because both MIN and MAX take their result value |
14607 | from the same buffer this->head->record[0] (i.e. this->record). |
14608 | |
14609 | RETURN |
14610 | None |
14611 | */ |
14612 | |
14613 | void QUICK_GROUP_MIN_MAX_SELECT::update_max_result() |
14614 | { |
14615 | Item_sum *max_func; |
14616 | |
14617 | max_functions_it->rewind(); |
14618 | while ((max_func= (*max_functions_it)++)) |
14619 | max_func->reset_and_add(); |
14620 | } |
14621 | |
14622 | |
14623 | /* |
14624 | Append comma-separated list of keys this quick select uses to key_names; |
14625 | append comma-separated list of corresponding used lengths to used_lengths. |
14626 | |
14627 | SYNOPSIS |
14628 | QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths() |
14629 | key_names [out] Names of used indexes |
14630 | used_lengths [out] Corresponding lengths of the index names |
14631 | |
14632 | DESCRIPTION |
14633 | This method is used by select_describe to extract the names of the |
14634 | indexes used by a quick select. |
14635 | |
14636 | */ |
14637 | |
14638 | void QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths(String *key_names, |
14639 | String *used_lengths) |
14640 | { |
14641 | bool first= TRUE; |
14642 | |
14643 | add_key_and_length(key_names, used_lengths, &first); |
14644 | } |
14645 | |
14646 | |
14647 | #ifndef DBUG_OFF |
14648 | |
14649 | static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map, |
14650 | const char *msg) |
14651 | { |
14652 | char buff[1024]; |
14653 | DBUG_ENTER("print_sel_tree" ); |
14654 | |
14655 | String tmp(buff,sizeof(buff),&my_charset_bin); |
14656 | tmp.length(0); |
14657 | for (uint idx= 0; idx < param->keys; idx++) |
14658 | { |
14659 | if (tree_map->is_set(idx)) |
14660 | { |
14661 | uint keynr= param->real_keynr[idx]; |
14662 | if (tmp.length()) |
14663 | tmp.append(','); |
14664 | tmp.append(¶m->table->key_info[keynr].name); |
14665 | } |
14666 | } |
14667 | if (!tmp.length()) |
14668 | tmp.append(STRING_WITH_LEN("(empty)" )); |
14669 | |
14670 | DBUG_PRINT("info" , ("SEL_TREE: %p (%s) scans: %s" , tree, msg, |
14671 | tmp.c_ptr_safe())); |
14672 | |
14673 | DBUG_VOID_RETURN; |
14674 | } |
14675 | |
14676 | |
14677 | static void print_ror_scans_arr(TABLE *table, const char *msg, |
14678 | struct st_ror_scan_info **start, |
14679 | struct st_ror_scan_info **end) |
14680 | { |
14681 | DBUG_ENTER("print_ror_scans_arr" ); |
14682 | |
14683 | char buff[1024]; |
14684 | String tmp(buff,sizeof(buff),&my_charset_bin); |
14685 | tmp.length(0); |
14686 | for (;start != end; start++) |
14687 | { |
14688 | if (tmp.length()) |
14689 | tmp.append(','); |
14690 | tmp.append(&table->key_info[(*start)->keynr].name); |
14691 | } |
14692 | if (!tmp.length()) |
14693 | tmp.append(STRING_WITH_LEN("(empty)" )); |
14694 | DBUG_PRINT("info" , ("ROR key scans (%s): %s" , msg, tmp.c_ptr())); |
14695 | DBUG_VOID_RETURN; |
14696 | } |
14697 | |
14698 | |
14699 | /***************************************************************************** |
14700 | ** Print a quick range for debugging |
14701 | ** TODO: |
14702 | ** This should be changed to use a String to store each row instead |
14703 | ** of locking the DEBUG stream ! |
14704 | *****************************************************************************/ |
14705 | |
14706 | static void |
14707 | print_key(KEY_PART *key_part, const uchar *key, uint used_length) |
14708 | { |
14709 | char buff[1024]; |
14710 | const uchar *key_end= key+used_length; |
14711 | uint store_length; |
14712 | TABLE *table= key_part->field->table; |
14713 | my_bitmap_map *old_sets[2]; |
14714 | |
14715 | dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set); |
14716 | |
14717 | for (; key < key_end; key+=store_length, key_part++) |
14718 | { |
14719 | String tmp(buff,sizeof(buff),&my_charset_bin); |
14720 | Field *field= key_part->field; |
14721 | store_length= key_part->store_length; |
14722 | |
14723 | if (field->real_maybe_null()) |
14724 | { |
14725 | if (*key) |
14726 | { |
14727 | fwrite("NULL" ,sizeof(char),4,DBUG_FILE); |
14728 | continue; |
14729 | } |
14730 | key++; // Skip null byte |
14731 | store_length--; |
14732 | } |
14733 | field->set_key_image(key, key_part->length); |
14734 | if (field->type() == MYSQL_TYPE_BIT) |
14735 | (void) field->val_int_as_str(&tmp, 1); |
14736 | else |
14737 | field->val_str(&tmp); |
14738 | fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE); |
14739 | if (key+store_length < key_end) |
14740 | fputc('/',DBUG_FILE); |
14741 | } |
14742 | dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets); |
14743 | } |
14744 | |
14745 | |
14746 | static void print_quick(QUICK_SELECT_I *quick, const key_map *needed_reg) |
14747 | { |
14748 | char buf[MAX_KEY/8+1]; |
14749 | TABLE *table; |
14750 | my_bitmap_map *old_sets[2]; |
14751 | DBUG_ENTER("print_quick" ); |
14752 | if (!quick) |
14753 | DBUG_VOID_RETURN; |
14754 | DBUG_LOCK_FILE; |
14755 | |
14756 | table= quick->head; |
14757 | dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set); |
14758 | quick->dbug_dump(0, TRUE); |
14759 | dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets); |
14760 | |
14761 | fprintf(DBUG_FILE,"other_keys: 0x%s:\n" , needed_reg->print(buf)); |
14762 | |
14763 | DBUG_UNLOCK_FILE; |
14764 | DBUG_VOID_RETURN; |
14765 | } |
14766 | |
14767 | |
14768 | void QUICK_RANGE_SELECT::dbug_dump(int indent, bool verbose) |
14769 | { |
14770 | /* purecov: begin inspected */ |
14771 | fprintf(DBUG_FILE, "%*squick range select, key %s, length: %d\n" , |
14772 | indent, "" , head->key_info[index].name.str, max_used_key_length); |
14773 | |
14774 | if (verbose) |
14775 | { |
14776 | QUICK_RANGE *range; |
14777 | QUICK_RANGE **pr= (QUICK_RANGE**)ranges.buffer; |
14778 | QUICK_RANGE **end_range= pr + ranges.elements; |
14779 | for (; pr != end_range; ++pr) |
14780 | { |
14781 | fprintf(DBUG_FILE, "%*s" , indent + 2, "" ); |
14782 | range= *pr; |
14783 | if (!(range->flag & NO_MIN_RANGE)) |
14784 | { |
14785 | print_key(key_parts, range->min_key, range->min_length); |
14786 | if (range->flag & NEAR_MIN) |
14787 | fputs(" < " ,DBUG_FILE); |
14788 | else |
14789 | fputs(" <= " ,DBUG_FILE); |
14790 | } |
14791 | fputs("X" ,DBUG_FILE); |
14792 | |
14793 | if (!(range->flag & NO_MAX_RANGE)) |
14794 | { |
14795 | if (range->flag & NEAR_MAX) |
14796 | fputs(" < " ,DBUG_FILE); |
14797 | else |
14798 | fputs(" <= " ,DBUG_FILE); |
14799 | print_key(key_parts, range->max_key, range->max_length); |
14800 | } |
14801 | fputs("\n" ,DBUG_FILE); |
14802 | } |
14803 | } |
14804 | /* purecov: end */ |
14805 | } |
14806 | |
14807 | void QUICK_INDEX_SORT_SELECT::dbug_dump(int indent, bool verbose) |
14808 | { |
14809 | List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); |
14810 | QUICK_RANGE_SELECT *quick; |
14811 | fprintf(DBUG_FILE, "%*squick index_merge select\n" , indent, "" ); |
14812 | fprintf(DBUG_FILE, "%*smerged scans {\n" , indent, "" ); |
14813 | while ((quick= it++)) |
14814 | quick->dbug_dump(indent+2, verbose); |
14815 | if (pk_quick_select) |
14816 | { |
14817 | fprintf(DBUG_FILE, "%*sclustered PK quick:\n" , indent, "" ); |
14818 | pk_quick_select->dbug_dump(indent+2, verbose); |
14819 | } |
14820 | fprintf(DBUG_FILE, "%*s}\n" , indent, "" ); |
14821 | } |
14822 | |
14823 | void QUICK_ROR_INTERSECT_SELECT::dbug_dump(int indent, bool verbose) |
14824 | { |
14825 | List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects); |
14826 | QUICK_SELECT_WITH_RECORD *qr; |
14827 | fprintf(DBUG_FILE, "%*squick ROR-intersect select, %scovering\n" , |
14828 | indent, "" , need_to_fetch_row? "" :"non-" ); |
14829 | fprintf(DBUG_FILE, "%*smerged scans {\n" , indent, "" ); |
14830 | while ((qr= it++)) |
14831 | qr->quick->dbug_dump(indent+2, verbose); |
14832 | if (cpk_quick) |
14833 | { |
14834 | fprintf(DBUG_FILE, "%*sclustered PK quick:\n" , indent, "" ); |
14835 | cpk_quick->dbug_dump(indent+2, verbose); |
14836 | } |
14837 | fprintf(DBUG_FILE, "%*s}\n" , indent, "" ); |
14838 | } |
14839 | |
14840 | void QUICK_ROR_UNION_SELECT::dbug_dump(int indent, bool verbose) |
14841 | { |
14842 | List_iterator_fast<QUICK_SELECT_I> it(quick_selects); |
14843 | QUICK_SELECT_I *quick; |
14844 | fprintf(DBUG_FILE, "%*squick ROR-union select\n" , indent, "" ); |
14845 | fprintf(DBUG_FILE, "%*smerged scans {\n" , indent, "" ); |
14846 | while ((quick= it++)) |
14847 | quick->dbug_dump(indent+2, verbose); |
14848 | fprintf(DBUG_FILE, "%*s}\n" , indent, "" ); |
14849 | } |
14850 | |
14851 | |
14852 | /* |
14853 | Print quick select information to DBUG_FILE. |
14854 | |
14855 | SYNOPSIS |
14856 | QUICK_GROUP_MIN_MAX_SELECT::dbug_dump() |
14857 | indent Indentation offset |
14858 | verbose If TRUE show more detailed output. |
14859 | |
14860 | DESCRIPTION |
14861 | Print the contents of this quick select to DBUG_FILE. The method also |
14862 | calls dbug_dump() for the used quick select if any. |
14863 | |
14864 | IMPLEMENTATION |
14865 | Caller is responsible for locking DBUG_FILE before this call and unlocking |
14866 | it afterwards. |
14867 | |
14868 | RETURN |
14869 | None |
14870 | */ |
14871 | |
14872 | void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose) |
14873 | { |
14874 | fprintf(DBUG_FILE, |
14875 | "%*squick_group_min_max_select: index %s (%d), length: %d\n" , |
14876 | indent, "" , index_info->name.str, index, max_used_key_length); |
14877 | if (key_infix_len > 0) |
14878 | { |
14879 | fprintf(DBUG_FILE, "%*susing key_infix with length %d:\n" , |
14880 | indent, "" , key_infix_len); |
14881 | } |
14882 | if (quick_prefix_select) |
14883 | { |
14884 | fprintf(DBUG_FILE, "%*susing quick_range_select:\n" , indent, "" ); |
14885 | quick_prefix_select->dbug_dump(indent + 2, verbose); |
14886 | } |
14887 | if (min_max_ranges.elements > 0) |
14888 | { |
14889 | fprintf(DBUG_FILE, "%*susing %d quick_ranges for MIN/MAX:\n" , |
14890 | indent, "" , min_max_ranges.elements); |
14891 | } |
14892 | } |
14893 | |
14894 | #endif /* !DBUG_OFF */ |
14895 | |