Commit 1c7c67d5 authored by Sergey Petrunya's avatar Sergey Petrunya

MWL#121-125 DS-MRR improvements

- Address Monty's review feedback, part 6: rename "handler *h" variable in all
  DS-MRR classes to something else.
parent 799a1b16
......@@ -293,20 +293,20 @@ int Mrr_simple_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
Buffer_manager *buf_manager_arg)
{
HANDLER_BUFFER no_buffer = {NULL, NULL, NULL};
h= h_arg;
return h->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
mode, &no_buffer);
file= h_arg;
return file->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)
{
int res;
while (!(res= h->handler::multi_range_read_next(range_info)))
while (!(res= file->handler::multi_range_read_next(range_info)))
{
KEY_MULTI_RANGE *curr_range= &h->handler::mrr_cur_range;
if (!h->mrr_funcs.skip_index_tuple ||
!h->mrr_funcs.skip_index_tuple(h->mrr_iter, curr_range->ptr))
KEY_MULTI_RANGE *curr_range= &file->handler::mrr_cur_range;
if (!file->mrr_funcs.skip_index_tuple ||
!file->mrr_funcs.skip_index_tuple(file->mrr_iter, curr_range->ptr))
break;
}
return res;
......@@ -430,12 +430,12 @@ int Mrr_ordered_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
Lifo_buffer *key_buffer_arg,
Buffer_manager *buf_manager_arg)
{
h= h_arg;
file= h_arg;
key_buffer= key_buffer_arg;
buf_manager= buf_manager_arg;
keypar= *key_par_arg;
KEY *key_info= &h->get_table()->key_info[h->active_index];
KEY *key_info= &file->get_table()->key_info[file->active_index];
keypar.index_ranges_unique= test(key_info->flags & HA_NOSAME &&
key_info->key_parts ==
my_count_bits(keypar.key_tuple_map));
......@@ -456,8 +456,8 @@ int Mrr_ordered_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
case it will make an index lookup only for the first such element,
for subsequent elements it will only return the new range_id.
The problem here is that h->table->record[0] is shared with the part that
does full record retrieval with rnd_pos() calls, and if we have the
The problem here is that file->table->record[0] is shared with the part
that does full record retrieval with rnd_pos() calls, and if we have the
following scenario:
1. We scan ranges {(key_value, range_id1), (key_value, range_id2)}
......@@ -484,9 +484,9 @@ int Mrr_ordered_index_reader::init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
}
static int rowid_cmp_reverse(void *h, uchar *a, uchar *b)
static int rowid_cmp_reverse(void *file, uchar *a, uchar *b)
{
return - ((handler*)h)->cmp_ref(a, b);
return - ((handler*)file)->cmp_ref(a, b);
}
......@@ -495,7 +495,7 @@ int Mrr_ordered_rndpos_reader::init(handler *h_arg,
uint mode,
Lifo_buffer *buf)
{
h= h_arg;
file= h_arg;
index_reader= index_reader_arg;
rowid_buffer= buf;
is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
......@@ -546,7 +546,7 @@ int Mrr_ordered_rndpos_reader::refill_buffer(bool initial)
void Mrr_index_reader::position()
{
h->position(h->get_table()->record[0]);
file->position(file->get_table()->record[0]);
}
......@@ -565,7 +565,7 @@ int Mrr_ordered_rndpos_reader::refill_from_index_reader()
DBUG_ASSERT(rowid_buffer->is_empty());
index_rowid= index_reader->get_rowid_ptr();
rowid_buffer->reset();
rowid_buffer->setup_writing(&index_rowid, h->ref_length,
rowid_buffer->setup_writing(&index_rowid, file->ref_length,
is_mrr_assoc? (uchar**)&range_info_ptr: NULL,
sizeof(void*));
......@@ -590,9 +590,9 @@ int Mrr_ordered_rndpos_reader::refill_from_index_reader()
}
/* Sort the buffer contents by rowid */
rowid_buffer->sort((qsort2_cmp)rowid_cmp_reverse, (void*)h);
rowid_buffer->sort((qsort2_cmp)rowid_cmp_reverse, (void*)file);
rowid_buffer->setup_reading(&rowid, h->ref_length,
rowid_buffer->setup_reading(&rowid, file->ref_length,
is_mrr_assoc? (uchar**)&rowids_range_id: NULL,
sizeof(void*));
DBUG_RETURN(rowid_buffer->is_empty()? HA_ERR_END_OF_FILE : 0);
......@@ -653,7 +653,7 @@ int Mrr_ordered_rndpos_reader::get_next(char **range_info)
continue;
}
res= h->ha_rnd_pos(h->get_table()->record[0], rowid);
res= file->ha_rnd_pos(file->get_table()->record[0], rowid);
if (res == HA_ERR_RECORD_DELETED)
{
......@@ -681,7 +681,7 @@ int Mrr_ordered_rndpos_reader::get_next(char **range_info)
it.init(rowid_buffer);
while (!it.read()) // reads to (rowid, ...)
{
if (h->cmp_ref(rowid, cur_rowid))
if (file->cmp_ref(rowid, cur_rowid))
break;
last_identical_rowid= rowid;
}
......@@ -699,7 +699,7 @@ int Mrr_ordered_rndpos_reader::get_next(char **range_info)
Initialize and start the MRR scan. Depending on the mode parameter, this
may use default or DS-MRR implementation.
@param h Table handler to be used
@param h_arg Table handler to be used
@param key Index to be used
@param seq_funcs Interval sequence enumeration functions
@param seq_init_param Interval sequence enumeration parameter
......@@ -728,7 +728,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
index_merge may invoke a scan on an object for which dsmrr_info[_const]
has not been called, so set the owner handler here as well.
*/
h= h_arg;
primary_file= h_arg;
is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
strategy_exhausted= FALSE;
......@@ -760,11 +760,12 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
- We're doing a scan on clustered primary key
- [In the future] We're doing an index_only read
*/
DBUG_ASSERT(h->inited == handler::INDEX ||
(h->inited == handler::RND && h2 &&
h2->inited == handler::INDEX));
DBUG_ASSERT(primary_file->inited == handler::INDEX ||
(primary_file->inited == handler::RND &&
secondary_file &&
secondary_file->inited == handler::INDEX));
h_idx= (h->inited == handler::INDEX)? h: h2;
h_idx= (primary_file->inited == handler::INDEX)? primary_file: secondary_file;
keyno= h_idx->active_index;
if (!(keyno == table->s->primary_key && h_idx->primary_key_is_clustered()))
......@@ -805,7 +806,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
if (do_sort_keys && !key_buffer->have_space_for(key_buff_elem_size))
goto use_default_impl;
if ((res= index_strategy->init(h, seq_funcs, seq_init_param, n_ranges,
if ((res= index_strategy->init(primary_file, seq_funcs, seq_init_param, n_ranges,
mode, &keypar, key_buffer, &buf_manager)))
goto error;
}
......@@ -825,7 +826,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
{
/* index strategy doesn't need buffer, give all space to rowids*/
rowid_buffer.set_buffer_space(full_buf, full_buf_end);
if (!rowid_buffer.have_space_for(h->ref_length +
if (!rowid_buffer.have_space_for(primary_file->ref_length +
(int)is_mrr_assoc * sizeof(char*)))
goto use_default_impl;
}
......@@ -833,9 +834,11 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
if ((res= setup_two_handlers()))
goto error;
if ((res= index_strategy->init(h2, seq_funcs, seq_init_param, n_ranges,
mode, &keypar, key_buffer, &buf_manager)) ||
(res= disk_strategy->init(h, index_strategy, mode, &rowid_buffer)))
if ((res= index_strategy->init(secondary_file, seq_funcs, seq_init_param,
n_ranges, mode, &keypar, key_buffer,
&buf_manager)) ||
(res= disk_strategy->init(primary_file, index_strategy, mode,
&rowid_buffer)))
{
goto error;
}
......@@ -865,10 +868,11 @@ error:
DBUG_RETURN(1);
use_default_impl:
DBUG_ASSERT(h->inited == handler::INDEX);
DBUG_ASSERT(primary_file->inited == handler::INDEX);
/* Call correct init function and assign to top level object */
Mrr_simple_index_reader *s= &reader_factory.simple_index_reader;
res= s->init(h, seq_funcs, seq_init_param, n_ranges, mode, NULL, NULL, NULL);
res= s->init(primary_file, seq_funcs, seq_init_param, n_ranges, mode, NULL,
NULL, NULL);
strategy= s;
DBUG_RETURN(res);
}
......@@ -876,8 +880,8 @@ use_default_impl:
/*
Whatever the current state is, make it so that we have two handler objects:
- h (the primary) - initialized for rnd_pos() scan
- h2 (the secondary) - initialized for scanning the index specified in
- primary_file - initialized for rnd_pos() scan
- secondary_file - initialized for scanning the index specified in
this->keyno
RETURN
0 OK
......@@ -887,13 +891,13 @@ use_default_impl:
int DsMrr_impl::setup_two_handlers()
{
int res;
THD *thd= h->get_table()->in_use;
THD *thd= primary_file->get_table()->in_use;
DBUG_ENTER("DsMrr_impl::setup_two_handlers");
if (!h2)
if (!secondary_file)
{
handler *new_h2;
Item *pushed_cond= NULL;
DBUG_ASSERT(h->inited == handler::INDEX);
DBUG_ASSERT(primary_file->inited == handler::INDEX);
/* Create a separate handler object to do rnd_pos() calls. */
/*
::clone() takes up a lot of stack, especially on 64 bit platforms.
......@@ -903,65 +907,65 @@ int DsMrr_impl::setup_two_handlers()
DBUG_RETURN(1);
/* Create a separate handler object to do rnd_pos() calls. */
if (!(new_h2= h->clone(thd->mem_root)) ||
if (!(new_h2= primary_file->clone(thd->mem_root)) ||
new_h2->ha_external_lock(thd, F_RDLCK))
{
delete new_h2;
DBUG_RETURN(1);
}
if (keyno == h->pushed_idx_cond_keyno)
pushed_cond= h->pushed_idx_cond;
if (keyno == primary_file->pushed_idx_cond_keyno)
pushed_cond= primary_file->pushed_idx_cond;
Mrr_reader *save_strategy= strategy;
strategy= NULL;
/*
Caution: this call will invoke this->dsmrr_close(). Do not put the
created secondary table handler new_h2 into this->h2 or it will delete
it. Also, save the picked strategy
created secondary table handler new_h2 into this->secondary_file or it
will delete it. Also, save the picked strategy
*/
res= h->ha_index_end();
res= primary_file->ha_index_end();
strategy= save_strategy;
h2= new_h2; /* Ok, now can put it into h2 */
secondary_file= new_h2;
if (res || (res= (h->ha_rnd_init(FALSE))))
if (res || (res= (primary_file->ha_rnd_init(FALSE))))
goto error;
table->prepare_for_position();
h2->extra(HA_EXTRA_KEYREAD);
h2->mrr_iter= h->mrr_iter;
secondary_file->extra(HA_EXTRA_KEYREAD);
secondary_file->mrr_iter= primary_file->mrr_iter;
if ((res= h2->ha_index_init(keyno, FALSE)))
if ((res= secondary_file->ha_index_init(keyno, FALSE)))
goto error;
if (pushed_cond)
h2->idx_cond_push(keyno, pushed_cond);
secondary_file->idx_cond_push(keyno, pushed_cond);
}
else
{
DBUG_ASSERT(h2 && h2->inited==handler::INDEX);
DBUG_ASSERT(secondary_file && secondary_file->inited==handler::INDEX);
/*
We get here when the access alternates betwen MRR scan(s) and non-MRR
scans.
Calling h->index_end() will invoke dsmrr_close() for this object,
which will delete h2. We need to keep it, so put it away and dont
Calling primary_file->index_end() will invoke dsmrr_close() for this object,
which will delete secondary_file. We need to keep it, so put it away and dont
let it be deleted:
*/
if (h->inited == handler::INDEX)
if (primary_file->inited == handler::INDEX)
{
handler *save_h2= h2;
handler *save_h2= secondary_file;
Mrr_reader *save_strategy= strategy;
h2= NULL;
secondary_file= NULL;
strategy= NULL;
res= h->ha_index_end();
h2= save_h2;
res= primary_file->ha_index_end();
secondary_file= save_h2;
strategy= save_strategy;
if (res)
goto error;
}
if ((h->inited != handler::RND) && h->ha_rnd_init(FALSE))
if ((primary_file->inited != handler::RND) && primary_file->ha_rnd_init(FALSE))
goto error;
}
DBUG_RETURN(0);
......@@ -973,13 +977,13 @@ error:
void DsMrr_impl::close_second_handler()
{
if (h2)
if (secondary_file)
{
h2->ha_index_or_rnd_end();
h2->ha_external_lock(current_thd, F_UNLCK);
h2->close();
delete h2;
h2= NULL;
secondary_file->ha_index_or_rnd_end();
secondary_file->ha_external_lock(current_thd, F_UNLCK);
secondary_file->close();
delete secondary_file;
secondary_file= NULL;
}
}
......@@ -1000,8 +1004,8 @@ void DsMrr_impl::dsmrr_close()
int Mrr_ordered_index_reader::compare_keys(void* arg, uchar* key1, uchar* key2)
{
Mrr_ordered_index_reader *reader= (Mrr_ordered_index_reader*)arg;
TABLE *table= reader->h->get_table();
KEY_PART_INFO *part= table->key_info[reader->h->active_index].key_part;
TABLE *table= reader->file->get_table();
KEY_PART_INFO *part= table->key_info[reader->file->active_index].key_part;
if (reader->keypar.use_key_pointers)
{
......@@ -1038,12 +1042,12 @@ bool DsMrr_impl::setup_buffer_sharing(uint key_size_in_keybuf,
uint key_buff_elem_size= key_size_in_keybuf +
(int)is_mrr_assoc * sizeof(void*);
KEY *key_info= &h->get_table()->key_info[keyno];
KEY *key_info= &primary_file->get_table()->key_info[keyno];
/*
Ok if we got here we need to allocate one part of the buffer
for keys and another part for rowids.
*/
ulonglong rowid_buf_elem_size= h->ref_length +
ulonglong rowid_buf_elem_size= primary_file->ref_length +
(int)is_mrr_assoc * sizeof(char*);
/*
......@@ -1171,7 +1175,7 @@ int Key_value_records_iterator::init(Mrr_ordered_index_reader *owner_arg)
}
identical_key_it.init(owner->key_buffer);
cur_index_tuple= save_cur_index_tuple;
res= owner->h->ha_index_read_map(owner->h->get_table()->record[0],
res= owner->file->ha_index_read_map(owner->file->get_table()->record[0],
cur_index_tuple,
owner->keypar.key_tuple_map,
HA_READ_KEY_EXACT);
......@@ -1199,7 +1203,7 @@ int Key_value_records_iterator::get_next()
return HA_ERR_END_OF_FILE;
}
handler *h= owner->h;
handler *h= owner->file;
if ((res= h->ha_index_next_same(h->get_table()->record[0],
cur_index_tuple,
owner->keypar.key_tuple_length)))
......@@ -1265,8 +1269,9 @@ ha_rows DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows,
uint def_bufsz= *bufsz;
/* Get cost/flags/mem_usage of default MRR implementation */
res= h->handler::multi_range_read_info(keyno, n_ranges, rows, key_parts,
&def_bufsz, &def_flags, cost);
res= primary_file->handler::multi_range_read_info(keyno, n_ranges, rows,
key_parts, &def_bufsz,
&def_flags, cost);
DBUG_ASSERT(!res);
if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
......@@ -1298,9 +1303,11 @@ ha_rows DsMrr_impl::dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
uint def_flags= *flags;
uint def_bufsz= *bufsz;
/* Get cost/flags/mem_usage of default MRR implementation */
rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
n_ranges, &def_bufsz,
&def_flags, cost);
rows= primary_file->handler::multi_range_read_info_const(keyno, seq,
seq_init_param,
n_ranges,
&def_bufsz,
&def_flags, cost);
if (rows == HA_POS_ERROR)
{
/* Default implementation can't perform MRR scan => we can't either */
......@@ -1372,11 +1379,10 @@ bool key_uses_partial_cols(TABLE *table, uint keyno)
bool DsMrr_impl::check_cpk_scan(THD *thd, uint keyno, uint mrr_flags)
{
return test((mrr_flags & HA_MRR_SINGLE_POINT) && // check
// !(mrr_flags & HA_MRR_SORTED) &&
return test((mrr_flags & HA_MRR_SINGLE_POINT) &&
keyno == table->s->primary_key &&
h->primary_key_is_clustered() &&
optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_SORT_KEYS)); //check
primary_file->primary_key_is_clustered() &&
optimizer_flag(thd, OPTIMIZER_SWITCH_MRR_SORT_KEYS));
}
......@@ -1413,7 +1419,7 @@ bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
bool doing_cpk_scan= check_cpk_scan(thd, keyno, *flags);
bool using_cpk= test(keyno == table->s->primary_key &&
h->primary_key_is_clustered());
primary_file->primary_key_is_clustered());
if (thd->variables.optimizer_use_mrr == 2 || *flags & HA_MRR_INDEX_ONLY ||
(using_cpk && !doing_cpk_scan) || key_uses_partial_cols(table, keyno))
{
......@@ -1422,7 +1428,7 @@ bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
return TRUE;
}
uint add_len= table->key_info[keyno].key_length + h->ref_length;
uint add_len= table->key_info[keyno].key_length + primary_file->ref_length;
*bufsz -= add_len;
if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
return TRUE;
......@@ -1484,7 +1490,8 @@ bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
uint n_full_steps;
double index_read_cost;
elem_size= h->ref_length + sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
elem_size= primary_file->ref_length +
sizeof(void*) * (!test(flags & HA_MRR_NO_ASSOCIATION));
max_buff_entries = *buffer_size / elem_size;
if (!max_buff_entries)
......@@ -1512,7 +1519,7 @@ bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
cost->zero();
*buffer_size= max(*buffer_size,
(size_t)(1.2*rows_in_last_step) * elem_size +
h->ref_length + table->key_info[keynr].key_length);
primary_file->ref_length + table->key_info[keynr].key_length);
}
COST_VECT last_step_cost;
......@@ -1525,7 +1532,7 @@ bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
cost->mem_cost= (double)rows_in_last_step * elem_size;
/* Total cost of all index accesses */
index_read_cost= h->keyread_time(keynr, 1, (double)rows);
index_read_cost= primary_file->keyread_time(keynr, 1, (double)rows);
cost->add_io(index_read_cost, 1 /* Random seeks */);
return FALSE;
}
......
......@@ -129,7 +129,7 @@ class Key_value_records_iterator
/*
FALSE <=> we're right after the init() call, the record has been already
read with owner->h->index_read_map() call
read with owner->file->index_read_map() call
*/
bool get_next_row;
......@@ -200,7 +200,7 @@ public:
class Mrr_index_reader : public Mrr_reader
{
protected:
handler *h; /* Handler object to use */
handler *file; /* Handler object to use */
public:
virtual int init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
void *seq_init_param, uint n_ranges,
......@@ -232,11 +232,11 @@ public:
Buffer_manager *buf_manager_arg);
int get_next(char **range_info);
int refill_buffer(bool initial) { return initial? 0: HA_ERR_END_OF_FILE; }
uchar *get_rowid_ptr() { return h->ref; }
uchar *get_rowid_ptr() { return file->ref; }
bool skip_record(char *range_id, uchar *rowid)
{
return (h->mrr_funcs.skip_record &&
h->mrr_funcs.skip_record(h->mrr_iter, range_id, rowid));
return (file->mrr_funcs.skip_record &&
file->mrr_funcs.skip_record(file->mrr_iter, range_id, rowid));
}
};
......@@ -255,7 +255,7 @@ public:
Buffer_manager *buf_manager_arg);
int get_next(char **range_info);
int refill_buffer(bool initial);
uchar *get_rowid_ptr() { return h->ref; }
uchar *get_rowid_ptr() { return file->ref; }
bool skip_record(char *range_info, uchar *rowid)
{
......@@ -318,12 +318,12 @@ private:
class Mrr_ordered_rndpos_reader : public Mrr_reader
{
public:
int init(handler *h, Mrr_index_reader *index_reader, uint mode,
int init(handler *file, Mrr_index_reader *index_reader, uint mode,
Lifo_buffer *buf);
int get_next(char **range_info);
int refill_buffer(bool initial);
private:
handler *h; /* Handler to use */
handler *file; /* Handler to use */
/* This what we get (rowid, range_info) pairs from */
Mrr_index_reader *index_reader;
......@@ -503,15 +503,16 @@ public:
typedef void (handler::*range_check_toggle_func_t)(bool on);
DsMrr_impl()
: h2(NULL) {};
: secondary_file(NULL) {};
void init(handler *h_arg, TABLE *table_arg)
{
h= h_arg;
primary_file= h_arg;
table= table_arg;
}
int dsmrr_init(handler *h, RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
uint n_ranges, uint mode, HANDLER_BUFFER *buf);
int dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
void *seq_init_param, uint n_ranges, uint mode,
HANDLER_BUFFER *buf);
void dsmrr_close();
int dsmrr_next(char **range_info);
......@@ -529,14 +530,14 @@ private:
The "owner" handler object (the one that is expected to "own" this object
and call its functions).
*/
handler *h;
TABLE *table; /* Always equal to h->table */
handler *primary_file;
TABLE *table; /* Always equal to primary_file->table */
/*
Secondary handler object. (created when needed, we need it when we need
to run both index scan and rnd_pos() scan at the same time)
*/
handler *h2;
handler *secondary_file;
uint keyno; /* index we're running the scan on */
/* TRUE <=> need range association, buffers hold {rowid, range_id} pairs */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment