Loading sql/opt_range.cc +15 −47 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading @@ -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) Loading Loading @@ -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()); } } Loading Loading @@ -5908,27 +5901,14 @@ 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) Loading @@ -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*) Loading @@ -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, Loading Loading @@ -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); } Loading Loading @@ -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); Loading sql/opt_range.h +46 −27 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -117,27 +155,16 @@ class QUICK_SELECT_I 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 */ Loading Loading @@ -284,18 +311,7 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I ~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); Loading @@ -310,6 +326,8 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I #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)); Loading Loading @@ -685,6 +703,7 @@ class FT_SELECT: public QUICK_RANGE_SELECT { 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; } }; Loading sql/records.cc +0 −11 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading
sql/opt_range.cc +15 −47 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading @@ -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) Loading Loading @@ -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()); } } Loading Loading @@ -5908,27 +5901,14 @@ 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) Loading @@ -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*) Loading @@ -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, Loading Loading @@ -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); } Loading Loading @@ -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); Loading
sql/opt_range.h +46 −27 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -117,27 +155,16 @@ class QUICK_SELECT_I 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 */ Loading Loading @@ -284,18 +311,7 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I ~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); Loading @@ -310,6 +326,8 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I #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)); Loading Loading @@ -685,6 +703,7 @@ class FT_SELECT: public QUICK_RANGE_SELECT { 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; } }; Loading
sql/records.cc +0 −11 Original line number Diff line number Diff line Loading @@ -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) { Loading