diff options
-rw-r--r-- | sql/field.cc | 8 | ||||
-rw-r--r-- | sql/sql_string.cc | 30 | ||||
-rw-r--r-- | sql/sql_string.h | 3 |
3 files changed, 36 insertions, 5 deletions
diff --git a/sql/field.cc b/sql/field.cc index c65346423a0..3069a1ef60b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7376,8 +7376,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) If content of the 'from'-address is cached in the 'value'-object it is possible that the content needs a character conversion. */ - uint32 dummy_offset; - if (!String::needs_conversion(length, cs, field_charset, &dummy_offset)) + if (!String::needs_conversion_on_storage(length, cs, field_charset)) { Field_blob::store_length(length); bmove(ptr+packlength, &from, sizeof(char*)); @@ -7980,7 +7979,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) String tmpstr(buff,sizeof(buff), &my_charset_bin); /* Convert character set if necessary */ - if (String::needs_conversion(length, cs, field_charset, ¬_used)) + if (String::needs_conversion_on_storage(length, cs, field_charset)) { uint dummy_errors; tmpstr.copy(from, length, cs, field_charset, &dummy_errors); @@ -8196,12 +8195,11 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs) int err= 0; char *not_used; uint not_used2; - uint32 not_used_offset; char buff[STRING_BUFFER_USUAL_SIZE]; String tmpstr(buff,sizeof(buff), &my_charset_bin); /* Convert character set if necessary */ - if (String::needs_conversion(length, cs, field_charset, ¬_used_offset)) + if (String::needs_conversion_on_storage(length, cs, field_charset)) { uint dummy_errors; tmpstr.copy(from, length, cs, field_charset, &dummy_errors); diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 07fc7e4ff1d..b9a9ce92cd6 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -224,6 +224,36 @@ bool String::needs_conversion(uint32 arg_length, /* + Checks that the source string can just be copied to the destination string + without conversion. + Unlike needs_conversion it will require conversion on incoming binary data + to ensure the data are verified for vailidity first. + + @param arg_length Length of string to copy. + @param from_cs Character set to copy from + @param to_cs Character set to copy to + + @return conversion needed +*/ +bool String::needs_conversion_on_storage(uint32 arg_length, + CHARSET_INFO *cs_from, + CHARSET_INFO *cs_to) +{ + uint32 offset; + return (needs_conversion(arg_length, cs_from, cs_to, &offset) || + (cs_from == &my_charset_bin && /* force conversion when storing a binary string */ + cs_to != &my_charset_bin && /* into a non-binary destination */ + ( /* and any of the following is true :*/ + cs_to->mbminlen != cs_to->mbmaxlen || /* it's a variable length encoding */ + cs_to->mbminlen > 2 || /* longer than 2 bytes : neither 1 byte nor ucs2 */ + 0 != (arg_length % cs_to->mbmaxlen) + ) + ) + ); +} + + +/* Copy a multi-byte character sets with adding leading zeros. SYNOPSIS diff --git a/sql/sql_string.h b/sql/sql_string.h index 234e8272b88..971af9ea91a 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -280,6 +280,9 @@ public: static bool needs_conversion(uint32 arg_length, CHARSET_INFO *cs_from, CHARSET_INFO *cs_to, uint32 *offset); + static bool needs_conversion_on_storage(uint32 arg_length, + CHARSET_INFO *cs_from, + CHARSET_INFO *cs_to); bool copy_aligned(const char *s, uint32 arg_length, uint32 offset, CHARSET_INFO *cs); bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs); |