From 6866ca008c941d2cc7afa106607257d9aaace519 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Apr 2007 01:40:35 +0500 Subject: [PATCH 1/3] =?UTF-8?q?BUG#24342=20-=20Incorrect=20results=20with?= =?UTF-8?q?=20query=20over=20MERGE=20table=20MERGE=20engine=20may=20return?= =?UTF-8?q?=20incorrect=20values=20when=20several=20representations=20of?= =?UTF-8?q?=20equal=20keys=20are=20present=20in=20the=20index.=20For=20exa?= =?UTF-8?q?mple=20"gro=C3=9F"=20and=20"gross"=20or=20"gross"=20and=20"gros?= =?UTF-8?q?s=20"=20(trailing=20space),=20which=20are=20considered=20equal,?= =?UTF-8?q?=20but=20have=20different=20lengths.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The problem was that key length was not recalculated after key lookup. Only MERGE engine is affected. myisam/mi_rkey.c: info->lastkey gets rewritten by mi_search. Later we recalculate found lastkey length. This is done to make sure that mi_rnext_same gets true, found (not searched) lastkey length. Searched and found key lengths may be different, for example in case searched key is "groß" and found is "gross" or in case a key has trailing spaces. Unfortunately we recalculate found lastkey length only for first underlying table. To recalculate found key length for non-first underlying table we need to know how much key segments were used to create this key. When mi_rkey is called for first underlying table of a merge table, store offset to last used key segment. Restore last_used_keyseg variable when mi_rkey is called for non-first underlying table. myisam/myisamdef.h: Added last_used_keyseg variable to MI_INFO. It is used by merge engine to calculate key length. myisammrg/myrg_rkey.c: Pass last used key segment returned by first table key read to other table key reads. mysql-test/r/merge.result: A test case for bug#24342. mysql-test/t/merge.test: A test case for bug#24342. --- myisam/mi_rkey.c | 3 ++- myisam/myisamdef.h | 1 + myisammrg/myrg_rkey.c | 4 ++++ mysql-test/r/merge.result | 11 +++++++++++ mysql-test/t/merge.test | 13 +++++++++++++ 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index b2d40288645..2933d694318 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -50,7 +50,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, key_buff=info->lastkey+info->s->base.max_key_length; pack_key_length= key_len; bmove(key_buff,key,key_len); - last_used_keyseg= 0; + last_used_keyseg= info->s->keyinfo[inx].seg + info->last_used_keyseg; } else { @@ -62,6 +62,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, key_len, &last_used_keyseg); /* Save packed_key_length for use by the MERGE engine. */ info->pack_key_length= pack_key_length; + info->last_used_keyseg= last_used_keyseg - info->s->keyinfo[inx].seg; DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg, key_buff, pack_key_length);); } diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 6365f0e1b0c..6ed041e8b9d 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -263,6 +263,7 @@ struct st_myisam_info { enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */ uint save_lastkey_length; uint pack_key_length; /* For MYISAMMRG */ + uint16 last_used_keyseg; /* For MyISAMMRG */ int errkey; /* Got last error on this key */ int lock_type; /* How database was locked */ int tmp_lock_type; /* When locked by readinfo */ diff --git a/myisammrg/myrg_rkey.c b/myisammrg/myrg_rkey.c index f87b264081e..b72334ea7dd 100644 --- a/myisammrg/myrg_rkey.c +++ b/myisammrg/myrg_rkey.c @@ -41,12 +41,14 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, { byte *key_buff; uint pack_key_length; + uint16 last_used_keyseg; MYRG_TABLE *table; MI_INFO *mi; int err; DBUG_ENTER("myrg_rkey"); LINT_INIT(key_buff); LINT_INIT(pack_key_length); + LINT_INIT(last_used_keyseg); if (_myrg_init_queue(info,inx,search_flag)) DBUG_RETURN(my_errno); @@ -61,10 +63,12 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, /* Get the saved packed key and packed key length. */ key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length; pack_key_length=mi->pack_key_length; + last_used_keyseg= mi->last_used_keyseg; } else { mi->once_flags|= USE_PACKED_KEYS; + mi->last_used_keyseg= last_used_keyseg; err=mi_rkey(mi,0,inx,key_buff,pack_key_length,search_flag); } info->last_used_table=table+1; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 00d8aa3d586..b12e4eb2d3a 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -819,3 +819,14 @@ ALTER TABLE m1 ENGINE=MERGE UNION=(t1); SELECT * FROM m1; c1 c2 c3 c4 c5 c6 c7 c8 c9 DROP TABLE t1, m1; +CREATE TABLE t1 (a VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_german2_ci, +b INT, INDEX(a,b)); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; +ALTER TABLE t3 ENGINE=MERGE UNION=(t1,t2); +INSERT INTO t1 VALUES ('ss',1); +INSERT INTO t2 VALUES ('ss',2),(0xDF,2); +SELECT COUNT(*) FROM t3 WHERE a=0xDF AND b=2; +COUNT(*) +2 +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 032e80ecc93..377160d0312 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -454,4 +454,17 @@ ALTER TABLE m1 ENGINE=MERGE UNION=(t1); SELECT * FROM m1; DROP TABLE t1, m1; +# +# BUG#24342 - Incorrect results with query over MERGE table +# +CREATE TABLE t1 (a VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_german2_ci, + b INT, INDEX(a,b)); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; +ALTER TABLE t3 ENGINE=MERGE UNION=(t1,t2); +INSERT INTO t1 VALUES ('ss',1); +INSERT INTO t2 VALUES ('ss',2),(0xDF,2); +SELECT COUNT(*) FROM t3 WHERE a=0xDF AND b=2; +DROP TABLE t1,t2,t3; + # End of 4.1 tests From 202f34e2f51cc888cecb6d1be683cf01ba3fbf88 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Apr 2007 02:31:34 +0500 Subject: [PATCH 2/3] BUG#25951 - ignore/use index does not work with fulltext IGNORE/USE/FORCE INDEX hints were honored when choosing FULLTEXT index. With this fix these hints are ignored. For regular indexes we may perform table scan instead of index lookup when IGNORE INDEX was specified. We cannot do this for FULLTEXT in NLQ mode. mysql-test/r/fulltext.result: A test case for bug#25951. mysql-test/t/fulltext.test: A test case for bug#25951. sql/item_func.cc: IGNOR/USE/FORCE INDEX hints should not be honored when choosing FULLTEXT index. Use proper bitmap, that is not modified by IGNORE/USE/FORCE INDEX hints. --- mysql-test/r/fulltext.result | 7 +++++++ mysql-test/t/fulltext.test | 10 ++++++++++ sql/item_func.cc | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index c1dd5f80d5c..3700ace4b19 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -447,3 +447,10 @@ a MATCH(a) AGAINST('test1 test') test1 0.68526661396027 DEALLOCATE PREPARE stmt; DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(255), FULLTEXT(a)); +SELECT * FROM t1 IGNORE INDEX(a) WHERE MATCH(a) AGAINST('test'); +a +ALTER TABLE t1 DISABLE KEYS; +SELECT * FROM t1 WHERE MATCH(a) AGAINST('test'); +ERROR HY000: Can't find FULLTEXT index matching the column list +DROP TABLE t1; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index d5ce6241490..1a9a6b578dc 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -369,4 +369,14 @@ EXECUTE stmt; DEALLOCATE PREPARE stmt; DROP TABLE t1; +# +# BUG#25951 - ignore/use index does not work with fulltext +# +CREATE TABLE t1 (a VARCHAR(255), FULLTEXT(a)); +SELECT * FROM t1 IGNORE INDEX(a) WHERE MATCH(a) AGAINST('test'); +ALTER TABLE t1 DISABLE KEYS; +--error 1191 +SELECT * FROM t1 WHERE MATCH(a) AGAINST('test'); +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index 88c3dfcdfc0..c6b2fa5cc3e 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3158,7 +3158,7 @@ bool Item_func_match::fix_index() for (keynr=0 ; keynr < table->keys ; keynr++) { if ((table->key_info[keynr].flags & HA_FULLTEXT) && - (table->keys_in_use_for_query.is_set(keynr))) + (table->keys_in_use.is_set(keynr))) { ft_to_key[fts]=keynr; ft_cnt[fts]=0; From 3673aaeb6b6e04b804e5308147234cfa80cd78de Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2007 11:53:25 +0500 Subject: [PATCH 3/3] Fixed a warning on win64. --- myisam/mi_rkey.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 2933d694318..e34799da6ed 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -62,7 +62,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, key_len, &last_used_keyseg); /* Save packed_key_length for use by the MERGE engine. */ info->pack_key_length= pack_key_length; - info->last_used_keyseg= last_used_keyseg - info->s->keyinfo[inx].seg; + info->last_used_keyseg= (uint16) (last_used_keyseg - + info->s->keyinfo[inx].seg); DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg, key_buff, pack_key_length);); }