MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:igor Date:June 21 2006 2:57am
Subject:bk commit into 4.1 tree (igor:1.2510) BUG#16674
View as plain text  
Below is the list of changes that have just been committed into a local
4.1 repository of igor. When igor does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2510 06/06/20 19:57:21 igor@stripped +3 -0
  Fixed bug #16674.
  The length of the prefix of the pattern string in the LIKE predicate that 
  determined the index range to be scanned was calculated incorrectly for
  multi-byte character sets. 
  As a result of this in 4. 1 the the scanned range was wider then necessary
  if the prefix contained not only one-byte characters.  
  In 5.0 additionally it caused missing some rows from the result set.

  strings/ctype-mb.c
    1.42 06/06/20 19:57:17 igor@stripped +16 -9
    Fixed bug #16674.
    The length of the prefix of the pattern string in the LIKE predicate that 
    determined the index range to be scanned was calculated incorrectly for
    multi-byte character sets. 
    As a result of this in 4. 1 the the scanned range was wider then necessary
    if the prefix contained not only one-byte characters.  
    In 5.0 additionally it caused missing some rows from the result set.
        
    The function my_like_range_mb was fixed to calculate the length of
    the prefix in a pattern string correctly in all cases.

  mysql-test/t/ctype_utf8.test
    1.72 06/06/20 19:57:17 igor@stripped +55 -0
    Added test cases for bug #16674.

  mysql-test/r/ctype_utf8.result
    1.70 06/06/20 19:57:17 igor@stripped +67 -0
    Added test cases for bug #16674.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	igor
# Host:	rurik.mysql.com
# Root:	/home/igor/mysql-4.1-opt

--- 1.69/mysql-test/r/ctype_utf8.result	2006-03-29 14:50:50 -08:00
+++ 1.70/mysql-test/r/ctype_utf8.result	2006-06-20 19:57:17 -07:00
@@ -1124,3 +1124,70 @@
 Table	Op	Msg_type	Msg_text
 test.t1	check	status	OK
 drop table t1;
+SET NAMES utf8;
+CREATE TABLE t1 (
+a CHAR(13) DEFAULT '',
+INDEX(a)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES 
+('Käli Käli 2-4'), ('Käli Käli 2-4'),
+('Käli Käli 2+4'), ('Käli Käli 2+4'),
+('Käli Käli 2-6'), ('Käli Käli 2-6');
+CREATE TABLE t2 (
+a CHAR(13) DEFAULT '',
+INDEX(a)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
+INSERT INTO t2 VALUES
+('Kali Kali 2-4'), ('Kali Kali 2-4'),
+('Kali Kali 2+4'), ('Kali Kali 2+4'),
+('Kali Kali 2-6'), ('Kali Kali 2-6');
+SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
+a
+Käli Käli 2+4
+Käli Käli 2+4
+SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
+a
+Kali Kali 2+4
+Kali Kali 2+4
+EXPLAIN SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	40	NULL	2	Using where; Using index
+EXPLAIN SELECT a FROM t1 WHERE a = 'Käli Käli 2+4';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ref	a	a	40	const	2	Using where; Using index
+EXPLAIN SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	range	a	a	14	NULL	2	Using where; Using index
+EXPLAIN SELECT a FROM t2 WHERE a = 'Kali Kali 2+4';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ref	a	a	14	const	2	Using where; Using index
+DROP TABLE t1,t2;
+CREATE TABLE t1 (
+a char(255) DEFAULT '', 
+KEY(a(10))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+a
+Käli Käli 2-4
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+a
+Käli Käli 2-4
+Käli Käli 2-4
+DROP TABLE t1;
+CREATE TABLE t1 (
+a char(255) DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+a
+Käli Käli 2-4
+Käli Käli 2-4
+ALTER TABLE t1 ADD KEY (a(10));
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+a
+Käli Käli 2-4
+Käli Käli 2-4
+DROP TABLE t1;

--- 1.71/mysql-test/t/ctype_utf8.test	2006-03-29 14:50:50 -08:00
+++ 1.72/mysql-test/t/ctype_utf8.test	2006-06-20 19:57:17 -07:00
@@ -926,4 +926,59 @@
 check table t1;
 drop table t1;
 
+#
+# Bug#16674: LIKE predicate for a utf8 character set column
+#
+
+SET NAMES utf8;
+
+CREATE TABLE t1 (
+  a CHAR(13) DEFAULT '',
+  INDEX(a)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES 
+ ('Käli Käli 2-4'), ('Käli Käli 2-4'),
+ ('Käli Käli 2+4'), ('Käli Käli 2+4'),
+ ('Käli Käli 2-6'), ('Käli Käli 2-6');
+
+CREATE TABLE t2 (
+  a CHAR(13) DEFAULT '',
+  INDEX(a)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
+
+INSERT INTO t2 VALUES
+ ('Kali Kali 2-4'), ('Kali Kali 2-4'),
+ ('Kali Kali 2+4'), ('Kali Kali 2+4'),
+ ('Kali Kali 2-6'), ('Kali Kali 2-6');
+
+SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
+SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
+
+EXPLAIN SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4';
+EXPLAIN SELECT a FROM t1 WHERE a = 'Käli Käli 2+4';
+EXPLAIN SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4';
+EXPLAIN SELECT a FROM t2 WHERE a = 'Kali Kali 2+4';
+
+DROP TABLE t1,t2;
+
+CREATE TABLE t1 (
+  a char(255) DEFAULT '', 
+  KEY(a(10))
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+  a char(255) DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+INSERT INTO t1 VALUES ('Käli Käli 2-4');
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+ALTER TABLE t1 ADD KEY (a(10));
+SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%';
+DROP TABLE t1;
+
 # End of 4.1 tests

--- 1.41/strings/ctype-mb.c	2005-09-21 10:12:14 -07:00
+++ 1.42/strings/ctype-mb.c	2006-06-20 19:57:17 -07:00
@@ -502,21 +502,19 @@
 			 char *min_str,char *max_str,
 			 uint *min_length,uint *max_length)
 {
+  uint mblen;
   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= res_length / cs->mbmaxlen;
+  uint maxcharlen= res_length / cs->mbmaxlen;
 
-  for (; ptr != end && min_str != min_end && charlen > 0 ; ptr++, charlen--)
+  for (; ptr != end && min_str != min_end && maxcharlen ; maxcharlen--)
   {
+    /* We assume here that escape, w_any, w_namy are one-byte characters */
     if (*ptr == escape && ptr+1 != end)
-    {
-      ptr++;					/* Skip escape */
-      *min_str++= *max_str++ = *ptr;
-      continue;
-    }
-    if (*ptr == w_one || *ptr == w_many)	/* '_' and '%' in SQL */
+      ptr++;                                    /* Skip escape */
+    else if (*ptr == w_one || *ptr == w_many)   /* '_' and '%' in SQL */
     {
       /* Write min key  */
       *min_length= (uint) (min_str - min_org);
@@ -534,7 +532,16 @@
       pad_max_char(cs, max_str, max_end);
       return 0;
     }
-    *min_str++= *max_str++ = *ptr;
+    if ((mblen= my_ismbchar(cs, ptr, end)) > 1)
+    {
+      if (ptr+mblen > end || min_str+mblen > min_end)
+        break;
+      while (mblen--)
+       *min_str++= *max_str++= *ptr++;
+    }
+    else
+       *min_str++= *max_str++= *ptr++;    
+
   }
   *min_length= *max_length = (uint) (min_str - min_org);
 
Thread
bk commit into 4.1 tree (igor:1.2510) BUG#16674igor21 Jun