diff options
-rw-r--r-- | include/my_bitmap.h | 1 | ||||
-rw-r--r-- | include/myisam.h | 81 | ||||
-rw-r--r-- | myisam/mi_check.c | 33 | ||||
-rw-r--r-- | myisam/mi_create.c | 2 | ||||
-rw-r--r-- | myisam/mi_delete.c | 2 | ||||
-rw-r--r-- | myisam/mi_extra.c | 4 | ||||
-rw-r--r-- | myisam/mi_open.c | 16 | ||||
-rw-r--r-- | myisam/mi_preload.c | 2 | ||||
-rw-r--r-- | myisam/mi_rsame.c | 2 | ||||
-rw-r--r-- | myisam/mi_rsamepos.c | 2 | ||||
-rw-r--r-- | myisam/mi_search.c | 2 | ||||
-rw-r--r-- | myisam/mi_update.c | 2 | ||||
-rw-r--r-- | myisam/mi_write.c | 15 | ||||
-rw-r--r-- | myisam/myisamchk.c | 16 | ||||
-rw-r--r-- | myisam/myisamdef.h | 4 | ||||
-rw-r--r-- | myisam/myisamlog.c | 2 | ||||
-rw-r--r-- | myisam/myisampack.c | 12 | ||||
-rw-r--r-- | myisam/sort.c | 2 | ||||
-rw-r--r-- | mysys/my_bitmap.c | 31 | ||||
-rw-r--r-- | sql/ha_myisam.cc | 10 | ||||
-rw-r--r-- | sql/sql_bitmap.h | 9 |
21 files changed, 180 insertions, 70 deletions
diff --git a/include/my_bitmap.h b/include/my_bitmap.h index 84a5d8bd18a..f4fe28266e4 100644 --- a/include/my_bitmap.h +++ b/include/my_bitmap.h @@ -54,6 +54,7 @@ extern void bitmap_clear_all(MY_BITMAP *map); extern void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit); extern void bitmap_free(MY_BITMAP *map); extern void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2); +extern void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit); extern void bitmap_set_all(MY_BITMAP *map); extern void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit); extern void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size); diff --git a/include/myisam.h b/include/myisam.h index 7d3f0e0c801..03194fe42ae 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -35,14 +35,26 @@ extern "C" { /* defines used by myisam-funktions */ -/* The following defines can be increased if necessary */ -#define MI_MAX_KEY 64 /* Max allowed keys */ -#define MI_MAX_KEY_SEG 16 /* Max segments for key */ -#define MI_MAX_KEY_LENGTH 1000 +/* + There is a hard limit for the maximum number of keys as there are only + 8 bits in the index file header for the number of keys in a table. + This means that 0..255 keys can exist for a table. The idea of + MI_MAX_POSSIBLE_KEY is to ensure that one can use myisamchk & tools on + a MyISAM table for which one has more keys than MyISAM is normally + compiled for. If you don't have this, you will get a core dump when + running myisamchk compiled for 128 keys on a table with 255 keys. +*/ +#define MI_MAX_POSSIBLE_KEY 255 /* For myisam_chk */ +#define MI_MAX_POSSIBLE_KEY_BUFF (1024+6+6) /* For myisam_chk */ +/* + The following defines can be increased if necessary. + BUT: MI_MAX_KEY must be <= MI_MAX_POSSIBLE_KEY. +*/ +#define MI_MAX_KEY 64 /* Max allowed keys */ +#define MI_MAX_KEY_SEG 16 /* Max segments for key */ +#define MI_MAX_KEY_LENGTH 1000 #define MI_MAX_KEY_BUFF (MI_MAX_KEY_LENGTH+MI_MAX_KEY_SEG*6+8+8) -#define MI_MAX_POSSIBLE_KEY_BUFF (1024+6+6) /* For myisam_chk */ -#define MI_MAX_POSSIBLE_KEY 64 /* For myisam_chk */ #define MI_MAX_MSG_BUF 1024 /* used in CHECK TABLE, REPAIR TABLE */ #define MI_NAME_IEXT ".MYI" #define MI_NAME_DEXT ".MYD" @@ -56,6 +68,63 @@ extern "C" { #define mi_portable_sizeof_char_ptr 8 +/* + In the following macros '_keyno_' is 0 .. keys-1. + If there can be more keys than bits in the key_map, the highest bit + is for all upper keys. They cannot be switched individually. + This means that clearing of high keys is ignored, setting one high key + sets all high keys. +*/ +#define MI_KEYMAP_BITS (8 * SIZEOF_LONG_LONG) +#define MI_KEYMAP_HIGH_MASK (ULL(1) << (MI_KEYMAP_BITS - 1)) +#define mi_get_mask_all_keys_active(_keys_) \ + (((_keys_) < MI_KEYMAP_BITS) ? \ + ((ULL(1) << (_keys_)) - ULL(1)) : \ + (~ ULL(0))) + +#if MI_MAX_KEY > MI_KEYMAP_BITS + +#define mi_is_key_active(_keymap_,_keyno_) \ + (((_keyno_) < MI_KEYMAP_BITS) ? \ + test((_keymap_) & (ULL(1) << (_keyno_))) : \ + test((_keymap_) & MI_KEYMAP_HIGH_MASK)) +#define mi_set_key_active(_keymap_,_keyno_) \ + (_keymap_)|= (((_keyno_) < MI_KEYMAP_BITS) ? \ + (ULL(1) << (_keyno_)) : \ + MI_KEYMAP_HIGH_MASK) +#define mi_clear_key_active(_keymap_,_keyno_) \ + (_keymap_)&= (((_keyno_) < MI_KEYMAP_BITS) ? \ + (~ (ULL(1) << (_keyno_))) : \ + (~ (ULL(0))) /*ignore*/ ) + +#else + +#define mi_is_key_active(_keymap_,_keyno_) \ + test((_keymap_) & (ULL(1) << (_keyno_))) +#define mi_set_key_active(_keymap_,_keyno_) \ + (_keymap_)|= (ULL(1) << (_keyno_)) +#define mi_clear_key_active(_keymap_,_keyno_) \ + (_keymap_)&= (~ (ULL(1) << (_keyno_))) + +#endif + +#define mi_is_any_key_active(_keymap_) \ + test((_keymap_)) +#define mi_is_all_keys_active(_keymap_,_keys_) \ + ((_keymap_) == mi_get_mask_all_keys_active(_keys_)) +#define mi_set_all_keys_active(_keymap_,_keys_) \ + (_keymap_)= mi_get_mask_all_keys_active(_keys_) +#define mi_clear_all_keys_active(_keymap_) \ + (_keymap_)= 0 +#define mi_intersect_keys_active(_to_,_from_) \ + (_to_)&= (_from_) +#define mi_is_any_intersect_keys_active(_keymap1_,_keys_,_keymap2_) \ + ((_keymap1_) & (_keymap2_) & \ + mi_get_mask_all_keys_active(_keys_)) +#define mi_copy_keys_active(_to_,_maxkeys_,_from_) \ + (_to_)= (mi_get_mask_all_keys_active(_maxkeys_) & \ + (_from_)) + /* Param to/from mi_info */ typedef struct st_mi_isaminfo /* Struct from h_info */ diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 9e003a18dac..1db829808a9 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -282,7 +282,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info) if ((skr=(my_off_t) info->state->key_file_length) != size) { /* Don't give error if file generated by myisampack */ - if (skr > size && info->s->state.key_map) + if (skr > size && mi_is_any_key_active(info->s->state.key_map)) { error=1; mi_check_print_error(param, @@ -379,7 +379,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info) rec_per_key_part+=keyinfo->keysegs, key++, keyinfo++) { param->key_crc[key]=0; - if (!(((ulonglong) 1 << key) & share->state.key_map)) + if (! mi_is_key_active(share->state.key_map, key)) { /* Remember old statistics for key */ memcpy((char*) rec_per_key_part, @@ -507,7 +507,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info) (int) ((my_off_t2double(key_totlength) - my_off_t2double(all_keydata))*100.0/ my_off_t2double(key_totlength))); - else if (all_totaldata != 0L && share->state.key_map) + else if (all_totaldata != 0L && mi_is_any_key_active(share->state.key_map)) puts(""); } if (param->key_file_blocks != info->state->key_file_length && @@ -1034,7 +1034,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) for (key=0,keyinfo= info->s->keyinfo; key < info->s->base.keys; key++,keyinfo++) { - if ((((ulonglong) 1 << key) & info->s->state.key_map)) + if (mi_is_key_active(info->s->state.key_map, key)) { if(!(keyinfo->flag & HA_FULLTEXT)) { @@ -1298,8 +1298,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, */ if (param->testflag & T_CREATE_MISSING_KEYS) - share->state.key_map= ((((ulonglong) 1L << share->base.keys)-1) & - param->keys_in_use); + mi_copy_keys_active(share->state.key_map, share->base.keys, + param->keys_in_use); info->state->key_file_length=share->base.keystart; @@ -1461,7 +1461,7 @@ static int writekeys(MI_CHECK *param, register MI_INFO *info, byte *buff, key=info->lastkey+info->s->base.max_key_length; for (i=0 ; i < info->s->base.keys ; i++) { - if (((ulonglong) 1 << i) & info->s->state.key_map) + if (mi_is_key_active(info->s->state.key_map, i)) { if (info->s->keyinfo[i].flag & HA_FULLTEXT ) { @@ -1492,7 +1492,7 @@ static int writekeys(MI_CHECK *param, register MI_INFO *info, byte *buff, info->errkey=(int) i; /* This key was found */ while ( i-- > 0 ) { - if (((ulonglong) 1 << i) & info->s->state.key_map) + if (mi_is_key_active(info->s->state.key_map, i)) { if (info->s->keyinfo[i].flag & HA_FULLTEXT) { @@ -1529,7 +1529,7 @@ int movepoint(register MI_INFO *info, byte *record, my_off_t oldpos, key=info->lastkey+info->s->base.max_key_length; for (i=0 ; i < info->s->base.keys; i++) { - if (i != prot_key && (((ulonglong) 1 << i) & info->s->state.key_map)) + if (i != prot_key && mi_is_key_active(info->s->state.key_map, i)) { key_length=_mi_make_key(info,i,key,record,oldpos); if (info->s->keyinfo[i].flag & HA_NOSAME) @@ -1628,7 +1628,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name) for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ; key++,keyinfo++) { - if (!(((ulonglong) 1 << key) & share->state.key_map)) + if (! mi_is_key_active(info->s->state.key_map, key)) continue; if (share->state.key_root[key] != HA_OFFSET_ERROR) @@ -2023,7 +2023,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, sort_param.read_cache=param->read_cache; sort_param.keyinfo=share->keyinfo+sort_param.key; sort_param.seg=sort_param.keyinfo->seg; - if (!(((ulonglong) 1 << sort_param.key) & key_map)) + if (! mi_is_key_active(key_map, sort_param.key)) { /* Remember old statistics for key */ memcpy((char*) rec_per_key_part, @@ -2084,7 +2084,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, if (param->testflag & T_STATISTICS) update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique, (ulonglong) info->state->records); - share->state.key_map|=(ulonglong) 1 << sort_param.key; + mi_set_key_active(share->state.key_map, sort_param.key); if (sort_param.fix_datafile) { @@ -2405,7 +2405,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, sort_param[i].key=key; sort_param[i].keyinfo=share->keyinfo+key; sort_param[i].seg=sort_param[i].keyinfo->seg; - if (!(((ulonglong) 1 << key) & key_map)) + if (! mi_is_key_active(key_map, key)) { /* Remember old statistics for key */ memcpy((char*) rec_per_key_part, @@ -3917,8 +3917,7 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, { byte *record; if (!info->s->base.auto_key || - !(((ulonglong) 1 << (info->s->base.auto_key-1) - & info->s->state.key_map))) + ! mi_is_key_active(info->s->state.key_map, info->s->base.auto_key - 1)) { if (!(param->testflag & T_VERY_SILENT)) mi_check_print_info(param, @@ -4070,7 +4069,7 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows) if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) && ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1) { - share->state.key_map&= ~ ((ulonglong) 1 << i); + mi_clear_key_active(share->state.key_map, i); info->update|= HA_STATE_CHANGED; } } @@ -4094,7 +4093,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, mi_repair_by_sort only works if we have at least one key. If we don't have any keys, we should use the normal repair. */ - if (!key_map) + if (! mi_is_any_key_active(key_map)) return FALSE; /* Can't use sort */ for (i=0 ; i < share->base.keys ; i++,key++) { diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 33b344405ec..560535f2933 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -508,7 +508,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, mi_int2store(share.state.header.key_parts,key_segs); mi_int2store(share.state.header.unique_key_parts,unique_key_parts); - share.state.key_map = ((ulonglong) 1 << keys)-1; + mi_set_all_keys_active(share.state.key_map, keys); share.base.keystart = share.state.state.key_file_length= MY_ALIGN(info_length, myisam_block_size); share.base.max_key_block_length=max_key_block_length; diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index cc4a17182f7..60a07254e82 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -74,7 +74,7 @@ int mi_delete(MI_INFO *info,const byte *record) old_key=info->lastkey2; for (i=0 ; i < share->base.keys ; i++ ) { - if (((ulonglong) 1 << i) & info->s->state.key_map) + if (mi_is_key_active(info->s->state.key_map, i)) { info->s->keyinfo[i].version++; if (info->s->keyinfo[i].flag & HA_FULLTEXT ) diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c index ba32bb9115a..bfe1748af01 100644 --- a/myisam/mi_extra.c +++ b/myisam/mi_extra.c @@ -244,7 +244,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) error=1; /* Not possibly if not lock */ break; } - if (share->state.key_map) + if (mi_is_any_key_active(share->state.key_map)) { MI_KEYDEF *key=share->keyinfo; uint i; @@ -252,7 +252,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) { if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1) { - share->state.key_map&= ~ ((ulonglong) 1 << i); + mi_clear_key_active(share->state.key_map, i); info->update|= HA_STATE_CHANGED; } } diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 74b97a65609..82663e0c318 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -192,14 +192,14 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) } share->state_diff_length=len-MI_STATE_INFO_SIZE; - mi_state_info_read(disk_cache, &share->state); + mi_state_info_read((uchar*) disk_cache, &share->state); len= mi_uint2korr(share->state.header.base_info_length); if (len != MI_BASE_INFO_SIZE) { DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d", len,MI_BASE_INFO_SIZE)) } - disk_pos=my_n_base_info_read(disk_cache+base_pos, &share->base); + disk_pos=my_n_base_info_read((uchar*) disk_cache + base_pos, &share->base); share->state.state_length=base_pos; if (!(open_flags & HA_OPEN_FOR_REPAIR) && @@ -863,7 +863,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite) } -char *mi_state_info_read(char *ptr, MI_STATE_INFO *state) +char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state) { uint i,keys,key_parts,key_blocks; memcpy_fixed(&state->header,ptr, sizeof(state->header)); @@ -929,7 +929,7 @@ uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead) } else if (my_read(file, buff, state->state_length,MYF(MY_NABP))) return (MY_FILE_ERROR); - mi_state_info_read(buff, state); + mi_state_info_read((uchar*) buff, state); } return 0; } @@ -974,7 +974,7 @@ uint mi_base_info_write(File file, MI_BASE_INFO *base) } -char *my_n_base_info_read(char *ptr, MI_BASE_INFO *base) +char *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base) { base->keystart = mi_sizekorr(ptr); ptr +=8; base->max_data_file_length = mi_sizekorr(ptr); ptr +=8; @@ -1204,7 +1204,7 @@ int mi_disable_indexes(MI_INFO *info) { MYISAM_SHARE *share= info->s; - share->state.key_map= 0; + mi_clear_all_keys_active(share->state.key_map); return 0; } @@ -1240,7 +1240,7 @@ int mi_enable_indexes(MI_INFO *info) error= HA_ERR_CRASHED; } else - share->state.key_map= ((ulonglong) 1L << share->base.keys) - 1; + mi_set_all_keys_active(share->state.key_map, share->base.keys); return error; } @@ -1265,6 +1265,6 @@ int mi_indexes_are_disabled(MI_INFO *info) { MYISAM_SHARE *share= info->s; - return (! share->state.key_map && share->base.keys); + return (! mi_is_any_key_active(share->state.key_map) && share->base.keys); } diff --git a/myisam/mi_preload.c b/myisam/mi_preload.c index 317ab4ad7fe..d63399b519d 100644 --- a/myisam/mi_preload.c +++ b/myisam/mi_preload.c @@ -51,7 +51,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) my_off_t pos= share->base.keystart; DBUG_ENTER("mi_preload"); - if (!keys || !key_map || key_file_length == pos) + if (!keys || !mi_is_any_key_active(key_map) || key_file_length == pos) DBUG_RETURN(0); block_length= keyinfo[0].block_length; diff --git a/myisam/mi_rsame.c b/myisam/mi_rsame.c index 56c8d1226ca..321097744b9 100644 --- a/myisam/mi_rsame.c +++ b/myisam/mi_rsame.c @@ -30,7 +30,7 @@ int mi_rsame(MI_INFO *info, byte *record, int inx) { DBUG_ENTER("mi_rsame"); - if (inx != -1 && ! (((ulonglong) 1 << inx) & info->s->state.key_map)) + if (inx != -1 && ! mi_is_key_active(info->s->state.key_map, inx)) { DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); } diff --git a/myisam/mi_rsamepos.c b/myisam/mi_rsamepos.c index a1d96fb7104..35cdd41e297 100644 --- a/myisam/mi_rsamepos.c +++ b/myisam/mi_rsamepos.c @@ -32,7 +32,7 @@ int mi_rsame_with_pos(MI_INFO *info, byte *record, int inx, my_off_t filepos) { DBUG_ENTER("mi_rsame_with_pos"); - if (inx < -1 || ! (((ulonglong) 1 << inx) & info->s->state.key_map)) + if (inx < -1 || ! mi_is_key_active(info->s->state.key_map, inx)) { DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX); } diff --git a/myisam/mi_search.c b/myisam/mi_search.c index c669a8be8f8..ed61bbfe41a 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -29,7 +29,7 @@ int _mi_check_index(MI_INFO *info, int inx) { if (inx == -1) /* Use last index */ inx=info->lastinx; - if (inx < 0 || ! (((ulonglong) 1 << inx) & info->s->state.key_map)) + if (inx < 0 || ! mi_is_key_active(info->s->state.key_map, inx)) { my_errno=HA_ERR_WRONG_INDEX; return -1; diff --git a/myisam/mi_update.c b/myisam/mi_update.c index cda60694008..ab23f2e6da9 100644 --- a/myisam/mi_update.c +++ b/myisam/mi_update.c @@ -87,7 +87,7 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec) changed=0; for (i=0 ; i < share->base.keys ; i++) { - if (((ulonglong) 1 << i) & share->state.key_map) + if (mi_is_key_active(share->state.key_map, i)) { if (share->keyinfo[i].flag & HA_FULLTEXT ) { diff --git a/myisam/mi_write.c b/myisam/mi_write.c index dd062b79769..c8f9aa84a41 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -101,7 +101,7 @@ int mi_write(MI_INFO *info, byte *record) buff=info->lastkey2; for (i=0 ; i < share->base.keys ; i++) { - if (((ulonglong) 1 << i) & share->state.key_map) + if (mi_is_key_active(share->state.key_map, i)) { bool local_lock_tree= (lock_tree && !(info->bulk_insert && @@ -175,7 +175,7 @@ err: info->errkey= (int) i; while ( i-- > 0) { - if (((ulonglong) 1 << i) & share->state.key_map) + if (mi_is_key_active(share->state.key_map, i)) { bool local_lock_tree= (lock_tree && !(info->bulk_insert && @@ -944,20 +944,21 @@ int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows) MI_KEYDEF *key=share->keyinfo; bulk_insert_param *params; uint i, num_keys, total_keylength; - ulonglong key_map=0; + ulonglong key_map; DBUG_ENTER("_mi_init_bulk_insert"); DBUG_PRINT("enter",("cache_size: %lu", cache_size)); DBUG_ASSERT(!info->bulk_insert && (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT)); + mi_clear_all_keys_active(key_map); for (i=total_keylength=num_keys=0 ; i < share->base.keys ; i++) { - if (!(key[i].flag & HA_NOSAME) && share->base.auto_key != i+1 - && test(share->state.key_map & ((ulonglong) 1 << i))) + if (! (key[i].flag & HA_NOSAME) && (share->base.auto_key != i + 1) && + mi_is_key_active(share->state.key_map, i)) { num_keys++; - key_map |=((ulonglong) 1 << i); + mi_set_key_active(key_map, i); total_keylength+=key[i].maxlength+TREE_ELEMENT_EXTRA_SIZE; } } @@ -981,7 +982,7 @@ int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows) params=(bulk_insert_param *)(info->bulk_insert+share->base.keys); for (i=0 ; i < share->base.keys ; i++) { - if (test(key_map & ((ulonglong) 1 << i))) + if (mi_is_key_active(key_map, i)) { params->info=info; params->keynr=i; diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 519e123e9da..4856d93b320 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -871,8 +871,8 @@ static int myisamchk(MI_CHECK *param, my_string filename) MI_STATE_INFO_SIZE || mi_uint2korr(share->state.header.base_info_length) != MI_BASE_INFO_SIZE || - ((param->keys_in_use & ~share->state.key_map) & - (((ulonglong) 1L << share->base.keys)-1)) || + mi_is_any_intersect_keys_active(param->keys_in_use, share->base.keys, + ~share->state.key_map) || test_if_almost_full(info) || info->s->state.header.file_version[3] != myisam_file_magic[3] || (set_collation && @@ -939,8 +939,8 @@ static int myisamchk(MI_CHECK *param, my_string filename) if (param->testflag & T_REP_ANY) { ulonglong tmp=share->state.key_map; - share->state.key_map= (((ulonglong) 1 << share->base.keys)-1) - & param->keys_in_use; + mi_copy_keys_active(share->state.key_map, share->base.keys, + param->keys_in_use); if (tmp != share->state.key_map) info->update|=HA_STATE_CHANGED; } @@ -961,7 +961,7 @@ static int myisamchk(MI_CHECK *param, my_string filename) if (!error) { if ((param->testflag & (T_REP_BY_SORT | T_REP_PARALLEL)) && - (share->state.key_map || + (mi_is_any_key_active(share->state.key_map) || (rep_quick && !param->keys_in_use && !recreate)) && mi_test_if_sort_rep(info, info->state->records, info->s->state.key_map, @@ -1037,7 +1037,7 @@ static int myisamchk(MI_CHECK *param, my_string filename) llstr(info->state->records,llbuff), llstr(info->state->del,llbuff2)); error =chk_status(param,info); - share->state.key_map &=param->keys_in_use; + mi_intersect_keys_active(share->state.key_map, param->keys_in_use); error =chk_size(param,info); if (!error || !(param->testflag & (T_FAST | T_FORCE_CREATE))) error|=chk_del(param, info,param->testflag); @@ -1266,7 +1266,7 @@ static void descript(MI_CHECK *param, register MI_INFO *info, my_string name) } printf("Recordlength: %13d\n",(int) share->base.pack_reclength); - if (share->state.key_map != (((ulonglong) 1 << share->base.keys) -1)) + if (! mi_is_all_keys_active(share->state.key_map, share->base.keys)) { longlong2str(share->state.key_map,buff,2); printf("Using only keys '%s' of %d possibly keys\n", @@ -1448,7 +1448,7 @@ static int mi_sort_records(MI_CHECK *param, temp_buff=0; new_file= -1; - if (!(((ulonglong) 1 << sort_key) & share->state.key_map)) + if (! mi_is_key_active(share->state.key_map, sort_key)) { mi_check_print_warning(param, "Can't sort table '%s' on key %d; No such key", diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 5688b377d3d..74463ec065a 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -676,10 +676,10 @@ extern void _mi_unmap_file(MI_INFO *info); extern uint save_pack_length(byte *block_buff,ulong length); uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite); -char *mi_state_info_read(char *ptr, MI_STATE_INFO *state); +char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state); uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead); uint mi_base_info_write(File file, MI_BASE_INFO *base); -char *my_n_base_info_read(char *ptr, MI_BASE_INFO *base); +char *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base); int mi_keyseg_write(File file, const HA_KEYSEG *keyseg); char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg); uint mi_keydef_write(File file, MI_KEYDEF *keydef); diff --git a/myisam/myisamlog.c b/myisam/myisamlog.c index dc98d813266..de55b86252c 100644 --- a/myisam/myisamlog.c +++ b/myisam/myisamlog.c @@ -810,7 +810,7 @@ static int find_record_with_key(struct file_info *file_info, byte *record) for (key=0 ; key < info->s->base.keys ; key++) { - if ((((ulonglong) 1 << key) & info->s->state.key_map) && + if (mi_is_key_active(info->s->state.key_map, key) && info->s->keyinfo[key].flag & HA_NOSAME) { VOID(_mi_make_key(info,key,tmp_key,record,0L)); diff --git a/myisam/myisampack.c b/myisam/myisampack.c index daf2bbdf85c..ba48cbf1b62 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -441,9 +441,9 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count) if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY))) goto error; - mrg->src_file_has_indexes_disabled|= ((mrg->file[i]->s->state.key_map != - (((ulonglong) 1) << - mrg->file[i]->s->base. keys) - 1)); + mrg->src_file_has_indexes_disabled|= + ! mi_is_all_keys_active(mrg->file[i]->s->state.key_map, + mrg->file[i]->s->base.keys); } /* Check that files are identical */ for (j=0 ; j < count-1 ; j++) @@ -2941,7 +2941,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, share->state.dellink= HA_OFFSET_ERROR; share->state.split=(ha_rows) mrg->records; share->state.version=(ulong) time((time_t*) 0); - if (share->state.key_map != (ULL(1) << share->base.keys) - 1) + if (! mi_is_all_keys_active(share->state.key_map, share->base.keys)) { /* Some indexes are disabled, cannot use current key_file_length value @@ -2955,7 +2955,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, original file so "myisamchk -rq" can use this value (this is necessary because index size cannot be easily calculated for fulltext keys) */ - share->state.key_map=0; + mi_clear_all_keys_active(share->state.key_map); for (key=0 ; key < share->base.keys ; key++) share->state.key_root[key]= HA_OFFSET_ERROR; for (key=0 ; key < share->state.header.max_block_size ; key++) @@ -2995,7 +2995,7 @@ static int save_state_mrg(File file,PACK_MRG_INFO *mrg,my_off_t new_length, } state.dellink= HA_OFFSET_ERROR; state.version=(ulong) time((time_t*) 0); - state.key_map=0; + mi_clear_all_keys_active(state.key_map); state.checksum=crc; if (isam_file->s->base.keys) isamchk_neaded=1; diff --git a/myisam/sort.c b/myisam/sort.c index 9d2af2e8c70..f2f8c8ef7ec 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -479,7 +479,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) } if (!got_error) { - share->state.key_map|=(ulonglong) 1 << sinfo->key; + mi_set_key_active(share->state.key_map, sinfo->key); if (param->testflag & T_STATISTICS) update_key_parts(sinfo->keyinfo, rec_per_key_part, sinfo->unique, (ulonglong) info->state->records); diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index c70c0fa0754..4a917fc8287 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -339,6 +339,37 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) } +/* + Set/clear all bits above a bit. + + SYNOPSIS + bitmap_set_above() + map RETURN The bitmap to change. + from_byte The bitmap buffer byte offset to start with. + use_bit The bit value (1/0) to use for all upper bits. + + NOTE + You can only set/clear full bytes. + The function is meant for the situation that you copy a smaller bitmap + to a bigger bitmap. Bitmap lengths are always multiple of eigth (the + size of a byte). Using 'from_byte' saves multiplication and division + by eight during parameter passing. + + RETURN + void +*/ + +void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit) +{ + uchar use_byte= use_bit ? 0xff : 0; + uchar *to= map->bitmap + from_byte; + uchar *end= map->bitmap + map->bitmap_size; + + while (to < end) + *to++= use_byte; +} + + void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) { uchar *to=map->bitmap, *from=map2->bitmap, *end; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 0d9c32adbfa..e94b697e0bb 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -602,7 +602,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool optimize) !(share->state.changed & STATE_NOT_OPTIMIZED_KEYS)))) { ulonglong key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ? - ((ulonglong) 1L << share->base.keys)-1 : + mi_get_mask_all_keys_active(share->base.keys) : share->state.key_map); uint testflag=param.testflag; if (mi_test_if_sort_rep(file,file->state->records,key_map,0) && @@ -903,7 +903,7 @@ int ha_myisam::enable_indexes(uint mode) { int error; - if (file->s->state.key_map == set_bits(ulonglong, file->s->base.keys)) + if (mi_is_all_keys_active(file->s->state.key_map, file->s->base.keys)) { /* All indexes are enabled already. */ return 0; @@ -1002,8 +1002,8 @@ void ha_myisam::start_bulk_insert(ha_rows rows) if (! rows || (rows > MI_MIN_ROWS_TO_USE_WRITE_CACHE)) mi_extra(file, HA_EXTRA_WRITE_CACHE, (void*) &size); - can_enable_indexes= (file->s->state.key_map == - set_bits(ulonglong, file->s->base.keys)); + can_enable_indexes= mi_is_all_keys_active(file->s->state.key_map, + file->s->base.keys); if (!(specialflag & SPECIAL_SAFE_MODE)) { @@ -1256,7 +1256,7 @@ void ha_myisam::info(uint flag) share->db_options_in_use= info.options; block_size= myisam_block_size; share->keys_in_use.set_prefix(share->keys); - share->keys_in_use.intersect(info.key_map); + share->keys_in_use.intersect_extended(info.key_map); share->keys_for_keyread.intersect(share->keys_in_use); share->db_record_offset= info.record_offset; if (share->key_parts) diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h index bc1484b4fb0..0f5b6dcd35e 100644 --- a/sql/sql_bitmap.h +++ b/sql/sql_bitmap.h @@ -51,6 +51,14 @@ public: bitmap_init(&map2, (uchar *)&map2buff, sizeof(ulonglong)*8, 0); bitmap_intersect(&map, &map2); } + /* Use highest bit for all bits above sizeof(ulonglong)*8. */ + void intersect_extended(ulonglong map2buff) + { + intersect(map2buff); + if (map.bitmap_size > sizeof(ulonglong)) + bitmap_set_above(&map, sizeof(ulonglong), + test(map2buff & (LL(1) << (sizeof(ulonglong) * 8 - 1)))); + } void subtract(Bitmap& map2) { bitmap_subtract(&map, &map2.map); } void merge(Bitmap& map2) { bitmap_union(&map, &map2.map); } my_bool is_set(uint n) const { return bitmap_is_set(&map, n); } @@ -116,6 +124,7 @@ public: void clear_all() { map=(ulonglong)0; } void intersect(Bitmap<64>& map2) { map&= map2.map; } void intersect(ulonglong map2) { map&= map2; } + void intersect_extended(ulonglong map2) { map&= map2; } void subtract(Bitmap<64>& map2) { map&= ~map2.map; } void merge(Bitmap<64>& map2) { map|= map2.map; } my_bool is_set(uint n) const { return test(map & (((ulonglong)1) << n)); } |