summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/field.cc8
-rw-r--r--sql/sql_string.cc30
-rw-r--r--sql/sql_string.h3
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, &not_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, &not_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);