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