1
1
/*****************************************************************************
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
372
369
mem_heap_t* heap, /*!< in/out: heap memory */
373
370
const rec_t* rec, /*!< in: current SYS_INDEXES rec */
374
371
dict_index_t* index, /*!< out: index to be filled */
375
table_id_t* table_id) /*!< out: index table id */
372
dulint* table_id) /*!< out: index table id */
377
374
const char* err_msg;
380
buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
377
buf = mem_heap_alloc(heap, 8);
382
379
/* Parse the record, and get "dict_index_t" struct filled */
383
380
err_msg = dict_load_index_low(buf, NULL,
398
395
mem_heap_t* heap, /*!< in/out: heap memory */
399
396
const rec_t* rec, /*!< in: current SYS_COLUMNS rec */
400
397
dict_col_t* column, /*!< out: dict_col_t to be filled */
401
table_id_t* table_id, /*!< out: table id */
398
dulint* table_id, /*!< out: table id */
402
399
const char** col_name) /*!< out: column name */
404
401
const char* err_msg;
422
419
dict_field_t* sys_field, /*!< out: dict_field_t to be
424
421
ulint* pos, /*!< out: Field position */
425
index_id_t* index_id, /*!< out: current index id */
426
index_id_t last_id) /*!< in: previous index id */
422
dulint* index_id, /*!< out: current index id */
423
dulint last_id) /*!< in: previous index id */
429
426
byte* last_index_id;
430
427
const char* err_msg;
432
buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
429
buf = mem_heap_alloc(heap, 8);
434
last_index_id = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
431
last_index_id = mem_heap_alloc(heap, 8);
435
432
mach_write_to_8(last_index_id, last_id);
437
434
err_msg = dict_load_field_low(buf, NULL, sys_field,
866
858
dict_load_column_low(
867
859
/*=================*/
868
860
dict_table_t* table, /*!< in/out: table, could be NULL
869
if we just populate a dict_column_t
861
if we just polulate a dict_column_t
870
862
struct with information from
871
863
a SYS_COLUMNS record */
872
864
mem_heap_t* heap, /*!< in/out: memory heap
873
865
for temporary storage */
874
dict_col_t* column, /*!< out: dict_column_t to fill,
875
or NULL if table != NULL */
876
table_id_t* table_id, /*!< out: table id */
866
dict_col_t* column, /*!< out: dict_column_t to fill */
867
dulint* table_id, /*!< out: table id */
877
868
const char** col_name, /*!< out: column name */
878
869
const rec_t* rec) /*!< in: SYS_COLUMNS record */
1028
1018
tuple = dtuple_create(heap, 1);
1029
1019
dfield = dtuple_get_nth_field(tuple, 0);
1031
buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
1021
buf = mem_heap_alloc(heap, 8);
1032
1022
mach_write_to_8(buf, table->id);
1034
1024
dfield_set_data(dfield, buf, 8);
1212
1202
tuple = dtuple_create(heap, 1);
1213
1203
dfield = dtuple_get_nth_field(tuple, 0);
1215
buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
1205
buf = mem_heap_alloc(heap, 8);
1216
1206
mach_write_to_8(buf, index->id);
1218
1208
dfield_set_data(dfield, buf, 8);
1260
1250
/********************************************************************//**
1261
1251
Loads an index definition from a SYS_INDEXES record to dict_index_t.
1262
If allocate=TRUE, we will create a dict_index_t structure and fill it
1263
accordingly. If allocated=FALSE, the dict_index_t will be supplied by
1264
the caller and filled with information read from the record. @return
1265
error message, or NULL on success */
1252
If "cached" is set to "TRUE", we will create a dict_index_t structure
1253
and fill it accordingly. Otherwise, the dict_index_t will
1254
be supplied by the caller and filled with information read from
1256
@return error message, or NULL on success */
1268
1259
dict_load_index_low(
1269
1260
/*================*/
1270
1261
byte* table_id, /*!< in/out: table id (8 bytes),
1271
an "in" value if allocate=TRUE
1272
and "out" when allocate=FALSE */
1262
an "in" value if cached=TRUE
1263
and "out" when cached=FALSE */
1273
1264
const char* table_name, /*!< in: table name */
1274
1265
mem_heap_t* heap, /*!< in/out: temporary memory heap */
1275
1266
const rec_t* rec, /*!< in: SYS_INDEXES record */
1276
ibool allocate, /*!< in: TRUE=allocate *index,
1277
FALSE=fill in a pre-allocated
1267
ibool cached, /*!< in: TRUE = add to cache,
1279
1269
dict_index_t** index) /*!< out,own: index, or NULL */
1281
1271
const byte* field;
1283
1273
ulint name_len;
1284
1274
char* name_buf;
1286
1276
ulint n_fields;
1291
/* If allocate=TRUE, no dict_index_t will
1281
/* If "cached" is set to TRUE, no dict_index_t will
1292
1282
be supplied. Initialize "*index" to NULL */
1415
1413
tuple = dtuple_create(heap, 1);
1416
1414
dfield = dtuple_get_nth_field(tuple, 0);
1418
buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
1416
buf = mem_heap_alloc(heap, 8);
1419
1417
mach_write_to_8(buf, table->id);
1421
1419
dfield_set_data(dfield, buf, 8);
1803
1801
err = dict_load_indexes(table, heap);
1805
/* Initialize table foreign_child value. Its value could be
1806
changed when dict_load_foreigns() is called below */
1807
table->fk_max_recusive_level = 0;
1809
1803
/* If the force recovery flag is set, we open the table irrespective
1810
1804
of the error condition, since the user may want to dump data from the
1811
1805
clustered index. However we load the foreign key information only if
1812
1806
all indexes were loaded. */
1814
1808
} else if (err == DB_SUCCESS) {
1815
err = dict_load_foreigns(table->name, TRUE, TRUE);
1817
if (err != DB_SUCCESS) {
1818
dict_table_remove_from_cache(table);
1821
table->fk_max_recusive_level = 0;
1809
err = dict_load_foreigns(table->name, TRUE);
1823
1810
} else if (!srv_force_recovery) {
1824
1811
dict_table_remove_from_cache(table);
1905
1890
BTR_SEARCH_LEAF, &pcur, &mtr);
1906
1891
rec = btr_pcur_get_rec(&pcur);
1908
if (!btr_pcur_is_on_user_rec(&pcur)) {
1893
if (!btr_pcur_is_on_user_rec(&pcur)
1894
|| rec_get_deleted_flag(rec, 0)) {
1909
1895
/* Not found */
1913
/* Find the first record that is not delete marked */
1914
while (rec_get_deleted_flag(rec, 0)) {
1915
if (!btr_pcur_move_to_next_user_rec(&pcur, &mtr)) {
1918
rec = btr_pcur_get_rec(&pcur);
1897
btr_pcur_close(&pcur);
1899
mem_heap_free(heap);
1921
1904
/*---------------------------------------------------*/
1989
1977
ut_ad(mutex_own(&(dict_sys->mutex)));
1991
foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(
1992
foreign->heap, foreign->n_fields * sizeof(void*)));
1979
foreign->foreign_col_names = mem_heap_alloc(
1980
foreign->heap, foreign->n_fields * sizeof(void*));
1994
foreign->referenced_col_names = static_cast<const char **>(mem_heap_alloc(
1995
foreign->heap, foreign->n_fields * sizeof(void*)));
1982
foreign->referenced_col_names = mem_heap_alloc(
1983
foreign->heap, foreign->n_fields * sizeof(void*));
1996
1984
mtr_start(&mtr);
1998
1986
sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
2046
2034
/*==============*/
2047
2035
const char* id, /*!< in: foreign constraint id as a
2048
2036
null-terminated string */
2049
ibool check_charsets,
2037
ibool check_charsets)
2050
2038
/*!< in: TRUE=check charset compatibility */
2051
ibool check_recursive)
2052
/*!< in: Whether to record the foreign table
2053
parent count to avoid unlimited recursive
2054
load of chained foreign tables */
2056
2040
dict_foreign_t* foreign;
2057
2041
dict_table_t* sys_foreign;
2152
2134
dict_load_foreign_cols(id, foreign);
2154
ref_table = dict_table_check_if_in_cache_low(
2155
foreign->referenced_table_name);
2157
/* We could possibly wind up in a deep recursive calls if
2158
we call dict_table_get_low() again here if there
2159
is a chain of tables concatenated together with
2160
foreign constraints. In such case, each table is
2161
both a parent and child of the other tables, and
2162
act as a "link" in such table chains.
2163
To avoid such scenario, we would need to check the
2164
number of ancesters the current table has. If that
2165
exceeds DICT_FK_MAX_CHAIN_LEN, we will stop loading
2167
Foreign constraints are loaded in a Breath First fashion,
2168
that is, the index on FOR_NAME is scanned first, and then
2169
index on REF_NAME. So foreign constrains in which
2170
current table is a child (foreign table) are loaded first,
2171
and then those constraints where current table is a
2172
parent (referenced) table.
2173
Thus we could check the parent (ref_table) table's
2174
reference count (fk_max_recusive_level) to know how deep the
2175
recursive call is. If the parent table (ref_table) is already
2176
loaded, and its fk_max_recusive_level is larger than
2177
DICT_FK_MAX_CHAIN_LEN, we will stop the recursive loading
2178
by skipping loading the child table. It will not affect foreign
2179
constraint check for DMLs since child table will be loaded
2180
at that time for the constraint check. */
2182
|| ref_table->fk_max_recusive_level < DICT_FK_MAX_RECURSIVE_LOAD) {
2184
/* If the foreign table is not yet in the dictionary cache, we
2185
have to load it so that we are able to make type comparisons
2186
in the next function call. */
2188
for_table = dict_table_get_low(foreign->foreign_table_name);
2190
if (for_table && ref_table && check_recursive) {
2191
/* This is to record the longest chain of ancesters
2192
this table has, if the parent has more ancesters
2193
than this table has, record it after add 1 (for this
2195
if (ref_table->fk_max_recusive_level
2196
>= for_table->fk_max_recusive_level) {
2197
for_table->fk_max_recusive_level =
2198
ref_table->fk_max_recusive_level + 1;
2136
/* If the foreign table is not yet in the dictionary cache, we
2137
have to load it so that we are able to make type comparisons
2138
in the next function call. */
2140
dict_table_get_low(foreign->foreign_table_name);
2203
2142
/* Note that there may already be a foreign constraint object in
2204
2143
the dictionary cache for this constraint: then the following