Commit 6e17f4f2 authored by serg@serg.mylan's avatar serg@serg.mylan

fixes to Bitmap class

parent d74ecc07
...@@ -25,14 +25,13 @@ typedef struct st_bitmap ...@@ -25,14 +25,13 @@ typedef struct st_bitmap
{ {
uchar *bitmap; uchar *bitmap;
uint bitmap_size; uint bitmap_size;
my_bool thread_safe; /* set if several threads access the bitmap */
/* /*
mutex will be acquired for the duration of each bitmap operation if mutex will be acquired for the duration of each bitmap operation if
thread_safe flag is set. Otherwise, we optimize by not acquiring the thread_safe flag in bitmap_init was set. Otherwise, we optimize by not
mutex acquiring the mutex
*/ */
#ifdef THREAD #ifdef THREAD
pthread_mutex_t mutex; pthread_mutex_t *mutex;
#endif #endif
} MY_BITMAP; } MY_BITMAP;
......
...@@ -240,11 +240,11 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -240,11 +240,11 @@ id select_type table type possible_keys key key_len ref rows Extra
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1; explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where 1 SIMPLE t1 ref y y 5 const 1 Using where
1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map: 1) 1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map: 0x1)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1; explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where 1 SIMPLE t1 ref y y 5 const 1 Using where
1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map: 1) 1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map: 0x1)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 0 and t1.y; explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 0 and t1.y;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where 1 SIMPLE t1 ref y y 5 const 1 Using where
...@@ -267,11 +267,11 @@ INSERT INTO t2 VALUES (0),(0),(1),(1),(2),(2); ...@@ -267,11 +267,11 @@ INSERT INTO t2 VALUES (0),(0),(1),(1),(2),(2);
explain select * from t1, t2 where (t1.key1 <t2.keya + 1) and t2.keya=3; explain select * from t1, t2 where (t1.key1 <t2.keya + 1) and t2.keya=3;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref j1 j1 4 const 1 Using where; Using index 1 SIMPLE t2 ref j1 j1 4 const 1 Using where; Using index
1 SIMPLE t1 ALL i1,i2 NULL NULL NULL 4 Range checked for each record (index map: 3) 1 SIMPLE t1 ALL i1,i2 NULL NULL NULL 4 Range checked for each record (index map: 0x3)
explain select * from t1 force index(i2), t2 where (t1.key1 <t2.keya + 1) and t2.keya=3; explain select * from t1 force index(i2), t2 where (t1.key1 <t2.keya + 1) and t2.keya=3;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref j1 j1 4 const 1 Using where; Using index 1 SIMPLE t2 ref j1 j1 4 const 1 Using where; Using index
1 SIMPLE t1 ALL i2 NULL NULL NULL 4 Range checked for each record (index map: 2) 1 SIMPLE t1 ALL i2 NULL NULL NULL 4 Range checked for each record (index map: 0x2)
DROP TABLE t1,t2; DROP TABLE t1,t2;
create table t1 (id int(10) primary key); create table t1 (id int(10) primary key);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9); insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
......
...@@ -30,63 +30,67 @@ ...@@ -30,63 +30,67 @@
inline void bitmap_lock(MY_BITMAP *map) inline void bitmap_lock(MY_BITMAP *map)
{ {
#ifdef THREAD #ifdef THREAD
if (map->thread_safe) if (map->mutex)
pthread_mutex_lock(&map->mutex); pthread_mutex_lock(map->mutex);
#endif #endif
} }
inline void bitmap_unlock(MY_BITMAP *map) inline void bitmap_unlock(MY_BITMAP *map)
{ {
#ifdef THREAD #ifdef THREAD
if (map->thread_safe) if (map->mutex)
pthread_mutex_unlock(&map->mutex); pthread_mutex_unlock(map->mutex);
#endif #endif
} }
my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size, my_bool thread_safe) 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) && if (!(map->bitmap=buf) &&
!(map->bitmap=(uchar*) my_malloc((bitmap_size+7)/8, !(map->bitmap=(uchar*)my_malloc(bitmap_size + sizeof(pthread_mutex_t),
MYF(MY_WME | MY_ZEROFILL)))) MYF(MY_WME | MY_ZEROFILL))))
return 1; return 1;
DBUG_ASSERT(bitmap_size != ~(uint) 0); map->bitmap_size=bitmap_size;
#ifdef THREAD #ifdef THREAD
if ((map->thread_safe = thread_safe)) if (thread_safe)
pthread_mutex_init(&map->mutex, MY_MUTEX_INIT_FAST); {
map->mutex=(pthread_mutex_t *)(map->bitmap+bitmap_size);
pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST);
}
else
map->mutex=0;
#endif #endif
map->bitmap_size=bitmap_size;
return 0; return 0;
} }
void bitmap_free(MY_BITMAP *map) void bitmap_free(MY_BITMAP *map)
{ {
#ifdef THREAD
if (map->mutex)
pthread_mutex_destroy(map->mutex);
#endif
if (map->bitmap) if (map->bitmap)
{ {
my_free((char*) map->bitmap, MYF(0)); my_free((char*) map->bitmap, MYF(0));
map->bitmap=0; map->bitmap=0;
#ifdef THREAD
if (map->thread_safe)
pthread_mutex_destroy(&map->mutex);
#endif
} }
} }
void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit) void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
{ {
DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
if (bitmap_bit < map->bitmap_size)
{
bitmap_lock(map); bitmap_lock(map);
map->bitmap[bitmap_bit / 8] |= (1 << (bitmap_bit & 7)); map->bitmap[bitmap_bit / 8] |= (1 << (bitmap_bit & 7));
bitmap_unlock(map); bitmap_unlock(map);
}
} }
uint bitmap_set_next(MY_BITMAP *map) uint bitmap_set_next(MY_BITMAP *map)
{ {
uchar *bitmap=map->bitmap; uchar *bitmap=map->bitmap;
uint bit_found = MY_BIT_NONE; uint bit_found = MY_BIT_NONE;
uint bitmap_size=map->bitmap_size; uint bitmap_size=map->bitmap_size*8;
uint i; uint i;
DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map->bitmap);
...@@ -114,28 +118,25 @@ uint bitmap_set_next(MY_BITMAP *map) ...@@ -114,28 +118,25 @@ uint bitmap_set_next(MY_BITMAP *map)
void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit) void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit)
{ {
DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
if (bitmap_bit < map->bitmap_size)
{
bitmap_lock(map); bitmap_lock(map);
map->bitmap[bitmap_bit / 8] &= ~ (1 << (bitmap_bit & 7)); map->bitmap[bitmap_bit / 8] &= ~ (1 << (bitmap_bit & 7));
bitmap_unlock(map); bitmap_unlock(map);
}
} }
void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
{ {
uint l, m; uint prefix_bytes, prefix_bits;
DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map->bitmap);
bitmap_lock(map); bitmap_lock(map);
set_if_smaller(prefix_size, map->bitmap_size); set_if_smaller(prefix_size, map->bitmap_size*8);
if ((l=prefix_size / 8)) if ((prefix_bytes= prefix_size / 8))
memset(map->bitmap, 0xff, l); memset(map->bitmap, 0xff, prefix_bytes);
if ((m=prefix_size & 7)) if ((prefix_bits= prefix_size & 7))
map->bitmap[l++]= (1 << m)-1; map->bitmap[prefix_bytes++]= (1 << prefix_bits)-1;
if (l < (m=(map->bitmap_size+7)/8)) if (prefix_bytes < map->bitmap_size)
bzero(map->bitmap+l, m-l); bzero(map->bitmap+prefix_bytes, map->bitmap_size-prefix_bytes);
bitmap_unlock(map); bitmap_unlock(map);
} }
...@@ -146,27 +147,27 @@ void bitmap_clear_all(MY_BITMAP *map) ...@@ -146,27 +147,27 @@ void bitmap_clear_all(MY_BITMAP *map)
void bitmap_set_all(MY_BITMAP *map) void bitmap_set_all(MY_BITMAP *map)
{ {
bitmap_set_prefix(map, map->bitmap_size); bitmap_set_prefix(map, ~0);
} }
my_bool bitmap_is_prefix(MY_BITMAP *map, uint prefix_size) my_bool bitmap_is_prefix(MY_BITMAP *map, uint prefix_size)
{ {
uint l=prefix_size/8, m=prefix_size & 7, i, res=0; uint prefix_bits= prefix_size & 7, res= 0;
uchar *m= map->bitmap, *end_prefix= map->bitmap+prefix_size/8,
*end= map->bitmap+map->bitmap_size;
DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map->bitmap && prefix_size <= map->bitmap_size*8);
if (prefix_size > map->bitmap_size)
return 0;
bitmap_lock(map); bitmap_lock(map);
for (i=0; i < l; i++) while (m < end_prefix)
if (map->bitmap[i] != 0xff) if (*m++ != 0xff)
goto ret; goto ret;
if (m && map->bitmap[i++] != (1 << m)-1) if (prefix_bits && *m++ != (1 << prefix_bits)-1)
goto ret; goto ret;
for (m=(map->bitmap_size+7)/8; i < m; i++) while (m < end)
if (map->bitmap[i] != 0) if (m++ != 0)
goto ret; goto ret;
res=1; res=1;
...@@ -182,38 +183,31 @@ my_bool bitmap_is_clear_all(MY_BITMAP *map) ...@@ -182,38 +183,31 @@ my_bool bitmap_is_clear_all(MY_BITMAP *map)
my_bool bitmap_is_set_all(MY_BITMAP *map) my_bool bitmap_is_set_all(MY_BITMAP *map)
{ {
return bitmap_is_prefix(map, map->bitmap_size); 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(MY_BITMAP *map, uint bitmap_bit)
{ {
DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
return (bitmap_bit < map->bitmap_size) ? return map->bitmap[bitmap_bit / 8] & (1 << (bitmap_bit & 7));
(map->bitmap[bitmap_bit / 8] & (1 << (bitmap_bit & 7))) : 0;
} }
my_bool bitmap_is_subset(MY_BITMAP *map1, MY_BITMAP *map2) my_bool bitmap_is_subset(MY_BITMAP *map1, MY_BITMAP *map2)
{ {
uint l1, l2, i, res=0; uint length, res=0;
uchar *m1=map1->bitmap, *m2=map2->bitmap; uchar *m1=map1->bitmap, *m2=map2->bitmap, *end;
DBUG_ASSERT(map1->bitmap); DBUG_ASSERT(map1->bitmap && map2->bitmap &&
DBUG_ASSERT(map2->bitmap); map1->bitmap_size==map2->bitmap_size);
bitmap_lock(map1); bitmap_lock(map1);
bitmap_lock(map2); bitmap_lock(map2);
l1=(map1->bitmap_size+7)/8; end= m1+map1->bitmap_size;
l2=(map2->bitmap_size+7)/8;
set_if_smaller(l2, l1);
for (i=0; i < l2; i++) while (m1 < end)
if ((*m1++) & ~(*m2++)) if ((*m1++) & ~(*m2++))
goto ret; goto ret;
for (; i < l1; i++)
if (*m1++)
goto ret;
res=1; res=1;
ret: ret:
bitmap_unlock(map2); bitmap_unlock(map2);
...@@ -225,13 +219,12 @@ my_bool bitmap_cmp(MY_BITMAP *map1, MY_BITMAP *map2) ...@@ -225,13 +219,12 @@ my_bool bitmap_cmp(MY_BITMAP *map1, MY_BITMAP *map2)
{ {
uint res; uint res;
DBUG_ASSERT(map1->bitmap); DBUG_ASSERT(map1->bitmap && map2->bitmap &&
DBUG_ASSERT(map2->bitmap); map1->bitmap_size==map2->bitmap_size);
bitmap_lock(map1); bitmap_lock(map1);
bitmap_lock(map2); bitmap_lock(map2);
res= map1->bitmap_size == map2->bitmap_size && res= memcmp(map1->bitmap, map2->bitmap, map1->bitmap_size)==0;
memcmp(map1->bitmap, map2->bitmap, (map1->bitmap_size+7)/8)==0;
bitmap_unlock(map2); bitmap_unlock(map2);
bitmap_unlock(map1); bitmap_unlock(map1);
...@@ -240,23 +233,17 @@ my_bool bitmap_cmp(MY_BITMAP *map1, MY_BITMAP *map2) ...@@ -240,23 +233,17 @@ my_bool bitmap_cmp(MY_BITMAP *map1, MY_BITMAP *map2)
void bitmap_intersect(MY_BITMAP *map, MY_BITMAP *map2) void bitmap_intersect(MY_BITMAP *map, MY_BITMAP *map2)
{ {
uint l1, l2, i; uchar *to=map->bitmap, *from=map2->bitmap, *end;
uchar *m=map->bitmap, *m2=map2->bitmap;
DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map->bitmap && map2->bitmap &&
DBUG_ASSERT(map2->bitmap); map->bitmap_size==map2->bitmap_size);
bitmap_lock(map); bitmap_lock(map);
bitmap_lock(map2); bitmap_lock(map2);
l1=(map->bitmap_size+7)/8; end= to+map->bitmap_size;
l2=(map2->bitmap_size+7)/8;
set_if_smaller(l2, l1);
for (i=0; i < l2; i++)
*m++ &= *m2++;
if (l1 > l2) while (to < end)
bzero(m, l1-l2); *to++ &= *from++;
bitmap_unlock(map2); bitmap_unlock(map2);
bitmap_unlock(map); bitmap_unlock(map);
...@@ -264,20 +251,17 @@ void bitmap_intersect(MY_BITMAP *map, MY_BITMAP *map2) ...@@ -264,20 +251,17 @@ void bitmap_intersect(MY_BITMAP *map, MY_BITMAP *map2)
void bitmap_subtract(MY_BITMAP *map, MY_BITMAP *map2) void bitmap_subtract(MY_BITMAP *map, MY_BITMAP *map2)
{ {
uint l1, l2, i; uchar *to=map->bitmap, *from=map2->bitmap, *end;
uchar *m=map->bitmap, *m2=map2->bitmap;
DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map->bitmap && map2->bitmap &&
DBUG_ASSERT(map2->bitmap); map->bitmap_size==map2->bitmap_size);
bitmap_lock(map); bitmap_lock(map);
bitmap_lock(map2); bitmap_lock(map2);
l1=(map->bitmap_size+7)/8; end= to+map->bitmap_size;
l2=(map2->bitmap_size+7)/8;
set_if_smaller(l2, l1);
for (i=0; i < l2; i++) while (to < end)
*m++ &= ~(*m2++); *to++ &= ~(*from++);
bitmap_unlock(map2); bitmap_unlock(map2);
bitmap_unlock(map); bitmap_unlock(map);
...@@ -285,20 +269,17 @@ void bitmap_subtract(MY_BITMAP *map, MY_BITMAP *map2) ...@@ -285,20 +269,17 @@ void bitmap_subtract(MY_BITMAP *map, MY_BITMAP *map2)
void bitmap_union(MY_BITMAP *map, MY_BITMAP *map2) void bitmap_union(MY_BITMAP *map, MY_BITMAP *map2)
{ {
uint l1, l2, i; uchar *to=map->bitmap, *from=map2->bitmap, *end;
uchar *m=map->bitmap, *m2=map2->bitmap;
DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map->bitmap && map2->bitmap &&
DBUG_ASSERT(map2->bitmap); map->bitmap_size==map2->bitmap_size);
bitmap_lock(map); bitmap_lock(map);
bitmap_lock(map2); bitmap_lock(map2);
l1=(map->bitmap_size+7)/8; end= to+map->bitmap_size;
l2=(map2->bitmap_size+7)/8;
set_if_smaller(l2, l1);
for (i=0; i < l2; i++) while (to < end)
*m++ |= *m2++; *to++ |= *from++;
bitmap_unlock(map2); bitmap_unlock(map2);
bitmap_unlock(map); bitmap_unlock(map);
......
...@@ -181,7 +181,8 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, ...@@ -181,7 +181,8 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
:ptr(ptr_arg),null_ptr(null_ptr_arg), :ptr(ptr_arg),null_ptr(null_ptr_arg),
table(table_arg),table_name(table_arg ? table_arg->table_name : 0), table(table_arg),table_name(table_arg ? table_arg->table_name : 0),
field_name(field_name_arg), field_name(field_name_arg),
query_id(0),unireg_check(unireg_check_arg), query_id(0), key_start(0), part_of_key(0), part_of_sortkey(0),
unireg_check(unireg_check_arg),
field_length(length_arg),null_bit(null_bit_arg),abs_offset(0) field_length(length_arg),null_bit(null_bit_arg),abs_offset(0)
{ {
flags=null_ptr ? 0: NOT_NULL_FLAG; flags=null_ptr ? 0: NOT_NULL_FLAG;
......
...@@ -151,9 +151,9 @@ class Field ...@@ -151,9 +151,9 @@ class Field
if (tmp->table->maybe_null) if (tmp->table->maybe_null)
tmp->flags&= ~NOT_NULL_FLAG; tmp->flags&= ~NOT_NULL_FLAG;
tmp->table= new_table; tmp->table= new_table;
tmp->key_start.init().clear_all(); tmp->key_start.init(0);
tmp->part_of_key.init().clear_all(); tmp->part_of_key.init(0);
tmp->part_of_sortkey.init().clear_all(); tmp->part_of_sortkey.init(0);
tmp->unireg_check=Field::NONE; tmp->unireg_check=Field::NONE;
tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG); ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
......
...@@ -107,7 +107,7 @@ class ha_berkeley: public handler ...@@ -107,7 +107,7 @@ class ha_berkeley: public handler
uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; } uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; }
ha_rows estimate_number_of_rows(); ha_rows estimate_number_of_rows();
bool fast_key_read() { return 1;} bool fast_key_read() { return 1;}
const key_map& keys_to_use_for_scanning() { return key_map_full; } const key_map *keys_to_use_for_scanning() { return &key_map_full; }
bool has_transactions() { return 1;} bool has_transactions() { return 1;}
int open(const char *name, int mode, uint test_if_locked); int open(const char *name, int mode, uint test_if_locked);
......
...@@ -125,7 +125,7 @@ class ha_innobase: public handler ...@@ -125,7 +125,7 @@ class ha_innobase: public handler
uint max_key_length() const { return((MAX_KEY_LENGTH <= 3500) ? uint max_key_length() const { return((MAX_KEY_LENGTH <= 3500) ?
MAX_KEY_LENGTH : 3500);} MAX_KEY_LENGTH : 3500);}
bool fast_key_read() { return 1;} bool fast_key_read() { return 1;}
const key_map& keys_to_use_for_scanning() { return key_map_full; } const key_map *keys_to_use_for_scanning() { return &key_map_full; }
bool has_transactions() { return 1;} bool has_transactions() { return 1;}
int open(const char *name, int mode, uint test_if_locked); int open(const char *name, int mode, uint test_if_locked);
......
...@@ -1023,7 +1023,8 @@ void ha_myisam::info(uint flag) ...@@ -1023,7 +1023,8 @@ void ha_myisam::info(uint flag)
ref_length=info.reflength; ref_length=info.reflength;
table->db_options_in_use = info.options; table->db_options_in_use = info.options;
block_size=myisam_block_size; block_size=myisam_block_size;
table->keys_in_use.set_prefix(table->keys).intersect(info.key_map); table->keys_in_use.set_prefix(table->keys);
table->keys_in_use.intersect(info.key_map);
table->keys_for_keyread= table->keys_in_use; table->keys_for_keyread= table->keys_in_use;
table->keys_for_keyread.subtract(table->read_only_keys); table->keys_for_keyread.subtract(table->read_only_keys);
table->db_record_offset=info.record_offset; table->db_record_offset=info.record_offset;
......
...@@ -241,7 +241,7 @@ class handler :public Sql_alloc ...@@ -241,7 +241,7 @@ class handler :public Sql_alloc
virtual double read_time(uint index, uint ranges, ha_rows rows) virtual double read_time(uint index, uint ranges, ha_rows rows)
{ return rows2double(ranges+rows); } { return rows2double(ranges+rows); }
virtual bool fast_key_read() { return 0;} virtual bool fast_key_read() { return 0;}
virtual const key_map& keys_to_use_for_scanning() { return key_map_empty; } virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; }
virtual bool has_transactions(){ return 0;} virtual bool has_transactions(){ return 0;}
virtual uint extra_rec_buf_length() { return 0; } virtual uint extra_rec_buf_length() { return 0; }
virtual ha_rows estimate_number_of_rows() { return records+EXTRA_RECORDS; } virtual ha_rows estimate_number_of_rows() { return records+EXTRA_RECORDS; }
......
...@@ -23,113 +23,13 @@ ...@@ -23,113 +23,13 @@
#include <signal.h> #include <signal.h>
#include <thr_lock.h> #include <thr_lock.h>
#include <my_base.h> /* Needed by field.h */ #include <my_base.h> /* Needed by field.h */
#include <my_bitmap.h> #include <sql_bitmap.h>
#include <assert.h> #include <assert.h>
#ifdef __EMX__ #ifdef __EMX__
#undef write /* remove pthread.h macro definition for EMX */ #undef write /* remove pthread.h macro definition for EMX */
#endif #endif
template <uint default_width> class Bitmap
{
MY_BITMAP map;
uchar buffer[(default_width+7)/8];
public:
Bitmap(uint prefix_to_set=0) { init(); set_prefix(prefix_to_set); }
Bitmap& init()
{
bitmap_init(&map, buffer, default_width, 0);
return *this;
}
uint length() const { return default_width; }
Bitmap& operator=(const Bitmap& map2)
{
init();
memcpy(buffer, map2.buffer, sizeof(buffer));
return *this;
}
Bitmap& set_bit(uint n) { bitmap_set_bit(&map, n); return *this; }
Bitmap& clear_bit(uint n) { bitmap_clear_bit(&map, n); return *this; }
Bitmap& set_prefix(uint n) { bitmap_set_prefix(&map, n); return *this; }
Bitmap& set_all() { bitmap_set_all(&map); return *this;}
Bitmap& clear_all() { bitmap_clear_all(&map); return *this; }
Bitmap& intersect(Bitmap& map2) { bitmap_intersect(&map, &map2.map); return *this; }
Bitmap& intersect(ulonglong map2buff)
{
MY_BITMAP map2;
bitmap_init(&map2, (uchar *)&map2buff, sizeof(ulonglong)*8, 0);
bitmap_intersect(&map, &map2);
return *this;
}
Bitmap& subtract(Bitmap& map2) { bitmap_subtract(&map, &map2.map); return *this; }
Bitmap& merge(Bitmap& map2) { bitmap_union(&map, &map2.map); return *this; }
my_bool is_set(uint n) const { return bitmap_is_set((MY_BITMAP*)&map, n); }
my_bool is_prefix(uint n) const { return bitmap_is_prefix((MY_BITMAP*)&map, n); }
my_bool is_clear_all() const { return bitmap_is_clear_all((MY_BITMAP*)&map); }
my_bool is_set_all() const { return bitmap_is_set_all((MY_BITMAP*)&map); }
my_bool is_subset(const Bitmap& map2) const { return bitmap_is_subset((MY_BITMAP*)&map, (MY_BITMAP*)&map2.map); }
my_bool operator==(const Bitmap& map2) const { return bitmap_cmp((MY_BITMAP*)&map, (MY_BITMAP*)&map2.map); }
char *print(char *buf) const
{
char *s=buf; int i;
for (i=sizeof(buffer)-1; i>=0 ; i--)
{
if ((*s=_dig_vec[buffer[i] >> 4]) != '0')
break;
if ((*s=_dig_vec[buffer[i] & 15]) != '0')
break;
}
for (s++, i-- ; i>=0 ; i--)
{
*s++=_dig_vec[buffer[i] >> 4];
*s++=_dig_vec[buffer[i] & 15];
}
*s=0;
return buf;
}
ulonglong to_ulonglong() const
{
if (sizeof(buffer) >= sizeof(ulonglong))
return *(ulonglong*)buffer;
ulonglong x=0;
memcpy(&x, buffer, sizeof(buffer));
return x;
}
};
template <> class Bitmap<64>
{
ulonglong map;
public:
Bitmap(uint prefix_to_set=0) { set_prefix(prefix_to_set); }
Bitmap<64>& init() { return *this; }
uint length() const { return 64; }
Bitmap<64>& set_bit(uint n) { map|= ((ulonglong)1) << n; return *this; }
Bitmap<64>& clear_bit(uint n) { map&= ~(((ulonglong)1) << n); return *this; }
Bitmap<64>& set_prefix(uint n)
{
if (n >= length())
set_all();
else
map= (((ulonglong)1) << n)-1;
return *this;
}
Bitmap<64>& set_all() { map=~(ulonglong)0; return *this;}
Bitmap<64>& clear_all() { map=(ulonglong)0; return *this; }
Bitmap<64>& intersect(Bitmap<64>& map2) { map&= map2.map; return *this; }
Bitmap<64>& intersect(ulonglong map2) { map&= map2; return *this; }
Bitmap<64>& subtract(Bitmap<64>& map2) { map&= ~map2.map; return *this; }
Bitmap<64>& merge(Bitmap<64>& map2) { map|= map2.map; return *this; }
my_bool is_set(uint n) const { return test(map & (((ulonglong)1) << n)); }
my_bool is_prefix(uint n) const { return map == (((ulonglong)1) << n)-1; }
my_bool is_clear_all() const { return map == (ulonglong)0; }
my_bool is_set_all() const { return map == ~(ulonglong)0; }
my_bool is_subset(const Bitmap<64>& map2) const { return !(map & ~map2.map); }
my_bool operator==(const Bitmap<64>& map2) const { return map == map2.map; }
char *print(char *buf) const { longlong2str(map,buf,16); return buf; }
ulonglong to_ulonglong() const { return map; }
};
/* TODO convert all these three maps to Bitmap classes */ /* TODO convert all these three maps to Bitmap classes */
typedef ulonglong table_map; /* Used for table bits in join */ typedef ulonglong table_map; /* Used for table bits in join */
typedef Bitmap<64> key_map; /* Used for finding keys */ typedef Bitmap<64> key_map; /* Used for finding keys */
......
...@@ -305,7 +305,7 @@ static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree, ...@@ -305,7 +305,7 @@ static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree,
static QUICK_SELECT *get_quick_select(PARAM *param,uint index, static QUICK_SELECT *get_quick_select(PARAM *param,uint index,
SEL_ARG *key_tree); SEL_ARG *key_tree);
#ifndef DBUG_OFF #ifndef DBUG_OFF
static void print_quick(QUICK_SELECT *quick,const key_map& needed_reg); static void print_quick(QUICK_SELECT *quick,const key_map* needed_reg);
#endif #endif
static SEL_TREE *tree_and(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2); static SEL_TREE *tree_and(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2);
static SEL_TREE *tree_or(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2); static SEL_TREE *tree_or(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2);
...@@ -364,6 +364,7 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, ...@@ -364,6 +364,7 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
SQL_SELECT::SQL_SELECT() :quick(0),cond(0),free_cond(0) SQL_SELECT::SQL_SELECT() :quick(0),cond(0),free_cond(0)
{ {
quick_keys.clear_all(); needed_reg.clear_all();
my_b_clear(&file); my_b_clear(&file);
} }
...@@ -588,9 +589,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -588,9 +589,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
uint idx; uint idx;
double scan_time; double scan_time;
DBUG_ENTER("test_quick_select"); DBUG_ENTER("test_quick_select");
/* DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu", DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
(ulong) keys_to_use, (ulong) prev_tables, keys_to_use.to_ulonglong(), (ulong) prev_tables,
(ulong) const_tables));*/ (ulong) const_tables));
delete quick; delete quick;
quick=0; quick=0;
...@@ -743,7 +744,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -743,7 +744,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
my_pthread_setspecific_ptr(THR_MALLOC,old_root); my_pthread_setspecific_ptr(THR_MALLOC,old_root);
thd->no_errors=0; thd->no_errors=0;
} }
DBUG_EXECUTE("info",print_quick(quick,needed_reg);); DBUG_EXECUTE("info",print_quick(quick,&needed_reg););
/* /*
Assume that if the user is using 'limit' we will only need to scan Assume that if the user is using 'limit' we will only need to scan
limit rows if we are using a key limit rows if we are using a key
...@@ -2869,7 +2870,7 @@ print_key(KEY_PART *key_part,const char *key,uint used_length) ...@@ -2869,7 +2870,7 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
} }
} }
static void print_quick(QUICK_SELECT *quick,const key_map& needed_reg) static void print_quick(QUICK_SELECT *quick,const key_map* needed_reg)
{ {
QUICK_RANGE *range; QUICK_RANGE *range;
char buf[MAX_KEY/8+1]; char buf[MAX_KEY/8+1];
...@@ -2879,8 +2880,8 @@ static void print_quick(QUICK_SELECT *quick,const key_map& needed_reg) ...@@ -2879,8 +2880,8 @@ static void print_quick(QUICK_SELECT *quick,const key_map& needed_reg)
List_iterator<QUICK_RANGE> li(quick->ranges); List_iterator<QUICK_RANGE> li(quick->ranges);
DBUG_LOCK_FILE; DBUG_LOCK_FILE;
fprintf(DBUG_FILE,"Used quick_range on key: %d (other_keys: %s):\n", fprintf(DBUG_FILE,"Used quick_range on key: %d (other_keys: 0x%s):\n",
quick->index, needed_reg.print(buf)); quick->index, needed_reg->print(buf));
while ((range=li++)) while ((range=li++))
{ {
if (!(range->flag & NO_MIN_RANGE)) if (!(range->flag & NO_MIN_RANGE))
......
...@@ -128,7 +128,7 @@ class SQL_SELECT :public Sql_alloc { ...@@ -128,7 +128,7 @@ class SQL_SELECT :public Sql_alloc {
SQL_SELECT(); SQL_SELECT();
~SQL_SELECT(); ~SQL_SELECT();
bool check_quick(THD *thd, bool force_quick_range, ha_rows limit) bool check_quick(THD *thd, bool force_quick_range, ha_rows limit)
{ return test_quick_select(thd, key_map(~0L),0,limit, force_quick_range) < 0; } { return test_quick_select(thd, key_map(~0), 0, limit, force_quick_range) < 0; }
inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; } inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; }
int test_quick_select(THD *thd, key_map keys, table_map prev_tables, int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
ha_rows limit, bool force_quick_range=0); ha_rows limit, bool force_quick_range=0);
......
#include <my_global.h>
//#include <mysql_version.h>
//#include <mysql_embed.h>
//#include <my_sys.h>
//#include <m_string.h>
//#include <hash.h>
//#include <signal.h>
//#include <thr_lock.h>
//#include <my_base.h>
#include <my_bitmap.h>
#include <assert.h>
template <uint default_width> class Bitmap
{
MY_BITMAP map;
uchar buffer[(default_width+7)/8];
public:
Bitmap() { init(); }
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); }
uint length() const { return default_width; }
Bitmap& operator=(const Bitmap& map2)
{
init();
memcpy(buffer, map2.buffer, sizeof(buffer));
}
void set_bit(uint n) { bitmap_set_bit(&map, n); }
void clear_bit(uint n) { bitmap_clear_bit(&map, n); }
void set_prefix(uint n) { bitmap_set_prefix(&map, n); }
void set_all() { bitmap_set_all(&map); }
void clear_all() { bitmap_clear_all(&map); }
void intersect(Bitmap& map2) { bitmap_intersect(&map, &map2.map); }
void intersect(ulonglong map2buff)
{
MY_BITMAP map2;
bitmap_init(&map2, (uchar *)&map2buff, sizeof(ulonglong)*8, 0);
bitmap_intersect(&map, &map2);
}
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); }
my_bool is_prefix(uint n) const { return bitmap_is_prefix(&map, n); }
my_bool is_clear_all() const { return bitmap_is_clear_all(&map); }
my_bool is_set_all() const { return bitmap_is_set_all(&map); }
my_bool is_subset(const Bitmap& map2) const { return bitmap_is_subset(&map, &map2.map); }
my_bool operator==(const Bitmap& map2) const { return bitmap_cmp(&map, &map2.map); }
char *print(char *buf) const
{
char *s=buf; int i;
for (i=sizeof(buffer)-1; i>=0 ; i--)
{
if ((*s=_dig_vec[buffer[i] >> 4]) != '0')
break;
if ((*s=_dig_vec[buffer[i] & 15]) != '0')
break;
}
for (s++, i-- ; i>=0 ; i--)
{
*s++=_dig_vec[buffer[i] >> 4];
*s++=_dig_vec[buffer[i] & 15];
}
*s=0;
return buf;
}
ulonglong to_ulonglong() const
{
if (sizeof(buffer) >= 8)
return uint8korr(buffer);
DBUG_ASSERT(sizeof(buffer) >= 4);
uint4korr(buffer);
}
};
template <> class Bitmap<64>
{
ulonglong map;
public:
Bitmap<64>() { }
Bitmap<64>(uint prefix_to_set) { set_prefix(prefix_to_set); }
void init() { }
void init(uint prefix_to_set) { set_prefix(prefix_to_set); }
uint length() const { return 64; }
void set_bit(uint n) { map|= ((ulonglong)1) << n; }
void clear_bit(uint n) { map&= ~(((ulonglong)1) << n); }
void set_prefix(uint n)
{
if (n >= length())
set_all();
else
map= (((ulonglong)1) << n)-1;
}
void set_all() { map=~(ulonglong)0; }
void clear_all() { map=(ulonglong)0; }
void intersect(Bitmap<64>& map2) { map&= map2.map; }
void intersect(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)); }
my_bool is_prefix(uint n) const { return map == (((ulonglong)1) << n)-1; }
my_bool is_clear_all() const { return map == (ulonglong)0; }
my_bool is_set_all() const { return map == ~(ulonglong)0; }
my_bool is_subset(const Bitmap<64>& map2) const { return !(map & ~map2.map); }
my_bool operator==(const Bitmap<64>& map2) const { return map == map2.map; }
char *print(char *buf) const { longlong2str(map,buf,16); return buf; }
ulonglong to_ulonglong() const { return map; }
};
...@@ -117,7 +117,7 @@ static int join_read_next_same_or_null(READ_RECORD *info); ...@@ -117,7 +117,7 @@ static int join_read_next_same_or_null(READ_RECORD *info);
static COND *make_cond_for_table(COND *cond,table_map table, static COND *make_cond_for_table(COND *cond,table_map table,
table_map used_table); table_map used_table);
static Item* part_of_refkey(TABLE *form,Field *field); static Item* part_of_refkey(TABLE *form,Field *field);
static uint find_shortest_key(TABLE *table, const key_map& usable_keys); static uint find_shortest_key(TABLE *table, const key_map *usable_keys);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order, static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
ha_rows select_limit, bool no_changes); ha_rows select_limit, bool no_changes);
static int create_sort_index(THD *thd, JOIN *join, ORDER *order, static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
...@@ -3257,13 +3257,13 @@ make_simple_join(JOIN *join,TABLE *tmp_table) ...@@ -3257,13 +3257,13 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join->row_limit=join->unit->select_limit_cnt; join->row_limit=join->unit->select_limit_cnt;
join->do_send_rows = (join->row_limit) ? 1 : 0; join->do_send_rows = (join->row_limit) ? 1 : 0;
join_tab->cache.buff=0; /* No cacheing */ join_tab->cache.buff=0; /* No caching */
join_tab->table=tmp_table; join_tab->table=tmp_table;
join_tab->select=0; join_tab->select=0;
join_tab->select_cond=0; join_tab->select_cond=0;
join_tab->quick=0; join_tab->quick=0;
join_tab->type= JT_ALL; /* Map through all records */ join_tab->type= JT_ALL; /* Map through all records */
join_tab->keys.init().set_all(); /* test everything in quick */ join_tab->keys.init(~0); /* test everything in quick */
join_tab->info=0; join_tab->info=0;
join_tab->on_expr=0; join_tab->on_expr=0;
join_tab->ref.key = -1; join_tab->ref.key = -1;
...@@ -3591,7 +3591,7 @@ make_join_readinfo(JOIN *join, uint options) ...@@ -3591,7 +3591,7 @@ make_join_readinfo(JOIN *join, uint options)
} }
else if (!table->used_keys.is_clear_all() && ! (tab->select && tab->select->quick)) else if (!table->used_keys.is_clear_all() && ! (tab->select && tab->select->quick))
{ // Only read index tree { // Only read index tree
tab->index=find_shortest_key(table, table->used_keys); tab->index=find_shortest_key(table, & table->used_keys);
tab->table->file->index_init(tab->index); tab->table->file->index_init(tab->index);
tab->read_first_record= join_read_first; tab->read_first_record= join_read_first;
tab->type=JT_NEXT; // Read with index_first / index_next tab->type=JT_NEXT; // Read with index_first / index_next
...@@ -6605,15 +6605,15 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, ...@@ -6605,15 +6605,15 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
return reverse; return reverse;
} }
static uint find_shortest_key(TABLE *table, const key_map& usable_keys) static uint find_shortest_key(TABLE *table, const key_map *usable_keys)
{ {
uint min_length= (uint) ~0; uint min_length= (uint) ~0;
uint best= MAX_KEY; uint best= MAX_KEY;
if (!usable_keys.is_clear_all()) if (!usable_keys->is_clear_all())
{ {
for (uint nr=0; nr < usable_keys.length() ; nr++) for (uint nr=0; nr < table->keys ; nr++)
{ {
if (usable_keys.is_set(nr)) if (usable_keys->is_set(nr))
{ {
if (table->key_info[nr].key_length < min_length) if (table->key_info[nr].key_length < min_length)
{ {
...@@ -6674,7 +6674,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts, ...@@ -6674,7 +6674,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
KEY_PART_INFO *ref_key_part= table->key_info[ref].key_part; KEY_PART_INFO *ref_key_part= table->key_info[ref].key_part;
KEY_PART_INFO *ref_key_part_end= ref_key_part + ref_key_parts; KEY_PART_INFO *ref_key_part_end= ref_key_part + ref_key_parts;
for (nr= 0; nr < usable_keys.length(); nr++) for (nr= 0 ; nr < table->keys ; nr++)
{ {
if (usable_keys.is_set(nr) && if (usable_keys.is_set(nr) &&
table->key_info[nr].key_length < min_length && table->key_info[nr].key_length < min_length &&
...@@ -6840,7 +6840,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -6840,7 +6840,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*/ */
if (select_limit >= table->file->records) if (select_limit >= table->file->records)
{ {
keys=table->file->keys_to_use_for_scanning(); keys=*table->file->keys_to_use_for_scanning();
keys.merge(table->used_keys); keys.merge(table->used_keys);
} }
else else
...@@ -6848,7 +6848,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -6848,7 +6848,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
keys.intersect(usable_keys); keys.intersect(usable_keys);
for (nr=0; nr < keys.length() ; nr++) for (nr=0; nr < table->keys ; nr++)
{ {
uint not_used; uint not_used;
if (keys.is_set(nr)) if (keys.is_set(nr))
...@@ -8845,7 +8845,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -8845,7 +8845,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (tab->use_quick == 2) if (tab->use_quick == 2)
{ {
char buf[MAX_KEY/8+1]; char buf[MAX_KEY/8+1];
sprintf(buff_ptr,"; Range checked for each record (index map: %s)", sprintf(buff_ptr,"; Range checked for each record (index map: 0x%s)",
tab->keys.print(buf)); tab->keys.print(buf));
buff_ptr=strend(buff_ptr); buff_ptr=strend(buff_ptr);
} }
......
...@@ -166,9 +166,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ...@@ -166,9 +166,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
outparam->keys= keys= disk_buff[0]; outparam->keys= keys= disk_buff[0];
outparam->key_parts= key_parts= disk_buff[1]; outparam->key_parts= key_parts= disk_buff[1];
} }
outparam->keys_for_keyread.init().set_prefix(keys); outparam->keys_for_keyread.init(keys);
outparam->keys_in_use.init().set_prefix(keys); outparam->keys_in_use.init(keys);
outparam->read_only_keys.init().clear_all(); outparam->read_only_keys.init(0);
outparam->quick_keys.init(); outparam->quick_keys.init();
outparam->used_keys.init(); outparam->used_keys.init();
outparam->keys_in_use_for_query.init(); outparam->keys_in_use_for_query.init();
......
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