WL#3700: Handler API change: all index search methods - that is,
index_read(), index_read_idx(), index_read_last(), and records_in_range() - instead of 'uint keylen' argument take 'ulonglong keypart_map', a bitmap showing which keyparts are present in the key value. Fallback method is provided for handlers that are lagging behind.
This commit is contained in:
parent
6e1ba88418
commit
4e8b49d656
@ -226,7 +226,7 @@ ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, key_range *min_key,
|
||||
key_range *max_key);
|
||||
int hp_panic(enum ha_panic_function flag);
|
||||
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
ulonglong keypart_map, enum ha_rkey_function find_flag);
|
||||
extern gptr heap_find(HP_INFO *info,int inx,const byte *key);
|
||||
extern int heap_check_heap(HP_INFO *info, my_bool print_status);
|
||||
extern byte *heap_position(HP_INFO *info);
|
||||
|
@ -384,9 +384,10 @@ enum ha_base_keytype {
|
||||
#define HA_ERR_TABLE_NEEDS_UPGRADE 164 /* The table changed in storage engine */
|
||||
#define HA_ERR_TABLE_READONLY 165 /* The table is not writable */
|
||||
|
||||
#define HA_ERR_AUTOINC_READ_FAILED 166/* Failed to get the next autoinc value */
|
||||
#define HA_ERR_AUTOINC_ERANGE 167 /* Failed to set the row autoinc value */
|
||||
#define HA_ERR_LAST 167 /*Copy last error nr.*/
|
||||
#define HA_ERR_AUTOINC_READ_FAILED 166 /* Failed to get next autoinc value */
|
||||
#define HA_ERR_AUTOINC_ERANGE 167 /* Failed to set row autoinc value */
|
||||
#define HA_ERR_GENERIC 168 /* Generic error */
|
||||
#define HA_ERR_LAST 168 /*Copy last error nr.*/
|
||||
/* Add error numbers before HA_ERR_LAST and change it accordingly. */
|
||||
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
|
||||
|
||||
@ -467,6 +468,7 @@ typedef struct st_key_range
|
||||
{
|
||||
const byte *key;
|
||||
uint length;
|
||||
ulonglong keypart_map;
|
||||
enum ha_rkey_function flag;
|
||||
} key_range;
|
||||
|
||||
|
@ -274,9 +274,8 @@ extern struct st_myisam_info *mi_open(const char *name,int mode,
|
||||
uint wait_if_locked);
|
||||
extern int mi_panic(enum ha_panic_function function);
|
||||
extern int mi_rfirst(struct st_myisam_info *file,byte *buf,int inx);
|
||||
extern int mi_rkey(struct st_myisam_info *file,byte *buf,int inx,
|
||||
const byte *key,
|
||||
uint key_len, enum ha_rkey_function search_flag);
|
||||
extern int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key,
|
||||
ulonglong keypart_map, enum ha_rkey_function search_flag);
|
||||
extern int mi_rlast(struct st_myisam_info *file,byte *buf,int inx);
|
||||
extern int mi_rnext(struct st_myisam_info *file,byte *buf,int inx);
|
||||
extern int mi_rnext_same(struct st_myisam_info *info, byte *buf);
|
||||
@ -303,7 +302,7 @@ extern int mi_extra(struct st_myisam_info *file,
|
||||
enum ha_extra_function function,
|
||||
void *extra_arg);
|
||||
extern int mi_reset(struct st_myisam_info *file);
|
||||
extern ha_rows mi_records_in_range(struct st_myisam_info *info,int inx,
|
||||
extern ha_rows mi_records_in_range(MI_INFO *info, int inx,
|
||||
key_range *min_key, key_range *max_key);
|
||||
extern int mi_log(int activate_log);
|
||||
extern int mi_is_changed(struct st_myisam_info *info);
|
||||
|
@ -86,8 +86,8 @@ extern int myrg_rlast(MYRG_INFO *file,byte *buf,int inx);
|
||||
extern int myrg_rnext(MYRG_INFO *file,byte *buf,int inx);
|
||||
extern int myrg_rprev(MYRG_INFO *file,byte *buf,int inx);
|
||||
extern int myrg_rnext_same(MYRG_INFO *file,byte *buf);
|
||||
extern int myrg_rkey(MYRG_INFO *file,byte *buf,int inx,const byte *key,
|
||||
uint key_len, enum ha_rkey_function search_flag);
|
||||
extern int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
|
||||
ulonglong keypart_map, enum ha_rkey_function search_flag);
|
||||
extern int myrg_rrnd(MYRG_INFO *file,byte *buf,ulonglong pos);
|
||||
extern int myrg_rsame(MYRG_INFO *file,byte *record,int inx);
|
||||
extern int myrg_update(MYRG_INFO *file,const byte *old,byte *new_rec);
|
||||
@ -100,7 +100,7 @@ extern int myrg_extra(MYRG_INFO *file,enum ha_extra_function function,
|
||||
void *extra_arg);
|
||||
extern int myrg_reset(MYRG_INFO *info);
|
||||
extern void myrg_extrafunc(MYRG_INFO *info,invalidator_by_filename inv);
|
||||
extern ha_rows myrg_records_in_range(MYRG_INFO *info,int inx,
|
||||
extern ha_rows myrg_records_in_range(MYRG_INFO *info, int inx,
|
||||
key_range *min_key, key_range *max_key);
|
||||
|
||||
extern ulonglong myrg_position(MYRG_INFO *info);
|
||||
|
@ -288,7 +288,7 @@ Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
|
||||
{
|
||||
key_copy(key_buf, event_table->record[0], key_info, key_len);
|
||||
if (!(ret= event_table->file->index_read(event_table->record[0], key_buf,
|
||||
key_len, HA_READ_PREFIX)))
|
||||
(ulonglong)1, HA_READ_PREFIX)))
|
||||
{
|
||||
DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret));
|
||||
do
|
||||
@ -518,7 +518,6 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
||||
my_bool create_if_not)
|
||||
{
|
||||
int ret= 0;
|
||||
CHARSET_INFO *scs= system_charset_info;
|
||||
TABLE *table= NULL;
|
||||
char old_db_buf[NAME_LEN+1];
|
||||
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
|
||||
@ -844,8 +843,7 @@ Event_db_repository::find_named_event(THD *thd, LEX_STRING db, LEX_STRING name,
|
||||
|
||||
key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
|
||||
|
||||
if (table->file->index_read_idx(table->record[0], 0, key,
|
||||
table->key_info->key_length,
|
||||
if (table->file->index_read_idx(table->record[0], 0, key, ~ULL(0),
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
DBUG_PRINT("info", ("Row not found"));
|
||||
|
@ -956,7 +956,6 @@ int ha_ndbcluster::get_ndb_partition_id(NdbOperation *ndb_op)
|
||||
|
||||
bool ha_ndbcluster::uses_blob_value()
|
||||
{
|
||||
uint blob_fields;
|
||||
MY_BITMAP *bitmap;
|
||||
uint *blob_index, *blob_index_end;
|
||||
if (table_share->blob_fields == 0)
|
||||
@ -1108,7 +1107,7 @@ int ha_ndbcluster::create_indexes(Ndb *ndb, TABLE *tab)
|
||||
const char **key_name= tab->s->keynames.type_names;
|
||||
NDBDICT *dict= ndb->getDictionary();
|
||||
DBUG_ENTER("ha_ndbcluster::create_indexes");
|
||||
|
||||
|
||||
for (i= 0; i < tab->s->keys; i++, key_info++, key_name++)
|
||||
{
|
||||
index_name= *key_name;
|
||||
@ -3375,19 +3374,6 @@ int ha_ndbcluster::index_read(byte *buf,
|
||||
}
|
||||
|
||||
|
||||
int ha_ndbcluster::index_read_idx(byte *buf, uint index_no,
|
||||
const byte *key, uint key_len,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status);
|
||||
DBUG_ENTER("ha_ndbcluster::index_read_idx");
|
||||
DBUG_PRINT("enter", ("index_no: %u, key_len: %u", index_no, key_len));
|
||||
close_scan();
|
||||
index_init(index_no, 0);
|
||||
DBUG_RETURN(index_read(buf, key, key_len, find_flag));
|
||||
}
|
||||
|
||||
|
||||
int ha_ndbcluster::index_next(byte *buf)
|
||||
{
|
||||
DBUG_ENTER("ha_ndbcluster::index_next");
|
||||
@ -3554,10 +3540,10 @@ int ha_ndbcluster::close_scan()
|
||||
|
||||
m_multi_cursor= 0;
|
||||
if (!m_active_cursor && !m_multi_cursor)
|
||||
DBUG_RETURN(1);
|
||||
DBUG_RETURN(0);
|
||||
|
||||
NdbScanOperation *cursor= m_active_cursor ? m_active_cursor : m_multi_cursor;
|
||||
|
||||
|
||||
if (m_lock_tuple)
|
||||
{
|
||||
/*
|
||||
|
@ -641,8 +641,6 @@ class ha_ndbcluster: public handler
|
||||
int index_end();
|
||||
int index_read(byte *buf, const byte *key, uint key_len,
|
||||
enum ha_rkey_function find_flag);
|
||||
int index_read_idx(byte *buf, uint index, const byte *key, uint key_len,
|
||||
enum ha_rkey_function find_flag);
|
||||
int index_next(byte *buf);
|
||||
int index_prev(byte *buf);
|
||||
int index_first(byte *buf);
|
||||
|
@ -584,7 +584,6 @@ int ha_partition::drop_partitions(const char *path)
|
||||
List_iterator<partition_element> part_it(m_part_info->partitions);
|
||||
char part_name_buff[FN_REFLEN];
|
||||
uint no_parts= m_part_info->partitions.elements;
|
||||
uint part_count= 0;
|
||||
uint no_subparts= m_part_info->no_subparts;
|
||||
uint i= 0;
|
||||
uint name_variant;
|
||||
@ -1075,7 +1074,6 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
|
||||
uint no_parts= m_part_info->no_parts;
|
||||
uint no_subparts= m_part_info->no_subparts;
|
||||
uint i= 0;
|
||||
LEX *lex= thd->lex;
|
||||
int error;
|
||||
DBUG_ENTER("ha_partition::handle_opt_partitions");
|
||||
DBUG_PRINT("enter", ("all_parts %u, flag= %u", all_parts, flag));
|
||||
@ -1136,7 +1134,6 @@ int ha_partition::prepare_new_partition(TABLE *table,
|
||||
{
|
||||
int error;
|
||||
bool create_flag= FALSE;
|
||||
bool open_flag= FALSE;
|
||||
DBUG_ENTER("prepare_new_partition");
|
||||
|
||||
if ((error= set_up_table_before_create(table, part_name, create_info,
|
||||
@ -1245,7 +1242,6 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
|
||||
handler **new_file_array;
|
||||
int error= 1;
|
||||
bool first;
|
||||
bool copy_parts= FALSE;
|
||||
uint temp_partitions= m_part_info->temp_partitions.elements;
|
||||
THD *thd= current_thd;
|
||||
DBUG_ENTER("ha_partition::change_partitions");
|
||||
@ -2061,7 +2057,6 @@ bool ha_partition::new_handlers_from_part_info(MEM_ROOT *mem_root)
|
||||
partition_element *part_elem;
|
||||
uint alloc_len= (m_tot_parts + 1) * sizeof(handler*);
|
||||
List_iterator_fast <partition_element> part_it(m_part_info->partitions);
|
||||
THD *thd= current_thd;
|
||||
DBUG_ENTER("ha_partition::new_handlers_from_part_info");
|
||||
|
||||
if (!(m_file= (handler **) alloc_root(mem_root, alloc_len)))
|
||||
@ -3327,13 +3322,14 @@ int ha_partition::index_end()
|
||||
*/
|
||||
|
||||
int ha_partition::index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
DBUG_ENTER("ha_partition::index_read");
|
||||
|
||||
end_range= 0;
|
||||
m_index_scan_type= partition_index_read;
|
||||
DBUG_RETURN(common_index_read(buf, key, key_len, find_flag));
|
||||
DBUG_RETURN(common_index_read(buf, key, keypart_map, find_flag));
|
||||
}
|
||||
|
||||
|
||||
@ -3346,14 +3342,17 @@ int ha_partition::index_read(byte * buf, const byte * key,
|
||||
see index_read for rest
|
||||
*/
|
||||
|
||||
int ha_partition::common_index_read(byte *buf, const byte *key, uint key_len,
|
||||
int ha_partition::common_index_read(byte *buf, const byte *key,
|
||||
ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
int error;
|
||||
bool reverse_order= FALSE;
|
||||
uint key_len= calculate_key_len(table, active_index, key, keypart_map);
|
||||
DBUG_ENTER("ha_partition::common_index_read");
|
||||
|
||||
memcpy((void*)m_start_key.key, key, key_len);
|
||||
m_start_key.keypart_map= keypart_map;
|
||||
m_start_key.length= key_len;
|
||||
m_start_key.flag= find_flag;
|
||||
|
||||
@ -3481,33 +3480,6 @@ int ha_partition::common_first_last(byte *buf)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Perform index read using index where always only one row is returned
|
||||
|
||||
SYNOPSIS
|
||||
index_read_idx()
|
||||
see index_read for rest of parameters and return values
|
||||
|
||||
DESCRIPTION
|
||||
Positions an index cursor to the index specified in key. Fetches the
|
||||
row if any. This is only used to read whole keys.
|
||||
TODO: Optimise this code to avoid index_init and index_end
|
||||
*/
|
||||
|
||||
int ha_partition::index_read_idx(byte * buf, uint index, const byte * key,
|
||||
uint key_len,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
int res;
|
||||
DBUG_ENTER("ha_partition::index_read_idx");
|
||||
|
||||
index_init(index, 0);
|
||||
res= index_read(buf, key, key_len, find_flag);
|
||||
index_end();
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Read last using key
|
||||
|
||||
@ -3526,14 +3498,15 @@ int ha_partition::index_read_idx(byte * buf, uint index, const byte * key,
|
||||
Can only be used on indexes supporting HA_READ_ORDER
|
||||
*/
|
||||
|
||||
int ha_partition::index_read_last(byte *buf, const byte *key, uint keylen)
|
||||
int ha_partition::index_read_last(byte *buf, const byte *key,
|
||||
ulonglong keypart_map)
|
||||
{
|
||||
DBUG_ENTER("ha_partition::index_read_last");
|
||||
|
||||
m_ordered= TRUE; // Safety measure
|
||||
end_range= 0;
|
||||
m_index_scan_type= partition_index_read_last;
|
||||
DBUG_RETURN(common_index_read(buf, key, keylen, HA_READ_PREFIX_LAST));
|
||||
DBUG_RETURN(common_index_read(buf, key, keypart_map, HA_READ_PREFIX_LAST));
|
||||
}
|
||||
|
||||
|
||||
@ -3679,7 +3652,7 @@ int ha_partition::read_range_first(const key_range *start_key,
|
||||
m_index_scan_type= partition_index_read;
|
||||
error= common_index_read(m_rec0,
|
||||
start_key->key,
|
||||
start_key->length, start_key->flag);
|
||||
start_key->keypart_map, start_key->flag);
|
||||
}
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
@ -3878,7 +3851,7 @@ int ha_partition::handle_unordered_scan_next_partition(byte * buf)
|
||||
case partition_index_read:
|
||||
DBUG_PRINT("info", ("index_read on partition %d", i));
|
||||
error= file->index_read(buf, m_start_key.key,
|
||||
m_start_key.length,
|
||||
m_start_key.keypart_map,
|
||||
m_start_key.flag);
|
||||
break;
|
||||
case partition_index_first:
|
||||
@ -3970,7 +3943,7 @@ int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order)
|
||||
case partition_index_read:
|
||||
error= file->index_read(rec_buf_ptr,
|
||||
m_start_key.key,
|
||||
m_start_key.length,
|
||||
m_start_key.keypart_map,
|
||||
m_start_key.flag);
|
||||
break;
|
||||
case partition_index_first:
|
||||
@ -3984,7 +3957,7 @@ int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order)
|
||||
case partition_index_read_last:
|
||||
error= file->index_read_last(rec_buf_ptr,
|
||||
m_start_key.key,
|
||||
m_start_key.length);
|
||||
m_start_key.keypart_map);
|
||||
reverse_order= TRUE;
|
||||
break;
|
||||
default:
|
||||
|
@ -378,9 +378,8 @@ public:
|
||||
any end processing needed.
|
||||
*/
|
||||
virtual int index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
virtual int index_read_idx(byte * buf, uint idx, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag);
|
||||
virtual int index_init(uint idx, bool sorted);
|
||||
virtual int index_end();
|
||||
|
||||
@ -393,7 +392,8 @@ public:
|
||||
virtual int index_first(byte * buf);
|
||||
virtual int index_last(byte * buf);
|
||||
virtual int index_next_same(byte * buf, const byte * key, uint keylen);
|
||||
virtual int index_read_last(byte * buf, const byte * key, uint keylen);
|
||||
virtual int index_read_last(byte * buf, const byte * key,
|
||||
ulonglong keypart_map);
|
||||
|
||||
/*
|
||||
read_first_row is virtual method but is only implemented by
|
||||
@ -419,7 +419,7 @@ public:
|
||||
|
||||
private:
|
||||
int common_index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
ulonglong keypart_map, enum ha_rkey_function find_flag);
|
||||
int common_first_last(byte * buf);
|
||||
int partition_scan_set_up(byte * buf, bool idx_read_flag);
|
||||
int handle_unordered_next(byte * buf, bool next_same);
|
||||
|
@ -48,8 +48,6 @@ KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0} };
|
||||
|
||||
static handler *create_default(TABLE_SHARE *table, MEM_ROOT *mem_root);
|
||||
|
||||
static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;
|
||||
|
||||
/* number of entries in handlertons[] */
|
||||
ulong total_ha= 0;
|
||||
/* number of storage engines (from handlertons[]) that support 2pc */
|
||||
@ -1854,7 +1852,7 @@ int handler::update_auto_increment()
|
||||
nr= compute_next_insert_id(nr-1, variables);
|
||||
}
|
||||
|
||||
if (table->s->next_number_key_offset == 0)
|
||||
if (table->s->next_number_keypart == 0)
|
||||
{
|
||||
/* We must defer the appending until "nr" has been possibly truncated */
|
||||
append= TRUE;
|
||||
@ -1976,7 +1974,7 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
|
||||
table->read_set);
|
||||
column_bitmaps_signal();
|
||||
index_init(table->s->next_number_index, 1);
|
||||
if (!table->s->next_number_key_offset)
|
||||
if (table->s->next_number_keypart == 0)
|
||||
{ // Autoincrement at key-start
|
||||
error=index_last(table->record[1]);
|
||||
/*
|
||||
@ -1992,7 +1990,8 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
|
||||
key_copy(key, table->record[0],
|
||||
table->key_info + table->s->next_number_index,
|
||||
table->s->next_number_key_offset);
|
||||
error= index_read(table->record[1], key, table->s->next_number_key_offset,
|
||||
error= index_read(table->record[1], key,
|
||||
make_prev_keypart_map(table->s->next_number_keypart),
|
||||
HA_READ_PREFIX_LAST);
|
||||
/*
|
||||
MySQL needs to call us for next row: assume we are inserting ("a",null)
|
||||
@ -3103,9 +3102,9 @@ int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
|
||||
multi_range_curr < multi_range_end;
|
||||
multi_range_curr++)
|
||||
{
|
||||
result= read_range_first(multi_range_curr->start_key.length ?
|
||||
result= read_range_first(multi_range_curr->start_key.keypart_map ?
|
||||
&multi_range_curr->start_key : 0,
|
||||
multi_range_curr->end_key.length ?
|
||||
multi_range_curr->end_key.keypart_map ?
|
||||
&multi_range_curr->end_key : 0,
|
||||
test(multi_range_curr->range_flag & EQ_RANGE),
|
||||
multi_range_sorted);
|
||||
@ -3171,9 +3170,9 @@ int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
|
||||
multi_range_curr < multi_range_end;
|
||||
multi_range_curr++)
|
||||
{
|
||||
result= read_range_first(multi_range_curr->start_key.length ?
|
||||
result= read_range_first(multi_range_curr->start_key.keypart_map ?
|
||||
&multi_range_curr->start_key : 0,
|
||||
multi_range_curr->end_key.length ?
|
||||
multi_range_curr->end_key.keypart_map ?
|
||||
&multi_range_curr->end_key : 0,
|
||||
test(multi_range_curr->range_flag & EQ_RANGE),
|
||||
multi_range_sorted);
|
||||
@ -3233,7 +3232,7 @@ int handler::read_range_first(const key_range *start_key,
|
||||
else
|
||||
result= index_read(table->record[0],
|
||||
start_key->key,
|
||||
start_key->length,
|
||||
start_key->keypart_map,
|
||||
start_key->flag);
|
||||
if (result)
|
||||
DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND)
|
||||
@ -3307,15 +3306,19 @@ int handler::compare_key(key_range *range)
|
||||
return cmp;
|
||||
}
|
||||
|
||||
|
||||
int handler::index_read_idx(byte * buf, uint index, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
int error= ha_index_init(index, 0);
|
||||
int error, error1;
|
||||
error= index_init(index, 0);
|
||||
if (!error)
|
||||
error= index_read(buf, key, key_len, find_flag);
|
||||
if (!error)
|
||||
error= ha_index_end();
|
||||
return error;
|
||||
{
|
||||
error= index_read(buf, key, keypart_map, find_flag);
|
||||
error1= index_end();
|
||||
}
|
||||
return error ? error : error1;
|
||||
}
|
||||
|
||||
|
||||
@ -3365,7 +3368,6 @@ static my_bool exts_handlerton(THD *unused, st_plugin_int *plugin,
|
||||
|
||||
TYPELIB *ha_known_exts(void)
|
||||
{
|
||||
MEM_ROOT *mem_root= current_thd->mem_root;
|
||||
if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
|
||||
{
|
||||
List<char> found_exts;
|
||||
|
@ -867,6 +867,18 @@ public:
|
||||
{}
|
||||
};
|
||||
|
||||
uint calculate_key_len(TABLE *, uint, const byte *, ulonglong);
|
||||
/*
|
||||
bitmap with first N+1 bits set
|
||||
(keypart_map for a key prefix of [0..N] keyparts)
|
||||
*/
|
||||
#define make_keypart_map(N) (((ulonglong)2 << (N)) - 1)
|
||||
/*
|
||||
bitmap with first N bits set
|
||||
(keypart_map for a key prefix of [0..N-1] keyparts)
|
||||
*/
|
||||
#define make_prev_keypart_map(N) (((ulonglong)1 << (N)) - 1)
|
||||
|
||||
/*
|
||||
The handler class is the interface for dynamically loadable
|
||||
storage engines. Do not add ifdefs and take care when adding or
|
||||
@ -1202,11 +1214,20 @@ public:
|
||||
DBUG_ASSERT(FALSE);
|
||||
return HA_ERR_WRONG_COMMAND;
|
||||
}
|
||||
virtual int index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
private:
|
||||
virtual int index_read(byte * buf, const byte * key, uint key_len,
|
||||
enum ha_rkey_function find_flag)
|
||||
{ return HA_ERR_WRONG_COMMAND; }
|
||||
public:
|
||||
virtual int index_read(byte * buf, const byte * key, ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
uint key_len= calculate_key_len(table, active_index, key, keypart_map);
|
||||
return index_read(buf, key, key_len, find_flag);
|
||||
}
|
||||
virtual int index_read_idx(byte * buf, uint index, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag);
|
||||
virtual int index_next(byte * buf)
|
||||
{ return HA_ERR_WRONG_COMMAND; }
|
||||
virtual int index_prev(byte * buf)
|
||||
@ -1216,8 +1237,16 @@ public:
|
||||
virtual int index_last(byte * buf)
|
||||
{ return HA_ERR_WRONG_COMMAND; }
|
||||
virtual int index_next_same(byte *buf, const byte *key, uint keylen);
|
||||
private:
|
||||
virtual int index_read_last(byte * buf, const byte * key, uint key_len)
|
||||
{ return (my_errno=HA_ERR_WRONG_COMMAND); }
|
||||
public:
|
||||
virtual int index_read_last(byte * buf, const byte * key,
|
||||
ulonglong keypart_map)
|
||||
{
|
||||
uint key_len= calculate_key_len(table, active_index, key, keypart_map);
|
||||
return index_read_last(buf, key, key_len);
|
||||
}
|
||||
virtual int read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
|
||||
KEY_MULTI_RANGE *ranges, uint range_count,
|
||||
bool sorted, HANDLER_BUFFER *buffer);
|
||||
@ -1243,8 +1272,7 @@ public:
|
||||
{ return HA_ERR_WRONG_COMMAND; }
|
||||
virtual int rnd_same(byte *buf, uint inx)
|
||||
{ return HA_ERR_WRONG_COMMAND; }
|
||||
virtual ha_rows records_in_range(uint inx, key_range *min_key,
|
||||
key_range *max_key)
|
||||
virtual ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key)
|
||||
{ return (ha_rows) 10; }
|
||||
virtual void position(const byte *record)=0;
|
||||
virtual int info(uint)=0; // see my_base.h for full description
|
||||
|
@ -2013,7 +2013,8 @@ int subselect_uniquesubquery_engine::exec()
|
||||
table->file->ha_index_init(tab->ref.key, 0);
|
||||
error= table->file->index_read(table->record[0],
|
||||
tab->ref.key_buff,
|
||||
tab->ref.key_length,HA_READ_KEY_EXACT);
|
||||
tab_to_keypart_map(tab),
|
||||
HA_READ_KEY_EXACT);
|
||||
if (error &&
|
||||
error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
||||
error= report_error(table, error);
|
||||
@ -2122,7 +2123,8 @@ int subselect_indexsubquery_engine::exec()
|
||||
table->file->ha_index_init(tab->ref.key, 1);
|
||||
error= table->file->index_read(table->record[0],
|
||||
tab->ref.key_buff,
|
||||
tab->ref.key_length,HA_READ_KEY_EXACT);
|
||||
tab_to_keypart_map(tab),
|
||||
HA_READ_KEY_EXACT);
|
||||
if (error &&
|
||||
error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
||||
error= report_error(table, error);
|
||||
|
14
sql/key.cc
14
sql/key.cc
@ -29,6 +29,7 @@
|
||||
field Field to search after
|
||||
key_length On partial match, contains length of fields before
|
||||
field
|
||||
keypart key part # of a field
|
||||
|
||||
NOTES
|
||||
Used when calculating key for NEXT_NUMBER
|
||||
@ -45,7 +46,7 @@
|
||||
*/
|
||||
|
||||
int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
|
||||
uint *key_length)
|
||||
uint *key_length, uint *keypart)
|
||||
{
|
||||
reg2 int i;
|
||||
reg3 KEY *key_info;
|
||||
@ -60,8 +61,8 @@ int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
|
||||
{
|
||||
if (key_info->key_part[0].offset == fieldpos)
|
||||
{ /* Found key. Calc keylength */
|
||||
*key_length=0;
|
||||
return(i); /* Use this key */
|
||||
*key_length= *keypart= 0;
|
||||
return i; /* Use this key */
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,8 +79,11 @@ int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
|
||||
j++, key_part++)
|
||||
{
|
||||
if (key_part->offset == fieldpos)
|
||||
return(i); /* Use this key */
|
||||
*key_length+=key_part->store_length;
|
||||
{
|
||||
*keypart= j;
|
||||
return i; /* Use this key */
|
||||
}
|
||||
*key_length+= key_part->store_length;
|
||||
}
|
||||
}
|
||||
return(-1); /* No key is ok */
|
||||
|
@ -3787,7 +3787,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
|
||||
nb_elements()));
|
||||
/*
|
||||
If the auto_increment was second in a table's index (possible with
|
||||
MyISAM or BDB) (table->next_number_key_offset != 0), such event is
|
||||
MyISAM or BDB) (table->next_number_keypart != 0), such event is
|
||||
in fact not necessary. We could avoid logging it.
|
||||
*/
|
||||
Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT,
|
||||
|
@ -6720,9 +6720,8 @@ replace_record(THD *thd, TABLE *table,
|
||||
}
|
||||
|
||||
key_copy((byte*)key.get(), table->record[0], table->key_info + keynum, 0);
|
||||
error= table->file->index_read_idx(table->record[1], keynum,
|
||||
(const byte*)key.get(),
|
||||
table->key_info[keynum].key_length,
|
||||
error= table->file->index_read_idx(table->record[1], keynum,
|
||||
(const byte*)key.get(), ~ULL(0),
|
||||
HA_READ_KEY_EXACT);
|
||||
if (error)
|
||||
DBUG_RETURN(error);
|
||||
@ -6907,8 +6906,7 @@ static int find_and_fetch_row(TABLE *table, byte *key)
|
||||
table->s->null_bytes > 0 ? table->s->null_bytes - 1 : 0;
|
||||
table->record[1][pos]= 0xFF;
|
||||
if ((error= table->file->index_read(table->record[1], key,
|
||||
table->key_info->key_length,
|
||||
HA_READ_KEY_EXACT)))
|
||||
~(ulonglong)0, HA_READ_KEY_EXACT)))
|
||||
{
|
||||
table->file->print_error(error, MYF(0));
|
||||
table->file->ha_index_end();
|
||||
|
@ -1445,7 +1445,7 @@ void print_plan(JOIN* join,uint idx, double record_count, double read_time,
|
||||
void mysql_print_status();
|
||||
/* key.cc */
|
||||
int find_ref_key(KEY *key, uint key_count, byte *record, Field *field,
|
||||
uint *key_length);
|
||||
uint *key_length, uint *keypart);
|
||||
void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length);
|
||||
void key_restore(byte *to_record, byte *from_key, KEY *key_info,
|
||||
uint key_length);
|
||||
|
243
sql/opt_range.cc
243
sql/opt_range.cc
@ -310,7 +310,7 @@ public:
|
||||
min_value=arg->max_value;
|
||||
min_flag=arg->max_flag & NEAR_MAX ? 0 : NEAR_MIN;
|
||||
}
|
||||
void store_min(uint length,char **min_key,uint min_key_flag)
|
||||
int store_min(uint length,char **min_key,uint min_key_flag)
|
||||
{
|
||||
if ((min_flag & GEOM_FLAG) ||
|
||||
(!(min_flag & NO_MIN_RANGE) &&
|
||||
@ -324,12 +324,12 @@ public:
|
||||
else
|
||||
memcpy(*min_key,min_value,length);
|
||||
(*min_key)+= length;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void store(uint length,char **min_key,uint min_key_flag,
|
||||
char **max_key, uint max_key_flag)
|
||||
int store_max(uint length,char **max_key, uint max_key_flag)
|
||||
{
|
||||
store_min(length, min_key, min_key_flag);
|
||||
if (!(max_flag & NO_MAX_RANGE) &&
|
||||
!(max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
|
||||
{
|
||||
@ -341,33 +341,45 @@ public:
|
||||
else
|
||||
memcpy(*max_key,max_value,length);
|
||||
(*max_key)+= length;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*void store(uint length,char **min_key,uint min_key_flag,
|
||||
char **max_key, uint max_key_flag)
|
||||
{
|
||||
store_min(length, min_key, min_key_flag);
|
||||
store_max(length, max_key, max_key_flag);
|
||||
}*/
|
||||
|
||||
void store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag)
|
||||
int store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag)
|
||||
{
|
||||
SEL_ARG *key_tree= first();
|
||||
key_tree->store(key[key_tree->part].store_length,
|
||||
range_key,*range_key_flag,range_key,NO_MAX_RANGE);
|
||||
uint res= key_tree->store_min(key[key_tree->part].store_length,
|
||||
range_key, *range_key_flag);
|
||||
*range_key_flag|= key_tree->min_flag;
|
||||
if (key_tree->next_key_part &&
|
||||
key_tree->next_key_part->part == key_tree->part+1 &&
|
||||
!(*range_key_flag & (NO_MIN_RANGE | NEAR_MIN)) &&
|
||||
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
|
||||
key_tree->next_key_part->store_min_key(key,range_key, range_key_flag);
|
||||
res+= key_tree->next_key_part->store_min_key(key, range_key,
|
||||
range_key_flag);
|
||||
return res;
|
||||
}
|
||||
|
||||
void store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag)
|
||||
int store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag)
|
||||
{
|
||||
SEL_ARG *key_tree= last();
|
||||
key_tree->store(key[key_tree->part].store_length,
|
||||
range_key, NO_MIN_RANGE, range_key,*range_key_flag);
|
||||
uint res=key_tree->store_max(key[key_tree->part].store_length,
|
||||
range_key, *range_key_flag);
|
||||
(*range_key_flag)|= key_tree->max_flag;
|
||||
if (key_tree->next_key_part &&
|
||||
key_tree->next_key_part->part == key_tree->part+1 &&
|
||||
!(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX)) &&
|
||||
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
|
||||
key_tree->next_key_part->store_max_key(key,range_key, range_key_flag);
|
||||
res+= key_tree->next_key_part->store_max_key(key, range_key,
|
||||
range_key_flag);
|
||||
return res;
|
||||
}
|
||||
|
||||
SEL_ARG *insert(SEL_ARG *key);
|
||||
@ -583,8 +595,8 @@ static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts);
|
||||
static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree,
|
||||
bool update_tbl_stats);
|
||||
static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree,
|
||||
char *min_key,uint min_key_flag,
|
||||
char *max_key, uint max_key_flag);
|
||||
char *min_key, uint min_key_flag, int,
|
||||
char *max_key, uint max_key_flag, int);
|
||||
|
||||
QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
|
||||
SEL_ARG *key_tree,
|
||||
@ -606,9 +618,6 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
||||
double read_time);
|
||||
static
|
||||
TRP_GROUP_MIN_MAX *get_best_group_min_max(PARAM *param, SEL_TREE *tree);
|
||||
static int get_index_merge_params(PARAM *param, key_map& needed_reg,
|
||||
SEL_IMERGE *imerge, double *read_time,
|
||||
ha_rows* imerge_rows);
|
||||
static double get_index_only_read_time(const PARAM* param, ha_rows records,
|
||||
int keynr);
|
||||
|
||||
@ -1455,6 +1464,7 @@ QUICK_ROR_UNION_SELECT::~QUICK_ROR_UNION_SELECT()
|
||||
|
||||
QUICK_RANGE::QUICK_RANGE()
|
||||
:min_key(0),max_key(0),min_length(0),max_length(0),
|
||||
min_keypart_map(0), max_keypart_map(0),
|
||||
flag(NO_MIN_RANGE | NO_MAX_RANGE)
|
||||
{}
|
||||
|
||||
@ -2425,8 +2435,6 @@ static int find_used_partitions_imerge(PART_PRUNE_PARAM *ppar,
|
||||
static int find_used_partitions_imerge_list(PART_PRUNE_PARAM *ppar,
|
||||
List<SEL_IMERGE> &merges);
|
||||
static void mark_all_partitions_as_used(partition_info *part_info);
|
||||
static uint32 part_num_to_part_id_range(PART_PRUNE_PARAM* prune_par,
|
||||
uint32 num);
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
static void print_partitioning_index(KEY_PART *parts, KEY_PART *parts_end);
|
||||
@ -4035,9 +4043,9 @@ void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src)
|
||||
The calculation is conducted as follows:
|
||||
Lets denote #records(keypart1, ... keypartK) as n_k. We need to calculate
|
||||
|
||||
n_{k1} n_{k_2}
|
||||
n_{k1} n_{k2}
|
||||
--------- * --------- * .... (3)
|
||||
n_{k1-1} n_{k2_1}
|
||||
n_{k1-1} n_{k2-1}
|
||||
|
||||
where k1,k2,... are key parts which fields were not yet marked as fixed
|
||||
( this is result of application of option b) of the recursion step for
|
||||
@ -4045,9 +4053,9 @@ void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src)
|
||||
Since it is reasonable to expect that most of the fields are not marked
|
||||
as fixed, we calculate (3) as
|
||||
|
||||
n_{i1} n_{i_2}
|
||||
n_{i1} n_{i2}
|
||||
(3) = n_{max_key_part} / ( --------- * --------- * .... )
|
||||
n_{i1-1} n_{i2_1}
|
||||
n_{i1-1} n_{i2-1}
|
||||
|
||||
where i1,i2, .. are key parts that were already marked as fixed.
|
||||
|
||||
@ -4056,7 +4064,6 @@ void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src)
|
||||
|
||||
RETURN
|
||||
Selectivity of given ROR scan.
|
||||
|
||||
*/
|
||||
|
||||
static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
|
||||
@ -4067,6 +4074,7 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
|
||||
byte key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */
|
||||
char *key_ptr= (char*) key_val;
|
||||
SEL_ARG *sel_arg, *tuple_arg= NULL;
|
||||
ulonglong keypart_map= 0;
|
||||
bool cur_covered;
|
||||
bool prev_covered= test(bitmap_is_set(&info->covered_fields,
|
||||
key_part->fieldnr-1));
|
||||
@ -4077,7 +4085,7 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
|
||||
max_range.key= (byte*) key_val;
|
||||
max_range.flag= HA_READ_AFTER_KEY;
|
||||
ha_rows prev_records= info->param->table->file->stats.records;
|
||||
DBUG_ENTER("ror_intersect_selectivity");
|
||||
DBUG_ENTER("ror_scan_selectivity");
|
||||
|
||||
for (sel_arg= scan->sel_arg; sel_arg;
|
||||
sel_arg= sel_arg->next_key_part)
|
||||
@ -4094,13 +4102,17 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
|
||||
tuple_arg= scan->sel_arg;
|
||||
/* Here we use the length of the first key part */
|
||||
tuple_arg->store_min(key_part->store_length, &key_ptr, 0);
|
||||
keypart_map= 1;
|
||||
}
|
||||
while (tuple_arg->next_key_part != sel_arg)
|
||||
{
|
||||
tuple_arg= tuple_arg->next_key_part;
|
||||
tuple_arg->store_min(key_part[tuple_arg->part].store_length, &key_ptr, 0);
|
||||
tuple_arg->store_min(key_part[tuple_arg->part].store_length,
|
||||
&key_ptr, 0);
|
||||
keypart_map= (keypart_map << 1) | 1;
|
||||
}
|
||||
min_range.length= max_range.length= ((char*) key_ptr - (char*) key_val);
|
||||
min_range.keypart_map= max_range.keypart_map= keypart_map;
|
||||
records= (info->param->table->file->
|
||||
records_in_range(scan->keynr, &min_range, &max_range));
|
||||
if (cur_covered)
|
||||
@ -5310,12 +5322,11 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond)
|
||||
*/
|
||||
for (uint i= 1 ; i < cond_func->arg_count ; i++)
|
||||
{
|
||||
|
||||
if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
field_item= (Item_field*) (cond_func->arguments()[i]->real_item());
|
||||
SEL_TREE *tmp= get_full_func_mm_tree(param, cond_func,
|
||||
field_item, (Item*) i, inv);
|
||||
field_item, (Item*)(intptr)i, inv);
|
||||
if (inv)
|
||||
tree= !tree ? tmp : tree_or(param, tree, tmp);
|
||||
else
|
||||
@ -7046,7 +7057,9 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree, bool update_tbl_stats)
|
||||
}
|
||||
param->n_ranges= 0;
|
||||
|
||||
records=check_quick_keys(param,idx,tree,param->min_key,0,param->max_key,0);
|
||||
records= check_quick_keys(param, idx, tree,
|
||||
param->min_key, 0, -1,
|
||||
param->max_key, 0, -1);
|
||||
if (records != HA_POS_ERROR)
|
||||
{
|
||||
if (update_tbl_stats)
|
||||
@ -7109,12 +7122,13 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree, bool update_tbl_stats)
|
||||
*/
|
||||
|
||||
static ha_rows
|
||||
check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
|
||||
char *min_key,uint min_key_flag, char *max_key,
|
||||
uint max_key_flag)
|
||||
check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree,
|
||||
char *min_key, uint min_key_flag, int min_keypart,
|
||||
char *max_key, uint max_key_flag, int max_keypart)
|
||||
{
|
||||
ha_rows records=0, tmp;
|
||||
uint tmp_min_flag, tmp_max_flag, keynr, min_key_length, max_key_length;
|
||||
uint tmp_min_keypart= min_keypart, tmp_max_keypart= max_keypart;
|
||||
char *tmp_min_key, *tmp_max_key;
|
||||
|
||||
param->max_key_part=max(param->max_key_part,key_tree->part);
|
||||
@ -7127,18 +7141,21 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
|
||||
This is not a ROR scan if the key is not Clustered Primary Key.
|
||||
*/
|
||||
param->is_ror_scan= FALSE;
|
||||
records=check_quick_keys(param,idx,key_tree->left,min_key,min_key_flag,
|
||||
max_key,max_key_flag);
|
||||
records=check_quick_keys(param, idx, key_tree->left,
|
||||
min_key, min_key_flag, min_keypart,
|
||||
max_key, max_key_flag, max_keypart);
|
||||
if (records == HA_POS_ERROR) // Impossible
|
||||
return records;
|
||||
}
|
||||
|
||||
tmp_min_key= min_key;
|
||||
tmp_max_key= max_key;
|
||||
key_tree->store(param->key[idx][key_tree->part].store_length,
|
||||
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
|
||||
min_key_length= (uint) (tmp_min_key- param->min_key);
|
||||
max_key_length= (uint) (tmp_max_key- param->max_key);
|
||||
tmp_min_keypart+= key_tree->store_min(param->key[idx][key_tree->part].store_length,
|
||||
&tmp_min_key, min_key_flag);
|
||||
tmp_max_keypart+= key_tree->store_max(param->key[idx][key_tree->part].store_length,
|
||||
&tmp_max_key, max_key_flag);
|
||||
min_key_length= (uint) (tmp_min_key - param->min_key);
|
||||
max_key_length= (uint) (tmp_max_key - param->max_key);
|
||||
|
||||
if (param->is_ror_scan)
|
||||
{
|
||||
@ -7158,12 +7175,13 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
|
||||
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
|
||||
{ // const key as prefix
|
||||
if (min_key_length == max_key_length &&
|
||||
!memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) &&
|
||||
!memcmp(min_key, max_key, (uint) (tmp_max_key - max_key)) &&
|
||||
!key_tree->min_flag && !key_tree->max_flag)
|
||||
{
|
||||
tmp=check_quick_keys(param,idx,key_tree->next_key_part,
|
||||
tmp_min_key, min_key_flag | key_tree->min_flag,
|
||||
tmp_max_key, max_key_flag | key_tree->max_flag);
|
||||
tmp=check_quick_keys(param,idx,key_tree->next_key_part, tmp_min_key,
|
||||
min_key_flag | key_tree->min_flag, tmp_min_keypart,
|
||||
tmp_max_key, max_key_flag | key_tree->max_flag,
|
||||
tmp_max_keypart);
|
||||
goto end; // Ugly, but efficient
|
||||
}
|
||||
else
|
||||
@ -7175,18 +7193,20 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
|
||||
tmp_min_flag=key_tree->min_flag;
|
||||
tmp_max_flag=key_tree->max_flag;
|
||||
if (!tmp_min_flag)
|
||||
tmp_min_keypart+=
|
||||
key_tree->next_key_part->store_min_key(param->key[idx], &tmp_min_key,
|
||||
&tmp_min_flag);
|
||||
if (!tmp_max_flag)
|
||||
tmp_max_keypart+=
|
||||
key_tree->next_key_part->store_max_key(param->key[idx], &tmp_max_key,
|
||||
&tmp_max_flag);
|
||||
min_key_length= (uint) (tmp_min_key- param->min_key);
|
||||
max_key_length= (uint) (tmp_max_key- param->max_key);
|
||||
min_key_length= (uint) (tmp_min_key - param->min_key);
|
||||
max_key_length= (uint) (tmp_max_key - param->max_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_min_flag=min_key_flag | key_tree->min_flag;
|
||||
tmp_max_flag=max_key_flag | key_tree->max_flag;
|
||||
tmp_min_flag= min_key_flag | key_tree->min_flag;
|
||||
tmp_max_flag= max_key_flag | key_tree->max_flag;
|
||||
}
|
||||
|
||||
keynr=param->real_keynr[idx];
|
||||
@ -7194,9 +7214,8 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
|
||||
if (!tmp_min_flag && ! tmp_max_flag &&
|
||||
(uint) key_tree->part+1 == param->table->key_info[keynr].key_parts &&
|
||||
(param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
|
||||
HA_NOSAME &&
|
||||
min_key_length == max_key_length &&
|
||||
!memcmp(param->min_key,param->max_key,min_key_length))
|
||||
HA_NOSAME && min_key_length == max_key_length &&
|
||||
!memcmp(param->min_key, param->max_key, min_key_length))
|
||||
{
|
||||
tmp=1; // Max one record
|
||||
param->n_ranges++;
|
||||
@ -7215,7 +7234,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
|
||||
first members of clustered primary key.
|
||||
*/
|
||||
if (!(min_key_length == max_key_length &&
|
||||
!memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) &&
|
||||
!memcmp(min_key, max_key, (uint) (tmp_max_key - max_key)) &&
|
||||
!key_tree->min_flag && !key_tree->max_flag &&
|
||||
is_key_scan_ror(param, keynr, key_tree->part + 1)))
|
||||
param->is_ror_scan= FALSE;
|
||||
@ -7227,11 +7246,12 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
|
||||
key_range min_range;
|
||||
min_range.key= (byte*) param->min_key;
|
||||
min_range.length= min_key_length;
|
||||
min_range.keypart_map= make_keypart_map(tmp_min_keypart);
|
||||
/* In this case tmp_min_flag contains the handler-read-function */
|
||||
min_range.flag= (ha_rkey_function) (tmp_min_flag ^ GEOM_FLAG);
|
||||
|
||||
tmp= param->table->file->records_in_range(keynr, &min_range,
|
||||
(key_range*) 0);
|
||||
tmp= param->table->file->records_in_range(keynr,
|
||||
&min_range, (key_range*) 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -7241,10 +7261,12 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
|
||||
min_range.length= min_key_length;
|
||||
min_range.flag= (tmp_min_flag & NEAR_MIN ? HA_READ_AFTER_KEY :
|
||||
HA_READ_KEY_EXACT);
|
||||
min_range.keypart_map= make_keypart_map(tmp_min_keypart);
|
||||
max_range.key= (byte*) param->max_key;
|
||||
max_range.length= max_key_length;
|
||||
max_range.flag= (tmp_max_flag & NEAR_MAX ?
|
||||
HA_READ_BEFORE_KEY : HA_READ_AFTER_KEY);
|
||||
max_range.keypart_map= make_keypart_map(tmp_max_keypart);
|
||||
tmp=param->table->file->records_in_range(keynr,
|
||||
(min_key_length ? &min_range :
|
||||
(key_range*) 0),
|
||||
@ -7265,8 +7287,9 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
|
||||
This is not a ROR scan if the key is not Clustered Primary Key.
|
||||
*/
|
||||
param->is_ror_scan= FALSE;
|
||||
tmp=check_quick_keys(param,idx,key_tree->right,min_key,min_key_flag,
|
||||
max_key,max_key_flag);
|
||||
tmp=check_quick_keys(param, idx, key_tree->right,
|
||||
min_key, min_key_flag, min_keypart,
|
||||
max_key, max_key_flag, max_keypart);
|
||||
if (tmp == HA_POS_ERROR)
|
||||
return tmp;
|
||||
records+=tmp;
|
||||
@ -7412,6 +7435,7 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
|
||||
{
|
||||
QUICK_RANGE *range;
|
||||
uint flag;
|
||||
int min_part= key_tree->part-1, max_part=key_tree->part-1;
|
||||
|
||||
if (key_tree->left != &null_element)
|
||||
{
|
||||
@ -7420,16 +7444,18 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
|
||||
return 1;
|
||||
}
|
||||
char *tmp_min_key=min_key,*tmp_max_key=max_key;
|
||||
key_tree->store(key[key_tree->part].store_length,
|
||||
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
|
||||
min_part+= key_tree->store_min(key[key_tree->part].store_length,
|
||||
&tmp_min_key,min_key_flag);
|
||||
max_part+= key_tree->store_max(key[key_tree->part].store_length,
|
||||
&tmp_max_key,max_key_flag);
|
||||
|
||||
if (key_tree->next_key_part &&
|
||||
key_tree->next_key_part->part == key_tree->part+1 &&
|
||||
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
|
||||
{ // const key as prefix
|
||||
if (!((tmp_min_key - min_key) != (tmp_max_key - max_key) ||
|
||||
memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) ||
|
||||
key_tree->min_flag || key_tree->max_flag))
|
||||
if ((tmp_min_key - min_key) == (tmp_max_key - max_key) &&
|
||||
memcmp(min_key, max_key, (uint)(tmp_max_key - max_key))==0 &&
|
||||
key_tree->min_flag==0 && key_tree->max_flag==0)
|
||||
{
|
||||
if (get_quick_keys(param,quick,key,key_tree->next_key_part,
|
||||
tmp_min_key, min_key_flag | key_tree->min_flag,
|
||||
@ -7440,11 +7466,15 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
|
||||
{
|
||||
uint tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag;
|
||||
if (!tmp_min_flag)
|
||||
key_tree->next_key_part->store_min_key(key, &tmp_min_key,
|
||||
{
|
||||
min_part+= key_tree->next_key_part->store_min_key(key, &tmp_min_key,
|
||||
&tmp_min_flag);
|
||||
}
|
||||
if (!tmp_max_flag)
|
||||
key_tree->next_key_part->store_max_key(key, &tmp_max_key,
|
||||
{
|
||||
max_part+= key_tree->next_key_part->store_max_key(key, &tmp_max_key,
|
||||
&tmp_max_flag);
|
||||
}
|
||||
flag=tmp_min_flag | tmp_max_flag;
|
||||
}
|
||||
}
|
||||
@ -7494,13 +7524,15 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
|
||||
/* Get range for retrieving rows in QUICK_SELECT::get_next */
|
||||
if (!(range= new QUICK_RANGE((const char *) param->min_key,
|
||||
(uint) (tmp_min_key - param->min_key),
|
||||
min_part >=0 ? make_keypart_map(min_part) : 0,
|
||||
(const char *) param->max_key,
|
||||
(uint) (tmp_max_key - param->max_key),
|
||||
max_part >=0 ? make_keypart_map(max_part) : 0,
|
||||
flag)))
|
||||
return 1; // out of memory
|
||||
|
||||
set_if_bigger(quick->max_used_key_length,range->min_length);
|
||||
set_if_bigger(quick->max_used_key_length,range->max_length);
|
||||
set_if_bigger(quick->max_used_key_length, range->min_length);
|
||||
set_if_bigger(quick->max_used_key_length, range->max_length);
|
||||
set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1);
|
||||
if (insert_dynamic(&quick->ranges, (gptr)&range))
|
||||
return 1;
|
||||
@ -7642,6 +7674,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
||||
|
||||
range->min_key=range->max_key=(char*) ref->key_buff;
|
||||
range->min_length=range->max_length=ref->key_length;
|
||||
range->min_keypart_map= range->max_keypart_map= (1 << ref->key_parts) - 1;
|
||||
range->flag= ((ref->key_length == key_info->key_length &&
|
||||
(key_info->flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
|
||||
HA_NOSAME) ? EQ_RANGE : 0);
|
||||
@ -7675,8 +7708,10 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
||||
*ref->null_ref_key= 1; // Set null byte then create a range
|
||||
if (!(null_range= new (alloc) QUICK_RANGE((char*)ref->key_buff,
|
||||
ref->key_length,
|
||||
(1 << ref->key_parts) - 1,
|
||||
(char*)ref->key_buff,
|
||||
ref->key_length,
|
||||
(1 << ref->key_parts) - 1,
|
||||
EQ_RANGE)))
|
||||
goto err;
|
||||
*ref->null_ref_key= 0; // Clear null byte
|
||||
@ -8129,6 +8164,7 @@ int QUICK_RANGE_SELECT::get_next()
|
||||
start_key->flag= ((range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
|
||||
(range->flag & EQ_RANGE) ?
|
||||
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
|
||||
start_key->keypart_map= range->min_keypart_map;
|
||||
end_key->key= (const byte*) range->max_key;
|
||||
end_key->length= range->max_length;
|
||||
/*
|
||||
@ -8137,6 +8173,7 @@ int QUICK_RANGE_SELECT::get_next()
|
||||
*/
|
||||
end_key->flag= (range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
|
||||
HA_READ_AFTER_KEY);
|
||||
end_key->keypart_map= range->max_keypart_map;
|
||||
|
||||
mrange_slot->range_flag= range->flag;
|
||||
}
|
||||
@ -8186,7 +8223,9 @@ end:
|
||||
other if some error occurred
|
||||
*/
|
||||
|
||||
int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix)
|
||||
int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length,
|
||||
ulonglong keypart_map,
|
||||
byte *cur_prefix)
|
||||
{
|
||||
DBUG_ENTER("QUICK_RANGE_SELECT::get_next_prefix");
|
||||
|
||||
@ -8198,8 +8237,7 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix)
|
||||
{
|
||||
/* Read the next record in the same range with prefix after cur_prefix. */
|
||||
DBUG_ASSERT(cur_prefix != 0);
|
||||
result= file->index_read(record, cur_prefix, prefix_length,
|
||||
HA_READ_AFTER_KEY);
|
||||
result= file->index_read(record, cur_prefix, keypart_map, HA_READ_AFTER_KEY);
|
||||
if (result || (file->compare_key(file->end_range) <= 0))
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
@ -8215,11 +8253,13 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix)
|
||||
|
||||
start_key.key= (const byte*) range->min_key;
|
||||
start_key.length= min(range->min_length, prefix_length);
|
||||
start_key.keypart_map= range->min_keypart_map & keypart_map;
|
||||
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= min(range->max_length, prefix_length);
|
||||
end_key.keypart_map= range->max_keypart_map & keypart_map;
|
||||
/*
|
||||
We use READ_AFTER_KEY here because if we are reading on a key
|
||||
prefix we want to find all keys with this prefix
|
||||
@ -8227,8 +8267,8 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_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,
|
||||
result= file->read_range_first(range->min_keypart_map ? &start_key : 0,
|
||||
range->max_keypart_map ? &end_key : 0,
|
||||
test(range->flag & EQ_RANGE),
|
||||
sorted);
|
||||
if (range->flag == (UNIQUE_RANGE | EQ_RANGE))
|
||||
@ -8268,9 +8308,8 @@ int QUICK_RANGE_SELECT_GEOM::get_next()
|
||||
}
|
||||
range= *(cur_range++);
|
||||
|
||||
result= file->index_read(record,
|
||||
(byte*) range->min_key,
|
||||
range->min_length,
|
||||
result= file->index_read(record, (byte*) range->min_key,
|
||||
range->min_keypart_map,
|
||||
(ha_rkey_function)(range->flag ^ GEOM_FLAG));
|
||||
if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
|
||||
DBUG_RETURN(result);
|
||||
@ -8403,13 +8442,13 @@ int QUICK_SELECT_DESC::get_next()
|
||||
if (range->flag & EQ_RANGE)
|
||||
{
|
||||
result = file->index_read(record, (byte*) range->max_key,
|
||||
range->max_length, HA_READ_KEY_EXACT);
|
||||
range->max_keypart_map, HA_READ_KEY_EXACT);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(range->flag & NEAR_MAX || range_reads_after_key(range));
|
||||
result=file->index_read(record, (byte*) range->max_key,
|
||||
range->max_length,
|
||||
range->max_keypart_map,
|
||||
((range->flag & NEAR_MAX) ?
|
||||
HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV));
|
||||
}
|
||||
@ -8728,8 +8767,7 @@ void QUICK_ROR_UNION_SELECT::add_keys_and_lengths(String *key_names,
|
||||
static inline uint get_field_keypart(KEY *index, Field *field);
|
||||
static inline SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree,
|
||||
PARAM *param, uint *param_idx);
|
||||
static bool
|
||||
get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
|
||||
static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
|
||||
KEY_PART_INFO *first_non_group_part,
|
||||
KEY_PART_INFO *min_max_arg_part,
|
||||
KEY_PART_INFO *last_part, THD *thd,
|
||||
@ -9127,7 +9165,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
|
||||
NULL;
|
||||
first_non_infix_part= min_max_arg_part ?
|
||||
(min_max_arg_part < last_part) ?
|
||||
min_max_arg_part + 1 :
|
||||
min_max_arg_part :
|
||||
NULL :
|
||||
NULL;
|
||||
if (first_non_group_part &&
|
||||
@ -9184,7 +9222,9 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
|
||||
*/
|
||||
if (first_non_infix_part)
|
||||
{
|
||||
for (cur_part= first_non_infix_part; cur_part != last_part; cur_part++)
|
||||
cur_part= first_non_infix_part +
|
||||
(min_max_arg_part && (min_max_arg_part < last_part));
|
||||
for (; cur_part != last_part; cur_part++)
|
||||
{
|
||||
if (bitmap_is_set(table->read_set, cur_part->field->field_index))
|
||||
goto next_index;
|
||||
@ -9730,7 +9770,7 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
|
||||
|
||||
RETURN
|
||||
New QUICK_GROUP_MIN_MAX_SELECT object if successfully created,
|
||||
NULL o/w.
|
||||
NULL otherwise.
|
||||
*/
|
||||
|
||||
QUICK_SELECT_I *
|
||||
@ -9743,10 +9783,10 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
|
||||
quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table,
|
||||
param->thd->lex->current_select->join,
|
||||
have_min, have_max, min_max_arg_part,
|
||||
group_prefix_len, used_key_parts,
|
||||
index_info, index, read_cost, records,
|
||||
key_infix_len, key_infix,
|
||||
parent_alloc);
|
||||
group_prefix_len, group_key_parts,
|
||||
used_key_parts, index_info, index,
|
||||
read_cost, records, key_infix_len,
|
||||
key_infix, parent_alloc);
|
||||
if (!quick)
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
@ -9835,7 +9875,7 @@ QUICK_GROUP_MIN_MAX_SELECT::
|
||||
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
|
||||
bool have_max_arg,
|
||||
KEY_PART_INFO *min_max_arg_part_arg,
|
||||
uint group_prefix_len_arg,
|
||||
uint group_prefix_len_arg, uint group_key_parts_arg,
|
||||
uint used_key_parts_arg, KEY *index_info_arg,
|
||||
uint use_index, double read_cost_arg,
|
||||
ha_rows records_arg, uint key_infix_len_arg,
|
||||
@ -9845,7 +9885,7 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
|
||||
have_max(have_max_arg), seen_first_key(FALSE),
|
||||
min_max_arg_part(min_max_arg_part_arg), key_infix(key_infix_arg),
|
||||
key_infix_len(key_infix_len_arg), min_functions_it(NULL),
|
||||
max_functions_it(NULL)
|
||||
max_functions_it(NULL), group_key_parts(group_key_parts_arg)
|
||||
{
|
||||
head= table;
|
||||
file= head->file;
|
||||
@ -9855,6 +9895,7 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
|
||||
read_time= read_cost_arg;
|
||||
records= records_arg;
|
||||
used_key_parts= used_key_parts_arg;
|
||||
real_key_parts= used_key_parts_arg;
|
||||
real_prefix_len= group_prefix_len + key_infix_len;
|
||||
group_prefix= NULL;
|
||||
min_max_arg_len= min_max_arg_part ? min_max_arg_part->store_length : 0;
|
||||
@ -10021,7 +10062,9 @@ bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
|
||||
range_flag|= EQ_RANGE; /* equality condition */
|
||||
}
|
||||
range= new QUICK_RANGE(sel_range->min_value, min_max_arg_len,
|
||||
make_keypart_map(sel_range->part),
|
||||
sel_range->max_value, min_max_arg_len,
|
||||
make_keypart_map(sel_range->part),
|
||||
range_flag);
|
||||
if (!range)
|
||||
return TRUE;
|
||||
@ -10256,7 +10299,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next()
|
||||
first sub-group with the extended prefix.
|
||||
*/
|
||||
if (!have_min && !have_max && key_infix_len > 0)
|
||||
result= file->index_read(record, group_prefix, real_prefix_len,
|
||||
result= file->index_read(record, group_prefix,
|
||||
make_prev_keypart_map(real_key_parts),
|
||||
HA_READ_KEY_EXACT);
|
||||
|
||||
result= have_min ? min_res : have_max ? max_res : result;
|
||||
@ -10319,7 +10363,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
|
||||
/* Apply the constant equality conditions to the non-group select fields */
|
||||
if (key_infix_len > 0)
|
||||
{
|
||||
if ((result= file->index_read(record, group_prefix, real_prefix_len,
|
||||
if ((result= file->index_read(record, group_prefix,
|
||||
make_prev_keypart_map(real_key_parts),
|
||||
HA_READ_KEY_EXACT)))
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
@ -10336,7 +10381,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
|
||||
/* Find the first subsequent record without NULL in the MIN/MAX field. */
|
||||
key_copy(tmp_record, record, index_info, 0);
|
||||
result= file->index_read(record, tmp_record,
|
||||
real_prefix_len + min_max_arg_len,
|
||||
make_keypart_map(real_key_parts),
|
||||
HA_READ_AFTER_KEY);
|
||||
/*
|
||||
Check if the new record belongs to the current group by comparing its
|
||||
@ -10392,7 +10437,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max()
|
||||
if (min_max_ranges.elements > 0)
|
||||
result= next_max_in_range();
|
||||
else
|
||||
result= file->index_read(record, group_prefix, real_prefix_len,
|
||||
result= file->index_read(record, group_prefix,
|
||||
make_prev_keypart_map(real_key_parts),
|
||||
HA_READ_PREFIX_LAST);
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
@ -10428,7 +10474,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
|
||||
{
|
||||
byte *cur_prefix= seen_first_key ? group_prefix : NULL;
|
||||
if ((result= quick_prefix_select->get_next_prefix(group_prefix_len,
|
||||
cur_prefix)))
|
||||
(ULL(1) << group_key_parts) - 1, cur_prefix)))
|
||||
DBUG_RETURN(result);
|
||||
seen_first_key= TRUE;
|
||||
}
|
||||
@ -10444,7 +10490,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
|
||||
else
|
||||
{
|
||||
/* Load the first key in this group into record. */
|
||||
result= file->index_read(record, group_prefix, group_prefix_len,
|
||||
result= file->index_read(record, group_prefix,
|
||||
make_prev_keypart_map(group_key_parts),
|
||||
HA_READ_AFTER_KEY);
|
||||
if (result)
|
||||
DBUG_RETURN(result);
|
||||
@ -10487,6 +10534,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
|
||||
{
|
||||
ha_rkey_function find_flag;
|
||||
uint search_prefix_len;
|
||||
ulonglong keypart_map;
|
||||
QUICK_RANGE *cur_range;
|
||||
bool found_null= FALSE;
|
||||
int result= HA_ERR_KEY_NOT_FOUND;
|
||||
@ -10508,8 +10556,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
|
||||
|
||||
if (cur_range->flag & NO_MIN_RANGE)
|
||||
{
|
||||
find_flag= HA_READ_KEY_EXACT;
|
||||
search_prefix_len= real_prefix_len;
|
||||
keypart_map= (ULL(1) << real_key_parts) - 1;
|
||||
find_flag= HA_READ_KEY_EXACT;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -10517,13 +10566,13 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
|
||||
memcpy(group_prefix + real_prefix_len, cur_range->min_key,
|
||||
cur_range->min_length);
|
||||
search_prefix_len= real_prefix_len + min_max_arg_len;
|
||||
keypart_map= (ULL(2) << real_key_parts) - 1;
|
||||
find_flag= (cur_range->flag & (EQ_RANGE | NULL_RANGE)) ?
|
||||
HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MIN) ?
|
||||
HA_READ_AFTER_KEY : HA_READ_KEY_OR_NEXT;
|
||||
}
|
||||
|
||||
result= file->index_read(record, group_prefix, search_prefix_len,
|
||||
find_flag);
|
||||
result= file->index_read(record, group_prefix, keypart_map, find_flag);
|
||||
if (result)
|
||||
{
|
||||
if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
|
||||
@ -10621,6 +10670,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
|
||||
{
|
||||
ha_rkey_function find_flag;
|
||||
uint search_prefix_len;
|
||||
ulonglong keypart_map;
|
||||
QUICK_RANGE *cur_range;
|
||||
int result;
|
||||
|
||||
@ -10642,8 +10692,9 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
|
||||
|
||||
if (cur_range->flag & NO_MAX_RANGE)
|
||||
{
|
||||
find_flag= HA_READ_PREFIX_LAST;
|
||||
search_prefix_len= real_prefix_len;
|
||||
keypart_map= (ULL(1) << real_key_parts) - 1;
|
||||
find_flag= HA_READ_PREFIX_LAST;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -10651,13 +10702,13 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
|
||||
memcpy(group_prefix + real_prefix_len, cur_range->max_key,
|
||||
cur_range->max_length);
|
||||
search_prefix_len= real_prefix_len + min_max_arg_len;
|
||||
keypart_map= (ULL(2) << real_key_parts) - 1;
|
||||
find_flag= (cur_range->flag & EQ_RANGE) ?
|
||||
HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MAX) ?
|
||||
HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV;
|
||||
}
|
||||
|
||||
result= file->index_read(record, group_prefix, search_prefix_len,
|
||||
find_flag);
|
||||
result= file->index_read(record, group_prefix, keypart_map, find_flag);
|
||||
|
||||
if (result)
|
||||
{
|
||||
|
@ -37,17 +37,22 @@ class QUICK_RANGE :public Sql_alloc {
|
||||
public:
|
||||
char *min_key,*max_key;
|
||||
uint16 min_length,max_length,flag;
|
||||
ulonglong min_keypart_map, max_keypart_map;
|
||||
#ifdef HAVE_purify
|
||||
uint16 dummy; /* Avoid warnings on 'flag' */
|
||||
#endif
|
||||
QUICK_RANGE(); /* Full range */
|
||||
QUICK_RANGE(const char *min_key_arg,uint min_length_arg,
|
||||
const char *max_key_arg,uint max_length_arg,
|
||||
QUICK_RANGE(const char *min_key_arg, uint min_length_arg,
|
||||
ulonglong min_keypart_map_arg,
|
||||
const char *max_key_arg, uint max_length_arg,
|
||||
ulonglong max_keypart_map_arg,
|
||||
uint flag_arg)
|
||||
: min_key((char*) sql_memdup(min_key_arg,min_length_arg+1)),
|
||||
max_key((char*) sql_memdup(max_key_arg,max_length_arg+1)),
|
||||
min_length((uint16) min_length_arg),
|
||||
max_length((uint16) max_length_arg),
|
||||
min_keypart_map(min_keypart_map_arg),
|
||||
max_keypart_map(max_keypart_map_arg),
|
||||
flag((uint16) flag_arg)
|
||||
{
|
||||
#ifdef HAVE_purify
|
||||
@ -318,7 +323,8 @@ public:
|
||||
int reset(void);
|
||||
int get_next();
|
||||
void range_end();
|
||||
int get_next_prefix(uint prefix_length, byte *cur_prefix);
|
||||
int get_next_prefix(uint prefix_length, ulonglong keypart_map,
|
||||
byte *cur_prefix);
|
||||
bool reverse_sorted() { return 0; }
|
||||
bool unique_key_range();
|
||||
int init_ror_merged_scan(bool reuse_handler);
|
||||
@ -605,6 +611,7 @@ private:
|
||||
byte *tmp_record; /* Temporary storage for next_min(), next_max(). */
|
||||
byte *group_prefix; /* Key prefix consisting of the GROUP fields. */
|
||||
uint group_prefix_len; /* Length of the group prefix. */
|
||||
uint group_key_parts;
|
||||
byte *last_prefix; /* Prefix of the last group for detecting EOF. */
|
||||
bool have_min; /* Specify whether we are computing */
|
||||
bool have_max; /* a MIN, a MAX, or both. */
|
||||
@ -616,6 +623,7 @@ private:
|
||||
uint key_infix_len;
|
||||
DYNAMIC_ARRAY min_max_ranges; /* Array of range ptrs for the MIN/MAX field. */
|
||||
uint real_prefix_len; /* Length of key prefix extended with key_infix. */
|
||||
uint real_key_parts;
|
||||
List<Item_sum> *min_functions;
|
||||
List<Item_sum> *max_functions;
|
||||
List_iterator<Item_sum> *min_functions_it;
|
||||
@ -638,10 +646,11 @@ private:
|
||||
public:
|
||||
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join, bool have_min,
|
||||
bool have_max, KEY_PART_INFO *min_max_arg_part,
|
||||
uint group_prefix_len, uint used_key_parts,
|
||||
KEY *index_info, uint use_index, double read_cost,
|
||||
ha_rows records, uint key_infix_len,
|
||||
byte *key_infix, MEM_ROOT *parent_alloc);
|
||||
uint group_prefix_len, uint group_key_parts,
|
||||
uint used_key_parts, KEY *index_info, uint
|
||||
use_index, double read_cost, ha_rows records, uint
|
||||
key_infix_len, byte *key_infix, MEM_ROOT
|
||||
*parent_alloc);
|
||||
~QUICK_GROUP_MIN_MAX_SELECT();
|
||||
bool add_range(SEL_ARG *sel_range);
|
||||
void update_key_stat();
|
||||
|
@ -251,7 +251,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
|
||||
error= table->file->index_first(table->record[0]);
|
||||
else
|
||||
error= table->file->index_read(table->record[0],key_buff,
|
||||
ref.key_length,
|
||||
make_prev_keypart_map(ref.key_parts),
|
||||
range_fl & NEAR_MIN ?
|
||||
HA_READ_AFTER_KEY :
|
||||
HA_READ_KEY_OR_NEXT);
|
||||
@ -338,11 +338,11 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
|
||||
error= table->file->index_last(table->record[0]);
|
||||
else
|
||||
error= table->file->index_read(table->record[0], key_buff,
|
||||
ref.key_length,
|
||||
make_prev_keypart_map(ref.key_parts),
|
||||
range_fl & NEAR_MAX ?
|
||||
HA_READ_BEFORE_KEY :
|
||||
HA_READ_PREFIX_LAST_OR_PREV);
|
||||
if (!error && reckey_in_range(1, &ref, item_field->field,
|
||||
if (!error && reckey_in_range(1, &ref, item_field->field,
|
||||
conds, range_fl, prefix_len))
|
||||
error= HA_ERR_KEY_NOT_FOUND;
|
||||
if (table->key_read)
|
||||
@ -605,15 +605,13 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
|
||||
/* Check if field is part of the tested partial key */
|
||||
byte *key_ptr= ref->key_buff;
|
||||
KEY_PART_INFO *part;
|
||||
for (part= keyinfo->key_part;
|
||||
;
|
||||
key_ptr+= part++->store_length)
|
||||
for (part= keyinfo->key_part; ; key_ptr+= part++->store_length)
|
||||
|
||||
{
|
||||
if (part > field_part)
|
||||
return 0; // Field is beyond the tested parts
|
||||
if (part->field->eq(((Item_field*) args[0])->field))
|
||||
break; // Found a part od the key for the field
|
||||
break; // Found a part of the key for the field
|
||||
}
|
||||
|
||||
bool is_field_part= part == field_part;
|
||||
@ -625,8 +623,11 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
|
||||
{
|
||||
uint length= (key_ptr-ref->key_buff)+part->store_length;
|
||||
if (ref->key_length < length)
|
||||
{
|
||||
/* Ultimately ref->key_length will contain the length of the search key */
|
||||
ref->key_length= length;
|
||||
ref->key_parts= (part - keyinfo->key_part) + 1;
|
||||
}
|
||||
if (!*prefix_len && part+1 == field_part)
|
||||
*prefix_len= length;
|
||||
if (is_field_part && eq_type)
|
||||
@ -773,6 +774,7 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
|
||||
{
|
||||
ref->key= idx;
|
||||
ref->key_length= 0;
|
||||
ref->key_parts= 0;
|
||||
key_part_map key_part_used= 0;
|
||||
*range_fl= NO_MIN_RANGE | NO_MAX_RANGE;
|
||||
if (matching_cond(max_fl, ref, keyinfo, part, cond,
|
||||
@ -788,6 +790,8 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
|
||||
*/
|
||||
ref->key_buff[ref->key_length]= 1;
|
||||
ref->key_length+= part->store_length;
|
||||
ref->key_parts++;
|
||||
DBUG_ASSERT(ref->key_parts == jdx+1);
|
||||
*range_fl&= ~NO_MIN_RANGE;
|
||||
*range_fl|= NEAR_MIN; // > NULL
|
||||
}
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "rpl_tblmap.h"
|
||||
|
||||
int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
|
||||
static Log_event* next_event(RELAY_LOG_INFO* rli);
|
||||
|
||||
|
||||
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
|
||||
|
||||
|
@ -111,8 +111,6 @@ extern ulonglong relay_log_space_limit;
|
||||
#define MYSQL_SLAVE_RUN_NOT_CONNECT 1
|
||||
#define MYSQL_SLAVE_RUN_CONNECT 2
|
||||
|
||||
static Log_event* next_event(RELAY_LOG_INFO* rli);
|
||||
|
||||
#define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\
|
||||
"FIRST")
|
||||
#define IO_RPL_LOG_NAME (mi->master_log_name[0] ? mi->master_log_name :\
|
||||
|
@ -218,8 +218,7 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table)
|
||||
key_copy(key, table->record[0], table->key_info,
|
||||
table->key_info->key_length);
|
||||
|
||||
if (table->file->index_read_idx(table->record[0], 0,
|
||||
key, table->key_info->key_length,
|
||||
if (table->file->index_read_idx(table->record[0], 0, key, ~ULL(0),
|
||||
HA_READ_KEY_EXACT))
|
||||
DBUG_RETURN(SP_KEY_NOT_FOUND);
|
||||
|
||||
@ -494,8 +493,6 @@ db_create_routine(THD *thd, int type, sp_head *sp)
|
||||
int ret;
|
||||
TABLE *table;
|
||||
char definer[USER_HOST_BUFF_SIZE];
|
||||
char old_db_buf[NAME_LEN+1];
|
||||
LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) };
|
||||
DBUG_ENTER("db_create_routine");
|
||||
DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length,
|
||||
sp->m_name.str));
|
||||
@ -906,7 +903,7 @@ sp_drop_db_routines(THD *thd, char *db)
|
||||
table->file->ha_index_init(0, 1);
|
||||
if (! table->file->index_read(table->record[0],
|
||||
(byte *)table->field[MYSQL_PROC_FIELD_DB]->ptr,
|
||||
key_len, HA_READ_KEY_EXACT))
|
||||
(ulonglong)1, HA_READ_KEY_EXACT))
|
||||
{
|
||||
int nxtres;
|
||||
bool deleted= FALSE;
|
||||
|
@ -1813,8 +1813,7 @@ static bool update_user_table(THD *thd, TABLE *table,
|
||||
table->key_info->key_length);
|
||||
|
||||
if (table->file->index_read_idx(table->record[0], 0,
|
||||
(byte *) user_key,
|
||||
table->key_info->key_length,
|
||||
(byte *) user_key, ~ULL(0),
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH),
|
||||
@ -1905,8 +1904,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
|
||||
key_copy(user_key, table->record[0], table->key_info,
|
||||
table->key_info->key_length);
|
||||
|
||||
if (table->file->index_read_idx(table->record[0], 0,
|
||||
user_key, table->key_info->key_length,
|
||||
if (table->file->index_read_idx(table->record[0], 0, user_key, ~ULL(0),
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
/* what == 'N' means revoke */
|
||||
@ -2123,8 +2121,7 @@ static int replace_db_table(TABLE *table, const char *db,
|
||||
key_copy(user_key, table->record[0], table->key_info,
|
||||
table->key_info->key_length);
|
||||
|
||||
if (table->file->index_read_idx(table->record[0],0,
|
||||
user_key, table->key_info->key_length,
|
||||
if (table->file->index_read_idx(table->record[0],0, user_key, ~ULL(0),
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
if (what == 'N')
|
||||
@ -2341,9 +2338,8 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
|
||||
col_privs->field[4]->store("",0, &my_charset_latin1);
|
||||
|
||||
col_privs->file->ha_index_init(0, 1);
|
||||
if (col_privs->file->index_read(col_privs->record[0],
|
||||
(byte*) key,
|
||||
key_prefix_len, HA_READ_KEY_EXACT))
|
||||
if (col_privs->file->index_read(col_privs->record[0], (byte*) key,
|
||||
(ulonglong)15, HA_READ_KEY_EXACT))
|
||||
{
|
||||
cols = 0; /* purecov: deadcode */
|
||||
col_privs->file->ha_index_end();
|
||||
@ -2479,7 +2475,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
|
||||
table->field[3]->store(table_name,(uint) strlen(table_name),
|
||||
system_charset_info);
|
||||
|
||||
/* Get length of 3 first key parts */
|
||||
/* Get length of 4 first key parts */
|
||||
key_prefix_length= (key_part[0].store_length + key_part[1].store_length +
|
||||
key_part[2].store_length + key_part[3].store_length);
|
||||
key_copy(key, table->record[0], table->key_info, key_prefix_length);
|
||||
@ -2505,8 +2501,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
|
||||
key_copy(user_key, table->record[0], table->key_info,
|
||||
table->key_info->key_length);
|
||||
|
||||
if (table->file->index_read(table->record[0], user_key,
|
||||
table->key_info->key_length,
|
||||
if (table->file->index_read(table->record[0], user_key, ~(ulonglong)0,
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
if (revoke_grant)
|
||||
@ -2582,8 +2577,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
|
||||
key_copy(user_key, table->record[0], table->key_info,
|
||||
key_prefix_length);
|
||||
|
||||
if (table->file->index_read(table->record[0], user_key,
|
||||
key_prefix_length,
|
||||
if (table->file->index_read(table->record[0], user_key, (ulonglong)15,
|
||||
HA_READ_KEY_EXACT))
|
||||
goto end;
|
||||
|
||||
@ -2684,8 +2678,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
|
||||
key_copy(user_key, table->record[0], table->key_info,
|
||||
table->key_info->key_length);
|
||||
|
||||
if (table->file->index_read_idx(table->record[0], 0,
|
||||
user_key, table->key_info->key_length,
|
||||
if (table->file->index_read_idx(table->record[0], 0, user_key, ~ULL(0),
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
/*
|
||||
@ -2808,8 +2801,8 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
|
||||
TRUE);
|
||||
store_record(table,record[1]); // store at pos 1
|
||||
|
||||
if (table->file->index_read_idx(table->record[0],0,
|
||||
(byte*) table->field[0]->ptr,0,
|
||||
if (table->file->index_read_idx(table->record[0], 0,
|
||||
(byte*) table->field[0]->ptr, ~ULL(0),
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
/*
|
||||
@ -4987,7 +4980,7 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop,
|
||||
key_copy(user_key, table->record[0], table->key_info, key_prefix_length);
|
||||
|
||||
if ((error= table->file->index_read_idx(table->record[0], 0,
|
||||
user_key, key_prefix_length,
|
||||
user_key, ULL(3),
|
||||
HA_READ_KEY_EXACT)))
|
||||
{
|
||||
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
||||
|
@ -515,7 +515,8 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||
}
|
||||
List_iterator<Item> it_ke(*key_expr);
|
||||
Item *item;
|
||||
for (key_len=0 ; (item=it_ke++) ; key_part++)
|
||||
ulonglong keypart_map;
|
||||
for (keypart_map= key_len=0 ; (item=it_ke++) ; key_part++)
|
||||
{
|
||||
my_bitmap_map *old_map;
|
||||
// 'item' can be changed by fix_fields() call
|
||||
@ -532,6 +533,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||
(void) item->save_in_field(key_part->field, 1);
|
||||
dbug_tmp_restore_column_map(table->write_set, old_map);
|
||||
key_len+=key_part->store_length;
|
||||
keypart_map= (keypart_map << 1) | 1;
|
||||
}
|
||||
|
||||
if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len))))
|
||||
@ -540,7 +542,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||
table->file->ha_index_init(keyno, 1);
|
||||
key_copy(key, table->record[0], table->key_info + keyno, key_len);
|
||||
error= table->file->index_read(table->record[0],
|
||||
key,key_len,ha_rkey_mode);
|
||||
key, keypart_map, ha_rkey_mode);
|
||||
mode=rkey_to_rnext[(int)ha_rkey_mode];
|
||||
break;
|
||||
}
|
||||
|
@ -295,8 +295,7 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
|
||||
rkey_id->store((longlong) key_id, TRUE);
|
||||
rkey_id->get_key_image(buff, rkey_id->pack_length(), Field::itRAW);
|
||||
int key_res= relations->file->index_read(relations->record[0],
|
||||
(byte *) buff,
|
||||
rkey_id->pack_length(),
|
||||
(byte *) buff, (ulonglong)1,
|
||||
HA_READ_KEY_EXACT);
|
||||
|
||||
for ( ;
|
||||
@ -310,7 +309,7 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
|
||||
field->get_key_image(topic_id_buff, field->pack_length(), Field::itRAW);
|
||||
|
||||
if (!topics->file->index_read(topics->record[0], (byte *)topic_id_buff,
|
||||
field->pack_length(), HA_READ_KEY_EXACT))
|
||||
(ulonglong)1, HA_READ_KEY_EXACT))
|
||||
{
|
||||
memorize_variant_topic(thd,topics,count,find_fields,
|
||||
names,name,description,example);
|
||||
|
@ -1165,9 +1165,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
}
|
||||
key_copy((byte*) key,table->record[0],table->key_info+key_nr,0);
|
||||
if ((error=(table->file->index_read_idx(table->record[1],key_nr,
|
||||
(byte*) key,
|
||||
table->key_info[key_nr].
|
||||
key_length,
|
||||
(byte*) key, ~ULL(0),
|
||||
HA_READ_KEY_EXACT))))
|
||||
goto err;
|
||||
}
|
||||
|
@ -921,8 +921,7 @@ my_bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name)
|
||||
table->use_all_columns();
|
||||
table->field[0]->store(name->str, name->length, system_charset_info);
|
||||
if (! table->file->index_read_idx(table->record[0], 0,
|
||||
(byte *)table->field[0]->ptr,
|
||||
table->key_info[0].key_length,
|
||||
(byte *)table->field[0]->ptr, ~ULL(0),
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
int error;
|
||||
|
@ -10854,7 +10854,8 @@ int safe_index_read(JOIN_TAB *tab)
|
||||
TABLE *table= tab->table;
|
||||
if ((error=table->file->index_read(table->record[0],
|
||||
tab->ref.key_buff,
|
||||
tab->ref.key_length, HA_READ_KEY_EXACT)))
|
||||
tab_to_keypart_map(tab),
|
||||
HA_READ_KEY_EXACT)))
|
||||
return report_error(table, error);
|
||||
return 0;
|
||||
}
|
||||
@ -10992,7 +10993,8 @@ join_read_const(JOIN_TAB *tab)
|
||||
{
|
||||
error=table->file->index_read_idx(table->record[0],tab->ref.key,
|
||||
(byte*) tab->ref.key_buff,
|
||||
tab->ref.key_length,HA_READ_KEY_EXACT);
|
||||
tab_to_keypart_map(tab),
|
||||
HA_READ_KEY_EXACT);
|
||||
}
|
||||
if (error)
|
||||
{
|
||||
@ -11035,7 +11037,8 @@ join_read_key(JOIN_TAB *tab)
|
||||
}
|
||||
error=table->file->index_read(table->record[0],
|
||||
tab->ref.key_buff,
|
||||
tab->ref.key_length,HA_READ_KEY_EXACT);
|
||||
tab_to_keypart_map(tab),
|
||||
HA_READ_KEY_EXACT);
|
||||
if (error && error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
||||
return report_error(table, error);
|
||||
}
|
||||
@ -11063,7 +11066,8 @@ join_read_always_key(JOIN_TAB *tab)
|
||||
return -1;
|
||||
if ((error=table->file->index_read(table->record[0],
|
||||
tab->ref.key_buff,
|
||||
tab->ref.key_length,HA_READ_KEY_EXACT)))
|
||||
tab_to_keypart_map(tab),
|
||||
HA_READ_KEY_EXACT)))
|
||||
{
|
||||
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
||||
return report_error(table, error);
|
||||
@ -11090,7 +11094,7 @@ join_read_last_key(JOIN_TAB *tab)
|
||||
return -1;
|
||||
if ((error=table->file->index_read_last(table->record[0],
|
||||
tab->ref.key_buff,
|
||||
tab->ref.key_length)))
|
||||
tab_to_keypart_map(tab))))
|
||||
{
|
||||
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
||||
return report_error(table, error);
|
||||
@ -11631,7 +11635,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
|
||||
group->buff[-1]= (char) group->field->is_null();
|
||||
}
|
||||
if (!table->file->index_read(table->record[1],
|
||||
join->tmp_table_param.group_buff,0,
|
||||
join->tmp_table_param.group_buff, ~(ulonglong)0,
|
||||
HA_READ_KEY_EXACT))
|
||||
{ /* Update old record */
|
||||
restore_record(table,record[1]);
|
||||
|
@ -202,6 +202,11 @@ typedef struct st_join_table {
|
||||
}
|
||||
} JOIN_TAB;
|
||||
|
||||
static inline ulonglong tab_to_keypart_map(JOIN_TAB *tab)
|
||||
{
|
||||
return (ULL(1) << tab->ref.key_parts) - 1;
|
||||
}
|
||||
|
||||
enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool
|
||||
end_of_records);
|
||||
enum_nested_loop_state sub_select(JOIN *join,JOIN_TAB *join_tab, bool
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "sp_head.h"
|
||||
#include "sp.h"
|
||||
|
||||
static my_bool servers_load(THD *thd, TABLE_LIST *tables);
|
||||
HASH servers_cache;
|
||||
pthread_mutex_t servers_cache_mutex; // To init the hash
|
||||
uint servers_cache_initialised=FALSE;
|
||||
@ -356,8 +357,7 @@ my_bool server_exists_in_table(THD *thd, LEX_SERVER_OPTIONS *server_options)
|
||||
system_charset_info);
|
||||
|
||||
if ((error= table->file->index_read_idx(table->record[0], 0,
|
||||
(byte *)table->field[0]->ptr,
|
||||
table->key_info[0].key_length,
|
||||
(byte *)table->field[0]->ptr, ~(ulonglong)0,
|
||||
HA_READ_KEY_EXACT)))
|
||||
{
|
||||
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
||||
@ -556,8 +556,7 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
|
||||
|
||||
/* read index until record is that specified in server_name */
|
||||
if ((error= table->file->index_read_idx(table->record[0], 0,
|
||||
(byte *)table->field[0]->ptr,
|
||||
table->key_info[0].key_length,
|
||||
(byte *)table->field[0]->ptr, ~(longlong)0,
|
||||
HA_READ_KEY_EXACT)))
|
||||
{
|
||||
/* if not found, err */
|
||||
@ -876,8 +875,7 @@ int update_server_record(TABLE *table, FOREIGN_SERVER *server)
|
||||
system_charset_info);
|
||||
|
||||
if ((error= table->file->index_read_idx(table->record[0], 0,
|
||||
(byte *)table->field[0]->ptr,
|
||||
table->key_info[0].key_length,
|
||||
(byte *)table->field[0]->ptr, ~(longlong)0,
|
||||
HA_READ_KEY_EXACT)))
|
||||
{
|
||||
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
||||
@ -931,8 +929,7 @@ int delete_server_record(TABLE *table,
|
||||
table->field[0]->store(server_name, server_name_length, system_charset_info);
|
||||
|
||||
if ((error= table->file->index_read_idx(table->record[0], 0,
|
||||
(byte *)table->field[0]->ptr,
|
||||
table->key_info[0].key_length,
|
||||
(byte *)table->field[0]->ptr, ~(ulonglong)0,
|
||||
HA_READ_KEY_EXACT)))
|
||||
{
|
||||
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
||||
|
@ -26,7 +26,6 @@ typedef struct st_federated_server
|
||||
|
||||
/* cache handlers */
|
||||
my_bool servers_init(bool dont_read_server_table);
|
||||
static my_bool servers_load(THD *thd, TABLE_LIST *tables);
|
||||
my_bool servers_reload(THD *thd);
|
||||
my_bool get_server_from_table_to_cache(TABLE *table);
|
||||
void servers_free(bool end=0);
|
||||
|
@ -514,8 +514,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
|
||||
table->use_all_columns();
|
||||
table->field[0]->store(exact_name_str, exact_name_len, &my_charset_bin);
|
||||
if (!table->file->index_read_idx(table->record[0], 0,
|
||||
(byte*) table->field[0]->ptr,
|
||||
table->key_info[0].key_length,
|
||||
(byte*) table->field[0]->ptr, ~ULL(0),
|
||||
HA_READ_KEY_EXACT))
|
||||
{
|
||||
int error;
|
||||
|
34
sql/table.cc
34
sql/table.cc
@ -1223,12 +1223,12 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
if ((int) (share->next_number_index= (uint)
|
||||
find_ref_key(share->key_info, share->keys,
|
||||
share->default_values, reg_field,
|
||||
&share->next_number_key_offset)) < 0)
|
||||
&share->next_number_key_offset,
|
||||
&share->next_number_keypart)) < 0)
|
||||
{
|
||||
/* Wrong field definition */
|
||||
DBUG_ASSERT(0);
|
||||
reg_field->unireg_check= Field::NONE; /* purecov: inspected */
|
||||
share->found_next_number_field= 0;
|
||||
error= 4;
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
reg_field->flags |= AUTO_INCREMENT_FLAG;
|
||||
@ -2245,6 +2245,30 @@ char *get_field(MEM_ROOT *mem, Field *field)
|
||||
return to;
|
||||
}
|
||||
|
||||
/*
|
||||
DESCRIPTION
|
||||
given a buffer with a key value, and a map of keyparts
|
||||
that are present in this value, returns the length of the value
|
||||
*/
|
||||
uint calculate_key_len(TABLE *table, uint key, const byte *buf,
|
||||
ulonglong keypart_map)
|
||||
{
|
||||
/* works only with key prefixes */
|
||||
DBUG_ASSERT(((keypart_map + 1) & keypart_map) == 0);
|
||||
|
||||
KEY *key_info= table->s->key_info+key;
|
||||
KEY_PART_INFO *key_part= key_info->key_part;
|
||||
KEY_PART_INFO *end_key_part= key_part + key_info->key_parts;
|
||||
uint length= 0;
|
||||
|
||||
while (key_part < end_key_part && keypart_map)
|
||||
{
|
||||
length+= key_part->store_length;
|
||||
keypart_map >>= 1;
|
||||
key_part++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
Check if database name is valid
|
||||
@ -3936,7 +3960,7 @@ void st_table::mark_auto_increment_column()
|
||||
*/
|
||||
bitmap_set_bit(read_set, found_next_number_field->field_index);
|
||||
bitmap_set_bit(write_set, found_next_number_field->field_index);
|
||||
if (s->next_number_key_offset)
|
||||
if (s->next_number_keypart)
|
||||
mark_columns_used_by_index_no_reset(s->next_number_index, read_set);
|
||||
file->column_bitmaps_signal();
|
||||
}
|
||||
|
@ -194,6 +194,7 @@ typedef struct st_table_share
|
||||
uint primary_key;
|
||||
uint next_number_index;
|
||||
uint next_number_key_offset;
|
||||
uint next_number_keypart;
|
||||
uint error, open_errno, errarg; /* error from open_table_def() */
|
||||
uint column_bitmap_size;
|
||||
uchar frm_version;
|
||||
|
@ -1900,9 +1900,9 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
|
||||
(void)table->file->ha_index_init(0, 1);
|
||||
|
||||
if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
|
||||
0, HA_READ_KEY_EXACT))
|
||||
~(ulonglong)0, HA_READ_KEY_EXACT))
|
||||
{
|
||||
#ifdef EXTRA_DEBUG
|
||||
#ifdef EXTRA_DEBUG
|
||||
/*
|
||||
Most probably user has mistyped time zone name, so no need to bark here
|
||||
unless we need it for debugging.
|
||||
@ -1928,7 +1928,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
|
||||
(void)table->file->ha_index_init(0, 1);
|
||||
|
||||
if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
|
||||
0, HA_READ_KEY_EXACT))
|
||||
~(ulonglong)0, HA_READ_KEY_EXACT))
|
||||
{
|
||||
sql_print_error("Can't find description of time zone '%u'", tzid);
|
||||
goto end;
|
||||
@ -1955,9 +1955,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
|
||||
table->field[0]->store((longlong) tzid, TRUE);
|
||||
(void)table->file->ha_index_init(0, 1);
|
||||
|
||||
// FIXME Is there any better approach than explicitly specifying 4 ???
|
||||
res= table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
|
||||
4, HA_READ_KEY_EXACT);
|
||||
(ulonglong)1, HA_READ_KEY_EXACT);
|
||||
while (!res)
|
||||
{
|
||||
ttid= (uint)table->field[1]->val_int();
|
||||
@ -2028,9 +2027,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
|
||||
table->field[0]->store((longlong) tzid, TRUE);
|
||||
(void)table->file->ha_index_init(0, 1);
|
||||
|
||||
// FIXME Is there any better approach than explicitly specifying 4 ???
|
||||
res= table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
|
||||
4, HA_READ_KEY_EXACT);
|
||||
(ulonglong)1, HA_READ_KEY_EXACT);
|
||||
while (!res)
|
||||
{
|
||||
ttime= (my_time_t)table->field[1]->val_int();
|
||||
|
@ -152,7 +152,8 @@ THR_LOCK_DATA **ha_blackhole::store_lock(THD *thd,
|
||||
|
||||
|
||||
int ha_blackhole::index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
ulonglong keypart_map, uint key_len,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
DBUG_ENTER("ha_blackhole::index_read");
|
||||
DBUG_RETURN(0);
|
||||
@ -160,14 +161,16 @@ int ha_blackhole::index_read(byte * buf, const byte * key,
|
||||
|
||||
|
||||
int ha_blackhole::index_read_idx(byte * buf, uint idx, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
ulonglong keypart_map, uint key_len,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
DBUG_ENTER("ha_blackhole::index_read_idx");
|
||||
DBUG_RETURN(HA_ERR_END_OF_FILE);
|
||||
}
|
||||
|
||||
|
||||
int ha_blackhole::index_read_last(byte * buf, const byte * key, uint key_len)
|
||||
int ha_blackhole::index_read_last(byte * buf, const byte * key,
|
||||
ulonglong keypart_map)
|
||||
{
|
||||
DBUG_ENTER("ha_blackhole::index_read_last");
|
||||
DBUG_RETURN(HA_ERR_END_OF_FILE);
|
||||
|
@ -64,11 +64,12 @@ public:
|
||||
int rnd_init(bool scan);
|
||||
int rnd_next(byte *buf);
|
||||
int rnd_pos(byte * buf, byte *pos);
|
||||
int index_read(byte * buf, const byte * key,
|
||||
int index_read(byte * buf, const byte * key, ulonglong keypart_map,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_idx(byte * buf, uint idx, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_last(byte * buf, const byte * key, uint key_len);
|
||||
ulonglong keypart_map, uint key_len,
|
||||
enum ha_rkey_function find_flag);
|
||||
int index_read_last(byte * buf, const byte * key, ulonglong keypart_map);
|
||||
int index_next(byte * buf);
|
||||
int index_prev(byte * buf);
|
||||
int index_first(byte * buf);
|
||||
|
@ -90,14 +90,13 @@
|
||||
static handler *example_create_handler(handlerton *hton,
|
||||
TABLE_SHARE *table,
|
||||
MEM_ROOT *mem_root);
|
||||
static int example_init_func();
|
||||
static int example_init_func(void *);
|
||||
|
||||
handlerton *example_hton;
|
||||
|
||||
/* Variables for example share methods */
|
||||
static HASH example_open_tables; ///< Hash used to track the number of open tables; variable for example share methods
|
||||
pthread_mutex_t example_mutex; ///< This is the mutex used to init the hash; variable for example share methods
|
||||
static int example_init= 0; ///< This variable is used to check the init state of hash; variable for example share methods
|
||||
|
||||
/** @brief
|
||||
Function we use in the creation of our hash to get key.
|
||||
@ -372,7 +371,7 @@ int ha_example::delete_row(const byte * buf)
|
||||
index.
|
||||
*/
|
||||
int ha_example::index_read(byte * buf, const byte * key,
|
||||
uint key_len __attribute__((unused)),
|
||||
ulonglong keypart_map __attribute__((unused)),
|
||||
enum ha_rkey_function find_flag
|
||||
__attribute__((unused)))
|
||||
{
|
||||
|
@ -191,7 +191,7 @@ public:
|
||||
skip it and and MySQL will treat it as not implemented.
|
||||
*/
|
||||
int index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
ulonglong keypart_map, enum ha_rkey_function find_flag);
|
||||
|
||||
/** @brief
|
||||
We implement this in ha_example.cc. It's not an obligatory method;
|
||||
|
@ -362,7 +362,7 @@ static handler *federated_create_handler(handlerton *hton,
|
||||
MEM_ROOT *mem_root);
|
||||
static int federated_commit(handlerton *hton, THD *thd, bool all);
|
||||
static int federated_rollback(handlerton *hton, THD *thd, bool all);
|
||||
static int federated_db_init(void);
|
||||
static int federated_db_init(void *);
|
||||
|
||||
|
||||
/* Federated storage engine handlerton */
|
||||
@ -573,9 +573,6 @@ int get_connection(FEDERATED_SHARE *share)
|
||||
int error_num= ER_FOREIGN_SERVER_DOESNT_EXIST;
|
||||
char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
|
||||
FOREIGN_SERVER *server;
|
||||
MYSQL *mysql_conn= 0;
|
||||
MYSQL_RES *result= 0;
|
||||
MYSQL_ROW row= 0;
|
||||
DBUG_ENTER("ha_federated::get_connection");
|
||||
|
||||
if (!(server=
|
||||
|
@ -238,34 +238,35 @@ int ha_heap::delete_row(const byte * buf)
|
||||
return res;
|
||||
}
|
||||
|
||||
int ha_heap::index_read(byte * buf, const byte * key, uint key_len,
|
||||
int ha_heap::index_read(byte * buf, const byte * key, ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
DBUG_ASSERT(inited==INDEX);
|
||||
statistic_increment(table->in_use->status_var.ha_read_key_count,
|
||||
&LOCK_status);
|
||||
int error = heap_rkey(file,buf,active_index, key, key_len, find_flag);
|
||||
int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
|
||||
table->status = error ? STATUS_NOT_FOUND : 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len)
|
||||
int ha_heap::index_read_last(byte *buf, const byte *key, ulonglong keypart_map)
|
||||
{
|
||||
DBUG_ASSERT(inited==INDEX);
|
||||
statistic_increment(table->in_use->status_var.ha_read_key_count,
|
||||
&LOCK_status);
|
||||
int error= heap_rkey(file, buf, active_index, key, key_len,
|
||||
int error= heap_rkey(file, buf, active_index, key, keypart_map,
|
||||
HA_READ_PREFIX_LAST);
|
||||
table->status= error ? STATUS_NOT_FOUND : 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
int ha_heap::index_read_idx(byte * buf, uint index, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
statistic_increment(table->in_use->status_var.ha_read_key_count,
|
||||
&LOCK_status);
|
||||
int error = heap_rkey(file, buf, index, key, key_len, find_flag);
|
||||
int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
|
||||
table->status = error ? STATUS_NOT_FOUND : 0;
|
||||
return error;
|
||||
}
|
||||
|
@ -75,11 +75,11 @@ public:
|
||||
ulonglong nb_desired_values,
|
||||
ulonglong *first_value,
|
||||
ulonglong *nb_reserved_values);
|
||||
int index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_idx(byte * buf, uint idx, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_last(byte * buf, const byte * key, uint key_len);
|
||||
int index_read(byte * buf, const byte * key, ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag);
|
||||
int index_read_last(byte *buf, const byte *key, ulonglong keypart_map);
|
||||
int index_read_idx(byte * buf, uint index, const byte * key,
|
||||
ulonglong keypart_map, enum ha_rkey_function find_flag);
|
||||
int index_next(byte * buf);
|
||||
int index_prev(byte * buf);
|
||||
int index_first(byte * buf);
|
||||
|
@ -100,7 +100,7 @@ extern int hp_close(register HP_INFO *info);
|
||||
extern void hp_clear(HP_SHARE *info);
|
||||
extern void hp_clear_keys(HP_SHARE *info);
|
||||
extern uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
|
||||
uint k_len);
|
||||
ulonglong keypart_map);
|
||||
#ifdef THREAD
|
||||
extern pthread_mutex_t THR_LOCK_heap;
|
||||
#else
|
||||
|
@ -784,30 +784,26 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
|
||||
|
||||
|
||||
uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
|
||||
uint k_len)
|
||||
ulonglong keypart_map)
|
||||
{
|
||||
HA_KEYSEG *seg, *endseg;
|
||||
uchar *start_key= key;
|
||||
|
||||
for (seg= keydef->seg, endseg= seg + keydef->keysegs;
|
||||
seg < endseg && (int) k_len > 0; old+= seg->length, seg++)
|
||||
seg < endseg && keypart_map; old+= seg->length, seg++)
|
||||
{
|
||||
uint char_length;
|
||||
keypart_map>>= 1;
|
||||
if (seg->null_bit)
|
||||
{
|
||||
k_len--;
|
||||
if (!(*key++= (char) 1 - *old++))
|
||||
{
|
||||
k_len-= seg->length;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (seg->flag & HA_SWAP_KEY)
|
||||
{
|
||||
uint length= seg->length;
|
||||
byte *pos= (byte*) old + length;
|
||||
|
||||
k_len-= length;
|
||||
while (length--)
|
||||
{
|
||||
*key++= *--pos;
|
||||
@ -822,7 +818,6 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
|
||||
CHARSET_INFO *cs= seg->charset;
|
||||
char_length= length/cs->mbmaxlen;
|
||||
|
||||
k_len-= 2+length;
|
||||
old+= 2;
|
||||
set_if_smaller(length,tmp_length); /* Safety */
|
||||
FIX_LENGTH(cs, old, length, char_length);
|
||||
@ -843,7 +838,6 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
|
||||
}
|
||||
memcpy(key, old, (size_t) char_length);
|
||||
key+= seg->length;
|
||||
k_len-= seg->length;
|
||||
}
|
||||
return (uint) (key - start_key);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "heapdef.h"
|
||||
|
||||
int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
ulonglong keypart_map, enum ha_rkey_function find_flag)
|
||||
{
|
||||
byte *pos;
|
||||
HP_SHARE *share= info->s;
|
||||
@ -38,7 +38,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
|
||||
custom_arg.keyseg= info->s->keydef[inx].seg;
|
||||
custom_arg.key_length= info->lastkey_len=
|
||||
hp_rb_pack_key(keyinfo, (uchar*) info->lastkey,
|
||||
(uchar*) key, key_len);
|
||||
(uchar*) key, keypart_map);
|
||||
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
|
||||
/* for next rkey() after deletion */
|
||||
if (find_flag == HA_READ_AFTER_KEY)
|
||||
|
@ -3920,14 +3920,14 @@ statement issued by the user. We also increment trx->n_mysql_tables_in_use.
|
||||
|
||||
2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
|
||||
instructions to prebuilt->template of the table handle instance in
|
||||
::index_read. The template is used to save CPU time in large joins.
|
||||
::index_read_old. The template is used to save CPU time in large joins.
|
||||
|
||||
3) In row_search_for_mysql, if prebuilt->sql_stat_start is true, we
|
||||
allocate a new consistent read view for the trx if it does not yet have one,
|
||||
or in the case of a locking read, set an InnoDB 'intention' table level
|
||||
lock on the table.
|
||||
|
||||
4) We do the SELECT. MySQL may repeatedly call ::index_read for the
|
||||
4) We do the SELECT. MySQL may repeatedly call ::index_read_old for the
|
||||
same table handle instance, if it is a join.
|
||||
|
||||
5) When the SELECT ends, MySQL removes its intention table level locks
|
||||
@ -3941,7 +3941,7 @@ table handler in that case has to execute the COMMIT in ::external_lock.
|
||||
B) If the user has explicitly set MySQL table level locks, then MySQL
|
||||
does NOT call ::external_lock at the start of the statement. To determine
|
||||
when we are at the start of a new SQL statement we at the start of
|
||||
::index_read also compare the query id to the latest query id where the
|
||||
::index_read_old also compare the query id to the latest query id where the
|
||||
table handle instance was used. If it has changed, we know we are at the
|
||||
start of a new SQL statement. Since the query id can theoretically
|
||||
overwrap, we use this test only as a secondary way of determining the
|
||||
@ -3978,7 +3978,7 @@ ha_innobase::index_read(
|
||||
int error;
|
||||
ulint ret;
|
||||
|
||||
DBUG_ENTER("index_read");
|
||||
DBUG_ENTER("index_read_old");
|
||||
|
||||
ut_a(prebuilt->trx ==
|
||||
(trx_t*) current_thd->ha_data[ht->slot]);
|
||||
@ -4060,7 +4060,7 @@ ha_innobase::index_read(
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
The following functions works like index_read, but it find the last
|
||||
The following functions works like index_read_old, but it find the last
|
||||
row with the current key value or prefix. */
|
||||
|
||||
int
|
||||
@ -4166,7 +4166,7 @@ ha_innobase::index_read_idx(
|
||||
|
||||
/***************************************************************************
|
||||
Reads the next or previous row from a cursor, which must have previously been
|
||||
positioned using index_read. */
|
||||
positioned using index_read_old. */
|
||||
|
||||
int
|
||||
ha_innobase::general_fetch(
|
||||
@ -4215,7 +4215,7 @@ ha_innobase::general_fetch(
|
||||
|
||||
/***************************************************************************
|
||||
Reads the next row from a cursor, which must have previously been
|
||||
positioned using index_read. */
|
||||
positioned using index_read_old. */
|
||||
|
||||
int
|
||||
ha_innobase::index_next(
|
||||
@ -4251,7 +4251,7 @@ ha_innobase::index_next_same(
|
||||
|
||||
/***************************************************************************
|
||||
Reads the previous row from a cursor, which must have previously been
|
||||
positioned using index_read. */
|
||||
positioned using index_read_old. */
|
||||
|
||||
int
|
||||
ha_innobase::index_prev(
|
||||
|
@ -1203,34 +1203,37 @@ int ha_myisam::delete_row(const byte * buf)
|
||||
return mi_delete(file,buf);
|
||||
}
|
||||
|
||||
int ha_myisam::index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
int ha_myisam::index_read(byte *buf, const byte *key, ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
DBUG_ASSERT(inited==INDEX);
|
||||
statistic_increment(table->in_use->status_var.ha_read_key_count,
|
||||
&LOCK_status);
|
||||
int error=mi_rkey(file,buf,active_index, key, key_len, find_flag);
|
||||
int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
int ha_myisam::index_read_idx(byte *buf, uint index, const byte *key,
|
||||
ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
statistic_increment(table->in_use->status_var.ha_read_key_count,
|
||||
&LOCK_status);
|
||||
int error=mi_rkey(file,buf,index, key, key_len, find_flag);
|
||||
int error=mi_rkey(file, buf, index, key, keypart_map, find_flag);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len)
|
||||
int ha_myisam::index_read_last(byte *buf, const byte *key,
|
||||
ulonglong keypart_map)
|
||||
{
|
||||
DBUG_ENTER("ha_myisam::index_read_last");
|
||||
DBUG_ASSERT(inited==INDEX);
|
||||
statistic_increment(table->in_use->status_var.ha_read_key_count,
|
||||
&LOCK_status);
|
||||
int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST);
|
||||
int error=mi_rkey(file, buf, active_index, key, keypart_map,
|
||||
HA_READ_PREFIX_LAST);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
@ -1338,7 +1341,7 @@ int ha_myisam::info(uint flag)
|
||||
stats.index_file_length=info.index_file_length;
|
||||
stats.delete_length = info.delete_length;
|
||||
stats.check_time = info.check_time;
|
||||
stats. mean_rec_length=info.mean_reclength;
|
||||
stats.mean_rec_length=info.mean_reclength;
|
||||
}
|
||||
if (flag & HA_STATUS_CONST)
|
||||
{
|
||||
@ -1698,8 +1701,9 @@ void ha_myisam::get_auto_increment(ulonglong offset, ulonglong increment,
|
||||
key_copy(key, table->record[0],
|
||||
table->key_info + table->s->next_number_index,
|
||||
table->s->next_number_key_offset);
|
||||
error= mi_rkey(file,table->record[1],(int) table->s->next_number_index,
|
||||
key,table->s->next_number_key_offset,HA_READ_PREFIX_LAST);
|
||||
error= mi_rkey(file, table->record[1], (int) table->s->next_number_index,
|
||||
key, make_prev_keypart_map(table->s->next_number_keypart),
|
||||
HA_READ_PREFIX_LAST);
|
||||
if (error)
|
||||
nr= 1;
|
||||
else
|
||||
|
@ -69,11 +69,11 @@ class ha_myisam: public handler
|
||||
int write_row(byte * buf);
|
||||
int update_row(const byte * old_data, byte * new_data);
|
||||
int delete_row(const byte * buf);
|
||||
int index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_idx(byte * buf, uint idx, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_last(byte * buf, const byte * key, uint key_len);
|
||||
int index_read(byte *buf, const byte *key, ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag);
|
||||
int index_read_idx(byte *buf, uint index, const byte *key,
|
||||
ulonglong keypart_map, enum ha_rkey_function find_flag);
|
||||
int index_read_last(byte *buf, const byte *key, ulonglong keypart_map);
|
||||
int index_next(byte * buf);
|
||||
int index_prev(byte * buf);
|
||||
int index_first(byte * buf);
|
||||
|
@ -532,7 +532,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
|
||||
mi_extra(info,HA_EXTRA_KEYREAD,0);
|
||||
bzero(info->lastkey,keyinfo->seg->length);
|
||||
if (!mi_rkey(info, info->rec_buff, key, (const byte*) info->lastkey,
|
||||
keyinfo->seg->length, HA_READ_KEY_EXACT))
|
||||
ULL(1), HA_READ_KEY_EXACT))
|
||||
{
|
||||
/* Don't count this as a real warning, as myisamchk can't correct it */
|
||||
uint save=param->warning_printed;
|
||||
|
@ -206,7 +206,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
|
||||
uint keynr key number
|
||||
key Store packed key here
|
||||
old Not packed key
|
||||
k_length Length of 'old' to use
|
||||
keypart_map bitmap of used keyparts
|
||||
last_used_keyseg out parameter. May be NULL
|
||||
|
||||
RETURN
|
||||
@ -216,34 +216,36 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
|
||||
*/
|
||||
|
||||
uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
|
||||
uint k_length, HA_KEYSEG **last_used_keyseg)
|
||||
ulonglong keypart_map, HA_KEYSEG **last_used_keyseg)
|
||||
{
|
||||
uchar *start_key=key;
|
||||
HA_KEYSEG *keyseg;
|
||||
my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT;
|
||||
DBUG_ENTER("_mi_pack_key");
|
||||
|
||||
for (keyseg=info->s->keyinfo[keynr].seg ;
|
||||
keyseg->type && (int) k_length > 0;
|
||||
old+=keyseg->length, keyseg++)
|
||||
/* "one part" rtree key is 2*SPDIMS part key in MyISAM */
|
||||
if (info->s->keyinfo[keynr].key_alg == HA_KEY_ALG_RTREE)
|
||||
keypart_map= (ULL(1) << (2*SPDIMS)) - 1;
|
||||
|
||||
/* only key prefixes are supported */
|
||||
DBUG_ASSERT(((keypart_map+1) & keypart_map) == 0);
|
||||
|
||||
for (keyseg= info->s->keyinfo[keynr].seg ; keyseg->type && keypart_map;
|
||||
old+= keyseg->length, keyseg++)
|
||||
{
|
||||
enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
|
||||
uint length=min((uint) keyseg->length,(uint) k_length);
|
||||
enum ha_base_keytype type= (enum ha_base_keytype) keyseg->type;
|
||||
uint length= keyseg->length;
|
||||
uint char_length;
|
||||
uchar *pos;
|
||||
CHARSET_INFO *cs=keyseg->charset;
|
||||
|
||||
keypart_map>>= 1;
|
||||
if (keyseg->null_bit)
|
||||
{
|
||||
k_length--;
|
||||
if (!(*key++= (char) 1-*old++)) /* Copy null marker */
|
||||
{
|
||||
k_length-=length;
|
||||
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
|
||||
{
|
||||
k_length-=2; /* Skip length */
|
||||
old+= 2;
|
||||
}
|
||||
continue; /* Found NULL */
|
||||
}
|
||||
}
|
||||
@ -262,7 +264,6 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
|
||||
while (pos < end && pos[0] == ' ')
|
||||
pos++;
|
||||
}
|
||||
k_length-=length;
|
||||
length=(uint) (end-pos);
|
||||
FIX_LENGTH(cs, pos, length, char_length);
|
||||
store_key_length_inc(key,char_length);
|
||||
@ -274,7 +275,6 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
|
||||
{
|
||||
/* Length of key-part used with mi_rkey() always 2 */
|
||||
uint tmp_length=uint2korr(pos);
|
||||
k_length-= 2+length;
|
||||
pos+=2;
|
||||
set_if_smaller(length,tmp_length); /* Safety */
|
||||
FIX_LENGTH(cs, pos, length, char_length);
|
||||
@ -287,11 +287,8 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
|
||||
else if (keyseg->flag & HA_SWAP_KEY)
|
||||
{ /* Numerical column */
|
||||
pos+=length;
|
||||
k_length-=length;
|
||||
while (length--)
|
||||
{
|
||||
*key++ = *--pos;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
FIX_LENGTH(cs, pos, length, char_length);
|
||||
@ -299,30 +296,10 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
|
||||
if (length > char_length)
|
||||
cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
|
||||
key+= length;
|
||||
k_length-=length;
|
||||
}
|
||||
if (last_used_keyseg)
|
||||
*last_used_keyseg= keyseg;
|
||||
|
||||
#ifdef NOT_USED
|
||||
if (keyseg->type)
|
||||
{
|
||||
/* Part-key ; fill with ASCII 0 for easier searching */
|
||||
length= (uint) -k_length; /* unused part of last key */
|
||||
do
|
||||
{
|
||||
if (keyseg->flag & HA_NULL_PART)
|
||||
length++;
|
||||
if (keyseg->flag & HA_SPACE_PACK)
|
||||
length+=2;
|
||||
else
|
||||
length+= keyseg->length;
|
||||
keyseg++;
|
||||
} while (keyseg->type);
|
||||
bzero((byte*) key,length);
|
||||
key+=length;
|
||||
}
|
||||
#endif
|
||||
DBUG_RETURN((uint) (key-start_key));
|
||||
} /* _mi_pack_key */
|
||||
|
||||
|
@ -21,13 +21,10 @@
|
||||
#include "myisamdef.h"
|
||||
#include "rt_index.h"
|
||||
|
||||
static ha_rows _mi_record_pos(MI_INFO *info,const byte *key,uint key_len,
|
||||
enum ha_rkey_function search_flag);
|
||||
static double _mi_search_pos(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
|
||||
uint key_len,uint nextflag,my_off_t pos);
|
||||
static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
|
||||
uchar *keypos,uint *ret_max_key);
|
||||
|
||||
static ha_rows _mi_record_pos(MI_INFO *, const byte *, ulonglong,
|
||||
enum ha_rkey_function);
|
||||
static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,uchar *, uint,uint,my_off_t);
|
||||
static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *,uchar *, uchar *,uint *);
|
||||
|
||||
/*
|
||||
Estimate how many records there is in a given range
|
||||
@ -47,9 +44,8 @@ static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page,
|
||||
number Estimated number of rows
|
||||
*/
|
||||
|
||||
|
||||
ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
|
||||
key_range *max_key)
|
||||
ha_rows mi_records_in_range(MI_INFO *info, int inx,
|
||||
key_range *min_key, key_range *max_key)
|
||||
{
|
||||
ha_rows start_pos,end_pos,res;
|
||||
DBUG_ENTER("mi_records_in_range");
|
||||
@ -87,7 +83,7 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
|
||||
}
|
||||
key_buff= info->lastkey+info->s->base.max_key_length;
|
||||
start_key_len= _mi_pack_key(info,inx, key_buff,
|
||||
(uchar*) min_key->key, min_key->length,
|
||||
(uchar*) min_key->key, min_key->keypart_map,
|
||||
(HA_KEYSEG**) 0);
|
||||
res= rtree_estimate(info, inx, key_buff, start_key_len,
|
||||
myisam_read_vec[min_key->flag]);
|
||||
@ -97,14 +93,12 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
|
||||
#endif
|
||||
case HA_KEY_ALG_BTREE:
|
||||
default:
|
||||
start_pos= (min_key ?
|
||||
_mi_record_pos(info, min_key->key, min_key->length,
|
||||
min_key->flag) :
|
||||
(ha_rows) 0);
|
||||
end_pos= (max_key ?
|
||||
_mi_record_pos(info, max_key->key, max_key->length,
|
||||
max_key->flag) :
|
||||
info->state->records+ (ha_rows) 1);
|
||||
start_pos= (min_key ? _mi_record_pos(info, min_key->key,
|
||||
min_key->keypart_map, min_key->flag)
|
||||
: (ha_rows) 0);
|
||||
end_pos= (max_key ? _mi_record_pos(info, max_key->key,
|
||||
max_key->keypart_map, max_key->flag)
|
||||
: info->state->records + (ha_rows) 1);
|
||||
res= (end_pos < start_pos ? (ha_rows) 0 :
|
||||
(end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos));
|
||||
if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
|
||||
@ -122,21 +116,21 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key,
|
||||
|
||||
/* Find relative position (in records) for key in index-tree */
|
||||
|
||||
static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len,
|
||||
static ha_rows _mi_record_pos(MI_INFO *info, const byte *key,
|
||||
ulonglong keypart_map,
|
||||
enum ha_rkey_function search_flag)
|
||||
{
|
||||
uint inx=(uint) info->lastinx, nextflag;
|
||||
uint inx=(uint) info->lastinx, nextflag, key_len;
|
||||
MI_KEYDEF *keyinfo=info->s->keyinfo+inx;
|
||||
uchar *key_buff;
|
||||
double pos;
|
||||
|
||||
DBUG_ENTER("_mi_record_pos");
|
||||
DBUG_PRINT("enter",("search_flag: %d",search_flag));
|
||||
DBUG_ASSERT(keypart_map);
|
||||
|
||||
if (key_len == 0)
|
||||
key_len=USE_WHOLE_KEY;
|
||||
key_buff=info->lastkey+info->s->base.max_key_length;
|
||||
key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len,
|
||||
key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key, keypart_map,
|
||||
(HA_KEYSEG**) 0);
|
||||
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,
|
||||
(uchar*) key_buff,key_len););
|
||||
|
@ -21,8 +21,8 @@
|
||||
/* Read a record using key */
|
||||
/* Ordinary search_flag is 0 ; Give error if no record with key */
|
||||
|
||||
int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
||||
enum ha_rkey_function search_flag)
|
||||
int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key,
|
||||
ulonglong keypart_map, enum ha_rkey_function search_flag)
|
||||
{
|
||||
uchar *key_buff;
|
||||
MYISAM_SHARE *share=info->s;
|
||||
@ -30,8 +30,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
||||
HA_KEYSEG *last_used_keyseg;
|
||||
uint pack_key_length, use_key_length, nextflag;
|
||||
DBUG_ENTER("mi_rkey");
|
||||
DBUG_PRINT("enter", ("base: %lx buf: %lx inx: %d search_flag: %d",
|
||||
(long) info, (long) buf, inx, search_flag));
|
||||
DBUG_PRINT("enter", ("base: %lx buf: %lx inx: %d keyparts %lx search_flag: %d",
|
||||
(long) info, (long) buf, inx, keypart_map, search_flag));
|
||||
|
||||
if ((inx = _mi_check_index(info,inx)) < 0)
|
||||
DBUG_RETURN(my_errno);
|
||||
@ -47,18 +47,17 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
||||
key is already packed!; This happens when we are using a MERGE TABLE
|
||||
*/
|
||||
key_buff=info->lastkey+info->s->base.max_key_length;
|
||||
pack_key_length= key_len;
|
||||
bmove(key_buff,key,key_len);
|
||||
pack_key_length= keypart_map;
|
||||
bmove(key_buff, key, pack_key_length);
|
||||
last_used_keyseg= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (key_len == 0)
|
||||
key_len=USE_WHOLE_KEY;
|
||||
DBUG_ASSERT(keypart_map);
|
||||
/* Save the packed key for later use in the second buffer of lastkey. */
|
||||
key_buff=info->lastkey+info->s->base.max_key_length;
|
||||
pack_key_length=_mi_pack_key(info,(uint) inx, key_buff, (uchar*) key,
|
||||
key_len, &last_used_keyseg);
|
||||
keypart_map, &last_used_keyseg);
|
||||
/* Save packed_key_length for use by the MERGE engine. */
|
||||
info->pack_key_length= pack_key_length;
|
||||
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg,
|
||||
|
@ -604,8 +604,9 @@ extern int _mi_dispose(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos,
|
||||
extern my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo,int level);
|
||||
extern uint _mi_make_key(MI_INFO *info,uint keynr,uchar *key,
|
||||
const byte *record,my_off_t filepos);
|
||||
extern uint _mi_pack_key(MI_INFO *info,uint keynr,uchar *key,uchar *old,
|
||||
uint key_length, HA_KEYSEG **last_used_keyseg);
|
||||
extern uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key,
|
||||
uchar *old, ulonglong keypart_map,
|
||||
HA_KEYSEG **last_used_keyseg);
|
||||
extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,byte *buf);
|
||||
extern int _mi_read_cache(IO_CACHE *info,byte *buff,my_off_t pos,
|
||||
uint length,int re_read_if_possibly);
|
||||
|
@ -323,7 +323,7 @@ static int run_test(const char *filename)
|
||||
range.key= record+1;
|
||||
range.length= 1000; /* Big enough */
|
||||
range.flag= HA_READ_MBR_INTERSECT;
|
||||
hrows= mi_records_in_range(file,0, &range, (key_range*) 0);
|
||||
hrows= mi_records_in_range(file, 0, &range, (key_range*) 0);
|
||||
printf(" %ld rows\n", (long) hrows);
|
||||
|
||||
if (mi_close(file)) goto err;
|
||||
|
@ -255,7 +255,7 @@ int run_test(const char *filename)
|
||||
max_range.key= record+1;
|
||||
max_range.length= 1000; /* Big enough */
|
||||
max_range.flag= HA_READ_KEY_EXACT;
|
||||
hrows= mi_records_in_range(file,0, &min_range, &max_range);
|
||||
hrows= mi_records_in_range(file, 0, &min_range, &max_range);
|
||||
printf(" %ld rows\n", (long) hrows);
|
||||
|
||||
if (mi_close(file)) goto err;
|
||||
|
@ -145,30 +145,33 @@ int ha_myisammrg::delete_row(const byte * buf)
|
||||
}
|
||||
|
||||
int ha_myisammrg::index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
statistic_increment(table->in_use->status_var.ha_read_key_count,
|
||||
&LOCK_status);
|
||||
int error=myrg_rkey(file,buf,active_index, key, key_len, find_flag);
|
||||
int error=myrg_rkey(file,buf,active_index, key, keypart_map, find_flag);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag)
|
||||
ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
statistic_increment(table->in_use->status_var.ha_read_key_count,
|
||||
&LOCK_status);
|
||||
int error=myrg_rkey(file,buf,index, key, key_len, find_flag);
|
||||
int error=myrg_rkey(file,buf,index, key, keypart_map, find_flag);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len)
|
||||
int ha_myisammrg::index_read_last(byte * buf, const byte * key,
|
||||
ulonglong keypart_map)
|
||||
{
|
||||
statistic_increment(table->in_use->status_var.ha_read_key_count,
|
||||
&LOCK_status);
|
||||
int error=myrg_rkey(file,buf,active_index, key, key_len,
|
||||
int error=myrg_rkey(file,buf,active_index, key, keypart_map,
|
||||
HA_READ_PREFIX_LAST);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
|
@ -56,11 +56,11 @@ class ha_myisammrg: public handler
|
||||
int write_row(byte * buf);
|
||||
int update_row(const byte * old_data, byte * new_data);
|
||||
int delete_row(const byte * buf);
|
||||
int index_read(byte * buf, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_idx(byte * buf, uint idx, const byte * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_last(byte * buf, const byte * key, uint key_len);
|
||||
int index_read(byte * buf, const byte * key, ulonglong keypart_map,
|
||||
enum ha_rkey_function find_flag);
|
||||
int index_read_idx(byte * buf, uint index, const byte * key,
|
||||
ulonglong keypart_map, enum ha_rkey_function find_flag);
|
||||
int index_read_last(byte * buf, const byte * key, ulonglong keypart_map);
|
||||
int index_next(byte * buf);
|
||||
int index_prev(byte * buf);
|
||||
int index_first(byte * buf);
|
||||
|
@ -36,7 +36,7 @@
|
||||
*/
|
||||
|
||||
int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
|
||||
uint key_len, enum ha_rkey_function search_flag)
|
||||
ulonglong keypart_map, enum ha_rkey_function search_flag)
|
||||
{
|
||||
byte *key_buff;
|
||||
uint pack_key_length;
|
||||
@ -56,7 +56,7 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
|
||||
|
||||
if (table == info->open_tables)
|
||||
{
|
||||
err=mi_rkey(mi,0,inx,key,key_len,search_flag);
|
||||
err=mi_rkey(mi, 0, inx, key, keypart_map, search_flag);
|
||||
/* Get the saved packed key and packed key length. */
|
||||
key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length;
|
||||
pack_key_length=mi->pack_key_length;
|
||||
@ -64,7 +64,7 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
|
||||
else
|
||||
{
|
||||
mi->once_flags|= USE_PACKED_KEYS;
|
||||
err=mi_rkey(mi,0,inx,key_buff,pack_key_length,search_flag);
|
||||
err=mi_rkey(mi, 0, inx, key_buff, pack_key_length, search_flag);
|
||||
}
|
||||
info->last_used_table=table+1;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user