From: Date: April 8 2005 2:13pm Subject: bk commit into 4.1 tree (ingo:1.2160) BUG#9188 List-Archive: http://lists.mysql.com/internals/23802 X-Bug: 9188 Message-Id: Below is the list of changes that have just been committed into a local 4.1 repository of mydev. When mydev 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.2160 05/04/08 14:13:02 ingo@stripped +4 -0 Bug#9188 - Corruption Can't open file: 'table.MYI' (errno: 145) Since 4.1 keys are compared with trailing spaces. Thus, a "x " key can be inserted between a couple of "x" keys. The existing code did not take this into account. Though the comments in the code claimed it did. mysql-test/t/myisam.test 1.36 05/04/08 14:12:19 ingo@stripped +10 -0 Bug#9188 - Corruption Can't open file: 'table.MYI' (errno: 145) The test case. mysql-test/r/myisam.result 1.48 05/04/08 14:12:19 ingo@stripped +8 -0 Bug#9188 - Corruption Can't open file: 'table.MYI' (errno: 145) The test result. myisam/mi_write.c 1.48 05/04/08 14:12:19 ingo@stripped +24 -2 Bug#9188 - Corruption Can't open file: 'table.MYI' (errno: 145) Fixed a function comment. myisam/mi_search.c 1.50 05/04/08 14:12:19 ingo@stripped +43 -8 Bug#9188 - Corruption Can't open file: 'table.MYI' (errno: 145) Fixed some function comments. In the case when we insert a different key between two identical keys, the difference must be additional spaces. In this case the prefix is the same as that of the new key instead of the (zero) remaining length. # 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: ingo # Host: chilla.local # Root: /home/mydev/mysql-4.1-bug9188 --- 1.49/myisam/mi_search.c Mon Aug 30 16:12:47 2004 +++ 1.50/myisam/mi_search.c Fri Apr 8 14:12:19 2005 @@ -210,9 +210,31 @@ } /* _mi_bin_search */ - /* Used instead of _mi_bin_search() when key is packed */ - /* Puts smaller or identical key in buff */ - /* Key is searched sequentially */ +/* + Locate a packed key in a key page. + + SYNOPSIS + _mi_seq_search() + info Open table information. + keyinfo Key definition information. + page Key page (beginning). + key Search key. + key_len Length to use from search key or USE_WHOLE_KEY + comp_flag Search flags like SEARCH_SAME etc. + ret_pos RETURN Position in key page behind this key. + buff RETURN Copy of previous or identical unpacked key. + last_key RETURN If key is last in page. + + DESCRIPTION + Used instead of _mi_bin_search() when key is packed. + Puts smaller or identical key in buff. + Key is searched sequentially. + + RETURN + > 0 Key in 'buff' is smaller than search key. + 0 Key in 'buff' is identical to search key. + < 0 Not found. +*/ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, @@ -718,7 +740,19 @@ } /* _mi_get_static_key */ -/* Key with is packed against previous key or key with a NULL column */ +/* + get key witch is packed against previous key or key with a NULL column. + + SYNOPSIS + _mi_get_pack_key() + keyinfo key definition information. + nod_flag If nod: Length of node pointer, else zero. + page_pos RETURN position in key page behind this key. + key IN/OUT in: prev key, out: unpacked key. + + RETURN + key_length + length of data pointer +*/ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, register uchar **page_pos, register uchar *key) @@ -1339,12 +1373,12 @@ Keys are compressed the following way: - If the max length of first key segment <= 127 characters the prefix is + If the max length of first key segment <= 127 bytes the prefix is 1 byte else it's 2 byte - prefix byte The high bit is set if this is a prefix for the prev key + prefix byte(s) The high bit is set if this is a prefix for the prev key length Packed length if the previous was a prefix byte - [length] Length character of data + [length] data bytes ('length' bytes) next-key-seg Next key segments If the first segment can have NULL: @@ -1537,7 +1571,8 @@ s_temp->part_of_prev_key= new_ref_length; s_temp->prev_length= org_key_length - (new_ref_length-pack_marker); - s_temp->n_ref_length= s_temp->n_length= s_temp->prev_length; + s_temp->n_ref_length= s_temp->part_of_prev_key; + s_temp->n_length= s_temp->prev_length; n_length= get_pack_length(s_temp->prev_length); s_temp->prev_key+= (new_ref_length - pack_marker); length+= s_temp->prev_length + n_length; --- 1.47/myisam/mi_write.c Fri Dec 10 13:05:59 2004 +++ 1.48/myisam/mi_write.c Fri Apr 8 14:12:19 2005 @@ -414,8 +414,30 @@ } /* w_search */ - /* Insert new key at right of key_pos */ - /* Returns 2 if key contains key to upper level */ +/* + Insert new key. + + SYNOPSIS + _mi_insert() + info Open table information. + keyinfo Key definition information. + key New key. + anc_buff Key page (beginning). + key_pos Position in key page where to insert. + key_buff Copy of previous key. + father_buff parent key page for balancing. + father_key_pos position in parent key page for balancing. + father_page position of parent key page in file. + insert_last If to append at end of page. + + DESCRIPTION + Insert new key at right of key_pos. + + RETURN + 2 if key contains key to upper level. + 0 OK. + < 0 Error. +*/ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key, uchar *anc_buff, uchar *key_pos, uchar *key_buff, --- 1.47/mysql-test/r/myisam.result Wed Mar 2 10:34:56 2005 +++ 1.48/mysql-test/r/myisam.result Fri Apr 8 14:12:19 2005 @@ -573,3 +573,11 @@ ERROR HY000: MyISAM table 't1' is in use (most likely by a MERGE table). Try FLUSH TABLES. insert into t1 values (1); drop table t1,t2; +create table t1 (c1 int, c2 varchar(4) not null default '', +key(c2(3))) default charset=utf8; +insert into t1 values (1,'A'), (2, 'B'), (3, 'A'); +update t1 set c2='A B' where c1=2; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; --- 1.35/mysql-test/t/myisam.test Wed Mar 2 10:34:56 2005 +++ 1.36/mysql-test/t/myisam.test Fri Apr 8 14:12:19 2005 @@ -550,3 +550,13 @@ insert into t1 values (1); drop table t1,t2; +# +# bug9188 - Corruption Can't open file: 'table.MYI' (errno: 145) +# +create table t1 (c1 int, c2 varchar(4) not null default '', + key(c2(3))) default charset=utf8; +insert into t1 values (1,'A'), (2, 'B'), (3, 'A'); +update t1 set c2='A B' where c1=2; +check table t1; +drop table t1; +