From 37934f862ec7952f6baeb5c5c323e37b151aa298 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Tue, 2 Feb 2010 15:08:49 +0400 Subject: [PATCH] BUG#50351 - ft_min_word_len=2 Causes query to hang Performing fulltext prefix search (a word with truncation operator) may cause a dead-loop. ft_min_word_len value doesn't matter actually. The problem was introduced along with "smarter index merge" optimization. --- mysql-test/r/fulltext.result | 20 ++++++++++++++++++++ mysql-test/t/fulltext.test | 21 +++++++++++++++++++++ storage/myisam/ft_boolean_search.c | 12 +++++++++++- 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 1ef6656e7a4..cebe2ee4746 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -603,4 +603,24 @@ WHERE t3.a=t1.a AND MATCH(b2) AGAINST('scargill' IN BOOLEAN MODE) count(*) 0 DROP TABLE t1,t2,t3; +CREATE TABLE t1 (a VARCHAR(4), FULLTEXT(a)); +INSERT INTO t1 VALUES +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('awrd'),('cwrd'), +('awrd'); +SELECT COUNT(*) FROM t1 WHERE MATCH(a) AGAINST("+awrd bwrd* +cwrd*" IN BOOLEAN MODE); +COUNT(*) +0 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 3853a224fd5..705d6478fed 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -544,5 +544,26 @@ SELECT count(*) FROM t1 WHERE DROP TABLE t1,t2,t3; +# +# BUG#50351 - ft_min_word_len=2 Causes query to hang +# +CREATE TABLE t1 (a VARCHAR(4), FULLTEXT(a)); +INSERT INTO t1 VALUES +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'), +('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('cwrd'),('awrd'),('cwrd'), +('awrd'); +SELECT COUNT(*) FROM t1 WHERE MATCH(a) AGAINST("+awrd bwrd* +cwrd*" IN BOOLEAN MODE); +DROP TABLE t1; --echo End of 5.1 tests diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 492261c5efc..52ad6b11aa1 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -437,8 +437,18 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) return 0; } - /* going up to the first-level tree to continue search there */ + /* + Going up to the first-level tree to continue search there. + Only done when performing prefix search. + + Key buffer data pointer as well as docid[0] may be smaller + than values we got while searching first-level tree. Thus + they must be restored to original values to avoid dead-loop, + when subsequent search for a bigger value eventually ends up + in this same second-level tree. + */ _mi_dpointer(info, (uchar*) (lastkey_buf+HA_FT_WLEN), ftbw->key_root); + ftbw->docid[0]= ftbw->key_root; ftbw->key_root=info->s->state.key_root[ftb->keynr]; ftbw->keyinfo=info->s->keyinfo+ftb->keynr; ftbw->off=0;