List:Commits« Previous MessageNext Message »
From:Sergey Vojtovich Date:December 1 2008 3:20pm
Subject:bzr commit into mysql-6.0-falcon-team branch (svoj:2922) Bug#29246
View as plain text  
#At file:///home/svoj/devel/bzr-mysql/mysql-6.0-falcon-team-bug29246/

 2922 Sergey Vojtovich	2008-12-01
      BUG#29246 - Falcon: searches fail if prefix index on
                  latin1_german2_ci column
      
      Searching falcon table with prefix index on collations that
      have characters with multiple weights may return no result
      when multi-weight characters/sequences are truncated by
      prefix bounds.
      
      E.g. searching for german 'ue' in an index that has entry for
      u-umlaut (or vice versa) will return no result.
      
      Fixed that falcon creates incorrect keys and uses wrong function
      for prefix search.
added:
  mysql-test/suite/falcon/r/falcon_bug_29246.result
  mysql-test/suite/falcon/t/falcon_bug_29246.test
modified:
  storage/falcon/MySQLCollation.cpp
  storage/falcon/StorageTable.cpp

per-file messages:
  mysql-test/suite/falcon/r/falcon_bug_29246.result
    A test case for BUG#29246.
  mysql-test/suite/falcon/t/falcon_bug_29246.test
    A test case for BUG#29246.
  storage/falcon/MySQLCollation.cpp
    Fixed that MySQLCollation::makeKey() creates incorrect prefix
    key, when it gets string with multiple-weight characters
    (like german u-umlaut).
    
    falcon_strnxfrmlen() was used in a mistake here, so it was
    removed.
    
    Rearranged falcon_strnxfrm() arguments:
    - third argument informs it about total buffer size;
    - fourth argument is the maximum number of weights we want
      to store in the buffer. In case of partial keys it is
      calculated as partialKey / mbmaxlen.
    
    For example if field value was 'u-umlaut' and partialKey was 1,
    then we get dstLen = 2. At the moment it is correct, as u-umlaut
    has 2 weights. We call strnxfrm() with buffer size set to 2 and
    number of weights set to MAX_PHYSICAL_KEY_LENGTH. As a result
    we get 2 bytes key 'UE'. Whereas we expect only one weight 'U'.
  storage/falcon/StorageTable.cpp
    strnncollsp() cannot handle prefix keys, as it will not return
    match when we get only first weight of multi-weight character.
    
    Fixed that wrong function (strnncollsp instead of strnncoll)
    was used for non-binary prefix keys comparison.
=== added file 'mysql-test/suite/falcon/r/falcon_bug_29246.result'
--- a/mysql-test/suite/falcon/r/falcon_bug_29246.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/falcon/r/falcon_bug_29246.result	2008-12-01 15:19:58 +0000
@@ -0,0 +1,15 @@
+*** Bug #29246 ***
+SET @@storage_engine = 'Falcon';
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (s1 VARCHAR(2) CHARACTER SET latin1 COLLATE latin1_german2_ci, KEY (s1(1))) ENGINE=falcon;
+INSERT INTO t1 VALUES(0xdc),('ue');
+SELECT COUNT(*) FROM t1 WHERE s1 = 0xdc;
+COUNT(*)
+2
+SELECT COUNT(*) FROM t1 WHERE s1 = 'ue';
+COUNT(*)
+2
+SELECT count(*) FROM t1;
+count(*)
+2
+DROP TABLE t1;

=== added file 'mysql-test/suite/falcon/t/falcon_bug_29246.test'
--- a/mysql-test/suite/falcon/t/falcon_bug_29246.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/falcon/t/falcon_bug_29246.test	2008-12-01 15:19:58 +0000
@@ -0,0 +1,35 @@
+--source include/have_falcon.inc
+
+#
+# Bug #29246: Falcon: searches fail if prefix index on latin1_german2_ci
+#             column
+#
+--echo *** Bug #29246 ***
+
+# ----------------------------------------------------- #
+# --- Initialisation                                --- #
+# ----------------------------------------------------- #
+let $engine = 'Falcon';
+eval SET @@storage_engine = $engine;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+# ----------------------------------------------------- #
+# --- Test                                          --- #
+# ----------------------------------------------------- #
+CREATE TABLE t1 (s1 VARCHAR(2) CHARACTER SET latin1 COLLATE latin1_german2_ci, KEY (s1(1))) ENGINE=falcon;
+INSERT INTO t1 VALUES(0xdc),('ue');
+SELECT COUNT(*) FROM t1 WHERE s1 = 0xdc;
+SELECT COUNT(*) FROM t1 WHERE s1 = 'ue';
+
+# ----------------------------------------------------- #
+# --- Check                                         --- #
+# ----------------------------------------------------- #
+SELECT count(*) FROM t1;
+
+# ----------------------------------------------------- #
+# --- Final cleanup                                 --- #
+# ----------------------------------------------------- #
+DROP TABLE t1;

