MDEV-18220: Backport some code from MariaDB 10.2

fts_get_table_name(): Output to a caller-allocated buffer.

fts_get_table_name_prefix(): Use the lower-overhead allocation
ut_malloc() instead of mem_alloc().

This is based on mysql/mysql-server@d1584b9f38
in MySQL 5.7.4.
This commit is contained in:
Marko Mäkelä 2019-05-09 09:31:30 +03:00
parent f92749ed36
commit f3718a112a
14 changed files with 612 additions and 536 deletions

View file

@ -85,6 +85,7 @@ fts_config_get_value(
que_t* graph;
dberr_t error;
ulint name_len = strlen(name);
char table_name[MAX_FULL_NAME_LEN];
info = pars_info_create();
@ -100,12 +101,14 @@ fts_config_get_value(
pars_info_bind_varchar_literal(info, "name", (byte*) name, name_len);
fts_table->suffix = "CONFIG";
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 value FROM \"%s\""
"DECLARE CURSOR c IS SELECT value FROM $table_name"
" WHERE key = :name;\n"
"BEGIN\n"
""
@ -212,6 +215,7 @@ fts_config_set_value(
undo_no_t undo_no;
undo_no_t n_rows_updated;
ulint name_len = strlen(name);
char table_name[MAX_FULL_NAME_LEN];
info = pars_info_create();
@ -220,10 +224,13 @@ fts_config_set_value(
value->f_str, value->f_len);
fts_table->suffix = "CONFIG";
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 UPDATE \"%s\" SET value = :value WHERE key = :name;");
"BEGIN UPDATE $table_name SET value = :value "
"WHERE key = :name;");
trx->op_info = "setting FTS config value";
@ -245,10 +252,13 @@ fts_config_set_value(
pars_info_bind_varchar_literal(
info, "value", value->f_str, value->f_len);
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\n"
"INSERT INTO \"%s\" VALUES(:name, :value);");
"INSERT INTO $table_name VALUES(:name, :value);");
trx->op_info = "inserting FTS config value";
@ -465,6 +475,7 @@ fts_config_increment_value(
que_t* graph = NULL;
ulint name_len = strlen(name);
pars_info_t* info = pars_info_create();
char table_name[MAX_FULL_NAME_LEN];
/* We set the length of value to the max bytes it can hold. This
information is used by the callback that reads the value.*/
@ -479,11 +490,13 @@ fts_config_increment_value(
info, "my_func", fts_config_fetch_value, &value);
fts_table->suffix = "CONFIG";
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 = :name FOR UPDATE;\n"
"BEGIN\n"
""

View file

@ -167,38 +167,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 +208,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 +221,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 +249,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
@ -1585,19 +1586,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);
err = fts_rename_one_aux_table(new_name, old_table_name, trx);
mem_free(old_table_name);
if (err != DB_SUCCESS) {
return(err);
}
@ -1616,12 +1615,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);
err = fts_rename_one_aux_table(
new_name, old_table_name, trx);
@ -1630,8 +1625,6 @@ fts_rename_aux_tables(
err = DB_DEADLOCK;
fts_sql_rollback(trx););
mem_free(old_table_name);
if (err != DB_SUCCESS) {
return(err);
}
@ -1659,11 +1652,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);
err = fts_drop_table(trx, table_name);
@ -1671,8 +1664,6 @@ fts_drop_common_tables(
if (err != DB_SUCCESS && err != DB_FAIL) {
error = err;
}
mem_free(table_name);
}
return(error);
@ -1698,11 +1689,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);
err = fts_drop_table(trx, table_name);
@ -1710,8 +1701,6 @@ fts_drop_index_split_tables(
if (err != DB_SUCCESS && err != DB_FAIL) {
error = err;
}
mem_free(table_name);
}
return(error);
@ -1748,11 +1737,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);
err = fts_drop_table(trx, table_name);
@ -1760,8 +1749,6 @@ fts_drop_index_tables(
if (err != DB_SUCCESS && err != DB_FAIL) {
error = err;
}
mem_free(table_name);
}
#endif /* FTS_DOC_STATS_DEBUG */
@ -1830,26 +1817,6 @@ fts_drop_tables(
return(error);
}
/*********************************************************************//**
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
@ -1864,12 +1831,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);
@ -1881,9 +1851,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]);
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);
@ -1895,9 +1875,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);
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);
@ -1965,13 +1950,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);
if (srv_file_per_table) {
flags2 = DICT_TF2_USE_TABLESPACE;
}
@ -2015,8 +2002,6 @@ fts_create_one_index_table(
"Fail to create FTS index table %s", table_name);
}
mem_free(table_name);
return(new_table);
}
@ -2039,7 +2024,9 @@ 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;
@ -2047,14 +2034,17 @@ fts_create_index_tables_low(
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);
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);
@ -2063,6 +2053,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. */
@ -2076,8 +2068,12 @@ fts_create_index_tables_low(
break;
}
fts_get_table_name(&fts_table, fts_name);
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);
@ -2701,6 +2697,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);
@ -2718,10 +2715,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"
""
@ -2814,6 +2814,7 @@ 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;
@ -2834,10 +2835,13 @@ fts_update_sync_doc_id(
pars_info_bind_varchar_literal(info, "doc_id", id, id_len);
fts_get_table_name(&fts_table, fts_name);
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);
@ -2984,6 +2988,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";
@ -2991,10 +2996,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);
@ -3813,11 +3821,15 @@ fts_write_node(
ib_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);
@ -3843,11 +3855,12 @@ 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);");
}
@ -3874,6 +3887,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);
@ -3889,10 +3903,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;
@ -4069,6 +4086,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;
@ -4091,10 +4109,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 (;;) {
@ -4216,6 +4239,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";
@ -4225,6 +4249,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);
@ -4235,7 +4261,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"
@ -4984,6 +5010,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();
@ -4993,13 +5020,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"
@ -6208,7 +6238,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, '/');
@ -6253,7 +6283,7 @@ fts_rename_one_aux_table_to_hex_format(
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) {
@ -6274,8 +6304,6 @@ fts_rename_one_aux_table_to_hex_format(
aux_table->name, new_name);
}
mem_free(new_name);
return (error);
}

View file

