Commit c15cf8b5 authored by unknown's avatar unknown

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.


myisam/mi_search.c:
  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.
myisam/mi_write.c:
  Bug#9188 - Corruption Can't open file: 'table.MYI' (errno: 145)
  Fixed a function comment.
mysql-test/r/myisam.result:
  Bug#9188 - Corruption Can't open file: 'table.MYI' (errno: 145)
  The test result.
mysql-test/t/myisam.test:
  Bug#9188 - Corruption Can't open file: 'table.MYI' (errno: 145)
  The test case.
parent 4fc8cb58
...@@ -210,9 +210,31 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, ...@@ -210,9 +210,31 @@ int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
} /* _mi_bin_search */ } /* _mi_bin_search */
/* Used instead of _mi_bin_search() when key is packed */ /*
/* Puts smaller or identical key in buff */ Locate a packed key in a key page.
/* Key is searched sequentially */
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, int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
...@@ -718,7 +740,19 @@ uint _mi_get_static_key(register MI_KEYDEF *keyinfo, uint nod_flag, ...@@ -718,7 +740,19 @@ uint _mi_get_static_key(register MI_KEYDEF *keyinfo, uint nod_flag,
} /* _mi_get_static_key */ } /* _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, uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
register uchar **page_pos, register uchar *key) register uchar **page_pos, register uchar *key)
...@@ -1339,12 +1373,12 @@ _mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint nod_flag, ...@@ -1339,12 +1373,12 @@ _mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
Keys are compressed the following way: 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 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 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 next-key-seg Next key segments
If the first segment can have NULL: If the first segment can have NULL:
...@@ -1537,7 +1571,8 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, ...@@ -1537,7 +1571,8 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
s_temp->part_of_prev_key= new_ref_length; s_temp->part_of_prev_key= new_ref_length;
s_temp->prev_length= org_key_length - s_temp->prev_length= org_key_length -
(new_ref_length-pack_marker); (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); n_length= get_pack_length(s_temp->prev_length);
s_temp->prev_key+= (new_ref_length - pack_marker); s_temp->prev_key+= (new_ref_length - pack_marker);
length+= s_temp->prev_length + n_length; length+= s_temp->prev_length + n_length;
......
...@@ -414,8 +414,30 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -414,8 +414,30 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
} /* w_search */ } /* 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, int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
uchar *key, uchar *anc_buff, uchar *key_pos, uchar *key_buff, uchar *key, uchar *anc_buff, uchar *key_pos, uchar *key_buff,
......
...@@ -573,3 +573,11 @@ truncate table t1; ...@@ -573,3 +573,11 @@ truncate table t1;
ERROR HY000: MyISAM table 't1' is in use (most likely by a MERGE table). Try FLUSH TABLES. ERROR HY000: MyISAM table 't1' is in use (most likely by a MERGE table). Try FLUSH TABLES.
insert into t1 values (1); insert into t1 values (1);
drop table t1,t2; 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;
...@@ -550,3 +550,13 @@ truncate table t1; ...@@ -550,3 +550,13 @@ truncate table t1;
insert into t1 values (1); insert into t1 values (1);
drop table t1,t2; 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;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment