mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MWL#121: DS-MRR support for clustered primary keys
- Add testcases - Code cleanup: garbage removal, better comments, make members private where possible
This commit is contained in:
@ -139,8 +139,13 @@ ha_rows handler::multi_range_read_info(uint keyno, uint n_ranges, uint n_rows,
|
||||
uint key_parts, uint *bufsz,
|
||||
uint *flags, COST_VECT *cost)
|
||||
{
|
||||
/*
|
||||
Currently we expect this function to be called only in preparation of scan
|
||||
with HA_MRR_SINGLE_POINT property.
|
||||
*/
|
||||
DBUG_ASSERT(*flags | HA_MRR_SINGLE_POINT);
|
||||
|
||||
*bufsz= 0; /* Default implementation doesn't need a buffer */
|
||||
//psergey2-todo: assert for singlepoint ranges here?
|
||||
*flags |= HA_MRR_USE_DEFAULT_IMPL;
|
||||
|
||||
cost->zero();
|
||||
@ -323,22 +328,25 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
|
||||
n_ranges, key_parts, mode, buf);
|
||||
DBUG_RETURN(retval);
|
||||
}
|
||||
rowids_buf= buf->buffer;
|
||||
mrr_buf= buf->buffer;
|
||||
|
||||
is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
|
||||
|
||||
if (is_mrr_assoc)
|
||||
status_var_increment(table->in_use->status_var.ha_multi_range_read_init_count);
|
||||
|
||||
rowids_buf_end= buf->buffer_end;
|
||||
mrr_buf_end= buf->buffer_end;
|
||||
|
||||
|
||||
doing_cpk_scan= check_cpk_scan(h->active_index, mode);
|
||||
if (doing_cpk_scan)
|
||||
{
|
||||
/*
|
||||
When doing a scan on CPK, the buffer stores {lookup_tuple, range_id}
|
||||
pairs
|
||||
*/
|
||||
uint keylen=0;
|
||||
DBUG_ASSERT(key_parts != 0);
|
||||
//psergey2-todo: new elem_size here
|
||||
for (uint kp= 0; kp < key_parts; kp++)
|
||||
keylen += table->key_info[h->active_index].key_part[kp].store_length;
|
||||
|
||||
@ -350,12 +358,29 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
|
||||
use_default_impl= FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In regular DS-MRR, buffer stores {rowid, range_id} pairs */
|
||||
elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
|
||||
}
|
||||
|
||||
rowids_buf_last= rowids_buf +
|
||||
((rowids_buf_end - rowids_buf)/ elem_size)*
|
||||
mrr_buf_last= mrr_buf +
|
||||
((mrr_buf_end - mrr_buf)/ elem_size)*
|
||||
elem_size;
|
||||
rowids_buf_end= rowids_buf_last;
|
||||
mrr_buf_end= mrr_buf_last;
|
||||
|
||||
if (doing_cpk_scan)
|
||||
{
|
||||
/*
|
||||
DS-MRR/CPK: fill buffer with lookup tuples and sort; also we don't need a
|
||||
secondary handler object.
|
||||
*/
|
||||
h->mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
|
||||
h->mrr_funcs= *seq_funcs;
|
||||
dsmrr_fill_buffer_cpk();
|
||||
if (dsmrr_eof)
|
||||
buf->end_of_used_area= mrr_buf_last;
|
||||
DBUG_RETURN(0); /* nothing could go wrong while filling the buffer */
|
||||
}
|
||||
|
||||
/*
|
||||
There can be two cases:
|
||||
@ -365,84 +390,68 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
|
||||
The caller might have called h->index_init(), need to switch h to
|
||||
rnd_pos calls.
|
||||
*/
|
||||
//psergey2-todo: don't create secondary for CPK scan.
|
||||
if (!doing_cpk_scan)
|
||||
if (!h2)
|
||||
{
|
||||
if (!h2)
|
||||
/* Create a separate handler object to do rndpos() calls. */
|
||||
THD *thd= current_thd;
|
||||
/*
|
||||
::clone() takes up a lot of stack, especially on 64 bit platforms.
|
||||
The constant 5 is an empiric result.
|
||||
*/
|
||||
if (check_stack_overrun(thd, 5*STACK_MIN_SIZE, (uchar*) &new_h2))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_ASSERT(h->active_index != MAX_KEY);
|
||||
uint mrr_keyno= h->active_index;
|
||||
|
||||
/* Create a separate handler object to do rndpos() calls. */
|
||||
if (!(new_h2= h->clone(thd->mem_root)) ||
|
||||
new_h2->ha_external_lock(thd, F_RDLCK))
|
||||
{
|
||||
/* Create a separate handler object to do rndpos() calls. */
|
||||
THD *thd= current_thd;
|
||||
/*
|
||||
::clone() takes up a lot of stack, especially on 64 bit platforms.
|
||||
The constant 5 is an empiric result.
|
||||
*/
|
||||
if (check_stack_overrun(thd, 5*STACK_MIN_SIZE, (uchar*) &new_h2))
|
||||
DBUG_RETURN(1);
|
||||
DBUG_ASSERT(h->active_index != MAX_KEY);
|
||||
uint mrr_keyno= h->active_index;
|
||||
|
||||
/* Create a separate handler object to do rndpos() calls. */
|
||||
if (!(new_h2= h->clone(thd->mem_root)) ||
|
||||
new_h2->ha_external_lock(thd, F_RDLCK))
|
||||
{
|
||||
delete new_h2;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (mrr_keyno == h->pushed_idx_cond_keyno)
|
||||
pushed_cond= h->pushed_idx_cond;
|
||||
|
||||
/*
|
||||
Caution: this call will invoke this->dsmrr_close(). Do not put the
|
||||
created secondary table handler into this->h2 or it will delete it.
|
||||
*/
|
||||
if (h->ha_index_end())
|
||||
{
|
||||
h2=new_h2;
|
||||
goto error;
|
||||
}
|
||||
|
||||
h2= new_h2; /* Ok, now can put it into h2 */
|
||||
table->prepare_for_position();
|
||||
h2->extra(HA_EXTRA_KEYREAD);
|
||||
|
||||
if (h2->ha_index_init(mrr_keyno, FALSE))
|
||||
goto error;
|
||||
|
||||
use_default_impl= FALSE;
|
||||
if (pushed_cond)
|
||||
h2->idx_cond_push(mrr_keyno, pushed_cond);
|
||||
delete new_h2;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
else
|
||||
|
||||
if (mrr_keyno == h->pushed_idx_cond_keyno)
|
||||
pushed_cond= h->pushed_idx_cond;
|
||||
|
||||
/*
|
||||
Caution: this call will invoke this->dsmrr_close(). Do not put the
|
||||
created secondary table handler into this->h2 or it will delete it.
|
||||
*/
|
||||
if (h->ha_index_end())
|
||||
{
|
||||
/*
|
||||
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 save put it away and dont
|
||||
let it be deleted:
|
||||
*/
|
||||
handler *save_h2= h2;
|
||||
h2= NULL;
|
||||
int res= (h->inited == handler::INDEX && h->ha_index_end());
|
||||
h2= save_h2;
|
||||
use_default_impl= FALSE;
|
||||
if (res)
|
||||
goto error;
|
||||
h2=new_h2;
|
||||
goto error;
|
||||
}
|
||||
|
||||
h2= new_h2; /* Ok, now can put it into h2 */
|
||||
table->prepare_for_position();
|
||||
h2->extra(HA_EXTRA_KEYREAD);
|
||||
|
||||
if (h2->ha_index_init(mrr_keyno, FALSE))
|
||||
goto error;
|
||||
|
||||
use_default_impl= FALSE;
|
||||
if (pushed_cond)
|
||||
h2->idx_cond_push(mrr_keyno, pushed_cond);
|
||||
}
|
||||
else
|
||||
{
|
||||
//doing DS-MRR/CPK
|
||||
// fill-buffer-analog
|
||||
// eof
|
||||
h->mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
|
||||
h->mrr_funcs= *seq_funcs;
|
||||
dsmrr_fill_buffer_cpk();
|
||||
if (dsmrr_eof)
|
||||
buf->end_of_used_area= rowids_buf_last;
|
||||
DBUG_RETURN(0); // nothing can go wrong while filling the buffer
|
||||
/*
|
||||
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 save put it away and dont
|
||||
let it be deleted:
|
||||
*/
|
||||
handler *save_h2= h2;
|
||||
h2= NULL;
|
||||
int res= (h->inited == handler::INDEX && h->ha_index_end());
|
||||
h2= save_h2;
|
||||
use_default_impl= FALSE;
|
||||
if (res)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
|
||||
@ -456,7 +465,7 @@ int DsMrr_impl::dsmrr_init(handler *h_arg, RANGE_SEQ_IF *seq_funcs,
|
||||
adjust *buf to indicate that the remaining buffer space will not be used.
|
||||
*/
|
||||
if (dsmrr_eof)
|
||||
buf->end_of_used_area= rowids_buf_last;
|
||||
buf->end_of_used_area= mrr_buf_last;
|
||||
|
||||
/*
|
||||
h->inited == INDEX may occur when 'range checked for each record' is
|
||||
@ -512,6 +521,9 @@ static int rowid_cmp(void *h, uchar *a, uchar *b)
|
||||
rowid and return.
|
||||
|
||||
The function assumes that rowids buffer is empty when it is invoked.
|
||||
|
||||
dsmrr_eof is set to indicate whether we've exhausted the list of ranges we're
|
||||
scanning.
|
||||
|
||||
@param h Table handler
|
||||
|
||||
@ -526,8 +538,8 @@ int DsMrr_impl::dsmrr_fill_buffer()
|
||||
int res;
|
||||
DBUG_ENTER("DsMrr_impl::dsmrr_fill_buffer");
|
||||
|
||||
rowids_buf_cur= rowids_buf;
|
||||
while ((rowids_buf_cur < rowids_buf_end) &&
|
||||
mrr_buf_cur= mrr_buf;
|
||||
while ((mrr_buf_cur < mrr_buf_end) &&
|
||||
!(res= h2->handler::multi_range_read_next(&range_info)))
|
||||
{
|
||||
KEY_MULTI_RANGE *curr_range= &h2->handler::mrr_cur_range;
|
||||
@ -537,13 +549,13 @@ int DsMrr_impl::dsmrr_fill_buffer()
|
||||
|
||||
/* Put rowid, or {rowid, range_id} pair into the buffer */
|
||||
h2->position(table->record[0]);
|
||||
memcpy(rowids_buf_cur, h2->ref, h2->ref_length);
|
||||
rowids_buf_cur += h2->ref_length;
|
||||
memcpy(mrr_buf_cur, h2->ref, h2->ref_length);
|
||||
mrr_buf_cur += h2->ref_length;
|
||||
|
||||
if (is_mrr_assoc)
|
||||
{
|
||||
memcpy(rowids_buf_cur, &range_info, sizeof(void*));
|
||||
rowids_buf_cur += sizeof(void*);
|
||||
memcpy(mrr_buf_cur, &range_info, sizeof(void*));
|
||||
mrr_buf_cur += sizeof(void*);
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,27 +565,29 @@ int DsMrr_impl::dsmrr_fill_buffer()
|
||||
|
||||
/* Sort the buffer contents by rowid */
|
||||
uint elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
|
||||
uint n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
|
||||
uint n_rowids= (mrr_buf_cur - mrr_buf) / elem_size;
|
||||
|
||||
my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
|
||||
my_qsort2(mrr_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
|
||||
(void*)h);
|
||||
rowids_buf_last= rowids_buf_cur;
|
||||
rowids_buf_cur= rowids_buf;
|
||||
mrr_buf_last= mrr_buf_cur;
|
||||
mrr_buf_cur= mrr_buf;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/* qsort-compatible function to compare key tuples */
|
||||
/*
|
||||
my_qsort2-compatible function to compare key tuples
|
||||
*/
|
||||
|
||||
int DsMrr_impl::key_tuple_cmp(void* arg, uchar* key1, uchar* key2)
|
||||
{
|
||||
DsMrr_impl *dsmrr= (DsMrr_impl*)arg;
|
||||
TABLE *table= dsmrr->h->table;
|
||||
|
||||
KEY_PART_INFO *part= table->key_info[table->s->primary_key].key_part;
|
||||
KEY_PART_INFO *part_end= part + dsmrr->cpk_n_parts;
|
||||
uchar *key1_end= key1 + dsmrr->cpk_tuple_length;
|
||||
|
||||
//uint32 *lengths=item->field_lengths;
|
||||
for (; part < part_end; ++part)
|
||||
while (key1 < key1_end)
|
||||
{
|
||||
Field* f = part->field;
|
||||
int len = part->store_length;
|
||||
@ -582,33 +596,43 @@ int DsMrr_impl::key_tuple_cmp(void* arg, uchar* key1, uchar* key2)
|
||||
return res;
|
||||
key1 += len;
|
||||
key2 += len;
|
||||
part++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//psergey2:
|
||||
int DsMrr_impl::dsmrr_fill_buffer_cpk()
|
||||
/*
|
||||
DS-MRR/CPK: Fill the buffer with (lookup_tuple, range_id) pairs and sort
|
||||
|
||||
DESCRIPTION
|
||||
DS-MRR/CPK: Fill the buffer with (lookup_tuple, range_id) pairs and sort
|
||||
|
||||
dsmrr_eof is set to indicate whether we've exhausted the list of ranges
|
||||
we're scanning.
|
||||
*/
|
||||
|
||||
void DsMrr_impl::dsmrr_fill_buffer_cpk()
|
||||
{
|
||||
int res;
|
||||
KEY_MULTI_RANGE cur_range;
|
||||
DBUG_ENTER("DsMrr_impl::dsmrr_fill_buffer_cpk");
|
||||
|
||||
rowids_buf_cur= rowids_buf;
|
||||
while ((rowids_buf_cur < rowids_buf_end) &&
|
||||
mrr_buf_cur= mrr_buf;
|
||||
while ((mrr_buf_cur < mrr_buf_end) &&
|
||||
!(res= h->mrr_funcs.next(h->mrr_iter, &cur_range)))
|
||||
{
|
||||
DBUG_ASSERT(cur_range.range_flag & EQ_RANGE);
|
||||
DBUG_ASSERT(cpk_tuple_length == cur_range.start_key.length);
|
||||
|
||||
/* Put key, or {key, range_id} pair into the buffer */
|
||||
memcpy(rowids_buf_cur, cur_range.start_key.key, cpk_tuple_length);
|
||||
rowids_buf_cur += cpk_tuple_length;
|
||||
memcpy(mrr_buf_cur, cur_range.start_key.key, cpk_tuple_length);
|
||||
mrr_buf_cur += cpk_tuple_length;
|
||||
|
||||
if (is_mrr_assoc)
|
||||
{
|
||||
memcpy(rowids_buf_cur, &cur_range.ptr, sizeof(void*));
|
||||
rowids_buf_cur += sizeof(void*);
|
||||
memcpy(mrr_buf_cur, &cur_range.ptr, sizeof(void*));
|
||||
mrr_buf_cur += sizeof(void*);
|
||||
}
|
||||
}
|
||||
|
||||
@ -616,77 +640,82 @@ int DsMrr_impl::dsmrr_fill_buffer_cpk()
|
||||
|
||||
/* Sort the buffer contents by rowid */
|
||||
uint elem_size= cpk_tuple_length + (int)is_mrr_assoc * sizeof(void*);
|
||||
uint n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
|
||||
uint n_rowids= (mrr_buf_cur - mrr_buf) / elem_size;
|
||||
|
||||
my_qsort2(rowids_buf, n_rowids, elem_size,
|
||||
my_qsort2(mrr_buf, n_rowids, elem_size,
|
||||
(qsort2_cmp)DsMrr_impl::key_tuple_cmp, (void*)this);
|
||||
rowids_buf_last= rowids_buf_cur;
|
||||
rowids_buf_cur= rowids_buf;
|
||||
DBUG_RETURN(0);
|
||||
mrr_buf_last= mrr_buf_cur;
|
||||
mrr_buf_cur= mrr_buf;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
CPK: so, the source is
|
||||
- buffer exhaustion/re-fill
|
||||
- advance to next range on "record-not-found" error.
|
||||
- if scanning on a prefix, enumerate all records for a key.
|
||||
DS-MRR/CPK: multi_range_read_next() function
|
||||
|
||||
DESCRIPTION
|
||||
DsMrr_impl::dsmrr_next_cpk()
|
||||
|
||||
DESCRIPTION
|
||||
DS-MRR/CPK: multi_range_read_next() function.
|
||||
This is similar to DsMrr_impl::dsmrr_next(), the differences are that
|
||||
- we get records with index_read(), not with rnd_pos()
|
||||
- we may get multiple records for one key (=element of the buffer)
|
||||
- unlike dsmrr_fill_buffer(), dsmrr_fill_buffer_cpk() never fails.
|
||||
|
||||
RETURN
|
||||
0 OK, next record was successfully read
|
||||
HA_ERR_END_OF_FILE End of records
|
||||
Other Some other error
|
||||
*/
|
||||
|
||||
int DsMrr_impl::dsmrr_next_cpk(char **range_info)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (cpk_have_range)
|
||||
{
|
||||
res= h->index_next_same(table->record[0], rowids_buf_cur, cpk_tuple_length);
|
||||
res= h->index_next_same(table->record[0], mrr_buf_cur, cpk_tuple_length);
|
||||
if (res != HA_ERR_END_OF_FILE)
|
||||
{
|
||||
// todo
|
||||
if (is_mrr_assoc)
|
||||
memcpy(range_info, &cpk_saved_range_info, sizeof(void*));
|
||||
return res;
|
||||
}
|
||||
/*
|
||||
Ok, we got EOF for records in this range. Fall through to get to another
|
||||
range.
|
||||
*/
|
||||
/* No more records in this range. Fall through to get to another range */
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* First, make sure we have a range at start of the buffer*/
|
||||
if (rowids_buf_cur == rowids_buf_last)
|
||||
/* First, make sure we have a range at start of the buffer */
|
||||
if (mrr_buf_cur == mrr_buf_last)
|
||||
{
|
||||
if (dsmrr_eof)
|
||||
{
|
||||
res= HA_ERR_END_OF_FILE;
|
||||
goto end;
|
||||
}
|
||||
// TODO: the return values are mix of HA_ERR_ codes and TRUE as "generic
|
||||
// failure" error. Is this ok?
|
||||
if ((res= dsmrr_fill_buffer_cpk()))
|
||||
goto end;
|
||||
dsmrr_fill_buffer_cpk();
|
||||
}
|
||||
|
||||
if (rowids_buf_cur == rowids_buf_last)
|
||||
if (mrr_buf_cur == mrr_buf_last)
|
||||
{
|
||||
res= HA_ERR_END_OF_FILE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
//TODO: make skip_index_tuple() calls, too?
|
||||
//TODO: skip-record calls here?
|
||||
//psergey2-todo: make skip_index_tuple() calls, too?
|
||||
//psergey2-todo: skip-record calls here?
|
||||
//if (h2->mrr_funcs.skip_record &&
|
||||
// h2->mrr_funcs.skip_record(h2->mrr_iter, (char *) cur_range_info, rowid))
|
||||
// continue;
|
||||
|
||||
/* Ok, got the range. Try making a lookup. */
|
||||
uchar *lookup_tuple= rowids_buf_cur;
|
||||
rowids_buf_cur += cpk_tuple_length;
|
||||
uchar *lookup_tuple= mrr_buf_cur;
|
||||
mrr_buf_cur += cpk_tuple_length;
|
||||
if (is_mrr_assoc)
|
||||
{
|
||||
memcpy(cpk_saved_range_info, rowids_buf_cur, sizeof(void*));
|
||||
rowids_buf_cur += sizeof(void*) * test(is_mrr_assoc);
|
||||
memcpy(cpk_saved_range_info, mrr_buf_cur, sizeof(void*));
|
||||
mrr_buf_cur += sizeof(void*) * test(is_mrr_assoc);
|
||||
}
|
||||
|
||||
res= h->index_read(table->record[0], lookup_tuple, cpk_tuple_length,
|
||||
@ -698,6 +727,10 @@ int DsMrr_impl::dsmrr_next_cpk(char **range_info)
|
||||
if (!res)
|
||||
{
|
||||
memcpy(range_info, cpk_saved_range_info, sizeof(void*));
|
||||
/*
|
||||
Attempt reading more rows from this range only if there actually can
|
||||
be multiple matches:
|
||||
*/
|
||||
cpk_have_range= !cpk_is_unique_scan;
|
||||
break;
|
||||
}
|
||||
@ -707,6 +740,7 @@ end:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
DS-MRR implementation: multi_range_read_next() function
|
||||
*/
|
||||
@ -725,7 +759,7 @@ int DsMrr_impl::dsmrr_next(char **range_info)
|
||||
|
||||
do
|
||||
{
|
||||
if (rowids_buf_cur == rowids_buf_last)
|
||||
if (mrr_buf_cur == mrr_buf_last)
|
||||
{
|
||||
if (dsmrr_eof)
|
||||
{
|
||||
@ -738,17 +772,17 @@ int DsMrr_impl::dsmrr_next(char **range_info)
|
||||
}
|
||||
|
||||
/* return eof if there are no rowids in the buffer after re-fill attempt */
|
||||
if (rowids_buf_cur == rowids_buf_last)
|
||||
if (mrr_buf_cur == mrr_buf_last)
|
||||
{
|
||||
res= HA_ERR_END_OF_FILE;
|
||||
goto end;
|
||||
}
|
||||
rowid= rowids_buf_cur;
|
||||
rowid= mrr_buf_cur;
|
||||
|
||||
if (is_mrr_assoc)
|
||||
memcpy(&cur_range_info, rowids_buf_cur + h->ref_length, sizeof(uchar**));
|
||||
memcpy(&cur_range_info, mrr_buf_cur + h->ref_length, sizeof(uchar**));
|
||||
|
||||
rowids_buf_cur += h->ref_length + sizeof(void*) * test(is_mrr_assoc);
|
||||
mrr_buf_cur += h->ref_length + sizeof(void*) * test(is_mrr_assoc);
|
||||
if (h2->mrr_funcs.skip_record &&
|
||||
h2->mrr_funcs.skip_record(h2->mrr_iter, (char *) cur_range_info, rowid))
|
||||
continue;
|
||||
@ -870,7 +904,33 @@ bool key_uses_partial_cols(TABLE *table, uint keyno)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/*
|
||||
Check if key/flags allow DS-MRR/CPK strategy to be used
|
||||
|
||||
SYNOPSIS
|
||||
DsMrr_impl::check_cpk_scan()
|
||||
keyno Index that will be used
|
||||
mrr_flags
|
||||
|
||||
DESCRIPTION
|
||||
Check if key/flags allow DS-MRR/CPK strategy to be used.
|
||||
|
||||
RETURN
|
||||
TRUE DS-MRR/CPK should be used
|
||||
FALSE Otherwise
|
||||
*/
|
||||
|
||||
bool DsMrr_impl::check_cpk_scan(uint keyno, uint mrr_flags)
|
||||
{
|
||||
return test((mrr_flags & HA_MRR_SINGLE_POINT) &&
|
||||
!(mrr_flags & HA_MRR_SORTED) &&
|
||||
keyno == table->s->primary_key &&
|
||||
h->primary_key_is_clustered());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
DS-MRR Internals: Choose between Default MRR implementation and DS-MRR
|
||||
|
||||
Make the choice between using Default MRR implementation and DS-MRR.
|
||||
@ -892,13 +952,7 @@ bool key_uses_partial_cols(TABLE *table, uint keyno)
|
||||
@retval TRUE Default MRR implementation should be used
|
||||
@retval FALSE DS-MRR implementation should be used
|
||||
*/
|
||||
bool DsMrr_impl::check_cpk_scan(uint keyno, uint mrr_flags)
|
||||
{
|
||||
return test((mrr_flags & HA_MRR_SINGLE_POINT) &&
|
||||
!(mrr_flags & HA_MRR_SORTED) &&
|
||||
keyno == table->s->primary_key &&
|
||||
h->primary_key_is_clustered());
|
||||
}
|
||||
|
||||
|
||||
bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
|
||||
uint *bufsz, COST_VECT *cost)
|
||||
@ -906,9 +960,8 @@ bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
|
||||
COST_VECT dsmrr_cost;
|
||||
bool res;
|
||||
THD *thd= current_thd;
|
||||
//psergey2: check the criteria.
|
||||
doing_cpk_scan= check_cpk_scan(keyno, *flags);
|
||||
|
||||
doing_cpk_scan= check_cpk_scan(keyno, *flags);
|
||||
if (thd->variables.optimizer_use_mrr == 2 || *flags & HA_MRR_INDEX_ONLY ||
|
||||
(keyno == table->s->primary_key && h->primary_key_is_clustered() &&
|
||||
!doing_cpk_scan) ||
|
||||
|
Reference in New Issue
Block a user