1800
1800
err = dict_load_indexes(table, heap);
1802
/* Initialize table foreign_child value. Its value could be
1803
changed when dict_load_foreigns() is called below */
1804
table->fk_max_recusive_level = 0;
1802
1806
/* If the force recovery flag is set, we open the table irrespective
1803
1807
of the error condition, since the user may want to dump data from the
1804
1808
clustered index. However we load the foreign key information only if
1805
1809
all indexes were loaded. */
1807
1811
} else if (err == DB_SUCCESS) {
1808
err = dict_load_foreigns(table->name, TRUE);
1812
err = dict_load_foreigns(table->name, TRUE, TRUE);
1814
if (err != DB_SUCCESS) {
1815
dict_table_remove_from_cache(table);
1809
1818
} else if (!srv_force_recovery) {
1810
1819
dict_table_remove_from_cache(table);
1823
table->fk_max_recusive_level = 0;
1814
1825
if (err != DB_SUCCESS && table != NULL) {
1889
1902
BTR_SEARCH_LEAF, &pcur, &mtr);
1890
1903
rec = btr_pcur_get_rec(&pcur);
1892
if (!btr_pcur_is_on_user_rec(&pcur)
1893
|| rec_get_deleted_flag(rec, 0)) {
1905
if (!btr_pcur_is_on_user_rec(&pcur)) {
1894
1906
/* Not found */
1896
btr_pcur_close(&pcur);
1898
mem_heap_free(heap);
1910
/* Find the first record that is not delete marked */
1911
while (rec_get_deleted_flag(rec, 0)) {
1912
if (!btr_pcur_move_to_next_user_rec(&pcur, &mtr)) {
1915
rec = btr_pcur_get_rec(&pcur);
1903
1918
/*---------------------------------------------------*/
2033
2043
/*==============*/
2034
2044
const char* id, /*!< in: foreign constraint id as a
2035
2045
null-terminated string */
2036
ibool check_charsets)
2046
ibool check_charsets,
2037
2047
/*!< in: TRUE=check charset compatibility */
2048
ibool check_recursive)
2049
/*!< in: Whether to record the foreign table
2050
parent count to avoid unlimited recursive
2051
load of chained foreign tables */
2039
2053
dict_foreign_t* foreign;
2040
2054
dict_table_t* sys_foreign;
2133
2149
dict_load_foreign_cols(id, foreign);
2135
/* If the foreign table is not yet in the dictionary cache, we
2136
have to load it so that we are able to make type comparisons
2137
in the next function call. */
2139
dict_table_get_low(foreign->foreign_table_name);
2151
ref_table = dict_table_check_if_in_cache_low(
2152
foreign->referenced_table_name);
2154
/* We could possibly wind up in a deep recursive calls if
2155
we call dict_table_get_low() again here if there
2156
is a chain of tables concatenated together with
2157
foreign constraints. In such case, each table is
2158
both a parent and child of the other tables, and
2159
act as a "link" in such table chains.
2160
To avoid such scenario, we would need to check the
2161
number of ancesters the current table has. If that
2162
exceeds DICT_FK_MAX_CHAIN_LEN, we will stop loading
2164
Foreign constraints are loaded in a Breath First fashion,
2165
that is, the index on FOR_NAME is scanned first, and then
2166
index on REF_NAME. So foreign constrains in which
2167
current table is a child (foreign table) are loaded first,
2168
and then those constraints where current table is a
2169
parent (referenced) table.
2170
Thus we could check the parent (ref_table) table's
2171
reference count (fk_max_recusive_level) to know how deep the
2172
recursive call is. If the parent table (ref_table) is already
2173
loaded, and its fk_max_recusive_level is larger than
2174
DICT_FK_MAX_CHAIN_LEN, we will stop the recursive loading
2175
by skipping loading the child table. It will not affect foreign
2176
constraint check for DMLs since child table will be loaded
2177
at that time for the constraint check. */
2179
|| ref_table->fk_max_recusive_level < DICT_FK_MAX_RECURSIVE_LOAD) {
2181
/* If the foreign table is not yet in the dictionary cache, we
2182
have to load it so that we are able to make type comparisons
2183
in the next function call. */
2185
for_table = dict_table_get_low(foreign->foreign_table_name);
2187
if (for_table && ref_table && check_recursive) {
2188
/* This is to record the longest chain of ancesters
2189
this table has, if the parent has more ancesters
2190
than this table has, record it after add 1 (for this
2192
if (ref_table->fk_max_recusive_level
2193
>= for_table->fk_max_recusive_level) {
2194
for_table->fk_max_recusive_level =
2195
ref_table->fk_max_recusive_level + 1;
2141
2200
/* Note that there may already be a foreign constraint object in
2142
2201
the dictionary cache for this constraint: then the following