summaryrefslogtreecommitdiff
path: root/sql/multi_range_read.cc
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2010-11-03 11:03:07 +0300
committerSergey Petrunya <psergey@askmonty.org>2010-11-03 11:03:07 +0300
commitd6ec99d0b663465c78e3a4cf8121ed05407fe2e4 (patch)
treedd3af29f1776365784d16b771d215b7b932e175d /sql/multi_range_read.cc
parent59db1d7a3939fde90cfe743ec9c2d81e5b57dc42 (diff)
parentc46450de724449466060a0934de2c4244674aa76 (diff)
downloadmariadb-git-d6ec99d0b663465c78e3a4cf8121ed05407fe2e4.tar.gz
Merge {DS-DRR improvements:code cleanup} into MWL#128+DS-MRR tree
Diffstat (limited to 'sql/multi_range_read.cc')
-rw-r--r--sql/multi_range_read.cc201
1 files changed, 67 insertions, 134 deletions
diff --git a/sql/multi_range_read.cc b/sql/multi_range_read.cc
index a6a75c1d06e..d70d3243903 100644
--- a/sql/multi_range_read.cc
+++ b/sql/multi_range_read.cc
@@ -282,8 +282,20 @@ scan_it_again:
DBUG_RETURN(result);
}
+/****************************************************************************
+ * Mrr_*_reader classes (building blocks for DS-MRR)
+ ***************************************************************************/
-/***** MRR_impl classes ****************************************************/
+int Mrr_simple_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
+ void *seq_init_param, uint n_ranges,
+ uint mode, Buffer_manager *buf_manager_arg)
+{
+ HANDLER_BUFFER no_buffer = {NULL, NULL, NULL};
+ h= h_arg;
+ res= 0;
+ return h->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
+ mode, &no_buffer);
+}
int Mrr_simple_index_reader::get_next(char **range_info)
{
@@ -297,44 +309,35 @@ int Mrr_simple_index_reader::get_next(char **range_info)
return res;
}
-int Mrr_simple_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
- void *seq_init_param, uint n_ranges,
- uint mode, Buffer_manager *buf_manager_arg)
-{
- HANDLER_BUFFER no_buffer = {NULL, NULL, NULL};
- h= h_arg;
- res= 0;
- return h->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
- mode, &no_buffer);
-}
/**
- DS-MRR/CPK: multi_range_read_next() function
-
- @param range_info OUT identifier of range that the returned record belongs to
+ @brief Get next index record
+
+ @param range_info OUT identifier of range that the returned record belongs to
@note
- This function walks over key buffer and does index reads, i.e. it produces
- {current_record, range_id} pairs.
-
- The function has the same call contract like multi_range_read_next()'s.
-
We actually iterate over nested sequences:
- - a disjoint sequence of index ranges
- - each range has multiple records
- - each record goes into multiple identical ranges.
+ - an ordered sequence of groups of identical keys
+ - each key group has key value, which has multiple matching records
+ - thus, each record matches all members of the key group
@retval 0 OK, next record was successfully read
@retval HA_ERR_END_OF_FILE End of records
@retval Other Some other error
*/
-int Mrr_ordered_index_reader::get_next(char **range_info_arg)
+int Mrr_ordered_index_reader::get_next(char **range_info)
{
DBUG_ENTER("Mrr_ordered_index_reader::get_next");
- if (!know_key_tuple_params) /* We're in startup phase */
+ if (!know_key_tuple_params)
+ {
+ /*
+ We're at the very start, haven't filled the buffer or even know what
+ will be there. Force the caller to call refill_buffer():
+ */
DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
while (1)
{
@@ -355,24 +358,8 @@ int Mrr_ordered_index_reader::get_next(char **range_info_arg)
{
if (key_buffer->is_empty())
{
- /*if (auto_refill)
- {
- int res;
- if ((res= refill_buffer()))
- DBUG_RETURN(res);
- if (key_buffer->is_empty())
- {
- index_scan_eof= TRUE;
- DBUG_RETURN(HA_ERR_END_OF_FILE);
- }
- }
- else
- */
- {
- /* Buffer refills are managed by somebody else for us */
- index_scan_eof= TRUE;
- DBUG_RETURN(HA_ERR_END_OF_FILE);
- }
+ index_scan_eof= TRUE;
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
}
}
scanning_key_val_iter= TRUE;
@@ -390,24 +377,21 @@ int Mrr_ordered_index_reader::get_next(char **range_info_arg)
/* Go get another (record, range_id) combination */
} /* while */
- memcpy(range_info_arg, cur_range_info, sizeof(void*));
+ memcpy(range_info, cur_range_info, sizeof(void*));
DBUG_RETURN(0);
}
/**
- DS-MRR/CPK: Fill the buffer with (lookup_tuple, range_id) pairs and sort
-
- Enumerate the input range (=key) sequence, fill the key buffer with
- (lookup_key, range_id) pairs and sort it.
-
- When this function returns, either
- - key buffer is non-empty, or
- - key buffer is empty and source range sequence is exhausted
-
+ Fill the buffer with (lookup_tuple, range_id) pairs and sort
+
@note
- dsmrr_eof is set to indicate whether we've exhausted the list of ranges
- we're scanning.
+ We don't know lookup_tuple before we get the first key from
+ mrr_funcs.get_next(). Not knowing tuple length means we can't setup the
+ key buffer (in particular, which part of the buffer space it should occupy
+ when we have both key and rowid buffers). This problem is solved by having
+ know_key_tuple_params variabe, and buf_manager, which we ask to set/reset
+ buffers for us.
*/
int Mrr_ordered_index_reader::refill_buffer()
@@ -427,23 +411,7 @@ int Mrr_ordered_index_reader::refill_buffer()
is_mrr_assoc? (uchar**)&range_info_ptr : NULL,
sizeof(uchar*));
}
-#if 0
- if (know_key_tuple_params)
- {
- if (do_rndpos_scan && rowid_buffer.is_empty())
- {
- /*
- We're using two buffers and both of them are empty now. Restore the
- original sizes
- */
- rowid_buffer.set_buffer_space(full_buf, rowid_buffer_end);
- key_buffer= &backward_key_buf;
- key_buffer->set_buffer_space(rowid_buffer_end, full_buf_end);
- }
- }
- is all of the ifdef-ed stuff is handled above?
-#endif
while ((!know_key_tuple_params || key_buffer->can_write()) &&
!(res= mrr_funcs.next(mrr_iter, &cur_range)))
{
@@ -478,7 +446,7 @@ int Mrr_ordered_index_reader::refill_buffer()
key_buffer->write();
}
- no_more_keys= test(res);
+ bool no_more_keys= test(res);
scanning_key_val_iter= FALSE;
index_scan_eof= FALSE;
@@ -522,15 +490,8 @@ int Mrr_ordered_rndpos_reader::init(handler *h_arg,
h= h_arg;
index_reader= index_reader_arg;
rowid_buffer= buf;
- is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
- //rowid_buff_elem_size= h->ref_length;
- //if (!(mode & HA_MRR_NO_ASSOCIATION))
- // rowid_buff_elem_size += sizeof(char*);
-
+ is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
index_reader_exhausted= FALSE;
- ///int res= index_reader->refill_buffer();
- ///if (res && res!=HA_ERR_END_OF_FILE)
- /// return res;
return 0;
}
@@ -553,7 +514,6 @@ int Mrr_ordered_rndpos_reader::init(handler *h_arg,
@retval other Error
*/
-
int Mrr_ordered_rndpos_reader::refill_buffer()
{
int res;
@@ -562,7 +522,7 @@ int Mrr_ordered_rndpos_reader::refill_buffer()
if (index_reader_exhausted)
DBUG_RETURN(HA_ERR_END_OF_FILE);
- while ((res= refill2() == HA_ERR_END_OF_FILE))
+ while ((res= refill_from_key_buffer() == HA_ERR_END_OF_FILE))
{
if ((res= index_reader->refill_buffer()))
{
@@ -575,13 +535,23 @@ int Mrr_ordered_rndpos_reader::refill_buffer()
}
-/* This one refills without calling index_reader->refill_buffer(). */
-int Mrr_ordered_rndpos_reader::refill2()
+void Mrr_index_reader::position()
+{
+ h->position(h->get_table()->record[0]);
+}
+
+
+/*
+ @brief Try to refill the rowid buffer without calling
+ index_reader->refill_buffer().
+*/
+
+int Mrr_ordered_rndpos_reader::refill_from_key_buffer()
{
char *range_info;
uchar **range_info_ptr= (uchar**)&range_info;
int res;
- DBUG_ENTER("Mrr_ordered_rndpos_reader::refill2");
+ DBUG_ENTER("Mrr_ordered_rndpos_reader::refill_from_key_buffer");
DBUG_ASSERT(rowid_buffer->is_empty());
index_rowid= index_reader->get_rowid_ptr();
@@ -600,7 +570,7 @@ int Mrr_ordered_rndpos_reader::refill2()
break;
/* Put rowid, or {rowid, range_id} pair into the buffer */
- index_reader->h->position(index_reader->h->get_table()->record[0]);
+ index_reader->position();
rowid_buffer->write();
}
@@ -615,10 +585,12 @@ int Mrr_ordered_rndpos_reader::refill2()
}
-/**
- DS-MRR implementation: multi_range_read_next() function.
+/*
+ Get the next record+range_id using ordered array of rowid+range_id pairds
- Calling convention is like multi_range_read_next() has.
+ @note
+ Since we have sorted rowids, we try not to make multiple rnd_pos() calls
+ with the same rowid value.
*/
int Mrr_ordered_rndpos_reader::get_next(char **range_info)
@@ -652,31 +624,6 @@ int Mrr_ordered_rndpos_reader::get_next(char **range_info)
while (1)
{
-#if 0
- if (rowid_buffer->is_empty()) /* We're out of rowids */
- {
- /* First, finish off the sorted keys we have */
- if (!index_reader->eof())
- {
- res= refill_buffer();
- if (res && res != HA_ERR_END_OF_FILE)
- return res;
- }
-
- if (rowid_buffer->is_empty())
- {
- /*
- Ok neither index_reader nor us have any records. Refill index
- reader, then refill us.
- */
- // TODO: if key buffer is empty, too, redistribute the buffer space.
- if ((res= index_reader->refill_buffer()) ||
- (res= refill_buffer()))
- return res;
- }
- }
-#endif
-
last_identical_rowid= NULL;
/* Return eof if there are no rowids in the buffer after re-fill attempt */
@@ -724,13 +671,8 @@ int Mrr_ordered_rndpos_reader::get_next(char **range_info)
}
-
-
-/************ MRR_impl classes end *********************************************/
-
-
/****************************************************************************
- * DS-MRR implementation
+ * Top-level DS-MRR implementation functions (the ones called by storage engine)
***************************************************************************/
/**
@@ -769,7 +711,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
if ((mode & HA_MRR_USE_DEFAULT_IMPL) || (mode & HA_MRR_SORTED))
{
DBUG_ASSERT(h->inited == handler::INDEX);
- Mrr_simple_index_reader *s= &strategy_factory.simple_index_reader;
+ Mrr_simple_index_reader *s= &reader_factory.simple_index_reader;
res= s->init(h, seq_funcs, seq_init_param, n_ranges, mode, this);
strategy= s;
DBUG_RETURN(res);
@@ -786,10 +728,10 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
if ((mode & HA_MRR_SINGLE_POINT) &&
optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_SORT_KEYS))
{
- index_strategy= ordered_idx_reader= &strategy_factory.ordered_index_reader;
+ index_strategy= ordered_idx_reader= &reader_factory.ordered_index_reader;
}
else
- index_strategy= &strategy_factory.simple_index_reader;
+ index_strategy= &reader_factory.simple_index_reader;
strategy= index_strategy;
/*
@@ -807,7 +749,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
Mrr_ordered_rndpos_reader *disk_strategy= NULL;
if (!(keyno == table->s->primary_key && h_idx->primary_key_is_clustered()))
{
- strategy= disk_strategy= &strategy_factory.ordered_rndpos_reader;
+ strategy= disk_strategy= &reader_factory.ordered_rndpos_reader;
}
if (is_mrr_assoc)
@@ -818,8 +760,6 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
if (strategy == index_strategy)
{
- ///if (ordered_idx_reader)
- // ordered_idx_reader->auto_refill= TRUE;
/* Index strategy serves it all. We don't need two handlers, etc */
/* Give the buffer to index strategy */
if ((res= index_strategy->init(h, seq_funcs, seq_init_param, n_ranges,
@@ -838,9 +778,6 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
if ((res= setup_two_handlers()))
DBUG_RETURN(res);
- ///if (ordered_idx_reader)
- /// ordered_idx_reader->auto_refill= FALSE;
-
if ((res= index_strategy->init(h2, seq_funcs, seq_init_param, n_ranges,
mode, this)) ||
(res= disk_strategy->init(h, index_strategy, mode, &rowid_buffer)))
@@ -960,8 +897,8 @@ int DsMrr_impl::setup_two_handlers()
goto error;
}
DBUG_RETURN(0);
+
error:
- //close_second_handler(); -- caller does that
DBUG_RETURN(res);
}
@@ -1132,6 +1069,7 @@ void DsMrr_impl::reset_buffer_sizes()
}
}
+
/**
Take unused space from the key buffer and give it to the rowid buffer
*/
@@ -1144,14 +1082,9 @@ void DsMrr_impl::reallocate_buffer_space()
}
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
bool Key_value_records_iterator::init(Mrr_ordered_index_reader *owner_arg)
{
int res;
- //h= h_arg;
- //param= param_arg;
owner= owner_arg;
identical_key_it.init(owner->key_buffer);