22 #include <drizzled/session.h>
23 #include <drizzled/optimizer/quick_range.h>
24 #include <drizzled/optimizer/quick_range_select.h>
25 #include <drizzled/internal/m_string.h>
26 #include <drizzled/current_session.h>
27 #include <drizzled/key.h>
28 #include <drizzled/table.h>
29 #include <drizzled/util/test.h>
30 #include <drizzled/system_variables.h>
39 optimizer::QuickRangeSelect::QuickRangeSelect(Session *session,
43 memory::Root *parent_alloc)
47 in_ror_merged_scan(false),
64 key_part_info= head->key_info[index].key_part;
65 ranges.init(
sizeof(optimizer::QuickRange*), 16, 16);
68 mrr_buf_size= session->variables.read_rnd_buff_size;
70 if (! no_alloc && ! parent_alloc)
73 alloc.init(session->variables.range_alloc_block_size);
74 session->mem_root= &alloc;
78 memset(&alloc, 0,
sizeof(alloc));
82 record= head->record[0];
83 save_read_set= head->read_set;
84 save_write_set= head->write_set;
85 column_bitmap=
new boost::dynamic_bitset<>(table->getShare()->sizeFields());
91 if (cursor->inited != Cursor::NONE)
92 cursor->ha_index_or_rnd_end();
93 return (cursor->startIndexScan(index, 1));
99 if (cursor->inited != Cursor::NONE)
100 cursor->ha_index_or_rnd_end();
104 optimizer::QuickRangeSelect::~QuickRangeSelect()
115 cursor->extra(HA_EXTRA_NO_KEYREAD);
119 cursor->ha_external_lock(current_session, F_UNLCK);
125 delete column_bitmap;
126 alloc.free_root(MYF(0));
128 head->column_bitmaps_set(*save_read_set, *save_write_set);
135 Cursor* save_file= cursor;
138 in_ror_merged_scan= 1;
141 if (init() || reset())
145 head->column_bitmaps_set(*column_bitmap, *column_bitmap);
156 session= head->in_use;
157 if (not (cursor= head->cursor->clone(session->
mem_root)))
166 my_error(ER_OUT_OF_RESOURCES, MYF(0));
171 head->column_bitmaps_set(*column_bitmap, *column_bitmap);
173 if (cursor->ha_external_lock(session, F_RDLCK))
176 if (init() || reset())
178 cursor->ha_external_lock(session, F_UNLCK);
183 last_rowid= cursor->ref;
192 org_file= head->cursor;
193 head->cursor= cursor;
195 if (not head->no_keyread)
198 head->mark_columns_used_by_index(index);
200 head->prepare_for_position();
201 head->cursor= org_file;
202 *column_bitmap|= *head->read_set;
203 head->column_bitmaps_set(*column_bitmap, *column_bitmap);
208 head->column_bitmaps_set(*save_read_set, *save_write_set);
217 cursor->position(record);
223 if (ranges.size() == 1)
226 if ((tmp->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE)
228 KeyInfo *key=head->key_info+index;
229 return ((key->flags & (HA_NOSAME)) == HA_NOSAME &&
230 key->key_length == tmp->min_length);
243 if (cursor->inited == Cursor::NONE && (error= cursor->startIndexScan(index, 1)))
253 assert(not (mrr_buf_size));
257 mrr_flags|= HA_MRR_SORTED;
260 optimizer::quick_range_seq_init,
261 optimizer::quick_range_seq_next
263 error= cursor->multi_range_read_init(&seq_funcs,
274 if (in_ror_merged_scan)
280 head->column_bitmaps_set(*column_bitmap, *column_bitmap);
283 int result= cursor->multi_range_read_next(&dummy);
285 if (in_ror_merged_scan)
288 head->column_bitmaps_set(*save_read_set, *save_write_set);
295 key_part_map keypart_map,
296 unsigned char *cur_prefix)
305 assert(cur_prefix != 0);
306 result= cursor->index_read_map(record,
310 if (result || (cursor->compare_key(cursor->end_range) <= 0))
319 return HA_ERR_END_OF_FILE;
321 last_range= *(cur_range++);
323 start_key.key= (
const unsigned char*) last_range->min_key;
324 start_key.length= min(last_range->min_length, (uint16_t)prefix_length);
325 start_key.keypart_map= last_range->min_keypart_map & keypart_map;
326 start_key.flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
327 (last_range->flag & EQ_RANGE) ?
328 HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
329 end_key.key= (
const unsigned char*) last_range->max_key;
330 end_key.length= min(last_range->max_length, (uint16_t)prefix_length);
331 end_key.keypart_map= last_range->max_keypart_map & keypart_map;
336 end_key.flag= (last_range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
339 result= cursor->read_range_first(last_range->min_keypart_map ? &start_key : 0,
340 last_range->max_keypart_map ? &end_key : 0,
341 test(last_range->flag & EQ_RANGE),
343 if (last_range->flag == (UNIQUE_RANGE | EQ_RANGE))
346 if (result != HA_ERR_END_OF_FILE)
357 uint32_t max= ranges.size() - 1;
358 uint32_t mid= (max + min) / 2;
362 if (cmp_next(reinterpret_cast<optimizer::QuickRange**>(ranges.buffer)[mid]))
369 mid= (min + max) / 2;
372 return not cmp_next(res) && not cmp_prev(res);
378 if (range_arg->flag & NO_MAX_RANGE)
384 for (
unsigned char *key=range_arg->max_key, *end=key+range_arg->max_length;
386 key+= store_length, key_part++)
389 store_length= key_part->store_length;
390 if (key_part->null_bit)
394 if (! key_part->field->is_null())
398 else if (key_part->field->is_null())
403 if ((cmp= key_part->field->key_cmp(key, key_part->length)) < 0)
408 return (range_arg->flag & NEAR_MAX) ? 1 : 0;
414 if (range_arg->flag & NO_MIN_RANGE)
417 int cmp=
key_cmp(key_part_info,
419 range_arg->min_length);
420 if (cmp > 0 || (cmp == 0 && (range_arg->flag & NEAR_MIN) ==
false))
428 KeyInfo *key_info= head->key_info + index;
429 str->append(key_info->name);
434 string *used_lengths)
438 KeyInfo *key_info= head->key_info + index;
439 key_names->append(key_info->name);
440 length= internal::int64_t2str(max_used_key_length, buf, 10) - buf;
441 used_lengths->append(buf, length);
457 used_key_parts(used_key_parts_arg)
461 for (; pr != end_range; pr++)
463 rev_ranges.push_back(*pr);
465 rev_it= rev_ranges.begin();
468 BOOST_FOREACH(QuickRange* it, rev_ranges)
470 if ((it->flag & EQ_RANGE) && head->
key_info[
index].key_length != it->max_length)
472 it->flag&= ~EQ_RANGE;
497 result= ((last_range->flag & EQ_RANGE &&
498 used_key_parts <= head->key_info[index].key_parts) ?
499 cursor->index_next_same(record, last_range->min_key,
500 last_range->min_length) :
501 cursor->index_prev(record));
504 if (cmp_prev(*(rev_it - 1)) == 0)
507 else if (result != HA_ERR_END_OF_FILE)
511 if (rev_it == rev_ranges.end())
513 return HA_ERR_END_OF_FILE;
518 if (last_range->flag & NO_MAX_RANGE)
521 if ((local_error= cursor->index_last(record)))
523 if (cmp_prev(last_range) == 0)
529 if (last_range->flag & EQ_RANGE
530 && used_key_parts <= head->key_info[index].key_parts)
532 result = cursor->index_read_map(record,
534 last_range->max_keypart_map,
539 assert(last_range->flag & NEAR_MAX ||
540 (last_range->flag & EQ_RANGE &&
541 used_key_parts > head->key_info[index].key_parts) ||
542 range_reads_after_key(last_range));
543 result= cursor->index_read_map(record,
545 last_range->max_keypart_map,
546 ((last_range->flag & NEAR_MAX) ?
548 HA_READ_PREFIX_LAST_OR_PREV));
552 if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
557 if (cmp_prev(last_range) == 0)
559 if (last_range->flag == (UNIQUE_RANGE | EQ_RANGE))
574 return ((range_arg->flag & (NO_MAX_RANGE | NEAR_MAX)) ||
575 ! (range_arg->flag & EQ_RANGE) ||
576 head->key_info[index].key_length != range_arg->max_length) ? 1 : 0;
bool unique_key_range() const
void add_keys_and_lengths(std::string *key_names, std::string *used_lengths)
int get_next_prefix(uint32_t prefix_length, key_part_map keypart_map, unsigned char *cur_prefix)
TODO: Rename this file - func.h is stupid.
int key_cmp(KeyPartInfo *key_part, const unsigned char *key, uint32_t key_length)
int cmp_prev(QuickRange *range)
int cmp_next(QuickRange *range)
static void store_length(unsigned char *to, uint32_t length, uint32_t pack_length)
int init_ror_merged_scan(bool reuse_handler)
void add_info_string(std::string *str)