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