@ -226,27 +226,30 @@ static ulint FTS_ZIP_BLOCK_SIZE = 1024;
/** The amount of time optimizing in a single pass, in milliseconds. */
static ib_time_t fts_optimize_time_limit = 0;
/** It's defined in fts0fts.cc */
extern const char* fts_common_tables[];
/** SQL Statement for changing state of rows to be deleted from FTS Index. */
static const char* fts_init_delete_sql =
"BEGIN\n"
"\n"
"INSERT INTO \"%s_BEING_DELETED\"\n"
"SELECT doc_id FROM \"%s_DELETED\";\n"
"INSERT INTO $BEING_DELETED\n"
"SELECT doc_id FROM $DELETED;\n"
"\n"
"INSERT INTO \"%s_BEING_DELETED_CACHE\"\n"
"SELECT doc_id FROM \"%s_DELETED_CACHE\";\n";
"INSERT INTO $BEING_DELETED_CACHE\n"
"SELECT doc_id FROM $DELETED_CACHE;\n";
static const char* fts_delete_doc_ids_sql =
"BEGIN\n"
"\n"
"DELETE FROM \"%s_DELETED\" WHERE doc_id = :doc_id1;\n"
"DELETE FROM \"%s_DELETED_CACHE\" WHERE doc_id = :doc_id2;\n";
"DELETE FROM $DELETED WHERE doc_id = :doc_id1;\n"
"DELETE FROM $DELETED_CACHE WHERE doc_id = :doc_id2;\n";
static const char* fts_end_delete_sql =
"BEGIN\n"
"\n"
"DELETE FROM \"%s_BEING_DELETED\";\n"
"DELETE FROM \"%s_BEING_DELETED_CACHE\";\n";
"DELETE FROM $BEING_DELETED;\n"
"DELETE FROM $BEING_DELETED_CACHE;\n";
/**********************************************************************//**
Initialize fts_zip_t. */
@ -477,21 +480,17 @@ fts_index_fetch_nodes(
{
pars_info_t* info;
dberr_t error;
char table_name[MAX_FULL_NAME_LEN];
trx->op_info = "fetching FTS index nodes";
if (*graph) {
info = (*graph)->info;
} else {
info = pars_info_create();
}
pars_info_bind_function(info, "my_func", fetch->read_record, fetch);
pars_info_bind_varchar_literal(info, "word", word->f_str, word->f_len);
if (!*graph) {
ulint selected;
info = pars_info_create();
ut_a(fts_table->type == FTS_INDEX_TABLE);
selected = fts_select_index(fts_table->charset,
@ -499,6 +498,16 @@ fts_index_fetch_nodes(
fts_table->suffix = fts_get_suffix(selected);
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", fetch->read_record, fetch);
pars_info_bind_varchar_literal(info, "word", word->f_str, word->f_len);
if (!*graph) {
*graph = fts_parse_sql(
fts_table,
info,
@ -506,7 +515,7 @@ fts_index_fetch_nodes(
"DECLARE CURSOR c IS"
" SELECT word, doc_count, first_doc_id, last_doc_id, "
"ilist\n"
" FROM \"%s\"\n"
" FROM $table_name\n"
" WHERE word LIKE :word\n"
" ORDER BY first_doc_id;\n"
"BEGIN\n"
@ -806,6 +815,8 @@ fts_index_fetch_words(
fts_index_selector[selected].value;
selected++) {
char table_name[MAX_FULL_NAME_LEN];
optim->fts_index_table.suffix = fts_get_suffix(selected);
/* We've search all indexes. */
@ -821,13 +832,16 @@ fts_index_fetch_words(
pars_info_bind_varchar_literal(
info, "word", word->f_str, word->f_len);
fts_get_table_name(&optim->fts_index_table, table_name);
pars_info_bind_id(info, true, "table_name", table_name);
graph = fts_parse_sql(
&optim->fts_index_table,
info,
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR c IS"
" SELECT word\n"
" FROM \"%s\"\n"
" FROM $table_name\n"
" WHERE word > :word\n"
" ORDER BY word;\n"
"BEGIN\n"
@ -969,6 +983,7 @@ fts_table_fetch_doc_ids(
que_t* graph;
pars_info_t* info = pars_info_create();
ibool alloc_bk_trx = FALSE;
char table_name[MAX_FULL_NAME_LEN];
ut_a(fts_table->suffix != NULL);
ut_a(fts_table->type == FTS_COMMON_TABLE);
@ -982,12 +997,15 @@ fts_table_fetch_doc_ids(
pars_info_bind_function(info, "my_func", fts_fetch_doc_ids, doc_ids);
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 doc_id FROM \"%s\";\n"
" SELECT doc_id FROM $table_name;\n"
"BEGIN\n"
"\n"
"OPEN c;\n"
@ -1440,7 +1458,7 @@ fts_optimize_write_word(
que_t* graph;
ulint selected;
dberr_t error = DB_SUCCESS;
char* table_name = fts_get_table_name(fts_table);
char table_name[MAX_FULL_NAME_LEN];
info = pars_info_create();
@ -1458,11 +1476,13 @@ fts_optimize_write_word(
word->f_str, word->f_len);
fts_table->suffix = fts_get_suffix(selected);
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 DELETE FROM \"%s\" WHERE word = :word;");
"BEGIN DELETE FROM $table_name WHERE word = :word;");
error = fts_eval_sql(trx, graph);
@ -1476,8 +1496,6 @@ fts_optimize_write_word(
fts_que_graph_free(graph);
graph = NULL;
mem_free(table_name);
/* Even if the operation needs to be rolled back and redone,
we iterate over the nodes in order to free the ilist. */
for (i = 0; i < ib_vector_size(nodes); ++i) {
@ -1727,7 +1745,7 @@ fts_optimize_free(
fts_doc_ids_free(optim->to_delete);
fts_optimize_graph_free(&optim->graph);
mem_free(optim->name_prefix);
ut_free(optim->name_prefix);
/* This will free the heap from which optim itself was allocated. */
mem_heap_free(heap);
@ -2067,9 +2085,10 @@ fts_optimize_purge_deleted_doc_ids(
pars_info_t* info;
que_t* graph;
fts_update_t* update;
char* sql_str;
doc_id_t write_doc_id;
dberr_t error = DB_SUCCESS;
char deleted[MAX_FULL_NAME_LEN];
char deleted_cache[MAX_FULL_NAME_LEN];
info = pars_info_create();
@ -2086,14 +2105,17 @@ fts_optimize_purge_deleted_doc_ids(
fts_bind_doc_id(info, "doc_id1", &write_doc_id);
fts_bind_doc_id(info, "doc_id2", &write_doc_id);
/* Since we only replace the table_id and don't construct the full
name, we do substitution ourselves. Remember to free sql_str. */
sql_str = ut_strreplace(
fts_delete_doc_ids_sql, "%s", optim->name_prefix);
/* Make sure the following two names are consistent with the name
used in the fts_delete_doc_ids_sql */
optim->fts_common_table.suffix = fts_common_tables[3];
fts_get_table_name(&optim->fts_common_table, deleted);
pars_info_bind_id(info, true, fts_common_tables[3], deleted);
graph = fts_parse_sql(NULL, info, sql_str);
optim->fts_common_table.suffix = fts_common_tables[4];
fts_get_table_name(&optim->fts_common_table, deleted_cache);
pars_info_bind_id(info, true, fts_common_tables[4], deleted_cache);
mem_free(sql_str);
graph = fts_parse_sql(NULL, info, fts_delete_doc_ids_sql);
/* Delete the doc ids that were copied at the start. */
for (i = 0; i < ib_vector_size(optim->to_delete->doc_ids); ++i) {
@ -2134,17 +2156,26 @@ fts_optimize_purge_deleted_doc_id_snapshot(
{
dberr_t error;
que_t* graph;
char* sql_str;
pars_info_t* info;
char being_deleted[MAX_FULL_NAME_LEN];
char being_deleted_cache[MAX_FULL_NAME_LEN];
/* Since we only replace the table_id and don't construct
the full name, we do the '%s' substitution ourselves. */
sql_str = ut_strreplace(fts_end_delete_sql, "%s", optim->name_prefix);
info = pars_info_create();
/* Make sure the following two names are consistent with the name
used in the fts_end_delete_sql */
optim->fts_common_table.suffix = fts_common_tables[0];
fts_get_table_name(&optim->fts_common_table, being_deleted);
pars_info_bind_id(info, true, fts_common_tables[0], being_deleted);
optim->fts_common_table.suffix = fts_common_tables[1];
fts_get_table_name(&optim->fts_common_table, being_deleted_cache);
pars_info_bind_id(info, true, fts_common_tables[1],
being_deleted_cache);
/* Delete the doc ids that were copied to delete pending state at
the start of optimize. */
graph = fts_parse_sql(NULL, NULL, sql_str);
mem_free(sql_str);
graph = fts_parse_sql(NULL, info, fts_end_delete_sql);
error = fts_eval_sql(optim->trx, graph);
fts_que_graph_free(graph);
@ -2184,16 +2215,35 @@ fts_optimize_create_deleted_doc_id_snapshot(
{
dberr_t error;
que_t* graph;
char* sql_str;
pars_info_t* info;
char being_deleted[MAX_FULL_NAME_LEN];
char deleted[MAX_FULL_NAME_LEN];
char being_deleted_cache[MAX_FULL_NAME_LEN];
char deleted_cache[MAX_FULL_NAME_LEN];
/* Since we only replace the table_id and don't construct the
full name, we do the substitution ourselves. */
sql_str = ut_strreplace(fts_init_delete_sql, "%s", optim->name_prefix);
info = pars_info_create();
/* Make sure the following four names are consistent with the name
used in the fts_init_delete_sql */
optim->fts_common_table.suffix = fts_common_tables[0];
fts_get_table_name(&optim->fts_common_table, being_deleted);
pars_info_bind_id(info, true, fts_common_tables[0], being_deleted);
optim->fts_common_table.suffix = fts_common_tables[3];
fts_get_table_name(&optim->fts_common_table, deleted);
pars_info_bind_id(info, true, fts_common_tables[3], deleted);
optim->fts_common_table.suffix = fts_common_tables[1];
fts_get_table_name(&optim->fts_common_table, being_deleted_cache);
pars_info_bind_id(info, true, fts_common_tables[1],
being_deleted_cache);
optim->fts_common_table.suffix = fts_common_tables[4];
fts_get_table_name(&optim->fts_common_table, deleted_cache);
pars_info_bind_id(info, true, fts_common_tables[4], deleted_cache);
/* Move doc_ids that are to be deleted to state being deleted. */
graph = fts_parse_sql(NULL, NULL, sql_str);
mem_free(sql_str);
graph = fts_parse_sql(NULL, info, fts_init_delete_sql);
error = fts_eval_sql(optim->trx, graph);

View file

@ -2032,13 +2032,22 @@ fts_query_find_term(
fts_select_t select;
doc_id_t match_doc_id;
trx_t* trx = query->trx;
char table_name[MAX_FULL_NAME_LEN];
trx->op_info = "fetching FTS index matching nodes";
if (*graph) {
info = (*graph)->info;
} else {
ulint selected;
info = pars_info_create();
selected = fts_select_index(*word->f_str);
query->fts_index_table.suffix = fts_get_suffix(selected);
fts_get_table_name(&query->fts_index_table, table_name);
pars_info_bind_id(info, true, "index_table_name", table_name);
}
select.found = FALSE;
@ -2057,11 +2066,6 @@ fts_query_find_term(
fts_bind_doc_id(info, "max_doc_id", &match_doc_id);
if (!*graph) {
ulint selected;
selected = fts_select_index(*word->f_str);
query->fts_index_table.suffix = fts_get_suffix(selected);
*graph = fts_parse_sql(
&query->fts_index_table,
@ -2069,7 +2073,7 @@ fts_query_find_term(
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR c IS"
" SELECT doc_count, ilist\n"
" FROM \"%s\"\n"
" FROM $index_table_name\n"
" WHERE word LIKE :word AND "
" first_doc_id <= :min_doc_id AND "
" last_doc_id >= :max_doc_id\n"
@ -2168,6 +2172,7 @@ fts_query_total_docs_containing_term(
que_t* graph;
ulint selected;
trx_t* trx = query->trx;
char table_name[MAX_FULL_NAME_LEN]
trx->op_info = "fetching FTS index document count";
@ -2182,13 +2187,17 @@ fts_query_total_docs_containing_term(
query->fts_index_table.suffix = fts_get_suffix(selected);
fts_get_table_name(&query->fts_index_table, table_name);
pars_info_bind_id(info, true, "index_table_name", table_name);
graph = fts_parse_sql(
&query->fts_index_table,
info,
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR c IS"
" SELECT doc_count\n"
" FROM %s\n"
" FROM $index_table_name\n"
" WHERE word = :word "
" ORDER BY first_doc_id;\n"
"BEGIN\n"
@ -2247,6 +2256,7 @@ fts_query_terms_in_document(
que_t* graph;
doc_id_t read_doc_id;
trx_t* trx = query->trx;
char table_name[MAX_FULL_NAME_LEN];
trx->op_info = "fetching FTS document term count";
@ -2262,13 +2272,17 @@ fts_query_terms_in_document(
query->fts_index_table.suffix = "DOC_ID";
fts_get_table_name(&query->fts_index_table, table_name);
pars_info_bind_id(info, true, "index_table_name", table_name);
graph = fts_parse_sql(
&query->fts_index_table,
info,
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR c IS"
" SELECT count\n"
" FROM \"%s\"\n"
" FROM $index_table_name\n"
" WHERE doc_id = :doc_id "
"BEGIN\n"
"\n"

View file

@ -36,8 +36,7 @@ Created 2007-03-27 Sunny Bains
#include "fts0vlc.ic"
#endif
/** SQL statements for creating the ancillary FTS tables. %s must be replaced
with the indexed table's id. */
/** SQL statements for creating the ancillary FTS tables. */
/** Preamble to all SQL statements. */
static const char* fts_sql_begin=
@ -96,77 +95,47 @@ fts_get_table_id(
return(len);
}
/******************************************************************//**
Construct the prefix name of an FTS table.
@return own: table name, must be freed with mem_free() */
UNIV_INTERN
char*
fts_get_table_name_prefix(
/*======================*/
const fts_table_t*
fts_table) /*!< in: Auxiliary table type */
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
@param[in] dict_locked whether dict_sys->mutex is being held
@return the prefix, must be freed with ut_free() */
UNIV_INTERN char* fts_get_table_name_prefix(const fts_table_t* fts_table)
{
int len;
const char* slash;
char* prefix_name;
int dbname_len = 0;
int prefix_name_len;
char table_id[FTS_AUX_MIN_TABLE_ID_LENGTH];
#if 0 /* FIXME: protect the access to dict_table_t::name */
ut_ad(mutex_own(&dict_sys->mutex));
#endif
slash = static_cast<const char*>(
strchr(fts_table->table->name, '/'));
const size_t table_id_len = size_t(fts_get_table_id(fts_table,
table_id)) + 1;
mutex_enter(&dict_sys->mutex);
const char* slash = strchr(fts_table->table->name, '/');
ut_ad(slash);
/* Print up to and including the separator. */
dbname_len = static_cast<int>(slash - fts_table->table->name) + 1;
len = fts_get_table_id(fts_table, table_id);
prefix_name_len = dbname_len + 4 + len + 1;
prefix_name = static_cast<char*>(mem_alloc(prefix_name_len));
len = sprintf(prefix_name, "%.*sFTS_%s",
dbname_len, fts_table->table->name, table_id);
ut_a(len > 0);
ut_a(len == prefix_name_len - 1);
return(prefix_name);
/* Include the separator as well. */
const size_t dbname_len = (slash - fts_table->table->name) + 1;
ut_ad(dbname_len > 1);
const size_t prefix_name_len = dbname_len + 4 + table_id_len;
char* prefix_name = static_cast<char*>(ut_malloc(prefix_name_len));
memcpy(prefix_name, fts_table->table->name, dbname_len);
mutex_exit(&dict_sys->mutex);
memcpy(prefix_name + dbname_len, "FTS_", 4);
memcpy(prefix_name + dbname_len + 4, table_id, table_id_len);
return prefix_name;
}
/******************************************************************//**
Construct the name of an ancillary FTS table.
@return own: table name, must be freed with mem_free() */
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
@param[out] table_name a name up to MAX_FULL_NAME_LEN */
UNIV_INTERN
char*
fts_get_table_name(
/*===============*/
const fts_table_t* fts_table)
/*!< in: Auxiliary table type */
void fts_get_table_name(const fts_table_t* fts_table, char* table_name)
{
int len;
char* name;
int name_len;
char* prefix_name;
prefix_name = fts_get_table_name_prefix(fts_table);
name_len = static_cast<int>(
strlen(prefix_name) + 1 + strlen(fts_table->suffix) + 1);
name = static_cast<char*>(mem_alloc(name_len));
len = sprintf(name, "%s_%s", prefix_name, fts_table->suffix);
ut_a(len > 0);
ut_a(len == name_len - 1);
mem_free(prefix_name);
return(name);
const char* slash = strchr(fts_table->table->name, '/');
ut_ad(slash);
/* Include the separator as well. */
const size_t dbname_len = (slash - fts_table->table->name) + 1;
ut_ad(dbname_len > 1);
memcpy(table_name, fts_table->table->name, dbname_len);
memcpy(table_name += dbname_len, "FTS_", 4);
table_name += 4;
table_name += fts_get_table_id(fts_table, table_name);
*table_name++ = '_';
strcpy(table_name, fts_table->suffix);
}
/******************************************************************//**
@ -182,24 +151,9 @@ fts_parse_sql(
{
char* str;
que_t* graph;
char* str_tmp;
ibool dict_locked;
if (fts_table != NULL) {
char* table_name;
table_name = fts_get_table_name(fts_table);
str_tmp = ut_strreplace(sql, "%s", table_name);
mem_free(table_name);
} else {
ulint sql_len = strlen(sql) + 1;
str_tmp = static_cast<char*>(mem_alloc(sql_len));
strcpy(str_tmp, sql);
}
str = ut_str3cat(fts_sql_begin, str_tmp, fts_sql_end);
mem_free(str_tmp);
str = ut_str3cat(fts_sql_begin, sql, fts_sql_end);
dict_locked = (fts_table && fts_table->table->fts
&& (fts_table->table->fts->fts_status
@ -225,7 +179,7 @@ fts_parse_sql(
}
/******************************************************************//**
Parse an SQL string. %s is replaced with the table's id.
Parse an SQL string.
@return query graph */
UNIV_INTERN
que_t*
@ -237,28 +191,10 @@ fts_parse_sql_no_dict_lock(
{
char* str;
que_t* graph;
char* str_tmp = NULL;
#ifdef UNIV_DEBUG
ut_ad(mutex_own(&dict_sys->mutex));
#endif
if (fts_table != NULL) {
char* table_name;
table_name = fts_get_table_name(fts_table);
str_tmp = ut_strreplace(sql, "%s", table_name);
mem_free(table_name);
}
if (str_tmp != NULL) {
str = ut_str3cat(fts_sql_begin, str_tmp, fts_sql_end);
mem_free(str_tmp);
} else {
str = ut_str3cat(fts_sql_begin, sql, fts_sql_end);
}
//fprintf(stderr, "%s\n", str);
str = ut_str3cat(fts_sql_begin, sql, fts_sql_end);
graph = pars_sql(info, str);
ut_a(graph);

View file

@ -3479,6 +3479,7 @@ i_s_fts_index_table_fill_selected(
que_t* graph;
dberr_t error;
fts_fetch_t fetch;
char table_name[MAX_FULL_NAME_LEN];
info = pars_info_create();
@ -3499,6 +3500,8 @@ i_s_fts_index_table_fill_selected(
FTS_INIT_INDEX_TABLE(&fts_table, fts_get_suffix(selected),
FTS_INDEX_TABLE, index);
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,
@ -3506,7 +3509,7 @@ i_s_fts_index_table_fill_selected(
"DECLARE CURSOR c IS"
" SELECT word, doc_count, first_doc_id, last_doc_id, "
"ilist\n"
" FROM %s WHERE word >= :word;\n"
" FROM $table_name WHERE word >= :word;\n"
"BEGIN\n"
"\n"
"OPEN c;\n"

View file

@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 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
@ -132,16 +133,13 @@ fts_eval_sql(
trx_t* trx, /*!< in: transaction */
que_t* graph) /*!< in: Parsed statement */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/******************************************************************//**
Construct the name of an ancillary FTS table for the given table.
@return own: table name, must be freed with mem_free() */
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
@param[out] table_name a name up to MAX_FULL_NAME_LEN */
UNIV_INTERN
char*
fts_get_table_name(
/*===============*/
const fts_table_t*
fts_table) /*!< in: FTS aux table info */
MY_ATTRIBUTE((nonnull, malloc, warn_unused_result));
void fts_get_table_name(const fts_table_t* fts_table, char* table_name)
MY_ATTRIBUTE((nonnull));
/******************************************************************//**
Construct the column specification part of the SQL string for selecting the
indexed FTS columns for the given table. Adds the necessary bound
@ -597,15 +595,11 @@ fts_get_table_id(
FTS_AUX_MIN_TABLE_ID_LENGTH bytes
long */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/******************************************************************//**
Construct the prefix name of an FTS table.
@return own: table name, must be freed with mem_free() */
UNIV_INTERN
char*
fts_get_table_name_prefix(
/*======================*/
const fts_table_t*
fts_table) /*!< in: Auxiliary table type */
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
@param[in] dict_locked whether dict_sys->mutex is being held
@return the prefix, must be freed with ut_free() */
UNIV_INTERN char* fts_get_table_name_prefix(const fts_table_t* fts_table)
MY_ATTRIBUTE((nonnull, malloc, warn_unused_result));
/******************************************************************//**
Add node positions. */

View file

@ -85,6 +85,7 @@ fts_config_get_value(
que_t* graph;
dberr_t error;
ulint name_len = strlen(name);
char table_name[MAX_FULL_NAME_LEN];
info = pars_info_create();
@ -100,12 +101,14 @@ fts_config_get_value(
pars_info_bind_varchar_literal(info, "name", (byte*) name, name_len);
fts_table->suffix = "CONFIG";
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 value FROM \"%s\""
"DECLARE CURSOR c IS SELECT value FROM $table_name"
" WHERE key = :name;\n"
"BEGIN\n"
""
@ -212,6 +215,7 @@ fts_config_set_value(
undo_no_t undo_no;
undo_no_t n_rows_updated;
ulint name_len = strlen(name);
char table_name[MAX_FULL_NAME_LEN];
info = pars_info_create();
@ -220,10 +224,13 @@ fts_config_set_value(
value->f_str, value->f_len);
fts_table->suffix = "CONFIG";
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 UPDATE \"%s\" SET value = :value WHERE key = :name;");
"BEGIN UPDATE $table_name SET value = :value "
"WHERE key = :name;");
trx->op_info = "setting FTS config value";
@ -245,10 +252,13 @@ fts_config_set_value(
pars_info_bind_varchar_literal(
info, "value", value->f_str, value->f_len);
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\n"
"INSERT INTO \"%s\" VALUES(:name, :value);");
"INSERT INTO $table_name VALUES(:name, :value);");
trx->op_info = "inserting FTS config value";
@ -465,6 +475,7 @@ fts_config_increment_value(
que_t* graph = NULL;
ulint name_len = strlen(name);
pars_info_t* info = pars_info_create();
char table_name[MAX_FULL_NAME_LEN];
/* We set the length of value to the max bytes it can hold. This
information is used by the callback that reads the value.*/
@ -479,11 +490,13 @@ fts_config_increment_value(
info, "my_func", fts_config_fetch_value, &value);
fts_table->suffix = "CONFIG";
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 = :name FOR UPDATE;\n"
"BEGIN\n"
""

View file

@ -167,38 +167,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 +208,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 +221,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 +249,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
@ -1585,19 +1586,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);
err = fts_rename_one_aux_table(new_name, old_table_name, trx);
mem_free(old_table_name);
if (err != DB_SUCCESS) {
return(err);
}
@ -1616,12 +1615,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);
err = fts_rename_one_aux_table(
new_name, old_table_name, trx);
@ -1630,8 +1625,6 @@ fts_rename_aux_tables(
err = DB_DEADLOCK;
fts_sql_rollback(trx););
mem_free(old_table_name);
if (err != DB_SUCCESS) {
return(err);
}
@ -1659,11 +1652,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);
err = fts_drop_table(trx, table_name);
@ -1671,8 +1664,6 @@ fts_drop_common_tables(
if (err != DB_SUCCESS && err != DB_FAIL) {
error = err;
}
mem_free(table_name);
}
return(error);
@ -1698,11 +1689,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);
err = fts_drop_table(trx, table_name);
@ -1710,8 +1701,6 @@ fts_drop_index_split_tables(
if (err != DB_SUCCESS && err != DB_FAIL) {
error = err;
}
mem_free(table_name);
}
return(error);
@ -1748,11 +1737,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);
err = fts_drop_table(trx, table_name);
@ -1760,8 +1749,6 @@ fts_drop_index_tables(
if (err != DB_SUCCESS && err != DB_FAIL) {
error = err;
}
mem_free(table_name);
}
#endif /* FTS_DOC_STATS_DEBUG */
@ -1830,26 +1817,6 @@ fts_drop_tables(
return(error);
}
/*********************************************************************//**
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
@ -1864,12 +1831,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);
@ -1881,9 +1851,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]);
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);
@ -1895,9 +1875,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);
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);
@ -1965,13 +1950,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);
if (srv_file_per_table) {
flags2 = DICT_TF2_USE_TABLESPACE;
}
@ -2015,8 +2002,6 @@ fts_create_one_index_table(
"Fail to create FTS index table %s", table_name);
}
mem_free(table_name);
return(new_table);
}
@ -2039,7 +2024,9 @@ 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;
@ -2047,14 +2034,17 @@ fts_create_index_tables_low(
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);
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);
@ -2063,6 +2053,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. */
@ -2076,8 +2068,12 @@ fts_create_index_tables_low(
break;
}
fts_get_table_name(&fts_table, fts_name);
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);
@ -2701,6 +2697,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);
@ -2718,10 +2715,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"
""
@ -2814,6 +2814,7 @@ 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;
@ -2834,10 +2835,13 @@ fts_update_sync_doc_id(
pars_info_bind_varchar_literal(info, "doc_id", id, id_len);
fts_get_table_name(&fts_table, fts_name);
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);
@ -2984,6 +2988,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";
@ -2991,10 +2996,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);
@ -3813,11 +3821,15 @@ fts_write_node(
ib_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);
@ -3843,11 +3855,12 @@ 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);");
}
@ -3874,6 +3887,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);
@ -3889,10 +3903,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;
@ -4069,6 +4086,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;
@ -4091,10 +4109,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 (;;) {
@ -4216,6 +4239,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";
@ -4225,6 +4249,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);
@ -4235,7 +4261,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"
@ -4984,6 +5010,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();
@ -4993,13 +5020,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"
@ -6208,7 +6238,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, '/');
@ -6253,7 +6283,7 @@ fts_rename_one_aux_table_to_hex_format(
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) {
@ -6274,8 +6304,6 @@ fts_rename_one_aux_table_to_hex_format(
aux_table->name, new_name);
}
mem_free(new_name);
return (error);
}

View file

@ -226,27 +226,30 @@ static ulint FTS_ZIP_BLOCK_SIZE = 1024;
/** The amount of time optimizing in a single pass, in milliseconds. */
static ib_time_t fts_optimize_time_limit = 0;
/** It's defined in fts0fts.cc */
extern const char* fts_common_tables[];
/** SQL Statement for changing state of rows to be deleted from FTS Index. */
static const char* fts_init_delete_sql =
"BEGIN\n"
"\n"
"INSERT INTO \"%s_BEING_DELETED\"\n"
"SELECT doc_id FROM \"%s_DELETED\";\n"
"INSERT INTO $BEING_DELETED\n"
"SELECT doc_id FROM $DELETED;\n"
"\n"
"INSERT INTO \"%s_BEING_DELETED_CACHE\"\n"
"SELECT doc_id FROM \"%s_DELETED_CACHE\";\n";
"INSERT INTO $BEING_DELETED_CACHE\n"
"SELECT doc_id FROM $DELETED_CACHE;\n";
static const char* fts_delete_doc_ids_sql =
"BEGIN\n"
"\n"
"DELETE FROM \"%s_DELETED\" WHERE doc_id = :doc_id1;\n"
"DELETE FROM \"%s_DELETED_CACHE\" WHERE doc_id = :doc_id2;\n";
"DELETE FROM $DELETED WHERE doc_id = :doc_id1;\n"
"DELETE FROM $DELETED_CACHE WHERE doc_id = :doc_id2;\n";
static const char* fts_end_delete_sql =
"BEGIN\n"
"\n"
"DELETE FROM \"%s_BEING_DELETED\";\n"
"DELETE FROM \"%s_BEING_DELETED_CACHE\";\n";
"DELETE FROM $BEING_DELETED;\n"
"DELETE FROM $BEING_DELETED_CACHE;\n";
/**********************************************************************//**
Initialize fts_zip_t. */
@ -477,21 +480,17 @@ fts_index_fetch_nodes(
{
pars_info_t* info;
dberr_t error;
char table_name[MAX_FULL_NAME_LEN];
trx->op_info = "fetching FTS index nodes";
if (*graph) {
info = (*graph)->info;
} else {
info = pars_info_create();
}
pars_info_bind_function(info, "my_func", fetch->read_record, fetch);
pars_info_bind_varchar_literal(info, "word", word->f_str, word->f_len);
if (!*graph) {
ulint selected;
info = pars_info_create();
ut_a(fts_table->type == FTS_INDEX_TABLE);
selected = fts_select_index(fts_table->charset,
@ -499,6 +498,16 @@ fts_index_fetch_nodes(
fts_table->suffix = fts_get_suffix(selected);
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", fetch->read_record, fetch);
pars_info_bind_varchar_literal(info, "word", word->f_str, word->f_len);
if (!*graph) {
*graph = fts_parse_sql(
fts_table,
info,
@ -506,7 +515,7 @@ fts_index_fetch_nodes(
"DECLARE CURSOR c IS"
" SELECT word, doc_count, first_doc_id, last_doc_id, "
"ilist\n"
" FROM \"%s\"\n"
" FROM $table_name\n"
" WHERE word LIKE :word\n"
" ORDER BY first_doc_id;\n"
"BEGIN\n"
@ -806,6 +815,8 @@ fts_index_fetch_words(
fts_index_selector[selected].value;
selected++) {
char table_name[MAX_FULL_NAME_LEN];
optim->fts_index_table.suffix = fts_get_suffix(selected);
/* We've search all indexes. */
@ -821,13 +832,16 @@ fts_index_fetch_words(
pars_info_bind_varchar_literal(
info, "word", word->f_str, word->f_len);
fts_get_table_name(&optim->fts_index_table, table_name);
pars_info_bind_id(info, true, "table_name", table_name);
graph = fts_parse_sql(
&optim->fts_index_table,
info,
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR c IS"
" SELECT word\n"
" FROM \"%s\"\n"
" FROM $table_name\n"
" WHERE word > :word\n"
" ORDER BY word;\n"
"BEGIN\n"
@ -969,6 +983,7 @@ fts_table_fetch_doc_ids(
que_t* graph;
pars_info_t* info = pars_info_create();
ibool alloc_bk_trx = FALSE;
char table_name[MAX_FULL_NAME_LEN];
ut_a(fts_table->suffix != NULL);
ut_a(fts_table->type == FTS_COMMON_TABLE);
@ -982,12 +997,15 @@ fts_table_fetch_doc_ids(
pars_info_bind_function(info, "my_func", fts_fetch_doc_ids, doc_ids);
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 doc_id FROM \"%s\";\n"
" SELECT doc_id FROM $table_name;\n"
"BEGIN\n"
"\n"
"OPEN c;\n"
@ -1440,7 +1458,7 @@ fts_optimize_write_word(
que_t* graph;
ulint selected;
dberr_t error = DB_SUCCESS;
char* table_name = fts_get_table_name(fts_table);
char table_name[MAX_FULL_NAME_LEN];
info = pars_info_create();
@ -1458,11 +1476,13 @@ fts_optimize_write_word(
word->f_str, word->f_len);
fts_table->suffix = fts_get_suffix(selected);
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 DELETE FROM \"%s\" WHERE word = :word;");
"BEGIN DELETE FROM $table_name WHERE word = :word;");
error = fts_eval_sql(trx, graph);
@ -1476,8 +1496,6 @@ fts_optimize_write_word(
fts_que_graph_free(graph);
graph = NULL;
mem_free(table_name);
/* Even if the operation needs to be rolled back and redone,
we iterate over the nodes in order to free the ilist. */
for (i = 0; i < ib_vector_size(nodes); ++i) {
@ -1727,7 +1745,7 @@ fts_optimize_free(
fts_doc_ids_free(optim->to_delete);
fts_optimize_graph_free(&optim->graph);
mem_free(optim->name_prefix);
ut_free(optim->name_prefix);
/* This will free the heap from which optim itself was allocated. */
mem_heap_free(heap);
@ -2067,9 +2085,10 @@ fts_optimize_purge_deleted_doc_ids(
pars_info_t* info;
que_t* graph;
fts_update_t* update;
char* sql_str;
doc_id_t write_doc_id;
dberr_t error = DB_SUCCESS;
char deleted[MAX_FULL_NAME_LEN];
char deleted_cache[MAX_FULL_NAME_LEN];
info = pars_info_create();
@ -2086,14 +2105,17 @@ fts_optimize_purge_deleted_doc_ids(
fts_bind_doc_id(info, "doc_id1", &write_doc_id);
fts_bind_doc_id(info, "doc_id2", &write_doc_id);
/* Since we only replace the table_id and don't construct the full
name, we do substitution ourselves. Remember to free sql_str. */
sql_str = ut_strreplace(
fts_delete_doc_ids_sql, "%s", optim->name_prefix);
/* Make sure the following two names are consistent with the name
used in the fts_delete_doc_ids_sql */
optim->fts_common_table.suffix = fts_common_tables[3];
fts_get_table_name(&optim->fts_common_table, deleted);
pars_info_bind_id(info, true, fts_common_tables[3], deleted);
graph = fts_parse_sql(NULL, info, sql_str);
optim->fts_common_table.suffix = fts_common_tables[4];
fts_get_table_name(&optim->fts_common_table, deleted_cache);
pars_info_bind_id(info, true, fts_common_tables[4], deleted_cache);
mem_free(sql_str);
graph = fts_parse_sql(NULL, info, fts_delete_doc_ids_sql);
/* Delete the doc ids that were copied at the start. */
for (i = 0; i < ib_vector_size(optim->to_delete->doc_ids); ++i) {
@ -2134,17 +2156,26 @@ fts_optimize_purge_deleted_doc_id_snapshot(
{
dberr_t error;
que_t* graph;
char* sql_str;
pars_info_t* info;
char being_deleted[MAX_FULL_NAME_LEN];
char being_deleted_cache[MAX_FULL_NAME_LEN];
/* Since we only replace the table_id and don't construct
the full name, we do the '%s' substitution ourselves. */
sql_str = ut_strreplace(fts_end_delete_sql, "%s", optim->name_prefix);
info = pars_info_create();
/* Make sure the following two names are consistent with the name
used in the fts_end_delete_sql */
optim->fts_common_table.suffix = fts_common_tables[0];
fts_get_table_name(&optim->fts_common_table, being_deleted);
pars_info_bind_id(info, true, fts_common_tables[0], being_deleted);
optim->fts_common_table.suffix = fts_common_tables[1];
fts_get_table_name(&optim->fts_common_table, being_deleted_cache);
pars_info_bind_id(info, true, fts_common_tables[1],
being_deleted_cache);
/* Delete the doc ids that were copied to delete pending state at
the start of optimize. */
graph = fts_parse_sql(NULL, NULL, sql_str);
mem_free(sql_str);
graph = fts_parse_sql(NULL, info, fts_end_delete_sql);
error = fts_eval_sql(optim->trx, graph);
fts_que_graph_free(graph);
@ -2184,16 +2215,35 @@ fts_optimize_create_deleted_doc_id_snapshot(
{
dberr_t error;
que_t* graph;
char* sql_str;
pars_info_t* info;
char being_deleted[MAX_FULL_NAME_LEN];
char deleted[MAX_FULL_NAME_LEN];
char being_deleted_cache[MAX_FULL_NAME_LEN];
char deleted_cache[MAX_FULL_NAME_LEN];
/* Since we only replace the table_id and don't construct the
full name, we do the substitution ourselves. */
sql_str = ut_strreplace(fts_init_delete_sql, "%s", optim->name_prefix);
info = pars_info_create();
/* Make sure the following four names are consistent with the name
used in the fts_init_delete_sql */
optim->fts_common_table.suffix = fts_common_tables[0];
fts_get_table_name(&optim->fts_common_table, being_deleted);
pars_info_bind_id(info, true, fts_common_tables[0], being_deleted);
optim->fts_common_table.suffix = fts_common_tables[3];
fts_get_table_name(&optim->fts_common_table, deleted);
pars_info_bind_id(info, true, fts_common_tables[3], deleted);
optim->fts_common_table.suffix = fts_common_tables[1];
fts_get_table_name(&optim->fts_common_table, being_deleted_cache);
pars_info_bind_id(info, true, fts_common_tables[1],
being_deleted_cache);
optim->fts_common_table.suffix = fts_common_tables[4];
fts_get_table_name(&optim->fts_common_table, deleted_cache);
pars_info_bind_id(info, true, fts_common_tables[4], deleted_cache);
/* Move doc_ids that are to be deleted to state being deleted. */
graph = fts_parse_sql(NULL, NULL, sql_str);
mem_free(sql_str);
graph = fts_parse_sql(NULL, info, fts_init_delete_sql);
error = fts_eval_sql(optim->trx, graph);

View file

@ -2052,13 +2052,22 @@ fts_query_find_term(
fts_select_t select;
doc_id_t match_doc_id;
trx_t* trx = query->trx;
char table_name[MAX_FULL_NAME_LEN];
trx->op_info = "fetching FTS index matching nodes";
if (*graph) {
info = (*graph)->info;
} else {
ulint selected;
info = pars_info_create();
selected = fts_select_index(*word->f_str);
query->fts_index_table.suffix = fts_get_suffix(selected);
fts_get_table_name(&query->fts_index_table, table_name);
pars_info_bind_id(info, true, "index_table_name", table_name);
}
select.found = FALSE;
@ -2077,11 +2086,6 @@ fts_query_find_term(
fts_bind_doc_id(info, "max_doc_id", &match_doc_id);
if (!*graph) {
ulint selected;
selected = fts_select_index(*word->f_str);
query->fts_index_table.suffix = fts_get_suffix(selected);
*graph = fts_parse_sql(
&query->fts_index_table,
@ -2089,7 +2093,7 @@ fts_query_find_term(
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR c IS"
" SELECT doc_count, ilist\n"
" FROM \"%s\"\n"
" FROM $index_table_name\n"
" WHERE word LIKE :word AND "
" first_doc_id <= :min_doc_id AND "
" last_doc_id >= :max_doc_id\n"
@ -2188,6 +2192,7 @@ fts_query_total_docs_containing_term(
que_t* graph;
ulint selected;
trx_t* trx = query->trx;
char table_name[MAX_FULL_NAME_LEN]
trx->op_info = "fetching FTS index document count";
@ -2202,13 +2207,17 @@ fts_query_total_docs_containing_term(
query->fts_index_table.suffix = fts_get_suffix(selected);
fts_get_table_name(&query->fts_index_table, table_name);
pars_info_bind_id(info, true, "index_table_name", table_name);
graph = fts_parse_sql(
&query->fts_index_table,
info,
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR c IS"
" SELECT doc_count\n"
" FROM %s\n"
" FROM $index_table_name\n"
" WHERE word = :word "
" ORDER BY first_doc_id;\n"
"BEGIN\n"
@ -2267,6 +2276,7 @@ fts_query_terms_in_document(
que_t* graph;
doc_id_t read_doc_id;
trx_t* trx = query->trx;
char table_name[MAX_FULL_NAME_LEN];
trx->op_info = "fetching FTS document term count";
@ -2282,13 +2292,17 @@ fts_query_terms_in_document(
query->fts_index_table.suffix = "DOC_ID";
fts_get_table_name(&query->fts_index_table, table_name);
pars_info_bind_id(info, true, "index_table_name", table_name);
graph = fts_parse_sql(
&query->fts_index_table,
info,
"DECLARE FUNCTION my_func;\n"
"DECLARE CURSOR c IS"
" SELECT count\n"
" FROM \"%s\"\n"
" FROM $index_table_name\n"
" WHERE doc_id = :doc_id "
"BEGIN\n"
"\n"

View file

@ -36,8 +36,7 @@ Created 2007-03-27 Sunny Bains
#include "fts0vlc.ic"
#endif
/** SQL statements for creating the ancillary FTS tables. %s must be replaced
with the indexed table's id. */
/** SQL statements for creating the ancillary FTS tables. */
/** Preamble to all SQL statements. */
static const char* fts_sql_begin=
@ -96,77 +95,47 @@ fts_get_table_id(
return(len);
}
/******************************************************************//**
Construct the prefix name of an FTS table.
@return own: table name, must be freed with mem_free() */
UNIV_INTERN
char*
fts_get_table_name_prefix(
/*======================*/
const fts_table_t*
fts_table) /*!< in: Auxiliary table type */
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
@param[in] dict_locked whether dict_sys->mutex is being held
@return the prefix, must be freed with ut_free() */
UNIV_INTERN char* fts_get_table_name_prefix(const fts_table_t* fts_table)
{
int len;
const char* slash;
char* prefix_name;
int dbname_len = 0;
int prefix_name_len;
char table_id[FTS_AUX_MIN_TABLE_ID_LENGTH];
#if 0 /* FIXME: protect the access to dict_table_t::name */
ut_ad(mutex_own(&dict_sys->mutex));
#endif
slash = static_cast<const char*>(
strchr(fts_table->table->name, '/'));
const size_t table_id_len = size_t(fts_get_table_id(fts_table,
table_id)) + 1;
mutex_enter(&dict_sys->mutex);
const char* slash = strchr(fts_table->table->name, '/');
ut_ad(slash);
/* Print up to and including the separator. */
dbname_len = static_cast<int>(slash - fts_table->table->name) + 1;
len = fts_get_table_id(fts_table, table_id);
prefix_name_len = dbname_len + 4 + len + 1;
prefix_name = static_cast<char*>(mem_alloc(prefix_name_len));
len = sprintf(prefix_name, "%.*sFTS_%s",
dbname_len, fts_table->table->name, table_id);
ut_a(len > 0);
ut_a(len == prefix_name_len - 1);
return(prefix_name);
/* Include the separator as well. */
const size_t dbname_len = (slash - fts_table->table->name) + 1;
ut_ad(dbname_len > 1);
const size_t prefix_name_len = dbname_len + 4 + table_id_len;
char* prefix_name = static_cast<char*>(ut_malloc(prefix_name_len));
memcpy(prefix_name, fts_table->table->name, dbname_len);
mutex_exit(&dict_sys->mutex);
memcpy(prefix_name + dbname_len, "FTS_", 4);
memcpy(prefix_name + dbname_len + 4, table_id, table_id_len);
return prefix_name;
}
/******************************************************************//**
Construct the name of an ancillary FTS table.
@return own: table name, must be freed with mem_free() */
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
@param[out] table_name a name up to MAX_FULL_NAME_LEN */
UNIV_INTERN
char*
fts_get_table_name(
/*===============*/
const fts_table_t* fts_table)
/*!< in: Auxiliary table type */
void fts_get_table_name(const fts_table_t* fts_table, char* table_name)
{
int len;
char* name;
int name_len;
char* prefix_name;
prefix_name = fts_get_table_name_prefix(fts_table);
name_len = static_cast<int>(
strlen(prefix_name) + 1 + strlen(fts_table->suffix) + 1);
name = static_cast<char*>(mem_alloc(name_len));
len = sprintf(name, "%s_%s", prefix_name, fts_table->suffix);
ut_a(len > 0);
ut_a(len == name_len - 1);
mem_free(prefix_name);
return(name);
const char* slash = strchr(fts_table->table->name, '/');
ut_ad(slash);
/* Include the separator as well. */
const size_t dbname_len = (slash - fts_table->table->name) + 1;
ut_ad(dbname_len > 1);
memcpy(table_name, fts_table->table->name, dbname_len);
memcpy(table_name += dbname_len, "FTS_", 4);
table_name += 4;
table_name += fts_get_table_id(fts_table, table_name);
*table_name++ = '_';
strcpy(table_name, fts_table->suffix);
}
/******************************************************************//**
@ -182,24 +151,9 @@ fts_parse_sql(
{
char* str;
que_t* graph;
char* str_tmp;
ibool dict_locked;
if (fts_table != NULL) {
char* table_name;
table_name = fts_get_table_name(fts_table);
str_tmp = ut_strreplace(sql, "%s", table_name);
mem_free(table_name);
} else {
ulint sql_len = strlen(sql) + 1;
str_tmp = static_cast<char*>(mem_alloc(sql_len));
strcpy(str_tmp, sql);
}
str = ut_str3cat(fts_sql_begin, str_tmp, fts_sql_end);
mem_free(str_tmp);
str = ut_str3cat(fts_sql_begin, sql, fts_sql_end);
dict_locked = (fts_table && fts_table->table->fts
&& (fts_table->table->fts->fts_status
@ -225,7 +179,7 @@ fts_parse_sql(
}
/******************************************************************//**
Parse an SQL string. %s is replaced with the table's id.
Parse an SQL string.
@return query graph */
UNIV_INTERN
que_t*
@ -237,28 +191,10 @@ fts_parse_sql_no_dict_lock(
{
char* str;
que_t* graph;
char* str_tmp = NULL;
#ifdef UNIV_DEBUG
ut_ad(mutex_own(&dict_sys->mutex));
#endif
if (fts_table != NULL) {
char* table_name;
table_name = fts_get_table_name(fts_table);
str_tmp = ut_strreplace(sql, "%s", table_name);
mem_free(table_name);
}
if (str_tmp != NULL) {
str = ut_str3cat(fts_sql_begin, str_tmp, fts_sql_end);
mem_free(str_tmp);
} else {
str = ut_str3cat(fts_sql_begin, sql, fts_sql_end);
}
//fprintf(stderr, "%s\n", str);
str = ut_str3cat(fts_sql_begin, sql, fts_sql_end);
graph = pars_sql(info, str);
ut_a(graph);

View file

@ -3470,6 +3470,7 @@ i_s_fts_index_table_fill_selected(
que_t* graph;
dberr_t error;
fts_fetch_t fetch;
char table_name[MAX_FULL_NAME_LEN];
info = pars_info_create();
@ -3490,6 +3491,8 @@ i_s_fts_index_table_fill_selected(
FTS_INIT_INDEX_TABLE(&fts_table, fts_get_suffix(selected),
FTS_INDEX_TABLE, index);
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,
@ -3497,7 +3500,7 @@ i_s_fts_index_table_fill_selected(
"DECLARE CURSOR c IS"
" SELECT word, doc_count, first_doc_id, last_doc_id, "
"ilist\n"
" FROM %s WHERE word >= :word;\n"
" FROM $table_name WHERE word >= :word;\n"
"BEGIN\n"
"\n"
"OPEN c;\n"

View file

@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2011, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 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
@ -132,16 +133,13 @@ fts_eval_sql(
trx_t* trx, /*!< in: transaction */
que_t* graph) /*!< in: Parsed statement */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/******************************************************************//**
Construct the name of an ancillary FTS table for the given table.
@return own: table name, must be freed with mem_free() */
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
@param[out] table_name a name up to MAX_FULL_NAME_LEN */
UNIV_INTERN
char*
fts_get_table_name(
/*===============*/
const fts_table_t*
fts_table) /*!< in: FTS aux table info */
MY_ATTRIBUTE((nonnull, malloc, warn_unused_result));
void fts_get_table_name(const fts_table_t* fts_table, char* table_name)
MY_ATTRIBUTE((nonnull));
/******************************************************************//**
Construct the column specification part of the SQL string for selecting the
indexed FTS columns for the given table. Adds the necessary bound
@ -597,15 +595,11 @@ fts_get_table_id(
FTS_AUX_MIN_TABLE_ID_LENGTH bytes
long */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/******************************************************************//**
Construct the prefix name of an FTS table.
@return own: table name, must be freed with mem_free() */
UNIV_INTERN
char*
fts_get_table_name_prefix(
/*======================*/
const fts_table_t*
fts_table) /*!< in: Auxiliary table type */
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
@param[in] dict_locked whether dict_sys->mutex is being held
@return the prefix, must be freed with ut_free() */
UNIV_INTERN char* fts_get_table_name_prefix(const fts_table_t* fts_table)
MY_ATTRIBUTE((nonnull, malloc, warn_unused_result));
/******************************************************************//**
Add node positions. */