mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
fixes to Bitmap class
This commit is contained in:
@ -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
|
|||||||
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);
|
|||||||
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 @@
|
|||||||
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);
|
|
||||||
#ifdef THREAD
|
|
||||||
if ((map->thread_safe = thread_safe))
|
|
||||||
pthread_mutex_init(&map->mutex, MY_MUTEX_INIT_FAST);
|
|
||||||
#endif
|
|
||||||
map->bitmap_size=bitmap_size;
|
map->bitmap_size=bitmap_size;
|
||||||
|
#ifdef THREAD
|
||||||
|
if (thread_safe)
|
||||||
|
{
|
||||||
|
map->mutex=(pthread_mutex_t *)(map->bitmap+bitmap_size);
|
||||||
|
pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
map->mutex=0;
|
||||||
|
#endif
|
||||||
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);
|
||||||
{
|
map->bitmap[bitmap_bit / 8] |= (1 << (bitmap_bit & 7));
|
||||||
bitmap_lock(map);
|
bitmap_unlock(map);
|
||||||
map->bitmap[bitmap_bit / 8] |= (1 << (bitmap_bit & 7));
|
|
||||||
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)
|
|||||||
|
|
||||||
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);
|
||||||
{
|
map->bitmap[bitmap_bit / 8] &= ~ (1 << (bitmap_bit & 7));
|
||||||
bitmap_lock(map);
|
bitmap_unlock(map);
|
||||||
map->bitmap[bitmap_bit / 8] &= ~ (1 << (bitmap_bit & 7));
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
|
|
||||||
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++)
|
while (to < end)
|
||||||
*m++ &= *m2++;
|
*to++ &= *from++;
|
||||||
|
|
||||||
if (l1 > l2)
|
|
||||||
bzero(m, l1-l2);
|
|
||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
: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 @@ public:
|
|||||||
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
|
|||||||
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
|
|||||||
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)
|
|||||||
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 @@ public:
|
|||||||
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; }
|
||||||
|
102
sql/mysql_priv.h
102
sql/mysql_priv.h
@ -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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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;
|
||||||
@ -622,7 +623,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
|||||||
SEL_TREE *tree;
|
SEL_TREE *tree;
|
||||||
KEY_PART *key_parts;
|
KEY_PART *key_parts;
|
||||||
PARAM param;
|
PARAM param;
|
||||||
|
|
||||||
/* set up parameter that is passed to all functions */
|
/* set up parameter that is passed to all functions */
|
||||||
param.thd= thd;
|
param.thd= thd;
|
||||||
param.baseflag=basflag;
|
param.baseflag=basflag;
|
||||||
@ -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
|
||||||
@ -2853,7 +2854,7 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
|
|||||||
fputc('/',DBUG_FILE);
|
fputc('/',DBUG_FILE);
|
||||||
if (field->real_maybe_null())
|
if (field->real_maybe_null())
|
||||||
{
|
{
|
||||||
length++; // null byte is not in part_length
|
length++; // null byte is not in part_length
|
||||||
if (*key++)
|
if (*key++)
|
||||||
{
|
{
|
||||||
fwrite("NULL",sizeof(char),4,DBUG_FILE);
|
fwrite("NULL",sizeof(char),4,DBUG_FILE);
|
||||||
@ -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)
|
|||||||
|
|
||||||
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 {
|
|||||||
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);
|
||||||
|
108
sql/sql_bitmap.h
Normal file
108
sql/sql_bitmap.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#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);
|
|||||||
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,
|
||||||
@ -529,7 +529,7 @@ JOIN::optimize()
|
|||||||
conds= optimize_cond(conds,&cond_value);
|
conds= optimize_cond(conds,&cond_value);
|
||||||
if (thd->net.report_error)
|
if (thd->net.report_error)
|
||||||
{
|
{
|
||||||
error= 1;
|
error= 1;
|
||||||
DBUG_PRINT("error",("Error from optimize_cond"));
|
DBUG_PRINT("error",("Error from optimize_cond"));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
@ -559,7 +559,7 @@ JOIN::optimize()
|
|||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
zero_result_cause= "No matching min/max row";
|
zero_result_cause= "No matching min/max row";
|
||||||
error=0;
|
error=0;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
zero_result_cause= "Select tables optimized away";
|
zero_result_cause= "Select tables optimized away";
|
||||||
@ -706,7 +706,7 @@ JOIN::optimize()
|
|||||||
/*
|
/*
|
||||||
Force MySQL to read the table in sorted order to get result in
|
Force MySQL to read the table in sorted order to get result in
|
||||||
ORDER BY order.
|
ORDER BY order.
|
||||||
*/
|
*/
|
||||||
tmp_table_param.quick_group=0;
|
tmp_table_param.quick_group=0;
|
||||||
}
|
}
|
||||||
order=0;
|
order=0;
|
||||||
@ -768,7 +768,7 @@ JOIN::optimize()
|
|||||||
make_join_readinfo(this,
|
make_join_readinfo(this,
|
||||||
(select_options & (SELECT_DESCRIBE |
|
(select_options & (SELECT_DESCRIBE |
|
||||||
SELECT_NO_JOIN_CACHE)) |
|
SELECT_NO_JOIN_CACHE)) |
|
||||||
(select_lex->ftfunc_list->elements ?
|
(select_lex->ftfunc_list->elements ?
|
||||||
SELECT_NO_JOIN_CACHE : 0));
|
SELECT_NO_JOIN_CACHE : 0));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1497,7 +1497,7 @@ JOIN::cleanup()
|
|||||||
|
|
||||||
int
|
int
|
||||||
mysql_select(THD *thd, Item ***rref_pointer_array,
|
mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||||
TABLE_LIST *tables, uint wild_num, List<Item> &fields,
|
TABLE_LIST *tables, uint wild_num, List<Item> &fields,
|
||||||
COND *conds, uint og_num, ORDER *order, ORDER *group,
|
COND *conds, uint og_num, ORDER *order, ORDER *group,
|
||||||
Item *having, ORDER *proc_param, ulong select_options,
|
Item *having, ORDER *proc_param, ulong select_options,
|
||||||
select_result *result, SELECT_LEX_UNIT *unit,
|
select_result *result, SELECT_LEX_UNIT *unit,
|
||||||
@ -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)
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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();
|
||||||
|
Reference in New Issue
Block a user