Skip to content

Commit 2ab8e1a

Browse files
author
Jimmy Yang
committed
Better handle the Doc ID update if it is supplied by user. Still such
Doc ID would follow rules set up for internal supplied Doc ID, and ID of zero is not allowed, and not tokenized.
1 parent a95a33e commit 2ab8e1a

16 files changed

Lines changed: 204 additions & 80 deletions

File tree

include/my_base.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,8 @@ enum ha_base_keytype {
448448
/* There's no explicitly listed partition in table for the given value */
449449
#define HA_ERR_NOT_IN_LOCK_PARTITIONS 178
450450
#define HA_ERR_INDEX_COL_TOO_LONG 179 /* Index column length exceeds limit */
451-
#define HA_ERR_LAST 179 /* Copy of last error nr */
451+
#define HA_FTS_INVALID_DOCID 180 /* Invalid InnoDB Doc ID */
452+
#define HA_ERR_LAST 180 /* Copy of last error nr */
452453

453454
/* Number of different errors */
454455
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)

mysql-test/suite/innodb_fts/r/innodb_fts_large_records.result

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ SELECT * FROM t1
5050
WHERE MATCH (a,b)
5151
AGAINST ('"row5col2word48 row5col2word49"@10' IN BOOLEAN MODE);
5252
FTS_DOC_ID a b
53-
UPDATE t1 SET a = "using update" , b = "changing fulltext index record"
53+
UPDATE t1 SET a = "using update" , b = "changing fulltext index record", FTS_DOC_ID = FTS_DOC_ID + 10000
5454
WHERE MATCH(a,b) AGAINST("+row5col2word49 +row5col1word49" IN BOOLEAN MODE);
5555
select sleep(1);
5656
sleep(1)
@@ -121,7 +121,7 @@ SELECT * FROM t1
121121
WHERE MATCH (a,b)
122122
AGAINST ('"row5col2word48 row5col2word49"@10' IN BOOLEAN MODE);
123123
FTS_DOC_ID a b
124-
UPDATE t1 SET a = "using update" , b = "changing fulltext index record"
124+
UPDATE t1 SET a = "using update" , b = "changing fulltext index record", FTS_DOC_ID = FTS_DOC_ID + 10000
125125
WHERE MATCH(a,b) AGAINST("+row5col2word49 +row5col1word49" IN BOOLEAN MODE);
126126
select a,b from t1 where MATCH(a,b) AGAINST("+row5col2word49 +row5col1word49" IN BOOLEAN MODE);
127127
a b
@@ -178,7 +178,7 @@ count(*)
178178
select count(*) from t1 where MATCH(a,b) AGAINST ("samerowword" WITH QUERY EXPANSION);
179179
count(*)
180180
5000
181-
UPDATE t1 SET a = "using update" , b = "changing fulltext index record"
181+
UPDATE t1 SET a = "using update" , b = "changing fulltext index record", FTS_DOC_ID = FTS_DOC_ID + 10000
182182
WHERE MATCH(a,b) AGAINST("+samerowword +samerowword" IN BOOLEAN MODE);
183183
select count(*) from t1 where MATCH(a,b) AGAINST("+samerowword +samerowword" IN BOOLEAN MODE);
184184
count(*)
@@ -243,7 +243,7 @@ count(*)
243243
select count(*) from t1 where MATCH(a,b) AGAINST ("samerowword" WITH QUERY EXPANSION);
244244
count(*)
245245
5000
246-
UPDATE t1 SET a = "using update" , b = "changing fulltext index record"
246+
UPDATE t1 SET a = "using update" , b = "changing fulltext index record", FTS_DOC_ID = FTS_DOC_ID + 10000
247247
WHERE MATCH(a,b) AGAINST("+samerowword +1050" IN BOOLEAN MODE);
248248
select sleep(1);
249249
sleep(1)

mysql-test/suite/innodb_fts/t/innodb_fts_large_records.test

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ SELECT * FROM t1
7272
WHERE MATCH (a,b)
7373
AGAINST ('"row5col2word48 row5col2word49"@10' IN BOOLEAN MODE);
7474

75-
UPDATE t1 SET a = "using update" , b = "changing fulltext index record"
75+
UPDATE t1 SET a = "using update" , b = "changing fulltext index record", FTS_DOC_ID = FTS_DOC_ID + 10000
7676
WHERE MATCH(a,b) AGAINST("+row5col2word49 +row5col1word49" IN BOOLEAN MODE);
7777

