diff --git a/heap/hp_write.c b/heap/hp_write.c index 86e79c9d7ec..19215fcf017 100644 --- a/heap/hp_write.c +++ b/heap/hp_write.c @@ -105,7 +105,6 @@ int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record, heap_rb_param custom_arg; uint old_allocated; - info->last_pos= NULL; /* For heap_rnext/heap_rprev */ custom_arg.keyseg= keyinfo->seg; custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos); if (keyinfo->flag & HA_NOSAME) diff --git a/myisam/mi_range.c b/myisam/mi_range.c index 6655f5a7de6..2f6d9600fac 100644 --- a/myisam/mi_range.c +++ b/myisam/mi_range.c @@ -144,8 +144,42 @@ static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len, if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))) key_len=USE_WHOLE_KEY; + /* + my_handler.c:mi_compare_text() has a flag 'skip_end_space'. + This is set in my_handler.c:ha_key_cmp() in dependence on the + compare flags 'nextflag' and the column type. + + TEXT columns are of type HA_KEYTYPE_VARTEXT. In this case the + condition is skip_end_space= ((nextflag & (SEARCH_FIND | + SEARCH_UPDATE)) == SEARCH_FIND). + + SEARCH_FIND is used for an exact key search. The combination + SEARCH_FIND | SEARCH_UPDATE is used in write/update/delete + operations with a comment like "Not real duplicates", whatever this + means. From the condition above we can see that 'skip_end_space' is + always false for these operations. The result is that trailing space + counts in key comparison and hence, emtpy strings ('', string length + zero, but not NULL) compare less that strings starting with control + characters and these in turn compare less than strings starting with + blanks. + + When estimating the number of records in a key range, we request an + exact search for the minimum key. This translates into a plain + SEARCH_FIND flag. Using this alone would lead to a 'skip_end_space' + compare. Empty strings would be expected above control characters. + Their keys would not be found because they are located below control + characters. + + This is the reason that we add the SEARCH_UPDATE flag here. It makes + the key estimation compare in the same way like key write operations + do. Olny so we will find the keys where they have been inserted. + + Adding the flag unconditionally does not hurt as it is used in the + above mentioned condition only. So it can safely be used together + with other flags. + */ pos=_mi_search_pos(info,keyinfo,key_buff,key_len, - nextflag | SEARCH_SAVE_BUFF, + nextflag | SEARCH_SAVE_BUFF | SEARCH_UPDATE, info->s->state.key_root[inx]); if (pos >= 0.0) { diff --git a/myisam/mi_search.c b/myisam/mi_search.c index 75e0e500109..7016a3a6876 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -924,11 +924,16 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, /* Keys are compressed the following way: - prefix length Packed length of prefix for the prev key. (1 or 3 bytes) + prefix length Packed length of prefix common with prev key (1 or 3 bytes) for each key segment: [is null] Null indicator if can be null (1 byte, zero means null) [length] Packed length if varlength (1 or 3 bytes) + key segment 'length' bytes of key segment value pointer Reference to the data file (last_keyseg->length). + + get_key_length() is a macro. It gets the prefix length from 'page' + and puts it into 'length'. It increments 'page' by 1 or 3, depending + on the packed length of the prefix length. */ get_key_length(length,page); if (length) @@ -942,34 +947,44 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, my_errno=HA_ERR_CRASHED; DBUG_RETURN(0); /* Wrong key */ } - from=key; from_end=key+length; + /* Key is packed against prev key, take prefix from prev key. */ + from= key; + from_end= key + length; } else { - from=page; from_end=page_end; /* Not packed key */ + /* Key is not packed against prev key, take all from page buffer. */ + from= page; + from_end= page_end; } /* - The trouble is that key is split in two parts: - The first part is in from ...from_end-1. - The second part starts at page + The trouble is that key can be split in two parts: + The first part (prefix) is in from .. from_end - 1. + The second part starts at page. + The split can be at every byte position. So we need to check for + the end of the first part before using every byte. */ for (keyseg=keyinfo->seg ; keyseg->type ;keyseg++) { if (keyseg->flag & HA_NULL_PART) { + /* If prefix is used up, switch to rest. */ if (from == from_end) { from=page; from_end=page_end; } if (!(*key++ = *from++)) continue; /* Null part */ } if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK)) { - /* Get length of dynamic length key part */ + /* If prefix is used up, switch to rest. */ if (from == from_end) { from=page; from_end=page_end; } + /* Get length of dynamic length key part */ if ((length= (*key++ = *from++)) == 255) { + /* If prefix is used up, switch to rest. */ if (from == from_end) { from=page; from_end=page_end; } length= (uint) ((*key++ = *from++)) << 8; + /* If prefix is used up, switch to rest. */ if (from == from_end) { from=page; from_end=page_end; } length+= (uint) ((*key++ = *from++)); } @@ -989,14 +1004,26 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, key+=length; from+=length; } + /* + Last segment (type == 0) contains length of data pointer. + If we have mixed key blocks with data pointer and key block pointer, + we have to copy both. + */ length=keyseg->length+nod_flag; if ((tmp=(uint) (from_end-from)) <= length) { + /* Remaining length is less or equal max possible length. */ memcpy(key+tmp,page,length-tmp); /* Get last part of key */ *page_pos= page+length-tmp; } else { + /* + Remaining length is greater than max possible length. + This can happen only if we switched to the new key bytes already. + 'page_end' is calculated with MI_MAX_KEY_BUFF. So it can be far + behind the real end of the key. + */ if (from_end != page_end) { DBUG_PRINT("error",("Error when unpacking key")); @@ -1004,6 +1031,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, my_errno=HA_ERR_CRASHED; DBUG_RETURN(0); /* Error */ } + /* Copy data pointer and, if appropriate, key block pointer. */ memcpy((byte*) key,(byte*) from,(size_t) length); *page_pos= from+length; } diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result index 5b9c7f2244f..91f51a95936 100644 --- a/mysql-test/r/heap_btree.result +++ b/mysql-test/r/heap_btree.result @@ -280,6 +280,33 @@ a 1 1 drop table t1; +CREATE TABLE t1 ( +c1 CHAR(3), +c2 INTEGER, +KEY USING BTREE(c1), +KEY USING BTREE(c2) +) ENGINE= MEMORY; +INSERT INTO t1 VALUES ('ABC',0), ('A',0), ('B',0), ('C',0); +UPDATE t1 SET c2= c2 + 1 WHERE c1 = 'A'; +SELECT * FROM t1; +c1 c2 +ABC 0 +A 1 +B 0 +C 0 +DROP TABLE t1; +CREATE TABLE t1 ( +c1 ENUM('1', '2'), +UNIQUE USING BTREE(c1) +) ENGINE= MEMORY DEFAULT CHARSET= utf8; +INSERT INTO t1 VALUES('1'), ('2'); +DROP TABLE t1; +CREATE TABLE t1 ( +c1 SET('1', '2'), +UNIQUE USING BTREE(c1) +) ENGINE= MEMORY DEFAULT CHARSET= utf8; +INSERT INTO t1 VALUES('1'), ('2'); +DROP TABLE t1; End of 4.1 tests CREATE TABLE t1(val INT, KEY USING BTREE(val)) ENGINE=memory; INSERT INTO t1 VALUES(0); diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 83359048a8c..94f2f1f72b3 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -943,6 +943,156 @@ SHOW TABLE STATUS LIKE 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment t1 MyISAM 10 Dynamic X X X 72057594037927935 X X X X X X latin1_swedish_ci X max_rows=4100100100 avg_row_length=70100 DROP TABLE t1; +CREATE TABLE t1 (c1 TEXT NOT NULL, KEY c1 (c1(10))) ENGINE=MyISAM; +INSERT INTO t1 VALUES +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), +(''), (''), (''), (''), +(' B'), (' B'), (' B'), (' B'); +SELECT DISTINCT COUNT(*) FROM t1 WHERE c1 = ''; +COUNT(*) +4 +SELECT DISTINCT length(c1), c1 FROM t1 WHERE c1 = ''; +length(c1) c1 +0 +SELECT DISTINCT COUNT(*) FROM t1 IGNORE INDEX (c1) WHERE c1 = ''; +COUNT(*) +4 +SELECT DISTINCT length(c1), c1 FROM t1 IGNORE INDEX (c1) WHERE c1 = ''; +length(c1) c1 +0 +SELECT DISTINCT length(c1), c1 FROM t1 ORDER BY c1; +length(c1) c1 +0 +2 A +2 B +DROP TABLE t1; End of 4.1 tests set storage_engine=MyISAM; drop table if exists t1,t2,t3; diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test index 03ba8661a3c..d5a4fb7a734 100644 --- a/mysql-test/t/heap_btree.test +++ b/mysql-test/t/heap_btree.test @@ -182,6 +182,37 @@ delete from t1 where a >= 2; select a from t1 order by a; drop table t1; +# +# Bug#26996 - Update of a Field in a Memory Table ends with wrong result +# +CREATE TABLE t1 ( + c1 CHAR(3), + c2 INTEGER, + KEY USING BTREE(c1), + KEY USING BTREE(c2) +) ENGINE= MEMORY; +INSERT INTO t1 VALUES ('ABC',0), ('A',0), ('B',0), ('C',0); +UPDATE t1 SET c2= c2 + 1 WHERE c1 = 'A'; +SELECT * FROM t1; +DROP TABLE t1; + +# +# Bug#24985 - UTF8 ENUM primary key on MEMORY using BTREE +# causes incorrect duplicate entries +# +CREATE TABLE t1 ( + c1 ENUM('1', '2'), + UNIQUE USING BTREE(c1) +) ENGINE= MEMORY DEFAULT CHARSET= utf8; +INSERT INTO t1 VALUES('1'), ('2'); +DROP TABLE t1; +CREATE TABLE t1 ( + c1 SET('1', '2'), + UNIQUE USING BTREE(c1) +) ENGINE= MEMORY DEFAULT CHARSET= utf8; +INSERT INTO t1 VALUES('1'), ('2'); +DROP TABLE t1; + --echo End of 4.1 tests # @@ -205,3 +236,4 @@ INSERT INTO t1 VALUES(NULL),(NULL); DROP TABLE t1; --echo End of 5.0 tests + diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 59e3206d1c3..82d10059c65 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -874,6 +874,150 @@ CREATE TABLE t1 (c1 TEXT) AVG_ROW_LENGTH=70100 MAX_ROWS=4100100100; SHOW TABLE STATUS LIKE 't1'; DROP TABLE t1; +# +# Bug#26231 - select count(*) on myisam table returns wrong value +# when index is used +# +CREATE TABLE t1 (c1 TEXT NOT NULL, KEY c1 (c1(10))) ENGINE=MyISAM; +# Fill at least two key blocks. "Tab, A" must be in both blocks. +INSERT INTO t1 VALUES + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), (CHAR(9,65)), + (''), (''), (''), (''), + (' B'), (' B'), (' B'), (' B'); +SELECT DISTINCT COUNT(*) FROM t1 WHERE c1 = ''; +SELECT DISTINCT length(c1), c1 FROM t1 WHERE c1 = ''; +SELECT DISTINCT COUNT(*) FROM t1 IGNORE INDEX (c1) WHERE c1 = ''; +SELECT DISTINCT length(c1), c1 FROM t1 IGNORE INDEX (c1) WHERE c1 = ''; +SELECT DISTINCT length(c1), c1 FROM t1 ORDER BY c1; +DROP TABLE t1; + --echo End of 4.1 tests diff --git a/mysys/my_redel.c b/mysys/my_redel.c index 1e3cfceb495..0aec395cf65 100644 --- a/mysys/my_redel.c +++ b/mysys/my_redel.c @@ -60,7 +60,7 @@ int my_redel(const char *org_name, const char *tmp_name, myf MyFlags) MyFlags)) goto end; } - else if (my_delete(org_name,MyFlags)) + else if (my_delete_allow_opened(org_name, MyFlags)) goto end; if (my_rename(tmp_name,org_name,MyFlags)) goto end; diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index d1a931b07f2..8838aa99c1a 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -604,7 +604,10 @@ int ha_heap::create(const char *name, TABLE *table_arg, seg->length= (uint) key_part->length; seg->flag= key_part->key_part_flag; - seg->charset= field->charset(); + if (field->flags & (ENUM_FLAG | SET_FLAG)) + seg->charset= &my_charset_bin; + else + seg->charset= field->charset(); if (field->null_ptr) { seg->null_bit= field->null_bit; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 10d3dbb2ec5..6d8a770175d 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -976,6 +976,22 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize) ha_rows rows= file->state->records; DBUG_ENTER("ha_myisam::repair"); + /* + Normally this method is entered with a properly opened table. If the + repair fails, it can be repeated with more elaborate options. Under + special circumstances it can happen that a repair fails so that it + closed the data file and cannot re-open it. In this case file->dfile + is set to -1. We must not try another repair without an open data + file. (Bug #25289) + */ + if (file->dfile == -1) + { + sql_print_information("Retrying repair of: '%s' failed. " + "Please try REPAIR EXTENDED or myisamchk", + table->s->path); + DBUG_RETURN(HA_ADMIN_FAILED); + } + param.db_name= table->s->db; param.table_name= table->alias; param.tmpfile_createflag = O_RDWR | O_TRUNC;