Skip to content

Commit 444587d

Browse files
committed
BIT field woes
* get_rec_bits() was always reading two bytes, even if the bit field contained only of one byte * In various places the code used field->pack_length() bytes starting from field->ptr, while it should be field->pack_length_in_rec() * Field_bit::key_cmp and Field_bit::cmp_max passed field_length as an argument to memcmp(), but field_length is the number of bits!
1 parent 5e7593a commit 444587d

File tree

5 files changed

+21
-19
lines changed

5 files changed

+21
-19
lines changed

include/my_compare.h

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,19 @@ typedef struct st_HA_KEYSEG /* Key-portion */
9191

9292
#define size_to_store_key_length(length) ((length) < 255 ? 1 : 3)
9393

94-
#define get_rec_bits(bit_ptr, bit_ofs, bit_len) \
95-
(((((uint16) (bit_ptr)[1] << 8) | (uint16) (bit_ptr)[0]) >> (bit_ofs)) & \
96-
((1 << (bit_len)) - 1))
97-
98-
#define set_rec_bits(bits, bit_ptr, bit_ofs, bit_len) \
99-
{ \
100-
(bit_ptr)[0]= ((bit_ptr)[0] & ~(((1 << (bit_len)) - 1) << (bit_ofs))) | \
101-
((bits) << (bit_ofs)); \
102-
if ((bit_ofs) + (bit_len) > 8) \
103-
(bit_ptr)[1]= ((bit_ptr)[1] & ~((1 << ((bit_len) - 8 + (bit_ofs))) - 1)) | \
104-
((bits) >> (8 - (bit_ofs))); \
94+
static inline uint16 get_rec_bits(const uchar *ptr, uchar ofs, uint len)
95+
{
96+
uint16 val= ptr[0];
97+
if (ofs + len > 8)
98+
val|= (uint16)(ptr[1]) << 8;
99+
return (val >> ofs) & ((1 << len) - 1);
100+
}
101+
102+
static inline void set_rec_bits(uint16 bits, uchar *ptr, uchar ofs, uint len)
103+
{
104+
ptr[0]= (ptr[0] & ~(((1 << len) - 1) << ofs)) | (bits << ofs);
105+
if (ofs + len > 8)
106+
ptr[1]= (ptr[1] & ~((1 << (len - 8 + ofs)) - 1)) | (bits >> (8 - ofs));
105107
}
106108

107109
#define clr_rec_bits(bit_ptr, bit_ofs, bit_len) \

sql/field.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,7 +1758,7 @@ uint Field::fill_cache_field(CACHE_FIELD *copy)
17581758
{
17591759
uint store_length;
17601760
copy->str= ptr;
1761-
copy->length= pack_length();
1761+
copy->length= pack_length_in_rec();
17621762
copy->field= this;
17631763
if (flags & BLOB_FLAG)
17641764
{
@@ -8422,7 +8422,7 @@ int Field_bit::cmp_max(const uchar *a, const uchar *b, uint max_len)
84228422
if ((flag= (int) (bits_a - bits_b)))
84238423
return flag;
84248424
}
8425-
return memcmp(a, b, field_length);
8425+
return memcmp(a, b, bytes_in_rec);
84268426
}
84278427

84288428

@@ -8437,7 +8437,7 @@ int Field_bit::key_cmp(const uchar *str, uint length)
84378437
str++;
84388438
length--;
84398439
}
8440-
return memcmp(ptr, str, length);
8440+
return memcmp(ptr, str, bytes_in_rec);
84418441
}
84428442

84438443

sql/field_conv.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ void Copy_field::set(uchar *to,Field *from)
589589
{
590590
from_ptr=from->ptr;
591591
to_ptr=to;
592-
from_length=from->pack_length();
592+
from_length=from->pack_length_in_rec();
593593
if (from->maybe_null())
594594
{
595595
from_null_ptr=from->null_ptr;
@@ -640,9 +640,9 @@ void Copy_field::set(Field *to,Field *from,bool save)
640640
from_field=from;
641641
to_field=to;
642642
from_ptr=from->ptr;
643-
from_length=from->pack_length();
643+
from_length=from->pack_length_in_rec();
644644
to_ptr= to->ptr;
645-
to_length=to_field->pack_length();
645+
to_length=to_field->pack_length_in_rec();
646646

647647
// set up null handling
648648
from_null_ptr=to_null_ptr=0;

sql/sql_join_cache.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ void JOIN_CACHE::create_flag_fields()
394394
TABLE *table= tab->table;
395395

396396
/* Create a field for the null bitmap from table if needed */
397-
if (tab->used_null_fields || tab->used_uneven_bit_fields)
397+
if (tab->used_null_fields || tab->used_uneven_bit_fields)
398398
length+= add_flag_field_to_join_cache(table->null_flags,
399399
table->s->null_bytes,
400400
&copy);

sql/sql_select.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15537,7 +15537,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
1553715537
else
1553815538
{
1553915539
field->set_notnull();
15540-
memcpy(field->ptr, orig_field->ptr, field->pack_length());
15540+
memcpy(field->ptr, orig_field->ptr, field->pack_length_in_rec());
1554115541
}
1554215542
orig_field->move_field_offset(-diff); // Back to record[0]
1554315543
}

0 commit comments

Comments
 (0)