Commit 629a4b1a authored by unknown's avatar unknown

Bug#15583: BIN()/OCT()/CONV() do not work with BIT values

Converting BIT to a string (an intermediate step in conversion) does 
not yield an ASCII numeric string, so we skip that step for BIT and
get the integer value directly from the item.

This site in sql/item_strfunc.cc may be ripe for refactoring for
other types as well, where converting to a string is a waste of time.


mysql-test/r/type_bit.result:
  Test that conversion functions on BIT types work properly, including 
  NULL.
mysql-test/t/type_bit.test:
  Test that conversion functions on BIT types work properly.
sql/item_strfunc.cc:
  BIT is unlike the other numeric types, in that when we convert it
  to a String, it becomes a one-byte string with ordinal numeric value
  of the BIT field, not a several-byte string with the ASCII decimal
  representation.  As a special case for conversion functions, we take
  the integer directly from the bit type instead of representing it
  as a string in an intermediate step.
parent 1cf65f31
...@@ -572,4 +572,34 @@ def test t1 t1 a a 16 7 1 Y 0 0 63 ...@@ -572,4 +572,34 @@ def test t1 t1 a a 16 7 1 Y 0 0 63
a a
` `
drop table t1; drop table t1;
create table bug15583(b BIT(8), n INT);
insert into bug15583 values(128, 128);
insert into bug15583 values(null, null);
insert into bug15583 values(0, 0);
insert into bug15583 values(255, 255);
select hex(b), bin(b), oct(b), hex(n), bin(n), oct(n) from bug15583;
hex(b) bin(b) oct(b) hex(n) bin(n) oct(n)
80 10000000 200 80 10000000 200
NULL NULL NULL NULL NULL NULL
0 0 0 0 0 0
FF 11111111 377 FF 11111111 377
select hex(b)=hex(n) as should_be_onetrue, bin(b)=bin(n) as should_be_onetrue, oct(b)=oct(n) as should_be_onetrue from bug15583;
should_be_onetrue should_be_onetrue should_be_onetrue
1 1 1
NULL NULL NULL
1 1 1
1 1 1
select hex(b + 0), bin(b + 0), oct(b + 0), hex(n), bin(n), oct(n) from bug15583;
hex(b + 0) bin(b + 0) oct(b + 0) hex(n) bin(n) oct(n)
80 10000000 200 80 10000000 200
NULL NULL NULL NULL NULL NULL
0 0 0 0 0 0
FF 11111111 377 FF 11111111 377
select conv(b, 10, 2), conv(b + 0, 10, 2) from bug15583;
conv(b, 10, 2) conv(b + 0, 10, 2)
10000000 10000000
NULL NULL
0 0
11111111 11111111
drop table bug15583;
End of 5.0 tests End of 5.0 tests
...@@ -238,4 +238,19 @@ select * from t1; ...@@ -238,4 +238,19 @@ select * from t1;
--disable_metadata --disable_metadata
drop table t1; drop table t1;
#
# Bug#15583: BIN()/OCT()/CONV() do not work with BIT values
#
create table bug15583(b BIT(8), n INT);
insert into bug15583 values(128, 128);
insert into bug15583 values(null, null);
insert into bug15583 values(0, 0);
insert into bug15583 values(255, 255);
select hex(b), bin(b), oct(b), hex(n), bin(n), oct(n) from bug15583;
select hex(b)=hex(n) as should_be_onetrue, bin(b)=bin(n) as should_be_onetrue, oct(b)=oct(n) as should_be_onetrue from bug15583;
select hex(b + 0), bin(b + 0), oct(b + 0), hex(n), bin(n), oct(n) from bug15583;
select conv(b, 10, 2), conv(b + 0, 10, 2) from bug15583;
drop table bug15583;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -2359,17 +2359,33 @@ String *Item_func_conv::val_str(String *str) ...@@ -2359,17 +2359,33 @@ String *Item_func_conv::val_str(String *str)
abs(to_base) > 36 || abs(to_base) < 2 || abs(to_base) > 36 || abs(to_base) < 2 ||
abs(from_base) > 36 || abs(from_base) < 2 || !(res->length())) abs(from_base) > 36 || abs(from_base) < 2 || !(res->length()))
{ {
null_value=1; null_value= 1;
return 0; return NULL;
} }
null_value=0; null_value= 0;
unsigned_flag= !(from_base < 0); unsigned_flag= !(from_base < 0);
if (from_base < 0)
dec= my_strntoll(res->charset(),res->ptr(),res->length(),-from_base,&endptr,&err); if (args[0]->field_type() == MYSQL_TYPE_BIT)
{
/*
Special case: The string representation of BIT doesn't resemble the
decimal representation, so we shouldn't change it to string and then to
decimal.
*/
dec= args[0]->val_int();
}
else else
dec= (longlong) my_strntoull(res->charset(),res->ptr(),res->length(),from_base,&endptr,&err); {
ptr= longlong2str(dec,ans,to_base); if (from_base < 0)
if (str->copy(ans,(uint32) (ptr-ans), default_charset())) dec= my_strntoll(res->charset(), res->ptr(), res->length(),
-from_base, &endptr, &err);
else
dec= (longlong) my_strntoull(res->charset(), res->ptr(), res->length(),
from_base, &endptr, &err);
}
ptr= longlong2str(dec, ans, to_base);
if (str->copy(ans, (uint32) (ptr-ans), default_charset()))
return &my_empty_string; return &my_empty_string;
return str; return str;
} }
......
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