Further fixes for 2390: ucs2 alignment

parent 237d655e
...@@ -324,3 +324,59 @@ HEX(_ucs2 0x0123456789ABCDE) ...@@ -324,3 +324,59 @@ HEX(_ucs2 0x0123456789ABCDE)
SELECT HEX(_ucs2 0x0123456789ABCDEF); SELECT HEX(_ucs2 0x0123456789ABCDEF);
HEX(_ucs2 0x0123456789ABCDEF) HEX(_ucs2 0x0123456789ABCDEF)
0123456789ABCDEF 0123456789ABCDEF
SELECT hex(cast(0xAA as char character set ucs2));
hex(cast(0xAA as char character set ucs2))
00AA
SELECT hex(convert(0xAA using ucs2));
hex(convert(0xAA using ucs2))
00AA
CREATE TABLE t1 (a char(10) character set ucs2);
INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
HEX(a)
000A
00AA
0AAA
AAAA
000AAAAA
DROP TABLE t1;
CREATE TABLE t1 (a varchar(10) character set ucs2);
INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
HEX(a)
000A
00AA
0AAA
AAAA
000AAAAA
DROP TABLE t1;
CREATE TABLE t1 (a text character set ucs2);
INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
HEX(a)
000A
00AA
0AAA
AAAA
000AAAAA
DROP TABLE t1;
CREATE TABLE t1 (a mediumtext character set ucs2);
INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
HEX(a)
000A
00AA
0AAA
AAAA
000AAAAA
DROP TABLE t1;
CREATE TABLE t1 (a longtext character set ucs2);
INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
HEX(a)
000A
00AA
0AAA
AAAA
000AAAAA
DROP TABLE t1;
...@@ -200,7 +200,7 @@ DROP TABLE t1; ...@@ -200,7 +200,7 @@ DROP TABLE t1;
# Bug #2390 # Bug #2390
# Check alignment # Check alignment for constants
# #
SELECT HEX(_ucs2 0x0); SELECT HEX(_ucs2 0x0);
SELECT HEX(_ucs2 0x01); SELECT HEX(_ucs2 0x01);
...@@ -218,3 +218,39 @@ SELECT HEX(_ucs2 0x0123456789ABC); ...@@ -218,3 +218,39 @@ SELECT HEX(_ucs2 0x0123456789ABC);
SELECT HEX(_ucs2 0x0123456789ABCD); SELECT HEX(_ucs2 0x0123456789ABCD);
SELECT HEX(_ucs2 0x0123456789ABCDE); SELECT HEX(_ucs2 0x0123456789ABCDE);
SELECT HEX(_ucs2 0x0123456789ABCDEF); SELECT HEX(_ucs2 0x0123456789ABCDEF);
#
# Check alignment for from-binary-conversion with CAST and CONVERT
#
SELECT hex(cast(0xAA as char character set ucs2));
SELECT hex(convert(0xAA using ucs2));
#
# Check alignment for string types
#
CREATE TABLE t1 (a char(10) character set ucs2);
INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a varchar(10) character set ucs2);
INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a text character set ucs2);
INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a mediumtext character set ucs2);
INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a longtext character set ucs2);
INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
DROP TABLE t1;
-- the same should be also done with enum and set
...@@ -4055,18 +4055,13 @@ void Field_datetime::sql_type(String &res) const ...@@ -4055,18 +4055,13 @@ void Field_datetime::sql_type(String &res) const
/* Copy a string and fill with space */ /* Copy a string and fill with space */
static bool use_conversion(CHARSET_INFO *cs1, CHARSET_INFO *cs2)
{
return (cs1 != &my_charset_bin) && (cs2 != &my_charset_bin) && (cs1!=cs2);
}
int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
{ {
int error= 0; int error= 0;
char buff[80]; char buff[80];
String tmpstr(buff,sizeof(buff), &my_charset_bin); String tmpstr(buff,sizeof(buff), &my_charset_bin);
/* Convert character set if nesessary */ /* Convert character set if nesessary */
if (use_conversion(cs, field_charset)) if (String::needs_conversion(from, length, cs, field_charset))
{ {
tmpstr.copy(from, length, cs, field_charset); tmpstr.copy(from, length, cs, field_charset);
from= tmpstr.ptr(); from= tmpstr.ptr();
...@@ -4254,7 +4249,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) ...@@ -4254,7 +4249,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
char buff[80]; char buff[80];
String tmpstr(buff,sizeof(buff), &my_charset_bin); String tmpstr(buff,sizeof(buff), &my_charset_bin);
/* Convert character set if nesessary */ /* Convert character set if nesessary */
if (use_conversion(cs, field_charset)) if (String::needs_conversion(from, length, cs, field_charset))
{ {
tmpstr.copy(from, length, cs, field_charset); tmpstr.copy(from, length, cs, field_charset);
from= tmpstr.ptr(); from= tmpstr.ptr();
...@@ -4572,7 +4567,8 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) ...@@ -4572,7 +4567,8 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
String tmpstr(buff,sizeof(buff), &my_charset_bin); String tmpstr(buff,sizeof(buff), &my_charset_bin);
/* Convert character set if nesessary */ /* Convert character set if nesessary */
if ((was_conversion= use_conversion(cs, field_charset))) if ((was_conversion= String::needs_conversion(from, length,
cs, field_charset)))
{ {
tmpstr.copy(from, length, cs, field_charset); tmpstr.copy(from, length, cs, field_charset);
from= tmpstr.ptr(); from= tmpstr.ptr();
...@@ -5082,7 +5078,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) ...@@ -5082,7 +5078,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
char buff[80]; char buff[80];
String tmpstr(buff,sizeof(buff), &my_charset_bin); String tmpstr(buff,sizeof(buff), &my_charset_bin);
/* Convert character set if nesessary */ /* Convert character set if nesessary */
if (use_conversion(cs, field_charset)) if (String::needs_conversion(from, length, cs, field_charset))
{ {
tmpstr.copy(from, length, cs, field_charset); tmpstr.copy(from, length, cs, field_charset);
from= tmpstr.ptr(); from= tmpstr.ptr();
...@@ -5263,7 +5259,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) ...@@ -5263,7 +5259,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
String tmpstr(buff,sizeof(buff), &my_charset_bin); String tmpstr(buff,sizeof(buff), &my_charset_bin);
/* Convert character set if nesessary */ /* Convert character set if nesessary */
if (use_conversion(cs, field_charset)) if (String::needs_conversion(from, length, cs, field_charset))
{ {
tmpstr.copy(from, length, cs, field_charset); tmpstr.copy(from, length, cs, field_charset);
from= tmpstr.ptr(); from= tmpstr.ptr();
......
...@@ -228,6 +228,32 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) ...@@ -228,6 +228,32 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
return FALSE; return FALSE;
} }
/*
Checks that the source string can be just copied
to the destination string without conversion.
If either character set conversion or adding leading
zeros (e.g. for UCS-2) must be done then return
value is TRUE else FALSE.
*/
bool String::needs_conversion(const char *str, uint32 arg_length,
CHARSET_INFO *from_cs,
CHARSET_INFO *to_cs)
{
if (to_cs == &my_charset_bin)
return FALSE;
if (to_cs == from_cs)
return FALSE;
if (my_charset_same(from_cs, to_cs))
return FALSE;
if ((from_cs == &my_charset_bin))
{
if (!(arg_length % to_cs->mbminlen))
return FALSE;
}
return TRUE;
}
/* /*
** For real multi-byte, ascii incompatible charactser sets, ** For real multi-byte, ascii incompatible charactser sets,
** like UCS-2, add leading zeros if we have an incomplete character. ** like UCS-2, add leading zeros if we have an incomplete character.
...@@ -237,15 +263,15 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) ...@@ -237,15 +263,15 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs)
** SELECT _ucs2 0x00AA ** SELECT _ucs2 0x00AA
*/ */
bool String::set_or_copy_aligned(const char *str,uint32 arg_length, bool String::copy_aligned(const char *str,uint32 arg_length,
CHARSET_INFO *cs) CHARSET_INFO *cs)
{ {
/* How many bytes are in incomplete character */ /* How many bytes are in incomplete character */
uint32 offs= (arg_length % cs->mbminlen); uint32 offs= (arg_length % cs->mbminlen);
if (!offs) /* All characters are complete, just copy */ if (!offs) /* All characters are complete, just copy */
{ {
set(str, arg_length, cs); copy(str, arg_length, cs);
return FALSE; return FALSE;
} }
...@@ -274,15 +300,35 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length, ...@@ -274,15 +300,35 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
return FALSE; return FALSE;
} }
bool String::set_or_copy_aligned(const char *str,uint32 arg_length,
CHARSET_INFO *cs)
{
/* How many bytes are in incomplete character */
uint32 offs= (arg_length % cs->mbminlen);
if (!offs) /* All characters are complete, just copy */
{
set(str, arg_length, cs);
return FALSE;
}
return copy_aligned(str, arg_length, cs);
}
/* Copy with charset convertion */ /* Copy with charset convertion */
bool String::copy(const char *str, uint32 arg_length, bool String::copy(const char *str, uint32 arg_length,
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
{ {
if ((from_cs == &my_charset_bin) || (to_cs == &my_charset_bin)) if (!needs_conversion(str, arg_length, from_cs, to_cs))
{ {
return copy(str, arg_length, to_cs); return copy(str, arg_length, to_cs);
} }
if ((from_cs == &my_charset_bin) && (arg_length % to_cs->mbminlen))
{
return copy_aligned(str, arg_length, to_cs);
}
uint32 new_length= to_cs->mbmaxlen*arg_length; uint32 new_length= to_cs->mbmaxlen*arg_length;
if (alloc(new_length)) if (alloc(new_length))
return TRUE; return TRUE;
......
...@@ -183,6 +183,9 @@ public: ...@@ -183,6 +183,9 @@ public:
bool copy(); // Alloc string if not alloced bool copy(); // Alloc string if not alloced
bool copy(const String &s); // Allocate new string bool copy(const String &s); // Allocate new string
bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string bool copy(const char *s,uint32 arg_length, CHARSET_INFO *cs); // Allocate new string
static bool needs_conversion(const char *s, uint32 arg_length,
CHARSET_INFO *cs_from, CHARSET_INFO *cs_to);
bool copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom,
CHARSET_INFO *csto); CHARSET_INFO *csto);
......
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