summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_bitmap.h1
-rw-r--r--include/myisam.h81
-rw-r--r--myisam/mi_check.c33
-rw-r--r--myisam/mi_create.c2
-rw-r--r--myisam/mi_delete.c2
-rw-r--r--myisam/mi_extra.c4
-rw-r--r--myisam/mi_open.c16
-rw-r--r--myisam/mi_preload.c2
-rw-r--r--myisam/mi_rsame.c2
-rw-r--r--myisam/mi_rsamepos.c2
-rw-r--r--myisam/mi_search.c2
-rw-r--r--myisam/mi_update.c2
-rw-r--r--myisam/mi_write.c15
-rw-r--r--myisam/myisamchk.c16
-rw-r--r--myisam/myisamdef.h4
-rw-r--r--myisam/myisamlog.c2
-rw-r--r--myisam/myisampack.c12
-rw-r--r--myisam/sort.c2
-rw-r--r--mysys/my_bitmap.c31
-rw-r--r--sql/ha_myisam.cc10
-rw-r--r--sql/sql_bitmap.h9
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 &param, 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)); }