summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bar@mysql.com>2004-12-06 20:45:32 +0400
committerunknown <bar@mysql.com>2004-12-06 20:45:32 +0400
commit8ec6cf2cd5ed54f1336784ffe548a813cbbde172 (patch)
treea397eb25eef58a660d9d2e554e7c8f8800bdb8f4 /sql
parent678fff408a8cd475555d3bbce3d77fd0a2c76a4a (diff)
downloadmariadb-git-8ec6cf2cd5ed54f1336784ffe548a813cbbde172.tar.gz
UCS2 support in ENUM and SET, which also fixes:
Bug #5174 SHOW CREATE TABLE hangs up if the table contains half-with katakana enum values UCS2 values are stored in HEX encoding in FRM file
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc19
-rw-r--r--sql/item_strfunc.cc11
-rw-r--r--sql/mysql_priv.h17
-rw-r--r--sql/strfunc.cc20
-rw-r--r--sql/table.cc17
-rw-r--r--sql/unireg.cc22
6 files changed, 83 insertions, 23 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 6dfddf6fd71..74252a46842 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5529,8 +5529,7 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
}
/* Remove end space */
- while (length > 0 && my_isspace(system_charset_info,from[length-1]))
- length--;
+ length= field_charset->cset->lengthsp(field_charset, from, length);
uint tmp=find_type2(typelib, from, length, field_charset);
if (!tmp)
{
@@ -5632,7 +5631,7 @@ String *Field_enum::val_str(String *val_buffer __attribute__((unused)),
val_ptr->set("", 0, field_charset);
else
val_ptr->set((const char*) typelib->type_names[tmp-1],
- (uint) strlen(typelib->type_names[tmp-1]),
+ typelib->type_lengths[tmp-1],
field_charset);
return val_ptr;
}
@@ -5669,13 +5668,14 @@ void Field_enum::sql_type(String &res) const
res.append("enum(");
bool flag=0;
- for (const char **pos= typelib->type_names; *pos; pos++)
+ uint *len= typelib->type_lengths;
+ for (const char **pos= typelib->type_names; *pos; pos++, len++)
{
uint dummy_errors;
if (flag)
res.append(',');
/* convert to res.charset() == utf8, then quote */
- enum_item.copy(*pos, strlen(*pos), charset(), res.charset(), &dummy_errors);
+ enum_item.copy(*pos, *len, charset(), res.charset(), &dummy_errors);
append_unescaped(&res, enum_item.ptr(), enum_item.length());
flag= 1;
}
@@ -5760,9 +5760,9 @@ String *Field_set::val_str(String *val_buffer,
if (tmp & 1)
{
if (val_buffer->length())
- val_buffer->append(field_separator);
+ val_buffer->append(&field_separator, 1, &my_charset_latin1);
String str(typelib->type_names[bitnr],
- (uint) strlen(typelib->type_names[bitnr]),
+ typelib->type_lengths[bitnr],
field_charset);
val_buffer->append(str);
}
@@ -5782,13 +5782,14 @@ void Field_set::sql_type(String &res) const
res.append("set(");
bool flag=0;
- for (const char **pos= typelib->type_names; *pos; pos++)
+ uint *len= typelib->type_lengths;
+ for (const char **pos= typelib->type_names; *pos; pos++, len++)
{
uint dummy_errors;
if (flag)
res.append(',');
/* convert to res.charset() == utf8, then quote */
- set_item.copy(*pos, strlen(*pos), charset(), res.charset(), &dummy_errors);
+ set_item.copy(*pos, *len, charset(), res.charset(), &dummy_errors);
append_unescaped(&res, set_item.ptr(), set_item.length());
flag= 1;
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 5a23eec5a1b..893126b7fe6 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2320,17 +2320,6 @@ String *Item_func_hex::val_str(String *str)
return &tmp_value;
}
-inline int hexchar_to_int(char c)
-{
- if (c <= '9' && c >= '0')
- return c-'0';
- c|=32;
- if (c <= 'f' && c >= 'a')
- return c-'a'+10;
- return -1;
-}
-
-
/* Convert given hex string to a binary string */
String *Item_func_unhex::val_str(String *str)
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 3a19a903e00..cefc77cb5d4 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1201,6 +1201,23 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
/*
+ SYNOPSYS
+ hexchar_to_int()
+ convert a hex digit into number
+*/
+
+inline int hexchar_to_int(char c)
+{
+ if (c <= '9' && c >= '0')
+ return c-'0';
+ c|=32;
+ if (c <= 'f' && c >= 'a')
+ return c-'a'+10;
+ return -1;
+}
+
+
+/*
Some functions that are different in the embedded library and the normal
server
*/
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
index b5255e9be06..8ab6992a63a 100644
--- a/sql/strfunc.cc
+++ b/sql/strfunc.cc
@@ -53,8 +53,22 @@ ulonglong find_set(TYPELIB *lib, const char *str, uint length, CHARSET_INFO *cs,
{
const char *pos= start;
uint var_len;
+ int mblen= 1;
- for (; pos != end && *pos != field_separator; pos++) ;
+ if (cs && cs->mbminlen > 1)
+ {
+ for ( ; pos < end; pos+= mblen)
+ {
+ my_wc_t wc;
+ if ((mblen= cs->cset->mb_wc(cs, &wc, (const uchar *) pos,
+ (const uchar *) end)) < 1)
+ mblen= 1; // Not to hang on a wrong multibyte sequence
+ if (wc == (my_wc_t) field_separator)
+ break;
+ }
+ }
+ else
+ for (; pos != end && *pos != field_separator; pos++) ;
var_len= (uint) (pos - start);
uint find= cs ? find_type2(lib, start, var_len, cs) :
find_type(lib, start, var_len, (bool) 0);
@@ -66,9 +80,9 @@ ulonglong find_set(TYPELIB *lib, const char *str, uint length, CHARSET_INFO *cs,
}
else
found|= ((longlong) 1 << (find - 1));
- if (pos == end)
+ if (pos >= end)
break;
- start= pos + 1;
+ start= pos + mblen;
}
}
return found;
diff --git a/sql/table.cc b/sql/table.cc
index cb565097c0b..370ad5eff1d 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -485,6 +485,23 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
charset= outparam->table_charset;
bzero((char*) &comment, sizeof(comment));
}
+
+ if (interval_nr && charset->mbminlen > 1)
+ {
+ /* Unescape UCS2 intervals from HEX notation */
+ TYPELIB *interval= outparam->intervals + interval_nr - 1;
+ for (uint pos= 0; pos < interval->count; pos++)
+ {
+ char *from, *to;
+ for (from= to= (char*) interval->type_names[pos]; *from; )
+ {
+ *to++= (char) (hexchar_to_int(*from++) << 4) +
+ hexchar_to_int(*from++);
+ }
+ interval->type_lengths[pos] /= 2;
+ }
+ }
+
*field_ptr=reg_field=
make_field(record+recpos,
(uint32) field_length,
diff --git a/sql/unireg.cc b/sql/unireg.cc
index c82fcc4abef..6d72c6af135 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -423,6 +423,28 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
if (field->interval)
{
uint old_int_count=int_count;
+
+ if (field->charset->mbminlen > 1)
+ {
+ /* Escape UCS2 intervals using HEX notation */
+ for (uint pos= 0; pos < field->interval->count; pos++)
+ {
+ char *dst;
+ uint length= field->interval->type_lengths[pos], hex_length;
+ const char *src= field->interval->type_names[pos];
+ const char *srcend= src + length;
+ hex_length= length * 2;
+ field->interval->type_lengths[pos]= hex_length;
+ field->interval->type_names[pos]= dst= sql_alloc(hex_length + 1);
+ for ( ; src < srcend; src++)
+ {
+ *dst++= _dig_vec_upper[((uchar) *src) >> 4];
+ *dst++= _dig_vec_upper[((uchar) *src) & 15];
+ }
+ *dst= '\0';
+ }
+ }
+
field->interval_id=get_interval_id(&int_count,create_fields,field);
if (old_int_count != int_count)
{