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, &mtr)) {
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, &mtr)) {
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
In a crash recovery we already have all the tablespace objects created.
227
This function compares the space id information in the InnoDB data dictionary
228
to what we already read with fil_load_single_table_tablespaces().
230
In a normal startup, we create the tablespace objects for every table in
231
InnoDB's data dictionary, if the corresponding .ibd file exists.
232
We also scan the biggest space id, and store it to fil_system. */
235
dict_check_tablespaces_and_store_max_id(
236
/*====================================*/
237
ibool in_crash_recovery) /* in: are we doing a crash recovery */
239
dict_table_t* sys_tables;
240
dict_index_t* sys_index;
246
ulint max_space_id = 0;
249
mutex_enter(&(dict_sys->mutex));
253
sys_tables = dict_table_get_low("SYS_TABLES");
254
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
255
ut_a(!dict_table_is_comp(sys_tables));
257
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
260
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
262
rec = btr_pcur_get_rec(&pcur);
264
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
267
btr_pcur_close(&pcur);
270
/* We must make the tablespace cache aware of the biggest
273
/* printf("Biggest space id in data dictionary %lu\n",
275
fil_set_max_space_id_if_bigger(max_space_id);
277
mutex_exit(&(dict_sys->mutex));
282
field = rec_get_nth_field_old(rec, 0, &len);
284
if (!rec_get_deleted_flag(rec, 0)) {
288
char* name = mem_strdupl((char*) field, len);
290
field = rec_get_nth_field_old(rec, 9, &len);
293
space_id = mach_read_from_4(field);
295
btr_pcur_store_position(&pcur, &mtr);
299
if (space_id != 0 && in_crash_recovery) {
300
/* Check that the tablespace (the .ibd file) really
301
exists; print a warning to the .err log if not */
303
fil_space_for_table_exists_in_mem(space_id, name,
307
if (space_id != 0 && !in_crash_recovery) {
308
/* It is a normal database startup: create the space
309
object and check that the .ibd file exists. */
311
fil_open_single_table_tablespace(FALSE, space_id,
317
if (space_id > max_space_id) {
318
max_space_id = space_id;
323
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
329
/************************************************************************
330
Loads definitions for table columns. */
335
dict_table_t* table, /* in: table */
336
mem_heap_t* heap) /* in: memory heap for temporary storage */
338
dict_table_t* sys_columns;
339
dict_index_t* sys_index;
354
ut_ad(mutex_own(&(dict_sys->mutex)));
358
sys_columns = dict_table_get_low("SYS_COLUMNS");
359
sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
360
ut_a(!dict_table_is_comp(sys_columns));
362
tuple = dtuple_create(heap, 1);
363
dfield = dtuple_get_nth_field(tuple, 0);
365
buf = mem_heap_alloc(heap, 8);
366
mach_write_to_8(buf, table->id);
368
dfield_set_data(dfield, buf, 8);
369
dict_index_copy_types(tuple, sys_index, 1);
371
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
372
BTR_SEARCH_LEAF, &pcur, &mtr);
373
for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
375
rec = btr_pcur_get_rec(&pcur);
377
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
379
ut_a(!rec_get_deleted_flag(rec, 0));
381
field = rec_get_nth_field_old(rec, 0, &len);
383
ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
385
field = rec_get_nth_field_old(rec, 1, &len);
387
ut_a(i == mach_read_from_4(field));
389
ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
391
field = rec_get_nth_field_old(rec, 4, &len);
392
name = mem_heap_strdupl(heap, (char*) field, len);
394
field = rec_get_nth_field_old(rec, 5, &len);
395
mtype = mach_read_from_4(field);
397
field = rec_get_nth_field_old(rec, 6, &len);
398
prtype = mach_read_from_4(field);
400
if (dtype_get_charset_coll(prtype) == 0
401
&& dtype_is_string_type(mtype)) {
402
/* The table was created with < 4.1.2. */
404
if (dtype_is_binary_string_type(mtype, prtype)) {
405
/* Use the binary collation for
406
string columns of binary type. */
408
prtype = dtype_form_prtype(
410
DATA_MYSQL_BINARY_CHARSET_COLL);
412
/* Use the default charset for
413
other than binary columns. */
415
prtype = dtype_form_prtype(
417
data_mysql_default_charset_coll);
421
field = rec_get_nth_field_old(rec, 7, &len);
422
col_len = mach_read_from_4(field);
424
ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
426
dict_mem_table_add_col(table, heap, name,
427
mtype, prtype, col_len);
428
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
431
btr_pcur_close(&pcur);
435
/************************************************************************
436
Report that an index field or index for a table has been delete marked. */
439
dict_load_report_deleted_index(
440
/*===========================*/
441
const char* name, /* in: table name */
442
ulint field) /* in: index field, or ULINT_UNDEFINED */
444
fprintf(stderr, "InnoDB: Error: data dictionary entry"
445
" for table %s is corrupt!\n", name);
446
if (field != ULINT_UNDEFINED) {
448
"InnoDB: Index field %lu is delete marked.\n", field);
450
fputs("InnoDB: An index is delete marked.\n", stderr);
454
/************************************************************************
455
Loads definitions for index fields. */
460
dict_table_t* table, /* in: table */
461
dict_index_t* index, /* in: index whose fields to load */
462
mem_heap_t* heap) /* in: memory heap for temporary storage */
464
dict_table_t* sys_fields;
465
dict_index_t* sys_index;
469
ulint pos_and_prefix_len;
478
ut_ad(mutex_own(&(dict_sys->mutex)));
482
sys_fields = dict_table_get_low("SYS_FIELDS");
483
sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
484
ut_a(!dict_table_is_comp(sys_fields));
486
tuple = dtuple_create(heap, 1);
487
dfield = dtuple_get_nth_field(tuple, 0);
489
buf = mem_heap_alloc(heap, 8);
490
mach_write_to_8(buf, index->id);
492
dfield_set_data(dfield, buf, 8);
493
dict_index_copy_types(tuple, sys_index, 1);
495
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
496
BTR_SEARCH_LEAF, &pcur, &mtr);
497
for (i = 0; i < index->n_fields; i++) {
499
rec = btr_pcur_get_rec(&pcur);
501
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
502
if (rec_get_deleted_flag(rec, 0)) {
503
dict_load_report_deleted_index(table->name, i);
506
field = rec_get_nth_field_old(rec, 0, &len);
508
ut_a(ut_memcmp(buf, field, len) == 0);
510
field = rec_get_nth_field_old(rec, 1, &len);
513
/* The next field stores the field position in the index
514
and a possible column prefix length if the index field
515
does not contain the whole column. The storage format is
516
like this: if there is at least one prefix field in the index,
517
then the HIGH 2 bytes contain the field number (== i) and the
518
low 2 bytes the prefix length for the field. Otherwise the
519
field number (== i) is contained in the 2 LOW bytes. */
521
pos_and_prefix_len = mach_read_from_4(field);
523
ut_a((pos_and_prefix_len & 0xFFFFUL) == i
524
|| (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
526
if ((i == 0 && pos_and_prefix_len > 0)
527
|| (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
529
prefix_len = pos_and_prefix_len & 0xFFFFUL;
534
ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
536
field = rec_get_nth_field_old(rec, 4, &len);
538
dict_mem_index_add_field(index,
539
mem_heap_strdupl(heap,
543
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
546
btr_pcur_close(&pcur);
550
/************************************************************************
551
Loads definitions for table indexes. Adds them to the data dictionary
557
/* out: DB_SUCCESS if ok, DB_CORRUPTION
558
if corruption of dictionary table or
559
DB_UNSUPPORTED if table has unknown index
561
dict_table_t* table, /* in: table */
562
mem_heap_t* heap) /* in: memory heap for temporary storage */
564
dict_table_t* sys_indexes;
565
dict_index_t* sys_index;
583
ulint error = DB_SUCCESS;
585
ut_ad(mutex_own(&(dict_sys->mutex)));
587
if ((ut_dulint_get_high(table->id) == 0)
588
&& (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
591
is_sys_table = FALSE;
596
sys_indexes = dict_table_get_low("SYS_INDEXES");
597
sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
598
ut_a(!dict_table_is_comp(sys_indexes));
600
tuple = dtuple_create(heap, 1);
601
dfield = dtuple_get_nth_field(tuple, 0);
603
buf = mem_heap_alloc(heap, 8);
604
mach_write_to_8(buf, table->id);
606
dfield_set_data(dfield, buf, 8);
607
dict_index_copy_types(tuple, sys_index, 1);
609
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
610
BTR_SEARCH_LEAF, &pcur, &mtr);
612
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
617
rec = btr_pcur_get_rec(&pcur);
619
field = rec_get_nth_field_old(rec, 0, &len);
622
if (ut_memcmp(buf, field, len) != 0) {
626
if (rec_get_deleted_flag(rec, 0)) {
627
dict_load_report_deleted_index(table->name,
630
error = DB_CORRUPTION;
634
field = rec_get_nth_field_old(rec, 1, &len);
636
id = mach_read_from_8(field);
638
ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
640
field = rec_get_nth_field_old(rec, 4, &name_len);
641
name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
643
field = rec_get_nth_field_old(rec, 5, &len);
644
n_fields = mach_read_from_4(field);
646
field = rec_get_nth_field_old(rec, 6, &len);
647
type = mach_read_from_4(field);
649
field = rec_get_nth_field_old(rec, 7, &len);
650
space = mach_read_from_4(field);
652
ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
654
field = rec_get_nth_field_old(rec, 8, &len);
655
page_no = mach_read_from_4(field);
657
/* We check for unsupported types first, so that the
658
subsequent checks are relevant for the supported types. */
659
if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
662
"InnoDB: Error: unknown type %lu"
663
" of index %s of table %s\n",
664
(ulong) type, name_buf, table->name);
666
error = DB_UNSUPPORTED;
668
} else if (page_no == FIL_NULL) {
671
"InnoDB: Error: trying to load index %s"
673
"InnoDB: but the index tree has been freed!\n",
674
name_buf, table->name);
676
error = DB_CORRUPTION;
678
} else if ((type & DICT_CLUSTERED) == 0
679
&& NULL == dict_table_get_first_index(table)) {
682
"InnoDB: Error: trying to load index %s"
684
"InnoDB: but the first index"
685
" is not clustered!\n",
686
name_buf, table->name);
688
error = DB_CORRUPTION;
690
} else if (is_sys_table
691
&& ((type & DICT_CLUSTERED)
692
|| ((table == dict_sys->sys_tables)
693
&& (name_len == (sizeof "ID_IND") - 1)
694
&& (0 == ut_memcmp(name_buf,
695
"ID_IND", name_len))))) {
697
/* The index was created in memory already at booting
698
of the database server */
700
index = dict_mem_index_create(table->name, name_buf,
701
space, type, n_fields);
704
dict_load_fields(table, index, heap);
705
dict_index_add_to_cache(table, index, page_no);
708
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
712
btr_pcur_close(&pcur);
718
/************************************************************************
719
Loads a table definition and also all its index definitions, and also
720
the cluster definition if the table is a member in a cluster. Also loads
721
all foreign key constraints where the foreign key is in the table or where
722
a foreign key references columns in this table. Adds all these to the data
728
/* out: table, NULL if does not exist;
729
if the table is stored in an .ibd file,
730
but the file does not exist,
731
then we set the ibd_file_missing flag TRUE
732
in the table object we return */
733
const char* name) /* in: table name in the
734
databasename/tablename format */
736
ibool ibd_file_missing = FALSE;
738
dict_table_t* sys_tables;
740
dict_index_t* sys_index;
753
ut_ad(mutex_own(&(dict_sys->mutex)));
755
heap = mem_heap_create(32000);
759
sys_tables = dict_table_get_low("SYS_TABLES");
760
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
761
ut_a(!dict_table_is_comp(sys_tables));
763
tuple = dtuple_create(heap, 1);
764
dfield = dtuple_get_nth_field(tuple, 0);
766
dfield_set_data(dfield, name, ut_strlen(name));
767
dict_index_copy_types(tuple, sys_index, 1);
769
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
770
BTR_SEARCH_LEAF, &pcur, &mtr);
771
rec = btr_pcur_get_rec(&pcur);
773
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
774
|| rec_get_deleted_flag(rec, 0)) {
777
btr_pcur_close(&pcur);
784
field = rec_get_nth_field_old(rec, 0, &len);
786
/* Check if the table name in record is the searched one */
787
if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
792
ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
794
field = rec_get_nth_field_old(rec, 9, &len);
795
space = mach_read_from_4(field);
797
/* Check if the tablespace exists and has the right name */
799
if (fil_space_for_table_exists_in_mem(space, name, FALSE,
801
/* Ok; (if we did a crash recovery then the tablespace
802
can already be in the memory cache) */
804
/* In >= 4.1.9, InnoDB scans the data dictionary also
805
at a normal mysqld startup. It is an error if the
806
space object does not exist in memory. */
808
ut_print_timestamp(stderr);
810
" InnoDB: error: space object of table %s,\n"
811
"InnoDB: space id %lu did not exist in memory."
812
" Retrying an open.\n",
814
/* Try to open the tablespace */
815
if (!fil_open_single_table_tablespace(TRUE,
817
/* We failed to find a sensible tablespace
820
ibd_file_missing = TRUE;
825
ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
827
field = rec_get_nth_field_old(rec, 4, &len);
828
n_cols = mach_read_from_4(field);
832
/* The high-order bit of N_COLS is the "compact format" flag. */
833
if (n_cols & 0x80000000UL) {
834
flags |= DICT_TF_COMPACT;
837
table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
840
table->ibd_file_missing = (unsigned int) ibd_file_missing;
842
ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
844
field = rec_get_nth_field_old(rec, 3, &len);
845
table->id = mach_read_from_8(field);
847
field = rec_get_nth_field_old(rec, 5, &len);
848
if (UNIV_UNLIKELY(mach_read_from_4(field) != DICT_TABLE_ORDINARY)) {
849
ut_print_timestamp(stderr);
851
" InnoDB: table %s: unknown table type %lu\n",
852
name, (ulong) mach_read_from_4(field));
856
btr_pcur_close(&pcur);
859
dict_load_columns(table, heap);
861
dict_table_add_to_cache(table, heap);
863
mem_heap_empty(heap);
865
err = dict_load_indexes(table, heap);
867
/* If the force recovery flag is set, we open the table irrespective
868
of the error condition, since the user may want to dump data from the
869
clustered index. However we load the foreign key information only if
870
all indexes were loaded. */
871
if (err != DB_SUCCESS && !srv_force_recovery) {
872
dict_mem_table_free(table);
874
} else if (err == DB_SUCCESS) {
875
err = dict_load_foreigns(table->name, TRUE);
878
if (err != DB_SUCCESS && table != NULL) {
880
mutex_enter(&dict_foreign_err_mutex);
882
ut_print_timestamp(stderr);
885
" InnoDB: Error: could not make a foreign key"
886
" definition to match\n"
887
"InnoDB: the foreign key table"
888
" or the referenced table!\n"
889
"InnoDB: The data dictionary of InnoDB is corrupt."
890
" You may need to drop\n"
891
"InnoDB: and recreate the foreign key table"
892
" or the referenced table.\n"
893
"InnoDB: Submit a detailed bug report"
894
" to http://bugs.mysql.com\n"
895
"InnoDB: Latest foreign key error printout:\n%s\n",
896
dict_foreign_err_buf);
898
mutex_exit(&dict_foreign_err_mutex);
906
/***************************************************************************
907
Loads a table object based on the table id. */
910
dict_load_table_on_id(
911
/*==================*/
912
/* out: table; NULL if table does not exist */
913
dulint table_id) /* in: table id */
920
dict_index_t* sys_table_ids;
921
dict_table_t* sys_tables;
928
ut_ad(mutex_own(&(dict_sys->mutex)));
930
/* NOTE that the operation of this function is protected by
931
the dictionary mutex, and therefore no deadlocks can occur
932
with other dictionary operations. */
935
/*---------------------------------------------------*/
936
/* Get the secondary index based on ID for table SYS_TABLES */
937
sys_tables = dict_sys->sys_tables;
938
sys_table_ids = dict_table_get_next_index(
939
dict_table_get_first_index(sys_tables));
940
ut_a(!dict_table_is_comp(sys_tables));
941
heap = mem_heap_create(256);
943
tuple = dtuple_create(heap, 1);
944
dfield = dtuple_get_nth_field(tuple, 0);
946
/* Write the table id in byte format to id_buf */
947
mach_write_to_8(id_buf, table_id);
949
dfield_set_data(dfield, id_buf, 8);
950
dict_index_copy_types(tuple, sys_table_ids, 1);
952
btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
953
BTR_SEARCH_LEAF, &pcur, &mtr);
954
rec = btr_pcur_get_rec(&pcur);
956
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
957
|| rec_get_deleted_flag(rec, 0)) {
960
btr_pcur_close(&pcur);
967
/*---------------------------------------------------*/
968
/* Now we have the record in the secondary index containing the
971
rec = btr_pcur_get_rec(&pcur);
972
field = rec_get_nth_field_old(rec, 0, &len);
975
/* Check if the table id in record is the one searched for */
976
if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
978
btr_pcur_close(&pcur);
985
/* Now we get the table name from the record */
986
field = rec_get_nth_field_old(rec, 1, &len);
987
/* Load the table definition to memory */
988
table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
990
btr_pcur_close(&pcur);
997
/************************************************************************
998
This function is called when the database is booted. Loads system table
999
index definitions except for the clustered index which is added to the
1000
dictionary cache at booting before calling this function. */
1003
dict_load_sys_table(
1004
/*================*/
1005
dict_table_t* table) /* in: system table */
1009
ut_ad(mutex_own(&(dict_sys->mutex)));
1011
heap = mem_heap_create(1000);
1013
dict_load_indexes(table, heap);
1015
mem_heap_free(heap);
1018
/************************************************************************
1019
Loads foreign key constraint col names (also for the referenced table). */
1022
dict_load_foreign_cols(
1023
/*===================*/
1024
const char* id, /* in: foreign constraint id as a
1025
null-terminated string */
1026
dict_foreign_t* foreign)/* in: foreign constraint object */
1028
dict_table_t* sys_foreign_cols;
1029
dict_index_t* sys_index;
1039
ut_ad(mutex_own(&(dict_sys->mutex)));
1041
foreign->foreign_col_names = mem_heap_alloc(
1042
foreign->heap, foreign->n_fields * sizeof(void*));
1044
foreign->referenced_col_names = mem_heap_alloc(
1045
foreign->heap, foreign->n_fields * sizeof(void*));
1048
sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
1049
sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
1050
ut_a(!dict_table_is_comp(sys_foreign_cols));
1052
tuple = dtuple_create(foreign->heap, 1);
1053
dfield = dtuple_get_nth_field(tuple, 0);
1055
dfield_set_data(dfield, id, ut_strlen(id));
1056
dict_index_copy_types(tuple, sys_index, 1);
1058
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1059
BTR_SEARCH_LEAF, &pcur, &mtr);
1060
for (i = 0; i < foreign->n_fields; i++) {
1062
rec = btr_pcur_get_rec(&pcur);
1064
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
1065
ut_a(!rec_get_deleted_flag(rec, 0));
1067
field = rec_get_nth_field_old(rec, 0, &len);
1068
ut_a(len == ut_strlen(id));
1069
ut_a(ut_memcmp(id, field, len) == 0);
1071
field = rec_get_nth_field_old(rec, 1, &len);
1073
ut_a(i == mach_read_from_4(field));
1075
field = rec_get_nth_field_old(rec, 4, &len);
1076
foreign->foreign_col_names[i] = mem_heap_strdupl(
1077
foreign->heap, (char*) field, len);
1079
field = rec_get_nth_field_old(rec, 5, &len);
1080
foreign->referenced_col_names[i] = mem_heap_strdupl(
1081
foreign->heap, (char*) field, len);
1083
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1086
btr_pcur_close(&pcur);
1090
/***************************************************************************
1091
Loads a foreign key constraint to the dictionary cache. */
1096
/* out: DB_SUCCESS or error code */
1097
const char* id, /* in: foreign constraint id as a
1098
null-terminated string */
1099
ibool check_charsets)
1100
/* in: TRUE=check charset compatibility */
1102
dict_foreign_t* foreign;
1103
dict_table_t* sys_foreign;
1105
dict_index_t* sys_index;
1112
ulint n_fields_and_type;
1115
ut_ad(mutex_own(&(dict_sys->mutex)));
1117
heap2 = mem_heap_create(1000);
1121
sys_foreign = dict_table_get_low("SYS_FOREIGN");
1122
sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
1123
ut_a(!dict_table_is_comp(sys_foreign));
1125
tuple = dtuple_create(heap2, 1);
1126
dfield = dtuple_get_nth_field(tuple, 0);
1128
dfield_set_data(dfield, id, ut_strlen(id));
1129
dict_index_copy_types(tuple, sys_index, 1);
1131
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1132
BTR_SEARCH_LEAF, &pcur, &mtr);
1133
rec = btr_pcur_get_rec(&pcur);
1135
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
1136
|| rec_get_deleted_flag(rec, 0)) {
1140
"InnoDB: Error A: cannot load foreign constraint %s\n",
1143
btr_pcur_close(&pcur);
1145
mem_heap_free(heap2);
1150
field = rec_get_nth_field_old(rec, 0, &len);
1152
/* Check if the id in record is the searched one */
1153
if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
1156
"InnoDB: Error B: cannot load foreign constraint %s\n",
1159
btr_pcur_close(&pcur);
1161
mem_heap_free(heap2);
1166
/* Read the table names and the number of columns associated
1167
with the constraint */
1169
mem_heap_free(heap2);
1171
foreign = dict_mem_foreign_create();
1173
n_fields_and_type = mach_read_from_4(
1174
rec_get_nth_field_old(rec, 5, &len));
1178
/* We store the type in the bits 24..29 of n_fields_and_type. */
1180
foreign->type = (unsigned int) (n_fields_and_type >> 24);
1181
foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
1183
foreign->id = mem_heap_strdup(foreign->heap, id);
1185
field = rec_get_nth_field_old(rec, 3, &len);
1186
foreign->foreign_table_name = mem_heap_strdupl(
1187
foreign->heap, (char*) field, len);
1189
field = rec_get_nth_field_old(rec, 4, &len);
1190
foreign->referenced_table_name = mem_heap_strdupl(
1191
foreign->heap, (char*) field, len);
1193
btr_pcur_close(&pcur);
1196
dict_load_foreign_cols(id, foreign);
1198
/* If the foreign table is not yet in the dictionary cache, we
1199
have to load it so that we are able to make type comparisons
1200
in the next function call. */
1202
dict_table_get_low(foreign->foreign_table_name);
1204
/* Note that there may already be a foreign constraint object in
1205
the dictionary cache for this constraint: then the following
1206
call only sets the pointers in it to point to the appropriate table
1207
and index objects and frees the newly created object foreign.
1208
Adding to the cache should always succeed since we are not creating
1209
a new foreign key constraint but loading one from the data
1212
return(dict_foreign_add_to_cache(foreign, check_charsets));
1215
/***************************************************************************
1216
Loads foreign key constraints where the table is either the foreign key
1217
holder or where the table is referenced by a foreign key. Adds these
1218
constraints to the data dictionary. Note that we know that the dictionary
1219
cache already contains all constraints where the other relevant table is
1220
already in the dictionary cache. */
1225
/* out: DB_SUCCESS or error code */
1226
const char* table_name, /* in: table name */
1227
ibool check_charsets) /* in: TRUE=check charset
1234
dict_index_t* sec_index;
1235
dict_table_t* sys_foreign;
1243
ut_ad(mutex_own(&(dict_sys->mutex)));
1245
sys_foreign = dict_table_get_low("SYS_FOREIGN");
1247
if (sys_foreign == NULL) {
1248
/* No foreign keys defined yet in this database */
1251
"InnoDB: Error: no foreign key system tables"
1252
" in the database\n");
1257
ut_a(!dict_table_is_comp(sys_foreign));
1260
/* Get the secondary index based on FOR_NAME from table
1263
sec_index = dict_table_get_next_index(
1264
dict_table_get_first_index(sys_foreign));
1266
heap = mem_heap_create(256);
1268
tuple = dtuple_create(heap, 1);
1269
dfield = dtuple_get_nth_field(tuple, 0);
1271
dfield_set_data(dfield, table_name, ut_strlen(table_name));
1272
dict_index_copy_types(tuple, sec_index, 1);
1274
btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE,
1275
BTR_SEARCH_LEAF, &pcur, &mtr);
1277
rec = btr_pcur_get_rec(&pcur);
1279
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
1282
goto load_next_index;
1285
/* Now we have the record in the secondary index containing a table
1286
name and a foreign constraint ID */
1288
rec = btr_pcur_get_rec(&pcur);
1289
field = rec_get_nth_field_old(rec, 0, &len);
1291
/* Check if the table name in the record is the one searched for; the
1292
following call does the comparison in the latin1_swedish_ci
1293
charset-collation, in a case-insensitive way. */
1295
if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
1296
dfield_get_type(dfield)->prtype,
1297
dfield_get_data(dfield), dfield_get_len(dfield),
1300
goto load_next_index;
1303
/* Since table names in SYS_FOREIGN are stored in a case-insensitive
1304
order, we have to check that the table name matches also in a binary
1305
string comparison. On Unix, MySQL allows table names that only differ
1306
in character case. */
1308
if (0 != ut_memcmp(field, table_name, len)) {
1313
if (rec_get_deleted_flag(rec, 0)) {
1318
/* Now we get a foreign key constraint id */
1319
field = rec_get_nth_field_old(rec, 1, &len);
1320
id = mem_heap_strdupl(heap, (char*) field, len);
1322
btr_pcur_store_position(&pcur, &mtr);
1326
/* Load the foreign constraint definition to the dictionary cache */
1328
err = dict_load_foreign(id, check_charsets);
1330
if (err != DB_SUCCESS) {
1331
btr_pcur_close(&pcur);
1332
mem_heap_free(heap);
1339
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
1341
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1346
btr_pcur_close(&pcur);
1348
mem_heap_free(heap);
1350
sec_index = dict_table_get_next_index(sec_index);
1352
if (sec_index != NULL) {