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