List:Internals« Previous MessageNext Message »
From:Lu Jingdong Date:December 3 2007 10:41am
Subject:Patch for bug #32705
View as plain text  
This patch for bug #32705 myisam corruption: Key in wrong position at 
page 1024 with ucs2_bin

diff -Nur storage/myisam/mi_open.c.orig storage/myisam/mi_open.c
--- storage/myisam/mi_open.c.orig       2007-12-03 17:20:32.000000000 +0800
+++ storage/myisam/mi_open.c    2007-12-03 17:31:23.000000000 +0800
@@ -813,7 +813,7 @@
     if (keyinfo->seg[0].flag & HA_PACK_KEY)
     {                                          /* Prefix compression */
       if (!keyinfo->seg->charset || use_strnxfrm(keyinfo->seg->charset) ||
-          (keyinfo->seg->flag & HA_NULL_PART))
+          (keyinfo->seg->flag & HA_NULL_PART) || 
my_binary_compare(keyinfo->seg->charset))
         keyinfo->bin_search=_mi_seq_search;
       else
         keyinfo->bin_search=_mi_prefix_search;

The diffrent methods used between creating keys and checking keys is the 
reason to cause this error.
... ...
(1)  mysql> insert into t values ('marshall\'s'); 
   ... ...
    |-- _mi_ck_real_write_btree
        |-- w_search
            |-- _mi_prefix_search  ( *keyinfo->bin_search)
... ...
(2) mysql> check table t extend;
   ... ...
    |-- chk_index
        |-- ha_key_cmp
            |-- mi_compare_text
                |-- my_strnncollsp_ucs2_bin

In ucs2, every character is represented by a two-byte Unicode code. The 
function "_mi_prefix_search" is not suitable for this kind of character set.
If we use charaset "ucs2" and collation "ucs2_bin" for a key, we should 
use this comparing function "my_strnncollsp_ucs2_bin" to order the 
key's  position during the period of inserting records to table. When 
executing the "check table t extended" statement, the key will be 
checked by using this function too.
So I think we should add a condition like 
"my_binary_compare(keyinfo->seg->charset)" or  
"(keyinfo->seg->charset->number == 90)". Because the function pointer 
"keyinfo->bin_search" should point to "_mi_seq_search" when setting up 
key functions.
The flow of function "_mi_seq_search" as following:
_mi_seq_search
|--  ha_key_cmp
     |-- mi_compare_text
         |-- my_strnncollsp_ucs2_bin

Test and result:
mysql> create table t1 (c1 char(255) character set ucs2 collate ucs2_bin 
not null,key(c1))
    -> engine=myisam;
Query OK, 0 rows affected (0.17 sec)

mysql> insert into t1 values ('marshall\'s');
Query OK, 1 row affected (0.13 sec)

mysql> insert into t1 values ('marsh');
Query OK, 1 row affected (0.07 sec)

mysql> check table t1 extended;
+---------+-------+----------+----------+
| Table   | Op    | Msg_type | Msg_text |
+---------+-------+----------+----------+
| test.t1 | check | status   | OK       |
+---------+-------+----------+----------+
1 row in set (0.00 sec)

mysql> select * from t1 order by c1;
+------------+
| c1         |
+------------+
| marsh      |
| marshall's |
+------------+
2 rows in set (0.10 sec)

mysql> select * from t1 order by c1 desc;
+------------+
| c1         |
+------------+
| marshall's |
| marsh      |
+------------+
2 rows in set (0.00 sec)
Thread
Patch for bug #32705Lu Jingdong3 Dec