7878
select sleep(1);
@@ -157,7 +157,7 @@ SELECT * FROM t1
157157
WHERE MATCH (a,b)
158158
AGAINST ('"row5col2word48 row5col2word49"@10' IN BOOLEAN MODE);
159159

160-
UPDATE t1 SET a = "using update" , b = "changing fulltext index record"
160+
UPDATE t1 SET a = "using update" , b = "changing fulltext index record", FTS_DOC_ID = FTS_DOC_ID + 10000
161161
WHERE MATCH(a,b) AGAINST("+row5col2word49 +row5col1word49" IN BOOLEAN MODE);
162162

163163
select a,b from t1 where MATCH(a,b) AGAINST("+row5col2word49 +row5col1word49" IN BOOLEAN MODE);
@@ -237,7 +237,7 @@ select count(*) from t1 where MATCH a,b AGAINST ("+sameroww" IN BOOLEAN MODE);
237237
select count(*) from t1 where MATCH(a,b) AGAINST ("samerowword" WITH QUERY EXPANSION);
238238

239239

240-
UPDATE t1 SET a = "using update" , b = "changing fulltext index record"
240+
UPDATE t1 SET a = "using update" , b = "changing fulltext index record", FTS_DOC_ID = FTS_DOC_ID + 10000
241241
WHERE MATCH(a,b) AGAINST("+samerowword +samerowword" IN BOOLEAN MODE);
242242

243243
select count(*) from t1 where MATCH(a,b) AGAINST("+samerowword +samerowword" IN BOOLEAN MODE);
@@ -321,7 +321,7 @@ select count(*) from t1 where MATCH a,b AGAINST ("+2001" IN BOOLEAN MODE);
321321
select count(*) from t1 where MATCH(a,b) AGAINST ("samerowword" WITH QUERY EXPANSION);
322322

323323

324-
UPDATE t1 SET a = "using update" , b = "changing fulltext index record"
324+
UPDATE t1 SET a = "using update" , b = "changing fulltext index record", FTS_DOC_ID = FTS_DOC_ID + 10000
325325
WHERE MATCH(a,b) AGAINST("+samerowword +1050" IN BOOLEAN MODE);
326326

327327
select sleep(1);

mysys/my_handler_errors.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ static const char *handler_error_messages[]=
8282
"Read page with wrong checksum",
8383
"Too many active concurrent transactions",
8484
"Record not matching the given partition set",
85-
"Index column length exceeds limit"
85+
"Index column length exceeds limit",
86+
"Invalid InnoDB FTS Doc ID"
8687
};
8788

8889
extern void my_handler_error_register(void);

sql/handler.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ int ha_init_errors(void)
399399
SETMSG(HA_ERR_AUTOINC_ERANGE, ER_DEFAULT(ER_WARN_DATA_OUT_OF_RANGE));
400400
SETMSG(HA_ERR_TOO_MANY_CONCURRENT_TRXS, ER_DEFAULT(ER_TOO_MANY_CONCURRENT_TRXS));
401401
SETMSG(HA_ERR_INDEX_COL_TOO_LONG, ER_DEFAULT(ER_INDEX_COLUMN_TOO_LONG));
402+
SETMSG(HA_FTS_INVALID_DOCID, "Invalid InnoDB FTS Doc ID");
402403

403404
/* Register the error messages for use with my_error(). */
404405
return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST);

storage/innobase/fut/fut0fut.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,7 +2527,12 @@ fts_delete(
25272527
pars_info_t* info = pars_info_create();
25282528
fts_cache_t* cache = table->fts->cache;
25292529

2530-
ut_a(doc_id != 0);
2530+
/* we do not index Documents whose Doc ID value is 0 */
2531+
if (doc_id == 0) {
2532+
ut_ad(!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID));
2533+
return(error);
2534+
}
2535+
25312536
ut_a(row->state == FTS_DELETE || row->state == FTS_MODIFY);
25322537

25332538
FTS_INIT_FTS_TABLE(&fts_table, "DELETED", FTS_COMMON_TABLE, table);
@@ -4987,9 +4992,6 @@ fts_get_doc_id_from_row(
49874992

49884993
doc_id = fts_read_doc_id(dfield_get_data(field));
49894994

4990-
/* Must not be 0. */
4991-
ut_ad(doc_id > 0);
4992-
49934995
return(doc_id);
49944996
}
49954997

@@ -5033,9 +5035,6 @@ fts_get_doc_id_from_rec(
50335035
ut_a(len == sizeof(doc_id));
50345036
doc_id = (doc_id_t) mach_read_from_8(data);
50355037

5036-
/* Must not be 0. */
5037-
ut_a(doc_id > 0);
5038-
50395038
return(doc_id);
50405039
}
50415040

