summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorbar@bar.intranet.mysql.r18.ru <>2004-01-21 14:15:19 +0400
committerbar@bar.intranet.mysql.r18.ru <>2004-01-21 14:15:19 +0400
commit03d00c7da907f7df22729f3795e49d025f1049af (patch)
tree058a7d4f2f63504db9bb954a87f85a755f802179 /sql
parent237d655e12585621f16770fed32b456241dda8f3 (diff)
downloadmariadb-git-03d00c7da907f7df22729f3795e49d025f1049af.tar.gz
Further fixes for 2390: ucs2 alignment
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc16
-rw-r--r--sql/sql_string.cc54
-rw-r--r--sql/sql_string.h3
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);