diff --git a/include/my_bitmap.h b/include/my_bitmap.h index d3fcece290b..cff2295f45c 100644 --- a/include/my_bitmap.h +++ b/include/my_bitmap.h @@ -25,14 +25,13 @@ typedef struct st_bitmap { uchar *bitmap; 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 - thread_safe flag is set. Otherwise, we optimize by not acquiring the - mutex + thread_safe flag in bitmap_init was set. Otherwise, we optimize by not + acquiring the mutex */ #ifdef THREAD - pthread_mutex_t mutex; + pthread_mutex_t *mutex; #endif } MY_BITMAP; diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 9f76676ee1a..8c363ef3c89 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -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; 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 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; 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 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; id select_type table type possible_keys key key_len ref rows Extra 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 thread_safe) - pthread_mutex_lock(&map->mutex); + if (map->mutex) + pthread_mutex_lock(map->mutex); #endif } inline void bitmap_unlock(MY_BITMAP *map) { #ifdef THREAD - if (map->thread_safe) - pthread_mutex_unlock(&map->mutex); + if (map->mutex) + pthread_mutex_unlock(map->mutex); #endif } 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+7)/8, - MYF(MY_WME | MY_ZEROFILL)))) + !(map->bitmap=(uchar*)my_malloc(bitmap_size + sizeof(pthread_mutex_t), + MYF(MY_WME | MY_ZEROFILL)))) 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; +#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; } void bitmap_free(MY_BITMAP *map) { +#ifdef THREAD + if (map->mutex) + pthread_mutex_destroy(map->mutex); +#endif if (map->bitmap) { my_free((char*) map->bitmap, MYF(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) { - DBUG_ASSERT(map->bitmap); - if (bitmap_bit < map->bitmap_size) - { - bitmap_lock(map); - map->bitmap[bitmap_bit / 8] |= (1 << (bitmap_bit & 7)); - bitmap_unlock(map); - } + DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); + bitmap_lock(map); + map->bitmap[bitmap_bit / 8] |= (1 << (bitmap_bit & 7)); + bitmap_unlock(map); } uint bitmap_set_next(MY_BITMAP *map) { uchar *bitmap=map->bitmap; uint bit_found = MY_BIT_NONE; - uint bitmap_size=map->bitmap_size; + uint bitmap_size=map->bitmap_size*8; uint i; 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) { - DBUG_ASSERT(map->bitmap); - if (bitmap_bit < map->bitmap_size) - { - bitmap_lock(map); - map->bitmap[bitmap_bit / 8] &= ~ (1 << (bitmap_bit & 7)); - bitmap_unlock(map); - } + DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); + bitmap_lock(map); + map->bitmap[bitmap_bit / 8] &= ~ (1 << (bitmap_bit & 7)); + bitmap_unlock(map); } void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) { - uint l, m; + uint prefix_bytes, prefix_bits; DBUG_ASSERT(map->bitmap); bitmap_lock(map); - set_if_smaller(prefix_size, map->bitmap_size); - if ((l=prefix_size / 8)) - memset(map->bitmap, 0xff, l); - if ((m=prefix_size & 7)) - map->bitmap[l++]= (1 << m)-1; - if (l < (m=(map->bitmap_size+7)/8)) - bzero(map->bitmap+l, m-l); + set_if_smaller(prefix_size, map->bitmap_size*8); + if ((prefix_bytes= prefix_size / 8)) + memset(map->bitmap, 0xff, prefix_bytes); + if ((prefix_bits= prefix_size & 7)) + map->bitmap[prefix_bytes++]= (1 << prefix_bits)-1; + if (prefix_bytes < map->bitmap_size) + bzero(map->bitmap+prefix_bytes, map->bitmap_size-prefix_bytes); bitmap_unlock(map); } @@ -146,27 +147,27 @@ void bitmap_clear_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) { - 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); - if (prefix_size > map->bitmap_size) - return 0; + DBUG_ASSERT(map->bitmap && prefix_size <= map->bitmap_size*8); bitmap_lock(map); - for (i=0; i < l; i++) - if (map->bitmap[i] != 0xff) + while (m < end_prefix) + if (*m++ != 0xff) goto ret; - if (m && map->bitmap[i++] != (1 << m)-1) + if (prefix_bits && *m++ != (1 << prefix_bits)-1) goto ret; - for (m=(map->bitmap_size+7)/8; i < m; i++) - if (map->bitmap[i] != 0) + while (m < end) + if (m++ != 0) goto ret; res=1; @@ -182,38 +183,31 @@ my_bool bitmap_is_clear_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) { - DBUG_ASSERT(map->bitmap); - return (bitmap_bit < map->bitmap_size) ? - (map->bitmap[bitmap_bit / 8] & (1 << (bitmap_bit & 7))) : 0; + 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) { - uint l1, l2, i, res=0; - uchar *m1=map1->bitmap, *m2=map2->bitmap; + uint length, res=0; + uchar *m1=map1->bitmap, *m2=map2->bitmap, *end; - DBUG_ASSERT(map1->bitmap); - DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map1->bitmap && map2->bitmap && + map1->bitmap_size==map2->bitmap_size); bitmap_lock(map1); bitmap_lock(map2); - l1=(map1->bitmap_size+7)/8; - l2=(map2->bitmap_size+7)/8; - set_if_smaller(l2, l1); + end= m1+map1->bitmap_size; - for (i=0; i < l2; i++) + while (m1 < end) if ((*m1++) & ~(*m2++)) goto ret; - for (; i < l1; i++) - if (*m1++) - goto ret; - res=1; ret: bitmap_unlock(map2); @@ -225,13 +219,12 @@ my_bool bitmap_cmp(MY_BITMAP *map1, MY_BITMAP *map2) { uint res; - DBUG_ASSERT(map1->bitmap); - DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map1->bitmap && map2->bitmap && + map1->bitmap_size==map2->bitmap_size); bitmap_lock(map1); bitmap_lock(map2); - res= map1->bitmap_size == map2->bitmap_size && - memcmp(map1->bitmap, map2->bitmap, (map1->bitmap_size+7)/8)==0; + res= memcmp(map1->bitmap, map2->bitmap, map1->bitmap_size)==0; bitmap_unlock(map2); 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) { - uint l1, l2, i; - uchar *m=map->bitmap, *m2=map2->bitmap; + uchar *to=map->bitmap, *from=map2->bitmap, *end; - DBUG_ASSERT(map->bitmap); - DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->bitmap && map2->bitmap && + map->bitmap_size==map2->bitmap_size); bitmap_lock(map); bitmap_lock(map2); - l1=(map->bitmap_size+7)/8; - l2=(map2->bitmap_size+7)/8; - set_if_smaller(l2, l1); + end= to+map->bitmap_size; - for (i=0; i < l2; i++) - *m++ &= *m2++; - - if (l1 > l2) - bzero(m, l1-l2); + while (to < end) + *to++ &= *from++; bitmap_unlock(map2); 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) { - uint l1, l2, i; - uchar *m=map->bitmap, *m2=map2->bitmap; + uchar *to=map->bitmap, *from=map2->bitmap, *end; - DBUG_ASSERT(map->bitmap); - DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->bitmap && map2->bitmap && + map->bitmap_size==map2->bitmap_size); bitmap_lock(map); bitmap_lock(map2); - l1=(map->bitmap_size+7)/8; - l2=(map2->bitmap_size+7)/8; - set_if_smaller(l2, l1); + end= to+map->bitmap_size; - for (i=0; i < l2; i++) - *m++ &= ~(*m2++); + while (to < end) + *to++ &= ~(*from++); bitmap_unlock(map2); 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) { - uint l1, l2, i; - uchar *m=map->bitmap, *m2=map2->bitmap; + uchar *to=map->bitmap, *from=map2->bitmap, *end; - DBUG_ASSERT(map->bitmap); - DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->bitmap && map2->bitmap && + map->bitmap_size==map2->bitmap_size); bitmap_lock(map); bitmap_lock(map2); - l1=(map->bitmap_size+7)/8; - l2=(map2->bitmap_size+7)/8; - set_if_smaller(l2, l1); + end= to+map->bitmap_size; - for (i=0; i < l2; i++) - *m++ |= *m2++; + while (to < end) + *to++ |= *from++; bitmap_unlock(map2); bitmap_unlock(map); diff --git a/sql/field.cc b/sql/field.cc index 98eb0e01f56..c30c06c6395 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -181,7 +181,8 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, :ptr(ptr_arg),null_ptr(null_ptr_arg), table(table_arg),table_name(table_arg ? table_arg->table_name : 0), 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) { flags=null_ptr ? 0: NOT_NULL_FLAG; diff --git a/sql/field.h b/sql/field.h index eb0af881121..e7d4bb2416a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -151,9 +151,9 @@ public: if (tmp->table->maybe_null) tmp->flags&= ~NOT_NULL_FLAG; tmp->table= new_table; - tmp->key_start.init().clear_all(); - tmp->part_of_key.init().clear_all(); - tmp->part_of_sortkey.init().clear_all(); + tmp->key_start.init(0); + tmp->part_of_key.init(0); + tmp->part_of_sortkey.init(0); tmp->unireg_check=Field::NONE; tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG); diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h index 850be48258a..79e52ea71af 100644 --- a/sql/ha_berkeley.h +++ b/sql/ha_berkeley.h @@ -107,7 +107,7 @@ class ha_berkeley: public handler uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; } ha_rows estimate_number_of_rows(); 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;} int open(const char *name, int mode, uint test_if_locked); diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index 9ef47a105d6..2fa70f27128 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -125,7 +125,7 @@ class ha_innobase: public handler uint max_key_length() const { return((MAX_KEY_LENGTH <= 3500) ? MAX_KEY_LENGTH : 3500);} 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;} int open(const char *name, int mode, uint test_if_locked); diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index ea356a4f17c..a23e4c55618 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1023,7 +1023,8 @@ void ha_myisam::info(uint flag) ref_length=info.reflength; table->db_options_in_use = info.options; 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.subtract(table->read_only_keys); table->db_record_offset=info.record_offset; diff --git a/sql/handler.h b/sql/handler.h index 26671bb5b11..29dea7f213b 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -241,7 +241,7 @@ public: virtual double read_time(uint index, uint ranges, ha_rows rows) { return rows2double(ranges+rows); } 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 uint extra_rec_buf_length() { return 0; } virtual ha_rows estimate_number_of_rows() { return records+EXTRA_RECORDS; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6bc1031739d..c22ca1c2d3c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -23,113 +23,13 @@ #include #include #include /* Needed by field.h */ -#include +#include #include #ifdef __EMX__ #undef write /* remove pthread.h macro definition for EMX */ #endif -template 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 */ typedef ulonglong table_map; /* Used for table bits in join */ typedef Bitmap<64> key_map; /* Used for finding keys */ diff --git a/sql/opt_range.cc b/sql/opt_range.cc index cf1838489d0..da6ede8586f 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -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, SEL_ARG *key_tree); #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 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); @@ -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) { + quick_keys.clear_all(); needed_reg.clear_all(); my_b_clear(&file); } @@ -588,9 +589,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, uint idx; double scan_time; DBUG_ENTER("test_quick_select"); -/* DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu", - (ulong) keys_to_use, (ulong) prev_tables, - (ulong) const_tables));*/ + DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu", + keys_to_use.to_ulonglong(), (ulong) prev_tables, + (ulong) const_tables)); delete quick; quick=0; @@ -622,7 +623,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, SEL_TREE *tree; KEY_PART *key_parts; PARAM param; - + /* set up parameter that is passed to all functions */ param.thd= thd; 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); 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 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); if (field->real_maybe_null()) { - length++; // null byte is not in part_length + length++; // null byte is not in part_length if (*key++) { 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; char buf[MAX_KEY/8+1]; @@ -2879,8 +2880,8 @@ static void print_quick(QUICK_SELECT *quick,const key_map& needed_reg) List_iterator li(quick->ranges); DBUG_LOCK_FILE; - fprintf(DBUG_FILE,"Used quick_range on key: %d (other_keys: %s):\n", - quick->index, needed_reg.print(buf)); + fprintf(DBUG_FILE,"Used quick_range on key: %d (other_keys: 0x%s):\n", + quick->index, needed_reg->print(buf)); while ((range=li++)) { if (!(range->flag & NO_MIN_RANGE)) diff --git a/sql/opt_range.h b/sql/opt_range.h index b4d855c0faa..1c209dc7027 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -128,7 +128,7 @@ class SQL_SELECT :public Sql_alloc { SQL_SELECT(); ~SQL_SELECT(); 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; } int test_quick_select(THD *thd, key_map keys, table_map prev_tables, ha_rows limit, bool force_quick_range=0); diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h new file mode 100644 index 00000000000..b8e163ce24a --- /dev/null +++ b/sql/sql_bitmap.h @@ -0,0 +1,108 @@ +#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include +#include + +template 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; } +}; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f25b012a0fa..5c784422bc4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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, table_map used_table); 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, ha_rows select_limit, bool no_changes); static int create_sort_index(THD *thd, JOIN *join, ORDER *order, @@ -529,7 +529,7 @@ JOIN::optimize() conds= optimize_cond(conds,&cond_value); if (thd->net.report_error) { - error= 1; + error= 1; DBUG_PRINT("error",("Error from optimize_cond")); DBUG_RETURN(1); } @@ -559,7 +559,7 @@ JOIN::optimize() if (res < 0) { zero_result_cause= "No matching min/max row"; - error=0; + error=0; DBUG_RETURN(0); } 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 ORDER BY order. - */ + */ tmp_table_param.quick_group=0; } order=0; @@ -768,7 +768,7 @@ JOIN::optimize() make_join_readinfo(this, (select_options & (SELECT_DESCRIBE | SELECT_NO_JOIN_CACHE)) | - (select_lex->ftfunc_list->elements ? + (select_lex->ftfunc_list->elements ? SELECT_NO_JOIN_CACHE : 0)); /* @@ -1497,7 +1497,7 @@ JOIN::cleanup() int mysql_select(THD *thd, Item ***rref_pointer_array, - TABLE_LIST *tables, uint wild_num, List &fields, + TABLE_LIST *tables, uint wild_num, List &fields, COND *conds, uint og_num, ORDER *order, ORDER *group, Item *having, ORDER *proc_param, ulong select_options, 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->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->select=0; join_tab->select_cond=0; join_tab->quick=0; 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->on_expr=0; 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)) { // 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->read_first_record= join_read_first; 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; } -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 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) { @@ -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_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) && 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) { - keys=table->file->keys_to_use_for_scanning(); + keys=*table->file->keys_to_use_for_scanning(); keys.merge(table->used_keys); } else @@ -6848,7 +6848,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, keys.intersect(usable_keys); - for (nr=0; nr < keys.length() ; nr++) + for (nr=0; nr < table->keys ; nr++) { uint not_used; 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) { 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)); buff_ptr=strend(buff_ptr); } diff --git a/sql/table.cc b/sql/table.cc index 24c5b941c0b..ebe1b51248e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -166,9 +166,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, outparam->keys= keys= disk_buff[0]; outparam->key_parts= key_parts= disk_buff[1]; } - outparam->keys_for_keyread.init().set_prefix(keys); - outparam->keys_in_use.init().set_prefix(keys); - outparam->read_only_keys.init().clear_all(); + outparam->keys_for_keyread.init(keys); + outparam->keys_in_use.init(keys); + outparam->read_only_keys.init(0); outparam->quick_keys.init(); outparam->used_keys.init(); outparam->keys_in_use_for_query.init();