1
/******************************************************
2
Loads to the memory cache database object definitions
7
Created 4/24/1996 Heikki Tuuri
8
*******************************************************/
10
#include "dict0load.h"
13
#include "dict0load.ic"
18
#include "page0page.h"
19
#include "mach0data.h"
20
#include "dict0dict.h"
21
#include "dict0boot.h"
23
#include "srv0start.h"
26
/********************************************************************
27
Returns TRUE if index's i'th column's name is 'name' .*/
33
dict_table_t* table, /* in: table */
34
dict_index_t* index, /* in: index */
36
const char* name) /* in: name to compare to */
38
ulint tmp = dict_col_get_no(dict_field_get_col(
39
dict_index_get_nth_field(
42
return(strcmp(name, dict_table_get_col_name(table, tmp)) == 0);
45
/************************************************************************
46
Finds the first table name in the given database. */
49
dict_get_first_table_name_in_db(
50
/*============================*/
51
/* out, own: table name, NULL if
52
does not exist; the caller must
53
free the memory in the string! */
54
const char* name) /* in: database name which ends in '/' */
56
dict_table_t* sys_tables;
58
dict_index_t* sys_index;
67
ut_ad(mutex_own(&(dict_sys->mutex)));
69
heap = mem_heap_create(1000);
73
sys_tables = dict_table_get_low("SYS_TABLES");
74
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
75
ut_a(!dict_table_is_comp(sys_tables));
77
tuple = dtuple_create(heap, 1);
78
dfield = dtuple_get_nth_field(tuple, 0);
80
dfield_set_data(dfield, name, ut_strlen(name));
81
dict_index_copy_types(tuple, sys_index, 1);
83
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
84
BTR_SEARCH_LEAF, &pcur, &mtr);
86
rec = btr_pcur_get_rec(&pcur);
88
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
91
btr_pcur_close(&pcur);
98
field = rec_get_nth_field_old(rec, 0, &len);
100
if (len < strlen(name)
101
|| ut_memcmp(name, field, strlen(name)) != 0) {
104
btr_pcur_close(&pcur);
111
if (!rec_get_deleted_flag(rec, 0)) {
115
char* table_name = mem_strdupl((char*) field, len);
117
btr_pcur_close(&pcur);
124
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
129
/************************************************************************
130
Prints to the standard output information on all tables found in the data
131
dictionary system table. */
137
dict_table_t* sys_tables;
138
dict_index_t* sys_index;
146
/* Enlarge the fatal semaphore wait timeout during the InnoDB table
149
mutex_enter(&kernel_mutex);
150
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
151
mutex_exit(&kernel_mutex);
153
mutex_enter(&(dict_sys->mutex));
157
sys_tables = dict_table_get_low("SYS_TABLES");
158
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
160
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
163
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
165
rec = btr_pcur_get_rec(&pcur);
167
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
170
btr_pcur_close(&pcur);
173
mutex_exit(&(dict_sys->mutex));
175
/* Restore the fatal semaphore wait timeout */
177
mutex_enter(&kernel_mutex);
178
srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
179
mutex_exit(&kernel_mutex);
184
field = rec_get_nth_field_old(rec, 0, &len);
186
if (!rec_get_deleted_flag(rec, 0)) {
190
char* table_name = mem_strdupl((char*) field, len);
192
btr_pcur_store_position(&pcur, &mtr);
196
table = dict_table_get_low(table_name);
197
mem_free(table_name);
200
fputs("InnoDB: Failed to load table ", stderr);
201
ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
204
/* The table definition was corrupt if there
207
if (dict_table_get_first_index(table)) {
208
dict_update_statistics_low(table, TRUE);
211
dict_table_print_low(table);
216
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
222
/************************************************************************
223
In a crash recovery we already have all the tablespace objects created.
224
This function compares the space id information in the InnoDB data dictionary
225
to what we already read with fil_load_single_table_tablespaces().
227
In a normal startup, we create the tablespace objects for every table in
228
InnoDB's data dictionary, if the corresponding .ibd file exists.
229
We also scan the biggest space id, and store it to fil_system. */
232
dict_check_tablespaces_and_store_max_id(
233
/*====================================*/
234
ibool in_crash_recovery) /* in: are we doing a crash recovery */
236
dict_table_t* sys_tables;
237
dict_index_t* sys_index;
243
ulint max_space_id = 0;
246
mutex_enter(&(dict_sys->mutex));
250
sys_tables = dict_table_get_low("SYS_TABLES");
251
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
252
ut_a(!dict_table_is_comp(sys_tables));
254
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
257
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
259
rec = btr_pcur_get_rec(&pcur);
261
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
264
btr_pcur_close(&pcur);
267
/* We must make the tablespace cache aware of the biggest
270
/* printf("Biggest space id in data dictionary %lu\n",
272
fil_set_max_space_id_if_bigger(max_space_id);
274
mutex_exit(&(dict_sys->mutex));
279
field = rec_get_nth_field_old(rec, 0, &len);
281
if (!rec_get_deleted_flag(rec, 0)) {
285
char* name = mem_strdupl((char*) field, len);
287
field = rec_get_nth_field_old(rec, 9, &len);
290
space_id = mach_read_from_4(field);
292
btr_pcur_store_position(&pcur, &mtr);
296
if (space_id != 0 && in_crash_recovery) {
297
/* Check that the tablespace (the .ibd file) really
298
exists; print a warning to the .err log if not */
300
fil_space_for_table_exists_in_mem(space_id, name,
304
if (space_id != 0 && !in_crash_recovery) {
305
/* It is a normal database startup: create the space
306
object and check that the .ibd file exists. */
308
fil_open_single_table_tablespace(FALSE, space_id,
314
if (space_id > max_space_id) {
315
max_space_id = space_id;
320
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
326
/************************************************************************
327
Loads definitions for table columns. */
332
dict_table_t* table, /* in: table */
333
mem_heap_t* heap) /* in: memory heap for temporary storage */
335
dict_table_t* sys_columns;
336
dict_index_t* sys_index;
351
ut_ad(mutex_own(&(dict_sys->mutex)));
355
sys_columns = dict_table_get_low("SYS_COLUMNS");
356
sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
357
ut_a(!dict_table_is_comp(sys_columns));
359
tuple = dtuple_create(heap, 1);
360
dfield = dtuple_get_nth_field(tuple, 0);
362
buf = mem_heap_alloc(heap, 8);
363
mach_write_to_8(buf, table->id);
365
dfield_set_data(dfield, buf, 8);
366
dict_index_copy_types(tuple, sys_index, 1);
368
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
369
BTR_SEARCH_LEAF, &pcur, &mtr);
370
for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
372
rec = btr_pcur_get_rec(&pcur);
374
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
376
ut_a(!rec_get_deleted_flag(rec, 0));
378
field = rec_get_nth_field_old(rec, 0, &len);
380
ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
382
field = rec_get_nth_field_old(rec, 1, &len);
384
ut_a(i == mach_read_from_4(field));
386
ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
388
field = rec_get_nth_field_old(rec, 4, &len);
389
name = mem_heap_strdupl(heap, (char*) field, len);
391
field = rec_get_nth_field_old(rec, 5, &len);
392
mtype = mach_read_from_4(field);
394
field = rec_get_nth_field_old(rec, 6, &len);
395
prtype = mach_read_from_4(field);
397
if (dtype_get_charset_coll(prtype) == 0
398
&& dtype_is_string_type(mtype)) {
399
/* The table was created with < 4.1.2. */
401
if (dtype_is_binary_string_type(mtype, prtype)) {
402
/* Use the binary collation for
403
string columns of binary type. */
405
prtype = dtype_form_prtype(
407
DATA_MYSQL_BINARY_CHARSET_COLL);
409
/* Use the default charset for
410
other than binary columns. */
412
prtype = dtype_form_prtype(
414
data_mysql_default_charset_coll);
418
field = rec_get_nth_field_old(rec, 7, &len);
419
col_len = mach_read_from_4(field);
421
ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
423
dict_mem_table_add_col(table, heap, name,
424
mtype, prtype, col_len);
425
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
428
btr_pcur_close(&pcur);
432
/************************************************************************
433
Report that an index field or index for a table has been delete marked. */
436
dict_load_report_deleted_index(
437
/*===========================*/
438
const char* name, /* in: table name */
439
ulint field) /* in: index field, or ULINT_UNDEFINED */
441
fprintf(stderr, "InnoDB: Error: data dictionary entry"
442
" for table %s is corrupt!\n", name);
443
if (field != ULINT_UNDEFINED) {
445
"InnoDB: Index field %lu is delete marked.\n", field);
447
fputs("InnoDB: An index is delete marked.\n", stderr);
451
/************************************************************************
452
Loads definitions for index fields. */
457
dict_table_t* table, /* in: table */
458
dict_index_t* index, /* in: index whose fields to load */
459
mem_heap_t* heap) /* in: memory heap for temporary storage */
461
dict_table_t* sys_fields;
462
dict_index_t* sys_index;
466
ulint pos_and_prefix_len;
475
ut_ad(mutex_own(&(dict_sys->mutex)));
479
sys_fields = dict_table_get_low("SYS_FIELDS");
480
sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
481
ut_a(!dict_table_is_comp(sys_fields));
483
tuple = dtuple_create(heap, 1);
484
dfield = dtuple_get_nth_field(tuple, 0);
486
buf = mem_heap_alloc(heap, 8);
487
mach_write_to_8(buf, index->id);
489
dfield_set_data(dfield, buf, 8);
490
dict_index_copy_types(tuple, sys_index, 1);
492
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
493
BTR_SEARCH_LEAF, &pcur, &mtr);
494
for (i = 0; i < index->n_fields; i++) {
496
rec = btr_pcur_get_rec(&pcur);
498
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
499
if (rec_get_deleted_flag(rec, 0)) {
500
dict_load_report_deleted_index(table->name, i);
503
field = rec_get_nth_field_old(rec, 0, &len);
505
ut_a(ut_memcmp(buf, field, len) == 0);
507
field = rec_get_nth_field_old(rec, 1, &len);
510
/* The next field stores the field position in the index
511
and a possible column prefix length if the index field
512
does not contain the whole column. The storage format is
513
like this: if there is at least one prefix field in the index,
514
then the HIGH 2 bytes contain the field number (== i) and the
515
low 2 bytes the prefix length for the field. Otherwise the
516
field number (== i) is contained in the 2 LOW bytes. */
518
pos_and_prefix_len = mach_read_from_4(field);
520
ut_a((pos_and_prefix_len & 0xFFFFUL) == i
521
|| (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
523
if ((i == 0 && pos_and_prefix_len > 0)
524
|| (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
526
prefix_len = pos_and_prefix_len & 0xFFFFUL;
531
ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
533
field = rec_get_nth_field_old(rec, 4, &len);
535
dict_mem_index_add_field(index,
536
mem_heap_strdupl(heap,
540
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
543
btr_pcur_close(&pcur);
547
/************************************************************************
548
Loads definitions for table indexes. Adds them to the data dictionary
554
/* out: DB_SUCCESS if ok, DB_CORRUPTION
555
if corruption of dictionary table or
556
DB_UNSUPPORTED if table has unknown index
558
dict_table_t* table, /* in: table */
559
mem_heap_t* heap) /* in: memory heap for temporary storage */
561
dict_table_t* sys_indexes;
562
dict_index_t* sys_index;
580
ulint error = DB_SUCCESS;
582
ut_ad(mutex_own(&(dict_sys->mutex)));
584
if ((ut_dulint_get_high(table->id) == 0)
585
&& (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
588
is_sys_table = FALSE;
593
sys_indexes = dict_table_get_low("SYS_INDEXES");
594
sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
595
ut_a(!dict_table_is_comp(sys_indexes));
597
tuple = dtuple_create(heap, 1);
598
dfield = dtuple_get_nth_field(tuple, 0);
600
buf = mem_heap_alloc(heap, 8);
601
mach_write_to_8(buf, table->id);
603
dfield_set_data(dfield, buf, 8);
604
dict_index_copy_types(tuple, sys_index, 1);
606
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
607
BTR_SEARCH_LEAF, &pcur, &mtr);
609
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
614
rec = btr_pcur_get_rec(&pcur);
616
field = rec_get_nth_field_old(rec, 0, &len);
619
if (ut_memcmp(buf, field, len) != 0) {
623
if (rec_get_deleted_flag(rec, 0)) {
624
dict_load_report_deleted_index(table->name,
627
error = DB_CORRUPTION;
631
field = rec_get_nth_field_old(rec, 1, &len);
633
id = mach_read_from_8(field);
635
ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
637
field = rec_get_nth_field_old(rec, 4, &name_len);
638
name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
640
field = rec_get_nth_field_old(rec, 5, &len);
641
n_fields = mach_read_from_4(field);
643
field = rec_get_nth_field_old(rec, 6, &len);
644
type = mach_read_from_4(field);
646
field = rec_get_nth_field_old(rec, 7, &len);
647
space = mach_read_from_4(field);
649
ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
651
field = rec_get_nth_field_old(rec, 8, &len);
652
page_no = mach_read_from_4(field);
654
/* We check for unsupported types first, so that the
655
subsequent checks are relevant for the supported types. */
656
if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
659
"InnoDB: Error: unknown type %lu"
660
" of index %s of table %s\n",
661
(ulong) type, name_buf, table->name);
663
error = DB_UNSUPPORTED;
665
} else if (page_no == FIL_NULL) {
668
"InnoDB: Error: trying to load index %s"
670
"InnoDB: but the index tree has been freed!\n",
671
name_buf, table->name);
673
error = DB_CORRUPTION;
675
} else if ((type & DICT_CLUSTERED) == 0
676
&& NULL == dict_table_get_first_index(table)) {
679
"InnoDB: Error: trying to load index %s"
681
"InnoDB: but the first index"
682
" is not clustered!\n",
683
name_buf, table->name);
685
error = DB_CORRUPTION;
687
} else if (is_sys_table
688
&& ((type & DICT_CLUSTERED)
689
|| ((table == dict_sys->sys_tables)
690
&& (name_len == (sizeof "ID_IND") - 1)
691
&& (0 == ut_memcmp(name_buf,
692
"ID_IND", name_len))))) {
694
/* The index was created in memory already at booting
695
of the database server */
697
index = dict_mem_index_create(table->name, name_buf,
698
space, type, n_fields);
701
dict_load_fields(table, index, heap);
702
dict_index_add_to_cache(table, index, page_no);
705
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
709
btr_pcur_close(&pcur);
715
/************************************************************************
716
Loads a table definition and also all its index definitions, and also
717
the cluster definition if the table is a member in a cluster. Also loads
718
all foreign key constraints where the foreign key is in the table or where
719
a foreign key references columns in this table. Adds all these to the data
725
/* out: table, NULL if does not exist;
726
if the table is stored in an .ibd file,
727
but the file does not exist,
728
then we set the ibd_file_missing flag TRUE
729
in the table object we return */
730
const char* name) /* in: table name in the
731
databasename/tablename format */
733
ibool ibd_file_missing = FALSE;
735
dict_table_t* sys_tables;
737
dict_index_t* sys_index;
750
ut_ad(mutex_own(&(dict_sys->mutex)));
752
heap = mem_heap_create(32000);
756
sys_tables = dict_table_get_low("SYS_TABLES");
757
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
758
ut_a(!dict_table_is_comp(sys_tables));
760
tuple = dtuple_create(heap, 1);
761
dfield = dtuple_get_nth_field(tuple, 0);
763
dfield_set_data(dfield, name, ut_strlen(name));
764
dict_index_copy_types(tuple, sys_index, 1);
766
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
767
BTR_SEARCH_LEAF, &pcur, &mtr);
768
rec = btr_pcur_get_rec(&pcur);
770
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
771
|| rec_get_deleted_flag(rec, 0)) {
774
btr_pcur_close(&pcur);
781
field = rec_get_nth_field_old(rec, 0, &len);
783
/* Check if the table name in record is the searched one */
784
if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
789
ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
791
field = rec_get_nth_field_old(rec, 9, &len);
792
space = mach_read_from_4(field);
794
/* Check if the tablespace exists and has the right name */
796
if (fil_space_for_table_exists_in_mem(space, name, FALSE,
798
/* Ok; (if we did a crash recovery then the tablespace
799
can already be in the memory cache) */
801
/* In >= 4.1.9, InnoDB scans the data dictionary also
802
at a normal mysqld startup. It is an error if the
803
space object does not exist in memory. */
805
ut_print_timestamp(stderr);
807
" InnoDB: error: space object of table %s,\n"
808
"InnoDB: space id %lu did not exist in memory."
809
" Retrying an open.\n",
811
/* Try to open the tablespace */
812
if (!fil_open_single_table_tablespace(TRUE,
814
/* We failed to find a sensible tablespace
817
ibd_file_missing = TRUE;
822
ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
824
field = rec_get_nth_field_old(rec, 4, &len);
825
n_cols = mach_read_from_4(field);
829
/* The high-order bit of N_COLS is the "compact format" flag. */
830
if (n_cols & 0x80000000UL) {
831
flags |= DICT_TF_COMPACT;
834
table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
837
table->ibd_file_missing = (unsigned int) ibd_file_missing;
839
ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
841
field = rec_get_nth_field_old(rec, 3, &len);
842
table->id = mach_read_from_8(field);
844
field = rec_get_nth_field_old(rec, 5, &len);
845
if (UNIV_UNLIKELY(mach_read_from_4(field) != DICT_TABLE_ORDINARY)) {
846
ut_print_timestamp(stderr);
848
" InnoDB: table %s: unknown table type %lu\n",
849
name, (ulong) mach_read_from_4(field));
853
btr_pcur_close(&pcur);
856
dict_load_columns(table, heap);
858
dict_table_add_to_cache(table, heap);
860
mem_heap_empty(heap);
862
err = dict_load_indexes(table, heap);
864
/* If the force recovery flag is set, we open the table irrespective
865
of the error condition, since the user may want to dump data from the
866
clustered index. However we load the foreign key information only if
867
all indexes were loaded. */
868
if (err != DB_SUCCESS && !srv_force_recovery) {
869
dict_mem_table_free(table);
871
} else if (err == DB_SUCCESS) {
872
err = dict_load_foreigns(table->name, TRUE);
875
if (err != DB_SUCCESS && table != NULL) {
877
mutex_enter(&dict_foreign_err_mutex);
879
ut_print_timestamp(stderr);
882
" InnoDB: Error: could not make a foreign key"
883
" definition to match\n"
884
"InnoDB: the foreign key table"
885
" or the referenced table!\n"
886
"InnoDB: The data dictionary of InnoDB is corrupt."
887
" You may need to drop\n"
888
"InnoDB: and recreate the foreign key table"
889
" or the referenced table.\n"
890
"InnoDB: Submit a detailed bug report"
891
" to http://bugs.mysql.com\n"
892
"InnoDB: Latest foreign key error printout:\n%s\n",
893
dict_foreign_err_buf);
895
mutex_exit(&dict_foreign_err_mutex);
903
/***************************************************************************
904
Loads a table object based on the table id. */
907
dict_load_table_on_id(
908
/*==================*/
909
/* out: table; NULL if table does not exist */
910
dulint table_id) /* in: table id */
917
dict_index_t* sys_table_ids;
918
dict_table_t* sys_tables;
925
ut_ad(mutex_own(&(dict_sys->mutex)));
927
/* NOTE that the operation of this function is protected by
928
the dictionary mutex, and therefore no deadlocks can occur
929
with other dictionary operations. */
932
/*---------------------------------------------------*/
933
/* Get the secondary index based on ID for table SYS_TABLES */
934
sys_tables = dict_sys->sys_tables;
935
sys_table_ids = dict_table_get_next_index(
936
dict_table_get_first_index(sys_tables));
937
ut_a(!dict_table_is_comp(sys_tables));
938
heap = mem_heap_create(256);
940
tuple = dtuple_create(heap, 1);
941
dfield = dtuple_get_nth_field(tuple, 0);
943
/* Write the table id in byte format to id_buf */
944
mach_write_to_8(id_buf, table_id);
946
dfield_set_data(dfield, id_buf, 8);
947
dict_index_copy_types(tuple, sys_table_ids, 1);
949
btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
950
BTR_SEARCH_LEAF, &pcur, &mtr);
951
rec = btr_pcur_get_rec(&pcur);
953
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
954
|| rec_get_deleted_flag(rec, 0)) {
957
btr_pcur_close(&pcur);
964
/*---------------------------------------------------*/
965
/* Now we have the record in the secondary index containing the
968
rec = btr_pcur_get_rec(&pcur);
969
field = rec_get_nth_field_old(rec, 0, &len);
972
/* Check if the table id in record is the one searched for */
973
if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
975
btr_pcur_close(&pcur);
982
/* Now we get the table name from the record */
983
field = rec_get_nth_field_old(rec, 1, &len);
984
/* Load the table definition to memory */
985
table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
987
btr_pcur_close(&pcur);
994
/************************************************************************
995
This function is called when the database is booted. Loads system table
996
index definitions except for the clustered index which is added to the
997
dictionary cache at booting before calling this function. */
1000
dict_load_sys_table(
1001
/*================*/
1002
dict_table_t* table) /* in: system table */
1006
ut_ad(mutex_own(&(dict_sys->mutex)));
1008
heap = mem_heap_create(1000);
1010
dict_load_indexes(table, heap);
1012
mem_heap_free(heap);
1015
/************************************************************************
1016
Loads foreign key constraint col names (also for the referenced table). */
1019
dict_load_foreign_cols(
1020
/*===================*/
1021
const char* id, /* in: foreign constraint id as a
1022
null-terminated string */
1023
dict_foreign_t* foreign)/* in: foreign constraint object */
1025
dict_table_t* sys_foreign_cols;
1026
dict_index_t* sys_index;
1036
ut_ad(mutex_own(&(dict_sys->mutex)));
1038
foreign->foreign_col_names = mem_heap_alloc(
1039
foreign->heap, foreign->n_fields * sizeof(void*));
1041
foreign->referenced_col_names = mem_heap_alloc(
1042
foreign->heap, foreign->n_fields * sizeof(void*));
1045
sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
1046
sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
1047
ut_a(!dict_table_is_comp(sys_foreign_cols));
1049
tuple = dtuple_create(foreign->heap, 1);
1050
dfield = dtuple_get_nth_field(tuple, 0);
1052
dfield_set_data(dfield, id, ut_strlen(id));
1053
dict_index_copy_types(tuple, sys_index, 1);
1055
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1056
BTR_SEARCH_LEAF, &pcur, &mtr);
1057
for (i = 0; i < foreign->n_fields; i++) {
1059
rec = btr_pcur_get_rec(&pcur);
1061
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
1062
ut_a(!rec_get_deleted_flag(rec, 0));
1064
field = rec_get_nth_field_old(rec, 0, &len);
1065
ut_a(len == ut_strlen(id));
1066
ut_a(ut_memcmp(id, field, len) == 0);
1068
field = rec_get_nth_field_old(rec, 1, &len);
1070
ut_a(i == mach_read_from_4(field));
1072
field = rec_get_nth_field_old(rec, 4, &len);
1073
foreign->foreign_col_names[i] = mem_heap_strdupl(
1074
foreign->heap, (char*) field, len);
1076
field = rec_get_nth_field_old(rec, 5, &len);
1077
foreign->referenced_col_names[i] = mem_heap_strdupl(
1078
foreign->heap, (char*) field, len);
1080
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1083
btr_pcur_close(&pcur);
1087
/***************************************************************************
1088
Loads a foreign key constraint to the dictionary cache. */
1093
/* out: DB_SUCCESS or error code */
1094
const char* id, /* in: foreign constraint id as a
1095
null-terminated string */
1096
ibool check_charsets)
1097
/* in: TRUE=check charset compatibility */
1099
dict_foreign_t* foreign;
1100
dict_table_t* sys_foreign;
1102
dict_index_t* sys_index;
1109
ulint n_fields_and_type;
1112
ut_ad(mutex_own(&(dict_sys->mutex)));
1114
heap2 = mem_heap_create(1000);
1118
sys_foreign = dict_table_get_low("SYS_FOREIGN");
1119
sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
1120
ut_a(!dict_table_is_comp(sys_foreign));
1122
tuple = dtuple_create(heap2, 1);
1123
dfield = dtuple_get_nth_field(tuple, 0);
1125
dfield_set_data(dfield, id, ut_strlen(id));
1126
dict_index_copy_types(tuple, sys_index, 1);
1128
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1129
BTR_SEARCH_LEAF, &pcur, &mtr);
1130
rec = btr_pcur_get_rec(&pcur);
1132
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
1133
|| rec_get_deleted_flag(rec, 0)) {
1137
"InnoDB: Error A: cannot load foreign constraint %s\n",
1140
btr_pcur_close(&pcur);
1142
mem_heap_free(heap2);
1147
field = rec_get_nth_field_old(rec, 0, &len);
1149
/* Check if the id in record is the searched one */
1150
if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
1153
"InnoDB: Error B: cannot load foreign constraint %s\n",
1156
btr_pcur_close(&pcur);
1158
mem_heap_free(heap2);
1163
/* Read the table names and the number of columns associated
1164
with the constraint */
1166
mem_heap_free(heap2);
1168
foreign = dict_mem_foreign_create();
1170
n_fields_and_type = mach_read_from_4(
1171
rec_get_nth_field_old(rec, 5, &len));
1175
/* We store the type in the bits 24..29 of n_fields_and_type. */
1177
foreign->type = (unsigned int) (n_fields_and_type >> 24);
1178
foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
1180
foreign->id = mem_heap_strdup(foreign->heap, id);
1182
field = rec_get_nth_field_old(rec, 3, &len);
1183
foreign->foreign_table_name = mem_heap_strdupl(
1184
foreign->heap, (char*) field, len);
1186
field = rec_get_nth_field_old(rec, 4, &len);
1187
foreign->referenced_table_name = mem_heap_strdupl(
1188
foreign->heap, (char*) field, len);
1190
btr_pcur_close(&pcur);
1193
dict_load_foreign_cols(id, foreign);
1195
/* If the foreign table is not yet in the dictionary cache, we
1196
have to load it so that we are able to make type comparisons
1197
in the next function call. */
1199
dict_table_get_low(foreign->foreign_table_name);
1201
/* Note that there may already be a foreign constraint object in
1202
the dictionary cache for this constraint: then the following
1203
call only sets the pointers in it to point to the appropriate table
1204
and index objects and frees the newly created object foreign.
1205
Adding to the cache should always succeed since we are not creating
1206
a new foreign key constraint but loading one from the data
1209
return(dict_foreign_add_to_cache(foreign, check_charsets));
1212
/***************************************************************************
1213
Loads foreign key constraints where the table is either the foreign key
1214
holder or where the table is referenced by a foreign key. Adds these
1215
constraints to the data dictionary. Note that we know that the dictionary
1216
cache already contains all constraints where the other relevant table is
1217
already in the dictionary cache. */
1222
/* out: DB_SUCCESS or error code */
1223
const char* table_name, /* in: table name */
1224
ibool check_charsets) /* in: TRUE=check charset
1231
dict_index_t* sec_index;
1232
dict_table_t* sys_foreign;
1240
ut_ad(mutex_own(&(dict_sys->mutex)));
1242
sys_foreign = dict_table_get_low("SYS_FOREIGN");
1244
if (sys_foreign == NULL) {
1245
/* No foreign keys defined yet in this database */
1248
"InnoDB: Error: no foreign key system tables"
1249
" in the database\n");
1254
ut_a(!dict_table_is_comp(sys_foreign));
1257
/* Get the secondary index based on FOR_NAME from table
1260
sec_index = dict_table_get_next_index(
1261
dict_table_get_first_index(sys_foreign));
1263
heap = mem_heap_create(256);
1265
tuple = dtuple_create(heap, 1);
1266
dfield = dtuple_get_nth_field(tuple, 0);
1268
dfield_set_data(dfield, table_name, ut_strlen(table_name));
1269
dict_index_copy_types(tuple, sec_index, 1);
1271
btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE,
1272
BTR_SEARCH_LEAF, &pcur, &mtr);
1274
rec = btr_pcur_get_rec(&pcur);
1276
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
1279
goto load_next_index;
1282
/* Now we have the record in the secondary index containing a table
1283
name and a foreign constraint ID */
1285
rec = btr_pcur_get_rec(&pcur);
1286
field = rec_get_nth_field_old(rec, 0, &len);
1288
/* Check if the table name in the record is the one searched for; the
1289
following call does the comparison in the latin1_swedish_ci
1290
charset-collation, in a case-insensitive way. */
1292
if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
1293
dfield_get_type(dfield)->prtype,
1294
dfield_get_data(dfield), dfield_get_len(dfield),
1297
goto load_next_index;
1300
/* Since table names in SYS_FOREIGN are stored in a case-insensitive
1301
order, we have to check that the table name matches also in a binary
1302
string comparison. On Unix, MySQL allows table names that only differ
1303
in character case. */
1305
if (0 != ut_memcmp(field, table_name, len)) {
1310
if (rec_get_deleted_flag(rec, 0)) {
1315
/* Now we get a foreign key constraint id */
1316
field = rec_get_nth_field_old(rec, 1, &len);
1317
id = mem_heap_strdupl(heap, (char*) field, len);
1319
btr_pcur_store_position(&pcur, &mtr);
1323
/* Load the foreign constraint definition to the dictionary cache */
1325
err = dict_load_foreign(id, check_charsets);
1327
if (err != DB_SUCCESS) {
1328
btr_pcur_close(&pcur);
1329
mem_heap_free(heap);
1336
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
1338
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1343
btr_pcur_close(&pcur);
1345
mem_heap_free(heap);
1347
sec_index = dict_table_get_next_index(sec_index);
1349
if (sec_index != NULL) {