diff options
Diffstat (limited to 'storage/innobase/fts/fts0que.cc')
-rw-r--r-- | storage/innobase/fts/fts0que.cc | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 8abeb63f0a4..dee7c59a58b 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -153,6 +153,13 @@ struct fts_query_t { bool multi_exist; /*!< multiple FTS_EXIST oper */ st_mysql_ftparser* parser; /*!< fts plugin parser */ + + /** limit value for the fts query */ + ulonglong limit; + + /** number of docs fetched by query. This is to restrict the + result with limit value */ + ulonglong n_docs; }; /** For phrase matching, first we collect the documents and the positions @@ -2700,7 +2707,7 @@ fts_query_phrase_split( /*****************************************************************//** Text/Phrase search. @return DB_SUCCESS or error code */ -static __attribute__((warn_unused_result)) +static MY_ATTRIBUTE((warn_unused_result)) dberr_t fts_query_phrase_search( /*====================*/ @@ -3209,6 +3216,11 @@ fts_query_filter_doc_ids( ulint decoded = 0; ib_rbt_t* doc_freqs = word_freq->doc_freqs; + if (query->limit != ULONG_UNDEFINED + && query->n_docs >= query->limit) { + return(DB_SUCCESS); + } + /* Decode the ilist and add the doc ids to the query doc_id set. */ while (decoded < len) { ulint freq = 0; @@ -3296,11 +3308,17 @@ 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 { @@ -3904,19 +3922,24 @@ fts_query_can_optimize( } } -/*******************************************************************//** -FTS Query entry point. +/** FTS Query entry point. +@param[in] trx transaction +@param[in] index fts index to search +@param[in] flags FTS search mode +@param[in] query_str FTS query +@param[in] query_len FTS query string len in bytes +@param[in,out] result result doc ids +@param[in] limit limit value @return DB_SUCCESS if successful otherwise error code */ dberr_t fts_query( -/*======*/ - trx_t* trx, /*!< in: transaction */ - dict_index_t* index, /*!< in: The FTS index to search */ - uint flags, /*!< in: FTS search mode */ - const byte* query_str, /*!< in: FTS query */ - ulint query_len, /*!< in: FTS query string len - in bytes */ - fts_result_t** result) /*!< in/out: result doc ids */ + trx_t* trx, + dict_index_t* index, + uint flags, + const byte* query_str, + ulint query_len, + fts_result_t** result, + ulonglong limit) { fts_query_t query; dberr_t error = DB_SUCCESS; @@ -3971,13 +3994,16 @@ fts_query( if (flags & FTS_EXPAND) { query.wildcard_words = rbt_create_arg_cmp( - sizeof(fts_string_t), innobase_fts_text_cmp, (void*)charset); + sizeof(fts_string_t), innobase_fts_text_cmp, (void *)charset); } query.total_size += SIZEOF_RBT_CREATE; query.total_docs = dict_table_get_n_rows(index->table); + query.limit = limit; + + query.n_docs = 0; #ifdef FTS_DOC_STATS_DEBUG if (ft_enable_diag_print) { error = fts_get_total_word_count( @@ -4053,6 +4079,19 @@ fts_query( fts_result_cache_limit = 2048; ); + /* Optimisation is allowed for limit value + when + i) No ranking involved + ii) Only FTS Union operations involved. */ + if (query.limit != ULONG_UNDEFINED + && !fts_ast_node_check_union(ast)) { + query.limit = ULONG_UNDEFINED; + } + + DBUG_EXECUTE_IF("fts_union_limit_off", + query.limit = ULONG_UNDEFINED; + ); + /* Traverse the Abstract Syntax Tree (AST) and execute the query. */ query.error = fts_ast_visit( |