00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021 #include <drizzled/session.h>
00022 #include <drizzled/sql_select.h>
00023 #include <drizzled/join.h>
00024 #include <drizzled/optimizer/range.h>
00025 #include <drizzled/optimizer/quick_group_min_max_select.h>
00026 #include <drizzled/optimizer/quick_range.h>
00027 #include <drizzled/optimizer/quick_range_select.h>
00028 #include <drizzled/optimizer/sel_arg.h>
00029 #include <drizzled/internal/m_string.h>
00030 #include <drizzled/util/functors.h>
00031 #include <drizzled/key.h>
00032 #include <drizzled/table.h>
00033 #include <drizzled/system_variables.h>
00034
00035 #include <vector>
00036
00037 using namespace std;
00038
00039 namespace drizzled {
00040 namespace optimizer {
00041
00042 QuickGroupMinMaxSelect::QuickGroupMinMaxSelect(Table *table,
00043 Join *join_arg,
00044 bool have_min_arg,
00045 bool have_max_arg,
00046 KeyPartInfo *min_max_arg_part_arg,
00047 uint32_t group_prefix_len_arg,
00048 uint32_t group_key_parts_arg,
00049 uint32_t used_key_parts_arg,
00050 KeyInfo *index_info_arg,
00051 uint32_t use_index,
00052 double read_cost_arg,
00053 ha_rows records_arg,
00054 uint32_t key_infix_len_arg,
00055 unsigned char *key_infix_arg,
00056 memory::Root *parent_alloc)
00057 :
00058 join(join_arg),
00059 index_info(index_info_arg),
00060 group_prefix_len(group_prefix_len_arg),
00061 group_key_parts(group_key_parts_arg),
00062 have_min(have_min_arg),
00063 have_max(have_max_arg),
00064 seen_first_key(false),
00065 min_max_arg_part(min_max_arg_part_arg),
00066 key_infix(key_infix_arg),
00067 key_infix_len(key_infix_len_arg),
00068 min_functions_it(NULL),
00069 max_functions_it(NULL)
00070 {
00071 head= table;
00072 cursor= head->cursor;
00073 index= use_index;
00074 record= head->record[0];
00075 tmp_record= head->getUpdateRecord();
00076 read_time= read_cost_arg;
00077 records= records_arg;
00078 used_key_parts= used_key_parts_arg;
00079 real_key_parts= used_key_parts_arg;
00080 real_prefix_len= group_prefix_len + key_infix_len;
00081 group_prefix= NULL;
00082 min_max_arg_len= min_max_arg_part ? min_max_arg_part->store_length : 0;
00083
00084
00085
00086
00087
00088 assert(! parent_alloc);
00089 if (! parent_alloc)
00090 {
00091 alloc.init(join->session->variables.range_alloc_block_size);
00092 join->session->mem_root= &alloc;
00093 }
00094 else
00095 memset(&alloc, 0, sizeof(memory::Root));
00096 }
00097
00098
00099 int QuickGroupMinMaxSelect::init()
00100 {
00101 if (group_prefix)
00102 return 0;
00103
00104 last_prefix= alloc.alloc(group_prefix_len);
00105
00106
00107
00108
00109 group_prefix= alloc.alloc(real_prefix_len + min_max_arg_len);
00110
00111 if (key_infix_len > 0)
00112 {
00113
00114
00115
00116
00117 unsigned char *tmp_key_infix= alloc.alloc(key_infix_len);
00118 memcpy(tmp_key_infix, this->key_infix, key_infix_len);
00119 this->key_infix= tmp_key_infix;
00120 }
00121
00122 if (min_max_arg_part)
00123 {
00124 min_functions= have_min ? new List<Item_sum> : NULL;
00125 max_functions= have_max ? new List<Item_sum> : NULL;
00126 Item_sum **func_ptr= join->sum_funcs;
00127 while (Item_sum* min_max_item= *(func_ptr++))
00128 {
00129 if (have_min && (min_max_item->sum_func() == Item_sum::MIN_FUNC))
00130 min_functions->push_back(min_max_item);
00131 else if (have_max && (min_max_item->sum_func() == Item_sum::MAX_FUNC))
00132 max_functions->push_back(min_max_item);
00133 }
00134
00135 if (have_min)
00136 min_functions_it= new List<Item_sum>::iterator(min_functions->begin());
00137 if (have_max)
00138 max_functions_it= new List<Item_sum>::iterator(max_functions->begin());
00139 }
00140 return 0;
00141 }
00142
00143 QuickGroupMinMaxSelect::~QuickGroupMinMaxSelect()
00144 {
00145 if (cursor->inited != Cursor::NONE)
00146 {
00147 cursor->endIndexScan();
00148 }
00149 if (min_max_arg_part)
00150 {
00151 for_each(min_max_ranges.begin(),
00152 min_max_ranges.end(),
00153 DeletePtr());
00154 }
00155 min_max_ranges.clear();
00156 alloc.free_root(MYF(0));
00157 delete min_functions_it;
00158 delete max_functions_it;
00159 delete quick_prefix_select;
00160 }
00161
00162
00163 bool QuickGroupMinMaxSelect::add_range(SEL_ARG *sel_range)
00164 {
00165 QuickRange *range= NULL;
00166 uint32_t range_flag= sel_range->min_flag | sel_range->max_flag;
00167
00168
00169 if ((range_flag & NO_MIN_RANGE) && (range_flag & NO_MAX_RANGE))
00170 return false;
00171
00172 if (! (sel_range->min_flag & NO_MIN_RANGE) &&
00173 ! (sel_range->max_flag & NO_MAX_RANGE))
00174 {
00175 if (sel_range->maybe_null &&
00176 sel_range->min_value[0] && sel_range->max_value[0])
00177 range_flag|= NULL_RANGE;
00178 else if (memcmp(sel_range->min_value, sel_range->max_value,
00179 min_max_arg_len) == 0)
00180 range_flag|= EQ_RANGE;
00181 }
00182 range= new QuickRange(sel_range->min_value,
00183 min_max_arg_len,
00184 make_keypart_map(sel_range->part),
00185 sel_range->max_value,
00186 min_max_arg_len,
00187 make_keypart_map(sel_range->part),
00188 range_flag);
00189 if (! range)
00190 return true;
00191 min_max_ranges.push_back(range);
00192 return false;
00193 }
00194
00195
00196 void QuickGroupMinMaxSelect::adjust_prefix_ranges()
00197 {
00198 if (quick_prefix_select &&
00199 group_prefix_len < quick_prefix_select->max_used_key_length)
00200 {
00201 DYNAMIC_ARRAY& arr= quick_prefix_select->ranges;
00202 for (size_t inx= 0; inx < arr.size(); inx++)
00203 reinterpret_cast<QuickRange**>(arr.buffer)[inx]->flag &= ~(NEAR_MIN | NEAR_MAX);
00204 }
00205 }
00206
00207
00208 void QuickGroupMinMaxSelect::update_key_stat()
00209 {
00210 max_used_key_length= real_prefix_len;
00211 if (! min_max_ranges.empty())
00212 {
00213 QuickRange *cur_range= NULL;
00214 if (have_min)
00215 {
00216 cur_range= min_max_ranges.back();
00217 if (! (cur_range->flag & NO_MIN_RANGE))
00218 {
00219 max_used_key_length+= min_max_arg_len;
00220 used_key_parts++;
00221 return;
00222 }
00223 }
00224 if (have_max)
00225 {
00226 cur_range= min_max_ranges.front();
00227 if (! (cur_range->flag & NO_MAX_RANGE))
00228 {
00229 max_used_key_length+= min_max_arg_len;
00230 used_key_parts++;
00231 return;
00232 }
00233 }
00234 }
00235 else if (have_min && min_max_arg_part &&
00236 min_max_arg_part->field->real_maybe_null())
00237 {
00238
00239
00240
00241
00242
00243
00244
00245
00246 max_used_key_length+= min_max_arg_len;
00247 used_key_parts++;
00248 }
00249 }
00250
00251
00252 int QuickGroupMinMaxSelect::reset(void)
00253 {
00254 int result;
00255
00256 cursor->extra(HA_EXTRA_KEYREAD);
00257 if ((result= cursor->startIndexScan(index,1)))
00258 return result;
00259 if (quick_prefix_select && quick_prefix_select->reset())
00260 return 0;
00261 result= cursor->index_last(record);
00262 if (result == HA_ERR_END_OF_FILE)
00263 return 0;
00264
00265 key_copy(last_prefix, record, index_info, group_prefix_len);
00266
00267 return 0;
00268 }
00269
00270
00271 int QuickGroupMinMaxSelect::get_next()
00272 {
00273 int min_res= 0;
00274 int max_res= 0;
00275 int result= 0;
00276 int is_last_prefix= 0;
00277
00278
00279
00280
00281
00282 do
00283 {
00284 result= next_prefix();
00285
00286
00287
00288
00289 if (! result)
00290 {
00291 is_last_prefix= key_cmp(index_info->key_part, last_prefix,
00292 group_prefix_len);
00293 assert(is_last_prefix <= 0);
00294 }
00295 else
00296 {
00297 if (result == HA_ERR_KEY_NOT_FOUND)
00298 continue;
00299 break;
00300 }
00301
00302 if (have_min)
00303 {
00304 min_res= next_min();
00305 if (min_res == 0)
00306 update_min_result();
00307 }
00308
00309 if ((have_max && !have_min) ||
00310 (have_max && have_min && (min_res == 0)))
00311 {
00312 max_res= next_max();
00313 if (max_res == 0)
00314 update_max_result();
00315
00316 assert(((have_max && !have_min) ||
00317 (have_max && have_min && (max_res == 0))));
00318 }
00319
00320
00321
00322
00323
00324 if (! have_min && ! have_max && key_infix_len > 0)
00325 result= cursor->index_read_map(record,
00326 group_prefix,
00327 make_prev_keypart_map(real_key_parts),
00328 HA_READ_KEY_EXACT);
00329
00330 result= have_min ? min_res : have_max ? max_res : result;
00331 } while ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
00332 is_last_prefix != 0);
00333
00334 if (result == 0)
00335 {
00336
00337
00338
00339
00340
00341
00342 copy_fields(&join->tmp_table_param);
00343 }
00344 else if (result == HA_ERR_KEY_NOT_FOUND)
00345 result= HA_ERR_END_OF_FILE;
00346
00347 return result;
00348 }
00349
00350
00351 int QuickGroupMinMaxSelect::next_min()
00352 {
00353 int result= 0;
00354
00355
00356 if (! min_max_ranges.empty())
00357 {
00358 if ((result= next_min_in_range()))
00359 return result;
00360 }
00361 else
00362 {
00363
00364 if (key_infix_len > 0)
00365 {
00366 if ((result= cursor->index_read_map(record,
00367 group_prefix,
00368 make_prev_keypart_map(real_key_parts),
00369 HA_READ_KEY_EXACT)))
00370 return result;
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380 if (min_max_arg_part && min_max_arg_part->field->is_null())
00381 {
00382
00383 key_copy(tmp_record, record, index_info, 0);
00384 result= cursor->index_read_map(record,
00385 tmp_record,
00386 make_keypart_map(real_key_parts),
00387 HA_READ_AFTER_KEY);
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 if (! result)
00399 {
00400 if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
00401 key_restore(record, tmp_record, index_info, 0);
00402 }
00403 else if (result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE)
00404 result= 0;
00405 }
00406 }
00407
00408
00409
00410
00411
00412 return result;
00413 }
00414
00415
00416 int QuickGroupMinMaxSelect::next_max()
00417 {
00418
00419 return min_max_ranges.empty()
00420 ? cursor->index_read_map(record, group_prefix, make_prev_keypart_map(real_key_parts), HA_READ_PREFIX_LAST)
00421 : next_max_in_range();
00422 }
00423
00424
00425 int QuickGroupMinMaxSelect::next_prefix()
00426 {
00427 int result= 0;
00428
00429 if (quick_prefix_select)
00430 {
00431 unsigned char *cur_prefix= seen_first_key ? group_prefix : NULL;
00432 if ((result= quick_prefix_select->get_next_prefix(group_prefix_len,
00433 make_prev_keypart_map(group_key_parts),
00434 cur_prefix)))
00435 return result;
00436 seen_first_key= true;
00437 }
00438 else
00439 {
00440 if (! seen_first_key)
00441 {
00442 result= cursor->index_first(record);
00443 if (result)
00444 return result;
00445 seen_first_key= true;
00446 }
00447 else
00448 {
00449
00450 result= cursor->index_read_map(record,
00451 group_prefix,
00452 make_prev_keypart_map(group_key_parts),
00453 HA_READ_AFTER_KEY);
00454 if (result)
00455 return result;
00456 }
00457 }
00458
00459
00460 key_copy(group_prefix, record, index_info, group_prefix_len);
00461
00462 if (key_infix_len > 0)
00463 memcpy(group_prefix + group_prefix_len,
00464 key_infix,
00465 key_infix_len);
00466
00467 return 0;
00468 }
00469
00470
00471 int QuickGroupMinMaxSelect::next_min_in_range()
00472 {
00473 ha_rkey_function find_flag;
00474 key_part_map keypart_map;
00475 QuickRange *cur_range= NULL;
00476 bool found_null= false;
00477 int result= HA_ERR_KEY_NOT_FOUND;
00478 basic_string<unsigned char> max_key;
00479
00480 max_key.reserve(real_prefix_len + min_max_arg_len);
00481
00482 assert(! min_max_ranges.empty());
00483
00484 for (vector<QuickRange *>::iterator it= min_max_ranges.begin(); it != min_max_ranges.end(); ++it)
00485 {
00486 cur_range= *it;
00487
00488
00489
00490
00491
00492 if (it != min_max_ranges.begin() &&
00493 ! (cur_range->flag & NO_MAX_RANGE) &&
00494 (key_cmp(min_max_arg_part,
00495 (const unsigned char*) cur_range->max_key,
00496 min_max_arg_len) == 1))
00497 continue;
00498
00499 if (cur_range->flag & NO_MIN_RANGE)
00500 {
00501 keypart_map= make_prev_keypart_map(real_key_parts);
00502 find_flag= HA_READ_KEY_EXACT;
00503 }
00504 else
00505 {
00506
00507 memcpy(group_prefix + real_prefix_len,
00508 cur_range->min_key,
00509 cur_range->min_length);
00510 keypart_map= make_keypart_map(real_key_parts);
00511 find_flag= (cur_range->flag & (EQ_RANGE | NULL_RANGE)) ?
00512 HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MIN) ?
00513 HA_READ_AFTER_KEY : HA_READ_KEY_OR_NEXT;
00514 }
00515
00516 result= cursor->index_read_map(record, group_prefix, keypart_map, find_flag);
00517 if (result)
00518 {
00519 if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
00520 (cur_range->flag & (EQ_RANGE | NULL_RANGE)))
00521 continue;
00522
00523
00524
00525
00526
00527
00528 break;
00529 }
00530
00531
00532 if (cur_range->flag & EQ_RANGE)
00533 break;
00534
00535 if (cur_range->flag & NULL_RANGE)
00536 {
00537
00538
00539
00540
00541 memcpy(tmp_record, record, head->getShare()->rec_buff_length);
00542 found_null= true;
00543 continue;
00544 }
00545
00546
00547 if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
00548 {
00549 result= HA_ERR_KEY_NOT_FOUND;
00550 continue;
00551 }
00552
00553
00554 if (! (cur_range->flag & NO_MAX_RANGE) )
00555 {
00556
00557 max_key.clear();
00558 max_key.append(group_prefix, real_prefix_len);
00559 max_key.append(cur_range->max_key, cur_range->max_length);
00560
00561 int cmp_res= key_cmp(index_info->key_part,
00562 max_key.data(),
00563 real_prefix_len + min_max_arg_len);
00564 if (! (((cur_range->flag & NEAR_MAX) && (cmp_res == -1)) ||
00565 (cmp_res <= 0)))
00566 {
00567 result= HA_ERR_KEY_NOT_FOUND;
00568 continue;
00569 }
00570 }
00571
00572 assert(result == 0);
00573 break;
00574 }
00575
00576
00577
00578
00579
00580 if (found_null && result)
00581 {
00582 memcpy(record, tmp_record, head->getShare()->rec_buff_length);
00583 result= 0;
00584 }
00585 return result;
00586 }
00587
00588
00589 int QuickGroupMinMaxSelect::next_max_in_range()
00590 {
00591 ha_rkey_function find_flag;
00592 key_part_map keypart_map;
00593 QuickRange *cur_range= NULL;
00594 int result= 0;
00595 basic_string<unsigned char> min_key;
00596 min_key.reserve(real_prefix_len + min_max_arg_len);
00597
00598 assert(! min_max_ranges.empty());
00599
00600 for (vector<QuickRange *>::reverse_iterator rit= min_max_ranges.rbegin();
00601 rit != min_max_ranges.rend();
00602 ++rit)
00603 {
00604 cur_range= *rit;
00605
00606
00607
00608
00609
00610 if (rit != min_max_ranges.rbegin() &&
00611 ! (cur_range->flag & NO_MIN_RANGE) &&
00612 (key_cmp(min_max_arg_part,
00613 (const unsigned char*) cur_range->min_key,
00614 min_max_arg_len) == -1))
00615 continue;
00616
00617 if (cur_range->flag & NO_MAX_RANGE)
00618 {
00619 keypart_map= make_prev_keypart_map(real_key_parts);
00620 find_flag= HA_READ_PREFIX_LAST;
00621 }
00622 else
00623 {
00624
00625 memcpy(group_prefix + real_prefix_len,
00626 cur_range->max_key,
00627 cur_range->max_length);
00628 keypart_map= make_keypart_map(real_key_parts);
00629 find_flag= (cur_range->flag & EQ_RANGE) ?
00630 HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MAX) ?
00631 HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV;
00632 }
00633
00634 result= cursor->index_read_map(record, group_prefix, keypart_map, find_flag);
00635
00636 if (result)
00637 {
00638 if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
00639 (cur_range->flag & EQ_RANGE))
00640 continue;
00641
00642
00643
00644
00645
00646 return result;
00647 }
00648
00649 if (cur_range->flag & EQ_RANGE)
00650 return 0;
00651
00652
00653 if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
00654 continue;
00655
00656
00657 if (! (cur_range->flag & NO_MIN_RANGE) )
00658 {
00659
00660 min_key.clear();
00661 min_key.append(group_prefix, real_prefix_len);
00662 min_key.append(cur_range->min_key, cur_range->min_length);
00663
00664
00665 int cmp_res= key_cmp(index_info->key_part,
00666 min_key.data(),
00667 real_prefix_len + min_max_arg_len);
00668 if (! (((cur_range->flag & NEAR_MIN) && (cmp_res == 1)) ||
00669 (cmp_res >= 0)))
00670 continue;
00671 }
00672
00673 return result;
00674 }
00675 return HA_ERR_KEY_NOT_FOUND;
00676 }
00677
00678
00679 void QuickGroupMinMaxSelect::update_min_result()
00680 {
00681 *min_functions_it= min_functions->begin();
00682 for (Item_sum *min_func; (min_func= (*min_functions_it)++); )
00683 min_func->reset();
00684 }
00685
00686
00687 void QuickGroupMinMaxSelect::update_max_result()
00688 {
00689 *max_functions_it= max_functions->begin();
00690 for (Item_sum *max_func; (max_func= (*max_functions_it)++); )
00691 max_func->reset();
00692 }
00693
00694
00695 void QuickGroupMinMaxSelect::add_keys_and_lengths(string *key_names,
00696 string *used_lengths)
00697 {
00698 char buf[64];
00699 key_names->append(index_info->name);
00700 uint32_t length= internal::int64_t2str(max_used_key_length, buf, 10) - buf;
00701 used_lengths->append(buf, length);
00702 }
00703
00704 }
00705 }