diff --git a/mysql-test/suite/innodb_fts/r/bug87518.result b/mysql-test/suite/innodb_fts/r/bug87518.result new file mode 100644 index 0000000..7b1872b --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/bug87518.result @@ -0,0 +1,23 @@ +# +# Bug 87518: Server asserts when using n-gram full text searching with LIMIT +# +CREATE TABLE t1 ( +FTS_DOC_ID BIGINT UNSIGNED NOT NULL PRIMARY KEY, +contents TEXT COLLATE utf8mb4_bin, +FULLTEXT KEY fx_contents (contents) WITH PARSER ngram +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +INSERT INTO t1 VALUES (1, 'xyz mnt'), (2, 'xyz mnt'), (3, 'xyz'); +SELECT * FROM t1 WHERE MATCH(contents) AGAINST ('xyz' IN BOOLEAN MODE); +FTS_DOC_ID contents +1 xyz mnt +2 xyz mnt +3 xyz +SELECT * FROM t1 WHERE MATCH(contents) AGAINST ('xyz' IN BOOLEAN MODE) LIMIT 1; +FTS_DOC_ID contents +1 xyz mnt +SELECT * FROM t1 WHERE MATCH(contents) AGAINST ('xyz mnt' IN BOOLEAN MODE) LIMIT 5; +FTS_DOC_ID contents +1 xyz mnt +2 xyz mnt +3 xyz +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/r/limit_union.result b/mysql-test/suite/innodb_fts/r/limit_union.result index 13fff0b..a0c6805 100644 --- a/mysql-test/suite/innodb_fts/r/limit_union.result +++ b/mysql-test/suite/innodb_fts/r/limit_union.result @@ -32,7 +32,7 @@ SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL' IN BOOLEAN MODE) limit 1; id title body -1 MySQL Tutorial DBMS stands for DataBase ... +6 MySQL Security When configured properly, MySQL ... # Without optimization SET DEBUG = '+d,fts_union_limit_off'; SELECT * FROM articles diff --git a/mysql-test/suite/innodb_fts/t/bug87518.test b/mysql-test/suite/innodb_fts/t/bug87518.test new file mode 100644 index 0000000..c3041be --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/bug87518.test @@ -0,0 +1,24 @@ +--source include/have_innodb.inc + +--echo # +--echo # Bug 87518: Server asserts when using n-gram full text searching with LIMIT +--echo # + +CREATE TABLE t1 ( + FTS_DOC_ID BIGINT UNSIGNED NOT NULL PRIMARY KEY, + contents TEXT COLLATE utf8mb4_bin, + FULLTEXT KEY fx_contents (contents) WITH PARSER ngram +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +INSERT INTO t1 VALUES (1, 'xyz mnt'), (2, 'xyz mnt'), (3, 'xyz'); + +# The query completes with or without bug +SELECT * FROM t1 WHERE MATCH(contents) AGAINST ('xyz' IN BOOLEAN MODE); + +# The query returns wrong result set with the bug +SELECT * FROM t1 WHERE MATCH(contents) AGAINST ('xyz' IN BOOLEAN MODE) LIMIT 1; + +# The query crashes with the bug +SELECT * FROM t1 WHERE MATCH(contents) AGAINST ('xyz mnt' IN BOOLEAN MODE) LIMIT 5; + +DROP TABLE t1; diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 79d1f15..8916cae 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -746,6 +746,9 @@ fts_query_union_doc_id( query->total_size += SIZEOF_RBT_NODE_ADD + sizeof(fts_ranking_t) + RANKING_WORDS_INIT_LEN; + + if (query->limit != ULONG_UNDEFINED) + query->n_docs++; } } @@ -772,6 +775,9 @@ fts_query_remove_doc_id( SIZEOF_RBT_NODE_ADD + sizeof(fts_ranking_t)); query->total_size -= SIZEOF_RBT_NODE_ADD + sizeof(fts_ranking_t); + + if (query->limit != ULONG_UNDEFINED) + query->n_docs--; } } @@ -892,6 +898,9 @@ fts_query_intersect_doc_id( query->total_size += SIZEOF_RBT_NODE_ADD + sizeof(fts_ranking_t); + + if (query->limit != ULONG_UNDEFINED) + query->n_docs++; } } } @@ -3217,6 +3226,7 @@ fts_query_filter_doc_ids( if (query->limit != ULONG_UNDEFINED && query->n_docs >= query->limit) { + ut_ad(0); return(DB_SUCCESS); } @@ -3307,17 +3317,11 @@ fts_query_filter_doc_ids( /* Add the word to the document's matched RB tree. */ fts_query_add_word_to_document(query, doc_id, word); } - - if (query->limit != ULONG_UNDEFINED - && query->limit <= ++query->n_docs) { - goto func_exit; - } } /* Some sanity checks. */ ut_a(doc_id == node->last_doc_id); -func_exit: if (query->total_size > fts_result_cache_limit) { return(DB_FTS_EXCEED_RESULT_CACHE_LIMIT); } else {