#At file:///home/svoj/devel/bzr-mysql/mysql-6.0-falcon-team-bug29246/
2922 Sergey Vojtovich 2008-12-04
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-04 11:00:12 +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-04 11:00:12 +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-04 11:00:12 +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-04 11:00:12 +0000
@@ -455,30 +455,25 @@ 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 prefix keys.
+ char padChar = falcon_get_pad_char(cs);
+ char minSortChar = falcon_get_min_sort_char(cs);
+ 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#29246 | Sergey Vojtovich | 4 Dec |