Commit 9c4049ad authored by serg@serg.mylan's avatar serg@serg.mylan

Bitmap post-review fixes

parent eb93b6b8
......@@ -38,23 +38,23 @@ typedef struct st_bitmap
#ifdef __cplusplus
extern "C" {
#endif
extern my_bool bitmap_cmp(MY_BITMAP *map1, MY_BITMAP *map2);
extern my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2);
extern my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size, my_bool thread_safe);
extern my_bool bitmap_is_clear_all(MY_BITMAP *map);
extern my_bool bitmap_is_prefix(MY_BITMAP *map, uint prefix_size);
extern my_bool bitmap_is_set(MY_BITMAP *map, uint bitmap_bit);
extern my_bool bitmap_is_set_all(MY_BITMAP *map);
extern my_bool bitmap_is_subset(MY_BITMAP *map1, MY_BITMAP *map2);
extern my_bool bitmap_is_clear_all(const MY_BITMAP *map);
extern my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size);
extern my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit);
extern my_bool bitmap_is_set_all(const MY_BITMAP *map);
extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2);
extern uint bitmap_set_next(MY_BITMAP *map);
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, MY_BITMAP *map2);
extern void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2);
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);
extern void bitmap_subtract(MY_BITMAP *map, MY_BITMAP *map2);
extern void bitmap_union(MY_BITMAP *map, MY_BITMAP *map2);
extern void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2);
extern void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2);
#ifdef __cplusplus
}
#endif
......
......@@ -16,7 +16,16 @@
/*
Handling of uchar arrays as large bitmaps.
We assume that the size of the used bitmap is less than ~(uint) 0
API limitations (or, rather asserted safety assumptions,
to encourage correct programming)
* the size of the used bitmap is less than ~(uint) 0
* it's a multiple of 8 (for efficiency reasons)
* when arguments are a bitmap and a bit number, the number
must be within bitmap size
* bitmap_set_prefix() is an exception - one can use ~0 to set all bits
* when both arguments are bitmaps, they must be of the same size
TODO:
Make assembler THREAD safe versions of these using test-and-set instructions
......@@ -45,11 +54,11 @@ inline void bitmap_unlock(MY_BITMAP *map)
my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size, my_bool thread_safe)
{
// for efficiency reasons - MY_BITMAP is heavily used
DBUG_ASSERT((bitmap_size & 7) == 0);
bitmap_size/=8;
if (!(map->bitmap=buf) &&
!(map->bitmap=(uchar*)my_malloc(bitmap_size + sizeof(pthread_mutex_t),
!(map->bitmap=(uchar*)my_malloc(bitmap_size +
(thread_safe ? sizeof(pthread_mutex_t) : 0),
MYF(MY_WME | MY_ZEROFILL))))
return 1;
map->bitmap_size=bitmap_size;
......@@ -128,7 +137,8 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
{
uint prefix_bytes, prefix_bits;
DBUG_ASSERT(map->bitmap);
DBUG_ASSERT(map->bitmap &&
(prefix_size <= map->bitmap_size*8 || prefix_size == ~0));
bitmap_lock(map);
set_if_smaller(prefix_size, map->bitmap_size*8);
if ((prefix_bytes= prefix_size / 8))
......@@ -150,7 +160,7 @@ void bitmap_set_all(MY_BITMAP *map)
bitmap_set_prefix(map, ~0);
}
my_bool bitmap_is_prefix(MY_BITMAP *map, uint prefix_size)
my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size)
{
uint prefix_bits= prefix_size & 7, res= 0;
uchar *m= map->bitmap, *end_prefix= map->bitmap+prefix_size/8,
......@@ -167,7 +177,7 @@ my_bool bitmap_is_prefix(MY_BITMAP *map, uint prefix_size)
goto ret;
while (m < end)
if (m++ != 0)
if (*m++ != 0)
goto ret;
res=1;
......@@ -176,23 +186,23 @@ my_bool bitmap_is_prefix(MY_BITMAP *map, uint prefix_size)
return res;
}
my_bool bitmap_is_clear_all(MY_BITMAP *map)
my_bool bitmap_is_clear_all(const MY_BITMAP *map)
{
return bitmap_is_prefix(map, 0);
}
my_bool bitmap_is_set_all(MY_BITMAP *map)
my_bool bitmap_is_set_all(const MY_BITMAP *map)
{
return bitmap_is_prefix(map, map->bitmap_size*8);
}
my_bool bitmap_is_set(MY_BITMAP *map, uint bitmap_bit)
my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit)
{
DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
return map->bitmap[bitmap_bit / 8] & (1 << (bitmap_bit & 7));
}
my_bool bitmap_is_subset(MY_BITMAP *map1, MY_BITMAP *map2)
my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
{
uint length, res=0;
uchar *m1=map1->bitmap, *m2=map2->bitmap, *end;
......@@ -215,7 +225,7 @@ my_bool bitmap_is_subset(MY_BITMAP *map1, MY_BITMAP *map2)
return res;
}
my_bool bitmap_cmp(MY_BITMAP *map1, MY_BITMAP *map2)
my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2)
{
uint res;
......@@ -231,7 +241,7 @@ my_bool bitmap_cmp(MY_BITMAP *map1, MY_BITMAP *map2)
return res;
}
void bitmap_intersect(MY_BITMAP *map, MY_BITMAP *map2)
void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
{
uchar *to=map->bitmap, *from=map2->bitmap, *end;
......@@ -249,7 +259,7 @@ void bitmap_intersect(MY_BITMAP *map, MY_BITMAP *map2)
bitmap_unlock(map);
}
void bitmap_subtract(MY_BITMAP *map, MY_BITMAP *map2)
void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
{
uchar *to=map->bitmap, *from=map2->bitmap, *end;
......@@ -267,7 +277,7 @@ void bitmap_subtract(MY_BITMAP *map, MY_BITMAP *map2)
bitmap_unlock(map);
}
void bitmap_union(MY_BITMAP *map, MY_BITMAP *map2)
void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
{
uchar *to=map->bitmap, *from=map2->bitmap, *end;
......
......@@ -844,7 +844,7 @@ int ha_berkeley::write_row(byte * record)
ulong thd_options = table->in_use ? table->in_use->options : 0;
for (uint retry=0 ; retry < berkeley_trans_retry ; retry++)
{
key_map changed_keys;
key_map changed_keys(0);
if (using_ignore && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
{
if ((error=txn_begin(db_env, transaction, &sub_trans, 0))) /* purecov: deadcode */
......@@ -888,7 +888,8 @@ int ha_berkeley::write_row(byte * record)
else if (!changed_keys.is_clear_all())
{
new_error = 0;
for (uint keynr=0; keynr < changed_keys.length(); keynr++)
for (uint keynr=0 ; keynr < table->keys+test(hidden_primary_key) ;
keynr++)
{
if (changed_keys.is_set(keynr))
{
......@@ -1012,7 +1013,7 @@ int ha_berkeley::update_primary_key(DB_TXN *trans, bool primary_key_changed,
Clobbers keybuff2
*/
int ha_berkeley::restore_keys(DB_TXN *trans, key_map changed_keys,
int ha_berkeley::restore_keys(DB_TXN *trans, key_map *changed_keys,
uint primary_key,
const byte *old_row, DBT *old_key,
const byte *new_row, DBT *new_key,
......@@ -1034,14 +1035,13 @@ int ha_berkeley::restore_keys(DB_TXN *trans, key_map changed_keys,
rolled back. The last key set in changed_keys is the one that
triggered the duplicate key error (it wasn't inserted), so for
that one just put back the old value. */
if (!changed_keys.is_clear_all())
if (!changed_keys->is_clear_all())
{
key_map map1(1);
for (keynr=0; keynr < changed_keys.length(); keynr++)
for (keynr=0 ; keynr < table->keys+test(hidden_primary_key) ; keynr++)
{
if (changed_keys.is_set(keynr))
if (changed_keys->is_set(keynr))
{
if (changed_keys.is_subset(map1) &&
if (changed_keys->is_prefix(1) &&
(error = remove_key(trans, keynr, new_row, new_key)))
break; /* purecov: inspected */
if ((error = key_file[keynr]->put(key_file[keynr], trans,
......@@ -1094,7 +1094,7 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
sub_trans = transaction;
for (uint retry=0 ; retry < berkeley_trans_retry ; retry++)
{
key_map changed_keys;
key_map changed_keys(0);
if (using_ignore && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
{
if ((error=txn_begin(db_env, transaction, &sub_trans, 0))) /* purecov: deadcode */
......@@ -1152,7 +1152,7 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
new_error=txn_abort(sub_trans); /* purecov: deadcode */
}
else if (!changed_keys.is_clear_all())
new_error=restore_keys(transaction, changed_keys, primary_key,
new_error=restore_keys(transaction, &changed_keys, primary_key,
old_row, &old_prim_key, new_row, &prim_key,
thd_options);
if (new_error)
......@@ -1233,12 +1233,12 @@ int ha_berkeley::remove_key(DB_TXN *trans, uint keynr, const byte *record,
/* Delete all keys for new_record */
int ha_berkeley::remove_keys(DB_TXN *trans, const byte *record,
DBT *new_record, DBT *prim_key, key_map keys)
DBT *new_record, DBT *prim_key, key_map *keys)
{
int result = 0;
for (uint keynr=0; keynr < keys.length(); keynr++)
for (uint keynr=0 ; keynr < table->keys+test(hidden_primary_key) ; keynr++)
{
if (keys.is_set(keynr))
if (keys->is_set(keynr))
{
int new_error=remove_key(trans, keynr, record, prim_key);
if (new_error)
......@@ -1278,7 +1278,7 @@ int ha_berkeley::delete_row(const byte * record)
break; /* purecov: deadcode */
DBUG_PRINT("trans",("starting sub transaction")); /* purecov: deadcode */
}
error=remove_keys(sub_trans, record, &row, &prim_key, keys);
error=remove_keys(sub_trans, record, &row, &prim_key, &keys);
if (!error && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
{
DBUG_PRINT("trans",("ending sub transaction")); /* purecov: deadcode */
......
......@@ -72,8 +72,8 @@ class ha_berkeley: public handler
uint key_length);
int remove_key(DB_TXN *trans, uint keynr, const byte *record, DBT *prim_key);
int remove_keys(DB_TXN *trans,const byte *record, DBT *new_record,
DBT *prim_key, key_map keys);
int restore_keys(DB_TXN *trans, key_map changed_keys, uint primary_key,
DBT *prim_key, key_map *keys);
int restore_keys(DB_TXN *trans, key_map *changed_keys, uint primary_key,
const byte *old_row, DBT *old_key,
const byte *new_row, DBT *new_key,
ulong thd_options);
......
......@@ -981,8 +981,8 @@ class Item_func_match :public Item_real_func
String value; // value of concat
String search_value; // key_item()'s value converted to cmp_collation
Item_func_match(List<Item> &a, uint b): Item_real_func(a), flags(b),
table(0), master(0), ft_handler(0), concat(0), key(0), join_key(0) { }
Item_func_match(List<Item> &a, uint b): Item_real_func(a), key(0), flags(b),
join_key(0), ft_handler(0), table(0), master(0), concat(0) { }
~Item_func_match()
{
if (!master && ft_handler)
......
......@@ -567,19 +567,29 @@ SEL_ARG *SEL_ARG::clone_tree()
return root;
}
/*****************************************************************************
** Test if a key can be used in different ranges
** Returns:
** -1 if impossible select
** 0 if can't use quick_select
** 1 if found usable range
** Updates the following in the select parameter:
** needed_reg ; Bits for keys with may be used if all prev regs are read
** quick ; Parameter to use when reading records.
** In the table struct the following information is updated:
** quick_keys ; Which keys can be used
** quick_rows ; How many rows the key matches
*****************************************************************************/
/*
Test if a key can be used in different ranges
SYNOPSIS
SQL_SELECT::test_quick_select(thd,keys_to_use, prev_tables,
limit, force_quick_range)
Updates the following in the select parameter:
needed_reg - Bits for keys with may be used if all prev regs are read
quick - Parameter to use when reading records.
In the table struct the following information is updated:
quick_keys - Which keys can be used
quick_rows - How many rows the key matches
RETURN VALUES
-1 if impossible select
0 if can't use quick_select
1 if found usable range
TODO
check if the function really needs to modify keys_to_use, and change the
code to pass it by reference if not
*/
int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
table_map prev_tables,
......
......@@ -16,6 +16,7 @@ template <uint default_width> class Bitmap
uchar buffer[(default_width+7)/8];
public:
Bitmap() { init(); }
Bitmap(Bitmap& from) { *this=from; }
Bitmap(uint prefix_to_set) { init(prefix_to_set); }
void init() { bitmap_init(&map, buffer, default_width, 0); }
void init(uint prefix_to_set) { init(); set_prefix(prefix_to_set); }
......@@ -24,6 +25,7 @@ template <uint default_width> class Bitmap
{
init();
memcpy(buffer, map2.buffer, sizeof(buffer));
return *this;
}
void set_bit(uint n) { bitmap_set_bit(&map, n); }
void clear_bit(uint n) { bitmap_clear_bit(&map, n); }
......
......@@ -1579,7 +1579,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
TABLE *table,
const key_map& keys,ha_rows limit)
const key_map *keys,ha_rows limit)
{
int error;
DBUG_ENTER("get_quick_record_count");
......@@ -1587,7 +1587,7 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
{
select->head=table;
table->reginfo.impossible_range=0;
if ((error=select->test_quick_select(thd, keys,(table_map) 0,limit))
if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,limit))
== 1)
DBUG_RETURN(select->quick->records);
if (error == -1)
......@@ -1876,7 +1876,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
s->on_expr ? s->on_expr : conds,
&error);
records= get_quick_record_count(join->thd, select, s->table,
s->const_keys, join->row_limit);
&s->const_keys, join->row_limit);
s->quick=select->quick;
s->needed_reg=select->needed_reg;
select->quick=0;
......@@ -2104,8 +2104,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
else
{
JOIN_TAB *stat=field->table->reginfo.join_tab;
key_map possible_keys;
possible_keys=field->key_start;
key_map possible_keys=field->key_start;
possible_keys.intersect(field->table->keys_in_use_for_query);
stat[0].keys.merge(possible_keys); // Add possible keys
......@@ -8777,7 +8776,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
uint j;
if (!tab->keys.is_clear_all())
{
for (j=0 ; j < tab->keys.length() ; j++)
for (j=0 ; j < table->keys ; j++)
{
if (tab->keys.is_set(j))
{
......
......@@ -156,9 +156,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
VOID(my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0)));
if (read_string(file,(gptr*) &disk_buff,key_info_length))
goto err_not_open; /* purecov: inspected */
if (disk_buff[1] & 0x80)
if (disk_buff[0] & 0x80)
{
outparam->keys= keys= uint2korr(disk_buff) & 0x7fff;
outparam->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
outparam->key_parts= key_parts= uint2korr(disk_buff+2);
}
else
......@@ -279,7 +279,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (my_pread(file,(byte*) record,(uint) outparam->reclength,
(ulong) (uint2korr(head+6)+
((uint2korr(head+14) == 0xffff ?
uint4korr(head+10) : uint2korr(head+14)))),
uint4korr(head+47) : uint2korr(head+14)))),
MYF(MY_NABP)))
goto err_not_open; /* purecov: inspected */
/* HACK: table->record[2] is used instead of table->default_values here */
......
......@@ -100,7 +100,8 @@ int rea_create_table(THD *thd, my_string file_name,
goto err;
maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo)+1000));
int2store(forminfo+2,maxlength);
int4store(fileinfo+10,key_buff_length);
int4store(fileinfo+10,(ulong) (filepos+maxlength));
int4store(fileinfo+47,key_buff_length);
fileinfo[26]= (uchar) test((create_info->max_rows == 1) &&
(create_info->min_rows == 1) && (keys == 0));
int2store(fileinfo+28,key_info_length);
......@@ -293,8 +294,8 @@ static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo)
if (key_count > 127 || key_parts > 127)
{
key_count|=0x8000;
int2store(keybuff,key_count);
keybuff[0]= (key_count & 0x7f) | 0x80;
keybuff[1]= key_count >> 7;
int2store(keybuff+2,key_parts);
}
else
......
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