1
/******************************************************
2
Loads to the memory cache database object definitions
7
Created 4/24/1996 Heikki Tuuri
8
*******************************************************/
10
#include "dict0load.h"
11
#ifndef UNIV_HOTBACKUP
12
#include "mysql_version.h"
13
#endif /* !UNIV_HOTBACKUP */
16
#include "dict0load.ic"
21
#include "page0page.h"
22
#include "mach0data.h"
23
#include "dict0dict.h"
24
#include "dict0boot.h"
26
#include "srv0start.h"
29
/********************************************************************
30
Returns TRUE if index's i'th column's name is 'name' .*/
36
dict_table_t* table, /* in: table */
37
dict_index_t* index, /* in: index */
39
const char* name) /* in: name to compare to */
41
ulint tmp = dict_col_get_no(dict_field_get_col(
42
dict_index_get_nth_field(
45
return(strcmp(name, dict_table_get_col_name(table, tmp)) == 0);
48
/************************************************************************
49
Finds the first table name in the given database. */
52
dict_get_first_table_name_in_db(
53
/*============================*/
54
/* out, own: table name, NULL if
55
does not exist; the caller must
56
free the memory in the string! */
57
const char* name) /* in: database name which ends in '/' */
59
dict_table_t* sys_tables;
61
dict_index_t* sys_index;
70
ut_ad(mutex_own(&(dict_sys->mutex)));
72
heap = mem_heap_create(1000);
76
sys_tables = dict_table_get_low("SYS_TABLES");
77
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
78
ut_a(!dict_table_is_comp(sys_tables));
80
tuple = dtuple_create(heap, 1);
81
dfield = dtuple_get_nth_field(tuple, 0);
83
dfield_set_data(dfield, name, ut_strlen(name));
84
dict_index_copy_types(tuple, sys_index, 1);
86
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
87
BTR_SEARCH_LEAF, &pcur, &mtr);
89
rec = btr_pcur_get_rec(&pcur);
91
if (!btr_pcur_is_on_user_rec(&pcur)) {
94
btr_pcur_close(&pcur);
101
field = rec_get_nth_field_old(rec, 0, &len);
103
if (len < strlen(name)
104
|| ut_memcmp(name, field, strlen(name)) != 0) {
107
btr_pcur_close(&pcur);
114
if (!rec_get_deleted_flag(rec, 0)) {
118
char* table_name = mem_strdupl((char*) field, len);
120
btr_pcur_close(&pcur);
127
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
132
/************************************************************************
133
Prints to the standard output information on all tables found in the data
134
dictionary system table. */
140
dict_table_t* sys_tables;
141
dict_index_t* sys_index;
149
/* Enlarge the fatal semaphore wait timeout during the InnoDB table
152
mutex_enter(&kernel_mutex);
153
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
154
mutex_exit(&kernel_mutex);
156
mutex_enter(&(dict_sys->mutex));
160
sys_tables = dict_table_get_low("SYS_TABLES");
161
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
163
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
166
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
168
rec = btr_pcur_get_rec(&pcur);
170
if (!btr_pcur_is_on_user_rec(&pcur)) {
173
btr_pcur_close(&pcur);
176
mutex_exit(&(dict_sys->mutex));
178
/* Restore the fatal semaphore wait timeout */
180
mutex_enter(&kernel_mutex);
181
srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
182
mutex_exit(&kernel_mutex);
187
field = rec_get_nth_field_old(rec, 0, &len);
189
if (!rec_get_deleted_flag(rec, 0)) {
193
char* table_name = mem_strdupl((char*) field, len);
195
btr_pcur_store_position(&pcur, &mtr);
199
table = dict_table_get_low(table_name);
200
mem_free(table_name);
203
fputs("InnoDB: Failed to load table ", stderr);
204
ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
207
/* The table definition was corrupt if there
210
if (dict_table_get_first_index(table)) {
211
dict_update_statistics_low(table, TRUE);
214
dict_table_print_low(table);
219
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
225
/************************************************************************
226
Determine the flags of a table described in SYS_TABLES. */
229
dict_sys_tables_get_flags(
230
/*======================*/
231
/* out: compressed page size in kilobytes;
232
or 0 if the tablespace is uncompressed,
233
ULINT_UNDEFINED on error */
234
const rec_t* rec) /* in: a record of SYS_TABLES */
241
field = rec_get_nth_field_old(rec, 5, &len);
244
flags = mach_read_from_4(field);
246
if (UNIV_LIKELY(flags == DICT_TABLE_ORDINARY)) {
250
field = rec_get_nth_field_old(rec, 4, &len);
251
n_cols = mach_read_from_4(field);
253
if (UNIV_UNLIKELY(!(n_cols & 0x80000000UL))) {
254
/* New file formats require ROW_FORMAT=COMPACT. */
255
return(ULINT_UNDEFINED);
258
switch (flags & (DICT_TF_FORMAT_MASK | DICT_TF_COMPACT)) {
260
case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT:
261
case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT | DICT_TF_COMPACT:
262
/* flags should be DICT_TABLE_ORDINARY,
263
or DICT_TF_FORMAT_MASK should be nonzero. */
264
return(ULINT_UNDEFINED);
266
case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT | DICT_TF_COMPACT:
267
#if DICT_TF_FORMAT_MAX > DICT_TF_FORMAT_ZIP
268
# error "missing case labels for DICT_TF_FORMAT_ZIP .. DICT_TF_FORMAT_MAX"
270
/* We support this format. */
274
if (UNIV_UNLIKELY((flags & DICT_TF_ZSSIZE_MASK)
275
> (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT))) {
276
/* Unsupported compressed page size. */
277
return(ULINT_UNDEFINED);
280
if (UNIV_UNLIKELY(flags & (~0 << DICT_TF_BITS))) {
281
/* Some unused bits are set. */
282
return(ULINT_UNDEFINED);
288
/************************************************************************
289
In a crash recovery we already have all the tablespace objects created.
290
This function compares the space id information in the InnoDB data dictionary
291
to what we already read with fil_load_single_table_tablespaces().
293
In a normal startup, we create the tablespace objects for every table in
294
InnoDB's data dictionary, if the corresponding .ibd file exists.
295
We also scan the biggest space id, and store it to fil_system. */
298
dict_check_tablespaces_and_store_max_id(
299
/*====================================*/
300
ibool in_crash_recovery) /* in: are we doing a crash recovery */
302
dict_table_t* sys_tables;
303
dict_index_t* sys_index;
306
ulint max_space_id = 0;
309
mutex_enter(&(dict_sys->mutex));
313
sys_tables = dict_table_get_low("SYS_TABLES");
314
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
315
ut_a(!dict_table_is_comp(sys_tables));
317
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
320
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
322
rec = btr_pcur_get_rec(&pcur);
324
if (!btr_pcur_is_on_user_rec(&pcur)) {
327
btr_pcur_close(&pcur);
330
/* We must make the tablespace cache aware of the biggest
333
/* printf("Biggest space id in data dictionary %lu\n",
335
fil_set_max_space_id_if_bigger(max_space_id);
337
mutex_exit(&(dict_sys->mutex));
342
if (!rec_get_deleted_flag(rec, 0)) {
351
field = rec_get_nth_field_old(rec, 0, &len);
352
name = mem_strdupl((char*) field, len);
354
flags = dict_sys_tables_get_flags(rec);
355
if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
357
field = rec_get_nth_field_old(rec, 5, &len);
358
flags = mach_read_from_4(field);
360
ut_print_timestamp(stderr);
361
fputs(" InnoDB: Error: table ", stderr);
362
ut_print_filename(stderr, name);
364
"InnoDB: in InnoDB data dictionary"
365
" has unknown type %lx.\n",
371
field = rec_get_nth_field_old(rec, 9, &len);
374
space_id = mach_read_from_4(field);
376
btr_pcur_store_position(&pcur, &mtr);
380
if (space_id != 0 && in_crash_recovery) {
381
/* Check that the tablespace (the .ibd file) really
382
exists; print a warning to the .err log if not */
384
fil_space_for_table_exists_in_mem(space_id, name,
388
if (space_id != 0 && !in_crash_recovery) {
389
/* It is a normal database startup: create the space
390
object and check that the .ibd file exists. */
392
fil_open_single_table_tablespace(FALSE, space_id,
398
if (space_id > max_space_id) {
399
max_space_id = space_id;
404
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
410
/************************************************************************
411
Loads definitions for table columns. */
416
dict_table_t* table, /* in: table */
417
mem_heap_t* heap) /* in: memory heap for temporary storage */
419
dict_table_t* sys_columns;
420
dict_index_t* sys_index;
435
ut_ad(mutex_own(&(dict_sys->mutex)));
439
sys_columns = dict_table_get_low("SYS_COLUMNS");
440
sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
441
ut_a(!dict_table_is_comp(sys_columns));
443
tuple = dtuple_create(heap, 1);
444
dfield = dtuple_get_nth_field(tuple, 0);
446
buf = mem_heap_alloc(heap, 8);
447
mach_write_to_8(buf, table->id);
449
dfield_set_data(dfield, buf, 8);
450
dict_index_copy_types(tuple, sys_index, 1);
452
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
453
BTR_SEARCH_LEAF, &pcur, &mtr);
454
for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
456
rec = btr_pcur_get_rec(&pcur);
458
ut_a(btr_pcur_is_on_user_rec(&pcur));
460
ut_a(!rec_get_deleted_flag(rec, 0));
462
field = rec_get_nth_field_old(rec, 0, &len);
464
ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
466
field = rec_get_nth_field_old(rec, 1, &len);
468
ut_a(i == mach_read_from_4(field));
470
ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
472
field = rec_get_nth_field_old(rec, 4, &len);
473
name = mem_heap_strdupl(heap, (char*) field, len);
475
field = rec_get_nth_field_old(rec, 5, &len);
476
mtype = mach_read_from_4(field);
478
field = rec_get_nth_field_old(rec, 6, &len);
479
prtype = mach_read_from_4(field);
481
if (dtype_get_charset_coll(prtype) == 0
482
&& dtype_is_string_type(mtype)) {
483
/* The table was created with < 4.1.2. */
485
if (dtype_is_binary_string_type(mtype, prtype)) {
486
/* Use the binary collation for
487
string columns of binary type. */
489
prtype = dtype_form_prtype(
491
DATA_MYSQL_BINARY_CHARSET_COLL);
493
/* Use the default charset for
494
other than binary columns. */
496
prtype = dtype_form_prtype(
498
data_mysql_default_charset_coll);
502
field = rec_get_nth_field_old(rec, 7, &len);
503
col_len = mach_read_from_4(field);
505
ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
507
dict_mem_table_add_col(table, heap, name,
508
mtype, prtype, col_len);
509
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
512
btr_pcur_close(&pcur);
516
/************************************************************************
517
Loads definitions for index fields. */
522
dict_index_t* index, /* in: index whose fields to load */
523
mem_heap_t* heap) /* in: memory heap for temporary storage */
525
dict_table_t* sys_fields;
526
dict_index_t* sys_index;
530
ulint pos_and_prefix_len;
539
ut_ad(mutex_own(&(dict_sys->mutex)));
543
sys_fields = dict_table_get_low("SYS_FIELDS");
544
sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
545
ut_a(!dict_table_is_comp(sys_fields));
547
tuple = dtuple_create(heap, 1);
548
dfield = dtuple_get_nth_field(tuple, 0);
550
buf = mem_heap_alloc(heap, 8);
551
mach_write_to_8(buf, index->id);
553
dfield_set_data(dfield, buf, 8);
554
dict_index_copy_types(tuple, sys_index, 1);
556
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
557
BTR_SEARCH_LEAF, &pcur, &mtr);
558
for (i = 0; i < index->n_fields; i++) {
560
rec = btr_pcur_get_rec(&pcur);
562
ut_a(btr_pcur_is_on_user_rec(&pcur));
564
/* There could be delete marked records in SYS_FIELDS
565
because SYS_FIELDS.INDEX_ID can be updated
566
by ALTER TABLE ADD INDEX. */
568
if (rec_get_deleted_flag(rec, 0)) {
573
field = rec_get_nth_field_old(rec, 0, &len);
576
field = rec_get_nth_field_old(rec, 1, &len);
579
/* The next field stores the field position in the index
580
and a possible column prefix length if the index field
581
does not contain the whole column. The storage format is
582
like this: if there is at least one prefix field in the index,
583
then the HIGH 2 bytes contain the field number (== i) and the
584
low 2 bytes the prefix length for the field. Otherwise the
585
field number (== i) is contained in the 2 LOW bytes. */
587
pos_and_prefix_len = mach_read_from_4(field);
589
ut_a((pos_and_prefix_len & 0xFFFFUL) == i
590
|| (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
592
if ((i == 0 && pos_and_prefix_len > 0)
593
|| (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
595
prefix_len = pos_and_prefix_len & 0xFFFFUL;
600
ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
602
field = rec_get_nth_field_old(rec, 4, &len);
604
dict_mem_index_add_field(index,
605
mem_heap_strdupl(heap,
610
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
613
btr_pcur_close(&pcur);
617
/************************************************************************
618
Loads definitions for table indexes. Adds them to the data dictionary
624
/* out: DB_SUCCESS if ok, DB_CORRUPTION
625
if corruption of dictionary table or
626
DB_UNSUPPORTED if table has unknown index
628
dict_table_t* table, /* in: table */
629
mem_heap_t* heap) /* in: memory heap for temporary storage */
631
dict_table_t* sys_indexes;
632
dict_index_t* sys_index;
650
ulint error = DB_SUCCESS;
652
ut_ad(mutex_own(&(dict_sys->mutex)));
654
if ((ut_dulint_get_high(table->id) == 0)
655
&& (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
658
is_sys_table = FALSE;
663
sys_indexes = dict_table_get_low("SYS_INDEXES");
664
sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
665
ut_a(!dict_table_is_comp(sys_indexes));
667
tuple = dtuple_create(heap, 1);
668
dfield = dtuple_get_nth_field(tuple, 0);
670
buf = mem_heap_alloc(heap, 8);
671
mach_write_to_8(buf, table->id);
673
dfield_set_data(dfield, buf, 8);
674
dict_index_copy_types(tuple, sys_index, 1);
676
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
677
BTR_SEARCH_LEAF, &pcur, &mtr);
679
if (!btr_pcur_is_on_user_rec(&pcur)) {
684
rec = btr_pcur_get_rec(&pcur);
686
field = rec_get_nth_field_old(rec, 0, &len);
689
if (ut_memcmp(buf, field, len) != 0) {
691
} else if (rec_get_deleted_flag(rec, 0)) {
692
/* Skip delete marked records */
696
field = rec_get_nth_field_old(rec, 1, &len);
698
id = mach_read_from_8(field);
700
ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
702
field = rec_get_nth_field_old(rec, 4, &name_len);
703
name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
705
field = rec_get_nth_field_old(rec, 5, &len);
706
n_fields = mach_read_from_4(field);
708
field = rec_get_nth_field_old(rec, 6, &len);
709
type = mach_read_from_4(field);
711
field = rec_get_nth_field_old(rec, 7, &len);
712
space = mach_read_from_4(field);
714
ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
716
field = rec_get_nth_field_old(rec, 8, &len);
717
page_no = mach_read_from_4(field);
719
/* We check for unsupported types first, so that the
720
subsequent checks are relevant for the supported types. */
721
if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
724
"InnoDB: Error: unknown type %lu"
725
" of index %s of table %s\n",
726
(ulong) type, name_buf, table->name);
728
error = DB_UNSUPPORTED;
730
} else if (page_no == FIL_NULL) {
733
"InnoDB: Error: trying to load index %s"
735
"InnoDB: but the index tree has been freed!\n",
736
name_buf, table->name);
738
error = DB_CORRUPTION;
740
} else if ((type & DICT_CLUSTERED) == 0
741
&& NULL == dict_table_get_first_index(table)) {
743
fputs("InnoDB: Error: trying to load index ",
745
ut_print_name(stderr, NULL, FALSE, name_buf);
746
fputs(" for table ", stderr);
747
ut_print_name(stderr, NULL, TRUE, table->name);
748
fputs("\nInnoDB: but the first index"
749
" is not clustered!\n", stderr);
751
error = DB_CORRUPTION;
753
} else if (is_sys_table
754
&& ((type & DICT_CLUSTERED)
755
|| ((table == dict_sys->sys_tables)
756
&& (name_len == (sizeof "ID_IND") - 1)
757
&& (0 == ut_memcmp(name_buf,
758
"ID_IND", name_len))))) {
760
/* The index was created in memory already at booting
761
of the database server */
763
index = dict_mem_index_create(table->name, name_buf,
764
space, type, n_fields);
767
dict_load_fields(index, heap);
768
error = dict_index_add_to_cache(table, index, page_no);
769
/* The data dictionary tables should never contain
770
invalid index definitions. If we ignored this error
771
and simply did not load this index definition, the
772
.frm file would disagree with the index definitions
774
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
781
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
785
btr_pcur_close(&pcur);
791
/************************************************************************
792
Loads a table definition and also all its index definitions, and also
793
the cluster definition if the table is a member in a cluster. Also loads
794
all foreign key constraints where the foreign key is in the table or where
795
a foreign key references columns in this table. Adds all these to the data
801
/* out: table, NULL if does not exist;
802
if the table is stored in an .ibd file,
803
but the file does not exist,
804
then we set the ibd_file_missing flag TRUE
805
in the table object we return */
806
const char* name) /* in: table name in the
807
databasename/tablename format */
809
ibool ibd_file_missing = FALSE;
811
dict_table_t* sys_tables;
813
dict_index_t* sys_index;
826
ut_ad(mutex_own(&(dict_sys->mutex)));
828
heap = mem_heap_create(32000);
832
sys_tables = dict_table_get_low("SYS_TABLES");
833
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
834
ut_a(!dict_table_is_comp(sys_tables));
836
tuple = dtuple_create(heap, 1);
837
dfield = dtuple_get_nth_field(tuple, 0);
839
dfield_set_data(dfield, name, ut_strlen(name));
840
dict_index_copy_types(tuple, sys_index, 1);
842
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
843
BTR_SEARCH_LEAF, &pcur, &mtr);
844
rec = btr_pcur_get_rec(&pcur);
846
if (!btr_pcur_is_on_user_rec(&pcur)
847
|| rec_get_deleted_flag(rec, 0)) {
850
btr_pcur_close(&pcur);
857
field = rec_get_nth_field_old(rec, 0, &len);
859
/* Check if the table name in record is the searched one */
860
if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
865
ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
867
field = rec_get_nth_field_old(rec, 9, &len);
868
space = mach_read_from_4(field);
870
/* Check if the tablespace exists and has the right name */
872
flags = dict_sys_tables_get_flags(rec);
874
if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
875
field = rec_get_nth_field_old(rec, 5, &len);
876
flags = mach_read_from_4(field);
878
ut_print_timestamp(stderr);
879
fputs(" InnoDB: Error: table ", stderr);
880
ut_print_filename(stderr, name);
882
"InnoDB: in InnoDB data dictionary"
883
" has unknown type %lx.\n",
888
if (fil_space_for_table_exists_in_mem(space, name, FALSE,
890
/* Ok; (if we did a crash recovery then the tablespace
891
can already be in the memory cache) */
893
/* In >= 4.1.9, InnoDB scans the data dictionary also
894
at a normal mysqld startup. It is an error if the
895
space object does not exist in memory. */
897
ut_print_timestamp(stderr);
899
" InnoDB: error: space object of table %s,\n"
900
"InnoDB: space id %lu did not exist in memory."
901
" Retrying an open.\n",
903
/* Try to open the tablespace */
904
if (!fil_open_single_table_tablespace(
905
TRUE, space, flags, name)) {
906
/* We failed to find a sensible tablespace
909
ibd_file_missing = TRUE;
916
ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
918
field = rec_get_nth_field_old(rec, 4, &len);
919
n_cols = mach_read_from_4(field);
921
/* The high-order bit of N_COLS is the "compact format" flag. */
922
if (n_cols & 0x80000000UL) {
923
flags |= DICT_TF_COMPACT;
926
table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
929
table->ibd_file_missing = (unsigned int) ibd_file_missing;
931
ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
933
field = rec_get_nth_field_old(rec, 3, &len);
934
table->id = mach_read_from_8(field);
936
btr_pcur_close(&pcur);
939
dict_load_columns(table, heap);
941
dict_table_add_to_cache(table, heap);
943
mem_heap_empty(heap);
945
err = dict_load_indexes(table, heap);
946
#ifndef UNIV_HOTBACKUP
947
/* If the force recovery flag is set, we open the table irrespective
948
of the error condition, since the user may want to dump data from the
949
clustered index. However we load the foreign key information only if
950
all indexes were loaded. */
951
if (err != DB_SUCCESS && !srv_force_recovery) {
952
dict_mem_table_free(table);
954
} else if (err == DB_SUCCESS) {
955
err = dict_load_foreigns(table->name, TRUE);
958
if (err != DB_SUCCESS && table != NULL) {
960
mutex_enter(&dict_foreign_err_mutex);
962
ut_print_timestamp(stderr);
965
" InnoDB: Error: could not make a foreign key"
966
" definition to match\n"
967
"InnoDB: the foreign key table"
968
" or the referenced table!\n"
969
"InnoDB: The data dictionary of InnoDB is corrupt."
970
" You may need to drop\n"
971
"InnoDB: and recreate the foreign key table"
972
" or the referenced table.\n"
973
"InnoDB: Submit a detailed bug report"
974
" to http://bugs.mysql.com\n"
975
"InnoDB: Latest foreign key error printout:\n%s\n",
976
dict_foreign_err_buf);
978
mutex_exit(&dict_foreign_err_mutex);
981
#endif /* !UNIV_HOTBACKUP */
987
/***************************************************************************
988
Loads a table object based on the table id. */
991
dict_load_table_on_id(
992
/*==================*/
993
/* out: table; NULL if table does not exist */
994
dulint table_id) /* in: table id */
1001
dict_index_t* sys_table_ids;
1002
dict_table_t* sys_tables;
1006
dict_table_t* table;
1009
ut_ad(mutex_own(&(dict_sys->mutex)));
1011
/* NOTE that the operation of this function is protected by
1012
the dictionary mutex, and therefore no deadlocks can occur
1013
with other dictionary operations. */
1016
/*---------------------------------------------------*/
1017
/* Get the secondary index based on ID for table SYS_TABLES */
1018
sys_tables = dict_sys->sys_tables;
1019
sys_table_ids = dict_table_get_next_index(
1020
dict_table_get_first_index(sys_tables));
1021
ut_a(!dict_table_is_comp(sys_tables));
1022
heap = mem_heap_create(256);
1024
tuple = dtuple_create(heap, 1);
1025
dfield = dtuple_get_nth_field(tuple, 0);
1027
/* Write the table id in byte format to id_buf */
1028
mach_write_to_8(id_buf, table_id);
1030
dfield_set_data(dfield, id_buf, 8);
1031
dict_index_copy_types(tuple, sys_table_ids, 1);
1033
btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
1034
BTR_SEARCH_LEAF, &pcur, &mtr);
1035
rec = btr_pcur_get_rec(&pcur);
1037
if (!btr_pcur_is_on_user_rec(&pcur)
1038
|| rec_get_deleted_flag(rec, 0)) {
1041
btr_pcur_close(&pcur);
1043
mem_heap_free(heap);
1048
/*---------------------------------------------------*/
1049
/* Now we have the record in the secondary index containing the
1050
table ID and NAME */
1052
rec = btr_pcur_get_rec(&pcur);
1053
field = rec_get_nth_field_old(rec, 0, &len);
1056
/* Check if the table id in record is the one searched for */
1057
if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
1059
btr_pcur_close(&pcur);
1061
mem_heap_free(heap);
1066
/* Now we get the table name from the record */
1067
field = rec_get_nth_field_old(rec, 1, &len);
1068
/* Load the table definition to memory */
1069
table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
1071
btr_pcur_close(&pcur);
1073
mem_heap_free(heap);
1078
/************************************************************************
1079
This function is called when the database is booted. Loads system table
1080
index definitions except for the clustered index which is added to the
1081
dictionary cache at booting before calling this function. */
1084
dict_load_sys_table(
1085
/*================*/
1086
dict_table_t* table) /* in: system table */
1090
ut_ad(mutex_own(&(dict_sys->mutex)));
1092
heap = mem_heap_create(1000);
1094
dict_load_indexes(table, heap);
1096
mem_heap_free(heap);
1099
#ifndef UNIV_HOTBACKUP
1100
/************************************************************************
1101
Loads foreign key constraint col names (also for the referenced table). */
1104
dict_load_foreign_cols(
1105
/*===================*/
1106
const char* id, /* in: foreign constraint id as a
1107
null-terminated string */
1108
dict_foreign_t* foreign)/* in: foreign constraint object */
1110
dict_table_t* sys_foreign_cols;
1111
dict_index_t* sys_index;
1121
ut_ad(mutex_own(&(dict_sys->mutex)));
1123
foreign->foreign_col_names = mem_heap_alloc(
1124
foreign->heap, foreign->n_fields * sizeof(void*));
1126
foreign->referenced_col_names = mem_heap_alloc(
1127
foreign->heap, foreign->n_fields * sizeof(void*));
1130
sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
1131
sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
1132
ut_a(!dict_table_is_comp(sys_foreign_cols));
1134
tuple = dtuple_create(foreign->heap, 1);
1135
dfield = dtuple_get_nth_field(tuple, 0);
1137
dfield_set_data(dfield, id, ut_strlen(id));
1138
dict_index_copy_types(tuple, sys_index, 1);
1140
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1141
BTR_SEARCH_LEAF, &pcur, &mtr);
1142
for (i = 0; i < foreign->n_fields; i++) {
1144
rec = btr_pcur_get_rec(&pcur);
1146
ut_a(btr_pcur_is_on_user_rec(&pcur));
1147
ut_a(!rec_get_deleted_flag(rec, 0));
1149
field = rec_get_nth_field_old(rec, 0, &len);
1150
ut_a(len == ut_strlen(id));
1151
ut_a(ut_memcmp(id, field, len) == 0);
1153
field = rec_get_nth_field_old(rec, 1, &len);
1155
ut_a(i == mach_read_from_4(field));
1157
field = rec_get_nth_field_old(rec, 4, &len);
1158
foreign->foreign_col_names[i] = mem_heap_strdupl(
1159
foreign->heap, (char*) field, len);
1161
field = rec_get_nth_field_old(rec, 5, &len);
1162
foreign->referenced_col_names[i] = mem_heap_strdupl(
1163
foreign->heap, (char*) field, len);
1165
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1168
btr_pcur_close(&pcur);
1172
/***************************************************************************
1173
Loads a foreign key constraint to the dictionary cache. */
1178
/* out: DB_SUCCESS or error code */
1179
const char* id, /* in: foreign constraint id as a
1180
null-terminated string */
1181
ibool check_charsets)
1182
/* in: TRUE=check charset compatibility */
1184
dict_foreign_t* foreign;
1185
dict_table_t* sys_foreign;
1187
dict_index_t* sys_index;
1194
ulint n_fields_and_type;
1197
ut_ad(mutex_own(&(dict_sys->mutex)));
1199
heap2 = mem_heap_create(1000);
1203
sys_foreign = dict_table_get_low("SYS_FOREIGN");
1204
sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
1205
ut_a(!dict_table_is_comp(sys_foreign));
1207
tuple = dtuple_create(heap2, 1);
1208
dfield = dtuple_get_nth_field(tuple, 0);
1210
dfield_set_data(dfield, id, ut_strlen(id));
1211
dict_index_copy_types(tuple, sys_index, 1);
1213
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1214
BTR_SEARCH_LEAF, &pcur, &mtr);
1215
rec = btr_pcur_get_rec(&pcur);
1217
if (!btr_pcur_is_on_user_rec(&pcur)
1218
|| rec_get_deleted_flag(rec, 0)) {
1222
"InnoDB: Error A: cannot load foreign constraint %s\n",
1225
btr_pcur_close(&pcur);
1227
mem_heap_free(heap2);
1232
field = rec_get_nth_field_old(rec, 0, &len);
1234
/* Check if the id in record is the searched one */
1235
if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
1238
"InnoDB: Error B: cannot load foreign constraint %s\n",
1241
btr_pcur_close(&pcur);
1243
mem_heap_free(heap2);
1248
/* Read the table names and the number of columns associated
1249
with the constraint */
1251
mem_heap_free(heap2);
1253
foreign = dict_mem_foreign_create();
1255
n_fields_and_type = mach_read_from_4(
1256
rec_get_nth_field_old(rec, 5, &len));
1260
/* We store the type in the bits 24..29 of n_fields_and_type. */
1262
foreign->type = (unsigned int) (n_fields_and_type >> 24);
1263
foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
1265
foreign->id = mem_heap_strdup(foreign->heap, id);
1267
field = rec_get_nth_field_old(rec, 3, &len);
1268
foreign->foreign_table_name = mem_heap_strdupl(
1269
foreign->heap, (char*) field, len);
1271
field = rec_get_nth_field_old(rec, 4, &len);
1272
foreign->referenced_table_name = mem_heap_strdupl(
1273
foreign->heap, (char*) field, len);
1275
btr_pcur_close(&pcur);
1278
dict_load_foreign_cols(id, foreign);
1280
/* If the foreign table is not yet in the dictionary cache, we
1281
have to load it so that we are able to make type comparisons
1282
in the next function call. */
1284
dict_table_get_low(foreign->foreign_table_name);
1286
/* Note that there may already be a foreign constraint object in
1287
the dictionary cache for this constraint: then the following
1288
call only sets the pointers in it to point to the appropriate table
1289
and index objects and frees the newly created object foreign.
1290
Adding to the cache should always succeed since we are not creating
1291
a new foreign key constraint but loading one from the data
1294
return(dict_foreign_add_to_cache(foreign, check_charsets));
1297
/***************************************************************************
1298
Loads foreign key constraints where the table is either the foreign key
1299
holder or where the table is referenced by a foreign key. Adds these
1300
constraints to the data dictionary. Note that we know that the dictionary
1301
cache already contains all constraints where the other relevant table is
1302
already in the dictionary cache. */
1307
/* out: DB_SUCCESS or error code */
1308
const char* table_name, /* in: table name */
1309
ibool check_charsets) /* in: TRUE=check charset
1316
dict_index_t* sec_index;
1317
dict_table_t* sys_foreign;
1325
ut_ad(mutex_own(&(dict_sys->mutex)));
1327
sys_foreign = dict_table_get_low("SYS_FOREIGN");
1329
if (sys_foreign == NULL) {
1330
/* No foreign keys defined yet in this database */
1333
"InnoDB: Error: no foreign key system tables"
1334
" in the database\n");
1339
ut_a(!dict_table_is_comp(sys_foreign));
1342
/* Get the secondary index based on FOR_NAME from table
1345
sec_index = dict_table_get_next_index(
1346
dict_table_get_first_index(sys_foreign));
1348
heap = mem_heap_create(256);
1350
tuple = dtuple_create(heap, 1);
1351
dfield = dtuple_get_nth_field(tuple, 0);
1353
dfield_set_data(dfield, table_name, ut_strlen(table_name));
1354
dict_index_copy_types(tuple, sec_index, 1);
1356
btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE,
1357
BTR_SEARCH_LEAF, &pcur, &mtr);
1359
rec = btr_pcur_get_rec(&pcur);
1361
if (!btr_pcur_is_on_user_rec(&pcur)) {
1364
goto load_next_index;
1367
/* Now we have the record in the secondary index containing a table
1368
name and a foreign constraint ID */
1370
rec = btr_pcur_get_rec(&pcur);
1371
field = rec_get_nth_field_old(rec, 0, &len);
1373
/* Check if the table name in the record is the one searched for; the
1374
following call does the comparison in the latin1_swedish_ci
1375
charset-collation, in a case-insensitive way. */
1377
if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
1378
dfield_get_type(dfield)->prtype,
1379
dfield_get_data(dfield), dfield_get_len(dfield),
1382
goto load_next_index;
1385
/* Since table names in SYS_FOREIGN are stored in a case-insensitive
1386
order, we have to check that the table name matches also in a binary
1387
string comparison. On Unix, MySQL allows table names that only differ
1388
in character case. */
1390
if (0 != ut_memcmp(field, table_name, len)) {
1395
if (rec_get_deleted_flag(rec, 0)) {
1400
/* Now we get a foreign key constraint id */
1401
field = rec_get_nth_field_old(rec, 1, &len);
1402
id = mem_heap_strdupl(heap, (char*) field, len);
1404
btr_pcur_store_position(&pcur, &mtr);
1408
/* Load the foreign constraint definition to the dictionary cache */
1410
err = dict_load_foreign(id, check_charsets);
1412
if (err != DB_SUCCESS) {
1413
btr_pcur_close(&pcur);
1414
mem_heap_free(heap);
1421
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
1423
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1428
btr_pcur_close(&pcur);
1430
mem_heap_free(heap);
1432
sec_index = dict_table_get_next_index(sec_index);
1434
if (sec_index != NULL) {
1443
#endif /* !UNIV_HOTBACKUP */