@@ -5236,11 +5235,15 @@ fts_update_doc_id(
52365235
upd_field_t* ufield, /* out: update node */
52375236
doc_id_t* next_doc_id) /* out: buffer for writing */
52385237
{
5239-
ulint error;
5238+
ulint error = DB_SUCCESS;
52405239
doc_id_t doc_id;
52415240

5242-
/* Get the new document id that will be added. */
5243-
error = fts_get_next_doc_id(table, &doc_id);
5241+
if (*next_doc_id) {
5242+
doc_id = *next_doc_id;
5243+
} else {
5244+
/* Get the new document id that will be added. */
5245+
error = fts_get_next_doc_id(table, &doc_id);
5246+
}
52445247

52455248
if (error == DB_SUCCESS) {
52465249
dict_index_t* clust_index;

storage/innobase/handler/ha_innodb.cc

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,9 @@ convert_error_code_to_mysql(
12551255
case DB_PRIMARY_KEY_IS_NULL:
12561256
return(ER_PRIMARY_CANT_HAVE_NULL);
12571257

1258+
case DB_FTS_INVALID_DOCID:
1259+
return(HA_FTS_INVALID_DOCID);
1260+
12581261
case DB_TOO_MANY_CONCURRENT_TRXS:
12591262
/* New error code HA_ERR_TOO_MANY_CONCURRENT_TRXS is only
12601263
available in 5.1.38 and later, but the plugin should still
@@ -1372,6 +1375,16 @@ innobase_strcasecmp(
13721375
const char* a, /*!< in: first string to compare */
13731376
const char* b) /*!< in: second string to compare */
13741377
{
1378+
if (!a) {
1379+
if (!b) {
1380+
return(0);
1381+
} else {
1382+
return(-1);
1383+
}
1384+
} else if (!b) {
1385+
return(1);
1386+
}
1387+
13751388
return(my_strcasecmp(system_charset_info, a, b));
13761389
}
13771390

@@ -5944,6 +5957,10 @@ ha_innobase::write_row(
59445957
prebuilt->table->flags,
59455958
user_thd);
59465959

5960+
if (error_result == HA_FTS_INVALID_DOCID) {
5961+
my_error(HA_FTS_INVALID_DOCID, MYF(0));
5962+
}
5963+
59475964
func_exit:
59485965
innobase_active_small();
59495966

@@ -5987,7 +6004,9 @@ calc_row_difference(
59876004
uint i;
59886005
ulint error = DB_SUCCESS;
59896006
ibool changes_fts_column = FALSE;
6007+
ibool changes_fts_doc_col = FALSE;
59906008
trx_t* trx = thd_to_trx(thd);
6009+
doc_id_t doc_id = 0;
59916010

59926011
n_fields = table->s->fields;
59936012
clust_index = dict_table_get_first_index(prebuilt->table);
@@ -6048,6 +6067,18 @@ calc_row_difference(
60486067
;
60496068
}
60506069

6070+
if (field_mysql_type == MYSQL_TYPE_LONGLONG
6071+
&& prebuilt->table->fts
6072+
&& innobase_strcasecmp(
6073+
field->field_name, FTS_DOC_ID_COL_NAME) == 0) {
6074+
doc_id = (doc_id_t) mach_read_from_n_little_endian(
6075+
n_ptr, 8);
6076+
if (doc_id == 0) {
6077+
return(DB_FTS_INVALID_DOCID);
6078+
}
6079+
}
6080+
6081+
60516082
if (field->null_ptr) {
60526083
if (field_in_record_is_null(table, field,
60536084
(char*) old_row)) {
@@ -6100,19 +6131,25 @@ calc_row_difference(
61006131
checking only once here. Later we will need to
61016132
note which columns have been updated and do
61026133
selective processing. */
6103-
if (prebuilt->table->fts != NULL
6104-
&& !changes_fts_column) {
6105-
6134+
if (prebuilt->table->fts != NULL) {
61066135
ulint offset;
61076136
dict_table_t* innodb_table;
61086137

61096138
innodb_table = prebuilt->table;
61106139

6111-
offset = row_upd_changes_fts_column(
6112-
innodb_table, ufield);
6140+
if (!changes_fts_column) {
6141+
offset = row_upd_changes_fts_column(
6142+
innodb_table, ufield);
61136143

6114-
if (offset != ULINT_UNDEFINED) {
6115-
changes_fts_column = TRUE;
6144+
if (offset != ULINT_UNDEFINED) {
6145+
changes_fts_column = TRUE;
6146+
}
6147+
}
6148+
6149+
if (!changes_fts_doc_col) {
6150+
changes_fts_doc_col =
6151+
row_upd_changes_doc_id(
6152+
innodb_table, ufield);
61166153
}
61176154
}
61186155
}
@@ -6122,11 +6159,19 @@ calc_row_difference(
61226159
then add an update column node with a new document id to the
61236160
other changes. We piggy back our changes on the normal UPDATE
61246161
to reduce processing and IO overhead. */
6125-
if (prebuilt->table->fts != NULL && changes_fts_column) {
6162+
if (prebuilt->table->fts != NULL
6163+
&& (changes_fts_column || changes_fts_doc_col)) {
61266164
dict_table_t* innodb_table = prebuilt->table;
61276165

61286166
ufield = uvect->fields + n_changed;
61296167

6168+
if (!DICT_TF2_FLAG_IS_SET(
6169+
innodb_table, DICT_TF2_FTS_HAS_DOC_ID)) {
6170+
trx->fts_next_doc_id = doc_id;
6171+
} else {
6172+
trx->fts_next_doc_id = 0;
6173+
}
6174+
61306175
error = fts_update_doc_id(
61316176
innodb_table, ufield, &trx->fts_next_doc_id);
61326177

@@ -6186,10 +6231,14 @@ ha_innobase::update_row(
61866231
/* Build an update vector from the modified fields in the rows
61876232
(uses upd_buff of the handle) */
61886233

6189-
calc_row_difference(uvect, (uchar*) old_row, new_row, table,
6234+
error = calc_row_difference(uvect, (uchar*) old_row, new_row, table,
61906235
upd_buff, (ulint)upd_and_key_val_buff_len,
61916236
prebuilt, user_thd);
61926237

6238+
if (error != DB_SUCCESS) {
6239+
goto func_exit;
6240+
}
6241+
61936242
/* This is not a delete */
61946243
prebuilt->upd_node->is_delete = FALSE;
61956244

@@ -6241,6 +6290,7 @@ ha_innobase::update_row(
62416290

62426291
innodb_srv_conc_exit_innodb(trx);
62436292

6293+
func_exit:
62446294
error = convert_error_code_to_mysql(error,
62456295
prebuilt->table->flags, user_thd);
62466296

@@ -6252,6 +6302,8 @@ ha_innobase::update_row(
62526302
should not increase the count of updated rows.
62536303
This is fix for http://bugs.mysql.com/29157 */
62546304
error = HA_ERR_RECORD_IS_THE_SAME;
6305+
} else if (error == HA_FTS_INVALID_DOCID) {
6306+
my_error(HA_FTS_INVALID_DOCID, MYF(0));
62556307
}
62566308

62576309
/* Tell InnoDB server that there might be work for
@@ -9258,9 +9310,10 @@ ha_innobase::info_low(
92589310
- prebuilt->clust_index_was_generated;
92599311

92609312
if (table->s->keys != num_innodb_index
9261-
&& (innobase_fts_check_doc_id_index(ib_table, NULL)
9313+
&& (innobase_fts_check_doc_id_index(ib_table, NULL)
9314+
== FTS_EXIST_DOC_ID_INDEX
92629315
&& table->s->keys != (num_innodb_index - 1))) {
9263-
sql_print_error("Table %s contains %lu "
9316+
sql_print_error("InnoDB: Table %s contains %lu "
92649317
"indexes inside InnoDB, which "
92659318
"is different from the number of "
92669319
"indexes %u defined in the MySQL ",

storage/innobase/handler/ha_innodb.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,12 +458,17 @@ innobase_fts_load_stopword(
458458
/*=======================*/
459459
dict_table_t* table, /*!< Table has the FTS */
460460
THD* thd); /*!< current thread */
461+
462+
/** Some defines for innobase_fts_check_doc_id_index() return value */
463+
#define FTS_INCORRECT_DOC_ID_INDEX 1
464+
#define FTS_EXIST_DOC_ID_INDEX 2
465+
#define FTS_NOT_EXIST_DOC_ID_INDEX 3
461466
/*******************************************************************//**
462467
Check whether the table has a unique index with FTS_DOC_ID_INDEX_NAME
463468
on the Doc ID column.
464469
@return TRUE if there exists the FTS_DOC_ID index */
465470
extern "C"
466-
ibool
471+
ulint
467472
innobase_fts_check_doc_id_index(
468473
/*============================*/
469474
dict_table_t* table, /*!< in: table definition */

0 commit comments

Comments
 (0)