Bug#18691: Converting number to UNICODE string returns invalid result.
Conversion from int and real numbers to UCS2 didn't work fine: CONVERT(100, CHAR(50) UNICODE) CONVERT(103.9, CHAR(50) UNICODE) The problem appeared because numbers have binary charset, so, simple charset recast binary->ucs2 was performed instead of real conversion. Fixed to make numbers pretend to be non-binary.
This commit is contained in:
parent
76a122d0c3
commit
45293fc346
@ -666,6 +666,18 @@ Warnings:
|
||||
Warning 1265 Data truncated for column 'Field1' at row 1
|
||||
DROP TABLE t1;
|
||||
SET NAMES latin1;
|
||||
SELECT CONVERT(103, CHAR(50) UNICODE);
|
||||
CONVERT(103, CHAR(50) UNICODE)
|
||||
103
|
||||
SELECT CONVERT(103.0, CHAR(50) UNICODE);
|
||||
CONVERT(103.0, CHAR(50) UNICODE)
|
||||
103.0
|
||||
SELECT CONVERT(-103, CHAR(50) UNICODE);
|
||||
CONVERT(-103, CHAR(50) UNICODE)
|
||||
-103
|
||||
SELECT CONVERT(-103.0, CHAR(50) UNICODE);
|
||||
CONVERT(-103.0, CHAR(50) UNICODE)
|
||||
-103.0
|
||||
CREATE TABLE t1 (
|
||||
a varchar(255) NOT NULL default '',
|
||||
KEY a (a)
|
||||
|
@ -407,6 +407,14 @@ INSERT INTO t1 VALUES ('-1');
|
||||
DROP TABLE t1;
|
||||
SET NAMES latin1;
|
||||
|
||||
#
|
||||
# Bug#18691 Converting number to UNICODE string returns invalid result
|
||||
#
|
||||
SELECT CONVERT(103, CHAR(50) UNICODE);
|
||||
SELECT CONVERT(103.0, CHAR(50) UNICODE);
|
||||
SELECT CONVERT(-103, CHAR(50) UNICODE);
|
||||
SELECT CONVERT(-103.0, CHAR(50) UNICODE);
|
||||
|
||||
#
|
||||
# Bug#9557 MyISAM utf8 table crash
|
||||
#
|
||||
|
@ -2221,8 +2221,8 @@ String *Item_char_typecast::val_str(String *str)
|
||||
// Convert character set if differ
|
||||
uint dummy_errors;
|
||||
if (!(res= args[0]->val_str(&tmp_value)) ||
|
||||
str->copy(res->ptr(), res->length(), res->charset(),
|
||||
cast_cs, &dummy_errors))
|
||||
str->copy(res->ptr(), res->length(), from_cs,
|
||||
cast_cs, &dummy_errors))
|
||||
{
|
||||
null_value= 1;
|
||||
return 0;
|
||||
@ -2261,14 +2261,32 @@ void Item_char_typecast::fix_length_and_dec()
|
||||
For single-byte character sets we allow just to copy
|
||||
from the argument. A single-byte character sets string
|
||||
is always well-formed.
|
||||
|
||||
There is a special trick to convert form a number to ucs2.
|
||||
As numbers have my_charset_bin as their character set,
|
||||
it wouldn't do conversion to ucs2 without an additional action.
|
||||
To force conversion, we should pretend to be non-binary.
|
||||
Let's choose from_cs this way:
|
||||
- If the argument in a number and cast_cs is ucs2 (i.e. mbminlen > 1),
|
||||
then from_cs is set to latin1, to perform latin1 -> ucs2 conversion.
|
||||
- If the argument is a number and cast_cs is ASCII-compatible
|
||||
(i.e. mbminlen == 1), then from_cs is set to cast_cs,
|
||||
which allows just to take over the args[0]->val_str() result
|
||||
and thus avoid unnecessary character set conversion.
|
||||
- If the argument is not a number, then from_cs is set to
|
||||
the argument's charset.
|
||||
*/
|
||||
from_cs= (args[0]->result_type() == INT_RESULT ||
|
||||
args[0]->result_type() == REAL_RESULT) ?
|
||||
(cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) :
|
||||
args[0]->collation.collation;
|
||||
charset_conversion= (cast_cs->mbmaxlen > 1) ||
|
||||
!my_charset_same(args[0]->collation.collation, cast_cs) &&
|
||||
args[0]->collation.collation != &my_charset_bin &&
|
||||
!my_charset_same(from_cs, cast_cs) &&
|
||||
from_cs != &my_charset_bin &&
|
||||
cast_cs != &my_charset_bin;
|
||||
collation.set(cast_cs, DERIVATION_IMPLICIT);
|
||||
char_length= (cast_length >= 0) ? cast_length :
|
||||
args[0]->max_length/args[0]->collation.collation->mbmaxlen;
|
||||
args[0]->max_length/from_cs->mbmaxlen;
|
||||
max_length= char_length * cast_cs->mbmaxlen;
|
||||
}
|
||||
|
||||
|
@ -681,7 +681,7 @@ public:
|
||||
class Item_char_typecast :public Item_typecast
|
||||
{
|
||||
int cast_length;
|
||||
CHARSET_INFO *cast_cs;
|
||||
CHARSET_INFO *cast_cs, *from_cs;
|
||||
bool charset_conversion;
|
||||
String tmp_value;
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user