00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 #include <config.h>
00104
00105 #include <math.h>
00106 #include <float.h>
00107
00108 #include <string>
00109 #include <vector>
00110 #include <algorithm>
00111
00112 #include <boost/dynamic_bitset.hpp>
00113
00114 #include <drizzled/check_stack_overrun.h>
00115 #include <drizzled/error.h>
00116 #include <drizzled/field/num.h>
00117 #include <drizzled/internal/iocache.h>
00118 #include <drizzled/internal/my_sys.h>
00119 #include <drizzled/item/cmpfunc.h>
00120 #include <drizzled/optimizer/cost_vector.h>
00121 #include <drizzled/optimizer/quick_group_min_max_select.h>
00122 #include <drizzled/optimizer/quick_index_merge_select.h>
00123 #include <drizzled/optimizer/quick_range.h>
00124 #include <drizzled/optimizer/quick_range_select.h>
00125 #include <drizzled/optimizer/quick_ror_intersect_select.h>
00126 #include <drizzled/optimizer/quick_ror_union_select.h>
00127 #include <drizzled/optimizer/range.h>
00128 #include <drizzled/optimizer/range_param.h>
00129 #include <drizzled/optimizer/sel_arg.h>
00130 #include <drizzled/optimizer/sel_imerge.h>
00131 #include <drizzled/optimizer/sel_tree.h>
00132 #include <drizzled/optimizer/sum.h>
00133 #include <drizzled/optimizer/table_read_plan.h>
00134 #include <drizzled/plugin/storage_engine.h>
00135 #include <drizzled/records.h>
00136 #include <drizzled/sql_base.h>
00137 #include <drizzled/sql_select.h>
00138 #include <drizzled/table_reference.h>
00139 #include <drizzled/session.h>
00140 #include <drizzled/key.h>
00141 #include <drizzled/unique.h>
00142 #include <drizzled/temporal.h>
00143 #include <drizzled/sql_lex.h>
00144 #include <drizzled/system_variables.h>
00145
00146 using namespace std;
00147
00148 namespace drizzled {
00149
00150 static const int HA_END_SPACE_KEY= 0;
00151
00152
00153
00154
00155
00156 static inline ha_rows double2rows(double x)
00157 {
00158 return static_cast<ha_rows>(x);
00159 }
00160
00161 static unsigned char is_null_string[2]= {1,0};
00162
00163
00207 static void get_sweep_read_cost(Table *table,
00208 ha_rows nrows,
00209 bool interrupted,
00210 optimizer::CostVector *cost)
00211 {
00212 cost->zero();
00213 if (table->cursor->primary_key_is_clustered())
00214 {
00215 cost->setIOCount(table->cursor->read_time(table->getShare()->getPrimaryKey(),
00216 static_cast<uint32_t>(nrows),
00217 nrows));
00218 }
00219 else
00220 {
00221 double n_blocks=
00222 ceil(static_cast<double>(table->cursor->stats.data_file_length) / IO_SIZE);
00223 double busy_blocks=
00224 n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, static_cast<double>(nrows)));
00225 if (busy_blocks < 1.0)
00226 busy_blocks= 1.0;
00227
00228 cost->setIOCount(busy_blocks);
00229
00230 if (! interrupted)
00231 {
00232
00233 cost->setAvgIOCost((DISK_SEEK_BASE_COST +
00234 DISK_SEEK_PROP_COST*n_blocks/busy_blocks));
00235 }
00236 }
00237 }
00238
00239 static optimizer::SEL_TREE * get_mm_parts(optimizer::RangeParameter *param,
00240 COND *cond_func,
00241 Field *field,
00242 Item_func::Functype type,
00243 Item *value,
00244 Item_result cmp_type);
00245
00246 static optimizer::SEL_ARG *get_mm_leaf(optimizer::RangeParameter *param,
00247 COND *cond_func,
00248 Field *field,
00249 KEY_PART *key_part,
00250 Item_func::Functype type,
00251 Item *value);
00252
00253 static optimizer::SEL_TREE *get_mm_tree(optimizer::RangeParameter *param, COND *cond);
00254
00255 static bool is_key_scan_ror(optimizer::Parameter *param, uint32_t keynr, uint8_t nparts);
00256
00257 static ha_rows check_quick_select(Session *session,
00258 optimizer::Parameter *param,
00259 uint32_t idx,
00260 bool index_only,
00261 optimizer::SEL_ARG *tree,
00262 bool update_tbl_stats,
00263 uint32_t *mrr_flags,
00264 uint32_t *bufsize,
00265 optimizer::CostVector *cost);
00266
00267 static optimizer::RangeReadPlan *get_key_scans_params(Session *session,
00268 optimizer::Parameter *param,
00269 optimizer::SEL_TREE *tree,
00270 bool index_read_must_be_used,
00271 bool update_tbl_stats,
00272 double read_time);
00273
00274 static
00275 optimizer::RorIntersectReadPlan *get_best_ror_intersect(const optimizer::Parameter *param,
00276 optimizer::SEL_TREE *tree,
00277 double read_time,
00278 bool *are_all_covering);
00279
00280 static
00281 optimizer::RorIntersectReadPlan *get_best_covering_ror_intersect(optimizer::Parameter *param,
00282 optimizer::SEL_TREE *tree,
00283 double read_time);
00284
00285 static
00286 optimizer::TableReadPlan *get_best_disjunct_quick(Session *session,
00287 optimizer::Parameter *param,
00288 optimizer::SEL_IMERGE *imerge,
00289 double read_time);
00290
00291 static
00292 optimizer::GroupMinMaxReadPlan *get_best_group_min_max(optimizer::Parameter *param, optimizer::SEL_TREE *tree);
00293
00294 static optimizer::SEL_TREE *tree_and(optimizer::RangeParameter *param,
00295 optimizer::SEL_TREE *tree1,
00296 optimizer::SEL_TREE *tree2);
00297
00298 static optimizer::SEL_ARG *sel_add(optimizer::SEL_ARG *key1, optimizer::SEL_ARG *key2);
00299
00300 static optimizer::SEL_ARG *key_and(optimizer::RangeParameter *param,
00301 optimizer::SEL_ARG *key1,
00302 optimizer::SEL_ARG *key2,
00303 uint32_t clone_flag);
00304
00305 static bool get_range(optimizer::SEL_ARG **e1, optimizer::SEL_ARG **e2, optimizer::SEL_ARG *root1);
00306
00307 optimizer::SEL_ARG optimizer::null_element(optimizer::SEL_ARG::IMPOSSIBLE);
00308
00309 static bool null_part_in_key(KEY_PART *key_part,
00310 const unsigned char *key,
00311 uint32_t length);
00312
00313 bool sel_trees_can_be_ored(optimizer::SEL_TREE *tree1,
00314 optimizer::SEL_TREE *tree2,
00315 optimizer::RangeParameter *param);
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 inline void imerge_list_and_list(List<optimizer::SEL_IMERGE> *im1, List<optimizer::SEL_IMERGE> *im2)
00327 {
00328 im1->concat(im2);
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 optimizer::SqlSelect *optimizer::make_select(Table *head,
00343 table_map const_tables,
00344 table_map read_tables,
00345 COND *conds,
00346 bool allow_null_cond,
00347 int *error)
00348 {
00349 *error= 0;
00350
00351 if (! conds && ! allow_null_cond)
00352 {
00353 return 0;
00354 }
00355 optimizer::SqlSelect* select= new optimizer::SqlSelect;
00356 select->read_tables=read_tables;
00357 select->const_tables=const_tables;
00358 select->head=head;
00359 select->cond=conds;
00360
00361 if (head->sort.io_cache)
00362 {
00363 memcpy(select->file, head->sort.io_cache, sizeof(internal::io_cache_st));
00364 select->records=(ha_rows) (select->file->end_of_file/
00365 head->cursor->ref_length);
00366 delete head->sort.io_cache;
00367 head->sort.io_cache=0;
00368 }
00369 return(select);
00370 }
00371
00372
00373 optimizer::SqlSelect::SqlSelect()
00374 :
00375 quick(NULL),
00376 cond(NULL),
00377 file(static_cast<internal::io_cache_st *>(memory::sql_calloc(sizeof(internal::io_cache_st)))),
00378 free_cond(false)
00379 {
00380 quick_keys.reset();
00381 needed_reg.reset();
00382 file->clear();
00383 }
00384
00385
00386 void optimizer::SqlSelect::cleanup()
00387 {
00388 delete quick;
00389 quick= NULL;
00390
00391 if (free_cond)
00392 {
00393 free_cond= 0;
00394 delete cond;
00395 cond= 0;
00396 }
00397 file->close_cached_file();
00398 }
00399
00400
00401 optimizer::SqlSelect::~SqlSelect()
00402 {
00403 cleanup();
00404 }
00405
00406
00407 bool optimizer::SqlSelect::check_quick(Session *session,
00408 bool force_quick_range,
00409 ha_rows limit)
00410 {
00411 key_map tmp;
00412 tmp.set();
00413 return (test_quick_select(session,
00414 tmp,
00415 0,
00416 limit,
00417 force_quick_range,
00418 false) < 0);
00419 }
00420
00421
00422 bool optimizer::SqlSelect::skip_record()
00423 {
00424 return (cond ? cond->val_int() == 0 : 0);
00425 }
00426
00427
00428 optimizer::QuickSelectInterface::QuickSelectInterface()
00429 :
00430 max_used_key_length(0),
00431 used_key_parts(0)
00432 {}
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 uint32_t optimizer::get_index_for_order(Table *table, Order *order, ha_rows limit)
00465 {
00466 uint32_t idx;
00467 uint32_t match_key= MAX_KEY, match_key_len= MAX_KEY_LENGTH + 1;
00468 Order *ord;
00469
00470 for (ord= order; ord; ord= ord->next)
00471 if (!ord->asc)
00472 return MAX_KEY;
00473
00474 for (idx= 0; idx < table->getShare()->sizeKeys(); idx++)
00475 {
00476 if (!(table->keys_in_use_for_query.test(idx)))
00477 continue;
00478 KeyPartInfo *keyinfo= table->key_info[idx].key_part;
00479 uint32_t n_parts= table->key_info[idx].key_parts;
00480 uint32_t partno= 0;
00481
00482
00483
00484
00485
00486
00487 if (! (table->index_flags(idx) & HA_READ_ORDER))
00488 continue;
00489 for (ord= order; ord && partno < n_parts; ord= ord->next, partno++)
00490 {
00491 Item *item= order->item[0];
00492 if (! (item->type() == Item::FIELD_ITEM &&
00493 ((Item_field*)item)->field->eq(keyinfo[partno].field)))
00494 break;
00495 }
00496
00497 if (! ord && table->key_info[idx].key_length < match_key_len)
00498 {
00499
00500
00501
00502
00503
00504 match_key= idx;
00505 match_key_len= table->key_info[idx].key_length;
00506 }
00507 }
00508
00509 if (match_key != MAX_KEY)
00510 {
00511
00512
00513
00514
00515
00516 double full_scan_time= table->cursor->scan_time();
00517 double index_scan_time= table->cursor->read_time(match_key, 1, limit);
00518 if (index_scan_time > full_scan_time)
00519 match_key= MAX_KEY;
00520 }
00521 return match_key;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 static int fill_used_fields_bitmap(optimizer::Parameter *param)
00541 {
00542 Table *table= param->table;
00543 uint32_t pk;
00544 param->tmp_covered_fields.clear();
00545 param->needed_fields.resize(table->getShare()->sizeFields());
00546 param->needed_fields.reset();
00547
00548 param->needed_fields|= *table->read_set;
00549 param->needed_fields|= *table->write_set;
00550
00551 pk= param->table->getShare()->getPrimaryKey();
00552 if (pk != MAX_KEY && param->table->cursor->primary_key_is_clustered())
00553 {
00554
00555 KeyPartInfo *key_part= param->table->key_info[pk].key_part;
00556 KeyPartInfo *key_part_end= key_part +
00557 param->table->key_info[pk].key_parts;
00558 for (;key_part != key_part_end; ++key_part)
00559 param->needed_fields.reset(key_part->fieldnr-1);
00560 }
00561 return 0;
00562 }
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 int optimizer::SqlSelect::test_quick_select(Session *session,
00632 key_map keys_to_use,
00633 table_map prev_tables,
00634 ha_rows limit,
00635 bool force_quick_range,
00636 bool ordered_output)
00637 {
00638 uint32_t idx;
00639 double scan_time;
00640
00641 delete quick;
00642 quick= NULL;
00643
00644 needed_reg.reset();
00645 quick_keys.reset();
00646 if (keys_to_use.none())
00647 return 0;
00648 records= head->cursor->stats.records;
00649 if (!records)
00650 records++;
00651 scan_time= (double) records / TIME_FOR_COMPARE + 1;
00652 read_time= (double) head->cursor->scan_time() + scan_time + 1.1;
00653 if (head->force_index)
00654 scan_time= read_time= DBL_MAX;
00655 if (limit < records)
00656 read_time= (double) records + scan_time + 1;
00657 else if (read_time <= 2.0 && !force_quick_range)
00658 return 0;
00659
00660 keys_to_use&= head->keys_in_use_for_query;
00661 if (keys_to_use.any())
00662 {
00663 memory::Root alloc;
00664 optimizer::SEL_TREE *tree= NULL;
00665 KEY_PART *key_parts;
00666 KeyInfo *key_info;
00667 optimizer::Parameter param;
00668
00669 if (check_stack_overrun(session, 2*STACK_MIN_SIZE, NULL))
00670 return 0;
00671
00672
00673 param.session= session;
00674 param.prev_tables= prev_tables | const_tables;
00675 param.read_tables= read_tables;
00676 param.current_table= head->map;
00677 param.table=head;
00678 param.keys=0;
00679 param.mem_root= &alloc;
00680 param.old_root= session->mem_root;
00681 param.needed_reg= &needed_reg;
00682 param.imerge_cost_buff_size= 0;
00683 param.using_real_indexes= true;
00684 param.remove_jump_scans= true;
00685 param.force_default_mrr= ordered_output;
00686
00687 session->no_errors=1;
00688 alloc.init(session->variables.range_alloc_block_size);
00689 param.key_parts= new (alloc) KEY_PART[head->getShare()->key_parts];
00690 if (fill_used_fields_bitmap(¶m))
00691 {
00692 session->no_errors=0;
00693 alloc.free_root(MYF(0));
00694
00695 return 0;
00696 }
00697 key_parts= param.key_parts;
00698 session->mem_root= &alloc;
00699
00700
00701
00702
00703
00704 key_info= head->key_info;
00705 for (idx=0 ; idx < head->getShare()->sizeKeys() ; idx++, key_info++)
00706 {
00707 KeyPartInfo *key_part_info;
00708 if (! keys_to_use.test(idx))
00709 continue;
00710
00711 param.key[param.keys]=key_parts;
00712 key_part_info= key_info->key_part;
00713 for (uint32_t part=0;
00714 part < key_info->key_parts;
00715 part++, key_parts++, key_part_info++)
00716 {
00717 key_parts->key= param.keys;
00718 key_parts->part= part;
00719 key_parts->length= key_part_info->length;
00720 key_parts->store_length= key_part_info->store_length;
00721 key_parts->field= key_part_info->field;
00722 key_parts->null_bit= key_part_info->null_bit;
00723
00724 key_parts->flag= (uint8_t) key_part_info->key_part_flag;
00725 }
00726 param.real_keynr[param.keys++]=idx;
00727 }
00728 param.key_parts_end=key_parts;
00729 param.alloced_sel_args= 0;
00730
00731
00732 if (!head->covering_keys.none())
00733 {
00734 int key_for_use= head->find_shortest_key(&head->covering_keys);
00735 double key_read_time=
00736 param.table->cursor->index_only_read_time(key_for_use, records) +
00737 (double) records / TIME_FOR_COMPARE;
00738 if (key_read_time < read_time)
00739 read_time= key_read_time;
00740 }
00741
00742 optimizer::TableReadPlan *best_trp= NULL;
00743 optimizer::GroupMinMaxReadPlan *group_trp= NULL;
00744 double best_read_time= read_time;
00745
00746 if (cond)
00747 {
00748 if ((tree= get_mm_tree(¶m,cond)))
00749 {
00750 if (tree->type == optimizer::SEL_TREE::IMPOSSIBLE)
00751 {
00752 records=0L;
00753 read_time= (double) HA_POS_ERROR;
00754 goto free_mem;
00755 }
00756
00757
00758
00759
00760 if (tree->type != optimizer::SEL_TREE::KEY && tree->type != optimizer::SEL_TREE::KEY_SMALLER)
00761 tree= NULL;
00762 }
00763 }
00764
00765
00766
00767
00768
00769 group_trp= get_best_group_min_max(¶m, tree);
00770 if (group_trp)
00771 {
00772 param.table->quick_condition_rows= min(group_trp->records,
00773 head->cursor->stats.records);
00774 if (group_trp->read_cost < best_read_time)
00775 {
00776 best_trp= group_trp;
00777 best_read_time= best_trp->read_cost;
00778 }
00779 }
00780
00781 if (tree)
00782 {
00783
00784
00785
00786
00787 if (tree->merges.is_empty())
00788 {
00789 optimizer::RangeReadPlan *range_trp= NULL;
00790 optimizer::RorIntersectReadPlan *rori_trp= NULL;
00791 bool can_build_covering= false;
00792
00793
00794 if ((range_trp= get_key_scans_params(session, ¶m, tree, false, true,
00795 best_read_time)))
00796 {
00797 best_trp= range_trp;
00798 best_read_time= best_trp->read_cost;
00799 }
00800
00801
00802
00803
00804
00805
00806 if ((session->lex().sql_command != SQLCOM_DELETE))
00807 {
00808
00809
00810
00811
00812 if ((rori_trp= get_best_ror_intersect(¶m, tree, best_read_time,
00813 &can_build_covering)))
00814 {
00815 best_trp= rori_trp;
00816 best_read_time= best_trp->read_cost;
00817
00818
00819
00820
00821 if (!rori_trp->is_covering && can_build_covering &&
00822 (rori_trp= get_best_covering_ror_intersect(¶m, tree,
00823 best_read_time)))
00824 best_trp= rori_trp;
00825 }
00826 }
00827 }
00828 else
00829 {
00830
00831 optimizer::SEL_IMERGE *imerge= NULL;
00832 optimizer::TableReadPlan *best_conj_trp= NULL;
00833 optimizer::TableReadPlan *new_conj_trp= NULL;
00834 List<optimizer::SEL_IMERGE>::iterator it(tree->merges.begin());
00835 while ((imerge= it++))
00836 {
00837 new_conj_trp= get_best_disjunct_quick(session, ¶m, imerge, best_read_time);
00838 if (new_conj_trp)
00839 set_if_smaller(param.table->quick_condition_rows,
00840 new_conj_trp->records);
00841 if (!best_conj_trp || (new_conj_trp && new_conj_trp->read_cost <
00842 best_conj_trp->read_cost))
00843 best_conj_trp= new_conj_trp;
00844 }
00845 if (best_conj_trp)
00846 best_trp= best_conj_trp;
00847 }
00848 }
00849
00850 session->mem_root= param.old_root;
00851
00852
00853 if (best_trp)
00854 {
00855 records= best_trp->records;
00856 if (! (quick= best_trp->make_quick(¶m, true)) || quick->init())
00857 {
00858 delete quick;
00859 quick= NULL;
00860 }
00861 }
00862
00863 free_mem:
00864 alloc.free_root(MYF(0));
00865 session->mem_root= param.old_root;
00866 session->no_errors=0;
00867 }
00868
00869
00870
00871
00872
00873 return(records ? test(quick) : -1);
00874 }
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942 static
00943 optimizer::TableReadPlan *get_best_disjunct_quick(Session *session,
00944 optimizer::Parameter *param,
00945 optimizer::SEL_IMERGE *imerge,
00946 double read_time)
00947 {
00948 optimizer::SEL_TREE **ptree= NULL;
00949 optimizer::IndexMergeReadPlan *imerge_trp= NULL;
00950 uint32_t n_child_scans= imerge->trees_next - imerge->trees;
00951 optimizer::RangeReadPlan **range_scans= NULL;
00952 optimizer::RangeReadPlan **cur_child= NULL;
00953 optimizer::RangeReadPlan **cpk_scan= NULL;
00954 bool imerge_too_expensive= false;
00955 double imerge_cost= 0.0;
00956 ha_rows cpk_scan_records= 0;
00957 ha_rows non_cpk_scan_records= 0;
00958 bool pk_is_clustered= param->table->cursor->primary_key_is_clustered();
00959 bool all_scans_ror_able= true;
00960 bool all_scans_rors= true;
00961 uint32_t unique_calc_buff_size;
00962 optimizer::TableReadPlan **roru_read_plans= NULL;
00963 optimizer::TableReadPlan **cur_roru_plan= NULL;
00964 double roru_index_costs;
00965 ha_rows roru_total_records;
00966 double roru_intersect_part= 1.0;
00967
00968 range_scans= new (*param->mem_root) optimizer::RangeReadPlan*[n_child_scans];
00969
00970
00971
00972
00973
00974
00975 for (ptree= imerge->trees, cur_child= range_scans; ptree != imerge->trees_next; ptree++, cur_child++)
00976 {
00977 if (!(*cur_child= get_key_scans_params(session, param, *ptree, true, false, read_time)))
00978 {
00979
00980
00981
00982
00983
00984
00985 imerge_too_expensive= true;
00986 }
00987 if (imerge_too_expensive)
00988 continue;
00989
00990 imerge_cost += (*cur_child)->read_cost;
00991 all_scans_ror_able &= ((*ptree)->n_ror_scans > 0);
00992 all_scans_rors &= (*cur_child)->is_ror;
00993 if (pk_is_clustered &&
00994 param->real_keynr[(*cur_child)->key_idx] ==
00995 param->table->getShare()->getPrimaryKey())
00996 {
00997 cpk_scan= cur_child;
00998 cpk_scan_records= (*cur_child)->records;
00999 }
01000 else
01001 non_cpk_scan_records += (*cur_child)->records;
01002 }
01003
01004 if (imerge_too_expensive || (imerge_cost > read_time) ||
01005 ((non_cpk_scan_records+cpk_scan_records >= param->table->cursor->stats.records) && read_time != DBL_MAX))
01006 {
01007
01008
01009
01010
01011 return NULL;
01012 }
01013 if (all_scans_rors)
01014 {
01015 roru_read_plans= (optimizer::TableReadPlan **) range_scans;
01016 goto skip_to_ror_scan;
01017 }
01018 if (cpk_scan)
01019 {
01020
01021
01022
01023
01024 imerge_cost += non_cpk_scan_records / TIME_FOR_COMPARE_ROWID;
01025 }
01026
01027
01028 {
01029 optimizer::CostVector sweep_cost;
01030 Join *join= param->session->lex().select_lex.join;
01031 bool is_interrupted= test(join && join->tables == 1);
01032 get_sweep_read_cost(param->table, non_cpk_scan_records, is_interrupted,
01033 &sweep_cost);
01034 imerge_cost += sweep_cost.total_cost();
01035 }
01036 if (imerge_cost > read_time)
01037 goto build_ror_index_merge;
01038
01039
01040 unique_calc_buff_size=
01041 Unique::get_cost_calc_buff_size((ulong)non_cpk_scan_records,
01042 param->table->cursor->ref_length,
01043 param->session->variables.sortbuff_size);
01044 if (param->imerge_cost_buff_size < unique_calc_buff_size)
01045 {
01046 param->imerge_cost_buff= (uint*)param->mem_root->alloc(unique_calc_buff_size);
01047 param->imerge_cost_buff_size= unique_calc_buff_size;
01048 }
01049
01050 imerge_cost +=
01051 Unique::get_use_cost(param->imerge_cost_buff, (uint32_t)non_cpk_scan_records,
01052 param->table->cursor->ref_length,
01053 param->session->variables.sortbuff_size);
01054 if (imerge_cost < read_time)
01055 {
01056 imerge_trp= new (*param->mem_root) optimizer::IndexMergeReadPlan;
01057 imerge_trp->read_cost= imerge_cost;
01058 imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
01059 imerge_trp->records= min(imerge_trp->records, param->table->cursor->stats.records);
01060 imerge_trp->range_scans= range_scans;
01061 imerge_trp->range_scans_end= range_scans + n_child_scans;
01062 read_time= imerge_cost;
01063 }
01064
01065 build_ror_index_merge:
01066 if (!all_scans_ror_able || param->session->lex().sql_command == SQLCOM_DELETE)
01067 return(imerge_trp);
01068
01069
01070 bool dummy;
01071 roru_read_plans= new (*param->mem_root) optimizer::TableReadPlan*[n_child_scans];
01072 skip_to_ror_scan:
01073 roru_index_costs= 0.0;
01074 roru_total_records= 0;
01075 cur_roru_plan= roru_read_plans;
01076
01077
01078 for (ptree= imerge->trees, cur_child= range_scans;
01079 ptree != imerge->trees_next;
01080 ptree++, cur_child++, cur_roru_plan++)
01081 {
01082
01083
01084
01085
01086
01087
01088 double cost;
01089 if ((*cur_child)->is_ror)
01090 {
01091
01092 cost= param->table->cursor->
01093 read_time(param->real_keynr[(*cur_child)->key_idx], 1,
01094 (*cur_child)->records) +
01095 static_cast<double>((*cur_child)->records) / TIME_FOR_COMPARE;
01096 }
01097 else
01098 cost= read_time;
01099
01100 optimizer::TableReadPlan *prev_plan= *cur_child;
01101 if (!(*cur_roru_plan= get_best_ror_intersect(param, *ptree, cost,
01102 &dummy)))
01103 {
01104 if (prev_plan->is_ror)
01105 *cur_roru_plan= prev_plan;
01106 else
01107 return(imerge_trp);
01108 roru_index_costs += (*cur_roru_plan)->read_cost;
01109 }
01110 else
01111 roru_index_costs +=
01112 ((optimizer::RorIntersectReadPlan*)(*cur_roru_plan))->index_scan_costs;
01113 roru_total_records += (*cur_roru_plan)->records;
01114 roru_intersect_part *= (*cur_roru_plan)->records /
01115 param->table->cursor->stats.records;
01116 }
01117
01118
01119
01120
01121
01122
01123
01124 roru_total_records -= (ha_rows)(roru_intersect_part*
01125 param->table->cursor->stats.records);
01126
01127
01128
01129
01130
01131
01132
01133
01134 double roru_total_cost;
01135 {
01136 optimizer::CostVector sweep_cost;
01137 Join *join= param->session->lex().select_lex.join;
01138 bool is_interrupted= test(join && join->tables == 1);
01139 get_sweep_read_cost(param->table, roru_total_records, is_interrupted,
01140 &sweep_cost);
01141 roru_total_cost= roru_index_costs +
01142 static_cast<double>(roru_total_records)*log((double)n_child_scans) /
01143 (TIME_FOR_COMPARE_ROWID * M_LN2) +
01144 sweep_cost.total_cost();
01145 }
01146
01147 optimizer::RorUnionReadPlan *roru= NULL;
01148 if (roru_total_cost < read_time)
01149 {
01150 if ((roru= new (*param->mem_root) optimizer::RorUnionReadPlan))
01151 {
01152 roru->first_ror= roru_read_plans;
01153 roru->last_ror= roru_read_plans + n_child_scans;
01154 roru->read_cost= roru_total_cost;
01155 roru->records= roru_total_records;
01156 return roru;
01157 }
01158 }
01159 return(imerge_trp);
01160 }
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179 static
01180 optimizer::RorScanInfo *make_ror_scan(const optimizer::Parameter *param, int idx, optimizer::SEL_ARG *sel_arg)
01181 {
01182 uint32_t keynr;
01183 optimizer::RorScanInfo* ror_scan= new (*param->mem_root) optimizer::RorScanInfo;
01184
01185 ror_scan->idx= idx;
01186 ror_scan->keynr= keynr= param->real_keynr[idx];
01187 ror_scan->key_rec_length= (param->table->key_info[keynr].key_length +
01188 param->table->cursor->ref_length);
01189 ror_scan->sel_arg= sel_arg;
01190 ror_scan->records= param->table->quick_rows[keynr];
01191
01192 ror_scan->covered_fields_size= param->table->getShare()->sizeFields();
01193 boost::dynamic_bitset<> tmp_bitset(param->table->getShare()->sizeFields());
01194 tmp_bitset.reset();
01195
01196 KeyPartInfo *key_part= param->table->key_info[keynr].key_part;
01197 KeyPartInfo *key_part_end= key_part +
01198 param->table->key_info[keynr].key_parts;
01199 for (; key_part != key_part_end; ++key_part)
01200 {
01201 if (param->needed_fields.test(key_part->fieldnr-1))
01202 tmp_bitset.set(key_part->fieldnr-1);
01203 }
01204 double rows= param->table->quick_rows[ror_scan->keynr];
01205 ror_scan->index_read_cost=
01206 param->table->cursor->index_only_read_time(ror_scan->keynr, rows);
01207 ror_scan->covered_fields= tmp_bitset.to_ulong();
01208 return ror_scan;
01209 }
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 static int cmp_ror_scan_info(optimizer::RorScanInfo** a, optimizer::RorScanInfo** b)
01226 {
01227 double val1= static_cast<double>((*a)->records) * (*a)->key_rec_length;
01228 double val2= static_cast<double>((*b)->records) * (*b)->key_rec_length;
01229 return (val1 < val2)? -1: (val1 == val2)? 0 : 1;
01230 }
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250 static int cmp_ror_scan_info_covering(optimizer::RorScanInfo** a, optimizer::RorScanInfo** b)
01251 {
01252 if ((*a)->used_fields_covered > (*b)->used_fields_covered)
01253 return -1;
01254 if ((*a)->used_fields_covered < (*b)->used_fields_covered)
01255 return 1;
01256 if ((*a)->key_components < (*b)->key_components)
01257 return -1;
01258 if ((*a)->key_components > (*b)->key_components)
01259 return 1;
01260 if ((*a)->first_uncovered_field < (*b)->first_uncovered_field)
01261 return -1;
01262 if ((*a)->first_uncovered_field > (*b)->first_uncovered_field)
01263 return 1;
01264 return 0;
01265 }
01266
01267
01268 typedef struct st_ror_intersect_info
01269 {
01270 st_ror_intersect_info()
01271 :
01272 param(NULL),
01273 covered_fields(),
01274 out_rows(0.0),
01275 is_covering(false),
01276 index_records(0),
01277 index_scan_costs(0.0),
01278 total_cost(0.0)
01279 {}
01280
01281 st_ror_intersect_info(const optimizer::Parameter *in_param)
01282 :
01283 param(in_param),
01284 covered_fields(in_param->table->getShare()->sizeFields()),
01285 out_rows(in_param->table->cursor->stats.records),
01286 is_covering(false),
01287 index_records(0),
01288 index_scan_costs(0.0),
01289 total_cost(0.0)
01290 {
01291 covered_fields.reset();
01292 }
01293
01294 const optimizer::Parameter *param;
01295 boost::dynamic_bitset<> covered_fields;
01296
01297
01298
01299
01300
01301 double out_rows;
01302
01303 bool is_covering;
01304
01305 ha_rows index_records;
01306 double index_scan_costs;
01307 double total_cost;
01308 } ROR_INTERSECT_INFO;
01309
01310
01311 static void ror_intersect_cpy(ROR_INTERSECT_INFO *dst,
01312 const ROR_INTERSECT_INFO *src)
01313 {
01314 dst->param= src->param;
01315 dst->covered_fields= src->covered_fields;
01316 dst->out_rows= src->out_rows;
01317 dst->is_covering= src->is_covering;
01318 dst->index_records= src->index_records;
01319 dst->index_scan_costs= src->index_scan_costs;
01320 dst->total_cost= src->total_cost;
01321 }
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414 static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
01415 const optimizer::RorScanInfo *scan)
01416 {
01417 double selectivity_mult= 1.0;
01418 KeyPartInfo *key_part= info->param->table->key_info[scan->keynr].key_part;
01419 unsigned char key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
01420 unsigned char *key_ptr= key_val;
01421 optimizer::SEL_ARG *sel_arg= NULL;
01422 optimizer::SEL_ARG *tuple_arg= NULL;
01423 key_part_map keypart_map= 0;
01424 bool cur_covered;
01425 bool prev_covered= test(info->covered_fields.test(key_part->fieldnr-1));
01426 key_range min_range;
01427 key_range max_range;
01428 min_range.key= key_val;
01429 min_range.flag= HA_READ_KEY_EXACT;
01430 max_range.key= key_val;
01431 max_range.flag= HA_READ_AFTER_KEY;
01432 ha_rows prev_records= info->param->table->cursor->stats.records;
01433
01434 for (sel_arg= scan->sel_arg; sel_arg;
01435 sel_arg= sel_arg->next_key_part)
01436 {
01437 cur_covered=
01438 test(info->covered_fields.test(key_part[sel_arg->part].fieldnr-1));
01439 if (cur_covered != prev_covered)
01440 {
01441
01442 ha_rows records;
01443 if (!tuple_arg)
01444 {
01445 tuple_arg= scan->sel_arg;
01446
01447 tuple_arg->store_min(key_part->store_length, &key_ptr, 0);
01448 keypart_map= 1;
01449 }
01450 while (tuple_arg->next_key_part != sel_arg)
01451 {
01452 tuple_arg= tuple_arg->next_key_part;
01453 tuple_arg->store_min(key_part[tuple_arg->part].store_length,
01454 &key_ptr, 0);
01455 keypart_map= (keypart_map << 1) | 1;
01456 }
01457 min_range.length= max_range.length= (size_t) (key_ptr - key_val);
01458 min_range.keypart_map= max_range.keypart_map= keypart_map;
01459 records= (info->param->table->cursor->
01460 records_in_range(scan->keynr, &min_range, &max_range));
01461 if (cur_covered)
01462 {
01463
01464 selectivity_mult *= static_cast<double>(records) / prev_records;
01465 prev_records= HA_POS_ERROR;
01466 }
01467 else
01468 {
01469
01470 prev_records= records;
01471 }
01472 }
01473 prev_covered= cur_covered;
01474 }
01475 if (!prev_covered)
01476 {
01477 selectivity_mult *= static_cast<double>(info->param->table->quick_rows[scan->keynr]) / prev_records;
01478 }
01479 return selectivity_mult;
01480 }
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519 static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
01520 optimizer::RorScanInfo* ror_scan, bool is_cpk_scan)
01521 {
01522 double selectivity_mult= 1.0;
01523
01524 selectivity_mult = ror_scan_selectivity(info, ror_scan);
01525 if (selectivity_mult == 1.0)
01526 {
01527
01528 return false;
01529 }
01530
01531 info->out_rows *= selectivity_mult;
01532
01533 if (is_cpk_scan)
01534 {
01535
01536
01537
01538
01539
01540 info->index_scan_costs += static_cast<double>(info->index_records) /
01541 TIME_FOR_COMPARE_ROWID;
01542 }
01543 else
01544 {
01545 info->index_records += info->param->table->quick_rows[ror_scan->keynr];
01546 info->index_scan_costs += ror_scan->index_read_cost;
01547 boost::dynamic_bitset<> tmp_bitset= ror_scan->bitsToBitset();
01548 info->covered_fields|= tmp_bitset;
01549 if (! info->is_covering && info->param->needed_fields.is_subset_of(info->covered_fields))
01550 {
01551 info->is_covering= true;
01552 }
01553 }
01554
01555 info->total_cost= info->index_scan_costs;
01556 if (! info->is_covering)
01557 {
01558 optimizer::CostVector sweep_cost;
01559 Join *join= info->param->session->lex().select_lex.join;
01560 bool is_interrupted= test(join && join->tables == 1);
01561 get_sweep_read_cost(info->param->table, double2rows(info->out_rows),
01562 is_interrupted, &sweep_cost);
01563 info->total_cost += sweep_cost.total_cost();
01564 }
01565 return true;
01566 }
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602 static
01603 optimizer::RorIntersectReadPlan *get_best_covering_ror_intersect(optimizer::Parameter *param,
01604 optimizer::SEL_TREE *tree,
01605 double read_time)
01606 {
01607 optimizer::RorScanInfo **ror_scan_mark;
01608 optimizer::RorScanInfo **ror_scans_end= tree->ror_scans_end;
01609
01610 for (optimizer::RorScanInfo **scan= tree->ror_scans; scan != ror_scans_end; ++scan)
01611 (*scan)->key_components=
01612 param->table->key_info[(*scan)->keynr].key_parts;
01613
01614
01615
01616
01617
01618
01619
01620 ror_scan_mark= tree->ror_scans;
01621
01622 boost::dynamic_bitset<> *covered_fields= ¶m->tmp_covered_fields;
01623 if (covered_fields->empty())
01624 {
01625 covered_fields->resize(param->table->getShare()->sizeFields());
01626 }
01627 covered_fields->reset();
01628
01629 double total_cost= 0.0f;
01630 ha_rows records=0;
01631 bool all_covered;
01632
01633 do
01634 {
01635
01636
01637
01638
01639
01640
01641 for (optimizer::RorScanInfo **scan= ror_scan_mark; scan != ror_scans_end; ++scan)
01642 {
01643
01644 (*scan)->subtractBitset(*covered_fields);
01645 (*scan)->used_fields_covered=
01646 (*scan)->getBitCount();
01647 (*scan)->first_uncovered_field= (*scan)->findFirstNotSet();
01648 }
01649
01650 internal::my_qsort(ror_scan_mark, ror_scans_end-ror_scan_mark,
01651 sizeof(optimizer::RorScanInfo*),
01652 (qsort_cmp)cmp_ror_scan_info_covering);
01653
01654
01655 total_cost += (*ror_scan_mark)->index_read_cost;
01656 records += (*ror_scan_mark)->records;
01657 if (total_cost > read_time)
01658 return NULL;
01659
01660 boost::dynamic_bitset<> tmp_bitset= (*ror_scan_mark)->bitsToBitset();
01661 *covered_fields|= tmp_bitset;
01662 all_covered= param->needed_fields.is_subset_of(*covered_fields);
01663 } while ((++ror_scan_mark < ror_scans_end) && ! all_covered);
01664
01665 if (!all_covered || (ror_scan_mark - tree->ror_scans) == 1)
01666 return NULL;
01667
01668
01669
01670
01671
01672
01673 total_cost += static_cast<double>(records) *
01674 log((double)(ror_scan_mark - tree->ror_scans)) /
01675 (TIME_FOR_COMPARE_ROWID * M_LN2);
01676
01677 if (total_cost > read_time)
01678 return NULL;
01679
01680 optimizer::RorIntersectReadPlan* trp= new (*param->mem_root) optimizer::RorIntersectReadPlan;
01681
01682 uint32_t best_num= (ror_scan_mark - tree->ror_scans);
01683 trp->first_scan= new (*param->mem_root) optimizer::RorScanInfo*[best_num];
01684 memcpy(trp->first_scan, tree->ror_scans, best_num*sizeof(optimizer::RorScanInfo*));
01685 trp->last_scan= trp->first_scan + best_num;
01686 trp->is_covering= true;
01687 trp->read_cost= total_cost;
01688 trp->records= records;
01689 trp->cpk_scan= NULL;
01690 set_if_smaller(param->table->quick_condition_rows, records);
01691
01692 return(trp);
01693 }
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760 static
01761 optimizer::RorIntersectReadPlan *get_best_ror_intersect(const optimizer::Parameter *param,
01762 optimizer::SEL_TREE *tree,
01763 double read_time,
01764 bool *are_all_covering)
01765 {
01766 uint32_t idx= 0;
01767 double min_cost= DBL_MAX;
01768
01769 if ((tree->n_ror_scans < 2) || ! param->table->cursor->stats.records)
01770 return NULL;
01771
01772
01773
01774
01775
01776 optimizer::RorScanInfo **cur_ror_scan= NULL;
01777 optimizer::RorScanInfo *cpk_scan= NULL;
01778 uint32_t cpk_no= 0;
01779 bool cpk_scan_used= false;
01780
01781 tree->ror_scans= new (*param->mem_root) optimizer::RorScanInfo*[param->keys];
01782 cpk_no= ((param->table->cursor->primary_key_is_clustered()) ? param->table->getShare()->getPrimaryKey() : MAX_KEY);
01783
01784 for (idx= 0, cur_ror_scan= tree->ror_scans; idx < param->keys; idx++)
01785 {
01786 optimizer::RorScanInfo *scan;
01787 if (! tree->ror_scans_map.test(idx))
01788 continue;
01789 if (! (scan= make_ror_scan(param, idx, tree->keys[idx])))
01790 return NULL;
01791 if (param->real_keynr[idx] == cpk_no)
01792 {
01793 cpk_scan= scan;
01794 tree->n_ror_scans--;
01795 }
01796 else
01797 *(cur_ror_scan++)= scan;
01798 }
01799
01800 tree->ror_scans_end= cur_ror_scan;
01801
01802
01803
01804
01805
01806 internal::my_qsort(tree->ror_scans, tree->n_ror_scans, sizeof(optimizer::RorScanInfo*),
01807 (qsort_cmp)cmp_ror_scan_info);
01808
01809 optimizer::RorScanInfo **intersect_scans= NULL;
01810 optimizer::RorScanInfo **intersect_scans_end= intersect_scans= new (*param->mem_root) optimizer::RorScanInfo*[tree->n_ror_scans];
01811 intersect_scans_end= intersect_scans;
01812
01813
01814 ROR_INTERSECT_INFO intersect(param);
01815 ROR_INTERSECT_INFO intersect_best(param);
01816
01817
01818 optimizer::RorScanInfo **intersect_scans_best= NULL;
01819 cur_ror_scan= tree->ror_scans;
01820 intersect_scans_best= intersect_scans;
01821 while (cur_ror_scan != tree->ror_scans_end && ! intersect.is_covering)
01822 {
01823
01824 if (! ror_intersect_add(&intersect, *cur_ror_scan, false))
01825 {
01826 cur_ror_scan++;
01827 continue;
01828 }
01829
01830 *(intersect_scans_end++)= *(cur_ror_scan++);
01831
01832 if (intersect.total_cost < min_cost)
01833 {
01834
01835 ror_intersect_cpy(&intersect_best, &intersect);
01836 intersect_scans_best= intersect_scans_end;
01837 min_cost = intersect.total_cost;
01838 }
01839 }
01840
01841 if (intersect_scans_best == intersect_scans)
01842 {
01843 return NULL;
01844 }
01845
01846 *are_all_covering= intersect.is_covering;
01847 uint32_t best_num= intersect_scans_best - intersect_scans;
01848 ror_intersect_cpy(&intersect, &intersect_best);
01849
01850
01851
01852
01853
01854
01855 if (cpk_scan && ! intersect.is_covering)
01856 {
01857 if (ror_intersect_add(&intersect, cpk_scan, true) &&
01858 (intersect.total_cost < min_cost))
01859 {
01860 cpk_scan_used= true;
01861 intersect_best= intersect;
01862 }
01863 }
01864
01865
01866 optimizer::RorIntersectReadPlan *trp= NULL;
01867 if (min_cost < read_time && (cpk_scan_used || best_num > 1))
01868 {
01869 trp= new (*param->mem_root) optimizer::RorIntersectReadPlan;
01870 trp->first_scan= new (*param->mem_root) optimizer::RorScanInfo*[best_num];
01871 memcpy(trp->first_scan, intersect_scans, best_num*sizeof(optimizer::RorScanInfo*));
01872 trp->last_scan= trp->first_scan + best_num;
01873 trp->is_covering= intersect_best.is_covering;
01874 trp->read_cost= intersect_best.total_cost;
01875
01876 ha_rows best_rows = double2rows(intersect_best.out_rows);
01877 if (! best_rows)
01878 best_rows= 1;
01879 set_if_smaller(param->table->quick_condition_rows, best_rows);
01880 trp->records= best_rows;
01881 trp->index_scan_costs= intersect_best.index_scan_costs;
01882 trp->cpk_scan= cpk_scan_used? cpk_scan: NULL;
01883 }
01884 return trp;
01885 }
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915 static optimizer::RangeReadPlan *get_key_scans_params(Session *session,
01916 optimizer::Parameter *param,
01917 optimizer::SEL_TREE *tree,
01918 bool index_read_must_be_used,
01919 bool update_tbl_stats,
01920 double read_time)
01921 {
01922 uint32_t idx;
01923 optimizer::SEL_ARG **key= NULL;
01924 optimizer::SEL_ARG **end= NULL;
01925 optimizer::SEL_ARG **key_to_read= NULL;
01926 ha_rows best_records= 0;
01927 uint32_t best_mrr_flags= 0;
01928 uint32_t best_buf_size= 0;
01929 optimizer::RangeReadPlan *read_plan= NULL;
01930
01931
01932
01933
01934
01935 tree->ror_scans_map.reset();
01936 tree->n_ror_scans= 0;
01937 for (idx= 0,key=tree->keys, end=key+param->keys; key != end; key++,idx++)
01938 {
01939 if (*key)
01940 {
01941 ha_rows found_records;
01942 optimizer::CostVector cost;
01943 double found_read_time= 0.0;
01944 uint32_t mrr_flags, buf_size;
01945 uint32_t keynr= param->real_keynr[idx];
01946 if ((*key)->type == optimizer::SEL_ARG::MAYBE_KEY ||
01947 (*key)->maybe_flag)
01948 param->needed_reg->set(keynr);
01949
01950 bool read_index_only= index_read_must_be_used ||
01951 param->table->covering_keys.test(keynr);
01952
01953 found_records= check_quick_select(session, param, idx, read_index_only, *key,
01954 update_tbl_stats, &mrr_flags,
01955 &buf_size, &cost);
01956 found_read_time= cost.total_cost();
01957 if ((found_records != HA_POS_ERROR) && param->is_ror_scan)
01958 {
01959 tree->n_ror_scans++;
01960 tree->ror_scans_map.set(idx);
01961 }
01962 if (read_time > found_read_time && found_records != HA_POS_ERROR)
01963 {
01964 read_time= found_read_time;
01965 best_records= found_records;
01966 key_to_read= key;
01967 best_mrr_flags= mrr_flags;
01968 best_buf_size= buf_size;
01969 }
01970 }
01971 }
01972
01973 if (key_to_read)
01974 {
01975 idx= key_to_read - tree->keys;
01976 read_plan= new (*param->mem_root) optimizer::RangeReadPlan(*key_to_read, idx, best_mrr_flags);
01977 read_plan->records= best_records;
01978 read_plan->is_ror= tree->ror_scans_map.test(idx);
01979 read_plan->read_cost= read_time;
01980 read_plan->mrr_buf_size= best_buf_size;
01981 }
01982 return read_plan;
01983 }
01984
01985
01986 optimizer::QuickSelectInterface *optimizer::IndexMergeReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *)
01987 {
01988
01989 optimizer::QuickIndexMergeSelect* quick_imerge= new optimizer::QuickIndexMergeSelect(param->session, param->table);
01990 quick_imerge->records= records;
01991 quick_imerge->read_time= read_cost;
01992 for (optimizer::RangeReadPlan **range_scan= range_scans; range_scan != range_scans_end; range_scan++)
01993 {
01994 optimizer::QuickRangeSelect* quick= (optimizer::QuickRangeSelect*)((*range_scan)->make_quick(param, false, &quick_imerge->alloc));
01995 if (not quick)
01996 {
01997 delete quick;
01998 delete quick_imerge;
01999 return NULL;
02000 }
02001 quick_imerge->push_quick_back(quick);
02002 }
02003 return quick_imerge;
02004 }
02005
02006 optimizer::QuickSelectInterface *optimizer::RorIntersectReadPlan::make_quick(optimizer::Parameter *param,
02007 bool retrieve_full_rows,
02008 memory::Root *parent_alloc)
02009 {
02010 optimizer::QuickRorIntersectSelect *quick_intersect= NULL;
02011 optimizer::QuickRangeSelect *quick= NULL;
02012 memory::Root *alloc= NULL;
02013
02014 if ((quick_intersect=
02015 new optimizer::QuickRorIntersectSelect(param->session,
02016 param->table,
02017 (retrieve_full_rows? (! is_covering) : false),
02018 parent_alloc)))
02019 {
02020 alloc= parent_alloc ? parent_alloc : &quick_intersect->alloc;
02021 for (; first_scan != last_scan; ++first_scan)
02022 {
02023 if (! (quick= optimizer::get_quick_select(param,
02024 (*first_scan)->idx,
02025 (*first_scan)->sel_arg,
02026 HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED,
02027 0,
02028 alloc)))
02029 {
02030 delete quick_intersect;
02031 return NULL;
02032 }
02033 quick_intersect->push_quick_back(quick);
02034 }
02035 if (cpk_scan)
02036 {
02037 if (! (quick= optimizer::get_quick_select(param,
02038 cpk_scan->idx,
02039 cpk_scan->sel_arg,
02040 HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED,
02041 0,
02042 alloc)))
02043 {
02044 delete quick_intersect;
02045 return NULL;
02046 }
02047 quick->resetCursor();
02048 quick_intersect->cpk_quick= quick;
02049 }
02050 quick_intersect->records= records;
02051 quick_intersect->read_time= read_cost;
02052 }
02053 return quick_intersect;
02054 }
02055
02056
02057 optimizer::QuickSelectInterface *optimizer::RorUnionReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *)
02058 {
02059
02060
02061
02062
02063 optimizer::QuickRorUnionSelect* quick_roru= new optimizer::QuickRorUnionSelect(param->session, param->table);
02064 for (optimizer::TableReadPlan** scan= first_ror; scan != last_ror; scan++)
02065 {
02066 optimizer::QuickSelectInterface* quick= (*scan)->make_quick(param, false, &quick_roru->alloc);
02067 if (not quick)
02068 return NULL;
02069 quick_roru->push_quick_back(quick);
02070 }
02071 quick_roru->records= records;
02072 quick_roru->read_time= read_cost;
02073 return quick_roru;
02074 }
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093 static optimizer::SEL_TREE *get_ne_mm_tree(optimizer::RangeParameter *param,
02094 Item_func *cond_func,
02095 Field *field,
02096 Item *lt_value, Item *gt_value,
02097 Item_result cmp_type)
02098 {
02099 optimizer::SEL_TREE *tree= NULL;
02100 tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
02101 lt_value, cmp_type);
02102 if (tree)
02103 {
02104 tree= tree_or(param,
02105 tree,
02106 get_mm_parts(param, cond_func, field,
02107 Item_func::GT_FUNC,
02108 gt_value,
02109 cmp_type));
02110 }
02111 return tree;
02112 }
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131 static optimizer::SEL_TREE *get_func_mm_tree(optimizer::RangeParameter *param,
02132 Item_func *cond_func,
02133 Field *field,
02134 Item *value,
02135 Item_result cmp_type,
02136 bool inv)
02137 {
02138 optimizer::SEL_TREE *tree= NULL;
02139
02140 switch (cond_func->functype())
02141 {
02142
02143 case Item_func::NE_FUNC:
02144 tree= get_ne_mm_tree(param, cond_func, field, value, value, cmp_type);
02145 break;
02146
02147 case Item_func::BETWEEN:
02148 {
02149 if (! value)
02150 {
02151 if (inv)
02152 {
02153 tree= get_ne_mm_tree(param,
02154 cond_func,
02155 field,
02156 cond_func->arguments()[1],
02157 cond_func->arguments()[2],
02158 cmp_type);
02159 }
02160 else
02161 {
02162 tree= get_mm_parts(param,
02163 cond_func,
02164 field,
02165 Item_func::GE_FUNC,
02166 cond_func->arguments()[1],
02167 cmp_type);
02168 if (tree)
02169 {
02170 tree= tree_and(param,
02171 tree,
02172 get_mm_parts(param, cond_func, field,
02173 Item_func::LE_FUNC,
02174 cond_func->arguments()[2],
02175 cmp_type));
02176 }
02177 }
02178 }
02179 else
02180 tree= get_mm_parts(param,
02181 cond_func,
02182 field,
02183 (inv ?
02184 (value == (Item*)1 ? Item_func::GT_FUNC :
02185 Item_func::LT_FUNC):
02186 (value == (Item*)1 ? Item_func::LE_FUNC :
02187 Item_func::GE_FUNC)),
02188 cond_func->arguments()[0],
02189 cmp_type);
02190 break;
02191 }
02192 case Item_func::IN_FUNC:
02193 {
02194 Item_func_in *func= (Item_func_in*) cond_func;
02195
02196
02197
02198
02199
02200
02201 if (! func->arg_types_compatible)
02202 break;
02203
02204 if (inv)
02205 {
02206 if (func->array && func->array->result_type() != ROW_RESULT)
02207 {
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235 const unsigned int NOT_IN_IGNORE_THRESHOLD= 1000;
02236 memory::Root *tmp_root= param->mem_root;
02237 param->session->mem_root= param->old_root;
02238
02239
02240
02241
02242
02243
02244
02245
02246 Item *value_item= func->array->create_item();
02247 param->session->mem_root= tmp_root;
02248
02249 if (func->array->count > NOT_IN_IGNORE_THRESHOLD || ! value_item)
02250 break;
02251
02252
02253 uint32_t i=0;
02254 do
02255 {
02256 func->array->value_to_item(i, value_item);
02257 tree= get_mm_parts(param,
02258 cond_func,
02259 field, Item_func::LT_FUNC,
02260 value_item,
02261 cmp_type);
02262 if (! tree)
02263 break;
02264 i++;
02265 } while (i < func->array->count && tree->type == optimizer::SEL_TREE::IMPOSSIBLE);
02266
02267 if (!tree || tree->type == optimizer::SEL_TREE::IMPOSSIBLE)
02268 {
02269
02270 tree= NULL;
02271 break;
02272 }
02273 optimizer::SEL_TREE *tree2= NULL;
02274 for (; i < func->array->count; i++)
02275 {
02276 if (func->array->compare_elems(i, i-1))
02277 {
02278
02279 func->array->value_to_item(i, value_item);
02280 tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
02281 value_item, cmp_type);
02282 if (!tree2)
02283 {
02284 tree= NULL;
02285 break;
02286 }
02287
02288
02289 for (uint32_t idx= 0; idx < param->keys; idx++)
02290 {
02291 optimizer::SEL_ARG *new_interval, *last_val;
02292 if (((new_interval= tree2->keys[idx])) &&
02293 (tree->keys[idx]) &&
02294 ((last_val= tree->keys[idx]->last())))
02295 {
02296 new_interval->min_value= last_val->max_value;
02297 new_interval->min_flag= NEAR_MIN;
02298 }
02299 }
02300
02301
02302
02303
02304 tree= tree_or(param, tree, tree2);
02305 }
02306 }
02307
02308 if (tree && tree->type != optimizer::SEL_TREE::IMPOSSIBLE)
02309 {
02310
02311
02312
02313
02314 tree2= get_mm_parts(param, cond_func, field, Item_func::GT_FUNC,
02315 value_item, cmp_type);
02316 tree= tree_or(param, tree, tree2);
02317 }
02318 }
02319 else
02320 {
02321 tree= get_ne_mm_tree(param, cond_func, field,
02322 func->arguments()[1], func->arguments()[1],
02323 cmp_type);
02324 if (tree)
02325 {
02326 Item **arg, **end;
02327 for (arg= func->arguments()+2, end= arg+func->argument_count()-2;
02328 arg < end ; arg++)
02329 {
02330 tree= tree_and(param, tree, get_ne_mm_tree(param, cond_func, field,
02331 *arg, *arg, cmp_type));
02332 }
02333 }
02334 }
02335 }
02336 else
02337 {
02338 tree= get_mm_parts(param, cond_func, field, Item_func::EQ_FUNC,
02339 func->arguments()[1], cmp_type);
02340 if (tree)
02341 {
02342 Item **arg, **end;
02343 for (arg= func->arguments()+2, end= arg+func->argument_count()-2;
02344 arg < end ; arg++)
02345 {
02346 tree= tree_or(param, tree, get_mm_parts(param, cond_func, field,
02347 Item_func::EQ_FUNC,
02348 *arg, cmp_type));
02349 }
02350 }
02351 }
02352 break;
02353 }
02354 default:
02355 {
02356
02357
02358
02359
02360
02361
02362
02363 Item_func::Functype func_type=
02364 (value != cond_func->arguments()[0]) ? cond_func->functype() :
02365 ((Item_bool_func2*) cond_func)->rev_functype();
02366 tree= get_mm_parts(param, cond_func, field, func_type, value, cmp_type);
02367 }
02368 }
02369
02370 return(tree);
02371 }
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444 static optimizer::SEL_TREE *get_full_func_mm_tree(optimizer::RangeParameter *param,
02445 Item_func *cond_func,
02446 Item_field *field_item, Item *value,
02447 bool inv)
02448 {
02449 optimizer::SEL_TREE *tree= 0;
02450 optimizer::SEL_TREE *ftree= 0;
02451 table_map ref_tables= 0;
02452 table_map param_comp= ~(param->prev_tables | param->read_tables |
02453 param->current_table);
02454
02455 for (uint32_t i= 0; i < cond_func->arg_count; i++)
02456 {
02457 Item *arg= cond_func->arguments()[i]->real_item();
02458 if (arg != field_item)
02459 ref_tables|= arg->used_tables();
02460 }
02461
02462 Field *field= field_item->field;
02463 field->setWriteSet();
02464
02465 Item_result cmp_type= field->cmp_type();
02466 if (!((ref_tables | field->getTable()->map) & param_comp))
02467 ftree= get_func_mm_tree(param, cond_func, field, value, cmp_type, inv);
02468 Item_equal *item_equal= field_item->item_equal;
02469 if (item_equal)
02470 {
02471 Item_equal_iterator it(item_equal->begin());
02472 Item_field *item;
02473 while ((item= it++))
02474 {
02475 Field *f= item->field;
02476 f->setWriteSet();
02477
02478 if (field->eq(f))
02479 continue;
02480 if (!((ref_tables | f->getTable()->map) & param_comp))
02481 {
02482 tree= get_func_mm_tree(param, cond_func, f, value, cmp_type, inv);
02483 ftree= !ftree ? tree : tree_and(param, ftree, tree);
02484 }
02485 }
02486 }
02487 return(ftree);
02488 }
02489
02490
02491
02492 static optimizer::SEL_TREE *get_mm_tree(optimizer::RangeParameter *param, COND *cond)
02493 {
02494 optimizer::SEL_TREE *tree=0;
02495 optimizer::SEL_TREE *ftree= 0;
02496 Item_field *field_item= 0;
02497 bool inv= false;
02498 Item *value= 0;
02499
02500 if (cond->type() == Item::COND_ITEM)
02501 {
02502 List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
02503
02504 if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
02505 {
02506 tree=0;
02507 while (Item* item=li++)
02508 {
02509 optimizer::SEL_TREE *new_tree= get_mm_tree(param,item);
02510 if (param->session->is_fatal_error ||
02511 param->alloced_sel_args > optimizer::SEL_ARG::MAX_SEL_ARGS)
02512 return 0;
02513 tree=tree_and(param,tree,new_tree);
02514 if (tree && tree->type == optimizer::SEL_TREE::IMPOSSIBLE)
02515 break;
02516 }
02517 }
02518 else
02519 {
02520 tree= get_mm_tree(param,li++);
02521 if (tree)
02522 {
02523 while (Item* item= li++)
02524 {
02525 optimizer::SEL_TREE *new_tree= get_mm_tree(param,item);
02526 if (!new_tree)
02527 return 0;
02528 tree=tree_or(param,tree,new_tree);
02529 if (!tree || tree->type == optimizer::SEL_TREE::ALWAYS)
02530 break;
02531 }
02532 }
02533 }
02534 return(tree);
02535 }
02536
02537
02538
02539
02540 if (cond->const_item() && !cond->is_expensive())
02541 {
02542
02543
02544
02545
02546
02547
02548 memory::Root *tmp_root= param->mem_root;
02549 param->session->mem_root= param->old_root;
02550 tree= cond->val_int() ? new(tmp_root) optimizer::SEL_TREE(optimizer::SEL_TREE::ALWAYS) :
02551 new(tmp_root) optimizer::SEL_TREE(optimizer::SEL_TREE::IMPOSSIBLE);
02552 param->session->mem_root= tmp_root;
02553 return(tree);
02554 }
02555
02556 table_map ref_tables= 0;
02557 table_map param_comp= ~(param->prev_tables | param->read_tables |
02558 param->current_table);
02559 if (cond->type() != Item::FUNC_ITEM)
02560 {
02561 ref_tables= cond->used_tables();
02562 if ((ref_tables & param->current_table) ||
02563 (ref_tables & ~(param->prev_tables | param->read_tables)))
02564 return 0;
02565 return(new optimizer::SEL_TREE(optimizer::SEL_TREE::MAYBE));
02566 }
02567
02568 Item_func *cond_func= (Item_func*) cond;
02569 if (cond_func->functype() == Item_func::BETWEEN ||
02570 cond_func->functype() == Item_func::IN_FUNC)
02571 inv= ((Item_func_opt_neg *) cond_func)->negated;
02572 else if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
02573 return 0;
02574
02575 param->cond= cond;
02576
02577 switch (cond_func->functype()) {
02578 case Item_func::BETWEEN:
02579 if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
02580 {
02581 field_item= (Item_field*) (cond_func->arguments()[0]->real_item());
02582 ftree= get_full_func_mm_tree(param, cond_func, field_item, NULL, inv);
02583 }
02584
02585
02586
02587
02588
02589 for (uint32_t i= 1 ; i < cond_func->arg_count ; i++)
02590 {
02591 if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM)
02592 {
02593 field_item= (Item_field*) (cond_func->arguments()[i]->real_item());
02594 optimizer::SEL_TREE *tmp= get_full_func_mm_tree(param, cond_func,
02595 field_item, (Item*)(intptr_t)i, inv);
02596 if (inv)
02597 tree= !tree ? tmp : tree_or(param, tree, tmp);
02598 else
02599 tree= tree_and(param, tree, tmp);
02600 }
02601 else if (inv)
02602 {
02603 tree= 0;
02604 break;
02605 }
02606 }
02607
02608 ftree = tree_and(param, ftree, tree);
02609 break;
02610 case Item_func::IN_FUNC:
02611 {
02612 Item_func_in *func=(Item_func_in*) cond_func;
02613 if (func->key_item()->real_item()->type() != Item::FIELD_ITEM)
02614 return 0;
02615 field_item= (Item_field*) (func->key_item()->real_item());
02616 ftree= get_full_func_mm_tree(param, cond_func, field_item, NULL, inv);
02617 break;
02618 }
02619 case Item_func::MULT_EQUAL_FUNC:
02620 {
02621 Item_equal *item_equal= (Item_equal *) cond;
02622 if (!(value= item_equal->get_const()))
02623 return 0;
02624 Item_equal_iterator it(item_equal->begin());
02625 ref_tables= value->used_tables();
02626 while ((field_item= it++))
02627 {
02628 Field *field= field_item->field;
02629 field->setWriteSet();
02630
02631 Item_result cmp_type= field->cmp_type();
02632 if (!((ref_tables | field->getTable()->map) & param_comp))
02633 {
02634 tree= get_mm_parts(param, cond, field, Item_func::EQ_FUNC,
02635 value,cmp_type);
02636 ftree= !ftree ? tree : tree_and(param, ftree, tree);
02637 }
02638 }
02639
02640 return(ftree);
02641 }
02642 default:
02643 if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM)
02644 {
02645 field_item= (Item_field*) (cond_func->arguments()[0]->real_item());
02646 value= cond_func->arg_count > 1 ? cond_func->arguments()[1] : 0;
02647 }
02648 else if (cond_func->have_rev_func() &&
02649 cond_func->arguments()[1]->real_item()->type() ==
02650 Item::FIELD_ITEM)
02651 {
02652 field_item= (Item_field*) (cond_func->arguments()[1]->real_item());
02653 value= cond_func->arguments()[0];
02654 }
02655 else
02656 return 0;
02657 ftree= get_full_func_mm_tree(param, cond_func, field_item, value, inv);
02658 }
02659
02660 return(ftree);
02661 }
02662
02663
02664 static optimizer::SEL_TREE *
02665 get_mm_parts(optimizer::RangeParameter *param,
02666 COND *cond_func,
02667 Field *field,
02668 Item_func::Functype type,
02669 Item *value, Item_result)
02670 {
02671 if (field->getTable() != param->table)
02672 return 0;
02673
02674 KEY_PART *key_part = param->key_parts;
02675 KEY_PART *end = param->key_parts_end;
02676 optimizer::SEL_TREE *tree=0;
02677 if (value &&
02678 value->used_tables() & ~(param->prev_tables | param->read_tables))
02679 return 0;
02680 for (; key_part != end; key_part++)
02681 {
02682 if (field->eq(key_part->field))
02683 {
02684 optimizer::SEL_ARG *sel_arg=0;
02685 if (!tree)
02686 tree= new optimizer::SEL_TREE;
02687 if (!value || !(value->used_tables() & ~param->read_tables))
02688 {
02689 sel_arg= get_mm_leaf(param,cond_func, key_part->field,key_part,type,value);
02690 if (! sel_arg)
02691 continue;
02692 if (sel_arg->type == optimizer::SEL_ARG::IMPOSSIBLE)
02693 {
02694 tree->type=optimizer::SEL_TREE::IMPOSSIBLE;
02695 return(tree);
02696 }
02697 }
02698 else
02699 {
02700
02701 sel_arg= new optimizer::SEL_ARG(optimizer::SEL_ARG::MAYBE_KEY);
02702 }
02703 sel_arg->part=(unsigned char) key_part->part;
02704 tree->keys[key_part->key]=sel_add(tree->keys[key_part->key],sel_arg);
02705 tree->keys_map.set(key_part->key);
02706 }
02707 }
02708
02709 return tree;
02710 }
02711
02712
02713 static optimizer::SEL_ARG *
02714 get_mm_leaf(optimizer::RangeParameter *param,
02715 COND *conf_func,
02716 Field *field,
02717 KEY_PART *key_part,
02718 Item_func::Functype type,
02719 Item *value)
02720 {
02721 uint32_t maybe_null=(uint32_t) field->real_maybe_null();
02722 bool optimize_range;
02723 optimizer::SEL_ARG *tree= NULL;
02724 memory::Root *alloc= param->mem_root;
02725 unsigned char *str;
02726 int err= 0;
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736 param->session->mem_root= param->old_root;
02737 if (!value)
02738 {
02739 if (field->getTable()->maybe_null)
02740 goto end;
02741 if (!maybe_null)
02742 {
02743 if (type == Item_func::ISNULL_FUNC)
02744 tree= &optimizer::null_element;
02745 goto end;
02746 }
02747 tree= new (*alloc) optimizer::SEL_ARG(field,is_null_string,is_null_string);
02748 if (type == Item_func::ISNOTNULL_FUNC)
02749 {
02750 tree->min_flag=NEAR_MIN;
02751 tree->max_flag=NO_MAX_RANGE;
02752 }
02753 goto end;
02754 }
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768 if (field->result_type() == STRING_RESULT &&
02769 value->result_type() == STRING_RESULT &&
02770 ((Field_str*)field)->charset() != conf_func->compare_collation() &&
02771 !(conf_func->compare_collation()->state & MY_CS_BINSORT))
02772 goto end;
02773
02774 if (param->using_real_indexes)
02775 optimize_range= field->optimize_range(param->real_keynr[key_part->key], key_part->part);
02776 else
02777 optimize_range= true;
02778
02779 if (type == Item_func::LIKE_FUNC)
02780 {
02781 bool like_error;
02782 char buff1[MAX_FIELD_WIDTH];
02783 unsigned char *min_str,*max_str;
02784 String tmp(buff1,sizeof(buff1),value->collation.collation),*res;
02785 size_t length, offset, min_length, max_length;
02786 uint32_t field_length= field->pack_length()+maybe_null;
02787
02788 if (!optimize_range)
02789 goto end;
02790 if (!(res= value->val_str(&tmp)))
02791 {
02792 tree= &optimizer::null_element;
02793 goto end;
02794 }
02795
02796
02797
02798
02799
02800
02801 if (res != &tmp)
02802 {
02803 tmp.copy(*res);
02804 res= &tmp;
02805 }
02806 if (field->cmp_type() != STRING_RESULT)
02807 goto end;
02808
02809 offset=maybe_null;
02810 length=key_part->store_length;
02811
02812 if (length != key_part->length + maybe_null)
02813 {
02814
02815 offset+= HA_KEY_BLOB_LENGTH;
02816 field_length= length - HA_KEY_BLOB_LENGTH;
02817 }
02818 else
02819 {
02820 if (unlikely(length < field_length))
02821 {
02822
02823
02824
02825
02826 length= field_length;
02827 }
02828 else
02829 field_length= length;
02830 }
02831 length+=offset;
02832 min_str= alloc->alloc(length*2);
02833 max_str=min_str+length;
02834 if (maybe_null)
02835 max_str[0]= min_str[0]=0;
02836
02837 field_length-= maybe_null;
02838 int escape_code= make_escape_code(field->charset(), ((Item_func_like*)(param->cond))->escape);
02839 like_error= my_like_range(field->charset(),
02840 res->ptr(), res->length(),
02841 escape_code,
02842 internal::wild_one, internal::wild_many,
02843 field_length,
02844 (char*) min_str+offset, (char*) max_str+offset,
02845 &min_length, &max_length);
02846 if (like_error)
02847 goto end;
02848
02849 if (offset != maybe_null)
02850 {
02851 int2store(min_str+maybe_null,min_length);
02852 int2store(max_str+maybe_null,max_length);
02853 }
02854 tree= new (alloc) optimizer::SEL_ARG(field, min_str, max_str);
02855 goto end;
02856 }
02857
02858 if (! optimize_range &&
02859 type != Item_func::EQ_FUNC &&
02860 type != Item_func::EQUAL_FUNC)
02861 goto end;
02862
02863
02864
02865
02866
02867 if (field->result_type() == STRING_RESULT &&
02868 value->result_type() != STRING_RESULT &&
02869 field->cmp_type() != value->result_type())
02870 goto end;
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903 if (field->is_timestamp())
02904 {
02905
02906
02907
02908
02909
02910
02911 if (value->real_item()->type() == Item::FIELD_ITEM
02912 && value->result_type() == STRING_RESULT)
02913 {
02914 char buff[DateTime::MAX_STRING_LENGTH];
02915 String tmp(buff, sizeof(buff), &my_charset_bin);
02916 String *res= value->val_str(&tmp);
02917
02918 if (!res)
02919 goto end;
02920 else
02921 {
02922
02923
02924
02925
02926 DateTime value_datetime;
02927
02928 if (! value_datetime.from_string(res->c_ptr(), (size_t) res->length()))
02929 goto end;
02930
02931 Timestamp max_timestamp;
02932 Timestamp min_timestamp;
02933
02934 (void) max_timestamp.from_time_t((time_t) INT32_MAX);
02935 (void) min_timestamp.from_time_t((time_t) 0);
02936
02937
02938 if (value_datetime < min_timestamp)
02939 {
02940
02941
02942
02943
02944 char new_value_buff[DateTime::MAX_STRING_LENGTH];
02945 int new_value_length;
02946 String new_value_string(new_value_buff, sizeof(new_value_buff), &my_charset_bin);
02947
02948 new_value_length= min_timestamp.to_string(new_value_string.c_ptr(),
02949 DateTime::MAX_STRING_LENGTH);
02950 assert((new_value_length+1) < DateTime::MAX_STRING_LENGTH);
02951 new_value_string.length(new_value_length);
02952 err= value->save_str_value_in_field(field, &new_value_string);
02953 }
02954 else if (value_datetime > max_timestamp)
02955 {
02956
02957
02958
02959
02960 char new_value_buff[DateTime::MAX_STRING_LENGTH];
02961 int new_value_length;
02962 String new_value_string(new_value_buff, sizeof(new_value_buff), &my_charset_bin);
02963
02964 new_value_length= max_timestamp.to_string(new_value_string.c_ptr(),
02965 DateTime::MAX_STRING_LENGTH);
02966 assert((new_value_length+1) < DateTime::MAX_STRING_LENGTH);
02967 new_value_string.length(new_value_length);
02968 err= value->save_str_value_in_field(field, &new_value_string);
02969 }
02970 else
02971 err= value->save_in_field(field, 1);
02972 }
02973 }
02974 else
02975 err= value->save_in_field(field, 1);
02976 }
02977 else
02978 err= value->save_in_field(field, 1);
02979
02980 if (err > 0)
02981 {
02982 if (field->cmp_type() != value->result_type())
02983 {
02984 if ((type == Item_func::EQ_FUNC || type == Item_func::EQUAL_FUNC) &&
02985 value->result_type() == item_cmp_type(field->result_type(),
02986 value->result_type()))
02987 {
02988 tree= new (alloc) optimizer::SEL_ARG(field, 0, 0);
02989 tree->type= optimizer::SEL_ARG::IMPOSSIBLE;
02990 goto end;
02991 }
02992 else
02993 {
02994
02995
02996
02997
02998 tree= 0;
02999 if (err == 3 && field->type() == DRIZZLE_TYPE_DATE &&
03000 (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC ||
03001 type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) )
03002 {
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021 }
03022 else
03023 goto end;
03024 }
03025 }
03026
03027
03028
03029
03030
03031
03032 else if (err == 1 && field->result_type() == INT_RESULT)
03033 {
03034 if (type == Item_func::LT_FUNC && (value->val_int() > 0))
03035 type = Item_func::LE_FUNC;
03036 else if (type == Item_func::GT_FUNC &&
03037 !((Field_num*)field)->unsigned_flag &&
03038 !((Item_int*)value)->unsigned_flag &&
03039 (value->val_int() < 0))
03040 type = Item_func::GE_FUNC;
03041 }
03042 else if (err == 1)
03043 {
03044 tree= new (alloc) optimizer::SEL_ARG(field, 0, 0);
03045 tree->type= optimizer::SEL_ARG::IMPOSSIBLE;
03046 goto end;
03047 }
03048 }
03049 else if (err < 0)
03050 {
03051
03052 tree= &optimizer::null_element;
03053 goto end;
03054 }
03055
03056
03057
03058
03059
03060
03061 if (type != Item_func::EQUAL_FUNC && field->is_real_null())
03062 {
03063 tree= &optimizer::null_element;
03064 goto end;
03065 }
03066
03067 str= alloc->alloc(key_part->store_length+1);
03068 if (maybe_null)
03069 *str= field->is_real_null();
03070 field->get_key_image(str+maybe_null, key_part->length);
03071 tree= new (alloc) optimizer::SEL_ARG(field, str, str);
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082
03083
03084 if (field->result_type() == INT_RESULT &&
03085 value->result_type() == INT_RESULT &&
03086 ((Field_num*)field)->unsigned_flag && !((Item_int*)value)->unsigned_flag)
03087 {
03088 int64_t item_val= value->val_int();
03089 if (item_val < 0)
03090 {
03091 if (type == Item_func::LT_FUNC || type == Item_func::LE_FUNC)
03092 {
03093 tree->type= optimizer::SEL_ARG::IMPOSSIBLE;
03094 goto end;
03095 }
03096 if (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC)
03097 {
03098 tree= 0;
03099 goto end;
03100 }
03101 }
03102 }
03103
03104 switch (type) {
03105 case Item_func::LT_FUNC:
03106 if (field_is_equal_to_item(field,value))
03107 tree->max_flag=NEAR_MAX;
03108
03109 case Item_func::LE_FUNC:
03110 if (!maybe_null)
03111 tree->min_flag=NO_MIN_RANGE;
03112 else
03113 {
03114 tree->min_value=is_null_string;
03115 tree->min_flag=NEAR_MIN;
03116 }
03117 break;
03118 case Item_func::GT_FUNC:
03119
03120 if (field_is_equal_to_item(field,value) &&
03121 !(key_part->flag & HA_PART_KEY_SEG))
03122 tree->min_flag=NEAR_MIN;
03123
03124 case Item_func::GE_FUNC:
03125 tree->max_flag=NO_MAX_RANGE;
03126 break;
03127 default:
03128 break;
03129 }
03130
03131 end:
03132 param->session->mem_root= alloc;
03133 return(tree);
03134 }
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150
03151
03152
03153
03154 static optimizer::SEL_ARG *
03155 sel_add(optimizer::SEL_ARG *key1, optimizer::SEL_ARG *key2)
03156 {
03157 optimizer::SEL_ARG *root= NULL;
03158 optimizer::SEL_ARG **key_link= NULL;
03159
03160 if (!key1)
03161 return key2;
03162 if (!key2)
03163 return key1;
03164
03165 key_link= &root;
03166 while (key1 && key2)
03167 {
03168 if (key1->part < key2->part)
03169 {
03170 *key_link= key1;
03171 key_link= &key1->next_key_part;
03172 key1=key1->next_key_part;
03173 }
03174 else
03175 {
03176 *key_link= key2;
03177 key_link= &key2->next_key_part;
03178 key2=key2->next_key_part;
03179 }
03180 }
03181 *key_link=key1 ? key1 : key2;
03182 return root;
03183 }
03184
03185 static const int CLONE_KEY1_MAYBE= 1;
03186 static const int CLONE_KEY2_MAYBE= 2;
03187
03188 static uint32_t swap_clone_flag(uint32_t a)
03189 {
03190 return ((a & 1) << 1) | ((a & 2) >> 1);
03191 }
03192
03193 static optimizer::SEL_TREE *
03194 tree_and(optimizer::RangeParameter *param, optimizer::SEL_TREE *tree1, optimizer::SEL_TREE *tree2)
03195 {
03196 if (!tree1)
03197 return(tree2);
03198 if (!tree2)
03199 return(tree1);
03200 if (tree1->type == optimizer::SEL_TREE::IMPOSSIBLE || tree2->type == optimizer::SEL_TREE::ALWAYS)
03201 return(tree1);
03202 if (tree2->type == optimizer::SEL_TREE::IMPOSSIBLE || tree1->type == optimizer::SEL_TREE::ALWAYS)
03203 return(tree2);
03204 if (tree1->type == optimizer::SEL_TREE::MAYBE)
03205 {
03206 if (tree2->type == optimizer::SEL_TREE::KEY)
03207 tree2->type=optimizer::SEL_TREE::KEY_SMALLER;
03208 return(tree2);
03209 }
03210 if (tree2->type == optimizer::SEL_TREE::MAYBE)
03211 {
03212 tree1->type=optimizer::SEL_TREE::KEY_SMALLER;
03213 return(tree1);
03214 }
03215 key_map result_keys;
03216 result_keys.reset();
03217
03218
03219 optimizer::SEL_ARG **key1,**key2,**end;
03220 for (key1= tree1->keys,key2= tree2->keys,end=key1+param->keys ;
03221 key1 != end ; key1++,key2++)
03222 {
03223 uint32_t flag=0;
03224 if (*key1 || *key2)
03225 {
03226 if (*key1 && !(*key1)->simple_key())
03227 flag|=CLONE_KEY1_MAYBE;
03228 if (*key2 && !(*key2)->simple_key())
03229 flag|=CLONE_KEY2_MAYBE;
03230 *key1=key_and(param, *key1, *key2, flag);
03231 if (*key1 && (*key1)->type == optimizer::SEL_ARG::IMPOSSIBLE)
03232 {
03233 tree1->type= optimizer::SEL_TREE::IMPOSSIBLE;
03234 return(tree1);
03235 }
03236 result_keys.set(key1 - tree1->keys);
03237 }
03238 }
03239 tree1->keys_map= result_keys;
03240
03241 if (result_keys.any())
03242 {
03243 tree1->merges.clear();
03244 return(tree1);
03245 }
03246
03247
03248 imerge_list_and_list(&tree1->merges, &tree2->merges);
03249 return(tree1);
03250 }
03251
03252
03253
03254
03255
03256 static optimizer::SEL_ARG *
03257 and_all_keys(optimizer::RangeParameter *param,
03258 optimizer::SEL_ARG *key1,
03259 optimizer::SEL_ARG *key2,
03260 uint32_t clone_flag)
03261 {
03262 optimizer::SEL_ARG *next= NULL;
03263 ulong use_count=key1->use_count;
03264
03265 if (key1->size() != 1)
03266 {
03267 key2->use_count+=key1->size()-1;
03268 key2->increment_use_count((int) key1->size()-1);
03269 }
03270 if (key1->type == optimizer::SEL_ARG::MAYBE_KEY)
03271 {
03272 key1->right= key1->left= &optimizer::null_element;
03273 key1->next= key1->prev= 0;
03274 }
03275 for (next= key1->first(); next ; next=next->next)
03276 {
03277 if (next->next_key_part)
03278 {
03279 optimizer::SEL_ARG *tmp= key_and(param, next->next_key_part, key2, clone_flag);
03280 if (tmp && tmp->type == optimizer::SEL_ARG::IMPOSSIBLE)
03281 {
03282 key1=key1->tree_delete(next);
03283 continue;
03284 }
03285 next->next_key_part=tmp;
03286 if (use_count)
03287 next->increment_use_count(use_count);
03288 if (param->alloced_sel_args > optimizer::SEL_ARG::MAX_SEL_ARGS)
03289 break;
03290 }
03291 else
03292 next->next_key_part=key2;
03293 }
03294 if (! key1)
03295 return &optimizer::null_element;
03296 key1->use_count++;
03297 return key1;
03298 }
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316 static optimizer::SEL_ARG *
03317 key_and(optimizer::RangeParameter *param,
03318 optimizer::SEL_ARG *key1,
03319 optimizer::SEL_ARG *key2,
03320 uint32_t clone_flag)
03321 {
03322 if (! key1)
03323 return key2;
03324 if (! key2)
03325 return key1;
03326 if (key1->part != key2->part)
03327 {
03328 if (key1->part > key2->part)
03329 {
03330 std::swap(key1, key2);
03331 clone_flag=swap_clone_flag(clone_flag);
03332 }
03333
03334 key1->use_count--;
03335 if (key1->use_count > 0)
03336 if (! (key1= key1->clone_tree(param)))
03337 return 0;
03338 return and_all_keys(param, key1, key2, clone_flag);
03339 }
03340
03341 if (((clone_flag & CLONE_KEY2_MAYBE) &&
03342 ! (clone_flag & CLONE_KEY1_MAYBE) &&
03343 key2->type != optimizer::SEL_ARG::MAYBE_KEY) ||
03344 key1->type == optimizer::SEL_ARG::MAYBE_KEY)
03345 {
03346 std::swap(key1, key2);
03347 clone_flag= swap_clone_flag(clone_flag);
03348 }
03349
03350
03351 if (key2->type == optimizer::SEL_ARG::MAYBE_KEY)
03352 {
03353 if (key1->use_count > 1)
03354 {
03355 key1->use_count--;
03356 if (! (key1=key1->clone_tree(param)))
03357 return 0;
03358 key1->use_count++;
03359 }
03360 if (key1->type == optimizer::SEL_ARG::MAYBE_KEY)
03361 {
03362 key1->next_key_part= key_and(param,
03363 key1->next_key_part,
03364 key2->next_key_part,
03365 clone_flag);
03366 if (key1->next_key_part &&
03367 key1->next_key_part->type == optimizer::SEL_ARG::IMPOSSIBLE)
03368 return key1;
03369 }
03370 else
03371 {
03372 key1->maybe_smaller();
03373 if (key2->next_key_part)
03374 {
03375 key1->use_count--;
03376 return and_all_keys(param, key1, key2, clone_flag);
03377 }
03378 key2->use_count--;
03379 }
03380 return key1;
03381 }
03382
03383 key1->use_count--;
03384 key2->use_count--;
03385 optimizer::SEL_ARG *e1= key1->first();
03386 optimizer::SEL_ARG *e2= key2->first();
03387 optimizer::SEL_ARG *new_tree= NULL;
03388
03389 while (e1 && e2)
03390 {
03391 int cmp= e1->cmp_min_to_min(e2);
03392 if (cmp < 0)
03393 {
03394 if (get_range(&e1, &e2, key1))
03395 continue;
03396 }
03397 else if (get_range(&e2, &e1, key2))
03398 continue;
03399 optimizer::SEL_ARG *next= key_and(param,
03400 e1->next_key_part,
03401 e2->next_key_part,
03402 clone_flag);
03403 e1->increment_use_count(1);
03404 e2->increment_use_count(1);
03405 if (! next || next->type != optimizer::SEL_ARG::IMPOSSIBLE)
03406 {
03407 optimizer::SEL_ARG *new_arg= e1->clone_and(e2);
03408 new_arg->next_key_part=next;
03409 if (! new_tree)
03410 {
03411 new_tree=new_arg;
03412 }
03413 else
03414 new_tree=new_tree->insert(new_arg);
03415 }
03416 if (e1->cmp_max_to_max(e2) < 0)
03417 e1=e1->next;
03418 else
03419 e2=e2->next;
03420 }
03421 key1->free_tree();
03422 key2->free_tree();
03423 if (! new_tree)
03424 return &optimizer::null_element;
03425 return new_tree;
03426 }
03427
03428
03429 static bool
03430 get_range(optimizer::SEL_ARG **e1, optimizer::SEL_ARG **e2, optimizer::SEL_ARG *root1)
03431 {
03432 (*e1)= root1->find_range(*e2);
03433 if ((*e1)->cmp_max_to_min(*e2) < 0)
03434 {
03435 if (! ((*e1)=(*e1)->next))
03436 return 1;
03437 if ((*e1)->cmp_min_to_max(*e2) > 0)
03438 {
03439 (*e2)=(*e2)->next;
03440 return 1;
03441 }
03442 }
03443 return 0;
03444 }
03445
03446
03447
03448
03449
03450
03451
03452 typedef struct st_range_seq_entry
03453 {
03454
03455
03456
03457
03458 unsigned char *min_key, *max_key;
03459
03460
03461
03462
03463
03464 uint32_t min_key_flag, max_key_flag;
03465
03466
03467 uint32_t min_key_parts, max_key_parts;
03468 optimizer::SEL_ARG *key_tree;
03469 } RANGE_SEQ_ENTRY;
03470
03471
03472
03473
03474
03475 typedef struct st_sel_arg_range_seq
03476 {
03477 uint32_t keyno;
03478 uint32_t real_keyno;
03479 optimizer::Parameter *param;
03480 optimizer::SEL_ARG *start;
03481
03482 RANGE_SEQ_ENTRY stack[MAX_REF_PARTS];
03483 int i;
03484
03485 bool at_start;
03486 } SEL_ARG_RANGE_SEQ;
03487
03488
03489
03490
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502 static range_seq_t sel_arg_range_seq_init(void *init_param, uint32_t, uint32_t)
03503 {
03504 SEL_ARG_RANGE_SEQ *seq= (SEL_ARG_RANGE_SEQ*)init_param;
03505 seq->at_start= true;
03506 seq->stack[0].key_tree= NULL;
03507 seq->stack[0].min_key= seq->param->min_key;
03508 seq->stack[0].min_key_flag= 0;
03509 seq->stack[0].min_key_parts= 0;
03510
03511 seq->stack[0].max_key= seq->param->max_key;
03512 seq->stack[0].max_key_flag= 0;
03513 seq->stack[0].max_key_parts= 0;
03514 seq->i= 0;
03515 return init_param;
03516 }
03517
03518
03519 static void step_down_to(SEL_ARG_RANGE_SEQ *arg, optimizer::SEL_ARG *key_tree)
03520 {
03521 RANGE_SEQ_ENTRY *cur= &arg->stack[arg->i+1];
03522 RANGE_SEQ_ENTRY *prev= &arg->stack[arg->i];
03523
03524 cur->key_tree= key_tree;
03525 cur->min_key= prev->min_key;
03526 cur->max_key= prev->max_key;
03527 cur->min_key_parts= prev->min_key_parts;
03528 cur->max_key_parts= prev->max_key_parts;
03529
03530 uint16_t stor_length= arg->param->key[arg->keyno][key_tree->part].store_length;
03531 cur->min_key_parts += key_tree->store_min(stor_length, &cur->min_key,
03532 prev->min_key_flag);
03533 cur->max_key_parts += key_tree->store_max(stor_length, &cur->max_key,
03534 prev->max_key_flag);
03535
03536 cur->min_key_flag= prev->min_key_flag | key_tree->min_flag;
03537 cur->max_key_flag= prev->max_key_flag | key_tree->max_flag;
03538
03539 if (key_tree->is_null_interval())
03540 cur->min_key_flag |= NULL_RANGE;
03541 (arg->i)++;
03542 }
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564
03565
03566
03567
03568
03569 static uint32_t sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
03570 {
03571 optimizer::SEL_ARG *key_tree;
03572 SEL_ARG_RANGE_SEQ *seq= (SEL_ARG_RANGE_SEQ*)rseq;
03573 if (seq->at_start)
03574 {
03575 key_tree= seq->start;
03576 seq->at_start= false;
03577 goto walk_up_n_right;
03578 }
03579
03580 key_tree= seq->stack[seq->i].key_tree;
03581
03582
03583
03584 if (key_tree->next && key_tree->next != &optimizer::null_element)
03585 {
03586
03587 seq->i--;
03588 step_down_to(seq, key_tree->next);
03589 key_tree= key_tree->next;
03590 seq->param->is_ror_scan= false;
03591 goto walk_right_n_up;
03592 }
03593
03594
03595 while (1)
03596 {
03597 if (seq->i == 1)
03598 return 1;
03599
03600 seq->i--;
03601 key_tree= seq->stack[seq->i].key_tree;
03602
03603
03604 if (key_tree->next && key_tree->next != &optimizer::null_element)
03605 {
03606
03607 seq->i--;
03608 step_down_to(seq, key_tree->next);
03609 key_tree= key_tree->next;
03610 break;
03611 }
03612 }
03613
03614
03615
03616
03617
03618 walk_right_n_up:
03619 while (key_tree->next_key_part && key_tree->next_key_part != &optimizer::null_element &&
03620 key_tree->next_key_part->part == key_tree->part + 1 &&
03621 key_tree->next_key_part->type == optimizer::SEL_ARG::KEY_RANGE)
03622 {
03623 {
03624 RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i];
03625 uint32_t min_key_length= cur->min_key - seq->param->min_key;
03626 uint32_t max_key_length= cur->max_key - seq->param->max_key;
03627 uint32_t len= cur->min_key - cur[-1].min_key;
03628 if (! (min_key_length == max_key_length &&
03629 ! memcmp(cur[-1].min_key, cur[-1].max_key, len) &&
03630 ! key_tree->min_flag && !key_tree->max_flag))
03631 {
03632 seq->param->is_ror_scan= false;
03633 if (! key_tree->min_flag)
03634 cur->min_key_parts +=
03635 key_tree->next_key_part->store_min_key(seq->param->key[seq->keyno],
03636 &cur->min_key,
03637 &cur->min_key_flag);
03638 if (! key_tree->max_flag)
03639 cur->max_key_parts +=
03640 key_tree->next_key_part->store_max_key(seq->param->key[seq->keyno],
03641 &cur->max_key,
03642 &cur->max_key_flag);
03643 break;
03644 }
03645 }
03646
03647
03648
03649
03650
03651 key_tree= key_tree->next_key_part;
03652
03653 walk_up_n_right:
03654 while (key_tree->prev && key_tree->prev != &optimizer::null_element)
03655 {
03656
03657 key_tree= key_tree->prev;
03658 }
03659 step_down_to(seq, key_tree);
03660 }
03661
03662
03663 RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i];
03664
03665 range->ptr= (char*)(size_t)(key_tree->part);
03666 {
03667 range->range_flag= cur->min_key_flag | cur->max_key_flag;
03668
03669 range->start_key.key= seq->param->min_key;
03670 range->start_key.length= cur->min_key - seq->param->min_key;
03671 range->start_key.keypart_map= make_prev_keypart_map(cur->min_key_parts);
03672 range->start_key.flag= (cur->min_key_flag & NEAR_MIN ? HA_READ_AFTER_KEY :
03673 HA_READ_KEY_EXACT);
03674
03675 range->end_key.key= seq->param->max_key;
03676 range->end_key.length= cur->max_key - seq->param->max_key;
03677 range->end_key.flag= (cur->max_key_flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
03678 HA_READ_AFTER_KEY);
03679 range->end_key.keypart_map= make_prev_keypart_map(cur->max_key_parts);
03680
03681 if (!(cur->min_key_flag & ~NULL_RANGE) && !cur->max_key_flag &&
03682 (uint32_t)key_tree->part+1 == seq->param->table->key_info[seq->real_keyno].key_parts &&
03683 (seq->param->table->key_info[seq->real_keyno].flags & (HA_NOSAME)) ==
03684 HA_NOSAME &&
03685 range->start_key.length == range->end_key.length &&
03686 !memcmp(seq->param->min_key,seq->param->max_key,range->start_key.length))
03687 range->range_flag= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE);
03688
03689 if (seq->param->is_ror_scan)
03690 {
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700 if (!(!(cur->min_key_flag & ~NULL_RANGE) && !cur->max_key_flag &&
03701 (range->start_key.length == range->end_key.length) &&
03702 !memcmp(range->start_key.key, range->end_key.key, range->start_key.length) &&
03703 is_key_scan_ror(seq->param, seq->real_keyno, key_tree->part + 1)))
03704 seq->param->is_ror_scan= false;
03705 }
03706 }
03707 seq->param->range_count++;
03708 seq->param->max_key_part= max(seq->param->max_key_part,(uint32_t)key_tree->part);
03709 return 0;
03710 }
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737
03738
03739
03740 static
03741 ha_rows check_quick_select(Session *session,
03742 optimizer::Parameter *param,
03743 uint32_t idx,
03744 bool index_only,
03745 optimizer::SEL_ARG *tree,
03746 bool update_tbl_stats,
03747 uint32_t *mrr_flags,
03748 uint32_t *bufsize,
03749 optimizer::CostVector *cost)
03750 {
03751 SEL_ARG_RANGE_SEQ seq;
03752 RANGE_SEQ_IF seq_if = {sel_arg_range_seq_init, sel_arg_range_seq_next};
03753 Cursor *cursor= param->table->cursor;
03754 ha_rows rows;
03755 uint32_t keynr= param->real_keynr[idx];
03756
03757
03758 if (! tree)
03759 return(HA_POS_ERROR);
03760 if (tree->type == optimizer::SEL_ARG::IMPOSSIBLE)
03761 return(0L);
03762 if (tree->type != optimizer::SEL_ARG::KEY_RANGE || tree->part != 0)
03763 return(HA_POS_ERROR);
03764
03765 seq.keyno= idx;
03766 seq.real_keyno= keynr;
03767 seq.param= param;
03768 seq.start= tree;
03769
03770 param->range_count=0;
03771 param->max_key_part=0;
03772
03773 param->is_ror_scan= true;
03774 if (param->table->index_flags(keynr) & HA_KEY_SCAN_NOT_ROR)
03775 param->is_ror_scan= false;
03776
03777 *mrr_flags= param->force_default_mrr? HA_MRR_USE_DEFAULT_IMPL: 0;
03778 *mrr_flags|= HA_MRR_NO_ASSOCIATION;
03779
03780 bool pk_is_clustered= cursor->primary_key_is_clustered();
03781 if (index_only &&
03782 (param->table->index_flags(keynr) & HA_KEYREAD_ONLY) &&
03783 !(pk_is_clustered && keynr == param->table->getShare()->getPrimaryKey()))
03784 *mrr_flags |= HA_MRR_INDEX_ONLY;
03785
03786 if (session->lex().sql_command != SQLCOM_SELECT)
03787 *mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
03788
03789 *bufsize= param->session->variables.read_rnd_buff_size;
03790 rows= cursor->multi_range_read_info_const(keynr, &seq_if, (void*)&seq, 0,
03791 bufsize, mrr_flags, cost);
03792 if (rows != HA_POS_ERROR)
03793 {
03794 param->table->quick_rows[keynr]=rows;
03795 if (update_tbl_stats)
03796 {
03797 param->table->quick_keys.set(keynr);
03798 param->table->quick_key_parts[keynr]=param->max_key_part+1;
03799 param->table->quick_n_ranges[keynr]= param->range_count;
03800 param->table->quick_condition_rows=
03801 min(param->table->quick_condition_rows, rows);
03802 }
03803 }
03804
03805 enum ha_key_alg key_alg= param->table->key_info[seq.real_keyno].algorithm;
03806 if ((key_alg != HA_KEY_ALG_BTREE) && (key_alg!= HA_KEY_ALG_UNDEF))
03807 {
03808
03809
03810
03811
03812
03813 param->is_ror_scan= false;
03814 }
03815 else
03816 {
03817
03818 if (param->table->getShare()->getPrimaryKey() == keynr && pk_is_clustered)
03819 param->is_ror_scan= true;
03820 }
03821
03822 return(rows);
03823 }
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863 static bool is_key_scan_ror(optimizer::Parameter *param, uint32_t keynr, uint8_t nparts)
03864 {
03865 KeyInfo *table_key= param->table->key_info + keynr;
03866 KeyPartInfo *key_part= table_key->key_part + nparts;
03867 KeyPartInfo *key_part_end= (table_key->key_part +
03868 table_key->key_parts);
03869 uint32_t pk_number;
03870
03871 for (KeyPartInfo *kp= table_key->key_part; kp < key_part; kp++)
03872 {
03873 uint16_t fieldnr= param->table->key_info[keynr].
03874 key_part[kp - table_key->key_part].fieldnr - 1;
03875 if (param->table->getField(fieldnr)->key_length() != kp->length)
03876 return false;
03877 }
03878
03879 if (key_part == key_part_end)
03880 return true;
03881
03882 key_part= table_key->key_part + nparts;
03883 pk_number= param->table->getShare()->getPrimaryKey();
03884 if (!param->table->cursor->primary_key_is_clustered() || pk_number == MAX_KEY)
03885 return false;
03886
03887 KeyPartInfo *pk_part= param->table->key_info[pk_number].key_part;
03888 KeyPartInfo *pk_part_end= pk_part +
03889 param->table->key_info[pk_number].key_parts;
03890 for (;(key_part!=key_part_end) && (pk_part != pk_part_end);
03891 ++key_part, ++pk_part)
03892 {
03893 if ((key_part->field != pk_part->field) ||
03894 (key_part->length != pk_part->length))
03895 return false;
03896 }
03897 return (key_part == key_part_end);
03898 }
03899
03900
03901 optimizer::QuickRangeSelect *
03902 optimizer::get_quick_select(Parameter *param,
03903 uint32_t idx,
03904 optimizer::SEL_ARG *key_tree,
03905 uint32_t mrr_flags,
03906 uint32_t mrr_buf_size,
03907 memory::Root *parent_alloc)
03908 {
03909 optimizer::QuickRangeSelect *quick= new optimizer::QuickRangeSelect(param->session,
03910 param->table,
03911 param->real_keynr[idx],
03912 test(parent_alloc),
03913 NULL);
03914
03915 if (quick)
03916 {
03917 if (get_quick_keys(param,
03918 quick,
03919 param->key[idx],
03920 key_tree,
03921 param->min_key,
03922 0,
03923 param->max_key,
03924 0))
03925 {
03926 delete quick;
03927 quick= NULL;
03928 }
03929 else
03930 {
03931 quick->mrr_flags= mrr_flags;
03932 quick->mrr_buf_size= mrr_buf_size;
03933 quick->key_parts= parent_alloc
03934 ? (KEY_PART*)parent_alloc->memdup(param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts)
03935 : (KEY_PART*)quick->alloc.memdup(param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts);
03936 }
03937 }
03938 return quick;
03939 }
03940
03941
03942
03943
03944
03945 bool
03946 optimizer::get_quick_keys(optimizer::Parameter *param,
03947 optimizer::QuickRangeSelect *quick,
03948 KEY_PART *key,
03949 optimizer::SEL_ARG *key_tree,
03950 unsigned char *min_key,
03951 uint32_t min_key_flag,
03952 unsigned char *max_key,
03953 uint32_t max_key_flag)
03954 {
03955 optimizer::QuickRange *range= NULL;
03956 uint32_t flag;
03957 int min_part= key_tree->part - 1;
03958 int max_part= key_tree->part - 1;
03959
03960 if (key_tree->left != &optimizer::null_element)
03961 {
03962 if (get_quick_keys(param,
03963 quick,
03964 key,
03965 key_tree->left,
03966 min_key,
03967 min_key_flag,
03968 max_key,
03969 max_key_flag))
03970 {
03971 return 1;
03972 }
03973 }
03974 unsigned char *tmp_min_key= min_key,*tmp_max_key= max_key;
03975 min_part+= key_tree->store_min(key[key_tree->part].store_length,
03976 &tmp_min_key,min_key_flag);
03977 max_part+= key_tree->store_max(key[key_tree->part].store_length,
03978 &tmp_max_key,max_key_flag);
03979
03980 if (key_tree->next_key_part &&
03981 key_tree->next_key_part->part == key_tree->part+1 &&
03982 key_tree->next_key_part->type == optimizer::SEL_ARG::KEY_RANGE)
03983 {
03984 if ((tmp_min_key - min_key) == (tmp_max_key - max_key) &&
03985 memcmp(min_key, max_key, (uint32_t)(tmp_max_key - max_key))==0 &&
03986 key_tree->min_flag==0 && key_tree->max_flag==0)
03987 {
03988 if (get_quick_keys(param,
03989 quick,
03990 key,
03991 key_tree->next_key_part,
03992 tmp_min_key,
03993 min_key_flag | key_tree->min_flag,
03994 tmp_max_key,
03995 max_key_flag | key_tree->max_flag))
03996 {
03997 return 1;
03998 }
03999 goto end;
04000 }
04001 {
04002 uint32_t tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag;
04003 if (! tmp_min_flag)
04004 {
04005 min_part+= key_tree->next_key_part->store_min_key(key,
04006 &tmp_min_key,
04007 &tmp_min_flag);
04008 }
04009 if (! tmp_max_flag)
04010 {
04011 max_part+= key_tree->next_key_part->store_max_key(key,
04012 &tmp_max_key,
04013 &tmp_max_flag);
04014 }
04015 flag=tmp_min_flag | tmp_max_flag;
04016 }
04017 }
04018 else
04019 {
04020 flag= key_tree->min_flag | key_tree->max_flag;
04021 }
04022
04023
04024
04025
04026
04027 if (tmp_min_key != param->min_key)
04028 {
04029 flag&= ~NO_MIN_RANGE;
04030 }
04031 else
04032 {
04033 flag|= NO_MIN_RANGE;
04034 }
04035 if (tmp_max_key != param->max_key)
04036 {
04037 flag&= ~NO_MAX_RANGE;
04038 }
04039 else
04040 {
04041 flag|= NO_MAX_RANGE;
04042 }
04043 if (flag == 0)
04044 {
04045 uint32_t length= (uint32_t) (tmp_min_key - param->min_key);
04046 if (length == (uint32_t) (tmp_max_key - param->max_key) &&
04047 ! memcmp(param->min_key,param->max_key,length))
04048 {
04049 KeyInfo *table_key= quick->head->key_info+quick->index;
04050 flag= EQ_RANGE;
04051 if ((table_key->flags & (HA_NOSAME)) == HA_NOSAME &&
04052 key->part == table_key->key_parts-1)
04053 {
04054 if (! (table_key->flags & HA_NULL_PART_KEY) ||
04055 ! null_part_in_key(key,
04056 param->min_key,
04057 (uint32_t) (tmp_min_key - param->min_key)))
04058 {
04059 flag|= UNIQUE_RANGE;
04060 }
04061 else
04062 {
04063 flag|= NULL_RANGE;
04064 }
04065 }
04066 }
04067 }
04068
04069
04070 range= new optimizer::QuickRange(param->min_key,
04071 (uint32_t) (tmp_min_key - param->min_key),
04072 min_part >=0 ? make_keypart_map(min_part) : 0,
04073 param->max_key,
04074 (uint32_t) (tmp_max_key - param->max_key),
04075 max_part >=0 ? make_keypart_map(max_part) : 0,
04076 flag);
04077
04078 set_if_bigger(quick->max_used_key_length, (uint32_t)range->min_length);
04079 set_if_bigger(quick->max_used_key_length, (uint32_t)range->max_length);
04080 set_if_bigger(quick->used_key_parts, (uint32_t) key_tree->part+1);
04081 quick->ranges.push_back(&range);
04082
04083 end:
04084 if (key_tree->right != &optimizer::null_element)
04085 {
04086 return get_quick_keys(param,
04087 quick,
04088 key,
04089 key_tree->right,
04090 min_key,
04091 min_key_flag,
04092 max_key,
04093 max_key_flag);
04094 }
04095 return 0;
04096 }
04097
04098
04099
04100
04101
04102
04103
04104
04105
04106
04107
04108
04109
04110
04111
04112 static bool null_part_in_key(KEY_PART *key_part, const unsigned char *key, uint32_t length)
04113 {
04114 for (const unsigned char *end=key+length ;
04115 key < end;
04116 key+= key_part++->store_length)
04117 {
04118 if (key_part->null_bit && *key)
04119 return 1;
04120 }
04121 return 0;
04122 }
04123
04124
04125 bool optimizer::QuickSelectInterface::is_keys_used(const boost::dynamic_bitset<>& fields)
04126 {
04127 return is_key_used(head, index, fields);
04128 }
04129
04130
04131
04132
04133
04134
04135
04136
04137
04138
04139
04140
04141
04142
04143
04144
04145
04146
04147
04148
04149
04150 optimizer::QuickRangeSelect *optimizer::get_quick_select_for_ref(Session *session,
04151 Table *table,
04152 table_reference_st *ref,
04153 ha_rows records)
04154 {
04155 memory::Root *old_root= NULL;
04156 memory::Root *alloc= NULL;
04157 KeyInfo *key_info = &table->key_info[ref->key];
04158 KEY_PART *key_part;
04159 optimizer::QuickRange *range= NULL;
04160 uint32_t part;
04161 optimizer::CostVector cost;
04162
04163 old_root= session->mem_root;
04164
04165 optimizer::QuickRangeSelect *quick= new optimizer::QuickRangeSelect(session, table, ref->key, 0, 0);
04166
04167 alloc= session->mem_root;
04168
04169
04170
04171
04172 session->mem_root= old_root;
04173
04174 if (! quick)
04175 return 0;
04176 if (quick->init())
04177 goto err;
04178 quick->records= records;
04179
04180 if (cp_buffer_from_ref(session, ref) && session->is_fatal_error)
04181 goto err;
04182 range= new (*alloc) optimizer::QuickRange;
04183
04184 range->min_key= range->max_key= ref->key_buff;
04185 range->min_length= range->max_length= ref->key_length;
04186 range->min_keypart_map= range->max_keypart_map=
04187 make_prev_keypart_map(ref->key_parts);
04188 range->flag= (ref->key_length == key_info->key_length && (key_info->flags & HA_END_SPACE_KEY) == 0) ? EQ_RANGE : 0;
04189
04190 quick->key_parts=key_part= new (quick->alloc) KEY_PART[ref->key_parts];
04191
04192 for (part=0 ; part < ref->key_parts ;part++,key_part++)
04193 {
04194 key_part->part=part;
04195 key_part->field= key_info->key_part[part].field;
04196 key_part->length= key_info->key_part[part].length;
04197 key_part->store_length= key_info->key_part[part].store_length;
04198 key_part->null_bit= key_info->key_part[part].null_bit;
04199 key_part->flag= (uint8_t) key_info->key_part[part].key_part_flag;
04200 }
04201 quick->ranges.push_back(&range);
04202
04203
04204
04205
04206
04207
04208
04209 if (ref->null_ref_key)
04210 {
04211 optimizer::QuickRange *null_range= NULL;
04212
04213 *ref->null_ref_key= 1;
04214 null_range= new (alloc)
04215 optimizer::QuickRange(ref->key_buff, ref->key_length,
04216 make_prev_keypart_map(ref->key_parts),
04217 ref->key_buff, ref->key_length,
04218 make_prev_keypart_map(ref->key_parts), EQ_RANGE);
04219 *ref->null_ref_key= 0;
04220 quick->ranges.push_back(&null_range);
04221 }
04222
04223
04224 quick->mrr_flags= HA_MRR_NO_ASSOCIATION |
04225 (table->key_read ? HA_MRR_INDEX_ONLY : 0);
04226 if (session->lex().sql_command != SQLCOM_SELECT)
04227 quick->mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
04228
04229 quick->mrr_buf_size= session->variables.read_rnd_buff_size;
04230 if (table->cursor->multi_range_read_info(quick->index, 1, (uint32_t)records, &quick->mrr_buf_size, &quick->mrr_flags, &cost))
04231 goto err;
04232
04233 return quick;
04234 err:
04235 delete quick;
04236 return 0;
04237 }
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253 range_seq_t optimizer::quick_range_seq_init(void *init_param, uint32_t, uint32_t)
04254 {
04255 optimizer::QuickRangeSelect *quick= (optimizer::QuickRangeSelect*)init_param;
04256 quick->qr_traversal_ctx.first= (optimizer::QuickRange**)quick->ranges.buffer;
04257 quick->qr_traversal_ctx.cur= (optimizer::QuickRange**)quick->ranges.buffer;
04258 quick->qr_traversal_ctx.last= quick->qr_traversal_ctx.cur +
04259 quick->ranges.size();
04260 return &quick->qr_traversal_ctx;
04261 }
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276 uint32_t optimizer::quick_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
04277 {
04278 QuickRangeSequenceContext *ctx= (QuickRangeSequenceContext*) rseq;
04279
04280 if (ctx->cur == ctx->last)
04281 return 1;
04282
04283 optimizer::QuickRange *cur= *(ctx->cur);
04284 key_range *start_key= &range->start_key;
04285 key_range *end_key= &range->end_key;
04286
04287 start_key->key= cur->min_key;
04288 start_key->length= cur->min_length;
04289 start_key->keypart_map= cur->min_keypart_map;
04290 start_key->flag= ((cur->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
04291 (cur->flag & EQ_RANGE) ?
04292 HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
04293 end_key->key= cur->max_key;
04294 end_key->length= cur->max_length;
04295 end_key->keypart_map= cur->max_keypart_map;
04296
04297
04298
04299
04300 end_key->flag= (cur->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
04301 HA_READ_AFTER_KEY);
04302 range->range_flag= cur->flag;
04303 ctx->cur++;
04304 return 0;
04305 }
04306
04307
04308 static inline uint32_t get_field_keypart(KeyInfo *index, Field *field);
04309
04310 static inline optimizer::SEL_ARG * get_index_range_tree(uint32_t index,
04311 optimizer::SEL_TREE *range_tree,
04312 optimizer::Parameter *param,
04313 uint32_t *param_idx);
04314
04315 static bool get_constant_key_infix(KeyInfo *index_info,
04316 optimizer::SEL_ARG *index_range_tree,
04317 KeyPartInfo *first_non_group_part,
04318 KeyPartInfo *min_max_arg_part,
04319 KeyPartInfo *last_part,
04320 Session *session,
04321 unsigned char *key_infix,
04322 uint32_t *key_infix_len,
04323 KeyPartInfo **first_non_infix_part);
04324
04325 static bool check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item);
04326
04327 static void
04328 cost_group_min_max(Table* table,
04329 KeyInfo *index_info,
04330 uint32_t used_key_parts,
04331 uint32_t group_key_parts,
04332 optimizer::SEL_TREE *range_tree,
04333 optimizer::SEL_ARG *index_tree,
04334 ha_rows quick_prefix_records,
04335 bool have_min,
04336 bool have_max,
04337 double *read_cost,
04338 ha_rows *records);
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348
04349
04350
04351
04352
04353
04354
04355
04356
04357
04358
04359
04360
04361
04362
04363
04364
04365
04366
04367
04368
04369
04370
04371
04372
04373
04374
04375
04376
04377
04378
04379
04380
04381
04382
04383
04384
04385
04386
04387
04388
04389
04390
04391
04392
04393
04394
04395
04396
04397
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444
04445
04446
04447
04448
04449
04450
04451
04452
04453
04454
04455
04456
04457
04458
04459
04460
04461
04462
04463
04464
04465
04466
04467
04468 static optimizer::GroupMinMaxReadPlan *
04469 get_best_group_min_max(optimizer::Parameter *param, optimizer::SEL_TREE *tree)
04470 {
04471 Session *session= param->session;
04472 Join *join= session->lex().current_select->join;
04473 Table *table= param->table;
04474 bool have_min= false;
04475 bool have_max= false;
04476 Item_field *min_max_arg_item= NULL;
04477 KeyPartInfo *min_max_arg_part= NULL;
04478 uint32_t group_prefix_len= 0;
04479 KeyInfo *index_info= NULL;
04480 uint32_t index= 0;
04481 uint32_t group_key_parts= 0;
04482 uint32_t used_key_parts= 0;
04483 unsigned char key_infix[MAX_KEY_LENGTH];
04484 uint32_t key_infix_len= 0;
04485 optimizer::GroupMinMaxReadPlan *read_plan= NULL;
04486 uint32_t key_part_nr;
04487 Order *tmp_group= NULL;
04488 Item *item= NULL;
04489 Item_field *item_field= NULL;
04490
04491
04492 if (! join)
04493 return NULL;
04494
04495 if ((join->tables != 1) ||
04496 ((! join->group_list) &&
04497 (! join->select_distinct)) ||
04498 (join->select_lex->olap == ROLLUP_TYPE))
04499 return NULL;
04500 if (table->getShare()->sizeKeys() == 0)
04501 return NULL;
04502
04503
04504 List<Item>::iterator select_items_it(join->fields_list.begin());
04505
04506
04507 if (join->make_sum_func_list(join->all_fields, join->fields_list, 1))
04508 return NULL;
04509
04510 if (join->sum_funcs[0])
04511 {
04512 Item_sum *min_max_item= NULL;
04513 Item_sum **func_ptr= join->sum_funcs;
04514 while ((min_max_item= *(func_ptr++)))
04515 {
04516 if (min_max_item->sum_func() == Item_sum::MIN_FUNC)
04517 have_min= true;
04518 else if (min_max_item->sum_func() == Item_sum::MAX_FUNC)
04519 have_max= true;
04520 else
04521 return NULL;
04522
04523
04524 Item *expr= min_max_item->args[0]->real_item();
04525 if (expr->type() == Item::FIELD_ITEM)
04526 {
04527 if (! min_max_arg_item)
04528 min_max_arg_item= (Item_field*) expr;
04529 else if (! min_max_arg_item->eq(expr, 1))
04530 return NULL;
04531 }
04532 else
04533 return NULL;
04534 }
04535 }
04536
04537
04538 if (join->select_distinct)
04539 {
04540 while ((item= select_items_it++))
04541 {
04542 if (item->type() != Item::FIELD_ITEM)
04543 return NULL;
04544 }
04545 }
04546
04547
04548 for (tmp_group= join->group_list; tmp_group; tmp_group= tmp_group->next)
04549 {
04550 if ((*tmp_group->item)->type() != Item::FIELD_ITEM)
04551 return NULL;
04552 }
04553
04554
04555
04556
04557
04558
04559 KeyInfo *cur_index_info= table->key_info;
04560 KeyInfo *cur_index_info_end= cur_index_info + table->getShare()->sizeKeys();
04561 KeyPartInfo *cur_part= NULL;
04562 KeyPartInfo *end_part= NULL;
04563
04564 KeyPartInfo *last_part= NULL;
04565 KeyPartInfo *first_non_group_part= NULL;
04566 KeyPartInfo *first_non_infix_part= NULL;
04567 uint32_t key_infix_parts= 0;
04568 uint32_t cur_group_key_parts= 0;
04569 uint32_t cur_group_prefix_len= 0;
04570
04571 double best_read_cost= DBL_MAX;
04572 ha_rows best_records= 0;
04573 optimizer::SEL_ARG *best_index_tree= NULL;
04574 ha_rows best_quick_prefix_records= 0;
04575 uint32_t best_param_idx= 0;
04576 double cur_read_cost= DBL_MAX;
04577 ha_rows cur_records;
04578 optimizer::SEL_ARG *cur_index_tree= NULL;
04579 ha_rows cur_quick_prefix_records= 0;
04580 uint32_t cur_param_idx= MAX_KEY;
04581 key_map used_key_parts_map;
04582 uint32_t cur_key_infix_len= 0;
04583 unsigned char cur_key_infix[MAX_KEY_LENGTH];
04584 uint32_t cur_used_key_parts= 0;
04585 uint32_t pk= param->table->getShare()->getPrimaryKey();
04586
04587 for (uint32_t cur_index= 0;
04588 cur_index_info != cur_index_info_end;
04589 cur_index_info++, cur_index++)
04590 {
04591
04592 if (! table->covering_keys.test(cur_index))
04593 goto next_index;
04594
04595
04596
04597
04598
04599
04600
04601
04602
04603
04604 if (pk < MAX_KEY && cur_index != pk &&
04605 (table->cursor->getEngine()->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX)))
04606 {
04607
04608 for (uint32_t i= 0; i < table->getShare()->sizeFields(); i++)
04609 {
04610 Field *cur_field= table->getField(i);
04611
04612
04613
04614
04615 if ((cur_field->isReadSet()) &&
04616 ! cur_field->part_of_key_not_clustered.test(cur_index))
04617 goto next_index;
04618 }
04619 }
04620
04621
04622
04623
04624 if (join->group_list)
04625 {
04626 cur_part= cur_index_info->key_part;
04627 end_part= cur_part + cur_index_info->key_parts;
04628
04629 for (tmp_group= join->group_list;
04630 tmp_group && (cur_part != end_part);
04631 tmp_group= tmp_group->next, cur_part++)
04632 {
04633
04634
04635
04636
04637
04638
04639 assert((*tmp_group->item)->type() == Item::FIELD_ITEM);
04640 Item_field *group_field= (Item_field *) (*tmp_group->item);
04641 if (group_field->field->eq(cur_part->field))
04642 {
04643 cur_group_prefix_len+= cur_part->store_length;
04644 ++cur_group_key_parts;
04645 }
04646 else
04647 goto next_index;
04648 }
04649 }
04650
04651
04652
04653
04654
04655
04656
04657
04658 else if (join->select_distinct)
04659 {
04660 select_items_it= join->fields_list.begin();
04661 used_key_parts_map.reset();
04662 uint32_t max_key_part= 0;
04663 while ((item= select_items_it++))
04664 {
04665 item_field= (Item_field*) item;
04666
04667 key_part_nr= get_field_keypart(cur_index_info, item_field->field);
04668
04669
04670
04671
04672 if (used_key_parts_map.test(key_part_nr))
04673 continue;
04674 if (key_part_nr < 1 || key_part_nr > join->fields_list.size())
04675 goto next_index;
04676 cur_part= cur_index_info->key_part + key_part_nr - 1;
04677 cur_group_prefix_len+= cur_part->store_length;
04678 used_key_parts_map.set(key_part_nr);
04679 ++cur_group_key_parts;
04680 max_key_part= max(max_key_part,key_part_nr);
04681 }
04682
04683
04684
04685
04686
04687
04688 key_map all_parts;
04689 key_map cur_parts;
04690 for (uint32_t pos= 0; pos < max_key_part; pos++)
04691 all_parts.set(pos);
04692 cur_parts= used_key_parts_map >> 1;
04693 if (all_parts != cur_parts)
04694 goto next_index;
04695 }
04696 else
04697 assert(false);
04698
04699
04700 if (min_max_arg_item)
04701 {
04702 key_part_nr= get_field_keypart(cur_index_info, min_max_arg_item->field);
04703 if (key_part_nr <= cur_group_key_parts)
04704 goto next_index;
04705 min_max_arg_part= cur_index_info->key_part + key_part_nr - 1;
04706 }
04707
04708
04709
04710
04711
04712
04713
04714
04715
04716
04717
04718
04719
04720
04721
04722
04723 last_part= cur_index_info->key_part + cur_index_info->key_parts;
04724 first_non_group_part= (cur_group_key_parts < cur_index_info->key_parts) ?
04725 cur_index_info->key_part + cur_group_key_parts :
04726 NULL;
04727 first_non_infix_part= min_max_arg_part ?
04728 (min_max_arg_part < last_part) ?
04729 min_max_arg_part :
04730 NULL :
04731 NULL;
04732 if (first_non_group_part &&
04733 (! min_max_arg_part || (min_max_arg_part - first_non_group_part > 0)))
04734 {
04735 if (tree)
04736 {
04737 uint32_t dummy;
04738 optimizer::SEL_ARG *index_range_tree= get_index_range_tree(cur_index,
04739 tree,
04740 param,
04741 &dummy);
04742 if (! get_constant_key_infix(cur_index_info,
04743 index_range_tree,
04744 first_non_group_part,
04745 min_max_arg_part,
04746 last_part,
04747 session,
04748 cur_key_infix,
04749 &cur_key_infix_len,
04750 &first_non_infix_part))
04751 {
04752 goto next_index;
04753 }
04754 }
04755 else if (min_max_arg_part &&
04756 (min_max_arg_part - first_non_group_part > 0))
04757 {
04758
04759
04760
04761
04762 goto next_index;
04763 }
04764 else if (first_non_group_part && join->conds)
04765 {
04766
04767
04768
04769
04770
04771
04772
04773
04774
04775
04776
04777
04778 KeyPartInfo *key_part_range[2];
04779 key_part_range[0]= first_non_group_part;
04780 key_part_range[1]= last_part;
04781
04782
04783 if (join->conds->walk(&Item::find_item_in_field_list_processor,
04784 0,
04785 (unsigned char*) key_part_range))
04786 goto next_index;
04787 }
04788 }
04789
04790
04791
04792
04793
04794 if (first_non_infix_part)
04795 {
04796 cur_part= first_non_infix_part +
04797 (min_max_arg_part && (min_max_arg_part < last_part));
04798 for (; cur_part != last_part; cur_part++)
04799 {
04800 if (cur_part->field->isReadSet())
04801 goto next_index;
04802 }
04803 }
04804
04805
04806 key_infix_parts= cur_key_infix_len ?
04807 (first_non_infix_part - first_non_group_part) : 0;
04808 cur_used_key_parts= cur_group_key_parts + key_infix_parts;
04809
04810
04811 if (tree)
04812 {
04813
04814 cur_index_tree= get_index_range_tree(cur_index,
04815 tree,
04816 param,
04817 &cur_param_idx);
04818
04819 optimizer::CostVector dummy_cost;
04820 uint32_t mrr_flags= HA_MRR_USE_DEFAULT_IMPL;
04821 uint32_t mrr_bufsize= 0;
04822 cur_quick_prefix_records= check_quick_select(session,
04823 param,
04824 cur_param_idx,
04825 false ,
04826 cur_index_tree,
04827 true,
04828 &mrr_flags,
04829 &mrr_bufsize,
04830 &dummy_cost);
04831 }
04832 cost_group_min_max(table,
04833 cur_index_info,
04834 cur_used_key_parts,
04835 cur_group_key_parts,
04836 tree,
04837 cur_index_tree,
04838 cur_quick_prefix_records,
04839 have_min,
04840 have_max,
04841 &cur_read_cost,
04842 &cur_records);
04843
04844
04845
04846
04847
04848 if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost))
04849 {
04850 assert(tree != 0 || cur_param_idx == MAX_KEY);
04851 index_info= cur_index_info;
04852 index= cur_index;
04853 best_read_cost= cur_read_cost;
04854 best_records= cur_records;
04855 best_index_tree= cur_index_tree;
04856 best_quick_prefix_records= cur_quick_prefix_records;
04857 best_param_idx= cur_param_idx;
04858 group_key_parts= cur_group_key_parts;
04859 group_prefix_len= cur_group_prefix_len;
04860 key_infix_len= cur_key_infix_len;
04861
04862 if (key_infix_len)
04863 {
04864 memcpy(key_infix, cur_key_infix, sizeof (key_infix));
04865 }
04866
04867 used_key_parts= cur_used_key_parts;
04868 }
04869
04870 next_index:
04871 cur_group_key_parts= 0;
04872 cur_group_prefix_len= 0;
04873 cur_key_infix_len= 0;
04874 }
04875 if (! index_info)
04876 return NULL;
04877
04878
04879 if (join->conds && min_max_arg_item &&
04880 ! check_group_min_max_predicates(join->conds, min_max_arg_item))
04881 return NULL;
04882
04883
04884 read_plan= new (*param->mem_root) optimizer::GroupMinMaxReadPlan(have_min,
04885 have_max,
04886 min_max_arg_part,
04887 group_prefix_len,
04888 used_key_parts,
04889 group_key_parts,
04890 index_info,
04891 index,
04892 key_infix_len,
04893 (key_infix_len > 0) ? key_infix : NULL,
04894 tree,
04895 best_index_tree,
04896 best_param_idx,
04897 best_quick_prefix_records);
04898 if (tree && read_plan->quick_prefix_records == 0)
04899 return NULL;
04900 read_plan->read_cost= best_read_cost;
04901 read_plan->records= best_records;
04902 return read_plan;
04903 }
04904
04905
04906
04907
04908
04909
04910
04911
04912
04913
04914
04915
04916
04917
04918
04919
04920
04921
04922
04923
04924
04925
04926
04927 static bool check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item)
04928 {
04929 assert(cond && min_max_arg_item);
04930
04931 cond= cond->real_item();
04932 Item::Type cond_type= cond->type();
04933 if (cond_type == Item::COND_ITEM)
04934 {
04935 List<Item>::iterator li(((Item_cond*) cond)->argument_list()->begin());
04936 Item *and_or_arg= NULL;
04937 while ((and_or_arg= li++))
04938 {
04939 if (! check_group_min_max_predicates(and_or_arg, min_max_arg_item))
04940 return false;
04941 }
04942 return true;
04943 }
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954 if (cond_type == Item::SUBSELECT_ITEM)
04955 return false;
04956
04957
04958 assert(cond_type == Item::FUNC_ITEM);
04959
04960
04961 Item_func *pred= (Item_func*) cond;
04962 Item **arguments= pred->arguments();
04963 Item *cur_arg= NULL;
04964 for (uint32_t arg_idx= 0; arg_idx < pred->argument_count (); arg_idx++)
04965 {
04966 cur_arg= arguments[arg_idx]->real_item();
04967 if (cur_arg->type() == Item::FIELD_ITEM)
04968 {
04969 if (min_max_arg_item->eq(cur_arg, 1))
04970 {
04971
04972
04973
04974
04975 Item_func::Functype pred_type= pred->functype();
04976 if (pred_type != Item_func::EQUAL_FUNC &&
04977 pred_type != Item_func::LT_FUNC &&
04978 pred_type != Item_func::LE_FUNC &&
04979 pred_type != Item_func::GT_FUNC &&
04980 pred_type != Item_func::GE_FUNC &&
04981 pred_type != Item_func::BETWEEN &&
04982 pred_type != Item_func::ISNULL_FUNC &&
04983 pred_type != Item_func::ISNOTNULL_FUNC &&
04984 pred_type != Item_func::EQ_FUNC &&
04985 pred_type != Item_func::NE_FUNC)
04986 return false;
04987
04988
04989 Item *args[3];
04990 memset(args, 0, 3 * sizeof(Item*));
04991 bool inv= false;
04992
04993 if (! optimizer::simple_pred(pred, args, inv))
04994 return false;
04995
04996
04997 if (args[0] && args[1] && !args[2] &&
04998 min_max_arg_item->result_type() == STRING_RESULT &&
04999
05000
05001
05002 ((args[1]->result_type() == STRING_RESULT &&
05003 ((Field_str*) min_max_arg_item->field)->charset() !=
05004 pred->compare_collation())
05005 ||
05006
05007
05008
05009
05010 (args[1]->result_type() != STRING_RESULT &&
05011 min_max_arg_item->field->cmp_type() != args[1]->result_type())))
05012 {
05013 return false;
05014 }
05015 }
05016 }
05017 else if (cur_arg->type() == Item::FUNC_ITEM)
05018 {
05019 if (! check_group_min_max_predicates(cur_arg, min_max_arg_item))
05020 return false;
05021 }
05022 else if (cur_arg->const_item())
05023 {
05024 return true;
05025 }
05026 else
05027 return false;
05028 }
05029
05030 return true;
05031 }
05032
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063
05064 static bool
05065 get_constant_key_infix(KeyInfo *,
05066 optimizer::SEL_ARG *index_range_tree,
05067 KeyPartInfo *first_non_group_part,
05068 KeyPartInfo *min_max_arg_part,
05069 KeyPartInfo *last_part,
05070 Session *,
05071 unsigned char *key_infix,
05072 uint32_t *key_infix_len,
05073 KeyPartInfo **first_non_infix_part)
05074 {
05075 optimizer::SEL_ARG *cur_range= NULL;
05076 KeyPartInfo *cur_part= NULL;
05077
05078 KeyPartInfo *end_part= min_max_arg_part ? min_max_arg_part : last_part;
05079
05080 *key_infix_len= 0;
05081 unsigned char *key_ptr= key_infix;
05082 for (cur_part= first_non_group_part; cur_part != end_part; cur_part++)
05083 {
05084
05085
05086
05087
05088 for (cur_range= index_range_tree; cur_range;
05089 cur_range= cur_range->next_key_part)
05090 {
05091 if (cur_range->field->eq(cur_part->field))
05092 break;
05093 }
05094 if (! cur_range)
05095 {
05096 if (min_max_arg_part)
05097 return false;
05098 else
05099 {
05100 *first_non_infix_part= cur_part;
05101 return true;
05102 }
05103 }
05104
05105
05106 if (cur_range->prev || cur_range->next)
05107 return false;
05108 if ((cur_range->min_flag & NO_MIN_RANGE) ||
05109 (cur_range->max_flag & NO_MAX_RANGE) ||
05110 (cur_range->min_flag & NEAR_MIN) ||
05111 (cur_range->max_flag & NEAR_MAX))
05112 return false;
05113
05114 uint32_t field_length= cur_part->store_length;
05115 if ((cur_range->maybe_null &&
05116 cur_range->min_value[0] && cur_range->max_value[0]) ||
05117 !memcmp(cur_range->min_value, cur_range->max_value, field_length))
05118 {
05119
05120 memcpy(key_ptr, cur_range->min_value, field_length);
05121 key_ptr+= field_length;
05122 *key_infix_len+= field_length;
05123 }
05124 else
05125 return false;
05126 }
05127
05128 if (!min_max_arg_part && (cur_part == last_part))
05129 *first_non_infix_part= last_part;
05130
05131 return true;
05132 }
05133
05134
05135
05136
05137
05138
05139
05140
05141
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151 static inline uint
05152 get_field_keypart(KeyInfo *index, Field *field)
05153 {
05154 KeyPartInfo *part= NULL;
05155 KeyPartInfo *end= NULL;
05156
05157 for (part= index->key_part, end= part + index->key_parts; part < end; part++)
05158 {
05159 if (field->eq(part->field))
05160 return part - index->key_part + 1;
05161 }
05162 return 0;
05163 }
05164
05165
05166
05167
05168
05169
05170
05171
05172
05173
05174
05175
05176
05177
05178
05179
05180
05181
05182
05183
05184
05185
05186
05187
05188 optimizer::SEL_ARG *get_index_range_tree(uint32_t index,
05189 optimizer::SEL_TREE* range_tree,
05190 optimizer::Parameter *param,
05191 uint32_t *param_idx)
05192 {
05193 uint32_t idx= 0;
05194 while (idx < param->keys)
05195 {
05196 if (index == param->real_keynr[idx])
05197 break;
05198 idx++;
05199 }
05200 *param_idx= idx;
05201 return range_tree->keys[idx];
05202 }
05203
05204
05205
05206
05207
05208
05209
05210
05211
05212
05213
05214
05215
05216
05217
05218
05219
05220
05221
05222
05223
05224
05225
05226
05227
05228
05229
05230
05231
05232
05233
05234
05235
05236
05237
05238
05239
05240
05241
05242
05243
05244
05245
05246
05247
05248
05249
05250
05251
05252
05253
05254
05255
05256
05257
05258
05259
05260
05261
05262
05263
05264 void cost_group_min_max(Table* table,
05265 KeyInfo *index_info,
05266 uint32_t used_key_parts,
05267 uint32_t group_key_parts,
05268 optimizer::SEL_TREE *range_tree,
05269 optimizer::SEL_ARG *,
05270 ha_rows quick_prefix_records,
05271 bool have_min,
05272 bool have_max,
05273 double *read_cost,
05274 ha_rows *records)
05275 {
05276 ha_rows table_records;
05277 uint32_t num_groups;
05278 uint32_t num_blocks;
05279 uint32_t keys_per_block;
05280 uint32_t keys_per_group;
05281 uint32_t keys_per_subgroup;
05282
05283 double p_overlap;
05284 double quick_prefix_selectivity;
05285 double io_cost;
05286 double cpu_cost= 0;
05287
05288 table_records= table->cursor->stats.records;
05289 keys_per_block= (table->cursor->stats.block_size / 2 /
05290 (index_info->key_length + table->cursor->ref_length)
05291 + 1);
05292 num_blocks= (uint32_t) (table_records / keys_per_block) + 1;
05293
05294
05295 keys_per_group= index_info->rec_per_key[group_key_parts - 1];
05296 if (keys_per_group == 0)
05297
05298 keys_per_group= (uint32_t)(table_records / 10) + 1;
05299 num_groups= (uint32_t)(table_records / keys_per_group) + 1;
05300
05301
05302 if (range_tree && (quick_prefix_records != HA_POS_ERROR))
05303 {
05304 quick_prefix_selectivity= (double) quick_prefix_records /
05305 (double) table_records;
05306 num_groups= (uint32_t) rint(num_groups * quick_prefix_selectivity);
05307 set_if_bigger(num_groups, 1U);
05308 }
05309
05310 if (used_key_parts > group_key_parts)
05311 {
05312
05313
05314
05315 keys_per_subgroup= index_info->rec_per_key[used_key_parts - 1];
05316 if (keys_per_subgroup >= keys_per_block)
05317 p_overlap= 1.0;
05318 else
05319 {
05320 double blocks_per_group= (double) num_blocks / (double) num_groups;
05321 p_overlap= (blocks_per_group * (keys_per_subgroup - 1)) / keys_per_group;
05322 p_overlap= min(p_overlap, 1.0);
05323 }
05324 io_cost= (double) min(num_groups * (1 + p_overlap), (double)num_blocks);
05325 }
05326 else
05327 io_cost= (keys_per_group > keys_per_block) ?
05328 (have_min && have_max) ? (double) (num_groups + 1) :
05329 (double) num_groups :
05330 (double) num_blocks;
05331
05332
05333
05334
05335
05336
05337 cpu_cost= (double) num_groups / TIME_FOR_COMPARE;
05338
05339 *read_cost= io_cost + cpu_cost;
05340 *records= num_groups;
05341 }
05342
05343
05344
05345
05346
05347
05348
05349
05350
05351
05352
05353
05354
05355
05356
05357
05358
05359
05360
05361
05362
05363
05364 optimizer::QuickSelectInterface *
05365 optimizer::GroupMinMaxReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
05366 {
05367 optimizer::QuickGroupMinMaxSelect *quick= new optimizer::QuickGroupMinMaxSelect(param->table,
05368 param->session->lex().current_select->join,
05369 have_min,
05370 have_max,
05371 min_max_arg_part,
05372 group_prefix_len,
05373 group_key_parts,
05374 used_key_parts,
05375 index_info,
05376 index,
05377 read_cost,
05378 records,
05379 key_infix_len,
05380 key_infix,
05381 parent_alloc);
05382 if (quick->init())
05383 {
05384 delete quick;
05385 return NULL;
05386 }
05387
05388 if (range_tree)
05389 {
05390 assert(quick_prefix_records > 0);
05391 if (quick_prefix_records == HA_POS_ERROR)
05392 {
05393 quick->quick_prefix_select= NULL;
05394 }
05395 else
05396 {
05397
05398 quick->quick_prefix_select= optimizer::get_quick_select(param,
05399 param_idx,
05400 index_tree,
05401 HA_MRR_USE_DEFAULT_IMPL,
05402 0,
05403 &quick->alloc);
05404 }
05405
05406
05407
05408
05409
05410
05411 if (min_max_arg_part)
05412 {
05413 optimizer::SEL_ARG *min_max_range= index_tree;
05414 while (min_max_range)
05415 {
05416 if (min_max_range->field->eq(min_max_arg_part->field))
05417 break;
05418 min_max_range= min_max_range->next_key_part;
05419 }
05420
05421 while (min_max_range && min_max_range->prev)
05422 min_max_range= min_max_range->prev;
05423
05424 while (min_max_range)
05425 {
05426 if (quick->add_range(min_max_range))
05427 {
05428 delete quick;
05429 quick= NULL;
05430 return NULL;
05431 }
05432 min_max_range= min_max_range->next;
05433 }
05434 }
05435 }
05436 else
05437 quick->quick_prefix_select= NULL;
05438
05439 quick->update_key_stat();
05440 quick->adjust_prefix_ranges();
05441
05442 return quick;
05443 }
05444
05445
05446 optimizer::QuickSelectInterface *optimizer::RangeReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
05447 {
05448 optimizer::QuickRangeSelect *quick= optimizer::get_quick_select(param, key_idx, key, mrr_flags, mrr_buf_size, parent_alloc);
05449 if (quick)
05450 {
05451 quick->records= records;
05452 quick->read_time= read_cost;
05453 }
05454 return quick;
05455 }
05456
05457
05458 uint32_t optimizer::RorScanInfo::findFirstNotSet() const
05459 {
05460 boost::dynamic_bitset<> map= bitsToBitset();
05461 for (boost::dynamic_bitset<>::size_type i= 0; i < map.size(); i++)
05462 {
05463 if (not map.test(i))
05464 return i;
05465 }
05466 return map.size();
05467 }
05468
05469
05470 size_t optimizer::RorScanInfo::getBitCount() const
05471 {
05472 boost::dynamic_bitset<> tmp_bitset= bitsToBitset();
05473 return tmp_bitset.count();
05474 }
05475
05476
05477 void optimizer::RorScanInfo::subtractBitset(const boost::dynamic_bitset<>& in_bitset)
05478 {
05479 boost::dynamic_bitset<> tmp_bitset= bitsToBitset();
05480 tmp_bitset-= in_bitset;
05481 covered_fields= tmp_bitset.to_ulong();
05482 }
05483
05484
05485 boost::dynamic_bitset<> optimizer::RorScanInfo::bitsToBitset() const
05486 {
05487 string res;
05488 uint64_t conv= covered_fields;
05489 while (conv)
05490 {
05491 res.push_back((conv & 1) + '0');
05492 conv>>= 1;
05493 }
05494 if (! res.empty())
05495 {
05496 std::reverse(res.begin(), res.end());
05497 }
05498 string final(covered_fields_size - res.length(), '0');
05499 final.append(res);
05500 return boost::dynamic_bitset<>(final);
05501 }
05502
05503
05504 }