diff options
Diffstat (limited to 'storage/xtradb/fts/fts0fts.cc')
-rw-r--r-- | storage/xtradb/fts/fts0fts.cc | 515 |
1 files changed, 200 insertions, 315 deletions
diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index 98aaf610f2a..6dbe5e0e2a0 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/fts/fts0fts.cc @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2017, MariaDB Corporation. +Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -13,7 +13,7 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA +51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -67,7 +67,7 @@ UNIV_INTERN ulong fts_max_total_cache_size; /** This is FTS result cache limit for each query and would be a configurable variable */ -UNIV_INTERN ulong fts_result_cache_limit; +UNIV_INTERN size_t fts_result_cache_limit; /** Variable specifying the maximum FTS max token size */ UNIV_INTERN ulong fts_max_token_size; @@ -77,8 +77,8 @@ UNIV_INTERN ulong fts_min_token_size; // FIXME: testing -ib_time_t elapsed_time = 0; -ulint n_nodes = 0; +static time_t elapsed_time; +static ulint n_nodes; /** Error condition reported by fts_utf8_decode() */ const ulint UTF8_ERROR = 0xFFFFFFFF; @@ -107,11 +107,6 @@ UNIV_INTERN mysql_pfs_key_t fts_doc_id_mutex_key; UNIV_INTERN mysql_pfs_key_t fts_pll_tokenize_mutex_key; #endif /* UNIV_PFS_MUTEX */ -/** variable to record innodb_fts_internal_tbl_name for information -schema table INNODB_FTS_INSERTED etc. */ -UNIV_INTERN char* fts_internal_tbl_name = NULL; -UNIV_INTERN char* fts_internal_tbl_name2 = NULL; - /** InnoDB default stopword list: There are different versions of stopwords, the stop words listed below comes from "Google Stopword" list. Reference: @@ -167,38 +162,39 @@ struct fts_aux_table_t { char* name; /*!< Name of the table */ }; -/** SQL statements for creating the ancillary common FTS tables. */ +/** SQL statements for creating the ancillary common FTS tables. +The table name here shall be consistent with fts_common_tables. */ static const char* fts_create_common_tables_sql = { "BEGIN\n" "" - "CREATE TABLE \"%s_DELETED\" (\n" + "CREATE TABLE $DELETED (\n" " doc_id BIGINT UNSIGNED\n" ") COMPACT;\n" - "CREATE UNIQUE CLUSTERED INDEX IND ON \"%s_DELETED\"(doc_id);\n" + "CREATE UNIQUE CLUSTERED INDEX IND ON $DELETED (doc_id);\n" "" - "CREATE TABLE \"%s_DELETED_CACHE\" (\n" + "CREATE TABLE $DELETED_CACHE (\n" " doc_id BIGINT UNSIGNED\n" ") COMPACT;\n" "CREATE UNIQUE CLUSTERED INDEX IND " - "ON \"%s_DELETED_CACHE\"(doc_id);\n" + "ON $DELETED_CACHE(doc_id);\n" "" - "CREATE TABLE \"%s_BEING_DELETED\" (\n" + "CREATE TABLE $BEING_DELETED (\n" " doc_id BIGINT UNSIGNED\n" ") COMPACT;\n" "CREATE UNIQUE CLUSTERED INDEX IND " - "ON \"%s_BEING_DELETED\"(doc_id);\n" + "ON $BEING_DELETED(doc_id);\n" "" - "CREATE TABLE \"%s_BEING_DELETED_CACHE\" (\n" + "CREATE TABLE $BEING_DELETED_CACHE (\n" " doc_id BIGINT UNSIGNED\n" ") COMPACT;\n" "CREATE UNIQUE CLUSTERED INDEX IND " - "ON \"%s_BEING_DELETED_CACHE\"(doc_id);\n" + "ON $BEING_DELETED_CACHE(doc_id);\n" "" - "CREATE TABLE \"%s_CONFIG\" (\n" + "CREATE TABLE $CONFIG (\n" " key CHAR(50),\n" " value CHAR(200) NOT NULL\n" ") COMPACT;\n" - "CREATE UNIQUE CLUSTERED INDEX IND ON \"%s_CONFIG\"(key);\n" + "CREATE UNIQUE CLUSTERED INDEX IND ON $CONFIG(key);\n" }; #ifdef FTS_DOC_STATS_DEBUG @@ -207,11 +203,11 @@ mainly designed for the statistics work in the future */ static const char* fts_create_index_tables_sql = { "BEGIN\n" "" - "CREATE TABLE \"%s_DOC_ID\" (\n" + "CREATE TABLE $doc_id_table (\n" " doc_id BIGINT UNSIGNED,\n" " word_count INTEGER UNSIGNED NOT NULL\n" ") COMPACT;\n" - "CREATE UNIQUE CLUSTERED INDEX IND ON \"%s_DOC_ID\"(doc_id);\n" + "CREATE UNIQUE CLUSTERED INDEX IND ON $doc_id_table(doc_id);\n" }; #endif @@ -220,11 +216,11 @@ static const char* fts_create_index_sql = { "BEGIN\n" "" "CREATE UNIQUE CLUSTERED INDEX FTS_INDEX_TABLE_IND " - "ON \"%s\"(word, first_doc_id);\n" + "ON $table (word, first_doc_id);\n" }; /** FTS auxiliary table suffixes that are common to all FT indexes. */ -static const char* fts_common_tables[] = { +const char* fts_common_tables[] = { "BEING_DELETED", "BEING_DELETED_CACHE", "CONFIG", @@ -248,19 +244,19 @@ const fts_index_selector_t fts_index_selector[] = { static const char* fts_config_table_insert_values_sql = "BEGIN\n" "\n" - "INSERT INTO \"%s\" VALUES('" + "INSERT INTO $config_table VALUES('" FTS_MAX_CACHE_SIZE_IN_MB "', '256');\n" "" - "INSERT INTO \"%s\" VALUES('" + "INSERT INTO $config_table VALUES('" FTS_OPTIMIZE_LIMIT_IN_SECS "', '180');\n" "" - "INSERT INTO \"%s\" VALUES ('" + "INSERT INTO $config_table VALUES ('" FTS_SYNCED_DOC_ID "', '0');\n" "" - "INSERT INTO \"%s\" VALUES ('" + "INSERT INTO $config_table VALUES ('" FTS_TOTAL_DELETED_COUNT "', '0');\n" "" /* Note: 0 == FTS_TABLE_STATE_RUNNING */ - "INSERT INTO \"%s\" VALUES ('" + "INSERT INTO $config_table VALUES ('" FTS_TABLE_STATE "', '0');\n"; /** Run SYNC on the table, i.e., write out data from the cache to the @@ -268,7 +264,7 @@ FTS auxiliary INDEX table and clear the cache at the end. @param[in,out] sync sync state @param[in] unlock_cache whether unlock cache lock when write node @param[in] wait whether wait when a sync is in progress -@param[in] has_dict whether has dict operation lock +@param[in] has_dict whether has dict operation lock @return DB_SUCCESS if all OK */ static dberr_t @@ -334,7 +330,6 @@ dberr_t fts_update_sync_doc_id( /*===================*/ const dict_table_t* table, /*!< in: table */ - const char* table_name, /*!< in: table name, or NULL */ doc_id_t doc_id, /*!< in: last document id */ trx_t* trx) /*!< in: update trx, or NULL */ MY_ATTRIBUTE((nonnull(1))); @@ -463,7 +458,7 @@ fts_load_user_stopword( dberr_t error = DB_SUCCESS; ibool ret = TRUE; trx_t* trx; - ibool has_lock = fts->fts_status & TABLE_DICT_LOCKED; + ibool has_lock = fts->dict_locked; trx = trx_allocate_for_background(); trx->op_info = "Load user stopword table into FTS cache"; @@ -567,7 +562,7 @@ fts_index_cache_init( index_cache->words = rbt_create_arg_cmp( sizeof(fts_tokenizer_word_t), innobase_fts_text_cmp, - (void*)index_cache->charset); + (void*) index_cache->charset); ut_a(index_cache->doc_stats == NULL); @@ -736,6 +731,7 @@ fts_reset_get_doc( memset(get_doc, 0x0, sizeof(*get_doc)); get_doc->index_cache = ind_cache; + get_doc->cache = cache; } ut_ad(ib_vector_size(cache->get_docs) @@ -869,37 +865,28 @@ fts_drop_index( err = fts_drop_index_tables(trx, index); - for(;;) { - bool retry = false; - if (index->index_fts_syncing) { - retry = true; - } - if (!retry){ - fts_free(table); - break; - } + while (index->index_fts_syncing + && !trx_is_interrupted(trx)) { DICT_BG_YIELD(trx); } + + fts_free(table); + return(err); } - for(;;) { - bool retry = false; - if (index->index_fts_syncing) { - retry = true; - } - if (!retry){ - current_doc_id = table->fts->cache->next_doc_id; - first_doc_id = table->fts->cache->first_doc_id; - fts_cache_clear(table->fts->cache); - fts_cache_destroy(table->fts->cache); - table->fts->cache = fts_cache_create(table); - table->fts->cache->next_doc_id = current_doc_id; - table->fts->cache->first_doc_id = first_doc_id; - break; - } + while (index->index_fts_syncing + && !trx_is_interrupted(trx)) { DICT_BG_YIELD(trx); } + + current_doc_id = table->fts->cache->next_doc_id; + first_doc_id = table->fts->cache->first_doc_id; + fts_cache_clear(table->fts->cache); + fts_cache_destroy(table->fts->cache); + table->fts->cache = fts_cache_create(table); + table->fts->cache->next_doc_id = current_doc_id; + table->fts->cache->first_doc_id = first_doc_id; } else { fts_cache_t* cache = table->fts->cache; fts_index_cache_t* index_cache; @@ -909,18 +896,14 @@ fts_drop_index( index_cache = fts_find_index_cache(cache, index); if (index_cache != NULL) { - for(;;) { - bool retry = false; - if (index->index_fts_syncing) { - retry = true; - } - if (!retry && index_cache->words) { - fts_words_free(index_cache->words); - rbt_free(index_cache->words); - break; - } + while (index->index_fts_syncing + && !trx_is_interrupted(trx)) { DICT_BG_YIELD(trx); } + if (index_cache->words) { + fts_words_free(index_cache->words); + rbt_free(index_cache->words); + } ib_vector_remove(cache->indexes, *(void**) index_cache); } @@ -950,18 +933,16 @@ fts_que_graph_free_check_lock( const fts_index_cache_t*index_cache, /*!< in: FTS index cache */ que_t* graph) /*!< in: query graph */ { - ibool has_dict = FALSE; + bool has_dict = FALSE; if (fts_table && fts_table->table) { ut_ad(fts_table->table->fts); - has_dict = fts_table->table->fts->fts_status - & TABLE_DICT_LOCKED; + has_dict = fts_table->table->fts->dict_locked; } else if (index_cache) { ut_ad(index_cache->index->table->fts); - has_dict = index_cache->index->table->fts->fts_status - & TABLE_DICT_LOCKED; + has_dict = index_cache->index->table->fts->dict_locked; } if (!has_dict) { @@ -1598,19 +1579,17 @@ fts_rename_aux_tables( FTS_INIT_FTS_TABLE(&fts_table, NULL, FTS_COMMON_TABLE, table); + dberr_t err = DB_SUCCESS; + char old_table_name[MAX_FULL_NAME_LEN]; + /* Rename common auxiliary tables */ for (i = 0; fts_common_tables[i] != NULL; ++i) { - char* old_table_name; - dberr_t err = DB_SUCCESS; - fts_table.suffix = fts_common_tables[i]; - old_table_name = fts_get_table_name(&fts_table); + fts_get_table_name(&fts_table, old_table_name, true); err = fts_rename_one_aux_table(new_name, old_table_name, trx); - mem_free(old_table_name); - if (err != DB_SUCCESS) { return(err); } @@ -1629,12 +1608,8 @@ fts_rename_aux_tables( FTS_INIT_INDEX_TABLE(&fts_table, NULL, FTS_INDEX_TABLE, index); for (ulint j = 0; fts_index_selector[j].value; ++j) { - dberr_t err; - char* old_table_name; - fts_table.suffix = fts_get_suffix(j); - - old_table_name = fts_get_table_name(&fts_table); + fts_get_table_name(&fts_table, old_table_name, true); err = fts_rename_one_aux_table( new_name, old_table_name, trx); @@ -1643,8 +1618,6 @@ fts_rename_aux_tables( err = DB_DEADLOCK; fts_sql_rollback(trx);); - mem_free(old_table_name); - if (err != DB_SUCCESS) { return(err); } @@ -1672,11 +1645,11 @@ fts_drop_common_tables( for (i = 0; fts_common_tables[i] != NULL; ++i) { dberr_t err; - char* table_name; + char table_name[MAX_FULL_NAME_LEN]; fts_table->suffix = fts_common_tables[i]; - table_name = fts_get_table_name(fts_table); + fts_get_table_name(fts_table, table_name, true); err = fts_drop_table(trx, table_name); @@ -1684,8 +1657,6 @@ fts_drop_common_tables( if (err != DB_SUCCESS && err != DB_FAIL) { error = err; } - - mem_free(table_name); } return(error); @@ -1711,11 +1682,11 @@ fts_drop_index_split_tables( for (i = 0; fts_index_selector[i].value; ++i) { dberr_t err; - char* table_name; + char table_name[MAX_FULL_NAME_LEN]; fts_table.suffix = fts_get_suffix(i); - table_name = fts_get_table_name(&fts_table); + fts_get_table_name(&fts_table, table_name, true); err = fts_drop_table(trx, table_name); @@ -1723,8 +1694,6 @@ fts_drop_index_split_tables( if (err != DB_SUCCESS && err != DB_FAIL) { error = err; } - - mem_free(table_name); } return(error); @@ -1761,11 +1730,11 @@ fts_drop_index_tables( FTS_INIT_INDEX_TABLE(&fts_table, NULL, FTS_INDEX_TABLE, index); for (ulint i = 0; index_tables[i] != NULL; ++i) { - char* table_name; + char table_name[MAX_FULL_NAME_LEN]; fts_table.suffix = index_tables[i]; - table_name = fts_get_table_name(&fts_table); + fts_get_table_name(&fts_table, table_name, true); err = fts_drop_table(trx, table_name); @@ -1773,8 +1742,6 @@ fts_drop_index_tables( if (err != DB_SUCCESS && err != DB_FAIL) { error = err; } - - mem_free(table_name); } #endif /* FTS_DOC_STATS_DEBUG */ @@ -1844,26 +1811,6 @@ fts_drop_tables( } /*********************************************************************//** -Prepare the SQL, so that all '%s' are replaced by the common prefix. -@return sql string, use mem_free() to free the memory */ -static -char* -fts_prepare_sql( -/*============*/ - fts_table_t* fts_table, /*!< in: table name info */ - const char* my_template) /*!< in: sql template */ -{ - char* sql; - char* name_prefix; - - name_prefix = fts_get_table_name_prefix(fts_table); - sql = ut_strreplace(my_template, "%s", name_prefix); - mem_free(name_prefix); - - return(sql); -} - -/*********************************************************************//** Creates the common ancillary tables needed for supporting an FTS index on the given table. row_mysql_lock_data_dictionary must have been called before this. @@ -1877,12 +1824,15 @@ fts_create_common_tables( const char* name, /*!< in: table name normalized.*/ bool skip_doc_id_index)/*!< in: Skip index on doc id */ { - char* sql; dberr_t error; que_t* graph; fts_table_t fts_table; mem_heap_t* heap = mem_heap_create(1024); pars_info_t* info; + char fts_name[MAX_FULL_NAME_LEN]; + char full_name[sizeof(fts_common_tables) / sizeof(char*)] + [MAX_FULL_NAME_LEN]; + ulint i; FTS_INIT_FTS_TABLE(&fts_table, NULL, FTS_COMMON_TABLE, table); @@ -1894,9 +1844,19 @@ fts_create_common_tables( } /* Create the FTS tables that are common to an FTS index. */ - sql = fts_prepare_sql(&fts_table, fts_create_common_tables_sql); - graph = fts_parse_sql_no_dict_lock(NULL, NULL, sql); - mem_free(sql); + info = pars_info_create(); + + for (i = 0; fts_common_tables[i] != NULL; ++i) { + + fts_table.suffix = fts_common_tables[i]; + fts_get_table_name(&fts_table, full_name[i], true); + + pars_info_bind_id(info, true, + fts_common_tables[i], full_name[i]); + } + + graph = fts_parse_sql_no_dict_lock(NULL, info, + fts_create_common_tables_sql); error = fts_eval_sql(trx, graph); @@ -1908,9 +1868,14 @@ fts_create_common_tables( } /* Write the default settings to the config table. */ + info = pars_info_create(); + fts_table.suffix = "CONFIG"; + fts_get_table_name(&fts_table, fts_name, true); + pars_info_bind_id(info, true, "config_table", fts_name); + graph = fts_parse_sql_no_dict_lock( - &fts_table, NULL, fts_config_table_insert_values_sql); + &fts_table, info, fts_config_table_insert_values_sql); error = fts_eval_sql(trx, graph); @@ -1978,13 +1943,15 @@ fts_create_one_index_table( { dict_field_t* field; dict_table_t* new_table = NULL; - char* table_name = fts_get_table_name(fts_table); + char table_name[MAX_FULL_NAME_LEN]; dberr_t error; CHARSET_INFO* charset; ulint flags2 = 0; ut_ad(index->type & DICT_FTS); + fts_get_table_name(fts_table, table_name, true); + if (srv_file_per_table) { flags2 = DICT_TF2_USE_TABLESPACE; } @@ -2017,7 +1984,8 @@ fts_create_one_index_table( dict_mem_table_add_col(new_table, heap, "ilist", DATA_BLOB, 4130048, 0); - error = row_create_table_for_mysql(new_table, trx, false, FIL_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY); + error = row_create_table_for_mysql(new_table, trx, false, + FIL_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY); if (error != DB_SUCCESS) { trx->error_state = error; @@ -2027,8 +1995,6 @@ fts_create_one_index_table( "Fail to create FTS index table %s", table_name); } - mem_free(table_name); - return(new_table); } @@ -2051,23 +2017,27 @@ fts_create_index_tables_low( que_t* graph; fts_table_t fts_table; dberr_t error = DB_SUCCESS; + pars_info_t* info; mem_heap_t* heap = mem_heap_create(1024); + char fts_name[MAX_FULL_NAME_LEN]; fts_table.type = FTS_INDEX_TABLE; fts_table.index_id = index->id; fts_table.table_id = table_id; - fts_table.parent = table_name; fts_table.table = index->table; #ifdef FTS_DOC_STATS_DEBUG - char* sql; - /* Create the FTS auxiliary tables that are specific to an FTS index. */ - sql = fts_prepare_sql(&fts_table, fts_create_index_tables_sql); + info = pars_info_create(); - graph = fts_parse_sql_no_dict_lock(NULL, NULL, sql); - mem_free(sql); + fts_table.suffix = "DOC_ID"; + fts_get_table_name(&fts_table, fts_name, true); + + pars_info_bind_id(info, true, "doc_id_table", fts_name); + + graph = fts_parse_sql_no_dict_lock(NULL, info, + fts_create_index_tables_sql); error = fts_eval_sql(trx, graph); que_graph_free(graph); @@ -2076,6 +2046,8 @@ fts_create_index_tables_low( for (i = 0; fts_index_selector[i].value && error == DB_SUCCESS; ++i) { dict_table_t* new_table; + info = pars_info_create(); + /* Create the FTS auxiliary tables that are specific to an FTS index. We need to preserve the table_id %s which fts_parse_sql_no_dict_lock() will fill in for us. */ @@ -2089,8 +2061,12 @@ fts_create_index_tables_low( break; } + fts_get_table_name(&fts_table, fts_name, true); + + pars_info_bind_id(info, true, "table", fts_name); + graph = fts_parse_sql_no_dict_lock( - &fts_table, NULL, fts_create_index_sql); + &fts_table, info, fts_create_index_sql); error = fts_eval_sql(trx, graph); que_graph_free(graph); @@ -2643,7 +2619,6 @@ fts_update_next_doc_id( /*===================*/ trx_t* trx, /*!< in/out: transaction */ const dict_table_t* table, /*!< in: table */ - const char* table_name, /*!< in: table name, or NULL */ doc_id_t doc_id) /*!< in: DOC ID to set */ { table->fts->cache->synced_doc_id = doc_id; @@ -2652,7 +2627,7 @@ fts_update_next_doc_id( table->fts->cache->first_doc_id = table->fts->cache->next_doc_id; fts_update_sync_doc_id( - table, table_name, table->fts->cache->synced_doc_id, trx); + table, table->fts->cache->synced_doc_id, trx); } @@ -2715,6 +2690,7 @@ fts_cmp_set_sync_doc_id( fts_table_t fts_table; que_t* graph = NULL; fts_cache_t* cache = table->fts->cache; + char table_name[MAX_FULL_NAME_LEN]; retry: ut_a(table->fts->doc_col != ULINT_UNDEFINED); @@ -2723,8 +2699,6 @@ retry: fts_table.type = FTS_COMMON_TABLE; fts_table.table = table; - fts_table.parent = table->name; - trx = trx_allocate_for_background(); trx->op_info = "update the next FTS document id"; @@ -2734,10 +2708,13 @@ retry: pars_info_bind_function( info, "my_func", fts_fetch_store_doc_id, doc_id); + fts_get_table_name(&fts_table, table_name); + pars_info_bind_id(info, true, "config_table", table_name); + graph = fts_parse_sql( &fts_table, info, "DECLARE FUNCTION my_func;\n" - "DECLARE CURSOR c IS SELECT value FROM \"%s\"" + "DECLARE CURSOR c IS SELECT value FROM $config_table" " WHERE key = 'synced_doc_id' FOR UPDATE;\n" "BEGIN\n" "" @@ -2762,6 +2739,10 @@ retry: } if (read_only) { + /* InnoDB stores actual synced_doc_id value + 1 in + FTS_CONFIG table. Reduce the value by 1 while reading + after startup. */ + if (*doc_id) *doc_id -= 1; goto func_exit; } @@ -2781,7 +2762,7 @@ retry: if (doc_id_cmp > *doc_id) { error = fts_update_sync_doc_id( - table, table->name, cache->synced_doc_id, trx); + table, cache->synced_doc_id, trx); } *doc_id = cache->next_doc_id; @@ -2819,7 +2800,6 @@ dberr_t fts_update_sync_doc_id( /*===================*/ const dict_table_t* table, /*!< in: table */ - const char* table_name, /*!< in: table name, or NULL */ doc_id_t doc_id, /*!< in: last document id */ trx_t* trx) /*!< in: update trx, or NULL */ { @@ -2831,16 +2811,12 @@ fts_update_sync_doc_id( dberr_t error; ibool local_trx = FALSE; fts_cache_t* cache = table->fts->cache; + char fts_name[MAX_FULL_NAME_LEN]; fts_table.suffix = "CONFIG"; fts_table.table_id = table->id; fts_table.type = FTS_COMMON_TABLE; fts_table.table = table; - if (table_name) { - fts_table.parent = table_name; - } else { - fts_table.parent = table->name; - } if (!trx) { trx = trx_allocate_for_background(); @@ -2856,10 +2832,14 @@ fts_update_sync_doc_id( pars_info_bind_varchar_literal(info, "doc_id", id, id_len); + fts_get_table_name(&fts_table, fts_name, + table->fts->dict_locked); + pars_info_bind_id(info, true, "table_name", fts_name); + graph = fts_parse_sql( &fts_table, info, "BEGIN " - "UPDATE \"%s\" SET value = :doc_id" + "UPDATE $table_name SET value = :doc_id" " WHERE key = 'synced_doc_id';"); error = fts_eval_sql(trx, graph); @@ -2907,22 +2887,6 @@ fts_doc_ids_create(void) } /*********************************************************************//** -Free a fts_doc_ids_t. */ - -void -fts_doc_ids_free( -/*=============*/ - fts_doc_ids_t* fts_doc_ids) -{ - mem_heap_t* heap = static_cast<mem_heap_t*>( - fts_doc_ids->self_heap->arg); - - memset(fts_doc_ids, 0, sizeof(*fts_doc_ids)); - - mem_heap_free(heap); -} - -/*********************************************************************//** Do commit-phase steps necessary for the insertion of a new row. */ void fts_add( @@ -2985,7 +2949,7 @@ fts_delete( into cache from last crash (delete Doc will not initialize the sync). Avoid any added counter accounting until the FTS cache is re-established and sync-ed */ - if (table->fts->fts_status & ADDED_TABLE_SYNCED + if (table->fts->added_synced && doc_id > cache->synced_doc_id) { mutex_enter(&table->fts->cache->deleted_lock); @@ -3006,6 +2970,7 @@ fts_delete( /* Note the deleted document for OPTIMIZE to purge. */ if (error == DB_SUCCESS) { + char table_name[MAX_FULL_NAME_LEN]; trx->op_info = "adding doc id to FTS DELETED"; @@ -3013,10 +2978,13 @@ fts_delete( fts_table.suffix = "DELETED"; + fts_get_table_name(&fts_table, table_name); + pars_info_bind_id(info, true, "deleted", table_name); + graph = fts_parse_sql( &fts_table, info, - "BEGIN INSERT INTO \"%s\" VALUES (:doc_id);"); + "BEGIN INSERT INTO $deleted VALUES (:doc_id);"); error = fts_eval_sql(trx, graph); @@ -3419,7 +3387,7 @@ fts_add_doc_by_id( /* If Doc ID has been supplied by the user, then the table might not yet be sync-ed */ - if (!(ftt->table->fts->fts_status & ADDED_TABLE_SYNCED)) { + if (!ftt->table->fts->added_synced) { fts_init_index(ftt->table, FALSE); } @@ -3832,14 +3800,18 @@ fts_write_node( pars_info_t* info; dberr_t error; ib_uint32_t doc_count; - ib_time_t start_time; + time_t start_time; doc_id_t last_doc_id; doc_id_t first_doc_id; + char table_name[MAX_FULL_NAME_LEN]; if (*graph) { info = (*graph)->info; } else { info = pars_info_create(); + + fts_get_table_name(fts_table, table_name); + pars_info_bind_id(info, true, "index_table_name", table_name); } pars_info_bind_varchar_literal(info, "token", word->f_str, word->f_len); @@ -3865,18 +3837,19 @@ fts_write_node( DATA_BLOB, DATA_BINARY_TYPE); if (!*graph) { + *graph = fts_parse_sql( fts_table, info, "BEGIN\n" - "INSERT INTO \"%s\" VALUES " + "INSERT INTO $index_table_name VALUES " "(:token, :first_doc_id," " :last_doc_id, :doc_count, :ilist);"); } - start_time = ut_time(); + start_time = time(NULL); error = fts_eval_sql(trx, *graph); - elapsed_time += ut_time() - start_time; + elapsed_time += time(NULL) - start_time; ++n_nodes; return(error); @@ -3896,6 +3869,7 @@ fts_sync_add_deleted_cache( pars_info_t* info; que_t* graph; fts_table_t fts_table; + char table_name[MAX_FULL_NAME_LEN]; doc_id_t dummy = 0; dberr_t error = DB_SUCCESS; ulint n_elems = ib_vector_size(doc_ids); @@ -3911,10 +3885,13 @@ fts_sync_add_deleted_cache( FTS_INIT_FTS_TABLE( &fts_table, "DELETED_CACHE", FTS_COMMON_TABLE, sync->table); + fts_get_table_name(&fts_table, table_name); + pars_info_bind_id(info, true, "table_name", table_name); + graph = fts_parse_sql( &fts_table, info, - "BEGIN INSERT INTO \"%s\" VALUES (:doc_id);"); + "BEGIN INSERT INTO $table_name VALUES (:doc_id);"); for (i = 0; i < n_elems && error == DB_SUCCESS; ++i) { fts_update_t* update; @@ -3974,6 +3951,9 @@ fts_sync_write_words( word = rbt_value(fts_tokenizer_word_t, rbt_node); + DBUG_EXECUTE_IF("fts_instrument_write_words_before_select_index", + os_thread_sleep(300000);); + selected = fts_select_index( index_cache->charset, word->text.f_str, word->text.f_len); @@ -4088,6 +4068,7 @@ fts_sync_write_doc_stat( doc_id_t doc_id; dberr_t error = DB_SUCCESS; ib_uint32_t word_count; + char table_name[MAX_FULL_NAME_LEN]; if (*graph) { info = (*graph)->info; @@ -4110,10 +4091,15 @@ fts_sync_write_doc_stat( FTS_INIT_INDEX_TABLE( &fts_table, "DOC_ID", FTS_INDEX_TABLE, index); + fts_get_table_name(&fts_table, table_name); + + pars_info_bind_id(info, true, "doc_id_table", table_name); + *graph = fts_parse_sql( &fts_table, info, - "BEGIN INSERT INTO \"%s\" VALUES (:doc_id, :count);"); + "BEGIN " + "INSERT INTO $doc_id_table VALUES (:doc_id, :count);"); } for (;;) { @@ -4235,6 +4221,7 @@ fts_is_word_in_index( { pars_info_t* info; dberr_t error; + char table_name[MAX_FULL_NAME_LEN]; trx->op_info = "looking up word in FTS index"; @@ -4244,6 +4231,8 @@ fts_is_word_in_index( info = pars_info_create(); } + fts_get_table_name(fts_table, table_name); + pars_info_bind_id(info, true, "table_name", table_name); pars_info_bind_function(info, "my_func", fts_lookup_word, found); pars_info_bind_varchar_literal(info, "word", word->f_str, word->f_len); @@ -4254,7 +4243,7 @@ fts_is_word_in_index( "DECLARE FUNCTION my_func;\n" "DECLARE CURSOR c IS" " SELECT doc_count\n" - " FROM \"%s\"\n" + " FROM $table_name\n" " WHERE word = :word " " ORDER BY first_doc_id;\n" "BEGIN\n" @@ -4311,14 +4300,14 @@ fts_sync_begin( n_nodes = 0; elapsed_time = 0; - sync->start_time = ut_time(); + sync->start_time = time(NULL); sync->trx = trx_allocate_for_background(); if (fts_enable_diag_print) { ib_logf(IB_LOG_LEVEL_INFO, "FTS SYNC for table %s, deleted count: %ld size: " - "%lu bytes", + "%zu bytes", sync->table->name, ib_vector_size(cache->deleted_doc_ids), cache->total_size); @@ -4470,7 +4459,7 @@ fts_sync_commit( "SYNC for table %s: SYNC time : %lu secs: " "elapsed %lf ins/sec", sync->table->name, - (ulong) (ut_time() - sync->start_time), + (ulong) (time(NULL) - sync->start_time), (double) n_nodes/ (double) elapsed_time); } @@ -4538,7 +4527,7 @@ FTS auxiliary INDEX table and clear the cache at the end. @param[in,out] sync sync state @param[in] unlock_cache whether unlock cache lock when write node @param[in] wait whether wait when a sync is in progress -@param[in] has_dict whether has dict operation lock +@param[in] has_dict whether has dict operation lock @return DB_SUCCESS if all OK */ static dberr_t @@ -4600,15 +4589,13 @@ begin_sync: continue; } + DBUG_EXECUTE_IF("fts_instrument_sync_before_syncing", + os_thread_sleep(300000);); index_cache->index->index_fts_syncing = true; - DBUG_EXECUTE_IF("fts_instrument_sync_sleep_drop_waits", - os_thread_sleep(10000000); - ); error = fts_sync_index(sync, index_cache); - if (error != DB_SUCCESS && !sync->interrupted) { - + if (error != DB_SUCCESS) { goto end_sync; } } @@ -4627,6 +4614,7 @@ begin_sync: ib_vector_get(cache->indexes, i)); if (index_cache->index->to_be_dropped + || index_cache->index->table->to_be_dropped || fts_sync_index_check(index_cache)) { continue; } @@ -4637,31 +4625,17 @@ begin_sync: end_sync: if (error == DB_SUCCESS && !sync->interrupted) { error = fts_sync_commit(sync); - if (error == DB_SUCCESS) { - for (i = 0; i < ib_vector_size(cache->indexes); ++i) { - fts_index_cache_t* index_cache; - index_cache = static_cast<fts_index_cache_t*>( - ib_vector_get(cache->indexes, i)); - if (index_cache->index->index_fts_syncing) { - index_cache->index->index_fts_syncing - = false; - } - } - } } else { fts_sync_rollback(sync); } rw_lock_x_lock(&cache->lock); - /* Clear fts syncing flags of any indexes incase sync is - interrupeted */ + /* Clear fts syncing flags of any indexes in case sync is + interrupted */ for (i = 0; i < ib_vector_size(cache->indexes); ++i) { - fts_index_cache_t* index_cache; - index_cache = static_cast<fts_index_cache_t*>( - ib_vector_get(cache->indexes, i)); - if (index_cache->index->index_fts_syncing == true) { - index_cache->index->index_fts_syncing = false; - } + static_cast<fts_index_cache_t*>( + ib_vector_get(cache->indexes, i)) + ->index->index_fts_syncing = false; } sync->interrupted = false; @@ -4760,9 +4734,17 @@ fts_process_token( t_str.f_str = static_cast<byte*>( mem_heap_alloc(heap, t_str.f_len)); - newlen = innobase_fts_casedn_str( - doc->charset, (char*) str.f_str, str.f_len, - (char*) t_str.f_str, t_str.f_len); + /* For binary collations, a case sensitive search is + performed. Hence don't convert to lower case. */ + if (my_binary_compare(result_doc->charset)) { + memcpy(t_str.f_str, str.f_str, str.f_len); + t_str.f_str[str.f_len]= 0; + newlen= str.f_len; + } else { + newlen = innobase_fts_casedn_str( + doc->charset, (char*) str.f_str, str.f_len, + (char*) t_str.f_str, t_str.f_len); + } t_str.f_len = newlen; t_str.f_str[newlen] = 0; @@ -4817,8 +4799,9 @@ fts_tokenize_document( ut_a(!doc->tokens); ut_a(doc->charset); - doc->tokens = rbt_create_arg_cmp( - sizeof(fts_token_t), innobase_fts_text_cmp, (void*) doc->charset); + doc->tokens = rbt_create_arg_cmp(sizeof(fts_token_t), + innobase_fts_text_cmp, + (void*) doc->charset); for (ulint i = 0; i < doc->text.f_len; i += inc) { inc = fts_process_token(doc, result, i, 0); @@ -4952,7 +4935,7 @@ fts_init_doc_id( fts_init_index((dict_table_t*) table, TRUE); } - table->fts->fts_status |= ADDED_TABLE_SYNCED; + table->fts->added_synced = true; table->fts->cache->first_doc_id = max_doc_id; @@ -5009,6 +4992,7 @@ fts_get_rows_count( que_t* graph; dberr_t error; ulint count = 0; + char table_name[MAX_FULL_NAME_LEN]; trx = trx_allocate_for_background(); @@ -5018,13 +5002,16 @@ fts_get_rows_count( pars_info_bind_function(info, "my_func", fts_read_ulint, &count); + fts_get_table_name(fts_table, table_name); + pars_info_bind_id(info, true, "table_name", table_name); + graph = fts_parse_sql( fts_table, info, "DECLARE FUNCTION my_func;\n" "DECLARE CURSOR c IS" " SELECT COUNT(*) " - " FROM \"%s\";\n" + " FROM $table_name;\n" "BEGIN\n" "\n" "OPEN c;\n" @@ -5402,69 +5389,6 @@ fts_cache_append_deleted_doc_ids( } /*********************************************************************//** -Wait for the background thread to start. We poll to detect change -of state, which is acceptable, since the wait should happen only -once during startup. -@return true if the thread started else FALSE (i.e timed out) */ -UNIV_INTERN -ibool -fts_wait_for_background_thread_to_start( -/*====================================*/ - dict_table_t* table, /*!< in: table to which the thread - is attached */ - ulint max_wait) /*!< in: time in microseconds, if - set to 0 then it disables - timeout checking */ -{ - ulint count = 0; - ibool done = FALSE; - - ut_a(max_wait == 0 || max_wait >= FTS_MAX_BACKGROUND_THREAD_WAIT); - - for (;;) { - fts_t* fts = table->fts; - - mutex_enter(&fts->bg_threads_mutex); - - if (fts->fts_status & BG_THREAD_READY) { - - done = TRUE; - } - - mutex_exit(&fts->bg_threads_mutex); - - if (!done) { - os_thread_sleep(FTS_MAX_BACKGROUND_THREAD_WAIT); - - if (max_wait > 0) { - - max_wait -= FTS_MAX_BACKGROUND_THREAD_WAIT; - - /* We ignore the residual value. */ - if (max_wait < FTS_MAX_BACKGROUND_THREAD_WAIT) { - break; - } - } - - ++count; - } else { - break; - } - - if (count >= FTS_BACKGROUND_THREAD_WAIT_COUNT) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Error the background thread " - "for the FTS table %s refuses to start\n", - table->name); - - count = 0; - } - } - - return(done); -} - -/*********************************************************************//** Add the FTS document id hidden column. */ UNIV_INTERN void @@ -5605,42 +5529,6 @@ fts_free( } /*********************************************************************//** -Signal FTS threads to initiate shutdown. */ -UNIV_INTERN -void -fts_start_shutdown( -/*===============*/ - dict_table_t* table, /*!< in: table with FTS indexes */ - fts_t* fts) /*!< in: fts instance that needs - to be informed about shutdown */ -{ - mutex_enter(&fts->bg_threads_mutex); - - fts->fts_status |= BG_THREAD_STOP; - - mutex_exit(&fts->bg_threads_mutex); - -} - -/*********************************************************************//** -Wait for FTS threads to shutdown. */ -UNIV_INTERN -void -fts_shutdown( -/*=========*/ - dict_table_t* table, /*!< in: table with FTS indexes */ - fts_t* fts) /*!< in: fts instance to shutdown */ -{ - mutex_enter(&fts->bg_threads_mutex); - - ut_a(fts->fts_status & BG_THREAD_STOP); - - dict_table_wait_for_bg_threads_to_exit(table, 20000); - - mutex_exit(&fts->bg_threads_mutex); -} - -/*********************************************************************//** Take a FTS savepoint. */ UNIV_INLINE void @@ -6233,7 +6121,7 @@ fts_rename_one_aux_table_to_hex_format( { const char* ptr; fts_table_t fts_table; - char* new_name; + char new_name[MAX_FULL_NAME_LEN]; dberr_t error; ptr = strchr(aux_table->name, '/'); @@ -6274,12 +6162,11 @@ fts_rename_one_aux_table_to_hex_format( ut_a(fts_table.suffix != NULL); - fts_table.parent = parent_table->name; fts_table.table_id = aux_table->parent_id; fts_table.index_id = aux_table->index_id; fts_table.table = parent_table; - new_name = fts_get_table_name(&fts_table); + fts_get_table_name(&fts_table, new_name); ut_ad(strcmp(new_name, aux_table->name) != 0); if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) { @@ -6300,8 +6187,6 @@ fts_rename_one_aux_table_to_hex_format( aux_table->name, new_name); } - mem_free(new_name); - return (error); } @@ -7657,7 +7542,7 @@ fts_init_index( } rw_lock_x_unlock(&cache->init_lock); - if (table->fts->fts_status & ADDED_TABLE_SYNCED) { + if (table->fts->added_synced) { goto func_exit; } @@ -7699,7 +7584,7 @@ fts_init_index( } } - table->fts->fts_status |= ADDED_TABLE_SYNCED; + table->fts->added_synced = true; fts_get_docs_clear(cache->get_docs); |