174
/* Enlarge the fatal semaphore wait timeout during the InnoDB table
177
mutex_enter(&kernel_mutex);
178
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
179
mutex_exit(&kernel_mutex);
181
heap = mem_heap_create(1000);
182
mutex_enter(&(dict_sys->mutex));
186
rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
191
err_msg = dict_process_sys_tables_rec(
193
static_cast<dict_table_info>(DICT_TABLE_LOAD_FROM_CACHE
194
| DICT_TABLE_UPDATE_STATS));
199
dict_table_print_low(table);
201
ut_print_timestamp(stderr);
202
fprintf(stderr, " InnoDB: %s\n", err_msg);
205
mem_heap_empty(heap);
208
rec = dict_getnext_system(&pcur, &mtr);
212
mutex_exit(&(dict_sys->mutex));
215
/* Restore the fatal semaphore wait timeout */
216
mutex_enter(&kernel_mutex);
217
srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
218
mutex_exit(&kernel_mutex);
222
/********************************************************************//**
223
This function gets the next system table record as it scans the table.
224
@return the next record if found, NULL if end of scan */
227
dict_getnext_system_low(
228
/*====================*/
229
btr_pcur_t* pcur, /*!< in/out: persistent cursor to the
231
mtr_t* mtr) /*!< in: the mini-transaction */
235
while (!rec || rec_get_deleted_flag(rec, 0)) {
236
btr_pcur_move_to_next_user_rec(pcur, mtr);
238
rec = btr_pcur_get_rec(pcur);
240
if (!btr_pcur_is_on_user_rec(pcur)) {
242
btr_pcur_close(pcur);
248
/* Get a record, let's save the position */
249
btr_pcur_store_position(pcur, mtr);
254
/********************************************************************//**
255
This function opens a system table, and return the first record.
256
@return first record of the system table */
259
dict_startscan_system(
260
/*==================*/
261
btr_pcur_t* pcur, /*!< out: persistent cursor to
263
mtr_t* mtr, /*!< in: the mini-transaction */
264
dict_system_id_t system_id) /*!< in: which system table to open */
266
dict_table_t* system_table;
267
dict_index_t* clust_index;
270
ut_a(system_id < SYS_NUM_SYSTEM_TABLES);
272
system_table = dict_table_get_low(SYSTEM_TABLE_NAME[system_id]);
274
clust_index = UT_LIST_GET_FIRST(system_table->indexes);
276
btr_pcur_open_at_index_side(TRUE, clust_index, BTR_SEARCH_LEAF, pcur,
279
rec = dict_getnext_system_low(pcur, mtr);
284
/********************************************************************//**
285
This function gets the next system table record as it scans the table.
286
@return the next record if found, NULL if end of scan */
291
btr_pcur_t* pcur, /*!< in/out: persistent cursor
293
mtr_t* mtr) /*!< in: the mini-transaction */
297
/* Restore the position */
298
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
300
/* Get the next record */
301
rec = dict_getnext_system_low(pcur, mtr);
305
/********************************************************************//**
306
This function processes one SYS_TABLES record and populate the dict_table_t
307
struct for the table. Extracted out of dict_print() to be used by
308
both monitor table output and information schema innodb_sys_tables output.
309
@return error message, or NULL on success */
312
dict_process_sys_tables_rec(
313
/*========================*/
314
mem_heap_t* heap, /*!< in/out: temporary memory heap */
315
const rec_t* rec, /*!< in: SYS_TABLES record */
316
dict_table_t** table, /*!< out: dict_table_t to fill */
317
dict_table_info_t status) /*!< in: status bit controls
318
options such as whether we shall
319
look for dict_table_t from cache
324
const char* err_msg = NULL;
327
field = (const char*) rec_get_nth_field_old(rec, 0, &len);
329
ut_a(!rec_get_deleted_flag(rec, 0));
331
/* Get the table name */
332
table_name = mem_heap_strdupl(heap, (const char*)field, len);
334
/* If DICT_TABLE_LOAD_FROM_CACHE is set, first check
335
whether there is cached dict_table_t struct first */
336
if (status & DICT_TABLE_LOAD_FROM_CACHE) {
337
*table = dict_table_get_low(table_name);
340
err_msg = "Table not found in cache";
343
err_msg = dict_load_table_low(table_name, rec, table);
350
if ((status & DICT_TABLE_UPDATE_STATS)
351
&& dict_table_get_first_index(*table)) {
353
/* Update statistics if DICT_TABLE_UPDATE_STATS
355
dict_update_statistics(*table,
356
FALSE /* update even if
363
/********************************************************************//**
364
This function parses a SYS_INDEXES record and populate a dict_index_t
365
structure with the information from the record. For detail information
366
about SYS_INDEXES fields, please refer to dict_boot() function.
367
@return error message, or NULL on success */
370
dict_process_sys_indexes_rec(
371
/*=========================*/
372
mem_heap_t* heap, /*!< in/out: heap memory */
373
const rec_t* rec, /*!< in: current SYS_INDEXES rec */
374
dict_index_t* index, /*!< out: index to be filled */
375
table_id_t* table_id) /*!< out: index table id */
380
buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
382
/* Parse the record, and get "dict_index_t" struct filled */
383
err_msg = dict_load_index_low(buf, NULL,
384
heap, rec, FALSE, &index);
386
*table_id = mach_read_from_8(buf);
390
/********************************************************************//**
391
This function parses a SYS_COLUMNS record and populate a dict_column_t
392
structure with the information from the record.
393
@return error message, or NULL on success */
396
dict_process_sys_columns_rec(
397
/*=========================*/
398
mem_heap_t* heap, /*!< in/out: heap memory */
399
const rec_t* rec, /*!< in: current SYS_COLUMNS rec */
400
dict_col_t* column, /*!< out: dict_col_t to be filled */
401
table_id_t* table_id, /*!< out: table id */
402
const char** col_name) /*!< out: column name */
406
/* Parse the record, and get "dict_col_t" struct filled */
407
err_msg = dict_load_column_low(NULL, heap, column,
408
table_id, col_name, rec);
412
/********************************************************************//**
413
This function parses a SYS_FIELDS record and populates a dict_field_t
414
structure with the information from the record.
415
@return error message, or NULL on success */
418
dict_process_sys_fields_rec(
419
/*========================*/
420
mem_heap_t* heap, /*!< in/out: heap memory */
421
const rec_t* rec, /*!< in: current SYS_FIELDS rec */
422
dict_field_t* sys_field, /*!< out: dict_field_t to be
424
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 */
432
buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
434
last_index_id = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
435
mach_write_to_8(last_index_id, last_id);
437
err_msg = dict_load_field_low(buf, NULL, sys_field,
438
pos, last_index_id, heap, rec);
440
*index_id = mach_read_from_8(buf);
445
/********************************************************************//**
446
This function parses a SYS_FOREIGN record and populate a dict_foreign_t
447
structure with the information from the record. For detail information
448
about SYS_FOREIGN fields, please refer to dict_load_foreign() function
449
@return error message, or NULL on success */
452
dict_process_sys_foreign_rec(
453
/*=========================*/
454
mem_heap_t* heap, /*!< in/out: heap memory */
455
const rec_t* rec, /*!< in: current SYS_FOREIGN rec */
456
dict_foreign_t* foreign) /*!< out: dict_foreign_t struct
461
ulint n_fields_and_type;
463
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
464
return("delete-marked record in SYS_FOREIGN");
467
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 6)) {
468
return("wrong number of columns in SYS_FOREIGN record");
471
field = rec_get_nth_field_old(rec, 0/*ID*/, &len);
472
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
474
return("incorrect column length in SYS_FOREIGN");
476
foreign->id = mem_heap_strdupl(heap, (const char*) field, len);
478
rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len);
479
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
482
rec_get_nth_field_offs_old(rec, 2/*DB_ROLL_PTR*/, &len);
483
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
487
field = rec_get_nth_field_old(rec, 3/*FOR_NAME*/, &len);
488
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
491
foreign->foreign_table_name = mem_heap_strdupl(
492
heap, (const char*) field, len);
494
field = rec_get_nth_field_old(rec, 4/*REF_NAME*/, &len);
495
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
498
foreign->referenced_table_name = mem_heap_strdupl(
499
heap, (const char*) field, len);
501
field = rec_get_nth_field_old(rec, 5/*N_COLS*/, &len);
502
if (UNIV_UNLIKELY(len != 4)) {
505
n_fields_and_type = mach_read_from_4(field);
507
foreign->type = (unsigned int) (n_fields_and_type >> 24);
508
foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
512
/********************************************************************//**
513
This function parses a SYS_FOREIGN_COLS record and extract necessary
514
information from the record and return to caller.
515
@return error message, or NULL on success */
518
dict_process_sys_foreign_col_rec(
519
/*=============================*/
520
mem_heap_t* heap, /*!< in/out: heap memory */
521
const rec_t* rec, /*!< in: current SYS_FOREIGN_COLS rec */
522
const char** name, /*!< out: foreign key constraint name */
523
const char** for_col_name, /*!< out: referencing column name */
524
const char** ref_col_name, /*!< out: referenced column name
525
in referenced table */
526
ulint* pos) /*!< out: column position */
531
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
532
return("delete-marked record in SYS_FOREIGN_COLS");
535
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 6)) {
536
return("wrong number of columns in SYS_FOREIGN_COLS record");
539
field = rec_get_nth_field_old(rec, 0/*ID*/, &len);
540
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
542
return("incorrect column length in SYS_FOREIGN_COLS");
544
*name = mem_heap_strdupl(heap, (char*) field, len);
546
field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
547
if (UNIV_UNLIKELY(len != 4)) {
550
*pos = mach_read_from_4(field);
552
rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
553
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
556
rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
557
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
561
field = rec_get_nth_field_old(rec, 4/*FOR_COL_NAME*/, &len);
562
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
565
*for_col_name = mem_heap_strdupl(heap, (char*) field, len);
567
field = rec_get_nth_field_old(rec, 5/*REF_COL_NAME*/, &len);
568
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
571
*ref_col_name = mem_heap_strdupl(heap, (char*) field, len);
577
Send data to callback function .
580
UNIV_INTERN void dict_print_with_callback(dict_print_callback func, void *func_arg)
582
158
dict_table_t* sys_tables;
583
159
dict_index_t* sys_index;
585
162
const rec_t* rec;
586
163
const byte* field;
860
427
/********************************************************************//**
861
Loads a table column definition from a SYS_COLUMNS record to
863
@return error message, or NULL on success */
866
dict_load_column_low(
867
/*=================*/
868
dict_table_t* table, /*!< in/out: table, could be NULL
869
if we just populate a dict_column_t
870
struct with information from
871
a SYS_COLUMNS record */
872
mem_heap_t* heap, /*!< in/out: memory heap
873
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 */
877
const char** col_name, /*!< out: column name */
878
const rec_t* rec) /*!< in: SYS_COLUMNS record */
428
Loads definitions for table columns. */
433
dict_table_t* table, /*!< in: table */
434
mem_heap_t* heap) /*!< in: memory heap for temporary storage */
436
dict_table_t* sys_columns;
437
dict_index_t* sys_index;
888
ut_ad(table || column);
890
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
891
return("delete-marked record in SYS_COLUMNS");
894
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 9)) {
895
return("wrong number of columns in SYS_COLUMNS record");
898
field = rec_get_nth_field_old(rec, 0/*TABLE_ID*/, &len);
899
if (UNIV_UNLIKELY(len != 8)) {
901
return("incorrect column length in SYS_COLUMNS");
905
*table_id = mach_read_from_8(field);
906
} else if (UNIV_UNLIKELY(table->id != mach_read_from_8(field))) {
907
return("SYS_COLUMNS.TABLE_ID mismatch");
910
field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
911
if (UNIV_UNLIKELY(len != 4)) {
916
pos = mach_read_from_4(field);
918
if (UNIV_UNLIKELY(table && table->n_def != pos)) {
919
return("SYS_COLUMNS.POS mismatch");
922
rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
923
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
926
rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
927
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
931
field = rec_get_nth_field_old(rec, 4/*NAME*/, &len);
932
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
936
name = mem_heap_strdupl(heap, (const char*) field, len);
942
field = rec_get_nth_field_old(rec, 5/*MTYPE*/, &len);
943
if (UNIV_UNLIKELY(len != 4)) {
947
mtype = mach_read_from_4(field);
949
field = rec_get_nth_field_old(rec, 6/*PRTYPE*/, &len);
950
if (UNIV_UNLIKELY(len != 4)) {
953
prtype = mach_read_from_4(field);
955
if (dtype_get_charset_coll(prtype) == 0
956
&& dtype_is_string_type(mtype)) {
957
/* The table was created with < 4.1.2. */
959
if (dtype_is_binary_string_type(mtype, prtype)) {
960
/* Use the binary collation for
961
string columns of binary type. */
963
prtype = dtype_form_prtype(
965
DATA_MYSQL_BINARY_CHARSET_COLL);
967
/* Use the default charset for
968
other than binary columns. */
970
prtype = dtype_form_prtype(
972
data_mysql_default_charset_coll);
976
field = rec_get_nth_field_old(rec, 7/*LEN*/, &len);
977
if (UNIV_UNLIKELY(len != 4)) {
980
col_len = mach_read_from_4(field);
981
field = rec_get_nth_field_old(rec, 8/*PREC*/, &len);
982
if (UNIV_UNLIKELY(len != 4)) {
987
dict_mem_table_add_col(table, heap, name, mtype,
990
dict_mem_fill_column_struct(column, pos, mtype,
997
/********************************************************************//**
998
Loads definitions for table columns. */
1003
dict_table_t* table, /*!< in/out: table */
1004
mem_heap_t* heap) /*!< in/out: memory heap
1005
for temporary storage */
1007
dict_table_t* sys_columns;
1008
dict_index_t* sys_index;
1037
469
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1038
470
BTR_SEARCH_LEAF, &pcur, &mtr);
1039
471
for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
1040
const char* err_msg;
1042
473
rec = btr_pcur_get_rec(&pcur);
1044
475
ut_a(btr_pcur_is_on_user_rec(&pcur));
1046
err_msg = dict_load_column_low(table, heap, NULL, NULL,
1050
fprintf(stderr, "InnoDB: %s\n", err_msg);
477
ut_a(!rec_get_deleted_flag(rec, 0));
479
field = rec_get_nth_field_old(rec, 0, &len);
481
ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
483
field = rec_get_nth_field_old(rec, 1, &len);
485
ut_a(i == mach_read_from_4(field));
487
ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
489
field = rec_get_nth_field_old(rec, 4, &len);
490
name = mem_heap_strdupl(heap, (char*) field, len);
492
field = rec_get_nth_field_old(rec, 5, &len);
493
mtype = mach_read_from_4(field);
495
field = rec_get_nth_field_old(rec, 6, &len);
496
prtype = mach_read_from_4(field);
498
if (dtype_get_charset_coll(prtype) == 0
499
&& dtype_is_string_type(mtype)) {
500
/* The table was created with < 4.1.2. */
502
if (dtype_is_binary_string_type(mtype, prtype)) {
503
/* Use the binary collation for
504
string columns of binary type. */
506
prtype = dtype_form_prtype(
508
DATA_MYSQL_BINARY_CHARSET_COLL);
510
/* Use the default charset for
511
other than binary columns. */
513
prtype = dtype_form_prtype(
515
data_mysql_default_charset_coll);
519
field = rec_get_nth_field_old(rec, 7, &len);
520
col_len = mach_read_from_4(field);
522
ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
524
dict_mem_table_add_col(table, heap, name,
525
mtype, prtype, col_len);
1054
526
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1058
530
mtr_commit(&mtr);
1061
/** Error message for a delete-marked record in dict_load_field_low() */
1062
static const char* dict_load_field_del = "delete-marked record in SYS_FIELDS";
1064
/********************************************************************//**
1065
Loads an index field definition from a SYS_FIELDS record to
1067
@return error message, or NULL on success */
1070
dict_load_field_low(
1071
/*================*/
1072
byte* index_id, /*!< in/out: index id (8 bytes)
1073
an "in" value if index != NULL
1074
and "out" if index == NULL */
1075
dict_index_t* index, /*!< in/out: index, could be NULL
1076
if we just populate a dict_field_t
1077
struct with information from
1078
a SYS_FIELDSS record */
1079
dict_field_t* sys_field, /*!< out: dict_field_t to be
1081
ulint* pos, /*!< out: Field position */
1082
byte* last_index_id, /*!< in: last index id */
1083
mem_heap_t* heap, /*!< in/out: memory heap
1084
for temporary storage */
1085
const rec_t* rec) /*!< in: SYS_FIELDS record */
1089
ulint pos_and_prefix_len;
1094
/* Either index or sys_field is supplied, not both */
1095
ut_a((!index) || (!sys_field));
1097
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1098
return(dict_load_field_del);
1101
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 5)) {
1102
return("wrong number of columns in SYS_FIELDS record");
1105
field = rec_get_nth_field_old(rec, 0/*INDEX_ID*/, &len);
1106
if (UNIV_UNLIKELY(len != 8)) {
1108
return("incorrect column length in SYS_FIELDS");
1112
ut_a(last_index_id);
1113
memcpy(index_id, (const char*)field, 8);
1114
first_field = memcmp(index_id, last_index_id, 8);
1116
first_field = (index->n_def == 0);
1117
if (memcmp(field, index_id, 8)) {
1118
return("SYS_FIELDS.INDEX_ID mismatch");
1122
field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
1123
if (UNIV_UNLIKELY(len != 4)) {
1127
rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
1128
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1131
rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
1132
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1136
/* The next field stores the field position in the index and a
1137
possible column prefix length if the index field does not
1138
contain the whole column. The storage format is like this: if
1139
there is at least one prefix field in the index, then the HIGH
1140
2 bytes contain the field number (index->n_def) and the low 2
1141
bytes the prefix length for the field. Otherwise the field
1142
number (index->n_def) is contained in the 2 LOW bytes. */
1144
pos_and_prefix_len = mach_read_from_4(field);
1146
if (index && UNIV_UNLIKELY
1147
((pos_and_prefix_len & 0xFFFFUL) != index->n_def
1148
&& (pos_and_prefix_len >> 16 & 0xFFFF) != index->n_def)) {
1149
return("SYS_FIELDS.POS mismatch");
1152
if (first_field || pos_and_prefix_len > 0xFFFFUL) {
1153
prefix_len = pos_and_prefix_len & 0xFFFFUL;
1154
position = (pos_and_prefix_len & 0xFFFF0000UL) >> 16;
1157
position = pos_and_prefix_len & 0xFFFFUL;
1160
field = rec_get_nth_field_old(rec, 4, &len);
1161
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
1166
dict_mem_index_add_field(
1167
index, mem_heap_strdupl(heap, (const char*) field, len),
1173
sys_field->name = mem_heap_strdupl(
1174
heap, (const char*) field, len);
1175
sys_field->prefix_len = prefix_len;
1182
/********************************************************************//**
1183
Loads definitions for index fields.
1184
@return DB_SUCCESS if ok, DB_CORRUPTION if corruption */
533
/********************************************************************//**
534
Loads definitions for index fields. */
1187
537
dict_load_fields(
1188
538
/*=============*/
1189
dict_index_t* index, /*!< in/out: index whose fields to load */
539
dict_index_t* index, /*!< in: index whose fields to load */
1190
540
mem_heap_t* heap) /*!< in: memory heap for temporary storage */
1192
542
dict_table_t* sys_fields;
1221
573
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1222
574
BTR_SEARCH_LEAF, &pcur, &mtr);
1223
575
for (i = 0; i < index->n_fields; i++) {
1224
const char* err_msg;
1226
577
rec = btr_pcur_get_rec(&pcur);
1228
579
ut_a(btr_pcur_is_on_user_rec(&pcur));
1230
err_msg = dict_load_field_low(buf, index, NULL, NULL, NULL,
581
/* There could be delete marked records in SYS_FIELDS
582
because SYS_FIELDS.INDEX_ID can be updated
583
by ALTER TABLE ADD INDEX. */
1233
if (err_msg == dict_load_field_del) {
1234
/* There could be delete marked records in
1235
SYS_FIELDS because SYS_FIELDS.INDEX_ID can be
1236
updated by ALTER TABLE ADD INDEX. */
585
if (rec_get_deleted_flag(rec, 0)) {
1239
} else if (err_msg) {
1240
fprintf(stderr, "InnoDB: %s\n", err_msg);
1241
error = DB_CORRUPTION;
590
field = rec_get_nth_field_old(rec, 0, &len);
593
field = rec_get_nth_field_old(rec, 1, &len);
596
/* The next field stores the field position in the index
597
and a possible column prefix length if the index field
598
does not contain the whole column. The storage format is
599
like this: if there is at least one prefix field in the index,
600
then the HIGH 2 bytes contain the field number (== i) and the
601
low 2 bytes the prefix length for the field. Otherwise the
602
field number (== i) is contained in the 2 LOW bytes. */
604
pos_and_prefix_len = mach_read_from_4(field);
606
ut_a((pos_and_prefix_len & 0xFFFFUL) == i
607
|| (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
609
if ((i == 0 && pos_and_prefix_len > 0)
610
|| (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
612
prefix_len = pos_and_prefix_len & 0xFFFFUL;
617
ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
619
field = rec_get_nth_field_old(rec, 4, &len);
621
dict_mem_index_add_field(index,
622
mem_heap_strdupl(heap,
1245
627
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1250
630
btr_pcur_close(&pcur);
1251
631
mtr_commit(&mtr);
1255
/** Error message for a delete-marked record in dict_load_index_low() */
1256
static const char* dict_load_index_del = "delete-marked record in SYS_INDEXES";
1257
/** Error message for table->id mismatch in dict_load_index_low() */
1258
static const char* dict_load_index_id_err = "SYS_INDEXES.TABLE_ID mismatch";
1260
/********************************************************************//**
1261
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 */
1268
dict_load_index_low(
1269
/*================*/
1270
byte* table_id, /*!< in/out: table id (8 bytes),
1271
an "in" value if allocate=TRUE
1272
and "out" when allocate=FALSE */
1273
const char* table_name, /*!< in: table name */
1274
mem_heap_t* heap, /*!< in/out: temporary memory heap */
1275
const rec_t* rec, /*!< in: SYS_INDEXES record */
1276
ibool allocate, /*!< in: TRUE=allocate *index,
1277
FALSE=fill in a pre-allocated
1279
dict_index_t** index) /*!< out,own: index, or NULL */
1291
/* If allocate=TRUE, no dict_index_t will
1292
be supplied. Initialize "*index" to NULL */
1296
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1297
return(dict_load_index_del);
1300
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 9)) {
1301
return("wrong number of columns in SYS_INDEXES record");
1304
field = rec_get_nth_field_old(rec, 0/*TABLE_ID*/, &len);
1305
if (UNIV_UNLIKELY(len != 8)) {
1307
return("incorrect column length in SYS_INDEXES");
1311
/* We are reading a SYS_INDEXES record. Copy the table_id */
1312
memcpy(table_id, (const char*)field, 8);
1313
} else if (memcmp(field, table_id, 8)) {
1314
/* Caller supplied table_id, verify it is the same
1315
id as on the index record */
1316
return(dict_load_index_id_err);
1319
field = rec_get_nth_field_old(rec, 1/*ID*/, &len);
1320
if (UNIV_UNLIKELY(len != 8)) {
1324
id = mach_read_from_8(field);
1326
rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
1327
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1330
rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
1331
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1335
field = rec_get_nth_field_old(rec, 4/*NAME*/, &name_len);
1336
if (UNIV_UNLIKELY(name_len == UNIV_SQL_NULL)) {
1340
name_buf = mem_heap_strdupl(heap, (const char*) field,
1343
field = rec_get_nth_field_old(rec, 5/*N_FIELDS*/, &len);
1344
if (UNIV_UNLIKELY(len != 4)) {
1347
n_fields = mach_read_from_4(field);
1349
field = rec_get_nth_field_old(rec, 6/*TYPE*/, &len);
1350
if (UNIV_UNLIKELY(len != 4)) {
1353
type = mach_read_from_4(field);
1355
field = rec_get_nth_field_old(rec, 7/*SPACE*/, &len);
1356
if (UNIV_UNLIKELY(len != 4)) {
1359
space = mach_read_from_4(field);
1361
field = rec_get_nth_field_old(rec, 8/*PAGE_NO*/, &len);
1362
if (UNIV_UNLIKELY(len != 4)) {
1367
*index = dict_mem_index_create(table_name, name_buf,
1368
space, type, n_fields);
1372
dict_mem_fill_index_struct(*index, NULL, NULL, name_buf,
1373
space, type, n_fields);
1377
(*index)->page = mach_read_from_4(field);
1378
ut_ad((*index)->page);
1383
634
/********************************************************************//**
1435
699
rec = btr_pcur_get_rec(&pcur);
1437
err_msg = dict_load_index_low(buf, table->name, heap, rec,
1439
ut_ad((index == NULL) == (err_msg != NULL));
701
field = rec_get_nth_field_old(rec, 0, &len);
1441
if (err_msg == dict_load_index_id_err) {
1442
/* TABLE_ID mismatch means that we have
1443
run out of index definitions for the table. */
704
if (ut_memcmp(buf, field, len) != 0) {
1445
} else if (err_msg == dict_load_index_del) {
1446
/* Skip delete-marked records. */
706
} else if (rec_get_deleted_flag(rec, 0)) {
707
/* Skip delete marked records */
1448
} else if (err_msg) {
1449
fprintf(stderr, "InnoDB: %s\n", err_msg);
1450
error = DB_CORRUPTION;
711
field = rec_get_nth_field_old(rec, 1, &len);
713
id = mach_read_from_8(field);
715
ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
717
field = rec_get_nth_field_old(rec, 4, &name_len);
718
name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
720
field = rec_get_nth_field_old(rec, 5, &len);
721
n_fields = mach_read_from_4(field);
723
field = rec_get_nth_field_old(rec, 6, &len);
724
type = mach_read_from_4(field);
726
field = rec_get_nth_field_old(rec, 7, &len);
727
space = mach_read_from_4(field);
729
ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
731
field = rec_get_nth_field_old(rec, 8, &len);
732
page_no = mach_read_from_4(field);
1456
734
/* We check for unsupported types first, so that the
1457
735
subsequent checks are relevant for the supported types. */
1458
if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
736
if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
1461
739
"InnoDB: Error: unknown type %lu"
1462
740
" of index %s of table %s\n",
1463
(ulong) index->type, index->name, table->name);
741
(ulong) type, name_buf, table->name);
1465
743
error = DB_UNSUPPORTED;
1466
dict_mem_index_free(index);
1468
} else if (index->page == FIL_NULL) {
745
} else if (page_no == FIL_NULL) {
1471
748
"InnoDB: Error: trying to load index %s"
1472
749
" for table %s\n"
1473
750
"InnoDB: but the index tree has been freed!\n",
1474
index->name, table->name);
751
name_buf, table->name);
1477
dict_mem_index_free(index);
1478
753
error = DB_CORRUPTION;
1480
} else if (!dict_index_is_clust(index)
1481
&& NULL == dict_table_get_first_index(table)) {
755
} else if ((type & DICT_CLUSTERED) == 0
756
&& NULL == dict_table_get_first_index(table)) {
1483
758
fputs("InnoDB: Error: trying to load index ",
1485
ut_print_name(stderr, NULL, FALSE, index->name);
760
ut_print_name(stderr, NULL, FALSE, name_buf);
1486
761
fputs(" for table ", stderr);
1487
762
ut_print_name(stderr, NULL, TRUE, table->name);
1488
763
fputs("\nInnoDB: but the first index"
1489
764
" is not clustered!\n", stderr);
1492
} else if (table->id < DICT_HDR_FIRST_ID
1493
&& (dict_index_is_clust(index)
766
error = DB_CORRUPTION;
768
} else if (is_sys_table
769
&& ((type & DICT_CLUSTERED)
1494
770
|| ((table == dict_sys->sys_tables)
1495
&& !strcmp("ID_IND", index->name)))) {
771
&& (name_len == (sizeof "ID_IND") - 1)
772
&& (0 == ut_memcmp(name_buf,
773
"ID_IND", name_len))))) {
1497
775
/* The index was created in memory already at booting
1498
776
of the database server */
1499
dict_mem_index_free(index);
778
index = dict_mem_index_create(table->name, name_buf,
779
space, type, n_fields);
1501
782
dict_load_fields(index, heap);
1502
error = dict_index_add_to_cache(table, index,
1503
index->page, FALSE);
783
error = dict_index_add_to_cache(table, index, page_no,
1504
785
/* The data dictionary tables should never contain
1505
786
invalid index definitions. If we ignored this error
1506
787
and simply did not load this index definition, the
1526
807
/********************************************************************//**
1527
Loads a table definition from a SYS_TABLES record to dict_table_t.
1528
Does not load any columns or indexes.
1529
@return error message, or NULL on success */
1532
dict_load_table_low(
1533
/*================*/
1534
const char* name, /*!< in: table name */
1535
const rec_t* rec, /*!< in: SYS_TABLES record */
1536
dict_table_t** table) /*!< out,own: table, or NULL */
1544
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1545
return("delete-marked record in SYS_TABLES");
1548
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 10)) {
1549
return("wrong number of columns in SYS_TABLES record");
1552
rec_get_nth_field_offs_old(rec, 0/*NAME*/, &len);
1553
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
1555
return("incorrect column length in SYS_TABLES");
1557
rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len);
1558
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1561
rec_get_nth_field_offs_old(rec, 2/*DB_ROLL_PTR*/, &len);
1562
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1566
rec_get_nth_field_offs_old(rec, 3/*ID*/, &len);
1567
if (UNIV_UNLIKELY(len != 8)) {
1571
field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
1572
if (UNIV_UNLIKELY(len != 4)) {
1576
n_cols = mach_read_from_4(field);
1578
rec_get_nth_field_offs_old(rec, 5/*TYPE*/, &len);
1579
if (UNIV_UNLIKELY(len != 4)) {
1583
rec_get_nth_field_offs_old(rec, 6/*MIX_ID*/, &len);
1584
if (UNIV_UNLIKELY(len != 8)) {
1588
rec_get_nth_field_offs_old(rec, 7/*MIX_LEN*/, &len);
1589
if (UNIV_UNLIKELY(len != 4)) {
1593
rec_get_nth_field_offs_old(rec, 8/*CLUSTER_ID*/, &len);
1594
if (UNIV_UNLIKELY(len != UNIV_SQL_NULL)) {
1598
field = rec_get_nth_field_old(rec, 9/*SPACE*/, &len);
1600
if (UNIV_UNLIKELY(len != 4)) {
1604
space = mach_read_from_4(field);
1606
/* Check if the tablespace exists and has the right name */
1608
flags = dict_sys_tables_get_flags(rec);
1610
if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
1611
field = rec_get_nth_field_old(rec, 5/*TYPE*/, &len);
1612
ut_ad(len == 4); /* this was checked earlier */
1613
flags = mach_read_from_4(field);
1615
ut_print_timestamp(stderr);
1616
fputs(" InnoDB: Error: table ", stderr);
1617
ut_print_filename(stderr, name);
1618
fprintf(stderr, "\n"
1619
"InnoDB: in InnoDB data dictionary"
1620
" has unknown type %lx.\n",
1628
/* The high-order bit of N_COLS is the "compact format" flag.
1629
For tables in that format, MIX_LEN may hold additional flags. */
1630
if (n_cols & 0x80000000UL) {
1633
flags |= DICT_TF_COMPACT;
1635
field = rec_get_nth_field_old(rec, 7, &len);
1637
if (UNIV_UNLIKELY(len != 4)) {
1642
flags2 = mach_read_from_4(field);
1644
if (flags2 & (SIZE_MAX << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
1645
ut_print_timestamp(stderr);
1646
fputs(" InnoDB: Warning: table ", stderr);
1647
ut_print_filename(stderr, name);
1648
fprintf(stderr, "\n"
1649
"InnoDB: in InnoDB data dictionary"
1650
" has unknown flags %lx.\n",
1653
flags2 &= ~(~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT));
1656
flags |= flags2 << DICT_TF2_SHIFT;
1659
/* See if the tablespace is available. */
1660
*table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
1663
field = rec_get_nth_field_old(rec, 3/*ID*/, &len);
1664
ut_ad(len == 8); /* this was checked earlier */
1666
(*table)->id = mach_read_from_8(field);
1668
(*table)->ibd_file_missing = FALSE;
1673
/********************************************************************//**
1674
808
Loads a table definition and also all its index definitions, and also
1675
809
the cluster definition if the table is a member in a cluster. Also loads
1676
810
all foreign key constraints where the foreign key is in the table or where
1748
err_msg = dict_load_table_low(name, rec, &table);
1752
ut_print_timestamp(stderr);
1753
fprintf(stderr, " InnoDB: %s\n", err_msg);
1757
if (table->space == 0) {
1758
/* The system tablespace is always available. */
1759
} else if (!fil_space_for_table_exists_in_mem(
1761
(table->flags >> DICT_TF2_SHIFT)
1762
& DICT_TF2_TEMPORARY,
1765
if (table->flags & (DICT_TF2_TEMPORARY << DICT_TF2_SHIFT)) {
1766
/* Do not bother to retry opening temporary tables. */
1767
table->ibd_file_missing = TRUE;
879
ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
881
field = rec_get_nth_field_old(rec, 9, &len);
882
space = mach_read_from_4(field);
884
/* Check if the tablespace exists and has the right name */
886
flags = dict_sys_tables_get_flags(rec);
888
if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
889
field = rec_get_nth_field_old(rec, 5, &len);
890
flags = mach_read_from_4(field);
892
ut_print_timestamp(stderr);
893
fputs(" InnoDB: Error: table ", stderr);
894
ut_print_filename(stderr, name);
896
"InnoDB: in InnoDB data dictionary"
897
" has unknown type %lx.\n",
902
if (fil_space_for_table_exists_in_mem(space, name, FALSE,
904
/* Ok; (if we did a crash recovery then the tablespace
905
can already be in the memory cache) */
907
/* In >= 4.1.9, InnoDB scans the data dictionary also
908
at a normal mysqld startup. It is an error if the
909
space object does not exist in memory. */
1769
911
ut_print_timestamp(stderr);
1771
" InnoDB: error: space object of table ");
1772
ut_print_filename(stderr, name);
1773
fprintf(stderr, ",\n"
913
" InnoDB: error: space object of table %s,\n"
1774
914
"InnoDB: space id %lu did not exist in memory."
1775
915
" Retrying an open.\n",
1776
(ulong) table->space);
1777
917
/* Try to open the tablespace */
1778
918
if (!fil_open_single_table_tablespace(
1780
table->flags == DICT_TF_COMPACT ? 0 :
1781
table->flags & ~(~0 << DICT_TF_BITS), name)) {
1782
/* We failed to find a sensible
919
TRUE, space, flags, name)) {
920
/* We failed to find a sensible tablespace
1785
table->ibd_file_missing = TRUE;
923
ibd_file_missing = TRUE;
930
ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
932
field = rec_get_nth_field_old(rec, 4, &len);
933
n_cols = mach_read_from_4(field);
935
/* The high-order bit of N_COLS is the "compact format" flag. */
936
if (n_cols & 0x80000000UL) {
937
flags |= DICT_TF_COMPACT;
940
table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
943
table->ibd_file_missing = (unsigned int) ibd_file_missing;
945
ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
947
field = rec_get_nth_field_old(rec, 3, &len);
948
table->id = mach_read_from_8(field);
1790
950
btr_pcur_close(&pcur);
1791
951
mtr_commit(&mtr);
1793
953
dict_load_columns(table, heap);
1796
dict_table_add_to_cache(table, heap);
1798
dict_table_add_system_columns(table, heap);
955
dict_table_add_to_cache(table, heap);
1801
957
mem_heap_empty(heap);
1803
959
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
961
/* If the force recovery flag is set, we open the table irrespective
1810
962
of the error condition, since the user may want to dump data from the
1811
963
clustered index. However we load the foreign key information only if
1812
964
all indexes were loaded. */
1814
} 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;
965
if (err == DB_SUCCESS) {
966
err = dict_load_foreigns(table->name, TRUE);
1823
967
} else if (!srv_force_recovery) {
1824
968
dict_table_remove_from_cache(table);
2152
1290
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;
1292
/* If the foreign table is not yet in the dictionary cache, we
1293
have to load it so that we are able to make type comparisons
1294
in the next function call. */
1296
dict_table_get_low(foreign->foreign_table_name);
2203
1298
/* Note that there may already be a foreign constraint object in
2204
1299
the dictionary cache for this constraint: then the following