=== modified file 'storage/falcon/MySQLCollation.cpp'
--- a/storage/falcon/MySQLCollation.cpp	2007-11-27 20:07:30 +0000
+++ b/storage/falcon/MySQLCollation.cpp	2008-12-01 15:19:58 +0000
@@ -69,10 +69,7 @@ int MySQLCollation::makeKey (Value *valu
 	if (!isBinary)
 		srcLen = computeKeyLength(srcLen, temp, padChar, minSortChar);
 
-	// Since some collations make dstLen > srcLen, be sure dstLen is < partialKey.
-
-	int dstLen = falcon_strnxfrmlen(charset, temp, srcLen, partialKey, MAX_PHYSICAL_KEY_LENGTH);
-	int len = falcon_strnxfrm(charset, (char*) key->key, dstLen, maxKeyLength, temp, srcLen);
+	int len = falcon_strnxfrm(charset, (char*) key->key, MAX_PHYSICAL_KEY_LENGTH, partialKey ? partialKey / falcon_get_mbmaxlen(charset) : maxKeyLength, temp, srcLen);
 	key->keyLength = len;
 	
 	return len;

=== modified file 'storage/falcon/StorageTable.cpp'
--- a/storage/falcon/StorageTable.cpp	2008-10-22 20:44:09 +0000
+++ b/storage/falcon/StorageTable.cpp	2008-12-01 15:19:58 +0000
@@ -455,30 +455,26 @@ int StorageTable::compareKey(const unsig
 							fldLen = MIN(fldLen, partialLength);
 							keyLen = MIN(keyLen, partialLength);
 							}
+						cmp = falcon_strnncollsp(cs, fldString, fldLen, 
+						                       keyString, keyLen, true);
 						}
 					else
 						{
-/* This is not necessary when comparing with the record using strnncollsp()
-						char padChar = falcon_get_pad_char(cs);
-						char minSortChar = falcon_get_min_sort_char(cs);
-						fldLen = MySQLCollation::computeKeyLength(fldLen, fldString, padChar, minSortChar);
-						keyLen = MySQLCollation::computeKeyLength(keyLen, keyString, padChar, minSortChar);
-*/
-						// Trim it down to the number of bytes that represent
-						// the number of characters indicated by partialLength.
 
 						if (partialLength)
 							{
-							fldLen = falcon_strntrunc(cs, partialLength, fldString, fldLen);
-							keyLen = falcon_strntrunc(cs, partialLength, keyString, keyLen);
+							// We must use falcon_strnncoll() for partial key comparision,
+							// as falcon_strnncollsp() cannot handle expansion/contraction.
+							char padChar = falcon_get_pad_char(cs);
+							char minSortChar = falcon_get_min_sort_char(cs);
+							fldLen = MySQLCollation::computeKeyLength(fldLen, fldString, padChar, minSortChar);
+							keyLen = MySQLCollation::computeKeyLength(keyLen, keyString, padChar, minSortChar);
+							cmp = falcon_strnncoll(cs, fldString, fldLen, keyString, keyLen, true);
 							}
+						else
+							cmp = falcon_strnncollsp(cs, fldString, fldLen, 
+							                       keyString, keyLen, true);
 						}
-
-					cmp = falcon_strnncollsp(cs, fldString, fldLen, 
-					                       keyString, keyLen, true);
-
-					//if ((cmp == 0) && (keyLen < fldLen))
-					//	cmp = 1;  // The field begins with the string searched for; fldString > keyString. #23962
 					}
 				else
 					{

Thread
bzr commit into mysql-6.0-falcon-team branch (svoj:2922) Bug#29246Sergey Vojtovich1 Dec