Commit f40ac0bb authored by jimw@mysql.com's avatar jimw@mysql.com

Merge mysql.com:/home/jimw/my/mysql-5.0-readline

into  mysql.com:/home/jimw/my/mysql-5.0-clean
parents 48536b76 ec15dda2
......@@ -1117,3 +1117,5 @@ vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
ndb/src/dummy.cpp
innobase/mkinstalldirs
mkinstalldirs
......@@ -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 */
#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 */
......
......@@ -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++)
{
......
......@@ -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);
......
This diff is collapsed.
......@@ -153,7 +153,7 @@ c varchar(64) utf8_general_ci NO select,insert,update,references
select * from information_schema.COLUMNS where table_name="t1"
and column_name= "a";
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT
NULL mysqltest t1 a 1 NULL YES int NULL NULL 11 0 NULL NULL int(11) select,insert,update,references
NULL mysqltest t1 a 1 NULL YES int NULL NULL 10 NULL NULL NULL int(11) select,insert,update,references
show columns from mysqltest.t1 where field like "%a%";
Field Type Null Key Default Extra
a int(11) YES NULL
......@@ -298,6 +298,9 @@ show create function sub2;
Function sql_mode Create Function
sub2 CREATE FUNCTION `test`.`sub2`(i int) RETURNS int(11)
return i+1
show function status like "sub2";
Db Name Type Definer Modified Created Security_type Comment
test sub2 FUNCTION mysqltest_1@localhost # # DEFINER
drop function sub2;
show create procedure sel2;
Procedure sql_mode Create Procedure
......@@ -520,7 +523,7 @@ c float(5,2) NULL NULL 5 2
d decimal(6,4) NULL NULL 6 4
e float NULL NULL 12 NULL
f decimal(6,3) NULL NULL 6 3
g int(11) NULL NULL 11 0
g int(11) NULL NULL 10 NULL
h double(10,3) NULL NULL 10 3
i double NULL NULL 22 NULL
drop table t1;
......@@ -841,3 +844,26 @@ drop procedure p2;
show create database information_schema;
Database Create Database
information_schema CREATE DATABASE `information_schema` /*!40100 DEFAULT CHARACTER SET utf8 */
create table t1(f1 LONGBLOB, f2 LONGTEXT);
select column_name,data_type,CHARACTER_OCTET_LENGTH,
CHARACTER_MAXIMUM_LENGTH
from information_schema.columns
where table_name='t1';
column_name data_type CHARACTER_OCTET_LENGTH CHARACTER_MAXIMUM_LENGTH
f1 longblob 4294967295 4294967295
f2 longtext 4294967295 4294967295
drop table t1;
create table t1(f1 tinyint, f2 SMALLINT, f3 mediumint, f4 int,
f5 BIGINT, f6 BIT, f7 bit(64));
select column_name, NUMERIC_PRECISION, NUMERIC_SCALE
from information_schema.columns
where table_name='t1';
column_name NUMERIC_PRECISION NUMERIC_SCALE
f1 3 NULL
f2 5 NULL
f3 7 NULL
f4 10 NULL
f5 19 NULL
f6 1 NULL
f7 64 NULL
drop table t1;
This diff is collapsed.
......@@ -157,6 +157,8 @@ select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES;
show create procedure sel2;
show create function sub1;
show create function sub2;
--replace_column 5 # 6 #
show function status like "sub2";
connection default;
disconnect user1;
drop function sub2;
......@@ -569,3 +571,19 @@ drop procedure p2;
# Bug #9434 SHOW CREATE DATABASE information_schema;
#
show create database information_schema;
#
# Bug #11057 information_schema: columns table has some questionable contents
#
create table t1(f1 LONGBLOB, f2 LONGTEXT);
select column_name,data_type,CHARACTER_OCTET_LENGTH,
CHARACTER_MAXIMUM_LENGTH
from information_schema.columns
where table_name='t1';
drop table t1;
create table t1(f1 tinyint, f2 SMALLINT, f3 mediumint, f4 int,
f5 BIGINT, f6 BIT, f7 bit(64));
select column_name, NUMERIC_PRECISION, NUMERIC_SCALE
from information_schema.columns
where table_name='t1';
drop table t1;
......@@ -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;
......
......@@ -495,7 +495,7 @@ static int check_foreign_data_source(
query.append(escaped_table_name);
query.append(FEDERATED_BTICK);
query.append(FEDERATED_WHERE);
query.append(FEDERATED_1EQ0);
query.append(FEDERATED_FALSE);
DBUG_PRINT("info", ("check_foreign_data_source query %s", query.c_ptr_quick()));
if (mysql_real_query(mysql, query.ptr(), query.length()))
......@@ -1661,6 +1661,62 @@ int ha_federated::write_row(byte *buf)
}
int ha_federated::optimize(THD* thd, HA_CHECK_OPT* check_opt)
{
char query_buffer[STRING_BUFFER_USUAL_SIZE];
String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
DBUG_ENTER("ha_federated::optimize");
query.length(0);
query.set_charset(system_charset_info);
query.append(FEDERATED_OPTIMIZE);
query.append(FEDERATED_BTICK);
query.append(share->table_name, share->table_name_length);
query.append(FEDERATED_BTICK);
if (mysql_real_query(mysql, query.ptr(), query.length()))
{
my_error(-1, MYF(0), mysql_error(mysql));
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}
int ha_federated::repair(THD* thd, HA_CHECK_OPT* check_opt)
{
char query_buffer[STRING_BUFFER_USUAL_SIZE];
String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
DBUG_ENTER("ha_federated::repair");
query.length(0);
query.set_charset(system_charset_info);
query.append(FEDERATED_REPAIR);
query.append(FEDERATED_BTICK);
query.append(share->table_name, share->table_name_length);
query.append(FEDERATED_BTICK);
if (check_opt->flags & T_QUICK)
query.append(FEDERATED_QUICK);
if (check_opt->flags & T_EXTEND)
query.append(FEDERATED_EXTENDED);
if (check_opt->sql_flags & TT_USEFRM)
query.append(FEDERATED_USE_FRM);
if (mysql_real_query(mysql, query.ptr(), query.length()))
{
my_error(-1, MYF(0), mysql_error(mysql));
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}
/*
Yes, update_row() does what you expect, it updates a row. old_data will have
the previous row record in it, while new_data will have the newest data in
......
......@@ -31,40 +31,83 @@
#define FEDERATED_RECORDS_IN_RANGE 2
#define FEDERATED_INFO " SHOW TABLE STATUS LIKE "
#define FEDERATED_INFO_LEN sizeof(FEDERATED_INFO)
#define FEDERATED_SELECT "SELECT "
#define FEDERATED_SELECT_LEN sizeof(FEDERATED_SELECT)
#define FEDERATED_WHERE " WHERE "
#define FEDERATED_WHERE_LEN sizeof(FEDERATED_WHERE)
#define FEDERATED_FROM " FROM "
#define FEDERATED_FROM_LEN sizeof(FEDERATED_FROM)
#define FEDERATED_PERCENT "%"
#define FEDERATED_PERCENT_LEN sizeof(FEDERATED_PERCENT)
#define FEDERATED_IS " IS "
#define FEDERATED_IS_LEN sizeof(FEDERATED_IS)
#define FEDERATED_NULL " NULL "
#define FEDERATED_NULL_LEN sizeof(FEDERATED_NULL)
#define FEDERATED_ISNULL " IS NULL "
#define FEDERATED_ISNULL_LEN sizeof(FEDERATED_ISNULL)
#define FEDERATED_LIKE " LIKE "
#define FEDERATED_LIKE_LEN sizeof(FEDERATED_LIKE)
#define FEDERATED_TRUNCATE "TRUNCATE "
#define FEDERATED_TRUNCATE_LEN sizeof(FEDERATED_TRUNCATE)
#define FEDERATED_DELETE "DELETE "
#define FEDERATED_DELETE_LEN sizeof(FEDERATED_DELETE)
#define FEDERATED_INSERT "INSERT INTO "
#define FEDERATED_INSERT_LEN sizeof(FEDERATED_INSERT)
#define FEDERATED_OPTIMIZE "OPTIMIZE TABLE "
#define FEDERATED_OPTIMIZE_LEN sizeof(FEDERATED_OPTIMIZE)
#define FEDERATED_REPAIR "REPAIR TABLE "
#define FEDERATED_REPAIR_LEN sizeof(FEDERATED_REPAIR)
#define FEDERATED_QUICK " QUICK"
#define FEDERATED_QUICK_LEN sizeof(FEDERATED_QUICK)
#define FEDERATED_EXTENDED " EXTENDED"
#define FEDERATED_EXTENDED_LEN sizeof(FEDERATED_EXTENDED)
#define FEDERATED_USE_FRM " USE_FRM"
#define FEDERATED_USE_FRM_LEN sizeof(FEDERATED_USE_FRM)
#define FEDERATED_LIMIT1 " LIMIT 1"
#define FEDERATED_LIMIT1_LEN sizeof(FEDERATED_LIMIT1)
#define FEDERATED_VALUES "VALUES "
#define FEDERATED_VALUES_LEN sizeof(FEDERATED_VALUES)
#define FEDERATED_UPDATE "UPDATE "
#define FEDERATED_UPDATE_LEN sizeof(FEDERATED_UPDATE)
#define FEDERATED_SET "SET "
#define FEDERATED_SET_LEN sizeof(FEDERATED_SET)
#define FEDERATED_AND " AND "
#define FEDERATED_AND_LEN sizeof(FEDERATED_AND)
#define FEDERATED_CONJUNCTION ") AND ("
#define FEDERATED_CONJUNCTION_LEN sizeof(FEDERATED_CONJUNCTION)
#define FEDERATED_OR " OR "
#define FEDERATED_OR_LEN sizeof(FEDERATED_OR)
#define FEDERATED_NOT " NOT "
#define FEDERATED_NOT_LEN sizeof(FEDERATED_NOT)
#define FEDERATED_STAR "* "
#define FEDERATED_STAR_LEN sizeof(FEDERATED_STAR)
#define FEDERATED_SPACE " "
#define FEDERATED_SPACE_LEN sizeof(FEDERATED_SPACE)
#define FEDERATED_SQUOTE "'"
#define FEDERATED_SQUOTE_LEN sizeof(FEDERATED_SQUOTE)
#define FEDERATED_COMMA ", "
#define FEDERATED_DQOUTE '"'
#define FEDERATED_BTICK "`"
#define FEDERATED_COMMA_LEN sizeof(FEDERATED_COMMA)
#define FEDERATED_BTICK "`"
#define FEDERATED_BTICK_LEN sizeof(FEDERATED_BTICK)
#define FEDERATED_OPENPAREN " ("
#define FEDERATED_OPENPAREN_LEN sizeof(FEDERATED_OPENPAREN)
#define FEDERATED_CLOSEPAREN ") "
#define FEDERATED_CLOSEPAREN_LEN sizeof(FEDERATED_CLOSEPAREN)
#define FEDERATED_NE " != "
#define FEDERATED_NE_LEN sizeof(FEDERATED_NE)
#define FEDERATED_GT " > "
#define FEDERATED_GT_LEN sizeof(FEDERATED_GT)
#define FEDERATED_LT " < "
#define FEDERATED_LT_LEN sizeof(FEDERATED_LT)
#define FEDERATED_LE " <= "
#define FEDERATED_LE_LEN sizeof(FEDERATED_LE)
#define FEDERATED_GE " >= "
#define FEDERATED_GE_LEN sizeof(FEDERATED_GE)
#define FEDERATED_EQ " = "
#define FEDERATED_1EQ0 " 1=0"
#define FEDERATED_EQ_LEN sizeof(FEDERATED_EQ)
#define FEDERATED_FALSE " 1=0"
#define FEDERATED_FALSE_LEN sizeof(FEDERATED_FALSE)
/*
FEDERATED_SHARE is a structure that will be shared amoung all open handlers
......@@ -88,7 +131,7 @@ typedef struct st_federated_share {
char *socket;
char *sport;
ushort port;
uint table_name_length,use_count;
uint table_name_length, use_count;
pthread_mutex_t mutex;
THR_LOCK lock;
} FEDERATED_SHARE;
......@@ -235,6 +278,9 @@ class ha_federated: public handler
void position(const byte *record); //required
void info(uint); //required
int repair(THD* thd, HA_CHECK_OPT* check_opt);
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int delete_all_rows(void);
int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); //required
......
......@@ -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)
......
......@@ -242,7 +242,7 @@ static void print_set_option(FILE* file, uint32 bits_changed, uint32 option,
{
if (*need_comma)
fprintf(file,", ");
fprintf(file,"%s=%d", name, (bool)(flags & option));
fprintf(file,"%s=%d", name, test(flags & option));
*need_comma= 1;
}
}
......
......@@ -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)); }
......
......@@ -2386,10 +2386,12 @@ mysql_execute_command(THD *thd)
select_result *result=lex->result;
if (all_tables)
{
res= check_table_access(thd,
lex->exchange ? SELECT_ACL | FILE_ACL :
SELECT_ACL,
all_tables, 0);
if (lex->orig_sql_command != SQLCOM_SHOW_STATUS_PROC &&
lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC)
res= check_table_access(thd,
lex->exchange ? SELECT_ACL | FILE_ACL :
SELECT_ACL,
all_tables, 0);
}
else
res= check_access(thd,
......
......@@ -2377,6 +2377,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
{
const char *tmp_buff;
byte *pos;
bool is_blob;
uint flags=field->flags;
char tmp[MAX_FIELD_WIDTH];
char tmp1[MAX_FIELD_WIDTH];
......@@ -2455,12 +2456,14 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
"NO" : "YES");
table->field[6]->store((const char*) pos,
strlen((const char*) pos), cs);
if (field->has_charset())
is_blob= (field->type() == FIELD_TYPE_BLOB);
if (field->has_charset() || is_blob)
{
table->field[8]->store((longlong) field->field_length/
field->charset()->mbmaxlen);
longlong c_octet_len= is_blob ? (longlong) field->max_length() :
(longlong) field->max_length()/field->charset()->mbmaxlen;
table->field[8]->store(c_octet_len);
table->field[8]->set_notnull();
table->field[9]->store((longlong) field->field_length);
table->field[9]->store((longlong) field->max_length());
table->field[9]->set_notnull();
}
......@@ -2488,6 +2491,17 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
case FIELD_TYPE_LONG:
case FIELD_TYPE_LONGLONG:
case FIELD_TYPE_INT24:
{
table->field[10]->store((longlong) field->max_length() - 1);
table->field[10]->set_notnull();
break;
}
case FIELD_TYPE_BIT:
{
table->field[10]->store((longlong) field->max_length());
table->field[10]->set_notnull();
break;
}
case FIELD_TYPE_FLOAT:
case FIELD_TYPE_DOUBLE:
{
......
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