Commit 4ab9c029 authored by jimw@mysql.com's avatar jimw@mysql.com

Merge mysql.com:/home/jimw/my/mysql-5.0-clean

into  mysql.com:/home/jimw/my/mysql-5.1-clean
parents e9ef9ef6 0647a26a
...@@ -564,3 +564,12 @@ b1+0 sum(b1) sum(b2) ...@@ -564,3 +564,12 @@ b1+0 sum(b1) sum(b2)
1 4 4 1 4 4
2 2 2 2 2 2
drop table t1, t2; drop table t1, t2;
create table t1 (a bit(7));
insert into t1 values (0x60);
select * from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t1 t1 a a 16 7 1 Y 0 0 63
a
`
drop table t1;
End of 5.0 tests
...@@ -402,3 +402,12 @@ t1 CREATE TABLE `t1` ( ...@@ -402,3 +402,12 @@ t1 CREATE TABLE `t1` (
`b` bit(10) DEFAULT NULL `b` bit(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create table t1 (a bit(7)) engine=innodb;
insert into t1 values (0x60);
select * from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t1 t1 a a 16 7 1 Y 0 0 63
a
`
drop table t1;
End of 5.0 tests
...@@ -227,3 +227,15 @@ select sum(a1), b1+0, b2+0 from t1 join t2 on b1 = b2 group by b1 order by 1; ...@@ -227,3 +227,15 @@ select sum(a1), b1+0, b2+0 from t1 join t2 on b1 = b2 group by b1 order by 1;
select 1 from t1 join t2 on b1 = b2 group by b1 order by 1; select 1 from t1 join t2 on b1 = b2 group by b1 order by 1;
select b1+0,sum(b1), sum(b2) from t1 join t2 on b1 = b2 group by b1 order by 1; select b1+0,sum(b1), sum(b2) from t1 join t2 on b1 = b2 group by b1 order by 1;
drop table t1, t2; drop table t1, t2;
#
# Bug #13601: Wrong field length reported for BIT fields
#
create table t1 (a bit(7));
insert into t1 values (0x60);
--enable_metadata
select * from t1;
--disable_metadata
drop table t1;
--echo End of 5.0 tests
...@@ -133,3 +133,15 @@ show create table t1; ...@@ -133,3 +133,15 @@ show create table t1;
alter table t1 engine=innodb; alter table t1 engine=innodb;
show create table t1; show create table t1;
drop table t1; drop table t1;
#
# Bug #13601: Wrong field length reported for BIT fields
#
create table t1 (a bit(7)) engine=innodb;
insert into t1 values (0x60);
--enable_metadata
select * from t1;
--disable_metadata
drop table t1;
--echo End of 5.0 tests
...@@ -7998,9 +7998,10 @@ uint Field_num::is_equal(create_field *new_field) ...@@ -7998,9 +7998,10 @@ uint Field_num::is_equal(create_field *new_field)
Field_bit::Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, 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, uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
enum utype unireg_check_arg, const char *field_name_arg) enum utype unireg_check_arg, const char *field_name_arg)
: Field(ptr_arg, len_arg >> 3, null_ptr_arg, null_bit_arg, : Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg), unireg_check_arg, field_name_arg),
bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7) bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7),
bytes_in_rec(len_arg / 8)
{ {
/* /*
Ensure that Field::eq() can distinguish between two different bit fields. Ensure that Field::eq() can distinguish between two different bit fields.
...@@ -8036,14 +8037,14 @@ int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs) ...@@ -8036,14 +8037,14 @@ int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs)
int delta; int delta;
for (; length && !*from; from++, length--); // skip left 0's for (; length && !*from; from++, length--); // skip left 0's
delta= field_length - length; delta= bytes_in_rec - length;
if (delta < -1 || if (delta < -1 ||
(delta == -1 && (uchar) *from > ((1 << bit_len) - 1)) || (delta == -1 && (uchar) *from > ((1 << bit_len) - 1)) ||
(!bit_len && delta < 0)) (!bit_len && delta < 0))
{ {
set_rec_bits(0xff, bit_ptr, bit_ofs, bit_len); set_rec_bits(0xff, bit_ptr, bit_ofs, bit_len);
memset(ptr, 0xff, field_length); memset(ptr, 0xff, bytes_in_rec);
if (table->in_use->really_abort_on_warning()) if (table->in_use->really_abort_on_warning())
set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
else else
...@@ -8071,7 +8072,7 @@ int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs) ...@@ -8071,7 +8072,7 @@ int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs)
set_rec_bits((uchar) *from, bit_ptr, bit_ofs, bit_len); set_rec_bits((uchar) *from, bit_ptr, bit_ofs, bit_len);
from++; from++;
} }
memcpy(ptr, from, field_length); memcpy(ptr, from, bytes_in_rec);
} }
return 0; return 0;
} }
...@@ -8112,10 +8113,10 @@ longlong Field_bit::val_int(void) ...@@ -8112,10 +8113,10 @@ longlong Field_bit::val_int(void)
if (bit_len) if (bit_len)
{ {
bits= get_rec_bits(bit_ptr, bit_ofs, bit_len); bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
bits<<= (field_length * 8); bits<<= (bytes_in_rec * 8);
} }
switch (field_length) { switch (bytes_in_rec) {
case 0: return bits; case 0: return bits;
case 1: return bits | (ulonglong) (uchar) ptr[0]; case 1: return bits | (ulonglong) (uchar) ptr[0];
case 2: return bits | mi_uint2korr(ptr); case 2: return bits | mi_uint2korr(ptr);
...@@ -8124,7 +8125,7 @@ longlong Field_bit::val_int(void) ...@@ -8124,7 +8125,7 @@ longlong Field_bit::val_int(void)
case 5: return bits | mi_uint5korr(ptr); case 5: return bits | mi_uint5korr(ptr);
case 6: return bits | mi_uint6korr(ptr); case 6: return bits | mi_uint6korr(ptr);
case 7: return bits | mi_uint7korr(ptr); case 7: return bits | mi_uint7korr(ptr);
default: return mi_uint8korr(ptr + field_length - sizeof(longlong)); default: return mi_uint8korr(ptr + bytes_in_rec - sizeof(longlong));
} }
} }
...@@ -8206,7 +8207,7 @@ int Field_bit::cmp_offset(uint row_offset) ...@@ -8206,7 +8207,7 @@ int Field_bit::cmp_offset(uint row_offset)
if ((flag= (int) (bits_a - bits_b))) if ((flag= (int) (bits_a - bits_b)))
return flag; return flag;
} }
return memcmp(ptr, ptr + row_offset, field_length); return memcmp(ptr, ptr + row_offset, bytes_in_rec);
} }
...@@ -8218,7 +8219,7 @@ void Field_bit::get_key_image(char *buff, uint length, imagetype type) ...@@ -8218,7 +8219,7 @@ void Field_bit::get_key_image(char *buff, uint length, imagetype type)
*buff++= bits; *buff++= bits;
length--; length--;
} }
memcpy(buff, ptr, min(length, field_length)); memcpy(buff, ptr, min(length, bytes_in_rec));
} }
...@@ -8226,21 +8227,21 @@ void Field_bit::sql_type(String &res) const ...@@ -8226,21 +8227,21 @@ void Field_bit::sql_type(String &res) const
{ {
CHARSET_INFO *cs= res.charset(); CHARSET_INFO *cs= res.charset();
ulong length= cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(), ulong length= cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(),
"bit(%d)", "bit(%d)", (int) field_length);
(int) field_length * 8 + bit_len);
res.length((uint) length); res.length((uint) length);
} }
char *Field_bit::pack(char *to, const char *from, uint max_length) char *Field_bit::pack(char *to, const char *from, uint max_length)
{ {
uint length= min(field_length + (bit_len > 0), max_length); DBUG_ASSERT(max_length);
uint length;
if (bit_len) if (bit_len)
{ {
uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len); uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
*to++= bits; *to++= bits;
length--;
} }
length= min(bytes_in_rec, max_length - (bit_len > 0));
memcpy(to, from, length); memcpy(to, from, length);
return to + length; return to + length;
} }
...@@ -8253,8 +8254,8 @@ const char *Field_bit::unpack(char *to, const char *from) ...@@ -8253,8 +8254,8 @@ const char *Field_bit::unpack(char *to, const char *from)
set_rec_bits(*from, bit_ptr, bit_ofs, bit_len); set_rec_bits(*from, bit_ptr, bit_ofs, bit_len);
from++; from++;
} }
memcpy(to, from, field_length); memcpy(to, from, bytes_in_rec);
return from + field_length; return from + bytes_in_rec;
} }
...@@ -8268,25 +8269,24 @@ Field_bit_as_char::Field_bit_as_char(char *ptr_arg, uint32 len_arg, ...@@ -8268,25 +8269,24 @@ Field_bit_as_char::Field_bit_as_char(char *ptr_arg, uint32 len_arg,
const char *field_name_arg) const char *field_name_arg)
:Field_bit(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, 0, 0, :Field_bit(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, 0, 0,
unireg_check_arg, field_name_arg), unireg_check_arg, field_name_arg),
create_length(len_arg)
{ {
bit_len= 0; bit_len= 0;
field_length= ((len_arg + 7) & ~7) / 8; bytes_in_rec= (len_arg + 7) / 8;
} }
int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs) int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs)
{ {
int delta; int delta;
uchar bits= create_length & 7; uchar bits= field_length & 7;
for (; length && !*from; from++, length--); // skip left 0's for (; length && !*from; from++, length--); // skip left 0's
delta= field_length - length; delta= bytes_in_rec - length;
if (delta < 0 || if (delta < 0 ||
(delta == 0 && bits && (uint) (uchar) *from >= (uint) (1 << bits))) (delta == 0 && bits && (uint) (uchar) *from >= (uint) (1 << bits)))
{ {
memset(ptr, 0xff, field_length); memset(ptr, 0xff, bytes_in_rec);
if (bits) if (bits)
*ptr&= ((1 << bits) - 1); /* set first byte */ *ptr&= ((1 << bits) - 1); /* set first byte */
if (table->in_use->really_abort_on_warning()) if (table->in_use->really_abort_on_warning())
...@@ -8305,7 +8305,7 @@ void Field_bit_as_char::sql_type(String &res) const ...@@ -8305,7 +8305,7 @@ void Field_bit_as_char::sql_type(String &res) const
{ {
CHARSET_INFO *cs= res.charset(); CHARSET_INFO *cs= res.charset();
ulong length= cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(), ulong length= cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(),
"bit(%d)", (int) create_length); "bit(%d)", (int) field_length);
res.length((uint) length); res.length((uint) length);
} }
...@@ -9033,11 +9033,6 @@ create_field::create_field(Field *old_field,Field *orig_field) ...@@ -9033,11 +9033,6 @@ create_field::create_field(Field *old_field,Field *orig_field)
geom_type= ((Field_geom*)old_field)->geom_type; geom_type= ((Field_geom*)old_field)->geom_type;
break; break;
#endif #endif
case FIELD_TYPE_BIT:
length= (old_field->key_type() == HA_KEYTYPE_BIT) ?
((Field_bit *) old_field)->bit_len + length * 8 :
((Field_bit_as_char *) old_field)->create_length;
break;
default: default:
break; break;
} }
......
...@@ -1346,16 +1346,17 @@ public: ...@@ -1346,16 +1346,17 @@ public:
uchar *bit_ptr; // position in record where 'uneven' bits store uchar *bit_ptr; // position in record where 'uneven' bits store
uchar bit_ofs; // offset to 'uneven' high bits uchar bit_ofs; // offset to 'uneven' high bits
uint bit_len; // number of 'uneven' high bits uint bit_len; // number of 'uneven' high bits
uint bytes_in_rec;
Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
enum utype unireg_check_arg, const char *field_name_arg); enum utype unireg_check_arg, const char *field_name_arg);
enum_field_types type() const { return FIELD_TYPE_BIT; } enum_field_types type() const { return FIELD_TYPE_BIT; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; }
uint32 key_length() const { return (uint32) field_length + (bit_len > 0); } uint32 key_length() const { return (uint32) (field_length + 7) / 8; }
uint32 max_length() { return (uint32) field_length * 8 + bit_len; } uint32 max_length() { return field_length; }
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
Item_result result_type () const { return INT_RESULT; } Item_result result_type () const { return INT_RESULT; }
void reset(void) { bzero(ptr, field_length); } void reset(void) { bzero(ptr, bytes_in_rec); }
int store(const char *to, uint length, CHARSET_INFO *charset); int store(const char *to, uint length, CHARSET_INFO *charset);
int store(double nr); int store(double nr);
int store(longlong nr, bool unsigned_val); int store(longlong nr, bool unsigned_val);
...@@ -1378,9 +1379,8 @@ public: ...@@ -1378,9 +1379,8 @@ public:
{ Field_bit::store(buff, length, &my_charset_bin); } { Field_bit::store(buff, length, &my_charset_bin); }
void sort_string(char *buff, uint length) void sort_string(char *buff, uint length)
{ get_key_image(buff, length, itRAW); } { get_key_image(buff, length, itRAW); }
uint32 pack_length() const uint32 pack_length() const { return (uint32) (field_length + 7) / 8; }
{ return (uint32) field_length + (bit_len > 0); } uint32 pack_length_in_rec() const { return bytes_in_rec; }
uint32 pack_length_in_rec() const { return field_length; }
void sql_type(String &str) const; void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0); char *pack(char *to, const char *from, uint max_length=~(uint) 0);
const char *unpack(char* to, const char *from); const char *unpack(char* to, const char *from);
...@@ -1402,12 +1402,10 @@ public: ...@@ -1402,12 +1402,10 @@ public:
class Field_bit_as_char: public Field_bit { class Field_bit_as_char: public Field_bit {
public: public:
uchar create_length;
Field_bit_as_char(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, Field_bit_as_char(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg); enum utype unireg_check_arg, const char *field_name_arg);
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
uint32 max_length() { return (uint32) create_length; }
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
int store(const char *to, uint length, CHARSET_INFO *charset); int store(const char *to, uint length, CHARSET_INFO *charset);
int store(double nr) { return Field_bit::store(nr); } int store(double nr) { return Field_bit::store(nr); }
......
...@@ -4411,7 +4411,7 @@ static int create_ndb_column(NDBCOL &col, ...@@ -4411,7 +4411,7 @@ static int create_ndb_column(NDBCOL &col,
break; break;
case MYSQL_TYPE_BIT: case MYSQL_TYPE_BIT:
{ {
int no_of_bits= field->field_length*8 + ((Field_bit *) field)->bit_len; int no_of_bits= field->field_length;
col.setType(NDBCOL::Bit); col.setType(NDBCOL::Bit);
if (!no_of_bits) if (!no_of_bits)
col.setLength(1); col.setLength(1);
......
...@@ -192,7 +192,8 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, ...@@ -192,7 +192,8 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info,
Field_bit *field= (Field_bit *) (key_part->field); Field_bit *field= (Field_bit *) (key_part->field);
if (field->bit_len) if (field->bit_len)
{ {
uchar bits= *(from_key + key_part->length - field->field_length -1); uchar bits= *(from_key + key_part->length -
field->pack_length_in_rec() - 1);
set_rec_bits(bits, to_record + key_part->null_offset + set_rec_bits(bits, to_record + key_part->null_offset +
(key_part->null_bit == 128), (key_part->null_bit == 128),
field->bit_ofs, field->bit_len); field->bit_ofs, field->bit_len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment