diff --git a/sql/handler.h b/sql/handler.h index cbc0a13aafe..5b83d8c9556 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1868,6 +1868,16 @@ public: } /* This is called after index_init() if we need to do a index scan */ virtual int prepare_index_scan() { return 0; } + virtual int prepare_index_key_scan_map(const uchar * key, key_part_map keypart_map) + { + uint key_len= calculate_key_len(table, active_index, key, keypart_map); + return prepare_index_key_scan(key, key_len); + } + virtual int prepare_index_key_scan( const uchar * key, uint key_len ) + { return 0; } + virtual int prepare_range_scan(const key_range *start_key, const key_range *end_key) + { return 0; } + int ha_rnd_init(bool scan) __attribute__ ((warn_unused_result)) { DBUG_EXECUTE_IF("ha_rnd_init_fail", return HA_ERR_TABLE_DEF_CHANGED;); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 1515b0d78a1..036f9a8f706 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -11390,6 +11390,26 @@ int QUICK_SELECT_DESC::get_next() if (!(last_range= rev_it++)) DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used + key_range start_key; + start_key.key= (const uchar*) last_range->min_key; + start_key.length= last_range->min_length; + start_key.flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY : + (last_range->flag & EQ_RANGE) ? + HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT); + start_key.keypart_map= last_range->min_keypart_map; + key_range end_key; + end_key.key= (const uchar*) last_range->max_key; + end_key.length= last_range->max_length; + end_key.flag= (last_range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY : + HA_READ_AFTER_KEY); + end_key.keypart_map= last_range->max_keypart_map; + result= file->prepare_range_scan((last_range->flag & NO_MIN_RANGE) ? NULL : &start_key, + (last_range->flag & NO_MAX_RANGE) ? NULL : &end_key); + if (result) + { + DBUG_RETURN(result); + } + if (last_range->flag & NO_MAX_RANGE) // Read last record { int local_error; diff --git a/sql/records.cc b/sql/records.cc index 7b2cea2830b..2f74030d5c4 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -371,7 +371,15 @@ static int rr_quick(READ_RECORD *info) static int rr_index_first(READ_RECORD *info) { - int tmp= info->table->file->ha_index_first(info->record); + int tmp; + // tell handler that we are doing an index scan + if ((tmp = info->table->file->prepare_index_scan())) + { + tmp= rr_handle_error(info, tmp); + return tmp; + } + + tmp= info->table->file->ha_index_first(info->record); info->read_record= rr_index; if (tmp) tmp= rr_handle_error(info, tmp); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c959e1d1ce9..d354d8950e2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -17291,6 +17291,11 @@ join_read_always_key(JOIN_TAB *tab) if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref)) return -1; + if ((error= table->file->prepare_index_key_scan_map(tab->ref.key_buff, make_prev_keypart_map(tab->ref.key_parts)))) + { + report_error(table,error); + return -1; + } if ((error= table->file->ha_index_read_map(table->record[0], tab->ref.key_buff, make_prev_keypart_map(tab->ref.key_parts), @@ -17324,6 +17329,11 @@ join_read_last_key(JOIN_TAB *tab) if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref)) return -1; + if ((error= table->file->prepare_index_key_scan_map(tab->ref.key_buff, make_prev_keypart_map(tab->ref.key_parts)))) + { + report_error(table,error); + return -1; + } if ((error= table->file->ha_index_read_map(table->record[0], tab->ref.key_buff, make_prev_keypart_map(tab->ref.key_parts),