diff options
-rw-r--r-- | mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result | 10 | ||||
-rw-r--r-- | mysql-test/suite/innodb_fts/r/innodb_ft_aux_table.result | 116 | ||||
-rw-r--r-- | mysql-test/suite/innodb_fts/t/innodb_ft_aux_table.opt | 6 | ||||
-rw-r--r-- | mysql-test/suite/innodb_fts/t/innodb_ft_aux_table.test | 43 | ||||
-rw-r--r-- | storage/innobase/fts/fts0fts.cc | 5 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 123 | ||||
-rw-r--r-- | storage/innobase/handler/i_s.cc | 103 | ||||
-rw-r--r-- | storage/innobase/handler/i_s.h | 6 | ||||
-rw-r--r-- | storage/innobase/include/fts0fts.h | 5 | ||||
-rw-r--r-- | storage/xtradb/fts/fts0fts.cc | 5 | ||||
-rw-r--r-- | storage/xtradb/handler/ha_innodb.cc | 123 | ||||
-rw-r--r-- | storage/xtradb/handler/i_s.cc | 103 | ||||
-rw-r--r-- | storage/xtradb/handler/i_s.h | 6 | ||||
-rw-r--r-- | storage/xtradb/include/fts0fts.h | 5 |
14 files changed, 341 insertions, 318 deletions
diff --git a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result index 65e063979c4..285c1a35709 100644 --- a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result +++ b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result @@ -319,14 +319,24 @@ the www select * from information_schema.innodb_ft_deleted; DOC_ID +Warnings: +Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_ft_deleted but the InnoDB storage engine is not installed select * from information_schema.innodb_ft_being_deleted; DOC_ID +Warnings: +Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_ft_being_deleted but the InnoDB storage engine is not installed select * from information_schema.innodb_ft_index_cache; WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +Warnings: +Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_ft_index_cache but the InnoDB storage engine is not installed select * from information_schema.innodb_ft_index_table; WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +Warnings: +Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_ft_index_table but the InnoDB storage engine is not installed select * from information_schema.innodb_ft_config; KEY VALUE +Warnings: +Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_ft_config but the InnoDB storage engine is not installed select * from information_schema.innodb_buffer_page; POOL_ID BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK Warnings: diff --git a/mysql-test/suite/innodb_fts/r/innodb_ft_aux_table.result b/mysql-test/suite/innodb_fts/r/innodb_ft_aux_table.result new file mode 100644 index 00000000000..cb233a466a5 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/innodb_ft_aux_table.result @@ -0,0 +1,116 @@ +CREATE TABLE t1 (v VARCHAR(100), FULLTEXT INDEX (v)) ENGINE=InnoDB; +insert into t1 VALUES('First record'),('Second record'),('Third record'); +SET @save_ft_aux_table = @@GLOBAL.innodb_ft_aux_table; +SET GLOBAL innodb_ft_aux_table = 'test/t0'; +ERROR 42000: Variable 'innodb_ft_aux_table' can't be set to the value of 'test/t0' +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD; +value +a +about +an +are +as +at +be +by +com +de +en +for +from +how +i +in +is +it +la +of +on +or +that +the +this +to +was +what +when +where +who +will +with +und +the +www +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED; +DOC_ID +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED; +DOC_ID +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG; +KEY VALUE +SET GLOBAL innodb_ft_aux_table = 'test/t1'; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED; +DOC_ID +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED; +DOC_ID +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +first 1 1 1 1 0 +record 1 3 3 1 6 +record 1 3 3 2 7 +record 1 3 3 3 6 +second 2 2 1 2 0 +third 3 3 1 3 0 +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG; +KEY VALUE +optimize_checkpoint_limit 180 +synced_doc_id 0 +stopword_table_name +use_stopword 1 +SELECT @@GLOBAL.innodb_ft_aux_table; +@@GLOBAL.innodb_ft_aux_table +test/t1 +RENAME TABLE t1 TO t2; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED; +DOC_ID +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED; +DOC_ID +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +first 1 1 1 1 0 +record 1 3 3 1 6 +record 1 3 3 2 7 +record 1 3 3 3 6 +second 2 2 1 2 0 +third 3 3 1 3 0 +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG; +KEY VALUE +optimize_checkpoint_limit 180 +synced_doc_id 0 +stopword_table_name +use_stopword 1 +SELECT @@GLOBAL.innodb_ft_aux_table; +@@GLOBAL.innodb_ft_aux_table +test/t1 +DROP TABLE t2; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED; +DOC_ID +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED; +DOC_ID +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG; +KEY VALUE +SELECT @@GLOBAL.innodb_ft_aux_table; +@@GLOBAL.innodb_ft_aux_table +test/t1 +SET GLOBAL innodb_ft_aux_table = @save_ft_aux_table; diff --git a/mysql-test/suite/innodb_fts/t/innodb_ft_aux_table.opt b/mysql-test/suite/innodb_fts/t/innodb_ft_aux_table.opt new file mode 100644 index 00000000000..f85581275ed --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/innodb_ft_aux_table.opt @@ -0,0 +1,6 @@ +--innodb_ft_default_stopword +--innodb_ft_deleted +--innodb_ft_being_deleted +--innodb_ft_index_cache +--innodb_ft_index_table +--innodb_ft_config diff --git a/mysql-test/suite/innodb_fts/t/innodb_ft_aux_table.test b/mysql-test/suite/innodb_fts/t/innodb_ft_aux_table.test new file mode 100644 index 00000000000..48964aef4fd --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/innodb_ft_aux_table.test @@ -0,0 +1,43 @@ +--source include/have_innodb.inc + +CREATE TABLE t1 (v VARCHAR(100), FULLTEXT INDEX (v)) ENGINE=InnoDB; + +insert into t1 VALUES('First record'),('Second record'),('Third record'); + +SET @save_ft_aux_table = @@GLOBAL.innodb_ft_aux_table; + +connect (con1,localhost,root,,); +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL innodb_ft_aux_table = 'test/t0'; +connection default; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG; +connection con1; +SET GLOBAL innodb_ft_aux_table = 'test/t1'; +disconnect con1; +connection default; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG; +SELECT @@GLOBAL.innodb_ft_aux_table; +RENAME TABLE t1 TO t2; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG; +SELECT @@GLOBAL.innodb_ft_aux_table; +DROP TABLE t2; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DELETED; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; +SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_CONFIG; +SELECT @@GLOBAL.innodb_ft_aux_table; +SET GLOBAL innodb_ft_aux_table = @save_ft_aux_table; diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index bfb469b1e2d..beed1b99d6c 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -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: diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 8b007bb0b38..cb6ec20e0d6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -17118,98 +17118,36 @@ innodb_stopword_table_validate( return(ret); } -/*************************************************************//** -Check whether valid argument given to "innodb_fts_internal_tbl_name" -This function is registered as a callback with MySQL. -@return 0 for valid stopword table */ -static -int -innodb_internal_table_validate( -/*===========================*/ - THD* thd, /*!< in: thread handle */ - struct st_mysql_sys_var* var, /*!< in: pointer to system - variable */ - void* save, /*!< out: immediate result - for update function */ - struct st_mysql_value* value) /*!< in: incoming string */ -{ - const char* table_name; - char buff[STRING_BUFFER_USUAL_SIZE]; - int len = sizeof(buff); - int ret = 1; - dict_table_t* user_table; - - ut_a(save != NULL); - ut_a(value != NULL); - - table_name = value->val_str(value, buff, &len); - - if (!table_name) { - *static_cast<const char**>(save) = NULL; - return(0); - } - - user_table = dict_table_open_on_name( - table_name, FALSE, TRUE, DICT_ERR_IGNORE_NONE); - - if (user_table) { - if (dict_table_has_fts_index(user_table)) { - *static_cast<const char**>(save) = table_name; - ret = 0; +/** The latest assigned innodb_ft_aux_table name */ +static char* innodb_ft_aux_table; + +/** Update innodb_ft_aux_table_id on SET GLOBAL innodb_ft_aux_table. +@param[out] save new value of innodb_ft_aux_table +@param[in] value user-specified value */ +static int innodb_ft_aux_table_validate(THD*, st_mysql_sys_var*, + void* save, st_mysql_value* value) +{ + char buf[STRING_BUFFER_USUAL_SIZE]; + int len = sizeof buf; + + if (const char* table_name = value->val_str(value, buf, &len)) { + if (dict_table_t* table = dict_table_open_on_name( + table_name, FALSE, TRUE, DICT_ERR_IGNORE_NONE)) { + const table_id_t id = dict_table_has_fts_index(table) + ? table->id : 0; + dict_table_close(table, FALSE, FALSE); + if (id) { + innodb_ft_aux_table_id = id; + *static_cast<const char**>(save) = table_name; + return 0; + } } - dict_table_close(user_table, FALSE, TRUE); - - DBUG_EXECUTE_IF("innodb_evict_autoinc_table", - mutex_enter(&dict_sys->mutex); - dict_table_remove_from_cache_low(user_table, TRUE); - mutex_exit(&dict_sys->mutex); - ); - } - - return(ret); -} - -/****************************************************************//** -Update global variable "fts_internal_tbl_name" with the "saved" -stopword table name value. This function is registered as a callback -with MySQL. */ -static -void -innodb_internal_table_update( -/*=========================*/ - THD* thd, /*!< in: thread handle */ - struct st_mysql_sys_var* var, /*!< in: pointer to - system variable */ - void* var_ptr,/*!< out: where the - formal string goes */ - const void* save) /*!< in: immediate result - from check function */ -{ - const char* table_name; - char* old; - - ut_a(save != NULL); - ut_a(var_ptr != NULL); - - table_name = *static_cast<const char*const*>(save); - old = *(char**) var_ptr; - - if (table_name) { - *(char**) var_ptr = my_strdup(table_name, MYF(0)); - } else { - *(char**) var_ptr = NULL; - } - - if (old) { - my_free(old); - } - - fts_internal_tbl_name2 = *(char**) var_ptr; - if (fts_internal_tbl_name2 == NULL) { - fts_internal_tbl_name = const_cast<char*>("default"); + return 1; } else { - fts_internal_tbl_name = fts_internal_tbl_name2; + *static_cast<char**>(save) = NULL; + innodb_ft_aux_table_id = 0; + return 0; } } @@ -19476,11 +19414,10 @@ static MYSQL_SYSVAR_BOOL(disable_sort_file_cache, srv_disable_sort_file_cache, "Whether to disable OS system file cache for sort I/O", NULL, NULL, FALSE); -static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name2, - PLUGIN_VAR_NOCMDARG, +static MYSQL_SYSVAR_STR(ft_aux_table, innodb_ft_aux_table, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_MEMALLOC, "FTS internal auxiliary table to be checked", - innodb_internal_table_validate, - innodb_internal_table_update, NULL); + innodb_ft_aux_table_validate, NULL, NULL); static MYSQL_SYSVAR_ULONG(ft_cache_size, fts_max_cache_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 9eae8ded633..2729a755570 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -64,6 +64,9 @@ Modified Dec 29, 2014 Jan Lindström (Added sys_semaphore_waits) #include "fil0fil.h" #include "fil0crypt.h" +/** The latest successfully looked up innodb_fts_aux_table */ +UNIV_INTERN table_id_t innodb_ft_aux_table_id; + /** structure associates a name string with a file page type and/or buffer page state. */ struct buf_page_desc_t{ @@ -2934,25 +2937,21 @@ i_s_fts_deleted_generic_fill( DBUG_RETURN(0); } - if (!fts_internal_tbl_name) { - DBUG_RETURN(0); - } + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - /* Prevent DDL to drop fts aux tables. */ + /* Prevent DROP of the internal tables for fulltext indexes. + FIXME: acquire DDL-blocking MDL on the user table name! */ rw_lock_s_lock(&dict_operation_lock); - user_table = dict_table_open_on_name( - fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + user_table = dict_table_open_on_id( + innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL); if (!user_table) { rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); } else if (!dict_table_has_fts_index(user_table)) { dict_table_close(user_table, FALSE, FALSE); - rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); } @@ -2967,6 +2966,12 @@ i_s_fts_deleted_generic_fill( fts_table_fetch_doc_ids(trx, &fts_table, deleted); + dict_table_close(user_table, FALSE, FALSE); + + rw_lock_s_unlock(&dict_operation_lock); + + trx_free_for_background(trx); + fields = table->field; int ret = 0; @@ -2981,14 +2986,8 @@ i_s_fts_deleted_generic_fill( BREAK_IF(ret = schema_table_store_record(thd, table)); } - trx_free_for_background(trx); - fts_doc_ids_free(deleted); - dict_table_close(user_table, FALSE, FALSE); - - rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(ret); } @@ -3348,32 +3347,33 @@ i_s_fts_index_cache_fill( DBUG_RETURN(0); } - if (!fts_internal_tbl_name) { - DBUG_RETURN(0); - } + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - user_table = dict_table_open_on_name( - fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + /* Prevent DROP of the internal tables for fulltext indexes. + FIXME: acquire DDL-blocking MDL on the user table name! */ + rw_lock_s_lock(&dict_operation_lock); + + user_table = dict_table_open_on_id( + innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL); if (!user_table) { +no_fts: + rw_lock_s_unlock(&dict_operation_lock); DBUG_RETURN(0); } - if (user_table->fts == NULL || user_table->fts->cache == NULL) { + if (!user_table->fts || !user_table->fts->cache) { dict_table_close(user_table, FALSE, FALSE); - - DBUG_RETURN(0); + goto no_fts; } cache = user_table->fts->cache; - ut_a(cache); - int ret = 0; fts_string_t conv_str; - conv_str.f_len = system_charset_info->mbmaxlen - * FTS_MAX_WORD_LEN_IN_CHAR; - conv_str.f_str = static_cast<byte*>(ut_malloc(conv_str.f_len)); + byte word[HA_FT_MAXBYTELEN + 1]; + conv_str.f_len = sizeof word; + conv_str.f_str = word; for (ulint i = 0; i < ib_vector_size(cache->indexes); i++) { fts_index_cache_t* index_cache; @@ -3385,9 +3385,8 @@ i_s_fts_index_cache_fill( index_cache, thd, &conv_str, tables)); } - ut_free(conv_str.f_str); - dict_table_close(user_table, FALSE, FALSE); + rw_lock_s_unlock(&dict_operation_lock); DBUG_RETURN(ret); } @@ -3801,19 +3800,17 @@ i_s_fts_index_table_fill( DBUG_RETURN(0); } - if (!fts_internal_tbl_name) { - DBUG_RETURN(0); - } + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - /* Prevent DDL to drop fts aux tables. */ + /* Prevent DROP of the internal tables for fulltext indexes. + FIXME: acquire DDL-blocking MDL on the user table name! */ rw_lock_s_lock(&dict_operation_lock); - user_table = dict_table_open_on_name( - fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + user_table = dict_table_open_on_id( + innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL); if (!user_table) { rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); } @@ -3966,32 +3963,28 @@ i_s_fts_config_fill( DBUG_RETURN(0); } - if (!fts_internal_tbl_name) { - DBUG_RETURN(0); - } - - DEBUG_SYNC_C("i_s_fts_config_fille_check"); - - fields = table->field; + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - /* Prevent DDL to drop fts aux tables. */ + /* Prevent DROP of the internal tables for fulltext indexes. + FIXME: acquire DDL-blocking MDL on the user table name! */ rw_lock_s_lock(&dict_operation_lock); - user_table = dict_table_open_on_name( - fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + user_table = dict_table_open_on_id( + innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL); if (!user_table) { +no_fts: rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); - } else if (!dict_table_has_fts_index(user_table)) { - dict_table_close(user_table, FALSE, FALSE); - - rw_lock_s_unlock(&dict_operation_lock); + } - DBUG_RETURN(0); + if (!dict_table_has_fts_index(user_table)) { + dict_table_close(user_table, FALSE, FALSE); + goto no_fts; } + fields = table->field; + trx = trx_allocate_for_background(); trx->op_info = "Select for FTS CONFIG TABLE"; @@ -4043,12 +4036,12 @@ i_s_fts_config_fill( fts_sql_commit(trx); - trx_free_for_background(trx); - dict_table_close(user_table, FALSE, FALSE); rw_lock_s_unlock(&dict_operation_lock); + trx_free_for_background(trx); + DBUG_RETURN(ret); } diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h index 596774a0b50..9dc025fa649 100644 --- a/storage/innobase/handler/i_s.h +++ b/storage/innobase/handler/i_s.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved. -Copyrigth (c) 2014, 2017, MariaDB Corporation. +Copyrigth (c) 2014, 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 @@ -27,6 +27,7 @@ Modified Dec 29, 2014 Jan Lindström #ifndef i_s_h #define i_s_h +#include "dict0types.h" const char plugin_author[] = "Oracle Corporation"; const char maria_plugin_author[] = "MariaDB Corporation"; @@ -64,6 +65,9 @@ extern struct st_maria_plugin i_s_innodb_tablespaces_encryption; extern struct st_maria_plugin i_s_innodb_tablespaces_scrubbing; extern struct st_maria_plugin i_s_innodb_sys_semaphore_waits; +/** The latest successfully looked up innodb_fts_aux_table */ +extern table_id_t innodb_ft_aux_table_id; + /** maximum number of buffer page info we would cache. */ #define MAX_BUF_INFO_CACHED 10000 diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index 19a1058dc0c..a1fab659732 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -367,11 +367,6 @@ extern bool fts_need_sync; /** Maximum possible Fulltext word length (in characters) */ #define FTS_MAX_WORD_LEN_IN_CHAR HA_FT_MAXCHARLEN -/** Variable specifying the table that has Fulltext index to display its -content through information schema table */ -extern char* fts_internal_tbl_name; -extern char* fts_internal_tbl_name2; - #define fts_que_graph_free(graph) \ do { \ mutex_enter(&dict_sys->mutex); \ diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index bfb469b1e2d..beed1b99d6c 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/fts/fts0fts.cc @@ -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: diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index df925327c1c..aa17eb6a5ea 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -17839,98 +17839,36 @@ innodb_stopword_table_validate( return(ret); } -/*************************************************************//** -Check whether valid argument given to "innodb_fts_internal_tbl_name" -This function is registered as a callback with MySQL. -@return 0 for valid stopword table */ -static -int -innodb_internal_table_validate( -/*===========================*/ - THD* thd, /*!< in: thread handle */ - struct st_mysql_sys_var* var, /*!< in: pointer to system - variable */ - void* save, /*!< out: immediate result - for update function */ - struct st_mysql_value* value) /*!< in: incoming string */ -{ - const char* table_name; - char buff[STRING_BUFFER_USUAL_SIZE]; - int len = sizeof(buff); - int ret = 1; - dict_table_t* user_table; - - ut_a(save != NULL); - ut_a(value != NULL); - - table_name = value->val_str(value, buff, &len); - - if (!table_name) { - *static_cast<const char**>(save) = NULL; - return(0); - } - - user_table = dict_table_open_on_name( - table_name, FALSE, TRUE, DICT_ERR_IGNORE_NONE); - - if (user_table) { - if (dict_table_has_fts_index(user_table)) { - *static_cast<const char**>(save) = table_name; - ret = 0; +/** The latest assigned innodb_ft_aux_table name */ +static char* innodb_ft_aux_table; + +/** Update innodb_ft_aux_table_id on SET GLOBAL innodb_ft_aux_table. +@param[out] save new value of innodb_ft_aux_table +@param[in] value user-specified value */ +static int innodb_ft_aux_table_validate(THD*, st_mysql_sys_var*, + void* save, st_mysql_value* value) +{ + char buf[STRING_BUFFER_USUAL_SIZE]; + int len = sizeof buf; + + if (const char* table_name = value->val_str(value, buf, &len)) { + if (dict_table_t* table = dict_table_open_on_name( + table_name, FALSE, TRUE, DICT_ERR_IGNORE_NONE)) { + const table_id_t id = dict_table_has_fts_index(table) + ? table->id : 0; + dict_table_close(table, FALSE, FALSE); + if (id) { + innodb_ft_aux_table_id = id; + *static_cast<const char**>(save) = table_name; + return 0; + } } - dict_table_close(user_table, FALSE, TRUE); - - DBUG_EXECUTE_IF("innodb_evict_autoinc_table", - mutex_enter(&dict_sys->mutex); - dict_table_remove_from_cache_low(user_table, TRUE); - mutex_exit(&dict_sys->mutex); - ); - } - - return(ret); -} - -/****************************************************************//** -Update global variable "fts_internal_tbl_name" with the "saved" -stopword table name value. This function is registered as a callback -with MySQL. */ -static -void -innodb_internal_table_update( -/*=========================*/ - THD* thd, /*!< in: thread handle */ - struct st_mysql_sys_var* var, /*!< in: pointer to - system variable */ - void* var_ptr,/*!< out: where the - formal string goes */ - const void* save) /*!< in: immediate result - from check function */ -{ - const char* table_name; - char* old; - - ut_a(save != NULL); - ut_a(var_ptr != NULL); - - table_name = *static_cast<const char*const*>(save); - old = *(char**) var_ptr; - - if (table_name) { - *(char**) var_ptr = my_strdup(table_name, MYF(0)); - } else { - *(char**) var_ptr = NULL; - } - - if (old) { - my_free(old); - } - - fts_internal_tbl_name2 = *(char**) var_ptr; - if (fts_internal_tbl_name2 == NULL) { - fts_internal_tbl_name = const_cast<char*>("default"); + return 1; } else { - fts_internal_tbl_name = fts_internal_tbl_name2; + *static_cast<char**>(save) = NULL; + innodb_ft_aux_table_id = 0; + return 0; } } @@ -20693,11 +20631,10 @@ static MYSQL_SYSVAR_BOOL(disable_sort_file_cache, srv_disable_sort_file_cache, "Whether to disable OS system file cache for sort I/O", NULL, NULL, FALSE); -static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name2, - PLUGIN_VAR_NOCMDARG, +static MYSQL_SYSVAR_STR(ft_aux_table, innodb_ft_aux_table, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_MEMALLOC, "FTS internal auxiliary table to be checked", - innodb_internal_table_validate, - innodb_internal_table_update, NULL); + innodb_ft_aux_table_validate, NULL, NULL); static MYSQL_SYSVAR_ULONG(ft_cache_size, fts_max_cache_size, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc index e1b5b1b700f..8eb53502da8 100644 --- a/storage/xtradb/handler/i_s.cc +++ b/storage/xtradb/handler/i_s.cc @@ -75,6 +75,9 @@ Modified Dec 29, 2014 Jan Lindström (Added sys_semaphore_waits) #include "fil0fil.h" #include "fil0crypt.h" +/** The latest successfully looked up innodb_fts_aux_table */ +UNIV_INTERN table_id_t innodb_ft_aux_table_id; + /** structure associates a name string with a file page type and/or buffer page state. */ struct buf_page_desc_t{ @@ -2928,25 +2931,21 @@ i_s_fts_deleted_generic_fill( DBUG_RETURN(0); } - if (!fts_internal_tbl_name) { - DBUG_RETURN(0); - } + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - /* Prevent DDL to drop fts aux tables. */ + /* Prevent DROP of the internal tables for fulltext indexes. + FIXME: acquire DDL-blocking MDL on the user table name! */ rw_lock_s_lock(&dict_operation_lock); - user_table = dict_table_open_on_name( - fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + user_table = dict_table_open_on_id( + innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL); if (!user_table) { rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); } else if (!dict_table_has_fts_index(user_table)) { dict_table_close(user_table, FALSE, FALSE); - rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); } @@ -2961,6 +2960,12 @@ i_s_fts_deleted_generic_fill( fts_table_fetch_doc_ids(trx, &fts_table, deleted); + dict_table_close(user_table, FALSE, FALSE); + + rw_lock_s_unlock(&dict_operation_lock); + + trx_free_for_background(trx); + fields = table->field; int ret = 0; @@ -2975,14 +2980,8 @@ i_s_fts_deleted_generic_fill( BREAK_IF(ret = schema_table_store_record(thd, table)); } - trx_free_for_background(trx); - fts_doc_ids_free(deleted); - dict_table_close(user_table, FALSE, FALSE); - - rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(ret); } @@ -3340,32 +3339,33 @@ i_s_fts_index_cache_fill( DBUG_RETURN(0); } - if (!fts_internal_tbl_name) { - DBUG_RETURN(0); - } + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - user_table = dict_table_open_on_name( - fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + /* Prevent DROP of the internal tables for fulltext indexes. + FIXME: acquire DDL-blocking MDL on the user table name! */ + rw_lock_s_lock(&dict_operation_lock); + + user_table = dict_table_open_on_id( + innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL); if (!user_table) { +no_fts: + rw_lock_s_unlock(&dict_operation_lock); DBUG_RETURN(0); } - if (user_table->fts == NULL || user_table->fts->cache == NULL) { + if (!user_table->fts || !user_table->fts->cache) { dict_table_close(user_table, FALSE, FALSE); - - DBUG_RETURN(0); + goto no_fts; } cache = user_table->fts->cache; - ut_a(cache); - int ret = 0; fts_string_t conv_str; - conv_str.f_len = system_charset_info->mbmaxlen - * FTS_MAX_WORD_LEN_IN_CHAR; - conv_str.f_str = static_cast<byte*>(ut_malloc(conv_str.f_len)); + byte word[HA_FT_MAXBYTELEN + 1]; + conv_str.f_len = sizeof word; + conv_str.f_str = word; for (ulint i = 0; i < ib_vector_size(cache->indexes); i++) { fts_index_cache_t* index_cache; @@ -3377,9 +3377,8 @@ i_s_fts_index_cache_fill( index_cache, thd, &conv_str, tables)); } - ut_free(conv_str.f_str); - dict_table_close(user_table, FALSE, FALSE); + rw_lock_s_unlock(&dict_operation_lock); DBUG_RETURN(ret); } @@ -3792,19 +3791,17 @@ i_s_fts_index_table_fill( DBUG_RETURN(0); } - if (!fts_internal_tbl_name) { - DBUG_RETURN(0); - } + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - /* Prevent DDL to drop fts aux tables. */ + /* Prevent DROP of the internal tables for fulltext indexes. + FIXME: acquire DDL-blocking MDL on the user table name! */ rw_lock_s_lock(&dict_operation_lock); - user_table = dict_table_open_on_name( - fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + user_table = dict_table_open_on_id( + innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL); if (!user_table) { rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); } @@ -3956,32 +3953,28 @@ i_s_fts_config_fill( DBUG_RETURN(0); } - if (!fts_internal_tbl_name) { - DBUG_RETURN(0); - } - - DEBUG_SYNC_C("i_s_fts_config_fille_check"); - - fields = table->field; + RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - /* Prevent DDL to drop fts aux tables. */ + /* Prevent DROP of the internal tables for fulltext indexes. + FIXME: acquire DDL-blocking MDL on the user table name! */ rw_lock_s_lock(&dict_operation_lock); - user_table = dict_table_open_on_name( - fts_internal_tbl_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); + user_table = dict_table_open_on_id( + innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL); if (!user_table) { +no_fts: rw_lock_s_unlock(&dict_operation_lock); - DBUG_RETURN(0); - } else if (!dict_table_has_fts_index(user_table)) { - dict_table_close(user_table, FALSE, FALSE); - - rw_lock_s_unlock(&dict_operation_lock); + } - DBUG_RETURN(0); + if (!dict_table_has_fts_index(user_table)) { + dict_table_close(user_table, FALSE, FALSE); + goto no_fts; } + fields = table->field; + trx = trx_allocate_for_background(); trx->op_info = "Select for FTS CONFIG TABLE"; @@ -4033,12 +4026,12 @@ i_s_fts_config_fill( fts_sql_commit(trx); - trx_free_for_background(trx); - dict_table_close(user_table, FALSE, FALSE); rw_lock_s_unlock(&dict_operation_lock); + trx_free_for_background(trx); + DBUG_RETURN(ret); } diff --git a/storage/xtradb/handler/i_s.h b/storage/xtradb/handler/i_s.h index 0353e426365..81d6977954d 100644 --- a/storage/xtradb/handler/i_s.h +++ b/storage/xtradb/handler/i_s.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved. -Copyrigth (c) 2014, 2017, MariaDB Corporation. +Copyrigth (c) 2014, 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 @@ -27,6 +27,7 @@ Modified Dec 29, 2014 Jan Lindström #ifndef i_s_h #define i_s_h +#include "dict0types.h" const char plugin_author[] = "Oracle Corporation"; const char maria_plugin_author[] = "MariaDB Corporation"; @@ -69,6 +70,9 @@ extern struct st_maria_plugin i_s_innodb_tablespaces_scrubbing; extern struct st_mysql_plugin i_s_innodb_sys_semaphore_waits; extern struct st_mysql_plugin i_s_innodb_changed_page_bitmaps; +/** The latest successfully looked up innodb_fts_aux_table */ +extern table_id_t innodb_ft_aux_table_id; + /** maximum number of buffer page info we would cache. */ #define MAX_BUF_INFO_CACHED 10000 diff --git a/storage/xtradb/include/fts0fts.h b/storage/xtradb/include/fts0fts.h index 19a1058dc0c..a1fab659732 100644 --- a/storage/xtradb/include/fts0fts.h +++ b/storage/xtradb/include/fts0fts.h @@ -367,11 +367,6 @@ extern bool fts_need_sync; /** Maximum possible Fulltext word length (in characters) */ #define FTS_MAX_WORD_LEN_IN_CHAR HA_FT_MAXCHARLEN -/** Variable specifying the table that has Fulltext index to display its -content through information schema table */ -extern char* fts_internal_tbl_name; -extern char* fts_internal_tbl_name2; - #define fts_que_graph_free(graph) \ do { \ mutex_enter(&dict_sys->mutex); \ |