241
class SEL_TREE :public memory::SqlAlloc
245
Starting an effort to document this field:
246
(for some i, keys[i]->type == optimizer::SEL_ARG::IMPOSSIBLE) =>
247
(type == SEL_TREE::IMPOSSIBLE)
258
SEL_TREE(enum Type type_arg) :type(type_arg) {}
259
SEL_TREE() :type(KEY)
262
memset(keys, 0, sizeof(keys));
265
Note: there may exist SEL_TREE objects with sel_tree->type=KEY and
266
keys[i]=0 for all i. (SergeyP: it is not clear whether there is any
267
merit in range analyzer functions (e.g. get_mm_parts) returning a
268
pointer to such SEL_TREE instead of NULL)
270
optimizer::SEL_ARG *keys[MAX_KEY];
271
key_map keys_map; /* bitmask of non-NULL elements in keys */
274
Possible ways to read rows using index_merge. The list is non-empty only
275
if type==KEY. Currently can be non empty only if keys_map.none().
277
List<SEL_IMERGE> merges;
279
/* The members below are filled/used only after get_mm_tree is done */
280
key_map ror_scans_map; /* bitmask of ROR scan-able elements in keys */
281
uint32_t n_ror_scans; /* number of set bits in ror_scans_map */
283
struct st_ror_scan_info **ror_scans; /* list of ROR key scans */
284
struct st_ror_scan_info **ror_scans_end; /* last ROR scan */
285
/* Note that #records for each key scan is stored in table->quick_rows */
288
233
struct st_ror_scan_info;
290
static SEL_TREE * get_mm_parts(optimizer::RangeParameter *param,
235
static optimizer::SEL_TREE * get_mm_parts(optimizer::RangeParameter *param,
293
238
Item_func::Functype type,
315
260
COST_VECT *cost);
317
262
static optimizer::RangeReadPlan *get_key_scans_params(optimizer::Parameter *param,
263
optimizer::SEL_TREE *tree,
319
264
bool index_read_must_be_used,
320
265
bool update_tbl_stats,
321
266
double read_time);
324
269
optimizer::RorIntersectReadPlan *get_best_ror_intersect(const optimizer::Parameter *param,
270
optimizer::SEL_TREE *tree,
326
271
double read_time,
327
272
bool *are_all_covering);
330
275
optimizer::RorIntersectReadPlan *get_best_covering_ror_intersect(optimizer::Parameter *param,
276
optimizer::SEL_TREE *tree,
332
277
double read_time);
335
280
optimizer::TableReadPlan *get_best_disjunct_quick(optimizer::Parameter *param,
281
optimizer::SEL_IMERGE *imerge,
337
282
double read_time);
340
optimizer::GroupMinMaxReadPlan *get_best_group_min_max(optimizer::Parameter *param, SEL_TREE *tree);
342
static void print_sel_tree(optimizer::Parameter *param,
347
static void print_ror_scans_arr(Table *table,
349
struct st_ror_scan_info **start,
350
struct st_ror_scan_info **end);
351
static void print_ror_scans_vector(Table *table,
353
vector<struct st_ror_scan_info *> &vec);
355
static SEL_TREE *tree_and(optimizer::RangeParameter *param, SEL_TREE *tree1, SEL_TREE *tree2);
357
static SEL_TREE *tree_or(optimizer::RangeParameter *param, SEL_TREE *tree1, SEL_TREE *tree2);
285
optimizer::GroupMinMaxReadPlan *get_best_group_min_max(optimizer::Parameter *param, optimizer::SEL_TREE *tree);
287
static optimizer::SEL_TREE *tree_and(optimizer::RangeParameter *param,
288
optimizer::SEL_TREE *tree1,
289
optimizer::SEL_TREE *tree2);
359
291
static optimizer::SEL_ARG *sel_add(optimizer::SEL_ARG *key1, optimizer::SEL_ARG *key2);
361
static optimizer::SEL_ARG *key_or(optimizer::RangeParameter *param, optimizer::SEL_ARG *key1, optimizer::SEL_ARG *key2);
363
293
static optimizer::SEL_ARG *key_and(optimizer::RangeParameter *param,
364
294
optimizer::SEL_ARG *key1,
365
295
optimizer::SEL_ARG *key2,
368
298
static bool get_range(optimizer::SEL_ARG **e1, optimizer::SEL_ARG **e2, optimizer::SEL_ARG *root1);
370
static bool eq_tree(optimizer::SEL_ARG* a, optimizer::SEL_ARG *b);
372
300
optimizer::SEL_ARG optimizer::null_element(optimizer::SEL_ARG::IMPOSSIBLE);
374
302
static bool null_part_in_key(KEY_PART *key_part,
375
303
const unsigned char *key,
376
304
uint32_t length);
378
bool sel_trees_can_be_ored(SEL_TREE *tree1, SEL_TREE *tree2, optimizer::RangeParameter *param);
382
SEL_IMERGE is a list of possible ways to do index merge, i.e. it is
383
a condition in the following form:
384
(t_1||t_2||...||t_N) && (next)
386
where all t_i are SEL_TREEs, next is another SEL_IMERGE and no pair
387
(t_i,t_j) contains SEL_ARGS for the same index.
389
SEL_TREE contained in SEL_IMERGE always has merges=NULL.
391
This class relies on memory manager to do the cleanup.
394
class SEL_IMERGE : public memory::SqlAlloc
396
enum { PREALLOCED_TREES= 10};
398
SEL_TREE *trees_prealloced[PREALLOCED_TREES];
399
SEL_TREE **trees; /* trees used to do index_merge */
400
SEL_TREE **trees_next; /* last of these trees */
401
SEL_TREE **trees_end; /* end of allocated space */
403
optimizer::SEL_ARG ***best_keys; /* best keys to read in SEL_TREEs */
406
trees(&trees_prealloced[0]),
408
trees_end(trees + PREALLOCED_TREES)
410
int or_sel_tree(optimizer::RangeParameter *param, SEL_TREE *tree);
411
int or_sel_tree_with_checks(optimizer::RangeParameter *param, SEL_TREE *new_tree);
412
int or_sel_imerge_with_checks(optimizer::RangeParameter *param, SEL_IMERGE* imerge);
417
Add SEL_TREE to this index_merge without any checks,
420
This function implements the following:
421
(x_1||...||x_N) || t = (x_1||...||x_N||t), where x_i, t are SEL_TREEs
427
int SEL_IMERGE::or_sel_tree(optimizer::RangeParameter *param, SEL_TREE *tree)
429
if (trees_next == trees_end)
431
const int realloc_ratio= 2; /* Double size for next round */
432
uint32_t old_elements= (trees_end - trees);
433
uint32_t old_size= sizeof(SEL_TREE**) * old_elements;
434
uint32_t new_size= old_size * realloc_ratio;
435
SEL_TREE **new_trees;
436
if (!(new_trees= (SEL_TREE**)alloc_root(param->mem_root, new_size)))
438
memcpy(new_trees, trees, old_size);
440
trees_next= trees + old_elements;
441
trees_end= trees + old_elements * realloc_ratio;
443
*(trees_next++)= tree;
449
Perform OR operation on this SEL_IMERGE and supplied SEL_TREE new_tree,
450
combining new_tree with one of the trees in this SEL_IMERGE if they both
451
have SEL_ARGs for the same key.
454
or_sel_tree_with_checks()
455
param Parameter from SqlSelect::test_quick_select
456
new_tree SEL_TREE with type KEY or KEY_SMALLER.
459
This does the following:
460
(t_1||...||t_k)||new_tree =
462
= (t_1||...||t_k||new_tree)
464
= (t_1||....||(t_j|| new_tree)||...||t_k),
466
where t_i, y are SEL_TREEs.
467
new_tree is combined with the first t_j it has a SEL_ARG on common
468
key with. As a consequence of this, choice of keys to do index_merge
469
read may depend on the order of conditions in WHERE part of the query.
473
1 One of the trees was combined with new_tree to SEL_TREE::ALWAYS,
474
and (*this) should be discarded.
475
-1 An error occurred.
477
int SEL_IMERGE::or_sel_tree_with_checks(optimizer::RangeParameter *param, SEL_TREE *new_tree)
479
for (SEL_TREE** tree = trees;
483
if (sel_trees_can_be_ored(*tree, new_tree, param))
485
*tree = tree_or(param, *tree, new_tree);
488
if (((*tree)->type == SEL_TREE::MAYBE) ||
489
((*tree)->type == SEL_TREE::ALWAYS))
491
/* SEL_TREE::IMPOSSIBLE is impossible here */
496
/* New tree cannot be combined with any of existing trees. */
497
return or_sel_tree(param, new_tree);
502
Perform OR operation on this index_merge and supplied index_merge list.
506
1 - One of conditions in result is always true and this SEL_IMERGE
508
-1 - An error occurred
511
int SEL_IMERGE::or_sel_imerge_with_checks(optimizer::RangeParameter *param, SEL_IMERGE* imerge)
513
for (SEL_TREE** tree= imerge->trees;
514
tree != imerge->trees_next;
517
if (or_sel_tree_with_checks(param, *tree))
306
bool sel_trees_can_be_ored(optimizer::SEL_TREE *tree1,
307
optimizer::SEL_TREE *tree2,
308
optimizer::RangeParameter *param);
525
316
Perform AND operation on two index_merge lists and store result in *im1.
528
inline void imerge_list_and_list(List<SEL_IMERGE> *im1, List<SEL_IMERGE> *im2)
319
inline void imerge_list_and_list(List<optimizer::SEL_IMERGE> *im1, List<optimizer::SEL_IMERGE> *im2)
530
321
im1->concat(im2);
535
Perform OR operation on 2 index_merge lists, storing result in first list.
538
The following conversion is implemented:
539
(a_1 &&...&& a_N)||(b_1 &&...&& b_K) = AND_i,j(a_i || b_j) =>
542
i.e. all conjuncts except the first one are currently dropped.
543
This is done to avoid producing N*K ways to do index_merge.
545
If (a_1||b_1) produce a condition that is always true, NULL is returned
546
and index_merge is discarded (while it is actually possible to try
549
As a consequence of this, choice of keys to do index_merge read may depend
550
on the order of conditions in WHERE part of the query.
553
0 OK, result is stored in *im1
554
other Error, both passed lists are unusable
557
static int imerge_list_or_list(optimizer::RangeParameter *param,
558
List<SEL_IMERGE> *im1,
559
List<SEL_IMERGE> *im2)
561
SEL_IMERGE *imerge= im1->head();
563
im1->push_back(imerge);
565
return imerge->or_sel_imerge_with_checks(param, im2->head());
570
Perform OR operation on index_merge list and key tree.
573
0 OK, result is stored in *im1.
577
static int imerge_list_or_tree(optimizer::RangeParameter *param,
578
List<SEL_IMERGE> *im1,
582
List_iterator<SEL_IMERGE> it(*im1);
583
while ((imerge= it++))
585
if (imerge->or_sel_tree_with_checks(param, tree))
588
return im1->is_empty();
592
325
/***************************************************************************
593
326
** Basic functions for SqlSelect and QuickRangeSelect
594
327
***************************************************************************/
2014
1743
internal::my_qsort(tree->ror_scans, tree->n_ror_scans, sizeof(ROR_SCAN_INFO*),
2015
1744
(qsort_cmp)cmp_ror_scan_info);
2016
print_ror_scans_arr(param->table, "ordered",
2018
tree->ror_scans_end);
2020
ROR_SCAN_INFO **intersect_scans; /* ROR scans used in index intersection */
2021
ROR_SCAN_INFO **intersect_scans_end;
2022
if (!(intersect_scans= (ROR_SCAN_INFO**)alloc_root(param->mem_root,
2023
sizeof(ROR_SCAN_INFO*)*
2024
tree->n_ror_scans)))
1746
ROR_SCAN_INFO **intersect_scans= NULL; /* ROR scans used in index intersection */
1747
ROR_SCAN_INFO **intersect_scans_end= NULL;
1748
if (! (intersect_scans= (ROR_SCAN_INFO**)alloc_root(param->mem_root,
1749
sizeof(ROR_SCAN_INFO*)*
1750
tree->n_ror_scans)))
2026
1752
intersect_scans_end= intersect_scans;
2028
1754
/* Create and incrementally update ROR intersection. */
2029
ROR_INTERSECT_INFO *intersect, *intersect_best;
2030
if (!(intersect= ror_intersect_init(param)) ||
2031
!(intersect_best= ror_intersect_init(param)))
1755
ROR_INTERSECT_INFO *intersect= NULL;
1756
ROR_INTERSECT_INFO *intersect_best= NULL;
1757
if (! (intersect= ror_intersect_init(param)) ||
1758
! (intersect_best= ror_intersect_init(param)))
2034
1761
/* [intersect_scans,intersect_scans_best) will hold the best intersection */
2035
ROR_SCAN_INFO **intersect_scans_best;
1762
ROR_SCAN_INFO **intersect_scans_best= NULL;
2036
1763
cur_ror_scan= tree->ror_scans;
2037
1764
intersect_scans_best= intersect_scans;
2038
1765
while (cur_ror_scan != tree->ror_scans_end && !intersect->is_covering)
3633
Check if two SEL_TREES can be combined into one (i.e. a single key range
3634
read can be constructed for "cond_of_tree1 OR cond_of_tree2" ) without
3638
bool sel_trees_can_be_ored(SEL_TREE *tree1, SEL_TREE *tree2,
3639
optimizer::RangeParameter* param)
3641
key_map common_keys= tree1->keys_map;
3642
common_keys&= tree2->keys_map;
3644
if (common_keys.none())
3647
/* trees have a common key, check if they refer to same key part */
3648
optimizer::SEL_ARG **key1,**key2;
3649
for (uint32_t key_no=0; key_no < param->keys; key_no++)
3651
if (common_keys.test(key_no))
3653
key1= tree1->keys + key_no;
3654
key2= tree2->keys + key_no;
3655
if ((*key1)->part == (*key2)->part)
3666
Remove the trees that are not suitable for record retrieval.
3668
param Range analysis parameter
3669
tree Tree to be processed, tree->type is KEY or KEY_SMALLER
3672
This function walks through tree->keys[] and removes the SEL_ARG* trees
3673
that are not "maybe" trees (*) and cannot be used to construct quick range
3675
(*) - have type MAYBE or MAYBE_KEY. Perhaps we should remove trees of
3676
these types here as well.
3678
A SEL_ARG* tree cannot be used to construct quick select if it has
3679
tree->part != 0. (e.g. it could represent "keypart2 < const").
3681
WHY THIS FUNCTION IS NEEDED
3683
Normally we allow construction of SEL_TREE objects that have SEL_ARG
3684
trees that do not allow quick range select construction. For example for
3685
" keypart1=1 AND keypart2=2 " the execution will proceed as follows:
3686
tree1= SEL_TREE { SEL_ARG{keypart1=1} }
3687
tree2= SEL_TREE { SEL_ARG{keypart2=2} } -- can't make quick range select
3689
call tree_and(tree1, tree2) -- this joins SEL_ARGs into a usable SEL_ARG
3692
There is an exception though: when we construct index_merge SEL_TREE,
3693
any SEL_ARG* tree that cannot be used to construct quick range select can
3694
be removed, because current range analysis code doesn't provide any way
3695
that tree could be later combined with another tree.
3696
Consider an example: we should not construct
3698
merges = SEL_IMERGE {
3699
SEL_TREE(t.key1part1 = 1),
3700
SEL_TREE(t.key2part2 = 2) -- (*)
3704
- (*) cannot be used to construct quick range select,
3705
- There is no execution path that would cause (*) to be converted to
3706
a tree that could be used.
3708
The latter is easy to verify: first, notice that the only way to convert
3709
(*) into a usable tree is to call tree_and(something, (*)).
3711
Second look at what tree_and/tree_or function would do when passed a
3712
SEL_TREE that has the structure like st1 tree has, and conlcude that
3713
tree_and(something, (*)) will not be called.
3716
0 Ok, some suitable trees left
3717
1 No tree->keys[] left.
3720
static bool remove_nonrange_trees(optimizer::RangeParameter *param, SEL_TREE *tree)
3723
for (uint32_t i=0; i < param->keys; i++)
3727
if (tree->keys[i]->part)
3729
tree->keys[i]= NULL;
3730
tree->keys_map.reset(i);
3741
tree_or(optimizer::RangeParameter *param,SEL_TREE *tree1,SEL_TREE *tree2)
3743
if (!tree1 || !tree2)
3745
if (tree1->type == SEL_TREE::IMPOSSIBLE || tree2->type == SEL_TREE::ALWAYS)
3747
if (tree2->type == SEL_TREE::IMPOSSIBLE || tree1->type == SEL_TREE::ALWAYS)
3749
if (tree1->type == SEL_TREE::MAYBE)
3750
return(tree1); // Can't use this
3751
if (tree2->type == SEL_TREE::MAYBE)
3754
SEL_TREE *result= 0;
3755
key_map result_keys;
3756
result_keys.reset();
3757
if (sel_trees_can_be_ored(tree1, tree2, param))
3759
/* Join the trees key per key */
3760
optimizer::SEL_ARG **key1,**key2,**end;
3761
for (key1= tree1->keys,key2= tree2->keys,end= key1+param->keys ;
3762
key1 != end ; key1++,key2++)
3764
*key1=key_or(param, *key1, *key2);
3767
result=tree1; // Added to tree1
3768
result_keys.set(key1 - tree1->keys);
3772
result->keys_map= result_keys;
3776
/* ok, two trees have KEY type but cannot be used without index merge */
3777
if (tree1->merges.is_empty() && tree2->merges.is_empty())
3779
if (param->remove_jump_scans)
3781
bool no_trees= remove_nonrange_trees(param, tree1);
3782
no_trees= no_trees || remove_nonrange_trees(param, tree2);
3784
return(new SEL_TREE(SEL_TREE::ALWAYS));
3787
/* both trees are "range" trees, produce new index merge structure */
3788
if (!(result= new SEL_TREE()) || !(merge= new SEL_IMERGE()) ||
3789
(result->merges.push_back(merge)) ||
3790
(merge->or_sel_tree(param, tree1)) ||
3791
(merge->or_sel_tree(param, tree2)))
3794
result->type= tree1->type;
3796
else if (!tree1->merges.is_empty() && !tree2->merges.is_empty())
3798
if (imerge_list_or_list(param, &tree1->merges, &tree2->merges))
3799
result= new SEL_TREE(SEL_TREE::ALWAYS);
3805
/* one tree is index merge tree and another is range tree */
3806
if (tree1->merges.is_empty())
3807
std::swap(tree1, tree2);
3809
if (param->remove_jump_scans && remove_nonrange_trees(param, tree2))
3810
return(new SEL_TREE(SEL_TREE::ALWAYS));
3811
/* add tree2 to tree1->merges, checking if it collapses to ALWAYS */
3812
if (imerge_list_or_tree(param, &tree1->merges, tree2))
3813
result= new SEL_TREE(SEL_TREE::ALWAYS);
3822
3339
/* And key trees where key1->part < key2 -> part */
4017
static optimizer::SEL_ARG *
4018
key_or(optimizer::RangeParameter *param, optimizer::SEL_ARG *key1, optimizer::SEL_ARG *key2)
4038
if (key1->part != key2->part)
4042
return 0; // Can't optimize this
4045
// If one of the key is MAYBE_KEY then the found region may be bigger
4046
if (key1->type == optimizer::SEL_ARG::MAYBE_KEY)
4052
if (key2->type == optimizer::SEL_ARG::MAYBE_KEY)
4059
if (key1->use_count > 0)
4061
if (key2->use_count == 0 || key1->elements > key2->elements)
4063
std::swap(key1,key2);
4065
if (key1->use_count > 0 || !(key1=key1->clone_tree(param)))
4069
// Add tree at key2 to tree at key1
4070
bool key2_shared= key2->use_count != 0;
4071
key1->maybe_flag|= key2->maybe_flag;
4073
for (key2=key2->first(); key2; )
4075
optimizer::SEL_ARG *tmp= key1->find_range(key2); // Find key1.min <= key2.min
4080
tmp=key1->first(); // tmp.min > key2.min
4083
else if ((cmp=tmp->cmp_max_to_min(key2)) < 0)
4084
{ // Found tmp.max < key2.min
4085
optimizer::SEL_ARG *next= tmp->next;
4086
if (cmp == -2 && eq_tree(tmp->next_key_part,key2->next_key_part))
4088
// Join near ranges like tmp.max < 0 and key2.min >= 0
4089
optimizer::SEL_ARG *key2_next=key2->next;
4092
if (! (key2=new optimizer::SEL_ARG(*key2)))
4093
return 0; // out of memory
4094
key2->increment_use_count(key1->use_count+1);
4095
key2->next= key2_next; // New copy of key2
4097
key2->copy_min(tmp);
4098
if (! (key1=key1->tree_delete(tmp)))
4099
{ // Only one key in tree
4106
if (! (tmp= next)) // tmp.min > key2.min
4107
break; // Copy rest of key2
4110
{ // tmp.min > key2.min
4112
if ((tmp_cmp= tmp->cmp_min_to_max(key2)) > 0) // if tmp.min > key2.max
4114
if (tmp_cmp == 2 && eq_tree(tmp->next_key_part,key2->next_key_part))
4115
{ // ranges are connected
4116
tmp->copy_min_to_min(key2);
4117
key1->merge_flags(key2);
4118
if (tmp->min_flag & NO_MIN_RANGE &&
4119
tmp->max_flag & NO_MAX_RANGE)
4121
if (key1->maybe_flag)
4122
return new optimizer::SEL_ARG(optimizer::SEL_ARG::MAYBE_KEY);
4125
key2->increment_use_count(-1); // Free not used tree
4131
optimizer::SEL_ARG *next= key2->next; // Keys are not overlapping
4134
optimizer::SEL_ARG *cpy= new optimizer::SEL_ARG(*key2); // Must make copy
4137
key1= key1->insert(cpy);
4138
key2->increment_use_count(key1->use_count+1);
4141
key1= key1->insert(key2); // Will destroy key2_root
4148
// tmp.max >= key2.min && tmp.min <= key.cmax(overlapping ranges)
4149
if (eq_tree(tmp->next_key_part,key2->next_key_part))
4151
if (tmp->is_same(key2))
4153
tmp->merge_flags(key2); // Copy maybe flags
4154
key2->increment_use_count(-1); // Free not used tree
4158
optimizer::SEL_ARG *last= tmp;
4159
while (last->next && last->next->cmp_min_to_max(key2) <= 0 &&
4160
eq_tree(last->next->next_key_part,key2->next_key_part))
4162
optimizer::SEL_ARG *save= last;
4164
key1= key1->tree_delete(save);
4166
last->copy_min(tmp);
4167
if (last->copy_min(key2) || last->copy_max(key2))
4170
for (; key2; key2= key2->next)
4171
key2->increment_use_count(-1); // Free not used tree
4172
if (key1->maybe_flag)
4173
return new optimizer::SEL_ARG(optimizer::SEL_ARG::MAYBE_KEY);
4181
if (cmp >= 0 && tmp->cmp_min_to_min(key2) < 0)
4182
{ // tmp.min <= x < key2.min
4183
optimizer::SEL_ARG *new_arg= tmp->clone_first(key2);
4186
if ((new_arg->next_key_part= key1->next_key_part))
4187
new_arg->increment_use_count(key1->use_count+1);
4188
tmp->copy_min_to_min(key2);
4189
key1= key1->insert(new_arg);
4192
// tmp.min >= key2.min && tmp.min <= key2.max
4193
optimizer::SEL_ARG key(*key2); // Get copy we can modify
4196
if (tmp->cmp_min_to_min(&key) > 0)
4197
{ // key.min <= x < tmp.min
4198
optimizer::SEL_ARG *new_arg= key.clone_first(tmp);
4201
if ((new_arg->next_key_part=key.next_key_part))
4202
new_arg->increment_use_count(key1->use_count+1);
4203
key1= key1->insert(new_arg);
4205
if ((cmp=tmp->cmp_max_to_max(&key)) <= 0)
4206
{ // tmp.min. <= x <= tmp.max
4207
tmp->maybe_flag|= key.maybe_flag;
4208
key.increment_use_count(key1->use_count+1);
4209
tmp->next_key_part= key_or(param, tmp->next_key_part, key.next_key_part);
4210
if (! cmp) // Key2 is ready
4212
key.copy_max_to_min(tmp);
4213
if (! (tmp= tmp->next))
4215
optimizer::SEL_ARG *tmp2= new optimizer::SEL_ARG(key);
4218
key1= key1->insert(tmp2);
4222
if (tmp->cmp_min_to_max(&key) > 0)
4224
optimizer::SEL_ARG *tmp2= new optimizer::SEL_ARG(key);
4227
key1= key1->insert(tmp2);
4233
optimizer::SEL_ARG *new_arg= tmp->clone_last(&key); // tmp.min <= x <= key.max
4236
tmp->copy_max_to_min(&key);
4237
tmp->increment_use_count(key1->use_count+1);
4238
/* Increment key count as it may be used for next loop */
4239
key.increment_use_count(1);
4240
new_arg->next_key_part= key_or(param, tmp->next_key_part, key.next_key_part);
4241
key1= key1->insert(new_arg);
4251
optimizer::SEL_ARG *next= key2->next;
4254
optimizer::SEL_ARG *tmp= new optimizer::SEL_ARG(*key2); // Must make copy
4257
key2->increment_use_count(key1->use_count+1);
4258
key1= key1->insert(tmp);
4261
key1= key1->insert(key2); // Will destroy key2_root
4269
/* Compare if two trees are equal */
4270
static bool eq_tree(optimizer::SEL_ARG *a, optimizer::SEL_ARG *b)
4277
if (! a || ! b || ! a->is_same(b))
4282
if (a->left != &optimizer::null_element && b->left != &optimizer::null_element)
4284
if (! eq_tree(a->left,b->left))
4287
else if (a->left != &optimizer::null_element || b->left != &optimizer::null_element)
4292
if (a->right != &optimizer::null_element && b->right != &optimizer::null_element)
4294
if (! eq_tree(a->right,b->right))
4297
else if (a->right != &optimizer::null_element || b->right != &optimizer::null_element)
4302
if (a->next_key_part != b->next_key_part)
4304
if (! a->next_key_part != ! b->next_key_part ||
4305
! eq_tree(a->next_key_part, b->next_key_part))
4313
3534
/****************************************************************************
4314
3535
MRR Range Sequence Interface implementation that walks a SEL_ARG* tree.
4315
3536
****************************************************************************/
6363
static void print_sel_tree(optimizer::Parameter *param, SEL_TREE *tree, key_map *tree_map, const char *)
6365
optimizer::SEL_ARG **key= NULL;
6366
optimizer::SEL_ARG **end= NULL;
6370
String tmp(buff,sizeof(buff),&my_charset_bin);
6372
for (idx= 0, key=tree->keys, end= key + param->keys;
6376
if (tree_map->test(idx))
6378
uint32_t keynr= param->real_keynr[idx];
6381
tmp.append(param->table->key_info[keynr].name);
6385
tmp.append(STRING_WITH_LEN("(empty)"));
6389
static void print_ror_scans_arr(Table *table,
6391
struct st_ror_scan_info **start,
6392
struct st_ror_scan_info **end)
6395
String tmp(buff,sizeof(buff),&my_charset_bin);
6397
for (; start != end; start++)
6401
tmp.append(table->key_info[(*start)->keynr].name);
6404
tmp.append(STRING_WITH_LEN("(empty)"));
6407
static void print_ror_scans_vector(Table *table,
6409
vector<struct st_ror_scan_info *> &vec)
6412
String tmp(buff,sizeof(buff),&my_charset_bin);
6414
for (vector<struct st_ror_scan_info *>::iterator it= vec.begin();
6420
tmp.append(table->key_info[(*it)->keynr].name);
6423
tmp.append(STRING_WITH_LEN("(empty)"));
6426
5584
} /* namespace drizzled */