34 #include "fts0types.ic"
42 #define FTS_MAX_ID_LEN 32
45 #define FTS_MAX_CACHE_SIZE_IN_MB "cache_size_in_mb"
77 static const ulint FTS_CACHE_SIZE_LOWER_LIMIT_IN_MB = 1;
80 static const ulint FTS_CACHE_SIZE_UPPER_LIMIT_IN_MB = 1024;
83 static const ulint FTS_DEADLOCK_RETRY_WAIT = 100000;
85 #ifdef UNIV_PFS_RWLOCK
86 UNIV_INTERN mysql_pfs_key_t fts_cache_rw_lock_key;
87 UNIV_INTERN mysql_pfs_key_t fts_cache_init_rw_lock_key;
91 UNIV_INTERN mysql_pfs_key_t fts_delete_mutex_key;
92 UNIV_INTERN mysql_pfs_key_t fts_optimize_mutex_key;
93 UNIV_INTERN mysql_pfs_key_t fts_bg_threads_mutex_key;
94 UNIV_INTERN mysql_pfs_key_t fts_doc_id_mutex_key;
157 static const char* fts_create_common_tables_sql = {
160 "CREATE TABLE \"%s_DELETED\" (\n"
161 " doc_id BIGINT UNSIGNED\n"
163 "CREATE UNIQUE CLUSTERED INDEX IND ON \"%s_DELETED\"(doc_id);\n"
165 "CREATE TABLE \"%s_DELETED_CACHE\" (\n"
166 " doc_id BIGINT UNSIGNED\n"
168 "CREATE UNIQUE CLUSTERED INDEX IND "
169 "ON \"%s_DELETED_CACHE\"(doc_id);\n"
171 "CREATE TABLE \"%s_BEING_DELETED\" (\n"
172 " doc_id BIGINT UNSIGNED\n"
174 "CREATE UNIQUE CLUSTERED INDEX IND "
175 "ON \"%s_BEING_DELETED\"(doc_id);\n"
177 "CREATE TABLE \"%s_BEING_DELETED_CACHE\" (\n"
178 " doc_id BIGINT UNSIGNED\n"
180 "CREATE UNIQUE CLUSTERED INDEX IND "
181 "ON \"%s_BEING_DELETED_CACHE\"(doc_id);\n"
183 "CREATE TABLE \"%s_CONFIG\" (\n"
185 " value CHAR(50) NOT NULL\n"
187 "CREATE UNIQUE CLUSTERED INDEX IND ON \"%s_CONFIG\"(key);\n"
190 #ifdef FTS_DOC_STATS_DEBUG
193 static const char* fts_create_index_tables_sql = {
196 "CREATE TABLE \"%s_DOC_ID\" (\n"
197 " doc_id BIGINT UNSIGNED,\n"
198 " word_count INTEGER UNSIGNED NOT NULL\n"
200 "CREATE UNIQUE CLUSTERED INDEX IND ON \"%s_DOC_ID\"(doc_id);\n"
205 static const char* fts_create_index_sql = {
208 "CREATE UNIQUE CLUSTERED INDEX FTS_INDEX_TABLE_IND "
209 "ON \"%s\"(word, first_doc_id);\n"
213 static const char* fts_common_tables[] = {
215 "BEING_DELETED_CACHE",
234 static const char* fts_config_table_insert_values_sql =
237 "INSERT INTO \"%s\" VALUES('"
240 "INSERT INTO \"%s\" VALUES('"
243 "INSERT INTO \"%s\" VALUES ('"
246 "INSERT INTO \"%s\" VALUES ('"
249 "INSERT INTO \"%s\" VALUES ('"
261 __attribute__((nonnull));
270 __attribute__((nonnull));
271 #ifdef FTS_CACHE_SIZE_DEBUG
276 fts_update_max_cache_size(
294 #ifdef FTS_DOC_STATS_DEBUG
300 fts_is_word_in_index(
307 __attribute__((nonnull, warn_unused_result));
316 fts_update_sync_doc_id(
322 __attribute__((nonnull(1)));
331 ibool stop_signalled = FALSE;
337 stop_signalled = TRUE;
342 return(stop_signalled);
349 fts_load_default_stopword(
358 allocator = stopword_info->
heap;
359 heap =
static_cast<mem_heap_t*
>(allocator->arg);
378 new_word.
nodes = ib_vector_create(
382 str.
f_str =
reinterpret_cast<byte*
>(
word);
389 stopword_info->
status = STOPWORD_FROM_DEFAULT;
417 heap =
static_cast<mem_heap_t*
>(allocator->arg);
425 str.
f_str =
static_cast<byte*
>(dfield_get_data(dfield));
429 if (str.
f_len != UNIV_SQL_NULL
430 &&
rbt_search(stop_words, &parent, &str) != 0) {
434 new_word.
nodes = ib_vector_create(
437 new_word.
text.
f_str =
static_cast<byte*
>(
457 fts_load_user_stopword(
460 const char* stopword_table_name,
472 trx->
op_info =
"Load user stopword table into FTS cache";
503 "DECLARE FUNCTION my_func;\n"
504 "DECLARE CURSOR c IS"
506 " FROM $table_stopword;\n"
511 " FETCH c INTO my_func();\n"
512 " IF c % NOTFOUND THEN\n"
521 if (error == DB_SUCCESS) {
523 stopword_info->
status = STOPWORD_USER_TABLE;
532 fprintf(stderr,
" InnoDB: Warning: lock wait "
533 "timeout reading user stopword table. "
538 fprintf(stderr,
" InnoDB: Error '%s' "
539 "while reading user stopword table.\n",
562 fts_index_cache_init(
577 index_cache->
doc_stats = ib_vector_create(
580 for (i = 0; fts_index_selector[
i].
value; ++
i) {
607 for (i = 0; i < ib_vector_size(cache->
indexes); ++
i) {
613 fts_index_cache_init(cache->
sync_heap, index_cache);
638 fts_cache_init_rw_lock_key, &cache->
init_lock,
639 SYNC_FTS_CACHE_INIT);
642 fts_delete_mutex_key, &cache->
deleted_lock, SYNC_FTS_OPTIMIZE);
649 fts_doc_id_mutex_key, &cache->
doc_id_lock, SYNC_FTS_OPTIMIZE);
652 cache->
self_heap = ib_heap_allocator_create(heap);
655 cache->
sync_heap = ib_heap_allocator_create(heap);
666 cache->
indexes = ib_vector_create(
690 fts_t* fts = table->fts;
695 cache = table->fts->
cache;
699 ib_vector_push(fts->
indexes, &index);
722 #ifdef UNIV_SYNC_DEBUG
727 for (i = 0; i < ib_vector_size(cache->
indexes); i++) {
734 ib_vector_push(cache->
get_docs, NULL));
736 memset(get_doc, 0x0,
sizeof(*get_doc));
742 == ib_vector_size(cache->
indexes));
757 for (index = dict_table_get_first_index(table);
759 index = dict_table_get_next_index(index)) {
761 if (index == index_check) {
781 for (i = 0; i < ib_vector_size(table->fts->
cache->
indexes); i++) {
787 if (index_cache->
index == index) {
807 if (!table->fts || !table->fts->
cache) {
814 for (i = 0; i < ib_vector_size(table->fts->
indexes); i++) {
818 ib_vector_getp(table->fts->
indexes, i));
820 if (!fts_in_index_cache(table, index)) {
824 if (!fts_in_dict_index(table, index)) {
848 if ((ib_vector_size(indexes) == 1
849 && (index == static_cast<dict_index_t*>(
850 ib_vector_getp(table->fts->
indexes, 0))))
865 if (!DICT_TF2_FLAG_IS_SET(
892 if (index_cache->
words) {
893 fts_words_free(index_cache->
words);
900 fts_reset_get_doc(cache);
924 ibool has_dict = FALSE;
926 if (fts_table && fts_table->
table) {
931 }
else if (index_cache) {
963 field = dict_index_get_nth_field(index, 0);
967 (
int) (prtype & DATA_MYSQL_TYPE_MASK),
973 for (i = 1; i < index->
n_fields; i++) {
976 field = dict_index_get_nth_field(index, i);
980 (
int)(prtype & DATA_MYSQL_TYPE_MASK),
985 ut_a(charset == fld_charset);
987 charset = fld_charset;
1009 ut_a(cache != NULL);
1011 #ifdef UNIV_SYNC_DEBUG
1019 ib_vector_push(cache->
indexes, NULL));
1021 memset(index_cache, 0x0,
sizeof(*index_cache));
1027 n_bytes =
sizeof(
que_t*) *
sizeof(fts_index_selector);
1037 fts_index_cache_init(cache->
sync_heap, index_cache);
1040 fts_reset_get_doc(cache);
1043 return(index_cache);
1067 for (i = 0; i < ib_vector_size(word->
nodes); ++
i) {
1073 fts_node->
ilist = NULL;
1095 for (i = 0; i < ib_vector_size(cache->
indexes); ++
i) {
1103 fts_words_free(index_cache->
words);
1110 index_cache->
words = NULL;
1112 for (j = 0; fts_index_selector[j].
value; ++j) {
1114 if (index_cache->
ins_graph[j] != NULL) {
1123 if (index_cache->
sel_graph[j] != NULL) {
1155 #ifdef UNIV_SYNC_DEBUG
1160 for (i = 0; i < ib_vector_size(cache->
indexes); ++
i) {
1166 if (index_cache->
index == index) {
1168 return(index_cache);
1181 fts_get_index_get_doc(
1188 #ifdef UNIV_SYNC_DEBUG
1192 for (i = 0; i < ib_vector_size(cache->
get_docs); ++
i) {
1216 rw_lock_free(&cache->
lock);
1238 fts_tokenizer_word_get(
1248 #ifdef UNIV_SYNC_DEBUG
1249 ut_ad(rw_lock_own(&cache->
lock, RW_LOCK_EX));
1254 &parent, text) == 0) {
1266 new_word.
nodes = ib_vector_create(
1272 index_cache->
words, &parent, &new_word);
1279 +
sizeof(*new_word.
nodes);
1308 #ifdef UNIV_SYNC_DEBUG
1310 ut_ad(rw_lock_own(&cache->
lock, RW_LOCK_EX));
1316 doc_id_delta = (ulint)(doc_id - node->
last_doc_id);
1320 for (i = 0; i < ib_vector_size(positions); i++) {
1321 ulint pos = *(
static_cast<ulint*
>(
1324 ut_ad(last_pos == 0 || pos > last_pos);
1343 if (new_size < 16) {
1345 }
else if (new_size < 32) {
1347 }
else if (new_size < 48) {
1350 new_size = (ulint)(1.2 * new_size);
1353 ilist =
static_cast<byte*
>(
ut_malloc(new_size));
1365 for (i = 0; i < ib_vector_size(positions); i++) {
1366 ulint pos = *(
static_cast<ulint*
>(
1375 ut_a(enc_len == (ulint)(ptr - ptr_start));
1385 node->
ilist = ilist;
1422 #ifdef UNIV_SYNC_DEBUG
1423 ut_ad(rw_lock_own(&cache->
lock, RW_LOCK_EX));
1426 n_words = rbt_size(tokens);
1435 word = fts_tokenizer_word_get(
1436 cache, index_cache, &token->
text);
1443 if (ib_vector_size(word->
nodes) > 0) {
1445 ib_vector_last(word->
nodes));
1448 if (fts_node == NULL
1450 || doc_id < fts_node->last_doc_id) {
1453 ib_vector_push(word->
nodes, NULL));
1455 memset(fts_node, 0x0,
sizeof(*fts_node));
1461 cache, fts_node, doc_id, token->
positions);
1466 ut_a(rbt_empty(tokens));
1470 ib_vector_push(index_cache->
doc_stats, NULL));
1472 doc_stats->
doc_id = doc_id;
1486 static __attribute__((nonnull, warn_unused_result))
1500 table_name, TRUE, FALSE,
1501 static_cast<dict_err_ignore_t>(
1513 if (error != DB_SUCCESS) {
1515 "Unable to drop FTS index aux table %s: %s",
1528 static __attribute__((nonnull, warn_unused_result))
1530 fts_rename_one_aux_table(
1532 const
char* new_name,
1533 const
char* fts_table_old_name,
1539 ulint table_new_name_len = strlen(fts_table_old_name)
1540 + new_db_name_len - old_db_name_len;
1544 ut_ad((new_db_name_len != old_db_name_len)
1545 || strncmp(new_name, fts_table_old_name, old_db_name_len) != 0);
1549 strncpy(fts_table_new_name, new_name, new_db_name_len);
1550 strncpy(fts_table_new_name + new_db_name_len,
1551 strchr(fts_table_old_name,
'/'),
1552 table_new_name_len - new_db_name_len);
1553 fts_table_new_name[table_new_name_len] = 0;
1556 fts_table_old_name, fts_table_new_name, trx,
false));
1568 const char* new_name,
1577 for (i = 0; fts_common_tables[
i] != NULL; ++
i) {
1578 char* old_table_name;
1581 fts_table.
suffix = fts_common_tables[
i];
1585 err = fts_rename_one_aux_table(new_name, old_table_name, trx);
1589 if (err != DB_SUCCESS) {
1594 fts_t* fts = table->fts;
1597 for (i = 0; fts->
indexes != 0 && i < ib_vector_size(fts->
indexes);
1602 ib_vector_getp(fts->
indexes, i));
1606 for (ulint j = 0; fts_index_selector[j].
value; ++j) {
1608 char* old_table_name;
1614 err = fts_rename_one_aux_table(
1615 new_name, old_table_name, trx);
1617 DBUG_EXECUTE_IF(
"fts_rename_failure",
1618 err = DB_DEADLOCK;);
1622 if (err != DB_SUCCESS) {
1636 static __attribute__((nonnull, warn_unused_result))
1638 fts_drop_common_tables(
1647 for (i = 0; fts_common_tables[
i] != NULL; ++
i) {
1651 fts_table->suffix = fts_common_tables[
i];
1655 err = fts_drop_table(trx, table_name);
1658 if (err != DB_SUCCESS && err != DB_FAIL) {
1686 for (i = 0; fts_index_selector[
i].
value; ++
i) {
1694 err = fts_drop_table(trx, table_name);
1697 if (err != DB_SUCCESS && err != DB_FAIL) {
1719 #ifdef FTS_DOC_STATS_DEBUG
1721 static const char* index_tables[] = {
1730 if (err != DB_SUCCESS) {
1734 #ifdef FTS_DOC_STATS_DEBUG
1737 for (ulint i = 0; index_tables[
i] != NULL; ++
i) {
1740 fts_table.
suffix = index_tables[
i];
1744 err = fts_drop_table(trx, table_name);
1747 if (err != DB_SUCCESS && err != DB_FAIL) {
1763 static __attribute__((nonnull, warn_unused_result))
1765 fts_drop_all_index_tables(
1773 fts->indexes != 0 && i < ib_vector_size(fts->indexes);
1780 ib_vector_getp(fts->indexes, i));
1784 if (err != DB_SUCCESS) {
1811 error = fts_drop_common_tables(trx, &fts_table);
1813 if (error == DB_SUCCESS) {
1814 error = fts_drop_all_index_tables(trx, table->fts);
1828 const char* my_template)
1852 bool skip_doc_id_index)
1863 error = fts_drop_common_tables(trx, &fts_table);
1865 if (error != DB_SUCCESS) {
1871 sql = fts_prepare_sql(&fts_table, fts_create_common_tables_sql);
1879 if (error != DB_SUCCESS) {
1885 fts_table.
suffix =
"CONFIG";
1887 &fts_table, NULL, fts_config_table_insert_values_sql);
1893 if (error != DB_SUCCESS || skip_doc_id_index) {
1913 "CREATE UNIQUE INDEX $index_name ON $table_name("
1914 "$doc_id_col_name);\n"));
1920 if (error != DB_SUCCESS) {
1943 fts_create_one_index_table(
1961 field = dict_index_get_nth_field(index, 0);
1963 (
int)(field->
col->
prtype & DATA_MYSQL_TYPE_MASK),
1966 if (strcmp(charset->name,
"latin1_swedish_ci") == 0) {
1975 DATA_NOT_NULL | DATA_UNSIGNED,
1979 DATA_NOT_NULL | DATA_UNSIGNED,
1983 DATA_NOT_NULL | DATA_UNSIGNED, 4);
1990 if (error != DB_SUCCESS) {
1995 "Fail to create FTS index table %s", table_name);
2014 const char* table_name,
2015 table_id_t table_id)
2028 fts_table.
table = NULL;
2030 #ifdef FTS_DOC_STATS_DEBUG
2035 sql = fts_prepare_sql(&fts_table, fts_create_index_tables_sql);
2044 for (i = 0; fts_index_selector[
i].
value && error == DB_SUCCESS; ++
i) {
2052 new_table = fts_create_one_index_table(
2053 trx, index, &fts_table, heap);
2061 &fts_table, NULL, fts_create_index_sql);
2067 if (error != DB_SUCCESS) {
2100 ut_a(table != NULL);
2104 if (err == DB_SUCCESS) {
2147 fts_trx_row_get_new_state(
2201 { FTS_INVALID, FTS_INSERT, FTS_NOTHING, FTS_INVALID },
2202 { FTS_INVALID, FTS_MODIFY, FTS_DELETE, FTS_INVALID },
2203 { FTS_MODIFY, FTS_INVALID, FTS_INVALID, FTS_INVALID },
2204 { FTS_INVALID, FTS_INVALID, FTS_INVALID, FTS_INVALID }
2209 ut_a(old_state < FTS_INVALID);
2210 ut_a(event < FTS_INVALID);
2212 result = table[(int) old_state][(
int) event];
2213 ut_a(result != FTS_INVALID);
2223 fts_savepoint_create(
2232 ib_vector_push(savepoints, NULL));
2234 memset(savepoint, 0x0,
sizeof(*savepoint));
2263 heap_alloc = ib_heap_allocator_create(heap);
2272 fts_savepoint_create(ftt->
savepoints, NULL, NULL);
2273 fts_savepoint_create(ftt->
last_stmt, NULL, NULL);
2283 fts_trx_table_create(
2293 memset(ftt, 0x0,
sizeof(*ftt));
2308 fts_trx_table_clone(
2317 memset(ftt, 0x0,
sizeof(*ftt));
2350 savepoint =
static_cast<fts_savepoint_t*
>(ib_vector_last(savepoints));
2352 tables = savepoint->
tables;
2355 if (parent.result == 0) {
2361 ftt = fts_trx_table_create(trx->
fts_trx, table);
2374 fts_trx_table_add_op(
2389 if (parent.result == 0) {
2392 row->
state = fts_trx_row_get_new_state(row->
state, state);
2394 if (row->
state == FTS_NOTHING) {
2434 trx->
fts_trx = fts_trx_create(trx);
2440 fts_trx_table_add_op(tran_ftt, doc_id, state, fts_indexes);
2441 fts_trx_table_add_op(stmt_ftt, doc_id, state, fts_indexes);
2450 fts_fetch_store_doc_id(
2466 ut_a(len > 0 && len <
sizeof(buf));
2468 memcpy(buf, dfield_get_data(dfield), len);
2472 ut_a(n_parsed == 1);
2477 #ifdef FTS_CACHE_SIZE_DEBUG
2485 fts_get_max_cache_size(
2492 ulint cache_size_in_mb;
2495 cache_size_in_mb = FTS_CACHE_SIZE_LOWER_LIMIT_IN_MB;
2506 if (error == DB_SUCCESS) {
2509 cache_size_in_mb = strtoul((
char*) value.
f_str, NULL, 10);
2511 if (cache_size_in_mb > FTS_CACHE_SIZE_UPPER_LIMIT_IN_MB) {
2514 fprintf(stderr,
" InnoDB: Warning: FTS max cache size "
2515 " (%lu) out of range. Minimum value is "
2516 "%luMB and the maximum values is %luMB, "
2517 "setting cache size to upper limit\n",
2519 FTS_CACHE_SIZE_LOWER_LIMIT_IN_MB,
2520 FTS_CACHE_SIZE_UPPER_LIMIT_IN_MB);
2522 cache_size_in_mb = FTS_CACHE_SIZE_UPPER_LIMIT_IN_MB;
2524 }
else if (cache_size_in_mb
2525 < FTS_CACHE_SIZE_LOWER_LIMIT_IN_MB) {
2528 fprintf(stderr,
" InnoDB: Warning: FTS max cache size "
2529 " (%lu) out of range. Minimum value is "
2530 "%luMB and the maximum values is %luMB, "
2531 "setting cache size to lower limit\n",
2533 FTS_CACHE_SIZE_LOWER_LIMIT_IN_MB,
2534 FTS_CACHE_SIZE_UPPER_LIMIT_IN_MB);
2536 cache_size_in_mb = FTS_CACHE_SIZE_LOWER_LIMIT_IN_MB;
2540 fprintf(stderr,
"InnoDB: Error: (%lu) reading max cache "
2541 "config value from config table\n", error);
2546 return(cache_size_in_mb * 1024 * 1024);
2550 #ifdef FTS_DOC_STATS_DEBUG
2556 fts_get_total_word_count(
2576 if (error == DB_SUCCESS) {
2579 *total = strtoul((
char*) value.
f_str, NULL, 10);
2582 fprintf(stderr,
" InnoDB: Error: (%s) reading total words "
2583 "value from config table\n",
ut_strerr(error));
2602 const char* table_name,
2610 fts_update_sync_doc_id(
2654 static __attribute__((nonnull))
2656 fts_cmp_set_sync_doc_id(
2671 que_t* graph = NULL;
2674 ut_a(table->fts->doc_col != ULINT_UNDEFINED);
2676 fts_table.
suffix =
"CONFIG";
2681 fts_table.
parent = table->name;
2685 trx->
op_info =
"update the next FTS document id";
2690 info,
"my_func", fts_fetch_store_doc_id, doc_id);
2694 "DECLARE FUNCTION my_func;\n"
2695 "DECLARE CURSOR c IS SELECT value FROM \"%s\""
2696 " WHERE key = 'synced_doc_id' FOR UPDATE;\n"
2700 "WHILE 1 = 1 LOOP\n"
2701 " FETCH c INTO my_func();\n"
2702 " IF c % NOTFOUND THEN\n"
2715 if (error != DB_SUCCESS) {
2723 if (doc_id_cmp == 0 && *doc_id) {
2737 if (doc_id_cmp > *doc_id) {
2738 error = fts_update_sync_doc_id(
2746 if (error == DB_SUCCESS) {
2752 fprintf(stderr,
" InnoDB: Error: (%s) "
2753 "while getting next doc id.\n",
ut_strerr(error));
2757 if (error == DB_DEADLOCK) {
2774 fts_update_sync_doc_id(
2777 const char* table_name,
2781 byte
id[FTS_MAX_ID_LEN];
2785 que_t* graph = NULL;
2787 ibool local_trx = FALSE;
2790 fts_table.
suffix =
"CONFIG";
2803 trx->
op_info =
"setting last FTS document id";
2817 "UPDATE %s SET value = :doc_id"
2818 " WHERE key = 'synced_doc_id';");
2825 if (error == DB_SUCCESS) {
2831 "(%s) while updating last doc id.",
2856 fts_doc_ids->
self_heap = ib_heap_allocator_create(heap);
2861 return(fts_doc_ids);
2875 memset(fts_doc_ids, 0,
sizeof(*fts_doc_ids));
2883 static __attribute__((nonnull, warn_unused_result))
2894 ut_a(row->state == FTS_INSERT || row->state == FTS_MODIFY);
2896 fts_add_doc_by_id(ftt, doc_id, row->fts_indexes);
2898 if (error == DB_SUCCESS) {
2915 static __attribute__((nonnull, warn_unused_result))
2938 ut_a(row->state == FTS_DELETE || row->state == FTS_MODIFY);
2966 ut_a(row->state == FTS_DELETE || row->state == FTS_MODIFY);
2970 if (error == DB_SUCCESS) {
2972 trx->
op_info =
"adding doc id to FTS DELETED";
2976 fts_table.
suffix =
"DELETED";
2981 "BEGIN INSERT INTO \"%s\" VALUES (:doc_id);");
2985 fts_que_graph_free(graph);
2992 if (error == DB_SUCCESS) {
3006 static __attribute__((nonnull, warn_unused_result))
3015 ut_a(row->state == FTS_MODIFY);
3017 error = fts_delete(ftt, row);
3019 if (error == DB_SUCCESS) {
3020 error = fts_add(ftt, row);
3053 if (error == DB_SUCCESS) {
3059 dfield = dtuple_get_nth_field(row, table->fts->
doc_col);
3060 write_doc_id =
static_cast<doc_id_t*
>(
3077 static __attribute__((nonnull, warn_unused_result))
3091 ftt->fts_trx->trx =
trx;
3102 node != NULL && error == DB_SUCCESS;
3107 switch (row->
state) {
3109 error = fts_add(ftt, row);
3113 error = fts_modify(ftt, row);
3117 error = fts_delete(ftt, row);
3149 tables = savepoint->
tables;
3151 for (node =
rbt_first(tables), error = DB_SUCCESS;
3152 node != NULL && error == DB_SUCCESS;
3159 error = fts_commit_table(*ftt);
3175 memset(doc, 0,
sizeof(*doc));
3177 doc->
self_heap = ib_heap_allocator_create(heap);
3195 memset(doc, 0,
sizeof(*doc));
3215 dtype_t* type = dfield_get_type(dfield);
3222 memcpy(user_arg, dfield_get_data(dfield), 8);
3256 doc_charset = result_doc->
charset;
3264 if (len == UNIV_SQL_NULL) {
3272 (
int)(prtype & DATA_MYSQL_TYPE_MASK),
3287 dfield_get_data(dfield));
3292 if (field_no == 0) {
3300 doc_len += (exp) ? len + 1 : len;
3308 result_doc->
charset = doc_charset;
3320 fts_fetch_doc_from_rec(
3332 const rec_t* clust_rec;
3339 ulint processed_doc = 0;
3348 clust_rec = btr_pcur_get_rec(pcur);
3353 ifield = dict_index_get_nth_field(index, i);
3362 (
int) (prtype & DATA_MYSQL_TYPE_MASK),
3372 static_cast<mem_heap_t*>(
3375 doc->
text.
f_str = (byte*) rec_get_nth_field(
3376 clust_rec, offsets, clust_pos,
3388 if (processed_doc == 0) {
3423 ibool is_id_cluster;
3444 clust_index = dict_table_get_first_index(table);
3449 is_id_cluster = (clust_index == fts_id_index);
3457 dfield = dtuple_get_nth_field(tuple, 0);
3459 dfield->
type.
prtype = DATA_NOT_NULL | DATA_UNSIGNED | DATA_BINARY_TYPE;
3464 btr_pcur_open_with_no_init(
3472 const rec_t* clust_rec;
3474 ulint* offsets = NULL;
3475 ulint num_idx = ib_vector_size(cache->
get_docs);
3477 rec = btr_pcur_get_rec(&pcur);
3486 if (is_id_cluster) {
3500 clust_ref, rec, fts_id_index, NULL, NULL);
3502 btr_pcur_open_with_no_init(
3503 clust_index, clust_ref, PAGE_CUR_LE,
3506 doc_pcur = &clust_pcur;
3507 clust_rec = btr_pcur_get_rec(&clust_pcur);
3511 offsets = rec_get_offsets(clust_rec, clust_index,
3512 NULL, ULINT_UNDEFINED, &heap);
3514 for (ulint i = 0; i < num_idx; ++
i) {
3526 fts_fetch_doc_from_rec(
3527 get_doc, clust_index, doc_pcur, offsets, &doc);
3530 ibool success __attribute__((unused));
3535 rw_lock_x_lock(&table->fts->
cache->
lock);
3542 rw_lock_x_unlock(&table->fts->
cache->
lock);
3545 "fts_instrument_sync",
3546 fts_sync(cache->
sync);
3551 fts_sync(cache->
sync);
3556 if (i < num_idx - 1) {
3558 success = btr_pcur_restore_position(
3569 if (!is_id_cluster) {
3594 ulint* value =
static_cast<ulint*
>(user_arg);
3597 void* data = dfield_get_data(dfield);
3600 static_cast<const byte*>(data)));
3626 dfield = dict_index_get_nth_field(index, 0);
3639 const rec_t* rec = NULL;
3640 ulint offsets_[REC_OFFS_NORMAL_SIZE];
3641 ulint* offsets = offsets_;
3646 rec_offs_init(offsets_);
3649 rec = btr_pcur_get_rec(&pcur);
3660 offsets = rec_get_offsets(
3661 rec, index, offsets, ULINT_UNDEFINED, &heap);
3663 data = rec_get_nth_field(rec, offsets, 0, &len);
3666 static_cast<const byte*>(data)));
3695 const char* select_str;
3701 trx->
op_info =
"fetching indexed FTS document";
3707 if (get_doc && get_doc->get_document_graph) {
3708 info = get_doc->get_document_graph->
info;
3721 if (!get_doc || !get_doc->get_document_graph) {
3727 "DECLARE FUNCTION my_func;\n"
3728 "DECLARE CURSOR c IS"
3729 " SELECT %s FROM $table_name"
3730 " WHERE %s = :doc_id;\n"
3734 "WHILE 1 = 1 LOOP\n"
3735 " FETCH c INTO my_func();\n"
3736 " IF c %% NOTFOUND THEN\n"
3743 ut_ad(option == FTS_FETCH_DOC_BY_ID_LARGE);
3763 "DECLARE FUNCTION my_func;\n"
3764 "DECLARE CURSOR c IS"
3765 " SELECT %s, %s FROM $table_name"
3766 " WHERE %s > :doc_id;\n"
3770 "WHILE 1 = 1 LOOP\n"
3771 " FETCH c INTO my_func();\n"
3772 " IF c %% NOTFOUND THEN\n"
3781 get_doc->get_document_graph = graph;
3784 graph = get_doc->get_document_graph;
3789 if (error == DB_SUCCESS) {
3798 fts_que_graph_free(graph);
3819 ib_uint32_t doc_count;
3825 info = (*graph)->info;
3845 info,
"doc_count", (
const ib_uint32_t*) &doc_count);
3848 pars_info_bind_literal(
3850 DATA_BLOB, DATA_BINARY_TYPE);
3857 "INSERT INTO \"%s\" VALUES "
3858 "(:token, :first_doc_id,"
3859 " :last_doc_id, :doc_count, :ilist);");
3864 elapsed_time +=
ut_time() - start_time;
3873 static __attribute__((nonnull, warn_unused_result))
3875 fts_sync_add_deleted_cache(
3886 ulint n_elems = ib_vector_size(doc_ids);
3888 ut_a(ib_vector_size(doc_ids) > 0);
3902 "BEGIN INSERT INTO \"%s\" VALUES (:doc_id);");
3904 for (i = 0; i < n_elems && error == DB_SUCCESS; ++
i) {
3917 fts_que_graph_free(graph);
3925 static __attribute__((nonnull, warn_unused_result))
3927 fts_sync_write_words(
3938 ibool print_error = FALSE;
3939 #ifdef FTS_DOC_STATS_DEBUG
3941 ulint n_new_words = 0;
3944 FTS_INIT_INDEX_TABLE(
3947 n_words = rbt_size(index_cache->words);
3951 for (rbt_node =
rbt_first(index_cache->words);
3953 rbt_node =
rbt_first(index_cache->words)) {
3967 #ifdef FTS_DOC_STATS_DEBUG
3971 ibool found = FALSE;
3973 error = fts_is_word_in_index(
3975 &index_cache->sel_graph[selected],
3977 &word->
text, &found);
3979 if (error == DB_SUCCESS && !found) {
3986 n_nodes += ib_vector_size(word->
nodes);
3990 for (i = 0; i < ib_vector_size(word->
nodes); ++
i) {
3995 if (error == DB_SUCCESS) {
3999 &index_cache->ins_graph[selected],
4000 &fts_table, &word->
text, fts_node);
4004 fts_node->
ilist = NULL;
4007 if (error != DB_SUCCESS && !print_error) {
4009 fprintf(stderr,
" InnoDB: Error (%s) writing "
4010 "word node to FTS auxiliary index "
4020 #ifdef FTS_DOC_STATS_DEBUG
4034 printf(
"Avg number of nodes: %lf\n",
4035 (
double) n_nodes / (
double) (n_words > 1 ? n_words : 1));
4041 #ifdef FTS_DOC_STATS_DEBUG
4045 static __attribute__((nonnull, warn_unused_result))
4047 fts_sync_write_doc_stat(
4057 ib_uint32_t word_count;
4060 info = (*graph)->info;
4068 info,
"count", (
const ib_uint32_t*) &word_count);
4077 FTS_INIT_INDEX_TABLE(
4083 "BEGIN INSERT INTO \"%s\" VALUES (:doc_id, :count);");
4089 if (error == DB_SUCCESS) {
4096 fprintf(stderr,
" InnoDB: Warning: lock wait "
4097 "timeout writing to FTS doc_id. "
4100 trx->error_state = DB_SUCCESS;
4102 fprintf(stderr,
" InnoDB: Error: (%s) "
4103 "while writing to FTS doc_id.\n",
4119 fts_sync_write_doc_stats(
4125 que_t* graph = NULL;
4132 doc_stat =
static_cast<ts_doc_stats_t*
>(
4136 error = fts_sync_write_doc_stat(
4137 trx, index_cache->
index, &graph, doc_stat);
4139 if (error != DB_SUCCESS) {
4147 doc_stat =
static_cast<ts_doc_stats_t*
>(
4151 if (graph != NULL) {
4171 ibool* found =
static_cast<ibool*
>(user_arg);
4179 if (len != UNIV_SQL_NULL && len != 0) {
4194 fts_is_word_in_index(
4206 trx->
op_info =
"looking up word in FTS index";
4209 info = (*graph)->info;
4217 if (*graph == NULL) {
4221 "DECLARE FUNCTION my_func;\n"
4222 "DECLARE CURSOR c IS"
4223 " SELECT doc_count\n"
4225 " WHERE word = :word "
4226 " ORDER BY first_doc_id;\n"
4230 "WHILE 1 = 1 LOOP\n"
4231 " FETCH c INTO my_func();\n"
4232 " IF c % NOTFOUND THEN\n"
4242 if (error == DB_SUCCESS) {
4249 fprintf(stderr,
" InnoDB: Warning: lock wait "
4250 "timeout reading FTS index. "
4255 fprintf(stderr,
" InnoDB: Error: (%s) "
4256 "while reading FTS index.\n",
4287 "FTS SYNC for table %s, deleted count: %ld size: "
4299 static __attribute__((nonnull, warn_unused_result))
4306 trx_t* trx = sync->trx;
4309 trx->
op_info =
"doing SYNC index";
4313 "SYNC words: %ld", rbt_size(index_cache->words));
4318 error = fts_sync_write_words(trx, index_cache);
4320 #ifdef FTS_DOC_STATS_DEBUG
4325 if (error == DB_SUCCESS) {
4327 error = fts_sync_write_doc_stats(trx, index_cache);
4337 static __attribute__((nonnull, warn_unused_result))
4344 trx_t* trx = sync->trx;
4348 trx->
op_info =
"doing SYNC commit";
4352 error = fts_cmp_set_sync_doc_id(sync->table, sync->max_doc_id, FALSE,
4359 if (error == DB_SUCCESS && ib_vector_size(cache->
deleted_doc_ids) > 0) {
4361 error = fts_sync_add_deleted_cache(
4371 rw_lock_x_unlock(&cache->
lock);
4373 if (error == DB_SUCCESS) {
4377 }
else if (error != DB_SUCCESS) {
4382 fprintf(stderr,
" InnoDB: Error: (%s) during SYNC.\n",
4388 "SYNC for table %s: SYNC time : %lu secs: "
4389 "elapsed %lf ins/sec",
4391 (ulong) (
ut_time() - sync->start_time),
4392 (
double) n_nodes/ (
double) elapsed_time);
4411 rw_lock_x_unlock(&cache->
lock);
4431 rw_lock_x_lock(&cache->
lock);
4433 fts_sync_begin(sync);
4435 for (i = 0; i < ib_vector_size(cache->
indexes); ++
i) {
4441 error = fts_sync_index(sync, index_cache);
4449 DBUG_EXECUTE_IF(
"fts_instrument_sync_interrupted",
4454 error = fts_sync_commit(sync);
4456 fts_sync_rollback(sync);
4484 if (table->fts->
cache) {
4514 result_doc = (result) ? result : doc;
4540 t_str.
f_str =
static_cast<byte*
>(
4547 t_str.
f_len = newlen;
4559 result_doc->
self_heap,
sizeof(ulint), 32);
4565 result_doc->
tokens, &parent, &new_token);
4570 #ifdef FTS_CHARSET_DEBUG
4571 offset += start_pos + add_pos;
4574 offset += start_pos + ret - str.
f_len + add_pos;
4577 ib_vector_push(token->
positions, &offset);
4602 for (ulint i = 0; i < doc->
text.
f_len; i += inc) {
4603 inc = fts_process_token(doc, result, i, 0);
4625 for (ulint i = 0; i < doc->
text.
f_len; i += inc) {
4626 inc = fts_process_token(doc, result, i, add_pos);
4644 #ifdef UNIV_SYNC_DEBUG
4648 get_docs = ib_vector_create(
4653 for (i = 0; i < ib_vector_size(cache->
indexes); ++
i) {
4662 ib_vector_push(get_docs, NULL));
4664 memset(get_doc, 0x0,
sizeof(*get_doc));
4667 get_doc->
cache = cache;
4687 for (i = 0; i < ib_vector_size(get_docs); ++
i) {
4692 if (get_doc->get_document_graph != NULL) {
4696 fts_que_graph_free(get_doc->get_document_graph);
4697 get_doc->get_document_graph = NULL;
4713 rw_lock_x_lock(&table->fts->
cache->
lock);
4717 rw_lock_x_unlock(&table->fts->
cache->
lock);
4721 DEBUG_SYNC_C(
"fts_initialize_doc_id");
4725 fts_cmp_set_sync_doc_id(table, 0, FALSE, &max_doc_id);
4738 rw_lock_x_unlock(&table->fts->
cache->
lock);
4740 ut_ad(max_doc_id > 0);
4745 #ifdef FTS_MULT_INDEX
4751 fts_is_index_updated(
4760 for (i = 0; i < ib_vector_size(fts_indexes); ++
i) {
4764 ib_vector_getp_const(fts_indexes, i));
4766 ut_a(updated_fts_index != NULL);
4768 if (updated_fts_index == index) {
4794 trx->
op_info =
"fetching FT table rows count";
4803 "DECLARE FUNCTION my_func;\n"
4804 "DECLARE CURSOR c IS"
4810 "WHILE 1 = 1 LOOP\n"
4811 " FETCH c INTO my_func();\n"
4812 " IF c % NOTFOUND THEN\n"
4821 if (error == DB_SUCCESS) {
4831 fprintf(stderr,
" InnoDB: Warning: lock wait "
4832 "timeout reading FTS table. "
4837 fprintf(stderr,
" InnoDB: Error: (%s) "
4838 "while reading FTS table.\n",
4846 fts_que_graph_free(graph);
4853 #ifdef FTS_CACHE_SIZE_DEBUG
4858 fts_update_max_cache_size(
4882 fts_trx_table_rows_free(
4905 ut_a(rbt_empty(rows));
4921 if (tables == NULL) {
4933 if (ftt->
rows != NULL) {
4934 fts_trx_table_rows_free(ftt->
rows);
4945 if (ftt->docs_added_graph) {
4946 fts_que_graph_free(ftt->docs_added_graph);
4953 ut_a(rbt_empty(tables));
4955 savepoint->
tables = NULL;
4968 for (i = 0; i < ib_vector_size(fts_trx->
savepoints); ++
i) {
4979 fts_savepoint_free(savepoint);
4982 for (i = 0; i < ib_vector_size(fts_trx->
last_stmt); ++
i) {
4993 fts_savepoint_free(savepoint);
4996 if (fts_trx->
heap) {
5017 field = dtuple_get_nth_field(row, table->fts->
doc_col);
5020 ut_a(dfield_get_type(field)->mtype == DATA_INT);
5023 static_cast<const byte*>(dfield_get_data(field)));
5044 ulint offsets_[REC_OFFS_NORMAL_SIZE];
5045 ulint* offsets = offsets_;
5050 clust_index = dict_table_get_first_index(table);
5052 rec_offs_init(offsets_);
5054 offsets = rec_get_offsets(
5055 rec, clust_index, offsets, ULINT_UNDEFINED, &my_heap);
5059 ut_ad(col_no != ULINT_UNDEFINED);
5061 data = rec_get_nth_field(rec, offsets, col_no, &len);
5064 ut_ad(8 ==
sizeof(doc_id));
5067 if (my_heap && !heap) {
5086 return(static_cast<fts_index_cache_t*>(
5102 #ifdef UNIV_SYNC_DEBUG
5115 nodes = word->
nodes;
5133 #ifdef UNIV_SYNC_DEBUG
5143 if (doc_id == update->
doc_id) {
5171 ib_vector_push(vector, &update->
doc_id);
5198 fts_t* fts = table->fts;
5229 fprintf(stderr,
" InnoDB: Error the background thread "
5230 "for the FTS table %s refuses to start\n",
5254 DATA_NOT_NULL | DATA_UNSIGNED
5255 | DATA_BINARY_TYPE | DATA_FTS_DOC_ID, 0),
5275 doc_id = *next_doc_id;
5281 if (error == DB_SUCCESS) {
5288 clust_index = dict_table_get_first_index(table);
5312 fts_dict_table_has_fts_index(
5338 memset(fts, 0x0,
sizeof(*fts));
5342 fts->
doc_col = ULINT_UNDEFINED;
5346 SYNC_FTS_BG_THREADS);
5348 heap_alloc = ib_heap_allocator_create(heap);
5363 fts_t* fts = table->fts;
5411 dict_table_wait_for_bg_threads_to_exit(table, 20000);
5437 ftt_dst = fts_trx_table_clone(*ftt_src);
5460 heap = fts_trx->
heap;
5467 savepoint = fts_savepoint_create(fts_trx->
savepoints, name, heap);
5469 if (last_savepoint->
tables != NULL) {
5470 fts_savepoint_copy(last_savepoint, savepoint);
5479 fts_savepoint_lookup(
5486 ut_a(ib_vector_size(savepoints) > 0);
5488 for (i = 1; i < ib_vector_size(savepoints); ++
i) {
5494 if (strcmp(name, savepoint->
name) == 0) {
5499 return(ULINT_UNDEFINED);
5515 ulint top_of_stack = 0;
5521 ut_a(ib_vector_size(savepoints) > 0);
5524 for (i = 1; i < ib_vector_size(savepoints); ++
i) {
5534 if (savepoint->
name != NULL
5535 && strcmp(name, savepoint->
name) == 0) {
5540 }
else if (savepoint->
name != NULL) {
5548 if (i < ib_vector_size(savepoints)) {
5550 ut_a(top_of_stack < ib_vector_size(savepoints));
5553 for (i = ib_vector_size(savepoints) - 1;
5563 if (savepoint->
name != NULL) {
5564 savepoint->
name = NULL;
5565 fts_savepoint_free(savepoint);
5568 ib_vector_pop(savepoints);
5572 ut_a(ib_vector_size(savepoints) > 0);
5575 ut_a(ib_vector_size(savepoints) == (top_of_stack + 1));
5595 fts_savepoint_free(savepoint);
5598 savepoint = fts_savepoint_create(fts_trx->
last_stmt, NULL, NULL);
5614 l_rows = l_ftt->
rows;
5615 s_rows = s_ftt->
rows;
5625 if (parent.result == 0) {
5629 switch (l_row->
state) {
5635 if (s_row->
state == FTS_NOTHING) {
5636 s_row->
state = FTS_INSERT;
5637 }
else if (s_row->
state == FTS_DELETE) {
5639 s_rows, parent.last));
5675 savepoint =
static_cast<fts_savepoint_t*
>(ib_vector_last(savepoints));
5679 l_tables = last_stmt->
tables;
5680 s_tables = savepoint->
tables;
5691 s_tables, &parent, &(*l_ftt)->table->id,
5694 if (parent.result == 0) {
5699 fts_undo_last_stmt(*s_ftt, *l_ftt);
5723 i = fts_savepoint_lookup(savepoints, name);
5725 if (i != ULINT_UNDEFINED) {
5730 while (ib_vector_size(savepoints) > i) {
5734 ib_vector_pop(savepoints));
5736 if (savepoint->
name != NULL) {
5740 savepoint->
name = NULL;
5742 fts_savepoint_free(savepoint);
5750 for (savepoint = static_cast<fts_savepoint_t*>(
5751 ib_vector_last(savepoints));
5752 ib_vector_size(savepoints) > 1
5753 && savepoint->
name == NULL;
5755 ib_vector_last(savepoints))) {
5757 ib_vector_pop(savepoints);
5761 ut_a(ib_vector_size(savepoints) > 0);
5770 fts_is_aux_table_name(
5778 char my_name[MAX_FULL_NAME_LEN + 1];
5780 ut_ad(len <= MAX_FULL_NAME_LEN);
5783 end = my_name + len;
5785 ptr =
static_cast<const char*
>(memchr(my_name,
'/', len));
5795 if (ptr != NULL && len > 20 && strncmp(ptr,
"FTS_", 4) == 0) {
5808 ptr =
static_cast<const char*
>(memchr(ptr,
'_', len));
5820 for (i = 0; fts_common_tables[
i] != NULL; ++
i) {
5822 if (strncmp(ptr, fts_common_tables[i], len) == 0) {
5833 ptr =
static_cast<const char*
>(memchr(ptr,
'_', len));
5845 for (i = 0; fts_index_selector[
i].
value; ++
i) {
5853 if (strncmp(ptr,
"DOC_ID", len) == 0) {
5880 ut_a(tables->allocator->arg != NULL);
5883 heap =
static_cast<mem_heap_t*
>(tables->allocator->arg);
5886 memset(table, 0x0,
sizeof(*table));
5892 void* data = dfield_get_data(dfield);
5895 ut_a(len != UNIV_SQL_NULL);
5901 if (!fts_is_aux_table_name(
5902 table, static_cast<const char*>(data), len)) {
5903 ib_vector_pop(tables);
5908 table->
name =
static_cast<char*
>(
5910 memcpy(table->
name, data, len);
5911 table->
name[len] = 0;
5917 static_cast<const byte*>(data));
5932 static __attribute__((nonnull))
5934 fts_check_and_drop_orphaned_tables(
5939 for (ulint i = 0; i < ib_vector_size(tables); ++
i) {
5950 if (table == NULL || table->fts == NULL) {
5954 }
else if (aux_table->
index_id != 0) {
5964 j < ib_vector_size(fts->
indexes);
5970 ib_vector_getp_const(fts->
indexes, j));
5972 if (index->
id ==
id) {
5987 "Parent table of FTS auxiliary table %s not "
5988 "found.", aux_table->
name);
5990 dberr_t err = fts_drop_table(trx, aux_table->
name);
5992 if (err == DB_FAIL) {
5996 aux_table->
name,
false);
5998 os_file_delete_if_exists(innodb_file_data_key,
6021 space_name_list_t space_name_list;
6027 if (error == DB_OUT_OF_MEMORY) {
6028 ib_logf(IB_LOG_LEVEL_ERROR,
"Out of memory");
6033 heap_alloc = ib_heap_allocator_create(heap);
6043 for (space_name_list_t::iterator it = space_name_list.begin();
6044 it != space_name_list.end();
6050 ib_vector_push(tables, NULL));
6052 memset(fts_aux_table, 0x0,
sizeof(*fts_aux_table));
6054 if (!fts_is_aux_table_name(fts_aux_table, *it, strlen(*it))) {
6055 ib_vector_pop(tables);
6057 ulint len = strlen(*it);
6063 ut_a(fts_aux_table->
id != ULINT_UNDEFINED);
6065 fts_aux_table->
name =
static_cast<char*
>(
6068 fts_aux_table->
name[len] = 0;
6073 trx->
op_info =
"dropping orphaned FTS tables";
6074 row_mysql_lock_data_dictionary(trx);
6083 "DECLARE FUNCTION my_func;\n"
6084 "DECLARE CURSOR c IS"
6086 " FROM SYS_TABLES;\n"
6090 "WHILE 1 = 1 LOOP\n"
6091 " FETCH c INTO my_func();\n"
6092 " IF c % NOTFOUND THEN\n"
6101 if (error == DB_SUCCESS) {
6102 fts_check_and_drop_orphaned_tables(trx, tables);
6106 ib_vector_reset(tables);
6114 "lock wait timeout reading SYS_TABLES. "
6120 "(%s) while reading SYS_TABLES.",
6139 for (space_name_list_t::iterator it = space_name_list.begin();
6140 it != space_name_list.end();
6155 const char* stopword_table_name)
6161 if (!stopword_table_name) {
6169 "InnoDB: user stopword table %s does not exist.\n",
6170 stopword_table_name);
6174 const char* col_name;
6180 "InnoDB: invalid column name for stopword "
6181 "table %s. Its first column must be named as "
6182 "'value'.\n", stopword_table_name);
6187 col = dict_table_get_nth_col(table, 0);
6189 if (col->
mtype != DATA_VARCHAR
6190 && col->
mtype != DATA_VARMYSQL) {
6192 "InnoDB: invalid column type for stopword "
6193 "table %s. Its first column must be of "
6194 "varchar type\n", stopword_table_name);
6203 static_cast<int>(col->
prtype & DATA_MYSQL_TYPE_MASK),
6220 const char* global_stopword_table,
6222 const char* session_stopword_table,
6224 ibool stopword_is_on,
6234 const char* stopword_to_use = NULL;
6235 ibool new_trx = FALSE;
6236 byte str_buffer[MAX_FULL_NAME_LEN + 1];
6240 cache = table->fts->
cache;
6249 trx->
op_info =
"upload FTS stopword";
6258 use_stopword = (ulint) stopword_is_on;
6264 if (error != DB_SUCCESS) {
6270 if (!use_stopword) {
6279 str.
f_str = str_buffer;
6280 str.
f_len =
sizeof(str_buffer) - 1;
6285 if (error != DB_SUCCESS) {
6289 if (strlen((
char*) str.
f_str) > 0) {
6290 stopword_to_use = (
const char*) str.
f_str;
6293 stopword_to_use = (session_stopword_table)
6294 ? session_stopword_table : global_stopword_table;
6298 && fts_load_user_stopword(table->fts, stopword_to_use,
6304 str.
f_str = (byte*) stopword_to_use;
6317 if (error == DB_SUCCESS) {
6331 return(error == DB_SUCCESS);
6340 fts_init_get_doc_id(
6355 dtype_t* type = dfield_get_type(dfield);
6356 void* data = dfield_get_data(dfield);
6361 static_cast<const byte*>(data)));
6378 fts_init_recover_doc(
6403 if (field_no == 0) {
6404 dtype_t* type = dfield_get_type(dfield);
6405 void* data = dfield_get_data(dfield);
6410 static_cast<const byte*>(data)));
6417 if (len == UNIV_SQL_NULL) {
6429 (
int)(prtype & DATA_MYSQL_TYPE_MASK),
6441 static_cast<byte*>(dfield_get_data(dfield)),
6443 static_cast<mem_heap_t*>(doc.
self_heap->arg));
6446 dfield_get_data(dfield));
6451 if (field_no == 1) {
6459 doc_len += (exp) ? len + 1 : len;
6488 ibool has_cache_lock)
6495 bool need_init =
false;
6500 if (!has_cache_lock) {
6501 rw_lock_x_lock(&cache->
lock);
6519 fts_cmp_set_sync_doc_id(table, 0, TRUE, &start_doc);
6532 FTS_FETCH_DOC_BY_ID_LARGE,
6533 fts_init_get_doc_id, cache);
6540 for (ulint i = 0; i < ib_vector_size(cache->
get_docs); ++
i) {
6547 FTS_FETCH_DOC_BY_ID_LARGE,
6548 fts_init_recover_doc, get_doc);
6554 fts_get_docs_clear(cache->
get_docs);
6557 if (!has_cache_lock) {
6558 rw_lock_x_unlock(&cache->
lock);