From aebe728dd188c4c668a9f4649c0bcc127032c54f Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 26 Sep 2004 21:52:20 +0500 Subject: bug #5723 length(varchar utf8 field) returns verying results --- mysql-test/r/bdb.result | 9 +++++++ mysql-test/r/ctype_utf8.result | 16 +++++++++++ mysql-test/t/bdb.test | 12 +++++++++ mysql-test/t/ctype_utf8.test | 14 ++++++++++ sql/field.cc | 60 ++++++++++++++++++++++++++++++++++-------- 5 files changed, 100 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index 25118702d09..846adaf53ef 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -1251,3 +1251,12 @@ truncate t1; select * from t1; a b drop table t1; +SET NAMES utf8; +create table t1 (a varchar(255) character set utf8) engine=bdb; +set @a:= convert(repeat(_latin1 0xFF, 255) using utf8); +insert into t1 values (@a); +select a, length(a), char_length(a) from t1; +a length(a) char_length(a) +ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 510 255 +drop table t1; +SET NAMES latin1; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index c7d015da9dc..dcd19584c31 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -644,3 +644,19 @@ INSERT INTO t1 VALUES ('test'); SELECT a FROM t1 WHERE a LIKE '%te'; a DROP TABLE t1; +SET NAMES utf8; +CREATE TABLE t1 ( +subject varchar(255) character set utf8 collate utf8_unicode_ci, +p varchar(15) character set utf8 +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t1 VALUES ('谷川俊二と申しますが、インターネット予約の会員登録をしましたところ、メールアドレスを間違えてしまい会員IDが受け取ることが出来ませんでした。間違えアドレスはtani-shun@n.vodafone.ne.jpを書き込みました。どうすればよいですか? その他、住所等は間違えありません。連絡ください。よろしくお願いします。m(__)m','040312-000057'); +INSERT INTO t1 VALUES ('aaa','bbb'); +SELECT length(subject) FROM t1; +length(subject) +432 +3 +SELECT length(subject) FROM t1 ORDER BY 1; +length(subject) +3 +432 +DROP TABLE t1; diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test index 7ee7d18439d..86214ecd5a8 100644 --- a/mysql-test/t/bdb.test +++ b/mysql-test/t/bdb.test @@ -897,3 +897,15 @@ commit; truncate t1; select * from t1; drop table t1; + +# +# Check that BDB works fine with a string which is +# longer than 255 bytes for multibyte characters. +# +SET NAMES utf8; +create table t1 (a varchar(255) character set utf8) engine=bdb; +set @a:= convert(repeat(_latin1 0xFF, 255) using utf8); +insert into t1 values (@a); +select a, length(a), char_length(a) from t1; +drop table t1; +SET NAMES latin1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index f5bd9ede673..4c6ff2abde7 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -499,3 +499,17 @@ CREATE TABLE t1 (a varchar(32) BINARY) CHARACTER SET utf8; INSERT INTO t1 VALUES ('test'); SELECT a FROM t1 WHERE a LIKE '%te'; DROP TABLE t1; + +# +# Bug #5723: length() returns varying results +# +SET NAMES utf8; +CREATE TABLE t1 ( + subject varchar(255) character set utf8 collate utf8_unicode_ci, + p varchar(15) character set utf8 +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t1 VALUES ('谷川俊二と申しますが、インターネット予約の会員登録をしましたところ、メールアドレスを間違えてしまい会員IDが受け取ることが出来ませんでした。間違えアドレスはtani-shun@n.vodafone.ne.jpを書き込みました。どうすればよいですか? その他、住所等は間違えありません。連絡ください。よろしくお願いします。m(__)m','040312-000057'); +INSERT INTO t1 VALUES ('aaa','bbb'); +SELECT length(subject) FROM t1; +SELECT length(subject) FROM t1 ORDER BY 1; +DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 17a89ad02c1..988dfbcb535 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4384,12 +4384,19 @@ void Field_string::sql_type(String &res) const char *Field_string::pack(char *to, const char *from, uint max_length) { const char *end=from+min(field_length,max_length); - uchar length; + uint length; while (end > from && end[-1] == ' ') end--; - *to= length=(uchar) (end-from); - memcpy(to+1, from, (int) length); - return to+1+length; + length= (end-from); + if (field_length > 255) + { + int2store(to, length); + to+= 2; + } + else + *to++= (char) (uchar) length; + memcpy(to, from, (int) length); + return to+length; } @@ -4402,15 +4409,28 @@ char *Field_string::pack_key(char *to, const char *from, uint max_length) set_if_smaller(length, char_length); while (length && from[length-1] == ' ') length--; - *to= (uchar)length; - memcpy(to+1, from, length); - return to+1+length; + if (field_length > 255) + { + int2store(to, length); + to+= 2; + } + else + *to++= (char) (uchar) length; + memcpy(to, from, length); + return to+length; } const char *Field_string::unpack(char *to, const char *from) { - uint length= (uint) (uchar) *from++; + uint length; + if (field_length > 255) + { + length= uint2korr(from); + from+= 2; + } + else + length= (uint) (uchar) *from++; memcpy(to, from, (int) length); bfill(to+length, field_length - length, ' '); return from+length; @@ -4419,8 +4439,19 @@ const char *Field_string::unpack(char *to, const char *from) int Field_string::pack_cmp(const char *a, const char *b, uint length) { - uint a_length= (uint) (uchar) *a++; - uint b_length= (uint) (uchar) *b++; + uint a_length, b_length; + if (field_length > 255) + { + a_length= uint2korr(a); + b_length= uint2korr(b); + a+= 2; + b+= 2; + } + else + { + a_length= (uint) (uchar) *a++; + b_length= (uint) (uchar) *b++; + } return my_strnncoll(field_charset, (const uchar*)a,a_length, (const uchar*)b,b_length); @@ -4429,7 +4460,14 @@ int Field_string::pack_cmp(const char *a, const char *b, uint length) int Field_string::pack_cmp(const char *b, uint length) { - uint b_length= (uint) (uchar) *b++; + uint b_length; + if (field_length > 255) + { + b_length= uint2korr(b); + b+= 2; + } + else + b_length= (uint) (uchar) *b++; char *end= ptr + field_length; while (end > ptr && end[-1] == ' ') end--; -- cgit v1.2.1