From 14912660c39354c366419d65899bc95061d63e6e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Sep 2005 23:10:51 +0500 Subject: [PATCH] Bug#13046: LIKE pattern matching using prefix index doesn't return correct result item_cmpfunc.cc: Use charset of LIKE to decide whether to use 8bit or Unicode "escape" value. But use charset of "escape" to scan escape character. strings/ctype-xxx.c: We cannot reduce "end" pointer using charpos(), because of possible escape characters in the string. Limit the loop using count of written characters instead. ctype_like_escape.inc: new file mysql-test/t/ctype_xxx: mysql-test/r/ctype_xxx: Adding test case. strings/ctype-big5.c: Bug#13046: LIKE pattern matching using prefix index doesn't return correct result We cannot change "end" pointer using charpos(), because of possible escape characters. Use limit by count of written characters instead. strings/ctype-cp932.c: Bug#13046: LIKE pattern matching using prefix index doesn't return correct result We cannot change "end" pointer using charpos(), because of possible escape characters. Use limit by count of written characters instead strings/ctype-gbk.c: Bug#13046: LIKE pattern matching using prefix index doesn't return correct result We cannot change "end" pointer using charpos(), because of possible escape characters. Use limit by count of written characters instead strings/ctype-mb.c: Bug#13046: LIKE pattern matching using prefix index doesn't return correct result We cannot change "end" pointer using charpos(), because of possible escape characters. Use limit by count of written characters instead strings/ctype-simple.c: Bug#13046: LIKE pattern matching using prefix index doesn't return correct result We cannot change "end" pointer using charpos(), because of possible escape characters. Use limit by count of written characters instead strings/ctype-sjis.c: Bug#13046: LIKE pattern matching using prefix index doesn't return correct result We cannot change "end" pointer using charpos(), because of possible escape characters. Use limit by count of written characters instead strings/ctype-tis620.c: Bug#13046: LIKE pattern matching using prefix index doesn't return correct result We cannot change "end" pointer using charpos(), because of possible escape characters. Use limit by count of written characters instead strings/ctype-ucs2.c: Bug#13046: LIKE pattern matching using prefix index doesn't return correct result We cannot change "end" pointer using charpos(), because of possible escape characters. Use limit by count of written characters instead mysql-test/t/ctype_big5.test: Adding test case. mysql-test/t/ctype_cp932.test: Adding test case. mysql-test/t/ctype_gbk.test: Adding test case. mysql-test/t/ctype_latin1.test: Adding test case. mysql-test/t/ctype_sjis.test: Adding test case. mysql-test/t/ctype_tis620.test: Adding test case. mysql-test/t/ctype_uca.test: Adding test case. mysql-test/t/ctype_ucs.test: Adding test case. mysql-test/t/ctype_ujis.test: Adding test case. mysql-test/t/ctype_utf8.test: Adding test case. mysql-test/r/ctype_big5.result: Adding test case. mysql-test/r/ctype_cp932.result: Adding test case. mysql-test/r/ctype_gbk.result: Adding test case. mysql-test/r/ctype_latin1.result: Adding test case. mysql-test/r/ctype_sjis.result: Adding test case. mysql-test/r/ctype_tis620.result: Adding test case. mysql-test/r/ctype_uca.result: Adding test case. mysql-test/r/ctype_ucs.result: Adding test case. mysql-test/r/ctype_ujis.result: Adding test case. mysql-test/r/ctype_utf8.result: Adding test case. sql/item_cmpfunc.cc: More fixes. --- mysql-test/include/ctype_like_escape.inc | 18 ++++++ mysql-test/r/ctype_big5.result | 36 ++++++++++++ mysql-test/r/ctype_cp932.result | 36 ++++++++++++ mysql-test/r/ctype_gbk.result | 36 ++++++++++++ mysql-test/r/ctype_latin1.result | 36 ++++++++++++ mysql-test/r/ctype_sjis.result | 36 ++++++++++++ mysql-test/r/ctype_tis620.result | 36 ++++++++++++ mysql-test/r/ctype_uca.result | 18 ++++++ mysql-test/r/ctype_ucs.result | 36 ++++++++++++ mysql-test/r/ctype_ujis.result | 36 ++++++++++++ mysql-test/r/ctype_utf8.result | 36 ++++++++++++ mysql-test/t/ctype_big5.test | 2 + mysql-test/t/ctype_cp932.test | 2 + mysql-test/t/ctype_gbk.test | 2 + mysql-test/t/ctype_latin1.test | 2 + mysql-test/t/ctype_sjis.test | 2 + mysql-test/t/ctype_tis620.test | 2 + mysql-test/t/ctype_uca.test | 1 + mysql-test/t/ctype_ucs.test | 2 + mysql-test/t/ctype_ujis.test | 2 + mysql-test/t/ctype_utf8.test | 2 + sql/item_cmpfunc.cc | 5 +- strings/ctype-big5.c | 15 +++-- strings/ctype-cp932.c | 11 ++-- strings/ctype-gbk.c | 15 +++-- strings/ctype-mb.c | 17 ++---- strings/ctype-simple.c | 11 +--- strings/ctype-sjis.c | 11 ++-- strings/ctype-tis620.c | 71 +----------------------- strings/ctype-ucs2.c | 6 +- 30 files changed, 418 insertions(+), 123 deletions(-) create mode 100644 mysql-test/include/ctype_like_escape.inc diff --git a/mysql-test/include/ctype_like_escape.inc b/mysql-test/include/ctype_like_escape.inc new file mode 100644 index 00000000000..ac97fbaa1a0 --- /dev/null +++ b/mysql-test/include/ctype_like_escape.inc @@ -0,0 +1,18 @@ +# +# Bugs: #13046: +# LIKE pattern matching using prefix index doesn't return correct result +# +select @@collation_connection; +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +-- should return ab_def +select c1 as c1u from t1 where c1 like 'ab\_def'; +-- should return ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +drop table t1; diff --git a/mysql-test/r/ctype_big5.result b/mysql-test/r/ctype_big5.result index 01b59b93b52..a31289775fe 100644 --- a/mysql-test/r/ctype_big5.result +++ b/mysql-test/r/ctype_big5.result @@ -89,6 +89,24 @@ select c1 from t1 where c1 like 'abcde111%' order by c1; c1 abcde111 drop table t1; +select @@collation_connection; +@@collation_connection +big5_chinese_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET collation_connection='big5_bin'; create table t1 select repeat('a',4000) a; delete from t1; @@ -121,6 +139,24 @@ select c1 from t1 where c1 like 'abcde111%' order by c1; c1 abcde111 drop table t1; +select @@collation_connection; +@@collation_connection +big5_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET NAMES big5; CREATE TABLE t1 (a text) character set big5; INSERT INTO t1 VALUES (''); diff --git a/mysql-test/r/ctype_cp932.result b/mysql-test/r/ctype_cp932.result index d8221a58b9e..8763055647c 100644 --- a/mysql-test/r/ctype_cp932.result +++ b/mysql-test/r/ctype_cp932.result @@ -8624,6 +8624,24 @@ select c1 from t1 where c1 like 'abcde111%' order by c1; c1 abcde111 drop table t1; +select @@collation_connection; +@@collation_connection +cp932_japanese_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET collation_connection='cp932_bin'; create table t1 select repeat('a',4000) a; delete from t1; @@ -8656,3 +8674,21 @@ select c1 from t1 where c1 like 'abcde111%' order by c1; c1 abcde111 drop table t1; +select @@collation_connection; +@@collation_connection +cp932_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; diff --git a/mysql-test/r/ctype_gbk.result b/mysql-test/r/ctype_gbk.result index 1a9dea28429..aaffe692126 100644 --- a/mysql-test/r/ctype_gbk.result +++ b/mysql-test/r/ctype_gbk.result @@ -89,6 +89,24 @@ select c1 from t1 where c1 like 'abcde111%' order by c1; c1 abcde111 drop table t1; +select @@collation_connection; +@@collation_connection +gbk_chinese_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET collation_connection='gbk_bin'; create table t1 select repeat('a',4000) a; delete from t1; @@ -121,6 +139,24 @@ select c1 from t1 where c1 like 'abcde111%' order by c1; c1 abcde111 drop table t1; +select @@collation_connection; +@@collation_connection +gbk_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET NAMES gbk; CREATE TABLE t1 (a text) character set gbk; INSERT INTO t1 VALUES (0xA3A0),(0xA1A1); diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result index 95fca1575ef..0fbdc8ac63c 100644 --- a/mysql-test/r/ctype_latin1.result +++ b/mysql-test/r/ctype_latin1.result @@ -315,6 +315,24 @@ latin1_swedish_ci 6109 latin1_swedish_ci 61 latin1_swedish_ci 6120 drop table t1; +select @@collation_connection; +@@collation_connection +latin1_swedish_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET collation_connection='latin1_bin'; create table t1 select repeat('a',4000) a; delete from t1; @@ -325,6 +343,24 @@ latin1_bin 6109 latin1_bin 61 latin1_bin 6120 drop table t1; +select @@collation_connection; +@@collation_connection +latin1_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; CREATE TABLE a (a int); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a (a int)' at line 1 SELECT 'a' as str; diff --git a/mysql-test/r/ctype_sjis.result b/mysql-test/r/ctype_sjis.result index e6669c63621..d1976a516d2 100644 --- a/mysql-test/r/ctype_sjis.result +++ b/mysql-test/r/ctype_sjis.result @@ -103,6 +103,24 @@ select c1 from t1 where c1 like 'abcde111%' order by c1; c1 abcde111 drop table t1; +select @@collation_connection; +@@collation_connection +sjis_japanese_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET collation_connection='sjis_bin'; create table t1 select repeat('a',4000) a; delete from t1; @@ -135,6 +153,24 @@ select c1 from t1 where c1 like 'abcde111%' order by c1; c1 abcde111 drop table t1; +select @@collation_connection; +@@collation_connection +sjis_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET NAMES sjis; SELECT HEX('@\\') FROM DUAL; HEX('@_\') diff --git a/mysql-test/r/ctype_tis620.result b/mysql-test/r/ctype_tis620.result index 6d8bfe74c4b..9d13d7cd34b 100644 --- a/mysql-test/r/ctype_tis620.result +++ b/mysql-test/r/ctype_tis620.result @@ -2947,6 +2947,24 @@ tis620_thai_ci 6109 tis620_thai_ci 61 tis620_thai_ci 6120 drop table t1; +select @@collation_connection; +@@collation_connection +tis620_thai_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET collation_connection='tis620_bin'; create table t1 select repeat('a',4000) a; delete from t1; @@ -2957,3 +2975,21 @@ tis620_bin 6109 tis620_bin 61 tis620_bin 6120 drop table t1; +select @@collation_connection; +@@collation_connection +tis620_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; diff --git a/mysql-test/r/ctype_uca.result b/mysql-test/r/ctype_uca.result index c6e803904a3..91ee427efb4 100644 --- a/mysql-test/r/ctype_uca.result +++ b/mysql-test/r/ctype_uca.result @@ -2396,3 +2396,21 @@ utf8_unicode_ci 6109 utf8_unicode_ci 61 utf8_unicode_ci 6120 drop table t1; +select @@collation_connection; +@@collation_connection +utf8_unicode_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 6d00f13737d..619ad750ff3 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -587,6 +587,24 @@ ucs2_general_ci 00610009 ucs2_general_ci 0061 ucs2_general_ci 00610020 drop table t1; +select @@collation_connection; +@@collation_connection +ucs2_general_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET NAMES latin1; SET collation_connection='ucs2_bin'; create table t1 select repeat('a',4000) a; @@ -598,6 +616,24 @@ ucs2_bin 00610009 ucs2_bin 0061 ucs2_bin 00610020 drop table t1; +select @@collation_connection; +@@collation_connection +ucs2_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; select hex(substr(_ucs2 0x00e400e50068,1)); hex(substr(_ucs2 0x00e400e50068,1)) 00E400E50068 diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result index dec1baf4a4b..c86cbe9ce53 100644 --- a/mysql-test/r/ctype_ujis.result +++ b/mysql-test/r/ctype_ujis.result @@ -2239,6 +2239,24 @@ select c1 from t1 where c1 like 'abcde111%' order by c1; c1 abcde111 drop table t1; +select @@collation_connection; +@@collation_connection +ujis_japanese_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET collation_connection='ujis_bin'; create table t1 select repeat('a',4000) a; delete from t1; @@ -2271,3 +2289,21 @@ select c1 from t1 where c1 like 'abcde111%' order by c1; c1 abcde111 drop table t1; +select @@collation_connection; +@@collation_connection +ujis_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 9f2d7eac700..aeea574ef6c 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -842,6 +842,24 @@ utf8_general_ci 6109 utf8_general_ci 61 utf8_general_ci 6120 drop table t1; +select @@collation_connection; +@@collation_connection +utf8_general_ci +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; SET collation_connection='utf8_bin'; create table t1 select repeat('a',4000) a; delete from t1; @@ -852,6 +870,24 @@ utf8_bin 6109 utf8_bin 61 utf8_bin 6120 drop table t1; +select @@collation_connection; +@@collation_connection +utf8_bin +create table t1 ROW_FORMAT=DYNAMIC select repeat('a',50) as c1 ; +insert into t1 values('abcdef'); +insert into t1 values('_bcdef'); +insert into t1 values('a_cdef'); +insert into t1 values('ab_def'); +insert into t1 values('abc_ef'); +insert into t1 values('abcd_f'); +insert into t1 values('abcde_'); +select c1 as c1u from t1 where c1 like 'ab\_def'; +c1u +ab_def +select c1 as c2h from t1 where c1 like 'ab#_def' escape '#'; +c2h +ab_def +drop table t1; CREATE TABLE t1 ( user varchar(255) NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1; diff --git a/mysql-test/t/ctype_big5.test b/mysql-test/t/ctype_big5.test index 73d9f06042c..1788dce755b 100644 --- a/mysql-test/t/ctype_big5.test +++ b/mysql-test/t/ctype_big5.test @@ -15,9 +15,11 @@ SET NAMES big5; SET collation_connection='big5_chinese_ci'; -- source include/ctype_filesort.inc -- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc SET collation_connection='big5_bin'; -- source include/ctype_filesort.inc -- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc # # Bugs#9357: TEXT columns break string with special word in BIG5 charset. diff --git a/mysql-test/t/ctype_cp932.test b/mysql-test/t/ctype_cp932.test index 8e6c53af095..d6c3c226140 100644 --- a/mysql-test/t/ctype_cp932.test +++ b/mysql-test/t/ctype_cp932.test @@ -427,8 +427,10 @@ DROP table t1; SET collation_connection='cp932_japanese_ci'; -- source include/ctype_filesort.inc -- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc SET collation_connection='cp932_bin'; -- source include/ctype_filesort.inc -- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc # End of 4.1 tests diff --git a/mysql-test/t/ctype_gbk.test b/mysql-test/t/ctype_gbk.test index 2210891454e..5eeade96186 100644 --- a/mysql-test/t/ctype_gbk.test +++ b/mysql-test/t/ctype_gbk.test @@ -15,9 +15,11 @@ SET NAMES gbk; SET collation_connection='gbk_chinese_ci'; -- source include/ctype_filesort.inc -- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc SET collation_connection='gbk_bin'; -- source include/ctype_filesort.inc -- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc # # Bug#11987 mysql will truncate the text when diff --git a/mysql-test/t/ctype_latin1.test b/mysql-test/t/ctype_latin1.test index 1b83373da29..8953aaecaf8 100644 --- a/mysql-test/t/ctype_latin1.test +++ b/mysql-test/t/ctype_latin1.test @@ -64,8 +64,10 @@ select 'a' regexp 'A' collate latin1_bin; SET collation_connection='latin1_swedish_ci'; -- source include/ctype_filesort.inc +-- source include/ctype_like_escape.inc SET collation_connection='latin1_bin'; -- source include/ctype_filesort.inc +-- source include/ctype_like_escape.inc # # Bug#8041 diff --git a/mysql-test/t/ctype_sjis.test b/mysql-test/t/ctype_sjis.test index 252f0a0b6c8..1d807b5e9a8 100644 --- a/mysql-test/t/ctype_sjis.test +++ b/mysql-test/t/ctype_sjis.test @@ -67,9 +67,11 @@ drop table t1; SET collation_connection='sjis_japanese_ci'; -- source include/ctype_filesort.inc -- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc SET collation_connection='sjis_bin'; -- source include/ctype_filesort.inc -- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc # Check parsing of string literals in SJIS with multibyte characters that # have an embedded \ in them. (Bug #8303) diff --git a/mysql-test/t/ctype_tis620.test b/mysql-test/t/ctype_tis620.test index d649828eda3..c49540de24b 100644 --- a/mysql-test/t/ctype_tis620.test +++ b/mysql-test/t/ctype_tis620.test @@ -155,7 +155,9 @@ DROP TABLE t1; SET collation_connection='tis620_thai_ci'; -- source include/ctype_filesort.inc +-- source include/ctype_like_escape.inc SET collation_connection='tis620_bin'; -- source include/ctype_filesort.inc +-- source include/ctype_like_escape.inc # End of 4.1 tests diff --git a/mysql-test/t/ctype_uca.test b/mysql-test/t/ctype_uca.test index 9d81aa74e90..2300abca69d 100644 --- a/mysql-test/t/ctype_uca.test +++ b/mysql-test/t/ctype_uca.test @@ -455,5 +455,6 @@ drop table t1; SET collation_connection='utf8_unicode_ci'; -- source include/ctype_filesort.inc +-- source include/ctype_like_escape.inc # End of 4.1 tests diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 4a5c80bed6e..2c9e71ddff5 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -370,9 +370,11 @@ drop table t1; SET collation_connection='ucs2_general_ci'; -- source include/ctype_filesort.inc +-- source include/ctype_like_escape.inc SET NAMES latin1; SET collation_connection='ucs2_bin'; -- source include/ctype_filesort.inc +-- source include/ctype_like_escape.inc # # Bug#10344 Some string functions fail for UCS2 diff --git a/mysql-test/t/ctype_ujis.test b/mysql-test/t/ctype_ujis.test index 88386500c9f..bf74371510b 100644 --- a/mysql-test/t/ctype_ujis.test +++ b/mysql-test/t/ctype_ujis.test @@ -1146,8 +1146,10 @@ DROP TABLE t1; SET collation_connection='ujis_japanese_ci'; -- source include/ctype_filesort.inc -- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc SET collation_connection='ujis_bin'; -- source include/ctype_filesort.inc -- source include/ctype_innodb_like.inc +-- source include/ctype_like_escape.inc # End of 4.1 tests diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 0cdda648899..23824a58dab 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -685,8 +685,10 @@ drop table t1; SET collation_connection='utf8_general_ci'; -- source include/ctype_filesort.inc +-- source include/ctype_like_escape.inc SET collation_connection='utf8_bin'; -- source include/ctype_filesort.inc +-- source include/ctype_like_escape.inc # # Bug #7874 CONCAT() gives wrong results mixing diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 74eed7fa41a..c4d3d6f7ab4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2443,9 +2443,9 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) String *escape_str= escape_item->val_str(&tmp_value1); if (escape_str) { - CHARSET_INFO *cs= cmp.cmp_collation.collation; - if (use_mb(cs)) + if (use_mb(cmp_collation.collation)) { + CHARSET_INFO *cs= escape_str->charset(); my_wc_t wc; int rc= cs->cset->mb_wc(cs, &wc, (const uchar*) escape_str->ptr(), @@ -2460,6 +2460,7 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) code instead of Unicode code as "escape" argument. Convert to "cs" if charset of escape differs. */ + CHARSET_INFO *cs= cmp_collation.collation; uint32 unused; if (escape_str->needs_conversion(escape_str->length(), escape_str->charset(), cs, &unused)) diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 76a4e197405..08b0ff009ee 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -392,16 +392,12 @@ static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)), uint res_length, char *min_str,char *max_str, uint *min_length,uint *max_length) { - const char *end; + const char *end= ptr + ptr_length; char *min_org=min_str; char *min_end=min_str+res_length; - uint charlen= my_charpos(cs, ptr, ptr+ptr_length, res_length/cs->mbmaxlen); + uint charlen= res_length / cs->mbmaxlen; - if (charlen < ptr_length) - ptr_length= charlen; - end= ptr + ptr_length; - - for (; ptr != end && min_str != min_end ; ptr++) + for (; ptr != end && min_str != min_end && charlen > 0; ptr++, charlen--) { if (ptr+1 != end && isbig5code(ptr[0],ptr[1])) { @@ -412,7 +408,10 @@ static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)), if (*ptr == escape && ptr+1 != end) { ptr++; /* Skip escape */ - *min_str++= *max_str++ = *ptr; + if (isbig5code(ptr[0], ptr[1])) + *min_str++= *max_str++ = *ptr++; + if (min_str < min_end) + *min_str++= *max_str++= *ptr; continue; } if (*ptr == w_one) /* '_' in SQL */ diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index e476130b706..63f95a28037 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -322,16 +322,13 @@ static my_bool my_like_range_cp932(CHARSET_INFO *cs __attribute__((unused)), uint res_length, char *min_str,char *max_str, uint *min_length,uint *max_length) { - const char *end; + const char *end= ptr + ptr_length; char *min_org=min_str; char *min_end=min_str+res_length; - uint charlen= my_charpos(cs, ptr, ptr+ptr_length, res_length/cs->mbmaxlen); + uint charlen= res_length / cs->mbmaxlen; - if (charlen < ptr_length) - ptr_length= charlen; - end= ptr + ptr_length; - - while (ptr < end && min_str < min_end) { + for ( ; ptr < end && min_str < min_end && charlen > 0 ; charlen--) + { if (ismbchar_cp932(cs, ptr, end)) { *min_str++ = *max_str++ = *ptr++; if (min_str < min_end) diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index 82c76b8ee96..b5b86984794 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -2705,16 +2705,12 @@ static my_bool my_like_range_gbk(CHARSET_INFO *cs __attribute__((unused)), uint res_length, char *min_str,char *max_str, uint *min_length,uint *max_length) { - const char *end; + const char *end= ptr + ptr_length; char *min_org=min_str; char *min_end=min_str+res_length; - uint charlen= my_charpos(cs, ptr, ptr+ptr_length, res_length/cs->mbmaxlen); + uint charlen= res_length / cs->mbmaxlen; - if (charlen < ptr_length) - ptr_length= charlen; - end= ptr + ptr_length; - - for (; ptr != end && min_str != min_end ; ptr++) + for (; ptr != end && min_str != min_end && charlen > 0; ptr++, charlen--) { if (ptr+1 != end && isgbkcode(ptr[0],ptr[1])) { @@ -2725,7 +2721,10 @@ static my_bool my_like_range_gbk(CHARSET_INFO *cs __attribute__((unused)), if (*ptr == escape && ptr+1 != end) { ptr++; /* Skip escape */ - *min_str++= *max_str++ = *ptr; + if (isgbkcode(ptr[0], ptr[1])) + *min_str++= *max_str++ = *ptr; + if (min_str < min_end) + *min_str++= *max_str++= *ptr; continue; } if (*ptr == w_one) /* '_' in SQL */ diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index 4b22f158284..eb032759d25 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -502,17 +502,13 @@ my_bool my_like_range_mb(CHARSET_INFO *cs, char *min_str,char *max_str, uint *min_length,uint *max_length) { - const char *end; + const char *end= ptr + ptr_length; char *min_org= min_str; char *min_end= min_str + res_length; char *max_end= max_str + res_length; - uint charlen= my_charpos(cs, ptr, ptr+ptr_length, res_length/cs->mbmaxlen); + uint charlen= res_length / cs->mbmaxlen; - if (charlen < ptr_length) - ptr_length= charlen; - end= ptr + ptr_length; - - for (; ptr != end && min_str != min_end ; ptr++) + for (; ptr != end && min_str != min_end && charlen > 0 ; ptr++, charlen--) { if (*ptr == escape && ptr+1 != end) { @@ -522,14 +518,8 @@ my_bool my_like_range_mb(CHARSET_INFO *cs, } if (*ptr == w_one || *ptr == w_many) /* '_' and '%' in SQL */ { - charlen= my_charpos(cs, min_org, min_str, res_length/cs->mbmaxlen); - - if (charlen < (uint) (min_str - min_org)) - min_str= min_org + charlen; - /* Write min key */ *min_length= (uint) (min_str - min_org); - *max_length= res_length; do { *min_str++= (char) cs->min_sort_char; @@ -540,6 +530,7 @@ my_bool my_like_range_mb(CHARSET_INFO *cs, representation of the max_sort_char character, and copy it into max_str in a loop. */ + *max_length= res_length; pad_max_char(cs, max_str, max_end); return 0; } diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index af673b78254..efddab621f2 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -997,17 +997,12 @@ my_bool my_like_range_simple(CHARSET_INFO *cs, char *min_str,char *max_str, uint *min_length,uint *max_length) { - const char *end; + const char *end= ptr + ptr_length; char *min_org=min_str; char *min_end=min_str+res_length; -#ifdef USE_MB - uint charlen= my_charpos(cs, ptr, ptr+ptr_length, res_length/cs->mbmaxlen); - if (charlen < ptr_length) - ptr_length= charlen; -#endif - end= ptr + ptr_length; + uint charlen= res_length / cs->mbmaxlen; - for (; ptr != end && min_str != min_end ; ptr++) + for (; ptr != end && min_str != min_end && charlen > 0 ; ptr++, charlen--) { if (*ptr == escape && ptr+1 != end) { diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 4342fc670df..da79f1796b8 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -322,16 +322,13 @@ static my_bool my_like_range_sjis(CHARSET_INFO *cs __attribute__((unused)), uint res_length, char *min_str,char *max_str, uint *min_length,uint *max_length) { - const char *end; + const char *end= ptr + ptr_length; char *min_org=min_str; char *min_end=min_str+res_length; - uint charlen= my_charpos(cs, ptr, ptr+ptr_length, res_length/cs->mbmaxlen); + uint charlen= res_length / cs->mbmaxlen; - if (charlen < ptr_length) - ptr_length= charlen; - end= ptr + ptr_length; - - while (ptr < end && min_str < min_end) { + for ( ; ptr < end && min_str < min_end && charlen > 0 ; charlen--) + { if (ismbchar_sjis(cs, ptr, end)) { *min_str++ = *max_str++ = *ptr++; if (min_str < min_end) diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index 208168bb946..dcb0e0525b4 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -641,71 +641,6 @@ int my_strnxfrm_tis620(CHARSET_INFO *cs __attribute__((unused)), } - -/* - Convert SQL LIKE string to C string - - Arg: String, its length, escape character, resource length, - minimal string and maximum string - Ret: Always 0 - - IMPLEMENTATION - We just copy this function from opt_range.cc. No need to convert to - thai2sortable string. min_str and max_str will be use for comparison and - converted there. - - RETURN VALUES - 0 -*/ - -#define max_sort_chr ((char) 255) - -static -my_bool my_like_range_tis620(CHARSET_INFO *cs __attribute__((unused)), - const char *ptr, uint ptr_length, - pbool escape, pbool w_one, pbool w_many, - uint res_length, char *min_str, char *max_str, - uint *min_length, uint *max_length) -{ - const char *end=ptr+ptr_length; - char *min_org=min_str; - char *min_end=min_str+res_length; - - for (; ptr != end && min_str != min_end ; ptr++) - { - if (*ptr == escape && ptr+1 != end) - { - ptr++; /* Skip escape */ - *min_str++ = *max_str++ = *ptr; - continue; - } - if (*ptr == w_one) /* '_' in SQL */ - { - *min_str++='\0'; /* This should be min char */ - *max_str++=max_sort_chr; - continue; - } - if (*ptr == w_many) /* '%' in SQL */ - { - *min_length= (uint) (min_str - min_org); - *max_length=res_length; - do - { - *min_str++ = 0; - *max_str++ = max_sort_chr; - } while (min_str != min_end); - return 0; - } - *min_str++= *max_str++ = *ptr; - } - *min_length= *max_length = (uint) (min_str - min_org); - - while (min_str != min_end) - *min_str++ = *max_str++ = ' '; /* Because of key compression */ - return 0; -} - - static unsigned short cs_to_uni[256]={ 0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007, 0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F, @@ -914,7 +849,7 @@ static MY_COLLATION_HANDLER my_collation_ci_handler = my_strnncoll_tis620, my_strnncollsp_tis620, my_strnxfrm_tis620, - my_like_range_tis620, + my_like_range_simple, my_wildcmp_8bit, /* wildcmp */ my_strcasecmp_8bit, my_instr_simple, /* QQ: To be fixed */ @@ -974,7 +909,7 @@ CHARSET_INFO my_charset_tis620_thai_ci= 1, /* mbminlen */ 1, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ 0, /* escape_with_backslash_is_dangerous */ &my_charset_handler, &my_collation_ci_handler @@ -1002,7 +937,7 @@ CHARSET_INFO my_charset_tis620_bin= 1, /* mbminlen */ 1, /* mbmaxlen */ 0, /* min_sort_char */ - 0, /* max_sort_char */ + 255, /* max_sort_char */ 0, /* escape_with_backslash_is_dangerous */ &my_charset_handler, &my_collation_8bit_bin_handler diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 2761e781724..56c05635300 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1426,10 +1426,12 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs, const char *end=ptr+ptr_length; char *min_org=min_str; char *min_end=min_str+res_length; + uint charlen= res_length / cs->mbmaxlen; - for (; ptr + 1 < end && min_str + 1 < min_end ; ptr+=2) + for ( ; ptr + 1 < end && min_str + 1 < min_end && charlen > 0 + ; ptr+=2, charlen--) { - if (ptr[0] == '\0' && ptr[1] == escape && ptr+2 < end) + if (ptr[0] == '\0' && ptr[1] == escape && ptr + 1 < end) { ptr+=2; /* Skip escape */ *min_str++= *max_str++ = ptr[0];