diff options
author | bar@bar.intranet.mysql.r18.ru <> | 2004-01-21 14:15:19 +0400 |
---|---|---|
committer | bar@bar.intranet.mysql.r18.ru <> | 2004-01-21 14:15:19 +0400 |
commit | 03d00c7da907f7df22729f3795e49d025f1049af (patch) | |
tree | 058a7d4f2f63504db9bb954a87f85a755f802179 /sql | |
parent | 237d655e12585621f16770fed32b456241dda8f3 (diff) | |
download | mariadb-git-03d00c7da907f7df22729f3795e49d025f1049af.tar.gz |
Further fixes for 2390: ucs2 alignment
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 16 | ||||
-rw-r--r-- | sql/sql_string.cc | 54 | ||||
-rw-r--r-- | sql/sql_string.h | 3 |
3 files changed, 59 insertions, 14 deletions
diff --git a/sql/field.cc b/sql/field.cc index 1a0716326fe..8dc133adae8 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4055,18 +4055,13 @@ void Field_datetime::sql_type(String &res) const /* 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 error= 0; char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); /* 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); from= tmpstr.ptr(); @@ -4254,7 +4249,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); /* 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); from= tmpstr.ptr(); @@ -4572,7 +4567,8 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) String tmpstr(buff,sizeof(buff), &my_charset_bin); /* 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); from= tmpstr.ptr(); @@ -5082,7 +5078,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) char buff[80]; String tmpstr(buff,sizeof(buff), &my_charset_bin); /* 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); from= tmpstr.ptr(); @@ -5263,7 +5259,7 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) String tmpstr(buff,sizeof(buff), &my_charset_bin); /* 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); from= tmpstr.ptr(); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 9534c5605fe..225076bc555 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -228,6 +228,32 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) 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, ** 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) ** SELECT _ucs2 0x00AA */ -bool String::set_or_copy_aligned(const char *str,uint32 arg_length, - CHARSET_INFO *cs) +bool String::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); + copy(str, arg_length, cs); return FALSE; } @@ -274,15 +300,35 @@ bool String::set_or_copy_aligned(const char *str,uint32 arg_length, 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 */ bool String::copy(const char *str, uint32 arg_length, 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); } + 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; if (alloc(new_length)) return TRUE; diff --git a/sql/sql_string.h b/sql/sql_string.h index 8817aa8eab8..9c0900137e3 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -183,6 +183,9 @@ public: bool copy(); // Alloc string if not alloced bool copy(const String &s); // 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 copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto); |