diff options
author | unknown <ingo@mysql.com> | 2004-12-23 21:45:10 +0100 |
---|---|---|
committer | unknown <ingo@mysql.com> | 2004-12-23 21:45:10 +0100 |
commit | 8d11c01c595261c9c742356c0152c2152b847db9 (patch) | |
tree | 2278239c23c9cfa8abc2cfb833b598df01227ee8 | |
parent | dd6981f4d01072cbc5fa898bd6c42b54ffbb0fcf (diff) | |
download | mariadb-git-8d11c01c595261c9c742356c0152c2152b847db9.tar.gz |
WL#2126 - Multi_read_range.
Added the required structures and functions for
handing over multiple key ranges to the table handler.
include/my_base.h:
WL#2126 - Multi_read_range.
Moved key range flags from sql/opt_range.h to here.
Added the multi-range structure.
sql/handler.cc:
WL#2126 - Multi_read_range.
Added the new table handler methods.
sql/handler.h:
WL#2126 - Multi_read_range.
Added a new table flag.
Added a declaration for the handler buffer.
Added new elements to class handler.
Added new function declarations.
sql/mysqld.cc:
WL#2126 - Multi_read_range.
Added an option to set new system variable 'multi_range_count'.
sql/opt_range.cc:
WL#2126 - Multi_read_range.
Added initialization for the new class members.
Added initialization for the extended get_next().
Added de-initialization for the allocated buffers.
Added a buffer allocation method.
Added an inner loop to collect multiple ranges.
Adapted range collection loops to the new initialization.
sql/opt_range.h:
WL#2126 - Multi_read_range.
Moved key range flags from here to include/my_base.h.
Added new elements to class QUICK_RANGE_SELECT.
Added a copy constructor.
sql/records.cc:
WL#2126 - Multi_read_range.
Added a call of the allocation method.
sql/set_var.cc:
WL#2126 - Multi_read_range.
Added the new system variable 'multi_range_count'.
sql/sql_class.h:
WL#2126 - Multi_read_range.
Added the new system variable 'multi_range_count'.
-rw-r--r-- | include/my_base.h | 17 | ||||
-rw-r--r-- | sql/handler.cc | 125 | ||||
-rw-r--r-- | sql/handler.h | 26 | ||||
-rw-r--r-- | sql/mysqld.cc | 7 | ||||
-rw-r--r-- | sql/opt_range.cc | 243 | ||||
-rw-r--r-- | sql/opt_range.h | 47 | ||||
-rw-r--r-- | sql/records.cc | 8 | ||||
-rw-r--r-- | sql/set_var.cc | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 1 |
9 files changed, 407 insertions, 69 deletions
diff --git a/include/my_base.h b/include/my_base.h index 4d043cf6b5b..d219cdd4289 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -370,6 +370,15 @@ enum data_file_type { /* For key ranges */ +#define NO_MIN_RANGE 1 +#define NO_MAX_RANGE 2 +#define NEAR_MIN 4 +#define NEAR_MAX 8 +#define UNIQUE_RANGE 16 +#define EQ_RANGE 32 +#define NULL_RANGE 64 +#define GEOM_FLAG 128 + typedef struct st_key_range { const byte *key; @@ -377,6 +386,14 @@ typedef struct st_key_range enum ha_rkey_function flag; } key_range; +typedef struct st_key_multi_range +{ + key_range start_key; + key_range end_key; + char *ptr; /* Free to use by caller (ptr to row etc) */ + uint range_flag; /* key range flags see above */ +} KEY_MULTI_RANGE; + /* For number of records */ #ifdef BIG_TABLES diff --git a/sql/handler.cc b/sql/handler.cc index e43f2c2e888..87a66dc54b5 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1686,6 +1686,131 @@ int ha_table_exists(THD* thd, const char* db, const char* name) /* + Read the first row of a multi-range set. + + SYNOPSIS + read_multi_range_first() + found_range_p Returns a pointer to the element in 'ranges' that + corresponds to the returned row. + ranges An array of KEY_MULTI_RANGE range descriptions. + range_count Number of ranges in 'ranges'. + sorted If result should be sorted per key. + buffer A HANDLER_BUFFER for internal handler usage. + + NOTES + Record is read into table->record[0]. + *found_range_p returns a valid value only if read_multi_range_first() + returns 0. + Sorting is done within each range. If you want an overall sort, enter + 'ranges' with sorted ranges. + + RETURN + 0 OK, found a row + HA_ERR_END_OF_FILE No rows in range + # Error code +*/ + +int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, + KEY_MULTI_RANGE *ranges, uint range_count, + bool sorted, HANDLER_BUFFER *buffer) +{ + int result= HA_ERR_END_OF_FILE; + DBUG_ENTER("handler::read_multi_range_first"); + multi_range_sorted= sorted; + multi_range_buffer= buffer; + + for (multi_range_curr= ranges, multi_range_end= ranges + range_count; + multi_range_curr < multi_range_end; + multi_range_curr++) + { + result= read_range_first(multi_range_curr->start_key.length ? + &multi_range_curr->start_key : 0, + multi_range_curr->end_key.length ? + &multi_range_curr->end_key : 0, + test(multi_range_curr->range_flag & EQ_RANGE), + multi_range_sorted); + if (result != HA_ERR_END_OF_FILE) + break; + } + + *found_range_p= multi_range_curr; + DBUG_PRINT("exit",("result %d", result)); + DBUG_RETURN(result); +} + + +/* + Read the next row of a multi-range set. + + SYNOPSIS + read_multi_range_next() + found_range_p Returns a pointer to the element in 'ranges' that + corresponds to the returned row. + + NOTES + Record is read into table->record[0]. + *found_range_p returns a valid value only if read_multi_range_next() + returns 0. + + RETURN + 0 OK, found a row + HA_ERR_END_OF_FILE No (more) rows in range + # Error code +*/ + +int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p) +{ + int result; + DBUG_ENTER("handler::read_multi_range_next"); + + /* We should not be called after the last call returned EOF. */ + DBUG_ASSERT(multi_range_curr < multi_range_end); + + do + { + /* Save a call if there can be only one row in range. */ + if (multi_range_curr->range_flag != (UNIQUE_RANGE | EQ_RANGE)) + { + result= read_range_next(); + + /* On success or non-EOF errors jump to the end. */ + if (result != HA_ERR_END_OF_FILE) + break; + } + else + { + /* + We need to set this for the last range only, but checking this + condition is more expensive than just setting the result code. + */ + result= HA_ERR_END_OF_FILE; + } + + /* Try the next range(s) until one matches a record. */ + for (multi_range_curr++; + multi_range_curr < multi_range_end; + multi_range_curr++) + { + result= read_range_first(multi_range_curr->start_key.length ? + &multi_range_curr->start_key : 0, + multi_range_curr->end_key.length ? + &multi_range_curr->end_key : 0, + test(multi_range_curr->range_flag & EQ_RANGE), + multi_range_sorted); + if (result != HA_ERR_END_OF_FILE) + break; + } + } + while ((result == HA_ERR_END_OF_FILE) && + (multi_range_curr < multi_range_end)); + + *found_range_p= multi_range_curr; + DBUG_PRINT("exit",("handler::read_multi_range_next: result %d", result)); + DBUG_RETURN(result); +} + + +/* Read first row between two ranges. Store ranges for future calls to read_range_next diff --git a/sql/handler.h b/sql/handler.h index f0faeff9234..62638ee456b 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -76,6 +76,7 @@ #define HA_FILE_BASED (1 << 26) #define HA_NO_VARCHAR (1 << 27) #define HA_CAN_BIT_FIELD (1 << 28) /* supports bit fields */ +#define HA_NEED_READ_RANGE_BUFFER (1 << 29) /* for read_multi_range */ /* bits in index_flags(index_number) for what you can do with index */ @@ -276,6 +277,21 @@ typedef struct st_ha_check_opt } HA_CHECK_OPT; +/* + This is a buffer area that the handler can use to store rows. + 'end_of_used_area' should be kept updated after calls to + read-functions so that other parts of the code can use the + remaining area (until next read calls is issued). +*/ + +typedef struct st_handler_buffer +{ + const byte *buffer; /* Buffer one can start using */ + const byte *buffer_end; /* End of buffer */ + byte *end_of_used_area; /* End of area that was used by handler */ +} HANDLER_BUFFER; + + class handler :public Sql_alloc { protected: @@ -310,6 +326,12 @@ public: time_t check_time; time_t update_time; + /* The following are for read_multi_range */ + bool multi_range_sorted; + KEY_MULTI_RANGE *multi_range_curr; + KEY_MULTI_RANGE *multi_range_end; + HANDLER_BUFFER *multi_range_buffer; + /* The following are for read_range() */ key_range save_end_range, *end_range; KEY_PART_INFO *range_key_part; @@ -421,6 +443,10 @@ public: virtual int index_next_same(byte *buf, const byte *key, uint keylen); virtual int index_read_last(byte * buf, const byte * key, uint key_len) { return (my_errno=HA_ERR_WRONG_COMMAND); } + virtual int read_multi_range_first(KEY_MULTI_RANGE **found_range_p, + KEY_MULTI_RANGE *ranges, uint range_count, + bool sorted, HANDLER_BUFFER *buffer); + virtual int read_multi_range_next(KEY_MULTI_RANGE **found_range_p); virtual int read_range_first(const key_range *start_key, const key_range *end_key, bool eq_range, bool sorted); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8eec97efd81..34b1fbcd364 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4141,7 +4141,7 @@ enum options_mysqld OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS, OPT_MAX_LENGTH_FOR_SORT_DATA, OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE, - OPT_MAX_ERROR_COUNT, OPT_MYISAM_DATA_POINTER_SIZE, + OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE, OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE, OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT, @@ -5137,6 +5137,11 @@ The minimum value for this variable is 4096.", "After this many write locks, allow some read locks to run in between.", (gptr*) &max_write_lock_count, (gptr*) &max_write_lock_count, 0, GET_ULONG, REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0}, + {"multi_range_count", OPT_MULTI_RANGE_COUNT, + "Number of key ranges to request at once.", + (gptr*) &global_system_variables.multi_range_count, + (gptr*) &max_system_variables.multi_range_count, 0, + GET_ULONG, REQUIRED_ARG, 256, 1, ~0L, 0, 1, 0}, {"myisam_block_size", OPT_MYISAM_BLOCK_SIZE, "Block size to be used for MyISAM index pages.", (gptr*) &opt_myisam_block_size, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index e47c7e147a7..e7f03b51fc0 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -712,7 +712,7 @@ QUICK_SELECT_I::QUICK_SELECT_I() QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc, MEM_ROOT *parent_alloc) - :dont_free(0),error(0),free_file(0),cur_range(NULL),range(0) + :dont_free(0),error(0),free_file(0),cur_range(NULL),range(0),in_range(0) { sorted= 0; index= key_nr; @@ -720,6 +720,13 @@ 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(). */ + multi_range_bufsiz= thd->variables.read_rnd_buff_size; + multi_range_count= thd->variables.multi_range_count; + multi_range_length= 0; + multi_range= NULL; + multi_range_buff= NULL; + if (!no_alloc && !parent_alloc) { // Allocates everything through the internal memroot @@ -736,6 +743,10 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr, 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; @@ -771,6 +782,10 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT() delete_dynamic(&ranges); /* ranges are allocated in alloc */ free_root(&alloc,MYF(0)); } + if (multi_range) + my_free((char*) multi_range, MYF(0)); + if (multi_range_buff) + my_free((char*) multi_range_buff, MYF(0)); DBUG_VOID_RETURN; } @@ -5872,58 +5887,178 @@ int QUICK_ROR_UNION_SELECT::get_next() DBUG_RETURN(error); } - /* get next possible record using quick-struct */ + +/* + 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) +{ + uint mrange_bufsiz; + byte *mrange_buff; + DBUG_ENTER("QUICK_RANGE_SELECT::get_next_init"); + + /* Do not allocate the buffers twice. */ + if (multi_range_length) + { + DBUG_ASSERT(multi_range_length == min(multi_range_count, ranges.elements)); + 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. + */ + multi_range_length= min(multi_range_count, ranges.elements); + DBUG_ASSERT(multi_range_length > 0); + while (multi_range_length && ! (multi_range= (KEY_MULTI_RANGE*) + my_malloc(multi_range_length * + sizeof(KEY_MULTI_RANGE), + MYF(MY_WME)))) + { + /* Try to shrink the buffers until it is 0. */ + multi_range_length/= 2; + } + if (! multi_range) + { + multi_range_length= 0; + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + + /* + Allocate the handler buffer if necessary. + */ + if (file->table_flags() & HA_NEED_READ_RANGE_BUFFER) + { + mrange_bufsiz= min(multi_range_bufsiz, + QUICK_SELECT_I::records * head->reclength); + + while (mrange_bufsiz && + ! my_multi_malloc(MYF(MY_WME), + &multi_range_buff, sizeof(*multi_range_buff), + &mrange_buff, mrange_bufsiz, + NullS)) + { + /* Try to shrink the buffers until both are 0. */ + mrange_bufsiz/= 2; + } + if (! multi_range_buff) + { + my_free((char*) multi_range, MYF(0)); + multi_range= NULL; + multi_range_length= 0; + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + + /* Initialize the handler buffer. */ + multi_range_buff->buffer= mrange_buff; + 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); +} + + +/* + Get next possible record using quick-struct. + + SYNOPSIS + QUICK_RANGE_SELECT::get_next() + + NOTES + Record is read into table->record[0] + + RETURN + 0 Found row + HA_ERR_END_OF_FILE No (more) rows in range + # Error code +*/ int QUICK_RANGE_SELECT::get_next() { + int result; + KEY_MULTI_RANGE *mrange; + key_range *start_key; + key_range *end_key; DBUG_ENTER("QUICK_RANGE_SELECT::get_next"); + DBUG_ASSERT(multi_range_length && multi_range && + (cur_range >= (QUICK_RANGE**) ranges.buffer) && + (cur_range <= (QUICK_RANGE**) ranges.buffer + ranges.elements)); for (;;) { - int result; - key_range start_key, end_key; - if (range) + if (in_range) { - // Already read through key - result= file->read_range_next(); + /* We did already start to read this key. */ + result= file->read_multi_range_next(&mrange); if (result != HA_ERR_END_OF_FILE) + { + in_range= ! result; DBUG_RETURN(result); + } } - if (!cur_range) - range= *(cur_range= (QUICK_RANGE**) ranges.buffer); - else - range= - (cur_range == ((QUICK_RANGE**) ranges.buffer + ranges.elements - 1)) ? - (QUICK_RANGE*) 0 : *(++cur_range); - - if (!range) - DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used - - start_key.key= (const byte*) range->min_key; - start_key.length= range->min_length; - start_key.flag= ((range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY : - (range->flag & EQ_RANGE) ? - HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT); - end_key.key= (const byte*) range->max_key; - end_key.length= range->max_length; - /* - We use READ_AFTER_KEY here because if we are reading on a key - prefix we want to find all keys with this prefix - */ - end_key.flag= (range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY : - HA_READ_AFTER_KEY); + uint count= min(multi_range_length, ranges.elements - + (cur_range - (QUICK_RANGE**) ranges.buffer)); + if (count == 0) + { + /* Ranges have already been used up before. None is left for read. */ + in_range= FALSE; + DBUG_RETURN(HA_ERR_END_OF_FILE); + } + KEY_MULTI_RANGE *mrange_slot, *mrange_end; + for (mrange_slot= multi_range, mrange_end= mrange_slot+count; + mrange_slot < mrange_end; + mrange_slot++) + { + start_key= &mrange_slot->start_key; + end_key= &mrange_slot->end_key; + range= *(cur_range++); + + start_key->key= (const byte*) range->min_key; + start_key->length= range->min_length; + start_key->flag= ((range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY : + (range->flag & EQ_RANGE) ? + HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT); + end_key->key= (const byte*) range->max_key; + end_key->length= range->max_length; + /* + We use HA_READ_AFTER_KEY here because if we are reading on a key + prefix. We want to find all keys with this prefix. + */ + end_key->flag= (range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY : + HA_READ_AFTER_KEY); - result= file->read_range_first(range->min_length ? &start_key : 0, - range->max_length ? &end_key : 0, - test(range->flag & EQ_RANGE), - sorted); - if (range->flag == (UNIQUE_RANGE | EQ_RANGE)) - range=0; // Stop searching + mrange_slot->range_flag= range->flag; + } + result= file->read_multi_range_first(&mrange, multi_range, count, + sorted, multi_range_buff); if (result != HA_ERR_END_OF_FILE) + { + in_range= ! result; DBUG_RETURN(result); - range=0; // No matching rows; go to next range + } + in_range= FALSE; /* No matching rows; go to next set of ranges. */ } } @@ -5974,15 +6109,14 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix) DBUG_RETURN(result); } - if (!cur_range) - range= *(cur_range= (QUICK_RANGE**) ranges.buffer); /* First range. */ - else - range= - (cur_range == ((QUICK_RANGE**) ranges.buffer + ranges.elements - 1)) ? - (QUICK_RANGE*) 0 : *(++cur_range); /* Next range. */ - - if (!range) - DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used + uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer); + if (count == 0) + { + /* Ranges have already been used up before. None is left for read. */ + range= 0; + DBUG_RETURN(HA_ERR_END_OF_FILE); + } + range= *(cur_range++); start_key.key= (const byte*) range->min_key; start_key.length= min(range->min_length, prefix_length); @@ -6030,15 +6164,14 @@ int QUICK_RANGE_SELECT_GEOM::get_next() DBUG_RETURN(result); } - if (!cur_range) - range= *(cur_range= (QUICK_RANGE**) ranges.buffer); - else - range= - (cur_range == ((QUICK_RANGE**) ranges.buffer + ranges.elements - 1)) ? - (QUICK_RANGE*) 0 : *(++cur_range); - - if (!range) - DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used + uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer); + if (count == 0) + { + /* Ranges have already been used up before. None is left for read. */ + range= 0; + DBUG_RETURN(HA_ERR_END_OF_FILE); + } + range= *(cur_range++); result= file->index_read(record, (byte*) range->min_key, diff --git a/sql/opt_range.h b/sql/opt_range.h index 74d388128c8..71981dfb5c7 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -24,16 +24,6 @@ #pragma interface /* gcc class implementation */ #endif -#define NO_MIN_RANGE 1 -#define NO_MAX_RANGE 2 -#define NEAR_MIN 4 -#define NEAR_MAX 8 -#define UNIQUE_RANGE 16 -#define EQ_RANGE 32 -#define NULL_RANGE 64 -#define GEOM_FLAG 128 - - typedef struct st_key_part { uint16 key,part, store_length, length; uint8 null_bit; @@ -135,9 +125,24 @@ public: */ 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 */ virtual void range_end() {} - virtual int get_next() = 0; /* get next record to retrieve */ + virtual bool reverse_sorted() = 0; virtual bool unique_key_range() { return false; } @@ -236,6 +241,14 @@ protected: closed no later then this quick select is deleted. */ bool free_file; + bool in_range; + uint multi_range_count; /* copy from thd->variables.multi_range_count */ + uint multi_range_length; /* the allocated length for the array */ + uint multi_range_bufsiz; /* copy from thd->variables.read_rnd_buff_size */ + KEY_MULTI_RANGE *multi_range; /* the multi-range array (allocated and + freed by QUICK_RANGE_SELECT) */ + HANDLER_BUFFER *multi_range_buff; /* the handler buffer (allocated and + freed by QUICK_RANGE_SELECT) */ protected: friend class TRP_ROR_INTERSECT; @@ -270,18 +283,19 @@ public: MEM_ROOT *parent_alloc=NULL); ~QUICK_RANGE_SELECT(); + int init(); int reset(void) { next=0; range= NULL; - cur_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 init(); + int get_next_init(void); int get_next(); void range_end(); int get_next_prefix(uint prefix_length, byte *cur_prefix); @@ -296,6 +310,13 @@ public: #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif + QUICK_RANGE_SELECT(const QUICK_RANGE_SELECT& org) : QUICK_SELECT_I() + { + bcopy(&org, this, sizeof(*this)); + multi_range_length= 0; + multi_range= NULL; + multi_range_buff= NULL; + } }; diff --git a/sql/records.cc b/sql/records.cc index 5963c36afd9..3c0143d2307 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -100,11 +100,19 @@ 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) { diff --git a/sql/set_var.cc b/sql/set_var.cc index b42ca91c7dd..2d453925fa5 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -259,6 +259,8 @@ sys_var_thd_ulong sys_max_tmp_tables("max_tmp_tables", &SV::max_tmp_tables); sys_var_long_ptr sys_max_write_lock_count("max_write_lock_count", &max_write_lock_count); +sys_var_thd_ulong sys_multi_range_count("multi_range_count", + &SV::multi_range_count); sys_var_long_ptr sys_myisam_data_pointer_size("myisam_data_pointer_size", &myisam_data_pointer_size); sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size, fix_myisam_max_extra_sort_file_size, 1); diff --git a/sql/sql_class.h b/sql/sql_class.h index 6cec2c2c787..af1ed0b2209 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -388,6 +388,7 @@ struct system_variables ulong max_sort_length; ulong max_tmp_tables; ulong max_insert_delayed_threads; + ulong multi_range_count; ulong myisam_repair_threads; ulong myisam_sort_buff_size; ulong net_buffer_length; |