1
/*****************************************************************************
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file dict/dict0load.c
21
Loads to the memory cache database object definitions
22
from dictionary tables
24
Created 4/24/1996 Heikki Tuuri
25
*******************************************************/
27
#if defined(BUILD_DRIZZLE)
30
# include "mysql_version.h"
31
#endif /* BUILD_DRIZZLE */
32
#include "dict0load.h"
35
#include "dict0load.ic"
40
#include "page0page.h"
41
#include "mach0data.h"
42
#include "dict0dict.h"
43
#include "dict0boot.h"
45
#include "srv0start.h"
48
/****************************************************************//**
49
Compare the name of an index column.
50
@return TRUE if the i'th column of index is 'name'. */
55
const dict_table_t* table, /*!< in: table */
56
const dict_index_t* index, /*!< in: index */
57
ulint i, /*!< in: index field offset */
58
const char* name) /*!< in: name to compare to */
60
ulint tmp = dict_col_get_no(dict_field_get_col(
61
dict_index_get_nth_field(
64
return(strcmp(name, dict_table_get_col_name(table, tmp)) == 0);
67
/********************************************************************//**
68
Finds the first table name in the given database.
69
@return own: table name, NULL if does not exist; the caller must free
70
the memory in the string! */
73
dict_get_first_table_name_in_db(
74
/*============================*/
75
const char* name) /*!< in: database name which ends in '/' */
77
dict_table_t* sys_tables;
79
dict_index_t* sys_index;
88
ut_ad(mutex_own(&(dict_sys->mutex)));
90
heap = mem_heap_create(1000);
94
sys_tables = dict_table_get_low("SYS_TABLES");
95
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
96
ut_a(!dict_table_is_comp(sys_tables));
98
tuple = dtuple_create(heap, 1);
99
dfield = dtuple_get_nth_field(tuple, 0);
101
dfield_set_data(dfield, name, ut_strlen(name));
102
dict_index_copy_types(tuple, sys_index, 1);
104
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
105
BTR_SEARCH_LEAF, &pcur, &mtr);
107
rec = btr_pcur_get_rec(&pcur);
109
if (!btr_pcur_is_on_user_rec(&pcur)) {
112
btr_pcur_close(&pcur);
119
field = rec_get_nth_field_old(rec, 0, &len);
121
if (len < strlen(name)
122
|| ut_memcmp(name, field, strlen(name)) != 0) {
125
btr_pcur_close(&pcur);
132
if (!rec_get_deleted_flag(rec, 0)) {
136
char* table_name = mem_strdupl((char*) field, len);
138
btr_pcur_close(&pcur);
145
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
150
/********************************************************************//**
151
Prints to the standard output information on all tables found in the data
152
dictionary system table. */
158
dict_table_t* sys_tables;
159
dict_index_t* sys_index;
167
/* Enlarge the fatal semaphore wait timeout during the InnoDB table
170
mutex_enter(&kernel_mutex);
171
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
172
mutex_exit(&kernel_mutex);
174
mutex_enter(&(dict_sys->mutex));
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);
232
dict_table_print_low(table);
237
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
243
/********************************************************************//**
244
Determine the flags of a table described in SYS_TABLES.
245
@return compressed page size in kilobytes; or 0 if the tablespace is
246
uncompressed, ULINT_UNDEFINED on error */
249
dict_sys_tables_get_flags(
250
/*======================*/
251
const rec_t* rec) /*!< in: a record of SYS_TABLES */
258
field = rec_get_nth_field_old(rec, 5, &len);
261
flags = mach_read_from_4(field);
263
if (UNIV_LIKELY(flags == DICT_TABLE_ORDINARY)) {
267
field = rec_get_nth_field_old(rec, 4, &len);
268
n_cols = mach_read_from_4(field);
270
if (UNIV_UNLIKELY(!(n_cols & 0x80000000UL))) {
271
/* New file formats require ROW_FORMAT=COMPACT. */
272
return(ULINT_UNDEFINED);
275
switch (flags & (DICT_TF_FORMAT_MASK | DICT_TF_COMPACT)) {
277
case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT:
278
case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT | DICT_TF_COMPACT:
279
/* flags should be DICT_TABLE_ORDINARY,
280
or DICT_TF_FORMAT_MASK should be nonzero. */
281
return(ULINT_UNDEFINED);
283
case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT | DICT_TF_COMPACT:
284
#if DICT_TF_FORMAT_MAX > DICT_TF_FORMAT_ZIP
285
# error "missing case labels for DICT_TF_FORMAT_ZIP .. DICT_TF_FORMAT_MAX"
287
/* We support this format. */
291
if (UNIV_UNLIKELY((flags & DICT_TF_ZSSIZE_MASK)
292
> (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT))) {
293
/* Unsupported compressed page size. */
294
return(ULINT_UNDEFINED);
297
if (UNIV_UNLIKELY(flags & (~0 << DICT_TF_BITS))) {
298
/* Some unused bits are set. */
299
return(ULINT_UNDEFINED);
305
/********************************************************************//**
306
In a crash recovery we already have all the tablespace objects created.
307
This function compares the space id information in the InnoDB data dictionary
308
to what we already read with fil_load_single_table_tablespaces().
310
In a normal startup, we create the tablespace objects for every table in
311
InnoDB's data dictionary, if the corresponding .ibd file exists.
312
We also scan the biggest space id, and store it to fil_system. */
315
dict_check_tablespaces_and_store_max_id(
316
/*====================================*/
317
ibool in_crash_recovery) /*!< in: are we doing a crash recovery */
319
dict_table_t* sys_tables;
320
dict_index_t* sys_index;
323
ulint max_space_id = 0;
326
mutex_enter(&(dict_sys->mutex));
330
sys_tables = dict_table_get_low("SYS_TABLES");
331
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
332
ut_a(!dict_table_is_comp(sys_tables));
334
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
337
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
339
rec = btr_pcur_get_rec(&pcur);
341
if (!btr_pcur_is_on_user_rec(&pcur)) {
344
btr_pcur_close(&pcur);
347
/* We must make the tablespace cache aware of the biggest
350
/* printf("Biggest space id in data dictionary %lu\n",
352
fil_set_max_space_id_if_bigger(max_space_id);
354
mutex_exit(&(dict_sys->mutex));
359
if (!rec_get_deleted_flag(rec, 0)) {
368
field = rec_get_nth_field_old(rec, 0, &len);
369
name = mem_strdupl((char*) field, len);
371
flags = dict_sys_tables_get_flags(rec);
372
if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
374
field = rec_get_nth_field_old(rec, 5, &len);
375
flags = mach_read_from_4(field);
377
ut_print_timestamp(stderr);
378
fputs(" InnoDB: Error: table ", stderr);
379
ut_print_filename(stderr, name);
381
"InnoDB: in InnoDB data dictionary"
382
" has unknown type %lx.\n",
388
field = rec_get_nth_field_old(rec, 9, &len);
391
space_id = mach_read_from_4(field);
393
btr_pcur_store_position(&pcur, &mtr);
397
if (space_id != 0 && in_crash_recovery) {
398
/* Check that the tablespace (the .ibd file) really
399
exists; print a warning to the .err log if not */
401
fil_space_for_table_exists_in_mem(space_id, name,
405
if (space_id != 0 && !in_crash_recovery) {
406
/* It is a normal database startup: create the space
407
object and check that the .ibd file exists. */
409
fil_open_single_table_tablespace(FALSE, space_id,
415
if (space_id > max_space_id) {
416
max_space_id = space_id;
421
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
427
/********************************************************************//**
428
Loads definitions for table columns. */
433
dict_table_t* table, /*!< in: table */
434
mem_heap_t* heap) /*!< in: memory heap for temporary storage */
436
dict_table_t* sys_columns;
437
dict_index_t* sys_index;
452
ut_ad(mutex_own(&(dict_sys->mutex)));
456
sys_columns = dict_table_get_low("SYS_COLUMNS");
457
sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
458
ut_a(!dict_table_is_comp(sys_columns));
460
tuple = dtuple_create(heap, 1);
461
dfield = dtuple_get_nth_field(tuple, 0);
463
buf = mem_heap_alloc(heap, 8);
464
mach_write_to_8(buf, table->id);
466
dfield_set_data(dfield, buf, 8);
467
dict_index_copy_types(tuple, sys_index, 1);
469
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
470
BTR_SEARCH_LEAF, &pcur, &mtr);
471
for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
473
rec = btr_pcur_get_rec(&pcur);
475
ut_a(btr_pcur_is_on_user_rec(&pcur));
477
ut_a(!rec_get_deleted_flag(rec, 0));
479
field = rec_get_nth_field_old(rec, 0, &len);
481
ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
483
field = rec_get_nth_field_old(rec, 1, &len);
485
ut_a(i == mach_read_from_4(field));
487
ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
489
field = rec_get_nth_field_old(rec, 4, &len);
490
name = mem_heap_strdupl(heap, (char*) field, len);
492
field = rec_get_nth_field_old(rec, 5, &len);
493
mtype = mach_read_from_4(field);
495
field = rec_get_nth_field_old(rec, 6, &len);
496
prtype = mach_read_from_4(field);
498
if (dtype_get_charset_coll(prtype) == 0
499
&& dtype_is_string_type(mtype)) {
500
/* The table was created with < 4.1.2. */
502
if (dtype_is_binary_string_type(mtype, prtype)) {
503
/* Use the binary collation for
504
string columns of binary type. */
506
prtype = dtype_form_prtype(
508
DATA_MYSQL_BINARY_CHARSET_COLL);
510
/* Use the default charset for
511
other than binary columns. */
513
prtype = dtype_form_prtype(
515
data_mysql_default_charset_coll);
519
field = rec_get_nth_field_old(rec, 7, &len);
520
col_len = mach_read_from_4(field);
522
ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
524
dict_mem_table_add_col(table, heap, name,
525
mtype, prtype, col_len);
526
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
529
btr_pcur_close(&pcur);
533
/********************************************************************//**
534
Loads definitions for index fields. */
539
dict_index_t* index, /*!< in: index whose fields to load */
540
mem_heap_t* heap) /*!< in: memory heap for temporary storage */
542
dict_table_t* sys_fields;
543
dict_index_t* sys_index;
547
ulint pos_and_prefix_len;
556
ut_ad(mutex_own(&(dict_sys->mutex)));
560
sys_fields = dict_table_get_low("SYS_FIELDS");
561
sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
562
ut_a(!dict_table_is_comp(sys_fields));
564
tuple = dtuple_create(heap, 1);
565
dfield = dtuple_get_nth_field(tuple, 0);
567
buf = mem_heap_alloc(heap, 8);
568
mach_write_to_8(buf, index->id);
570
dfield_set_data(dfield, buf, 8);
571
dict_index_copy_types(tuple, sys_index, 1);
573
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
574
BTR_SEARCH_LEAF, &pcur, &mtr);
575
for (i = 0; i < index->n_fields; i++) {
577
rec = btr_pcur_get_rec(&pcur);
579
ut_a(btr_pcur_is_on_user_rec(&pcur));
581
/* There could be delete marked records in SYS_FIELDS
582
because SYS_FIELDS.INDEX_ID can be updated
583
by ALTER TABLE ADD INDEX. */
585
if (rec_get_deleted_flag(rec, 0)) {
590
field = rec_get_nth_field_old(rec, 0, &len);
593
field = rec_get_nth_field_old(rec, 1, &len);
596
/* The next field stores the field position in the index
597
and a possible column prefix length if the index field
598
does not contain the whole column. The storage format is
599
like this: if there is at least one prefix field in the index,
600
then the HIGH 2 bytes contain the field number (== i) and the
601
low 2 bytes the prefix length for the field. Otherwise the
602
field number (== i) is contained in the 2 LOW bytes. */
604
pos_and_prefix_len = mach_read_from_4(field);
606
ut_a((pos_and_prefix_len & 0xFFFFUL) == i
607
|| (pos_and_prefix_len & 0xFFFF0000UL) == (i << 16));
609
if ((i == 0 && pos_and_prefix_len > 0)
610
|| (pos_and_prefix_len & 0xFFFF0000UL) > 0) {
612
prefix_len = pos_and_prefix_len & 0xFFFFUL;
617
ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
619
field = rec_get_nth_field_old(rec, 4, &len);
621
dict_mem_index_add_field(index,
622
mem_heap_strdupl(heap,
627
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
630
btr_pcur_close(&pcur);
634
/********************************************************************//**
635
Loads definitions for table indexes. Adds them to the data dictionary
637
@return DB_SUCCESS if ok, DB_CORRUPTION if corruption of dictionary
638
table or DB_UNSUPPORTED if table has unknown index type */
643
dict_table_t* table, /*!< in: table */
644
mem_heap_t* heap) /*!< in: memory heap for temporary storage */
646
dict_table_t* sys_indexes;
647
dict_index_t* sys_index;
665
ulint error = DB_SUCCESS;
667
ut_ad(mutex_own(&(dict_sys->mutex)));
669
if ((ut_dulint_get_high(table->id) == 0)
670
&& (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) {
673
is_sys_table = FALSE;
678
sys_indexes = dict_table_get_low("SYS_INDEXES");
679
sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
680
ut_a(!dict_table_is_comp(sys_indexes));
682
tuple = dtuple_create(heap, 1);
683
dfield = dtuple_get_nth_field(tuple, 0);
685
buf = mem_heap_alloc(heap, 8);
686
mach_write_to_8(buf, table->id);
688
dfield_set_data(dfield, buf, 8);
689
dict_index_copy_types(tuple, sys_index, 1);
691
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
692
BTR_SEARCH_LEAF, &pcur, &mtr);
694
if (!btr_pcur_is_on_user_rec(&pcur)) {
699
rec = btr_pcur_get_rec(&pcur);
701
field = rec_get_nth_field_old(rec, 0, &len);
704
if (ut_memcmp(buf, field, len) != 0) {
706
} else if (rec_get_deleted_flag(rec, 0)) {
707
/* Skip delete marked records */
711
field = rec_get_nth_field_old(rec, 1, &len);
713
id = mach_read_from_8(field);
715
ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
717
field = rec_get_nth_field_old(rec, 4, &name_len);
718
name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
720
field = rec_get_nth_field_old(rec, 5, &len);
721
n_fields = mach_read_from_4(field);
723
field = rec_get_nth_field_old(rec, 6, &len);
724
type = mach_read_from_4(field);
726
field = rec_get_nth_field_old(rec, 7, &len);
727
space = mach_read_from_4(field);
729
ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
731
field = rec_get_nth_field_old(rec, 8, &len);
732
page_no = mach_read_from_4(field);
734
/* We check for unsupported types first, so that the
735
subsequent checks are relevant for the supported types. */
736
if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
739
"InnoDB: Error: unknown type %lu"
740
" of index %s of table %s\n",
741
(ulong) type, name_buf, table->name);
743
error = DB_UNSUPPORTED;
745
} else if (page_no == FIL_NULL) {
748
"InnoDB: Error: trying to load index %s"
750
"InnoDB: but the index tree has been freed!\n",
751
name_buf, table->name);
753
error = DB_CORRUPTION;
755
} else if ((type & DICT_CLUSTERED) == 0
756
&& NULL == dict_table_get_first_index(table)) {
758
fputs("InnoDB: Error: trying to load index ",
760
ut_print_name(stderr, NULL, FALSE, name_buf);
761
fputs(" for table ", stderr);
762
ut_print_name(stderr, NULL, TRUE, table->name);
763
fputs("\nInnoDB: but the first index"
764
" is not clustered!\n", stderr);
766
error = DB_CORRUPTION;
768
} else if (is_sys_table
769
&& ((type & DICT_CLUSTERED)
770
|| ((table == dict_sys->sys_tables)
771
&& (name_len == (sizeof "ID_IND") - 1)
772
&& (0 == ut_memcmp(name_buf,
773
"ID_IND", name_len))))) {
775
/* The index was created in memory already at booting
776
of the database server */
778
index = dict_mem_index_create(table->name, name_buf,
779
space, type, n_fields);
782
dict_load_fields(index, heap);
783
error = dict_index_add_to_cache(table, index, page_no,
785
/* The data dictionary tables should never contain
786
invalid index definitions. If we ignored this error
787
and simply did not load this index definition, the
788
.frm file would disagree with the index definitions
790
if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
797
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
801
btr_pcur_close(&pcur);
807
/********************************************************************//**
808
Loads a table definition and also all its index definitions, and also
809
the cluster definition if the table is a member in a cluster. Also loads
810
all foreign key constraints where the foreign key is in the table or where
811
a foreign key references columns in this table. Adds all these to the data
813
@return table, NULL if does not exist; if the table is stored in an
814
.ibd file, but the file does not exist, then we set the
815
ibd_file_missing flag TRUE in the table object we return */
820
const char* name) /*!< in: table name in the
821
databasename/tablename format */
823
ibool ibd_file_missing = FALSE;
825
dict_table_t* sys_tables;
827
dict_index_t* sys_index;
840
ut_ad(mutex_own(&(dict_sys->mutex)));
842
heap = mem_heap_create(32000);
846
sys_tables = dict_table_get_low("SYS_TABLES");
847
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
848
ut_a(!dict_table_is_comp(sys_tables));
850
tuple = dtuple_create(heap, 1);
851
dfield = dtuple_get_nth_field(tuple, 0);
853
dfield_set_data(dfield, name, ut_strlen(name));
854
dict_index_copy_types(tuple, sys_index, 1);
856
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
857
BTR_SEARCH_LEAF, &pcur, &mtr);
858
rec = btr_pcur_get_rec(&pcur);
860
if (!btr_pcur_is_on_user_rec(&pcur)
861
|| rec_get_deleted_flag(rec, 0)) {
864
btr_pcur_close(&pcur);
871
field = rec_get_nth_field_old(rec, 0, &len);
873
/* Check if the table name in record is the searched one */
874
if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
879
ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
881
field = rec_get_nth_field_old(rec, 9, &len);
882
space = mach_read_from_4(field);
884
/* Check if the tablespace exists and has the right name */
886
flags = dict_sys_tables_get_flags(rec);
888
if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
889
field = rec_get_nth_field_old(rec, 5, &len);
890
flags = mach_read_from_4(field);
892
ut_print_timestamp(stderr);
893
fputs(" InnoDB: Error: table ", stderr);
894
ut_print_filename(stderr, name);
896
"InnoDB: in InnoDB data dictionary"
897
" has unknown type %lx.\n",
902
if (fil_space_for_table_exists_in_mem(space, name, FALSE,
904
/* Ok; (if we did a crash recovery then the tablespace
905
can already be in the memory cache) */
907
/* In >= 4.1.9, InnoDB scans the data dictionary also
908
at a normal mysqld startup. It is an error if the
909
space object does not exist in memory. */
911
ut_print_timestamp(stderr);
913
" InnoDB: error: space object of table %s,\n"
914
"InnoDB: space id %lu did not exist in memory."
915
" Retrying an open.\n",
917
/* Try to open the tablespace */
918
if (!fil_open_single_table_tablespace(
919
TRUE, space, flags, name)) {
920
/* We failed to find a sensible tablespace
923
ibd_file_missing = TRUE;
930
ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
932
field = rec_get_nth_field_old(rec, 4, &len);
933
n_cols = mach_read_from_4(field);
935
/* The high-order bit of N_COLS is the "compact format" flag. */
936
if (n_cols & 0x80000000UL) {
937
flags |= DICT_TF_COMPACT;
940
table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
943
table->ibd_file_missing = (unsigned int) ibd_file_missing;
945
ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
947
field = rec_get_nth_field_old(rec, 3, &len);
948
table->id = mach_read_from_8(field);
950
btr_pcur_close(&pcur);
953
dict_load_columns(table, heap);
955
dict_table_add_to_cache(table, heap);
957
mem_heap_empty(heap);
959
err = dict_load_indexes(table, heap);
961
/* If the force recovery flag is set, we open the table irrespective
962
of the error condition, since the user may want to dump data from the
963
clustered index. However we load the foreign key information only if
964
all indexes were loaded. */
965
if (err == DB_SUCCESS) {
966
err = dict_load_foreigns(table->name, TRUE);
967
} else if (!srv_force_recovery) {
968
dict_table_remove_from_cache(table);
972
if (err != DB_SUCCESS && table != NULL) {
974
mutex_enter(&dict_foreign_err_mutex);
976
ut_print_timestamp(stderr);
979
" InnoDB: Error: could not make a foreign key"
980
" definition to match\n"
981
"InnoDB: the foreign key table"
982
" or the referenced table!\n"
983
"InnoDB: The data dictionary of InnoDB is corrupt."
984
" You may need to drop\n"
985
"InnoDB: and recreate the foreign key table"
986
" or the referenced table.\n"
987
"InnoDB: Submit a detailed bug report"
988
" to http://bugs.mysql.com\n"
989
"InnoDB: Latest foreign key error printout:\n%s\n",
990
dict_foreign_err_buf);
992
mutex_exit(&dict_foreign_err_mutex);
1000
/***********************************************************************//**
1001
Loads a table object based on the table id.
1002
@return table; NULL if table does not exist */
1005
dict_load_table_on_id(
1006
/*==================*/
1007
dulint table_id) /*!< in: table id */
1014
dict_index_t* sys_table_ids;
1015
dict_table_t* sys_tables;
1019
dict_table_t* table;
1022
ut_ad(mutex_own(&(dict_sys->mutex)));
1024
/* NOTE that the operation of this function is protected by
1025
the dictionary mutex, and therefore no deadlocks can occur
1026
with other dictionary operations. */
1029
/*---------------------------------------------------*/
1030
/* Get the secondary index based on ID for table SYS_TABLES */
1031
sys_tables = dict_sys->sys_tables;
1032
sys_table_ids = dict_table_get_next_index(
1033
dict_table_get_first_index(sys_tables));
1034
ut_a(!dict_table_is_comp(sys_tables));
1035
heap = mem_heap_create(256);
1037
tuple = dtuple_create(heap, 1);
1038
dfield = dtuple_get_nth_field(tuple, 0);
1040
/* Write the table id in byte format to id_buf */
1041
mach_write_to_8(id_buf, table_id);
1043
dfield_set_data(dfield, id_buf, 8);
1044
dict_index_copy_types(tuple, sys_table_ids, 1);
1046
btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
1047
BTR_SEARCH_LEAF, &pcur, &mtr);
1048
rec = btr_pcur_get_rec(&pcur);
1050
if (!btr_pcur_is_on_user_rec(&pcur)
1051
|| rec_get_deleted_flag(rec, 0)) {
1054
btr_pcur_close(&pcur);
1056
mem_heap_free(heap);
1061
/*---------------------------------------------------*/
1062
/* Now we have the record in the secondary index containing the
1063
table ID and NAME */
1065
rec = btr_pcur_get_rec(&pcur);
1066
field = rec_get_nth_field_old(rec, 0, &len);
1069
/* Check if the table id in record is the one searched for */
1070
if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) {
1072
btr_pcur_close(&pcur);
1074
mem_heap_free(heap);
1079
/* Now we get the table name from the record */
1080
field = rec_get_nth_field_old(rec, 1, &len);
1081
/* Load the table definition to memory */
1082
table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
1084
btr_pcur_close(&pcur);
1086
mem_heap_free(heap);
1091
/********************************************************************//**
1092
This function is called when the database is booted. Loads system table
1093
index definitions except for the clustered index which is added to the
1094
dictionary cache at booting before calling this function. */
1097
dict_load_sys_table(
1098
/*================*/
1099
dict_table_t* table) /*!< in: system table */
1103
ut_ad(mutex_own(&(dict_sys->mutex)));
1105
heap = mem_heap_create(1000);
1107
dict_load_indexes(table, heap);
1109
mem_heap_free(heap);
1112
/********************************************************************//**
1113
Loads foreign key constraint col names (also for the referenced table). */
1116
dict_load_foreign_cols(
1117
/*===================*/
1118
const char* id, /*!< in: foreign constraint id as a
1119
null-terminated string */
1120
dict_foreign_t* foreign)/*!< in: foreign constraint object */
1122
dict_table_t* sys_foreign_cols;
1123
dict_index_t* sys_index;
1133
ut_ad(mutex_own(&(dict_sys->mutex)));
1135
foreign->foreign_col_names = mem_heap_alloc(
1136
foreign->heap, foreign->n_fields * sizeof(void*));
1138
foreign->referenced_col_names = mem_heap_alloc(
1139
foreign->heap, foreign->n_fields * sizeof(void*));
1142
sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
1143
sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
1144
ut_a(!dict_table_is_comp(sys_foreign_cols));
1146
tuple = dtuple_create(foreign->heap, 1);
1147
dfield = dtuple_get_nth_field(tuple, 0);
1149
dfield_set_data(dfield, id, ut_strlen(id));
1150
dict_index_copy_types(tuple, sys_index, 1);
1152
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1153
BTR_SEARCH_LEAF, &pcur, &mtr);
1154
for (i = 0; i < foreign->n_fields; i++) {
1156
rec = btr_pcur_get_rec(&pcur);
1158
ut_a(btr_pcur_is_on_user_rec(&pcur));
1159
ut_a(!rec_get_deleted_flag(rec, 0));
1161
field = rec_get_nth_field_old(rec, 0, &len);
1162
ut_a(len == ut_strlen(id));
1163
ut_a(ut_memcmp(id, field, len) == 0);
1165
field = rec_get_nth_field_old(rec, 1, &len);
1167
ut_a(i == mach_read_from_4(field));
1169
field = rec_get_nth_field_old(rec, 4, &len);
1170
foreign->foreign_col_names[i] = mem_heap_strdupl(
1171
foreign->heap, (char*) field, len);
1173
field = rec_get_nth_field_old(rec, 5, &len);
1174
foreign->referenced_col_names[i] = mem_heap_strdupl(
1175
foreign->heap, (char*) field, len);
1177
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1180
btr_pcur_close(&pcur);
1184
/***********************************************************************//**
1185
Loads a foreign key constraint to the dictionary cache.
1186
@return DB_SUCCESS or error code */
1191
const char* id, /*!< in: foreign constraint id as a
1192
null-terminated string */
1193
ibool check_charsets)
1194
/*!< in: TRUE=check charset compatibility */
1196
dict_foreign_t* foreign;
1197
dict_table_t* sys_foreign;
1199
dict_index_t* sys_index;
1206
ulint n_fields_and_type;
1209
ut_ad(mutex_own(&(dict_sys->mutex)));
1211
heap2 = mem_heap_create(1000);
1215
sys_foreign = dict_table_get_low("SYS_FOREIGN");
1216
sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
1217
ut_a(!dict_table_is_comp(sys_foreign));
1219
tuple = dtuple_create(heap2, 1);
1220
dfield = dtuple_get_nth_field(tuple, 0);
1222
dfield_set_data(dfield, id, ut_strlen(id));
1223
dict_index_copy_types(tuple, sys_index, 1);
1225
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
1226
BTR_SEARCH_LEAF, &pcur, &mtr);
1227
rec = btr_pcur_get_rec(&pcur);
1229
if (!btr_pcur_is_on_user_rec(&pcur)
1230
|| rec_get_deleted_flag(rec, 0)) {
1234
"InnoDB: Error A: cannot load foreign constraint %s\n",
1237
btr_pcur_close(&pcur);
1239
mem_heap_free(heap2);
1244
field = rec_get_nth_field_old(rec, 0, &len);
1246
/* Check if the id in record is the searched one */
1247
if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
1250
"InnoDB: Error B: cannot load foreign constraint %s\n",
1253
btr_pcur_close(&pcur);
1255
mem_heap_free(heap2);
1260
/* Read the table names and the number of columns associated
1261
with the constraint */
1263
mem_heap_free(heap2);
1265
foreign = dict_mem_foreign_create();
1267
n_fields_and_type = mach_read_from_4(
1268
rec_get_nth_field_old(rec, 5, &len));
1272
/* We store the type in the bits 24..29 of n_fields_and_type. */
1274
foreign->type = (unsigned int) (n_fields_and_type >> 24);
1275
foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
1277
foreign->id = mem_heap_strdup(foreign->heap, id);
1279
field = rec_get_nth_field_old(rec, 3, &len);
1280
foreign->foreign_table_name = mem_heap_strdupl(
1281
foreign->heap, (char*) field, len);
1283
field = rec_get_nth_field_old(rec, 4, &len);
1284
foreign->referenced_table_name = mem_heap_strdupl(
1285
foreign->heap, (char*) field, len);
1287
btr_pcur_close(&pcur);
1290
dict_load_foreign_cols(id, foreign);
1292
/* If the foreign table is not yet in the dictionary cache, we
1293
have to load it so that we are able to make type comparisons
1294
in the next function call. */
1296
dict_table_get_low(foreign->foreign_table_name);
1298
/* Note that there may already be a foreign constraint object in
1299
the dictionary cache for this constraint: then the following
1300
call only sets the pointers in it to point to the appropriate table
1301
and index objects and frees the newly created object foreign.
1302
Adding to the cache should always succeed since we are not creating
1303
a new foreign key constraint but loading one from the data
1306
return(dict_foreign_add_to_cache(foreign, check_charsets));
1309
/***********************************************************************//**
1310
Loads foreign key constraints where the table is either the foreign key
1311
holder or where the table is referenced by a foreign key. Adds these
1312
constraints to the data dictionary. Note that we know that the dictionary
1313
cache already contains all constraints where the other relevant table is
1314
already in the dictionary cache.
1315
@return DB_SUCCESS or error code */
1320
const char* table_name, /*!< in: table name */
1321
ibool check_charsets) /*!< in: TRUE=check charset
1328
dict_index_t* sec_index;
1329
dict_table_t* sys_foreign;
1337
ut_ad(mutex_own(&(dict_sys->mutex)));
1339
sys_foreign = dict_table_get_low("SYS_FOREIGN");
1341
if (sys_foreign == NULL) {
1342
/* No foreign keys defined yet in this database */
1345
"InnoDB: Error: no foreign key system tables"
1346
" in the database\n");
1351
ut_a(!dict_table_is_comp(sys_foreign));
1354
/* Get the secondary index based on FOR_NAME from table
1357
sec_index = dict_table_get_next_index(
1358
dict_table_get_first_index(sys_foreign));
1360
heap = mem_heap_create(256);
1362
tuple = dtuple_create(heap, 1);
1363
dfield = dtuple_get_nth_field(tuple, 0);
1365
dfield_set_data(dfield, table_name, ut_strlen(table_name));
1366
dict_index_copy_types(tuple, sec_index, 1);
1368
btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE,
1369
BTR_SEARCH_LEAF, &pcur, &mtr);
1371
rec = btr_pcur_get_rec(&pcur);
1373
if (!btr_pcur_is_on_user_rec(&pcur)) {
1376
goto load_next_index;
1379
/* Now we have the record in the secondary index containing a table
1380
name and a foreign constraint ID */
1382
rec = btr_pcur_get_rec(&pcur);
1383
field = rec_get_nth_field_old(rec, 0, &len);
1385
/* Check if the table name in the record is the one searched for; the
1386
following call does the comparison in the latin1_swedish_ci
1387
charset-collation, in a case-insensitive way. */
1389
if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
1390
dfield_get_type(dfield)->prtype,
1391
dfield_get_data(dfield), dfield_get_len(dfield),
1394
goto load_next_index;
1397
/* Since table names in SYS_FOREIGN are stored in a case-insensitive
1398
order, we have to check that the table name matches also in a binary
1399
string comparison. On Unix, MySQL allows table names that only differ
1400
in character case. */
1402
if (0 != ut_memcmp(field, table_name, len)) {
1407
if (rec_get_deleted_flag(rec, 0)) {
1412
/* Now we get a foreign key constraint id */
1413
field = rec_get_nth_field_old(rec, 1, &len);
1414
id = mem_heap_strdupl(heap, (char*) field, len);
1416
btr_pcur_store_position(&pcur, &mtr);
1420
/* Load the foreign constraint definition to the dictionary cache */
1422
err = dict_load_foreign(id, check_charsets);
1424
if (err != DB_SUCCESS) {
1425
btr_pcur_close(&pcur);
1426
mem_heap_free(heap);
1433
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
1435
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
1440
btr_pcur_close(&pcur);
1442
mem_heap_free(heap);
1444
sec_index = dict_table_get_next_index(sec_index);
1446
if (sec_index != NULL) {