Commit 42707b9e authored by unknown's avatar unknown

Bug#10932 - Building server with key limit of 128, makes test cases fail

This patch allows to configure MyISAM for 128 indexes per table.
The main problem is the key_map, wich is implemented as an ulonglong.
To get rid of the limit and keep the efficient and flexible
implementation, the highest bit is now used for all upper keys.
This means that the lower keys can be disabled and enabled 
individually as usual and the high keys can only be disabled and
enabled as a block. That way the existing test suite is still
applicable, while more keys work, though slightly less efficient.
To really get more than 64 keys, some defines need to be changed.
Another patch will address this.


include/my_bitmap.h:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Added the declaration for a function that extends the highest bit value
  to all upper bits of a bigger bitmap.
include/myisam.h:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed MI_MAX_POSSIBLE_KEY to what it was meant for.
  Added a bunch of macros to handle the MyISAM key_map.
myisam/mi_check.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_create.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_delete.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_extra.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_open.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
  Changed pointer types from signed char* to unsigned char*.
myisam/mi_preload.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_rsame.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_rsamepos.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_search.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_update.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/mi_write.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/myisamchk.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/myisamdef.h:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed pointer types from signed char* to unsigned char*.
myisam/myisamlog.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/myisampack.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
myisam/sort.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
mysys/my_bitmap.c:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Added a function that extends the highest bit value
  to all upper bits of a bigger bitmap.
sql/ha_myisam.cc:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Changed key_map access to use the new macros.
sql/sql_bitmap.h:
  Bug#10932 - Building server with key limit of 128, makes test cases fail
  Added a method that extends the highest bit value
  to all upper bits of a bigger bitmap.
parent 4aac980f
......@@ -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);
......
......@@ -35,14 +35,26 @@ extern "C" {
/* defines used by myisam-funktions */
/* The following defines can be increased if necessary */
/*
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 */
......
......@@ -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,7 +1298,7 @@ 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) &
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++)
{
......
......@@ -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;
......
......@@ -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 )
......
......@@ -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;
}
}
......
......@@ -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);
}
......@@ -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;
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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;
......
......@@ -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 )
{
......
......@@ -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 @@ int mi_write(MI_INFO *info, byte *record)
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;
......
......@@ -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",
......
......@@ -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);
......
......@@ -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));
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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)
......
......@@ -51,6 +51,14 @@ template <uint default_width> class Bitmap
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 @@ template <> class Bitmap<64>
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)); }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment