Commit 9dda3a70 authored by sergefp@mysql.com's avatar sergefp@mysql.com

Merge

parents 9a7a47c2 fb0845f8
......@@ -725,7 +725,7 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
key_part_info= head->key_info[index].key_part;
my_init_dynamic_array(&ranges, sizeof(QUICK_RANGE*), 16, 16);
/* 'thd' is not accessible in QUICK_RANGE_SELECT::get_next_init(). */
/* 'thd' is not accessible in QUICK_RANGE_SELECT::reset(). */
multi_range_bufsiz= thd->variables.read_rnd_buff_size;
multi_range_count= thd->variables.multi_range_count;
multi_range_length= 0;
......@@ -749,9 +749,6 @@ int QUICK_RANGE_SELECT::init()
{
DBUG_ENTER("QUICK_RANGE_SELECT::init");
if ((error= get_next_init()))
DBUG_RETURN(error);
if (file->inited == handler::NONE)
DBUG_RETURN(error= file->ha_index_init(index));
error= 0;
......@@ -5655,9 +5652,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
We reuse the same instance of handler so we need to call both init and
reset here.
*/
if (cur_quick->init())
if (cur_quick->init() || cur_quick->reset())
DBUG_RETURN(1);
cur_quick->reset();
unique= new Unique(refpos_order_cmp, (void *)head->file,
head->file->ref_length,
......@@ -5675,10 +5671,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
if (cur_quick->file->inited != handler::NONE)
cur_quick->file->ha_index_end();
if (cur_quick->init())
if (cur_quick->init() || cur_quick->reset())
DBUG_RETURN(1);
/* QUICK_RANGE_SELECT::reset never fails */
cur_quick->reset();
}
if (result)
......@@ -5745,9 +5739,8 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
if (pk_quick_select)
{
doing_pk_scan= TRUE;
if ((result= pk_quick_select->init()))
if ((result= pk_quick_select->init()) || (result= pk_quick_select->reset()))
DBUG_RETURN(result);
pk_quick_select->reset();
DBUG_RETURN(pk_quick_select->get_next());
}
}
......@@ -5908,28 +5901,15 @@ int QUICK_ROR_UNION_SELECT::get_next()
DBUG_RETURN(error);
}
/*
Initialize data structures needed by get_next().
SYNOPSIS
QUICK_RANGE_SELECT::get_next_init()
DESCRIPTION
This is called from get_next() at its first call for an object.
It allocates memory buffers and sets size variables.
RETURN
0 OK.
!= 0 Error.
*/
int QUICK_RANGE_SELECT::get_next_init(void)
int QUICK_RANGE_SELECT::reset()
{
uint mrange_bufsiz;
byte *mrange_buff;
DBUG_ENTER("QUICK_RANGE_SELECT::get_next_init");
DBUG_ENTER("QUICK_RANGE_SELECT::reset");
next=0;
range= NULL;
cur_range= (QUICK_RANGE**) ranges.buffer;
/* Do not allocate the buffers twice. */
if (multi_range_length)
{
......@@ -5937,15 +5917,8 @@ int QUICK_RANGE_SELECT::get_next_init(void)
DBUG_RETURN(0);
}
/* If the ranges are not yet initialized, wait for the next call. */
if (! ranges.elements)
{
DBUG_RETURN(0);
}
/*
Allocate the ranges array.
*/
/* Allocate the ranges array. */
DBUG_ASSERT(ranges.elements);
multi_range_length= min(multi_range_count, ranges.elements);
DBUG_ASSERT(multi_range_length > 0);
while (multi_range_length && ! (multi_range= (KEY_MULTI_RANGE*)
......@@ -5962,9 +5935,7 @@ int QUICK_RANGE_SELECT::get_next_init(void)
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
}
/*
Allocate the handler buffer if necessary.
*/
/* Allocate the handler buffer if necessary. */
if (file->table_flags() & HA_NEED_READ_RANGE_BUFFER)
{
mrange_bufsiz= min(multi_range_bufsiz,
......@@ -5992,9 +5963,6 @@ int QUICK_RANGE_SELECT::get_next_init(void)
multi_range_buff->buffer_end= mrange_buff + mrange_bufsiz;
multi_range_buff->end_of_used_area= mrange_buff;
}
/* Initialize the current QUICK_RANGE pointer. */
cur_range= (QUICK_RANGE**) ranges.buffer;
DBUG_RETURN(0);
}
......@@ -7948,10 +7916,10 @@ int QUICK_GROUP_MIN_MAX_SELECT::reset(void)
file->extra(HA_EXTRA_KEYREAD); /* We need only the key attributes */
result= file->ha_index_init(index);
result= file->index_last(record);
if (quick_prefix_select)
quick_prefix_select->reset();
if (result)
DBUG_RETURN(result);
if (quick_prefix_select && quick_prefix_select->reset())
DBUG_RETURN(1);
/* Save the prefix of the last group. */
key_copy(last_prefix, record, index_info, group_prefix_len);
......
......@@ -59,6 +59,44 @@ class QUICK_RANGE :public Sql_alloc {
/*
Quick select interface.
This class is a parent for all QUICK_*_SELECT and FT_SELECT classes.
The usage scenario is as follows:
1. Create quick select
quick= new QUICK_XXX_SELECT(...);
2. Perform lightweight initialization. This can be done in 2 ways:
2.a: Regular initialization
if (quick->init())
{
//the only valid action after failed init() call is delete
delete quick;
}
2.b: Special initialization for quick selects merged by QUICK_ROR_*_SELECT
if (quick->init_ror_merged_scan())
delete quick;
3. Perform zero, one, or more scans.
while (...)
{
// initialize quick select for scan. This may allocate
// buffers and/or prefetch rows.
if (quick->reset())
{
//the only valid action after failed reset() call is delete
delete quick;
//abort query
}
// perform the scan
do
{
res= quick->get_next();
} while (res && ...)
}
4. Delete the select:
delete quick;
*/
class QUICK_SELECT_I
......@@ -117,27 +155,16 @@ public:
reset() should be called when it is certain that row retrieval will be
necessary. This call may do heavyweight initialization like buffering first
N records etc. If reset() call fails get_next() must not be called.
Note that reset() may be called several times if this quick select
executes in a subselect.
Note that reset() may be called several times if
* the quick select is executed in a subselect
* a JOIN buffer is used
RETURN
0 OK
other Error code
*/
virtual int reset(void) = 0;
/*
Initialize get_next() for row retrieval.
SYNOPSIS
get_next_init()
get_next_init() must be called before the first get_next().
If get_next_init() call fails get_next() must not be called.
RETURN
0 OK
other Error code
*/
virtual int get_next_init() { return false; }
virtual int get_next() = 0; /* get next record to retrieve */
/* Range end should be called when we have looped over the whole index */
......@@ -284,18 +311,7 @@ public:
~QUICK_RANGE_SELECT();
int init();
int reset(void)
{
next=0;
range= NULL;
cur_range= (QUICK_RANGE**) ranges.buffer;
/*
Note: in opt_range.cc there are places where it is assumed that this
function always succeeds
*/
return 0;
}
int get_next_init(void);
int reset(void);
int get_next();
void range_end();
int get_next_prefix(uint prefix_length, byte *cur_prefix);
......@@ -310,6 +326,8 @@ public:
#ifndef DBUG_OFF
void dbug_dump(int indent, bool verbose);
#endif
private:
/* Used only by QUICK_SELECT_DESC */
QUICK_RANGE_SELECT(const QUICK_RANGE_SELECT& org) : QUICK_SELECT_I()
{
bcopy(&org, this, sizeof(*this));
......@@ -685,6 +703,7 @@ public:
QUICK_RANGE_SELECT (thd, table, key, 1) { init(); }
~FT_SELECT() { file->ft_end(); }
int init() { return error=file->ft_init(); }
int reset() { return 0; }
int get_next() { return error=file->ft_read(record); }
int get_type() { return QS_TYPE_FULLTEXT; }
};
......
......@@ -100,19 +100,8 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
}
else if (select && select->quick)
{
int error;
DBUG_PRINT("info",("using rr_quick"));
if (!table->file->inited)
table->file->ha_index_init(select->quick->index);
info->read_record=rr_quick;
if ((error= select->quick->get_next_init()))
{
/* Cannot return error code here. Instead print to error log. */
table->file->print_error(error,MYF(ME_NOREFRESH));
thd->fatal_error();
}
}
else if (table->sort.record_pointers)
{
......
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