Skip to content

Commit a8c96ce

Browse files
author
Nisha Gopalakrishnan
committed
Bug#36234681: InnoDB: Failing assertion: result != FTS_INVALID
ANALYSIS DELETE operation on a table with self referential foreign key constraint and full text index may trigger an assert. When performing the DELETE operation, marking of deletion of the full text row happens twice due to the self referential foreign key constraint. Hence the state of the row becomes invalid and the assert is triggered. Fix Avoid updating the full text index if the foreign key has self referential constraint. Change-Id: I0c018b63f259b7b1c89c10de8e560d34a63bbd0c
1 parent 1eaeaa7 commit a8c96ce

File tree

3 files changed

+37
-30
lines changed

3 files changed

+37
-30
lines changed

storage/innobase/dict/dict0mem.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,28 @@ bool dict_foreign_set_validate(const dict_table_t &table) {
872872
return (dict_foreign_set_validate(table.foreign_set) &&
873873
dict_foreign_set_validate(table.referenced_set));
874874
}
875+
876+
bool dict_foreign_t::is_fts_col_affected() const {
877+
/* The check is skipped:
878+
- if the table has no full text index defined.
879+
- if it is a self referential foreign constaint. This is because
880+
in the context of cascading DML operation, only the referenced
881+
table is relevant for the validation even if the current table
882+
has FTS index.*/
883+
if (!foreign_table->fts || foreign_table == referenced_table) {
884+
return false;
885+
}
886+
887+
for (ulint i = 0; i < n_fields; i++) {
888+
const dict_col_t *col = foreign_index->get_col(i);
889+
if (dict_table_is_fts_column(foreign_table->fts->indexes,
890+
dict_col_get_no(col),
891+
col->is_virtual()) != ULINT_UNDEFINED) {
892+
return true;
893+
}
894+
}
895+
return false;
896+
}
875897
#endif /* !UNIV_HOTBACKUP */
876898

877899
std::ostream &operator<<(std::ostream &out, const dict_foreign_t &foreign) {

storage/innobase/include/dict0mem.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,6 +1698,15 @@ struct dict_foreign_t {
16981698

16991699
dict_vcol_set *v_cols; /*!< set of virtual columns affected
17001700
by foreign key constraint. */
1701+
1702+
/** Check whether foreign key constraint contains a column with a full
1703+
index on it. The function is used in the context of cascading DML
1704+
operations.
1705+
@retval true if the column has FTS index on it.
1706+
@retval false if the FK table has no FTS index or has self referential
1707+
relationship
1708+
*/
1709+
bool is_fts_col_affected() const;
17011710
};
17021711

17031712
std::ostream &operator<<(std::ostream &out, const dict_foreign_t &foreign);

storage/innobase/row/row0ins.cc

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ static bool row_ins_cascade_ancestor_updates_table(
490490

491491
n_fields_updated = 0;
492492

493-
*fts_col_affected = false;
493+
*fts_col_affected = foreign->is_fts_col_affected();
494494

495495
if (table->fts) {
496496
doc_id_pos = dict_table_get_nth_col_pos(table, table->fts->doc_col);
@@ -593,14 +593,6 @@ static bool row_ins_cascade_ancestor_updates_table(
593593
dfield_set_data(&ufield->new_val, padded_data, min_size);
594594
}
595595

596-
/* Check whether the current column has
597-
FTS index on it */
598-
if (table->fts &&
599-
dict_table_is_fts_column(table->fts->indexes, dict_col_get_no(col),
600-
col->is_virtual()) != ULINT_UNDEFINED) {
601-
*fts_col_affected = true;
602-
}
603-
604596
/* If Doc ID is updated, check whether the
605597
Doc ID is valid */
606598
if (table->fts && ufield->field_no == doc_id_pos) {
@@ -986,7 +978,6 @@ static void row_ins_foreign_fill_virtual(upd_node_t *cascade, const rec_t *rec,
986978
trx_t *trx;
987979
mem_heap_t *tmp_heap = nullptr;
988980
doc_id_t doc_id = FTS_NULL_DOC_ID;
989-
bool fts_col_affacted = false;
990981

991982
DBUG_TRACE;
992983
ut_a(thr);
@@ -1191,16 +1182,9 @@ static void row_ins_foreign_fill_virtual(upd_node_t *cascade, const rec_t *rec,
11911182
ufield->orig_len = 0;
11921183
ufield->exp = nullptr;
11931184
dfield_set_null(&ufield->new_val);
1194-
1195-
if (table->fts &&
1196-
dict_table_is_fts_column(table->fts->indexes, index->get_col_no(i),
1197-
index->get_col(i)->is_virtual()) !=
1198-
ULINT_UNDEFINED) {
1199-
fts_col_affacted = true;
1200-
}
12011185
}
12021186

1203-
if (fts_col_affacted) {
1187+
if (foreign->is_fts_col_affected()) {
12041188
fts_trx_add_op(trx, table, doc_id, FTS_DELETE, nullptr);
12051189
}
12061190

@@ -1215,26 +1199,18 @@ static void row_ins_foreign_fill_virtual(upd_node_t *cascade, const rec_t *rec,
12151199

12161200
} else if (table->fts && cascade->is_delete) {
12171201
/* DICT_FOREIGN_ON_DELETE_CASCADE case */
1218-
for (i = 0; i < foreign->n_fields; i++) {
1219-
if (table->fts &&
1220-
dict_table_is_fts_column(table->fts->indexes, index->get_col_no(i),
1221-
index->get_col(i)->is_virtual()) !=
1222-
ULINT_UNDEFINED) {
1223-
fts_col_affacted = true;
1224-
}
1225-
}
1226-
1227-
if (fts_col_affacted) {
1202+
if (foreign->is_fts_col_affected()) {
12281203
fts_trx_add_op(trx, table, doc_id, FTS_DELETE, nullptr);
12291204
}
12301205
}
12311206

12321207
if (!node->is_delete && (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)) {
1208+
bool fts_col_affected = false;
12331209
/* Build the appropriate update vector which sets changing
12341210
foreign->n_fields first fields in rec to new values */
12351211

12361212
n_to_update = row_ins_cascade_calc_update_vec(node, foreign, tmp_heap, trx,
1237-
&fts_col_affacted);
1213+
&fts_col_affected);
12381214

12391215
if (foreign->v_cols != nullptr && foreign->v_cols->size() > 0) {
12401216
row_ins_foreign_fill_virtual(cascade, clust_rec, clust_index, node,
@@ -1271,7 +1247,7 @@ static void row_ins_foreign_fill_virtual(upd_node_t *cascade, const rec_t *rec,
12711247
}
12721248

12731249
/* Mark the old Doc ID as deleted */
1274-
if (fts_col_affacted) {
1250+
if (fts_col_affected) {
12751251
ut_ad(table->fts);
12761252
fts_trx_add_op(trx, table, doc_id, FTS_DELETE, nullptr);
12771253
}

0 commit comments

Comments
 (0)