diff options
author | unknown <monty@mysql.com> | 2004-12-19 20:25:19 +0200 |
---|---|---|
committer | unknown <monty@mysql.com> | 2004-12-19 20:25:19 +0200 |
commit | 069041031074d606e3cb084898ea2504e716e03a (patch) | |
tree | edce84855fbf08b0328dae28794074f565be89e6 /sql | |
parent | 3fa699ef04e02070c9430adacee3a08b3f365e34 (diff) | |
download | mariadb-git-069041031074d606e3cb084898ea2504e716e03a.tar.gz |
Merge with global tree
Fixed some found bugs in BIT fields
Added more test cases for BIT fields and varchar
include/my_base.h:
Merge
Added HA_BIT_PART for easier test in key.cc
innobase/os/os0proc.c:
Fixed typo
myisam/mi_dbug.c:
Add printing of BIT types when debugging
mysql-test/r/show_check.result:
Set 'Avg_row_length' to # as this value is different between 32 and 64 bit machines
mysql-test/r/type_bit.result:
More tests
mysql-test/r/type_varchar.result:
More tests
mysql-test/t/show_check.test:
Set 'Avg_row_length' to # as this value is different between 32 and 64 bit machines
mysql-test/t/type_bit.test:
More tests
mysql-test/t/type_varchar.test:
More tests
sql/field.cc:
Added Field::val_int_as_str() to get better logging of bit fields
Merged new_key_field with move_field() to fix some problems with bit fields
Fixed some bugs with bit fields
sql/field.h:
Added Field::val_int_as_str() to get better logging of bit fields
Merged new_key_field with move_field() to fix some problems with bit fields
Fixed some bugs with bit fields
sql/ha_myisam.cc:
Fixed problem with unintialized memory (not critical)
sql/key.cc:
Fix so that 'key_cmp_if_same' works with bit fields.
sql/opt_range.cc:
Move declarations first in function
Nice printing of bit fields in debug log
sql/sql_prepare.cc:
Fixed old merge error (not critical)
sql/sql_select.cc:
Use new interface to new_key_field
sql/sql_select.h:
Use new interface to new_key_fields()
This fixes a bug with BIT fields where the upper bit of the data was not stored in the key buffer
sql/structs.h:
Extend key_part_flag to be able to add HA_BIT_PART to it
sql/table.cc:
Mark BIT key parts with HA_BIT_PART to make test in key.cc simpler
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 99 | ||||
-rw-r--r-- | sql/field.h | 29 | ||||
-rw-r--r-- | sql/ha_myisam.cc | 3 | ||||
-rw-r--r-- | sql/key.cc | 54 | ||||
-rw-r--r-- | sql/opt_range.cc | 18 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 18 | ||||
-rw-r--r-- | sql/sql_select.h | 7 | ||||
-rw-r--r-- | sql/structs.h | 2 | ||||
-rw-r--r-- | sql/table.cc | 3 |
10 files changed, 166 insertions, 70 deletions
diff --git a/sql/field.cc b/sql/field.cc index ee12ce5ea68..ebeee476985 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -329,6 +329,27 @@ bool Field::field_cast_compatible(Field::field_cast_enum type) } +/* + Interpret field value as an integer but return the result as a string. + + This is used for printing bit_fields as numbers while debugging +*/ + +String *Field::val_int_as_str(String *val_buffer, my_bool unsigned_flag) +{ + CHARSET_INFO *cs= &my_charset_bin; + uint length= 21; + longlong value= val_int(); + if (val_buffer->alloc(length)) + return 0; + length= (uint) cs->cset->longlong10_to_str(cs, (char*) val_buffer->ptr(), + length, unsigned_flag ? 10 : -10, + value); + val_buffer->length(length); + return val_buffer; +} + + /**************************************************************************** ** Functions for the base classes ** This is an unpacked number. @@ -500,6 +521,22 @@ Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table) return tmp; } + +Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table, + char *new_ptr, uchar *new_null_ptr, + uint new_null_bit) +{ + Field *tmp; + if ((tmp= new_field(root, new_table))) + { + tmp->ptr= new_ptr; + tmp->null_ptr= new_null_ptr; + tmp->null_bit= new_null_bit; + } + return tmp; +} + + /**************************************************************************** Field_null, a field that always return NULL ****************************************************************************/ @@ -5116,12 +5153,20 @@ Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table) Field *Field_varstring::new_key_field(MEM_ROOT *root, - struct st_table *new_table) -{ - Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table); - /* Keys length prefixes are always packed with 2 bytes */ - if (res) + struct st_table *new_table, + char *new_ptr, uchar *new_null_ptr, + uint new_null_bit) +{ + Field_varstring *res; + if ((res= (Field_varstring*) Field::new_key_field(root, + new_table, + new_ptr, + new_null_ptr, + new_null_bit))) + { + /* Keys length prefixes are always packed with 2 bytes */ res->length_bytes= 2; + } return res; } @@ -6210,6 +6255,43 @@ bool Field_num::eq_def(Field *field) 11 one byte for 'd' */ +Field_bit::Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, + enum utype unireg_check_arg, const char *field_name_arg, + struct st_table *table_arg) + : Field(ptr_arg, len_arg >> 3, null_ptr_arg, null_bit_arg, + unireg_check_arg, field_name_arg, table_arg), + bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7) +{ + /* + Ensure that Field::eq() can distinguish between two different bit fields. + (two bit fields that are not null, may have same ptr and null_ptr) + */ + if (!null_ptr_arg) + null_bit= bit_ofs_arg; +} + + +Field *Field_bit::new_key_field(MEM_ROOT *root, + struct st_table *new_table, + char *new_ptr, uchar *new_null_ptr, + uint new_null_bit) +{ + Field_bit *res; + if ((res= (Field_bit*) Field::new_key_field(root, new_table, + new_ptr, new_null_ptr, + new_null_bit))) + { + /* Move bits normally stored in null_pointer to new_ptr */ + res->bit_ptr= (uchar*) new_ptr; + res->bit_ofs= 0; + if (bit_len) + res->ptr++; // Store rest of data here + } + return res; +} + + void Field_bit::make_field(Send_field *field) { /* table_cache_key is not set for temp tables */ @@ -6331,7 +6413,7 @@ int Field_bit::key_cmp(const byte *str, uint length) { int flag; uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len); - if ((flag= (int) (bits - *str))) + if ((flag= (int) (bits - *(uchar*) str))) return flag; str++; length--; @@ -6426,6 +6508,11 @@ void create_field::create_length_to_internal_length(void) length*= charset->mbmaxlen; key_length= pack_length; break; + case MYSQL_TYPE_BIT: + pack_length= calc_pack_length(sql_type, length); + /* We need one extra byte to store the bits we save among the null bits */ + key_length= pack_length+ test(length & 7); + break; default: key_length= pack_length= calc_pack_length(sql_type, length); break; diff --git a/sql/field.h b/sql/field.h index 2d84d240839..6ce5cf2a526 100644 --- a/sql/field.h +++ b/sql/field.h @@ -113,9 +113,14 @@ public: This trickery is used to decrease a number of malloc calls. */ virtual String *val_str(String*,String *)=0; + String *Field::val_int_as_str(String *val_buffer, my_bool unsigned_flag); virtual Item_result result_type () const=0; virtual Item_result cmp_type () const { return result_type(); } - bool eq(Field *field) { return ptr == field->ptr && null_ptr == field->null_ptr; } + bool eq(Field *field) + { + return (ptr == field->ptr && null_ptr == field->null_ptr && + null_bit == field->null_bit); + } virtual bool eq_def(Field *field); virtual uint32 pack_length() const { return (uint32) field_length; } virtual void reset(void) { bzero(ptr,pack_length()); } @@ -184,11 +189,10 @@ public: virtual bool can_be_compared_as_longlong() const { return FALSE; } virtual void free() {} virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table); - virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table) - { - return new_field(root, new_table); - } - inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) + virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, + char *new_ptr, uchar *new_null_ptr, + uint new_null_bit); + virtual void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) { ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg; } @@ -994,7 +998,9 @@ public: { return charset() == &my_charset_bin ? FALSE : TRUE; } field_cast_enum field_cast_type() { return FIELD_CAST_VARSTRING; } Field *new_field(MEM_ROOT *root, struct st_table *new_table); - Field *new_key_field(MEM_ROOT *root, struct st_table *new_table); + Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, + char *new_ptr, uchar *new_null_ptr, + uint new_null_bit); }; @@ -1199,11 +1205,7 @@ public: Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, enum utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg) - : Field(ptr_arg, len_arg >> 3, null_ptr_arg, null_bit_arg, - unireg_check_arg, field_name_arg, table_arg), - bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7) - { } + struct st_table *table_arg); enum_field_types type() const { return FIELD_TYPE_BIT; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; } uint32 key_length() const { return (uint32) field_length + (bit_len > 0); } @@ -1235,6 +1237,9 @@ public: field_cast_enum field_cast_type() { return FIELD_CAST_BIT; } char *pack(char *to, const char *from, uint max_length=~(uint) 0); const char *unpack(char* to, const char *from); + Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, + char *new_ptr, uchar *new_null_ptr, + uint new_null_bit); }; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index ce3287d8745..c23a728b715 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1409,7 +1409,8 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, keydef[i].seg[j].type= (int) type; keydef[i].seg[j].start= pos->key_part[j].offset; keydef[i].seg[j].length= pos->key_part[j].length; - keydef[i].seg[j].bit_start=keydef[i].seg[j].bit_end=0; + keydef[i].seg[j].bit_start= keydef[i].seg[j].bit_end= + keydef[i].seg[j].bit_pos= 0; keydef[i].seg[j].language = field->charset()->number; if (field->null_ptr) diff --git a/sql/key.cc b/sql/key.cc index fe35638608d..d54b8721cab 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -250,54 +250,54 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, bool key_cmp_if_same(TABLE *table,const byte *key,uint idx,uint key_length) { - uint length; + uint store_length; KEY_PART_INFO *key_part; + const byte *key_end= key + key_length;; for (key_part=table->key_info[idx].key_part; - (int) key_length > 0; - key_part++, key+=length, key_length-=length) + key < key_end ; + key_part++, key+= store_length) { + uint length; + store_length= key_part->store_length; + if (key_part->null_bit) { - key_length--; if (*key != test(table->record[0][key_part->null_offset] & key_part->null_bit)) return 1; if (*key) - { - length=key_part->store_length; continue; - } key++; + store_length--; } - if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART)) + if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART | + HA_BIT_PART)) { if (key_part->field->key_cmp(key, key_part->length)) return 1; - length=key_part->length+HA_KEY_BLOB_LENGTH; + continue; } - else + length= min((uint) (key_end-key), store_length); + if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+ + FIELDFLAG_PACK))) { - length=min(key_length,key_part->length); - if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+ - FIELDFLAG_PACK))) + CHARSET_INFO *cs= key_part->field->charset(); + uint char_length= key_part->length / cs->mbmaxlen; + const byte *pos= table->record[0] + key_part->offset; + if (length > char_length) { - CHARSET_INFO *cs= key_part->field->charset(); - uint char_length= key_part->length / cs->mbmaxlen; - const byte *pos= table->record[0] + key_part->offset; - if (length > char_length) - { - char_length= my_charpos(cs, pos, pos + length, char_length); - set_if_smaller(char_length, length); - } - if (cs->coll->strnncollsp(cs, - (const uchar*) key, length, - (const uchar*) pos, char_length, 0)) - return 1; + char_length= my_charpos(cs, pos, pos + length, char_length); + set_if_smaller(char_length, length); } - else if (memcmp(key,table->record[0]+key_part->offset,length)) - return 1; + if (cs->coll->strnncollsp(cs, + (const uchar*) key, length, + (const uchar*) pos, char_length, 0)) + return 1; + continue; } + if (memcmp(key,table->record[0]+key_part->offset,length)) + return 1; } return 0; } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 0f54f06a22b..80237766d29 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5000,7 +5000,9 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, char *min_key,uint min_key_flag, char *max_key, uint max_key_flag) { - ha_rows records=0,tmp; + ha_rows records=0, tmp; + uint tmp_min_flag, tmp_max_flag, keynr, min_key_length, max_key_length; + char *tmp_min_key, *tmp_max_key; param->max_key_part=max(param->max_key_part,key_tree->part); if (key_tree->left != &null_element) @@ -5018,13 +5020,12 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, return records; } - uint tmp_min_flag,tmp_max_flag,keynr; - char *tmp_min_key=min_key,*tmp_max_key=max_key; - + tmp_min_key= min_key; + tmp_max_key= max_key; key_tree->store(param->key[idx][key_tree->part].store_length, &tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag); - uint min_key_length= (uint) (tmp_min_key- param->min_key); - uint max_key_length= (uint) (tmp_max_key- param->max_key); + min_key_length= (uint) (tmp_min_key- param->min_key); + max_key_length= (uint) (tmp_max_key- param->max_key); if (param->is_ror_scan) { @@ -8448,7 +8449,10 @@ print_key(KEY_PART *key_part,const char *key,uint used_length) store_length--; } field->set_key_image((char*) key, key_part->length); - field->val_str(&tmp); + if (field->type() == MYSQL_TYPE_BIT) + (void) field->val_int_as_str(&tmp, 1); + else + field->val_str(&tmp); fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE); if (key+store_length < key_end) fputc('/',DBUG_FILE); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 6d59d465445..8afefe3cae8 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2041,10 +2041,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt, thd->cleanup_after_query(); if (stmt->state == Item_arena::PREPARED) - { - thd->current_arena= thd; stmt->state= Item_arena::EXECUTED; - } DBUG_VOID_RETURN; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5425ddfb64b..44412cdc43a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8159,25 +8159,27 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, if (!using_unique_constraint) { group->buff=(char*) group_buff; - if (!(group->field=field->new_key_field(thd->mem_root,table))) + if (!(group->field= field->new_key_field(thd->mem_root,table, + (char*) group_buff + + test(maybe_null), + field->null_ptr, + field->null_bit))) goto err; /* purecov: inspected */ if (maybe_null) { /* - To be able to group on NULL, we reserve place in group_buff - for the NULL flag just before the column. + To be able to group on NULL, we reserved place in group_buff + for the NULL flag just before the column. (see above). The field data is after this flag. - The NULL flag is updated by 'end_update()' and 'end_write()' + The NULL flag is updated in 'end_update()' and 'end_write()' */ keyinfo->flags|= HA_NULL_ARE_EQUAL; // def. that NULL == NULL key_part_info->null_bit=field->null_bit; key_part_info->null_offset= (uint) (field->null_ptr - (uchar*) table->record[0]); - group->field->move_field((char*) ++group->buff); - group_buff++; + group->buff++; // Pointer to field data + group_buff++; // Skipp null flag } - else - group->field->move_field((char*) group_buff); /* In GROUP BY 'a' and 'a ' are equal for VARCHAR fields */ key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL; group_buff+= group->field->pack_length(); diff --git a/sql/sql_select.h b/sql/sql_select.h index be3a72836b4..0f26207b391 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -427,11 +427,8 @@ class store_key :public Sql_alloc field_arg->table, field_arg->charset()); } else - { - to_field=field_arg->new_key_field(thd->mem_root, field_arg->table); - if (to_field) - to_field->move_field(ptr, (uchar*) null, 1); - } + to_field=field_arg->new_key_field(thd->mem_root, field_arg->table, + ptr, (uchar*) null, 1); } virtual ~store_key() {} /* Not actually needed */ virtual bool copy()=0; diff --git a/sql/structs.h b/sql/structs.h index 5d0c7bc4f1f..0b59c3abeb3 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -74,7 +74,7 @@ typedef struct st_key_part_info { /* Info about a key part */ uint16 store_length; uint16 key_type; uint16 fieldnr; /* Fieldnum in UNIREG */ - uint8 key_part_flag; /* 0 or HA_REVERSE_SORT */ + uint16 key_part_flag; /* 0 or HA_REVERSE_SORT */ uint8 type; uint8 null_bit; /* Position to null_bit */ } KEY_PART_INFO ; diff --git a/sql/table.cc b/sql/table.cc index 610de9e4e9b..c18a2557337 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -631,6 +631,9 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (!(field->flags & BINARY_FLAG)) keyinfo->flags|= HA_END_SPACE_KEY; } + if (field->type() == MYSQL_TYPE_BIT) + key_part->key_part_flag|= HA_BIT_PART; + if (i == 0 && key != primary_key) field->flags |= ((keyinfo->flags & HA_NOSAME) && |