178
171
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
179
172
mutex_exit(&kernel_mutex);
181
heap = mem_heap_create(1000);
182
174
mutex_enter(&(dict_sys->mutex));
186
rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
191
err_msg = dict_process_sys_tables_rec(
192
heap, rec, &table, DICT_TABLE_LOAD_FROM_CACHE
193
| DICT_TABLE_UPDATE_STATS);
178
sys_tables = dict_table_get_low("SYS_TABLES");
179
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
181
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
184
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
186
rec = btr_pcur_get_rec(&pcur);
188
if (!btr_pcur_is_on_user_rec(&pcur)) {
191
btr_pcur_close(&pcur);
194
mutex_exit(&(dict_sys->mutex));
196
/* Restore the fatal semaphore wait timeout */
198
mutex_enter(&kernel_mutex);
199
srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
200
mutex_exit(&kernel_mutex);
205
field = rec_get_nth_field_old(rec, 0, &len);
207
if (!rec_get_deleted_flag(rec, 0)) {
211
char* table_name = mem_strdupl((char*) field, len);
213
btr_pcur_store_position(&pcur, &mtr);
217
table = dict_table_get_low(table_name);
218
mem_free(table_name);
221
fputs("InnoDB: Failed to load table ", stderr);
222
ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
225
/* The table definition was corrupt if there
228
if (dict_table_get_first_index(table)) {
229
dict_update_statistics_low(table, TRUE);
198
232
dict_table_print_low(table);
200
ut_print_timestamp(stderr);
201
fprintf(stderr, " InnoDB: %s\n", err_msg);
204
mem_heap_empty(heap);
207
rec = dict_getnext_system(&pcur, &mtr);
211
mutex_exit(&(dict_sys->mutex));
214
/* Restore the fatal semaphore wait timeout */
215
mutex_enter(&kernel_mutex);
216
srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
217
mutex_exit(&kernel_mutex);
221
/********************************************************************//**
222
This function gets the next system table record as it scans the table.
223
@return the next record if found, NULL if end of scan */
226
dict_getnext_system_low(
227
/*====================*/
228
btr_pcur_t* pcur, /*!< in/out: persistent cursor to the
230
mtr_t* mtr) /*!< in: the mini-transaction */
234
while (!rec || rec_get_deleted_flag(rec, 0)) {
235
btr_pcur_move_to_next_user_rec(pcur, mtr);
237
rec = btr_pcur_get_rec(pcur);
239
if (!btr_pcur_is_on_user_rec(pcur)) {
241
btr_pcur_close(pcur);
247
/* Get a record, let's save the position */
248
btr_pcur_store_position(pcur, mtr);
253
/********************************************************************//**
254
This function opens a system table, and return the first record.
255
@return first record of the system table */
258
dict_startscan_system(
259
/*==================*/
260
btr_pcur_t* pcur, /*!< out: persistent cursor to
262
mtr_t* mtr, /*!< in: the mini-transaction */
263
dict_system_id_t system_id) /*!< in: which system table to open */
265
dict_table_t* system_table;
266
dict_index_t* clust_index;
269
ut_a(system_id < SYS_NUM_SYSTEM_TABLES);
271
system_table = dict_table_get_low(SYSTEM_TABLE_NAME[system_id]);
273
clust_index = UT_LIST_GET_FIRST(system_table->indexes);
275
btr_pcur_open_at_index_side(TRUE, clust_index, BTR_SEARCH_LEAF, pcur,
278
rec = dict_getnext_system_low(pcur, mtr);
283
/********************************************************************//**
284
This function gets the next system table record as it scans the table.
285
@return the next record if found, NULL if end of scan */
290
btr_pcur_t* pcur, /*!< in/out: persistent cursor
292
mtr_t* mtr) /*!< in: the mini-transaction */
296
/* Restore the position */
297
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
299
/* Get the next record */
300
rec = dict_getnext_system_low(pcur, mtr);
304
/********************************************************************//**
305
This function processes one SYS_TABLES record and populate the dict_table_t
306
struct for the table. Extracted out of dict_print() to be used by
307
both monitor table output and information schema innodb_sys_tables output.
308
@return error message, or NULL on success */
311
dict_process_sys_tables_rec(
312
/*========================*/
313
mem_heap_t* heap, /*!< in/out: temporary memory heap */
314
const rec_t* rec, /*!< in: SYS_TABLES record */
315
dict_table_t** table, /*!< out: dict_table_t to fill */
316
dict_table_info_t status) /*!< in: status bit controls
317
options such as whether we shall
318
look for dict_table_t from cache
323
const char* err_msg = NULL;
326
field = (const char*) rec_get_nth_field_old(rec, 0, &len);
328
ut_a(!rec_get_deleted_flag(rec, 0));
330
/* Get the table name */
331
table_name = mem_heap_strdupl(heap, (const char*)field, len);
333
/* If DICT_TABLE_LOAD_FROM_CACHE is set, first check
334
whether there is cached dict_table_t struct first */
335
if (status & DICT_TABLE_LOAD_FROM_CACHE) {
336
*table = dict_table_get_low(table_name);
339
err_msg = "Table not found in cache";
342
err_msg = dict_load_table_low(table_name, rec, table);
349
if ((status & DICT_TABLE_UPDATE_STATS)
350
&& dict_table_get_first_index(*table)) {
352
/* Update statistics if DICT_TABLE_UPDATE_STATS
354
dict_update_statistics_low(*table, TRUE);
360
/********************************************************************//**
361
This function parses a SYS_INDEXES record and populate a dict_index_t
362
structure with the information from the record. For detail information
363
about SYS_INDEXES fields, please refer to dict_boot() function.
364
@return error message, or NULL on success */
367
dict_process_sys_indexes_rec(
368
/*=========================*/
369
mem_heap_t* heap, /*!< in/out: heap memory */
370
const rec_t* rec, /*!< in: current SYS_INDEXES rec */
371
dict_index_t* index, /*!< out: index to be filled */
372
table_id_t* table_id) /*!< out: index table id */
377
buf = mem_heap_alloc(heap, 8);
379
/* Parse the record, and get "dict_index_t" struct filled */
380
err_msg = dict_load_index_low(buf, NULL,
381
heap, rec, FALSE, &index);
383
*table_id = mach_read_from_8(buf);
387
/********************************************************************//**
388
This function parses a SYS_COLUMNS record and populate a dict_column_t
389
structure with the information from the record.
390
@return error message, or NULL on success */
393
dict_process_sys_columns_rec(
394
/*=========================*/
395
mem_heap_t* heap, /*!< in/out: heap memory */
396
const rec_t* rec, /*!< in: current SYS_COLUMNS rec */
397
dict_col_t* column, /*!< out: dict_col_t to be filled */
398
table_id_t* table_id, /*!< out: table id */
399
const char** col_name) /*!< out: column name */
403
/* Parse the record, and get "dict_col_t" struct filled */
404
err_msg = dict_load_column_low(NULL, heap, column,
405
table_id, col_name, rec);
409
/********************************************************************//**
410
This function parses a SYS_FIELDS record and populates a dict_field_t
411
structure with the information from the record.
412
@return error message, or NULL on success */
415
dict_process_sys_fields_rec(
416
/*========================*/
417
mem_heap_t* heap, /*!< in/out: heap memory */
418
const rec_t* rec, /*!< in: current SYS_FIELDS rec */
419
dict_field_t* sys_field, /*!< out: dict_field_t to be
421
ulint* pos, /*!< out: Field position */
422
index_id_t* index_id, /*!< out: current index id */
423
index_id_t last_id) /*!< in: previous index id */
429
buf = mem_heap_alloc(heap, 8);
431
last_index_id = mem_heap_alloc(heap, 8);
432
mach_write_to_8(last_index_id, last_id);
434
err_msg = dict_load_field_low(buf, NULL, sys_field,
435
pos, last_index_id, heap, rec);
437
*index_id = mach_read_from_8(buf);
442
/********************************************************************//**
443
This function parses a SYS_FOREIGN record and populate a dict_foreign_t
444
structure with the information from the record. For detail information
445
about SYS_FOREIGN fields, please refer to dict_load_foreign() function
446
@return error message, or NULL on success */
449
dict_process_sys_foreign_rec(
450
/*=========================*/
451
mem_heap_t* heap, /*!< in/out: heap memory */
452
const rec_t* rec, /*!< in: current SYS_FOREIGN rec */
453
dict_foreign_t* foreign) /*!< out: dict_foreign_t struct
458
ulint n_fields_and_type;
460
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
461
return("delete-marked record in SYS_FOREIGN");
464
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 6)) {
465
return("wrong number of columns in SYS_FOREIGN record");
468
field = rec_get_nth_field_old(rec, 0/*ID*/, &len);
469
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
471
return("incorrect column length in SYS_FOREIGN");
473
foreign->id = mem_heap_strdupl(heap, (const char*) field, len);
475
rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len);
476
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
479
rec_get_nth_field_offs_old(rec, 2/*DB_ROLL_PTR*/, &len);
480
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
484
field = rec_get_nth_field_old(rec, 3/*FOR_NAME*/, &len);
485
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
488
foreign->foreign_table_name = mem_heap_strdupl(
489
heap, (const char*) field, len);
491
field = rec_get_nth_field_old(rec, 4/*REF_NAME*/, &len);
492
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
495
foreign->referenced_table_name = mem_heap_strdupl(
496
heap, (const char*) field, len);
498
field = rec_get_nth_field_old(rec, 5/*N_COLS*/, &len);
499
if (UNIV_UNLIKELY(len != 4)) {
502
n_fields_and_type = mach_read_from_4(field);
504
foreign->type = (unsigned int) (n_fields_and_type >> 24);
505
foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
509
/********************************************************************//**
510
This function parses a SYS_FOREIGN_COLS record and extract necessary
511
information from the record and return to caller.
512
@return error message, or NULL on success */
515
dict_process_sys_foreign_col_rec(
516
/*=============================*/
517
mem_heap_t* heap, /*!< in/out: heap memory */
518
const rec_t* rec, /*!< in: current SYS_FOREIGN_COLS rec */
519
const char** name, /*!< out: foreign key constraint name */
520
const char** for_col_name, /*!< out: referencing column name */
521
const char** ref_col_name, /*!< out: referenced column name
522
in referenced table */
523
ulint* pos) /*!< out: column position */
528
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
529
return("delete-marked record in SYS_FOREIGN_COLS");
532
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 6)) {
533
return("wrong number of columns in SYS_FOREIGN_COLS record");
536
field = rec_get_nth_field_old(rec, 0/*ID*/, &len);
537
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
539
return("incorrect column length in SYS_FOREIGN_COLS");
541
*name = mem_heap_strdupl(heap, (char*) field, len);
543
field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
544
if (UNIV_UNLIKELY(len != 4)) {
547
*pos = mach_read_from_4(field);
549
rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
550
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
553
rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
554
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
558
field = rec_get_nth_field_old(rec, 4/*FOR_COL_NAME*/, &len);
559
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
562
*for_col_name = mem_heap_strdupl(heap, (char*) field, len);
564
field = rec_get_nth_field_old(rec, 5/*REF_COL_NAME*/, &len);
565
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
568
*ref_col_name = mem_heap_strdupl(heap, (char*) field, len);
237
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
857
502
/********************************************************************//**
858
Loads a table column definition from a SYS_COLUMNS record to
860
@return error message, or NULL on success */
863
dict_load_column_low(
864
/*=================*/
865
dict_table_t* table, /*!< in/out: table, could be NULL
866
if we just populate a dict_column_t
867
struct with information from
868
a SYS_COLUMNS record */
869
mem_heap_t* heap, /*!< in/out: memory heap
870
for temporary storage */
871
dict_col_t* column, /*!< out: dict_column_t to fill,
872
or NULL if table != NULL */
873
table_id_t* table_id, /*!< out: table id */
874
const char** col_name, /*!< out: column name */
875
const rec_t* rec) /*!< in: SYS_COLUMNS record */
503
Loads definitions for table columns. */
508
dict_table_t* table, /*!< in: table */
509
mem_heap_t* heap) /*!< in: memory heap for temporary storage */
511
dict_table_t* sys_columns;
512
dict_index_t* sys_index;
885
ut_ad(table || column);
887
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
888
return("delete-marked record in SYS_COLUMNS");
891
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 9)) {
892
return("wrong number of columns in SYS_COLUMNS record");
895
field = rec_get_nth_field_old(rec, 0/*TABLE_ID*/, &len);
896
if (UNIV_UNLIKELY(len != 8)) {
898
return("incorrect column length in SYS_COLUMNS");
902
*table_id = mach_read_from_8(field);
903
} else if (UNIV_UNLIKELY(table->id != mach_read_from_8(field))) {
904
return("SYS_COLUMNS.TABLE_ID mismatch");
907
field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
908
if (UNIV_UNLIKELY(len != 4)) {
913
pos = mach_read_from_4(field);
915
if (UNIV_UNLIKELY(table && table->n_def != pos)) {
916
return("SYS_COLUMNS.POS mismatch");
919
rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
920
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
923
rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
924
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
928
field = rec_get_nth_field_old(rec, 4/*NAME*/, &len);
929
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
933
name = mem_heap_strdupl(heap, (const char*) field, len);
939
field = rec_get_nth_field_old(rec, 5/*MTYPE*/, &len);
940
if (UNIV_UNLIKELY(len != 4)) {
944
mtype = mach_read_from_4(field);
946
field = rec_get_nth_field_old(rec, 6/*PRTYPE*/, &len);
947
if (UNIV_UNLIKELY(len != 4)) {
950
prtype = mach_read_from_4(field);
952
if (dtype_get_charset_coll(prtype) == 0
953
&& dtype_is_string_type(mtype)) {
954
/* The table was created with < 4.1.2. */
956
if (dtype_is_binary_string_type(mtype, prtype)) {
957
/* Use the binary collation for
958
string columns of binary type. */
960
prtype = dtype_form_prtype(
962
DATA_MYSQL_BINARY_CHARSET_COLL);
964
/* Use the default charset for
965
other than binary columns. */
967
prtype = dtype_form_prtype(
969
data_mysql_default_charset_coll);
973
field = rec_get_nth_field_old(rec, 7/*LEN*/, &len);
974
if (UNIV_UNLIKELY(len != 4)) {
977
col_len = mach_read_from_4(field);
978
field = rec_get_nth_field_old(rec, 8/*PREC*/, &len);
979
if (UNIV_UNLIKELY(len != 4)) {
984
dict_mem_table_add_col(table, heap, name, mtype,
987
dict_mem_fill_column_struct(column, pos, mtype,
994
/********************************************************************//**
995
Loads definitions for table columns. */
1000
dict_table_t* table, /*!< in/out: table */
1001
mem_heap_t* heap) /*!< in/out: memory heap
1002
for temporary storage */
1004
dict_table_t* sys_columns;
1005
dict_index_t* sys_index;
1055
605
mtr_commit(&mtr);
1058
/** Error message for a delete-marked record in dict_load_field_low() */
1059
static const char* dict_load_field_del = "delete-marked record in SYS_FIELDS";
1061
/********************************************************************//**
1062
Loads an index field definition from a SYS_FIELDS record to
1064
@return error message, or NULL on success */
1067
dict_load_field_low(
1068
/*================*/
1069
byte* index_id, /*!< in/out: index id (8 bytes)
1070
an "in" value if index != NULL
1071
and "out" if index == NULL */
1072
dict_index_t* index, /*!< in/out: index, could be NULL
1073
if we just populate a dict_field_t
1074
struct with information from
1075
a SYS_FIELDSS record */
1076
dict_field_t* sys_field, /*!< out: dict_field_t to be
1078
ulint* pos, /*!< out: Field position */
1079
byte* last_index_id, /*!< in: last index id */
1080
mem_heap_t* heap, /*!< in/out: memory heap
1081
for temporary storage */
1082
const rec_t* rec) /*!< in: SYS_FIELDS record */
1086
ulint pos_and_prefix_len;
1091
/* Either index or sys_field is supplied, not both */
1092
ut_a((!index) || (!sys_field));
1094
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1095
return(dict_load_field_del);
1098
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 5)) {
1099
return("wrong number of columns in SYS_FIELDS record");
1102
field = rec_get_nth_field_old(rec, 0/*INDEX_ID*/, &len);
1103
if (UNIV_UNLIKELY(len != 8)) {
1105
return("incorrect column length in SYS_FIELDS");
1109
ut_a(last_index_id);
1110
memcpy(index_id, (const char*)field, 8);
1111
first_field = memcmp(index_id, last_index_id, 8);
1113
first_field = (index->n_def == 0);
1114
if (memcmp(field, index_id, 8)) {
1115
return("SYS_FIELDS.INDEX_ID mismatch");
1119
field = rec_get_nth_field_old(rec, 1/*POS*/, &len);
1120
if (UNIV_UNLIKELY(len != 4)) {
1124
rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
1125
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1128
rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
1129
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1133
/* The next field stores the field position in the index and a
1134
possible column prefix length if the index field does not
1135
contain the whole column. The storage format is like this: if
1136
there is at least one prefix field in the index, then the HIGH
1137
2 bytes contain the field number (index->n_def) and the low 2
1138
bytes the prefix length for the field. Otherwise the field
1139
number (index->n_def) is contained in the 2 LOW bytes. */
1141
pos_and_prefix_len = mach_read_from_4(field);
1143
if (index && UNIV_UNLIKELY
1144
((pos_and_prefix_len & 0xFFFFUL) != index->n_def
1145
&& (pos_and_prefix_len >> 16 & 0xFFFF) != index->n_def)) {
1146
return("SYS_FIELDS.POS mismatch");
1149
if (first_field || pos_and_prefix_len > 0xFFFFUL) {
1150
prefix_len = pos_and_prefix_len & 0xFFFFUL;
1151
position = (pos_and_prefix_len & 0xFFFF0000UL) >> 16;
1154
position = pos_and_prefix_len & 0xFFFFUL;
1157
field = rec_get_nth_field_old(rec, 4, &len);
1158
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
1163
dict_mem_index_add_field(
1164
index, mem_heap_strdupl(heap, (const char*) field, len),
1170
sys_field->name = mem_heap_strdupl(
1171
heap, (const char*) field, len);
1172
sys_field->prefix_len = prefix_len;
1179
/********************************************************************//**
1180
Loads definitions for index fields.
1181
@return DB_SUCCESS if ok, DB_CORRUPTION if corruption */
608
/********************************************************************//**
609
Loads definitions for index fields. */
1184
612
dict_load_fields(
1185
613
/*=============*/
1186
dict_index_t* index, /*!< in/out: index whose fields to load */
614
dict_index_t* index, /*!< in: index whose fields to load */
1187
615
mem_heap_t* heap) /*!< in: memory heap for temporary storage */
1189
617
dict_table_t* sys_fields;
1218
648
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1219
649
BTR_SEARCH_LEAF, &pcur, &mtr);
1220
650
for (i = 0; i < index->n_fields; i++) {
1221
const char* err_msg;
1223
652
rec = btr_pcur_get_rec(&pcur);
1225
654
ut_a(btr_pcur_is_on_user_rec(&pcur));
1227
err_msg = dict_load_field_low(buf, index, NULL, NULL, NULL,
656
/* There could be delete marked records in SYS_FIELDS
657
because SYS_FIELDS.INDEX_ID can be updated
658
by ALTER TABLE ADD INDEX. */
1230
if (err_msg == dict_load_field_del) {
1231
/* There could be delete marked records in
1232
SYS_FIELDS because SYS_FIELDS.INDEX_ID can be
1233
updated by ALTER TABLE ADD INDEX. */
660
if (rec_get_deleted_flag(rec, 0)) {
1236
} else if (err_msg) {
1237
fprintf(stderr, "InnoDB: %s\n", err_msg);
1238
error = DB_CORRUPTION;
665
field = rec_get_nth_field_old(rec, 0, &len);
668
field = rec_get_nth_field_old(rec, 1, &len);
671
/* The next field stores the field position in the index
672
and a possible column prefix length if the index field
673
does not contain the whole column. The storage format is
674
like this: if there is at least one prefix field in the index,
675
then the HIGH 2 bytes contain the field number (== i) and the
676
low 2 bytes the prefix length for the field. Otherwise the
677
field number (== i) is contained in the 2 LOW bytes. */
679
pos_and_prefix_len = mach_read_from_4(field);
681
ut_a((pos_and_prefix_len & 0xFFFFUL) == i
682
|| (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
684
if ((i == 0 && pos_and_prefix_len > 0)
685
|| (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
687
prefix_len = pos_and_prefix_len & 0xFFFFUL;
692
ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
694
field = rec_get_nth_field_old(rec, 4, &len);
696
dict_mem_index_add_field(index,
697
mem_heap_strdupl(heap,
1242
702
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1247
705
btr_pcur_close(&pcur);
1248
706
mtr_commit(&mtr);
1252
/** Error message for a delete-marked record in dict_load_index_low() */
1253
static const char* dict_load_index_del = "delete-marked record in SYS_INDEXES";
1254
/** Error message for table->id mismatch in dict_load_index_low() */
1255
static const char* dict_load_index_id_err = "SYS_INDEXES.TABLE_ID mismatch";
1257
/********************************************************************//**
1258
Loads an index definition from a SYS_INDEXES record to dict_index_t.
1259
If allocate=TRUE, we will create a dict_index_t structure and fill it
1260
accordingly. If allocated=FALSE, the dict_index_t will be supplied by
1261
the caller and filled with information read from the record. @return
1262
error message, or NULL on success */
1265
dict_load_index_low(
1266
/*================*/
1267
byte* table_id, /*!< in/out: table id (8 bytes),
1268
an "in" value if allocate=TRUE
1269
and "out" when allocate=FALSE */
1270
const char* table_name, /*!< in: table name */
1271
mem_heap_t* heap, /*!< in/out: temporary memory heap */
1272
const rec_t* rec, /*!< in: SYS_INDEXES record */
1273
ibool allocate, /*!< in: TRUE=allocate *index,
1274
FALSE=fill in a pre-allocated
1276
dict_index_t** index) /*!< out,own: index, or NULL */
1288
/* If allocate=TRUE, no dict_index_t will
1289
be supplied. Initialize "*index" to NULL */
1293
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1294
return(dict_load_index_del);
1297
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 9)) {
1298
return("wrong number of columns in SYS_INDEXES record");
1301
field = rec_get_nth_field_old(rec, 0/*TABLE_ID*/, &len);
1302
if (UNIV_UNLIKELY(len != 8)) {
1304
return("incorrect column length in SYS_INDEXES");
1308
/* We are reading a SYS_INDEXES record. Copy the table_id */
1309
memcpy(table_id, (const char*)field, 8);
1310
} else if (memcmp(field, table_id, 8)) {
1311
/* Caller supplied table_id, verify it is the same
1312
id as on the index record */
1313
return(dict_load_index_id_err);
1316
field = rec_get_nth_field_old(rec, 1/*ID*/, &len);
1317
if (UNIV_UNLIKELY(len != 8)) {
1321
id = mach_read_from_8(field);
1323
rec_get_nth_field_offs_old(rec, 2/*DB_TRX_ID*/, &len);
1324
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1327
rec_get_nth_field_offs_old(rec, 3/*DB_ROLL_PTR*/, &len);
1328
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1332
field = rec_get_nth_field_old(rec, 4/*NAME*/, &name_len);
1333
if (UNIV_UNLIKELY(name_len == UNIV_SQL_NULL)) {
1337
name_buf = mem_heap_strdupl(heap, (const char*) field,
1340
field = rec_get_nth_field_old(rec, 5/*N_FIELDS*/, &len);
1341
if (UNIV_UNLIKELY(len != 4)) {
1344
n_fields = mach_read_from_4(field);
1346
field = rec_get_nth_field_old(rec, 6/*TYPE*/, &len);
1347
if (UNIV_UNLIKELY(len != 4)) {
1350
type = mach_read_from_4(field);
1352
field = rec_get_nth_field_old(rec, 7/*SPACE*/, &len);
1353
if (UNIV_UNLIKELY(len != 4)) {
1356
space = mach_read_from_4(field);
1358
field = rec_get_nth_field_old(rec, 8/*PAGE_NO*/, &len);
1359
if (UNIV_UNLIKELY(len != 4)) {
1364
*index = dict_mem_index_create(table_name, name_buf,
1365
space, type, n_fields);
1369
dict_mem_fill_index_struct(*index, NULL, NULL, name_buf,
1370
space, type, n_fields);
1374
(*index)->page = mach_read_from_4(field);
1375
ut_ad((*index)->page);
1380
709
/********************************************************************//**
1432
774
rec = btr_pcur_get_rec(&pcur);
1434
err_msg = dict_load_index_low(buf, table->name, heap, rec,
1436
ut_ad((index == NULL) == (err_msg != NULL));
776
field = rec_get_nth_field_old(rec, 0, &len);
1438
if (err_msg == dict_load_index_id_err) {
1439
/* TABLE_ID mismatch means that we have
1440
run out of index definitions for the table. */
779
if (ut_memcmp(buf, field, len) != 0) {
1442
} else if (err_msg == dict_load_index_del) {
1443
/* Skip delete-marked records. */
781
} else if (rec_get_deleted_flag(rec, 0)) {
782
/* Skip delete marked records */
1445
} else if (err_msg) {
1446
fprintf(stderr, "InnoDB: %s\n", err_msg);
1447
error = DB_CORRUPTION;
786
field = rec_get_nth_field_old(rec, 1, &len);
788
id = mach_read_from_8(field);
790
ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
792
field = rec_get_nth_field_old(rec, 4, &name_len);
793
name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
795
field = rec_get_nth_field_old(rec, 5, &len);
796
n_fields = mach_read_from_4(field);
798
field = rec_get_nth_field_old(rec, 6, &len);
799
type = mach_read_from_4(field);
801
field = rec_get_nth_field_old(rec, 7, &len);
802
space = mach_read_from_4(field);
804
ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
806
field = rec_get_nth_field_old(rec, 8, &len);
807
page_no = mach_read_from_4(field);
1453
809
/* We check for unsupported types first, so that the
1454
810
subsequent checks are relevant for the supported types. */
1455
if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
811
if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
1458
814
"InnoDB: Error: unknown type %lu"
1459
815
" of index %s of table %s\n",
1460
(ulong) index->type, index->name, table->name);
816
(ulong) type, name_buf, table->name);
1462
818
error = DB_UNSUPPORTED;
1463
dict_mem_index_free(index);
1465
} else if (index->page == FIL_NULL) {
820
} else if (page_no == FIL_NULL) {
1468
823
"InnoDB: Error: trying to load index %s"
1469
824
" for table %s\n"
1470
825
"InnoDB: but the index tree has been freed!\n",
1471
index->name, table->name);
826
name_buf, table->name);
1474
dict_mem_index_free(index);
1475
828
error = DB_CORRUPTION;
1477
} else if (!dict_index_is_clust(index)
1478
&& NULL == dict_table_get_first_index(table)) {
830
} else if ((type & DICT_CLUSTERED) == 0
831
&& NULL == dict_table_get_first_index(table)) {
1480
833
fputs("InnoDB: Error: trying to load index ",
1482
ut_print_name(stderr, NULL, FALSE, index->name);
835
ut_print_name(stderr, NULL, FALSE, name_buf);
1483
836
fputs(" for table ", stderr);
1484
837
ut_print_name(stderr, NULL, TRUE, table->name);
1485
838
fputs("\nInnoDB: but the first index"
1486
839
" is not clustered!\n", stderr);
1489
} else if (table->id < DICT_HDR_FIRST_ID
1490
&& (dict_index_is_clust(index)
841
error = DB_CORRUPTION;
843
} else if (is_sys_table
844
&& ((type & DICT_CLUSTERED)
1491
845
|| ((table == dict_sys->sys_tables)
1492
&& !strcmp("ID_IND", index->name)))) {
846
&& (name_len == (sizeof "ID_IND") - 1)
847
&& (0 == ut_memcmp(name_buf,
848
"ID_IND", name_len))))) {
1494
850
/* The index was created in memory already at booting
1495
851
of the database server */
1496
dict_mem_index_free(index);
853
index = dict_mem_index_create(table->name, name_buf,
854
space, type, n_fields);
1498
857
dict_load_fields(index, heap);
1499
error = dict_index_add_to_cache(table, index,
1500
index->page, FALSE);
858
error = dict_index_add_to_cache(table, index, page_no,
1501
860
/* The data dictionary tables should never contain
1502
861
invalid index definitions. If we ignored this error
1503
862
and simply did not load this index definition, the
1523
882
/********************************************************************//**
1524
Loads a table definition from a SYS_TABLES record to dict_table_t.
1525
Does not load any columns or indexes.
1526
@return error message, or NULL on success */
1529
dict_load_table_low(
1530
/*================*/
1531
const char* name, /*!< in: table name */
1532
const rec_t* rec, /*!< in: SYS_TABLES record */
1533
dict_table_t** table) /*!< out,own: table, or NULL */
1541
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
1542
return("delete-marked record in SYS_TABLES");
1545
if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 10)) {
1546
return("wrong number of columns in SYS_TABLES record");
1549
rec_get_nth_field_offs_old(rec, 0/*NAME*/, &len);
1550
if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
1552
return("incorrect column length in SYS_TABLES");
1554
rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len);
1555
if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
1558
rec_get_nth_field_offs_old(rec, 2/*DB_ROLL_PTR*/, &len);
1559
if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
1563
rec_get_nth_field_offs_old(rec, 3/*ID*/, &len);
1564
if (UNIV_UNLIKELY(len != 8)) {
1568
field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
1569
if (UNIV_UNLIKELY(len != 4)) {
1573
n_cols = mach_read_from_4(field);
1575
rec_get_nth_field_offs_old(rec, 5/*TYPE*/, &len);
1576
if (UNIV_UNLIKELY(len != 4)) {
1580
rec_get_nth_field_offs_old(rec, 6/*MIX_ID*/, &len);
1581
if (UNIV_UNLIKELY(len != 8)) {
1585
rec_get_nth_field_offs_old(rec, 7/*MIX_LEN*/, &len);
1586
if (UNIV_UNLIKELY(len != 4)) {
1590
rec_get_nth_field_offs_old(rec, 8/*CLUSTER_ID*/, &len);
1591
if (UNIV_UNLIKELY(len != UNIV_SQL_NULL)) {
1595
field = rec_get_nth_field_old(rec, 9/*SPACE*/, &len);
1597
if (UNIV_UNLIKELY(len != 4)) {
1601
space = mach_read_from_4(field);
1603
/* Check if the tablespace exists and has the right name */
1605
flags = dict_sys_tables_get_flags(rec);
1607
if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
1608
field = rec_get_nth_field_old(rec, 5/*TYPE*/, &len);
1609
ut_ad(len == 4); /* this was checked earlier */
1610
flags = mach_read_from_4(field);
1612
ut_print_timestamp(stderr);
1613
fputs(" InnoDB: Error: table ", stderr);
1614
ut_print_filename(stderr, name);
1615
fprintf(stderr, "\n"
1616
"InnoDB: in InnoDB data dictionary"
1617
" has unknown type %lx.\n",
1625
/* The high-order bit of N_COLS is the "compact format" flag.
1626
For tables in that format, MIX_LEN may hold additional flags. */
1627
if (n_cols & 0x80000000UL) {
1630
flags |= DICT_TF_COMPACT;
1632
field = rec_get_nth_field_old(rec, 7, &len);
1634
if (UNIV_UNLIKELY(len != 4)) {
1639
flags2 = mach_read_from_4(field);
1641
if (flags2 & (~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
1642
ut_print_timestamp(stderr);
1643
fputs(" InnoDB: Warning: table ", stderr);
1644
ut_print_filename(stderr, name);
1645
fprintf(stderr, "\n"
1646
"InnoDB: in InnoDB data dictionary"
1647
" has unknown flags %lx.\n",
1650
flags2 &= ~(~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT));
1653
flags |= flags2 << DICT_TF2_SHIFT;
1656
/* See if the tablespace is available. */
1657
*table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
1660
field = rec_get_nth_field_old(rec, 3/*ID*/, &len);
1661
ut_ad(len == 8); /* this was checked earlier */
1663
(*table)->id = mach_read_from_8(field);
1665
(*table)->ibd_file_missing = FALSE;
1670
/********************************************************************//**
1671
883
Loads a table definition and also all its index definitions, and also
1672
884
the cluster definition if the table is a member in a cluster. Also loads
1673
885
all foreign key constraints where the foreign key is in the table or where
1745
err_msg = dict_load_table_low(name, rec, &table);
1749
ut_print_timestamp(stderr);
1750
fprintf(stderr, " InnoDB: %s\n", err_msg);
1754
if (table->space == 0) {
1755
/* The system tablespace is always available. */
1756
} else if (!fil_space_for_table_exists_in_mem(
1758
(table->flags >> DICT_TF2_SHIFT)
1759
& DICT_TF2_TEMPORARY,
1762
if (table->flags & (DICT_TF2_TEMPORARY << DICT_TF2_SHIFT)) {
1763
/* Do not bother to retry opening temporary tables. */
1764
table->ibd_file_missing = TRUE;
954
ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
956
field = rec_get_nth_field_old(rec, 9, &len);
957
space = mach_read_from_4(field);
959
/* Check if the tablespace exists and has the right name */
961
flags = dict_sys_tables_get_flags(rec);
963
if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
964
field = rec_get_nth_field_old(rec, 5, &len);
965
flags = mach_read_from_4(field);
967
ut_print_timestamp(stderr);
968
fputs(" InnoDB: Error: table ", stderr);
969
ut_print_filename(stderr, name);
971
"InnoDB: in InnoDB data dictionary"
972
" has unknown type %lx.\n",
977
if (fil_space_for_table_exists_in_mem(space, name, FALSE,
979
/* Ok; (if we did a crash recovery then the tablespace
980
can already be in the memory cache) */
982
/* In >= 4.1.9, InnoDB scans the data dictionary also
983
at a normal mysqld startup. It is an error if the
984
space object does not exist in memory. */
1766
986
ut_print_timestamp(stderr);
1768
" InnoDB: error: space object of table ");
1769
ut_print_filename(stderr, name);
1770
fprintf(stderr, ",\n"
988
" InnoDB: error: space object of table %s,\n"
1771
989
"InnoDB: space id %lu did not exist in memory."
1772
990
" Retrying an open.\n",
1773
(ulong) table->space);
1774
992
/* Try to open the tablespace */
1775
993
if (!fil_open_single_table_tablespace(
1777
table->flags == DICT_TF_COMPACT ? 0 :
1778
table->flags & ~(~0 << DICT_TF_BITS), name)) {
1779
/* We failed to find a sensible
994
TRUE, space, flags, name)) {
995
/* We failed to find a sensible tablespace
1782
table->ibd_file_missing = TRUE;
998
ibd_file_missing = TRUE;
1005
ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
1007
field = rec_get_nth_field_old(rec, 4, &len);
1008
n_cols = mach_read_from_4(field);
1010
/* The high-order bit of N_COLS is the "compact format" flag. */
1011
if (n_cols & 0x80000000UL) {
1012
flags |= DICT_TF_COMPACT;
1015
table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
1018
table->ibd_file_missing = (unsigned int) ibd_file_missing;
1020
ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
1022
field = rec_get_nth_field_old(rec, 3, &len);
1023
table->id = mach_read_from_8(field);
1787
1025
btr_pcur_close(&pcur);
1788
1026
mtr_commit(&mtr);
1790
1028
dict_load_columns(table, heap);
1793
dict_table_add_to_cache(table, heap);
1795
dict_table_add_system_columns(table, heap);
1030
dict_table_add_to_cache(table, heap);
1798
1032
mem_heap_empty(heap);
1800
1034
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;
1806
1036
/* If the force recovery flag is set, we open the table irrespective
1807
1037
of the error condition, since the user may want to dump data from the
1808
1038
clustered index. However we load the foreign key information only if
1809
1039
all indexes were loaded. */
1811
} else if (err == DB_SUCCESS) {
1812
err = dict_load_foreigns(table->name, TRUE, TRUE);
1814
if (err != DB_SUCCESS) {
1815
dict_table_remove_from_cache(table);
1040
if (err == DB_SUCCESS) {
1041
err = dict_load_foreigns(table->name, TRUE);
1818
1042
} else if (!srv_force_recovery) {
1819
1043
dict_table_remove_from_cache(table);
1823
table->fk_max_recusive_level = 0;
1825
1047
if (err != DB_SUCCESS && table != NULL) {