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:
unknown 2007-01-29 10:40:26 +01:00
parent 6e1ba88418
commit 4e8b49d656
58 changed files with 483 additions and 441 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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"));

View File

@ -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)
{
/*

View File

@ -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);

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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,

View File

@ -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();

View File

@ -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);

View File

@ -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)
{

View File

@ -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();

View File

@ -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
}

View File

@ -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" ":"")

View File

@ -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 :\

View File

@ -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;

View File

@ -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)

View 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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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]);

View File

@ -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

View File

@ -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)

View 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);

View File

@ -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;

View File

@ -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();
}

View File

@ -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;

View File

@ -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();

View File

@ -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);

View 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);

View File

@ -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)))
{

View File

@ -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;

View File

@ -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=

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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)

View File

@ -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(

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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););

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;