00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00027 #if defined(BUILD_DRIZZLE)
00028 # include "config.h"
00029 #else
00030 # include "mysql_version.h"
00031 #endif
00032 #include "dict0load.h"
00033
00034 #ifdef UNIV_NONINL
00035 #include "dict0load.ic"
00036 #endif
00037
00038 #include "btr0pcur.h"
00039 #include "btr0btr.h"
00040 #include "page0page.h"
00041 #include "mach0data.h"
00042 #include "dict0dict.h"
00043 #include "dict0boot.h"
00044 #include "rem0cmp.h"
00045 #include "srv0start.h"
00046 #include "srv0srv.h"
00047
00048
00050 static const char* SYSTEM_TABLE_NAME[] = {
00051 "SYS_TABLES",
00052 "SYS_INDEXES",
00053 "SYS_COLUMNS",
00054 "SYS_FIELDS",
00055 "SYS_FOREIGN",
00056 "SYS_FOREIGN_COLS"
00057 };
00058
00061 static
00062 ibool
00063 name_of_col_is(
00064
00065 const dict_table_t* table,
00066 const dict_index_t* index,
00067 ulint i,
00068 const char* name)
00069 {
00070 ulint tmp = dict_col_get_no(dict_field_get_col(
00071 dict_index_get_nth_field(
00072 index, i)));
00073
00074 return(strcmp(name, dict_table_get_col_name(table, tmp)) == 0);
00075 }
00076
00077
00081 UNIV_INTERN
00082 char*
00083 dict_get_first_table_name_in_db(
00084
00085 const char* name)
00086 {
00087 dict_table_t* sys_tables;
00088 btr_pcur_t pcur;
00089 dict_index_t* sys_index;
00090 dtuple_t* tuple;
00091 mem_heap_t* heap;
00092 dfield_t* dfield;
00093 const rec_t* rec;
00094 const byte* field;
00095 ulint len;
00096 mtr_t mtr;
00097
00098 ut_ad(mutex_own(&(dict_sys->mutex)));
00099
00100 heap = mem_heap_create(1000);
00101
00102 mtr_start(&mtr);
00103
00104 sys_tables = dict_table_get_low("SYS_TABLES");
00105 sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
00106 ut_a(!dict_table_is_comp(sys_tables));
00107
00108 tuple = dtuple_create(heap, 1);
00109 dfield = dtuple_get_nth_field(tuple, 0);
00110
00111 dfield_set_data(dfield, name, ut_strlen(name));
00112 dict_index_copy_types(tuple, sys_index, 1);
00113
00114 btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
00115 BTR_SEARCH_LEAF, &pcur, &mtr);
00116 loop:
00117 rec = btr_pcur_get_rec(&pcur);
00118
00119 if (!btr_pcur_is_on_user_rec(&pcur)) {
00120
00121
00122 btr_pcur_close(&pcur);
00123 mtr_commit(&mtr);
00124 mem_heap_free(heap);
00125
00126 return(NULL);
00127 }
00128
00129 field = rec_get_nth_field_old(rec, 0, &len);
00130
00131 if (len < strlen(name)
00132 || ut_memcmp(name, field, strlen(name)) != 0) {
00133
00134
00135 btr_pcur_close(&pcur);
00136 mtr_commit(&mtr);
00137 mem_heap_free(heap);
00138
00139 return(NULL);
00140 }
00141
00142 if (!rec_get_deleted_flag(rec, 0)) {
00143
00144
00145
00146 char* table_name = mem_strdupl((char*) field, len);
00147
00148 btr_pcur_close(&pcur);
00149 mtr_commit(&mtr);
00150 mem_heap_free(heap);
00151
00152 return(table_name);
00153 }
00154
00155 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
00156
00157 goto loop;
00158 }
00159
00160
00163 UNIV_INTERN
00164 void
00165 dict_print(void)
00166
00167 {
00168 dict_table_t* table;
00169 btr_pcur_t pcur;
00170 const rec_t* rec;
00171 mem_heap_t* heap;
00172 mtr_t mtr;
00173
00174
00175
00176
00177 mutex_enter(&kernel_mutex);
00178 srv_fatal_semaphore_wait_threshold += 7200;
00179 mutex_exit(&kernel_mutex);
00180
00181 heap = mem_heap_create(1000);
00182 mutex_enter(&(dict_sys->mutex));
00183
00184 mtr_start(&mtr);
00185
00186 rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
00187
00188 while (rec) {
00189 const char* err_msg;
00190
00191 err_msg = dict_process_sys_tables_rec(
00192 heap, rec, &table,
00193 static_cast<dict_table_info>(DICT_TABLE_LOAD_FROM_CACHE
00194 | DICT_TABLE_UPDATE_STATS));
00195
00196 mtr_commit(&mtr);
00197
00198 if (!err_msg) {
00199 dict_table_print_low(table);
00200 } else {
00201 ut_print_timestamp(stderr);
00202 fprintf(stderr, " InnoDB: %s\n", err_msg);
00203 }
00204
00205 mem_heap_empty(heap);
00206
00207 mtr_start(&mtr);
00208 rec = dict_getnext_system(&pcur, &mtr);
00209 }
00210
00211 mtr_commit(&mtr);
00212 mutex_exit(&(dict_sys->mutex));
00213 mem_heap_free(heap);
00214
00215
00216 mutex_enter(&kernel_mutex);
00217 srv_fatal_semaphore_wait_threshold -= 7200;
00218 mutex_exit(&kernel_mutex);
00219 }
00220
00221
00222
00225 static
00226 const rec_t*
00227 dict_getnext_system_low(
00228
00229 btr_pcur_t* pcur,
00231 mtr_t* mtr)
00232 {
00233 rec_t* rec = NULL;
00234
00235 while (!rec || rec_get_deleted_flag(rec, 0)) {
00236 btr_pcur_move_to_next_user_rec(pcur, mtr);
00237
00238 rec = btr_pcur_get_rec(pcur);
00239
00240 if (!btr_pcur_is_on_user_rec(pcur)) {
00241
00242 btr_pcur_close(pcur);
00243
00244 return(NULL);
00245 }
00246 }
00247
00248
00249 btr_pcur_store_position(pcur, mtr);
00250
00251 return(rec);
00252 }
00253
00254
00257 UNIV_INTERN
00258 const rec_t*
00259 dict_startscan_system(
00260
00261 btr_pcur_t* pcur,
00263 mtr_t* mtr,
00264 dict_system_id_t system_id)
00265 {
00266 dict_table_t* system_table;
00267 dict_index_t* clust_index;
00268 const rec_t* rec;
00269
00270 ut_a(system_id < SYS_NUM_SYSTEM_TABLES);
00271
00272 system_table = dict_table_get_low(SYSTEM_TABLE_NAME[system_id]);
00273
00274 clust_index = UT_LIST_GET_FIRST(system_table->indexes);
00275
00276 btr_pcur_open_at_index_side(TRUE, clust_index, BTR_SEARCH_LEAF, pcur,
00277 TRUE, mtr);
00278
00279 rec = dict_getnext_system_low(pcur, mtr);
00280
00281 return(rec);
00282 }
00283
00284
00287 UNIV_INTERN
00288 const rec_t*
00289 dict_getnext_system(
00290
00291 btr_pcur_t* pcur,
00293 mtr_t* mtr)
00294 {
00295 const rec_t* rec;
00296
00297
00298 btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
00299
00300
00301 rec = dict_getnext_system_low(pcur, mtr);
00302
00303 return(rec);
00304 }
00305
00310 UNIV_INTERN
00311 const char*
00312 dict_process_sys_tables_rec(
00313
00314 mem_heap_t* heap,
00315 const rec_t* rec,
00316 dict_table_t** table,
00317 dict_table_info_t status)
00321 {
00322 ulint len;
00323 const char* field;
00324 const char* err_msg = NULL;
00325 char* table_name;
00326
00327 field = (const char*) rec_get_nth_field_old(rec, 0, &len);
00328
00329 ut_a(!rec_get_deleted_flag(rec, 0));
00330
00331
00332 table_name = mem_heap_strdupl(heap, (const char*)field, len);
00333
00334
00335
00336 if (status & DICT_TABLE_LOAD_FROM_CACHE) {
00337 *table = dict_table_get_low(table_name);
00338
00339 if (!(*table)) {
00340 err_msg = "Table not found in cache";
00341 }
00342 } else {
00343 err_msg = dict_load_table_low(table_name, rec, table);
00344 }
00345
00346 if (err_msg) {
00347 return(err_msg);
00348 }
00349
00350 if ((status & DICT_TABLE_UPDATE_STATS)
00351 && dict_table_get_first_index(*table)) {
00352
00353
00354
00355 dict_update_statistics(*table,
00356 FALSE
00357 );
00358 }
00359
00360 return(NULL);
00361 }
00362
00363
00368 UNIV_INTERN
00369 const char*
00370 dict_process_sys_indexes_rec(
00371
00372 mem_heap_t* heap,
00373 const rec_t* rec,
00374 dict_index_t* index,
00375 table_id_t* table_id)
00376 {
00377 const char* err_msg;
00378 byte* buf;
00379
00380 buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
00381
00382
00383 err_msg = dict_load_index_low(buf, NULL,
00384 heap, rec, FALSE, &index);
00385
00386 *table_id = mach_read_from_8(buf);
00387
00388 return(err_msg);
00389 }
00390
00394 UNIV_INTERN
00395 const char*
00396 dict_process_sys_columns_rec(
00397
00398 mem_heap_t* heap,
00399 const rec_t* rec,
00400 dict_col_t* column,
00401 table_id_t* table_id,
00402 const char** col_name)
00403 {
00404 const char* err_msg;
00405
00406
00407 err_msg = dict_load_column_low(NULL, heap, column,
00408 table_id, col_name, rec);
00409
00410 return(err_msg);
00411 }
00412
00416 UNIV_INTERN
00417 const char*
00418 dict_process_sys_fields_rec(
00419
00420 mem_heap_t* heap,
00421 const rec_t* rec,
00422 dict_field_t* sys_field,
00424 ulint* pos,
00425 index_id_t* index_id,
00426 index_id_t last_id)
00427 {
00428 byte* buf;
00429 byte* last_index_id;
00430 const char* err_msg;
00431
00432 buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
00433
00434 last_index_id = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
00435 mach_write_to_8(last_index_id, last_id);
00436
00437 err_msg = dict_load_field_low(buf, NULL, sys_field,
00438 pos, last_index_id, heap, rec);
00439
00440 *index_id = mach_read_from_8(buf);
00441
00442 return(err_msg);
00443
00444 }
00445
00450 UNIV_INTERN
00451 const char*
00452 dict_process_sys_foreign_rec(
00453
00454 mem_heap_t* heap,
00455 const rec_t* rec,
00456 dict_foreign_t* foreign)
00458 {
00459 ulint len;
00460 const byte* field;
00461 ulint n_fields_and_type;
00462
00463 if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
00464 return("delete-marked record in SYS_FOREIGN");
00465 }
00466
00467 if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 6)) {
00468 return("wrong number of columns in SYS_FOREIGN record");
00469 }
00470
00471 field = rec_get_nth_field_old(rec, 0, &len);
00472 if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
00473 err_len:
00474 return("incorrect column length in SYS_FOREIGN");
00475 }
00476 foreign->id = mem_heap_strdupl(heap, (const char*) field, len);
00477
00478 rec_get_nth_field_offs_old(rec, 1, &len);
00479 if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
00480 goto err_len;
00481 }
00482 rec_get_nth_field_offs_old(rec, 2, &len);
00483 if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
00484 goto err_len;
00485 }
00486
00487 field = rec_get_nth_field_old(rec, 3, &len);
00488 if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
00489 goto err_len;
00490 }
00491 foreign->foreign_table_name = mem_heap_strdupl(
00492 heap, (const char*) field, len);
00493
00494 field = rec_get_nth_field_old(rec, 4, &len);
00495 if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
00496 goto err_len;
00497 }
00498 foreign->referenced_table_name = mem_heap_strdupl(
00499 heap, (const char*) field, len);
00500
00501 field = rec_get_nth_field_old(rec, 5, &len);
00502 if (UNIV_UNLIKELY(len != 4)) {
00503 goto err_len;
00504 }
00505 n_fields_and_type = mach_read_from_4(field);
00506
00507 foreign->type = (unsigned int) (n_fields_and_type >> 24);
00508 foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
00509
00510 return(NULL);
00511 }
00512
00516 UNIV_INTERN
00517 const char*
00518 dict_process_sys_foreign_col_rec(
00519
00520 mem_heap_t* heap,
00521 const rec_t* rec,
00522 const char** name,
00523 const char** for_col_name,
00524 const char** ref_col_name,
00526 ulint* pos)
00527 {
00528 ulint len;
00529 const byte* field;
00530
00531 if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
00532 return("delete-marked record in SYS_FOREIGN_COLS");
00533 }
00534
00535 if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 6)) {
00536 return("wrong number of columns in SYS_FOREIGN_COLS record");
00537 }
00538
00539 field = rec_get_nth_field_old(rec, 0, &len);
00540 if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
00541 err_len:
00542 return("incorrect column length in SYS_FOREIGN_COLS");
00543 }
00544 *name = mem_heap_strdupl(heap, (char*) field, len);
00545
00546 field = rec_get_nth_field_old(rec, 1, &len);
00547 if (UNIV_UNLIKELY(len != 4)) {
00548 goto err_len;
00549 }
00550 *pos = mach_read_from_4(field);
00551
00552 rec_get_nth_field_offs_old(rec, 2, &len);
00553 if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
00554 goto err_len;
00555 }
00556 rec_get_nth_field_offs_old(rec, 3, &len);
00557 if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
00558 goto err_len;
00559 }
00560
00561 field = rec_get_nth_field_old(rec, 4, &len);
00562 if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
00563 goto err_len;
00564 }
00565 *for_col_name = mem_heap_strdupl(heap, (char*) field, len);
00566
00567 field = rec_get_nth_field_old(rec, 5, &len);
00568 if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
00569 goto err_len;
00570 }
00571 *ref_col_name = mem_heap_strdupl(heap, (char*) field, len);
00572
00573 return(NULL);
00574 }
00575
00576
00577
00578
00579
00580 UNIV_INTERN void dict_print_with_callback(dict_print_callback func, void *func_arg)
00581 {
00582 dict_table_t* sys_tables;
00583 dict_index_t* sys_index;
00584 btr_pcur_t pcur;
00585 const rec_t* rec;
00586 const byte* field;
00587 ulint len;
00588 mtr_t mtr;
00589
00590
00591
00592
00593 mutex_enter(&kernel_mutex);
00594 srv_fatal_semaphore_wait_threshold += 7200;
00595 mutex_exit(&kernel_mutex);
00596
00597 mutex_enter(&(dict_sys->mutex));
00598
00599 mtr_start(&mtr);
00600
00601 sys_tables = dict_table_get_low("SYS_TABLES");
00602 sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
00603
00604 btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
00605 TRUE, &mtr);
00606 loop:
00607 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
00608
00609 rec = btr_pcur_get_rec(&pcur);
00610
00611 if (!btr_pcur_is_on_user_rec(&pcur)) {
00612
00613
00614 btr_pcur_close(&pcur);
00615 mtr_commit(&mtr);
00616
00617 mutex_exit(&(dict_sys->mutex));
00618
00619
00620
00621 mutex_enter(&kernel_mutex);
00622 srv_fatal_semaphore_wait_threshold -= 7200;
00623 mutex_exit(&kernel_mutex);
00624
00625 return;
00626 }
00627
00628 field = rec_get_nth_field_old(rec, 0, &len);
00629
00630 if (!rec_get_deleted_flag(rec, 0)) {
00631
00632
00633
00634 char* table_name = mem_strdupl((char*) field, len);
00635
00636 btr_pcur_store_position(&pcur, &mtr);
00637
00638 mtr_commit(&mtr);
00639
00640 func(func_arg, table_name);
00641 mem_free(table_name);
00642
00643 mtr_start(&mtr);
00644
00645 btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
00646 }
00647
00648 goto loop;
00649 }
00650
00651
00655 static
00656 ulint
00657 dict_sys_tables_get_flags(
00658
00659 const rec_t* rec)
00660 {
00661 const byte* field;
00662 ulint len;
00663 ulint n_cols;
00664 ulint flags;
00665
00666 field = rec_get_nth_field_old(rec, 5, &len);
00667 ut_a(len == 4);
00668
00669 flags = mach_read_from_4(field);
00670
00671 if (UNIV_LIKELY(flags == DICT_TABLE_ORDINARY)) {
00672 return(0);
00673 }
00674
00675 field = rec_get_nth_field_old(rec, 4, &len);
00676 n_cols = mach_read_from_4(field);
00677
00678 if (UNIV_UNLIKELY(!(n_cols & 0x80000000UL))) {
00679
00680 return(ULINT_UNDEFINED);
00681 }
00682
00683 switch (flags & (DICT_TF_FORMAT_MASK | DICT_TF_COMPACT)) {
00684 default:
00685 case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT:
00686 case DICT_TF_FORMAT_51 << DICT_TF_FORMAT_SHIFT | DICT_TF_COMPACT:
00687
00688
00689 return(ULINT_UNDEFINED);
00690
00691 case DICT_TF_FORMAT_ZIP << DICT_TF_FORMAT_SHIFT | DICT_TF_COMPACT:
00692 #if DICT_TF_FORMAT_MAX > DICT_TF_FORMAT_ZIP
00693 # error "missing case labels for DICT_TF_FORMAT_ZIP .. DICT_TF_FORMAT_MAX"
00694 #endif
00695
00696 break;
00697 }
00698
00699 if (UNIV_UNLIKELY((flags & DICT_TF_ZSSIZE_MASK)
00700 > (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT))) {
00701
00702 return(ULINT_UNDEFINED);
00703 }
00704
00705 if (UNIV_UNLIKELY(flags & (SIZE_MAX << DICT_TF_BITS))) {
00706
00707 return(ULINT_UNDEFINED);
00708 }
00709
00710 return(flags);
00711 }
00712
00713
00721 UNIV_INTERN
00722 void
00723 dict_check_tablespaces_and_store_max_id(
00724
00725 ibool in_crash_recovery)
00726 {
00727 dict_table_t* sys_tables;
00728 dict_index_t* sys_index;
00729 btr_pcur_t pcur;
00730 const rec_t* rec;
00731 ulint max_space_id;
00732 mtr_t mtr;
00733
00734 mutex_enter(&(dict_sys->mutex));
00735
00736 mtr_start(&mtr);
00737
00738 sys_tables = dict_table_get_low("SYS_TABLES");
00739 sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
00740 ut_a(!dict_table_is_comp(sys_tables));
00741
00742 max_space_id = mtr_read_ulint(dict_hdr_get(&mtr)
00743 + DICT_HDR_MAX_SPACE_ID,
00744 MLOG_4BYTES, &mtr);
00745 fil_set_max_space_id_if_bigger(max_space_id);
00746
00747 btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
00748 TRUE, &mtr);
00749 loop:
00750 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
00751
00752 rec = btr_pcur_get_rec(&pcur);
00753
00754 if (!btr_pcur_is_on_user_rec(&pcur)) {
00755
00756
00757 btr_pcur_close(&pcur);
00758 mtr_commit(&mtr);
00759
00760
00761
00762
00763
00764
00765 fil_set_max_space_id_if_bigger(max_space_id);
00766
00767 mutex_exit(&(dict_sys->mutex));
00768
00769 return;
00770 }
00771
00772 if (!rec_get_deleted_flag(rec, 0)) {
00773
00774
00775 const byte* field;
00776 ulint len;
00777 ulint space_id;
00778 ulint flags;
00779 char* name;
00780
00781 field = rec_get_nth_field_old(rec, 0, &len);
00782 name = mem_strdupl((char*) field, len);
00783
00784 flags = dict_sys_tables_get_flags(rec);
00785 if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
00786
00787 field = rec_get_nth_field_old(rec, 5, &len);
00788 flags = mach_read_from_4(field);
00789
00790 ut_print_timestamp(stderr);
00791 fputs(" InnoDB: Error: table ", stderr);
00792 ut_print_filename(stderr, name);
00793 fprintf(stderr, "\n"
00794 "InnoDB: in InnoDB data dictionary"
00795 " has unknown type %lx.\n",
00796 (ulong) flags);
00797
00798 goto loop;
00799 }
00800
00801 field = rec_get_nth_field_old(rec, 9, &len);
00802 ut_a(len == 4);
00803
00804 space_id = mach_read_from_4(field);
00805
00806 btr_pcur_store_position(&pcur, &mtr);
00807
00808 mtr_commit(&mtr);
00809
00810 if (space_id == 0) {
00811
00812 } else if (in_crash_recovery) {
00813
00814
00815
00816 ibool is_temp;
00817
00818 field = rec_get_nth_field_old(rec, 4, &len);
00819 if (0x80000000UL & mach_read_from_4(field)) {
00820
00821
00822 field = rec_get_nth_field_old(rec, 7, &len);
00823 is_temp = mach_read_from_4(field)
00824 & DICT_TF2_TEMPORARY;
00825 } else {
00826
00827
00828
00829
00830
00831
00832
00833 is_temp = FALSE;
00834 }
00835
00836 fil_space_for_table_exists_in_mem(
00837 space_id, name, is_temp, TRUE, !is_temp);
00838 } else {
00839
00840
00841
00842 fil_open_single_table_tablespace(FALSE, space_id,
00843 flags, name);
00844 }
00845
00846 mem_free(name);
00847
00848 if (space_id > max_space_id) {
00849 max_space_id = space_id;
00850 }
00851
00852 mtr_start(&mtr);
00853
00854 btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
00855 }
00856
00857 goto loop;
00858 }
00859
00860
00864 UNIV_INTERN
00865 const char*
00866 dict_load_column_low(
00867
00868 dict_table_t* table,
00872 mem_heap_t* heap,
00874 dict_col_t* column,
00876 table_id_t* table_id,
00877 const char** col_name,
00878 const rec_t* rec)
00879 {
00880 char* name;
00881 const byte* field;
00882 ulint len;
00883 ulint mtype;
00884 ulint prtype;
00885 ulint col_len;
00886 ulint pos = 0;
00887
00888 ut_ad(table || column);
00889
00890 if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
00891 return("delete-marked record in SYS_COLUMNS");
00892 }
00893
00894 if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 9)) {
00895 return("wrong number of columns in SYS_COLUMNS record");
00896 }
00897
00898 field = rec_get_nth_field_old(rec, 0, &len);
00899 if (UNIV_UNLIKELY(len != 8)) {
00900 err_len:
00901 return("incorrect column length in SYS_COLUMNS");
00902 }
00903
00904 if (table_id) {
00905 *table_id = mach_read_from_8(field);
00906 } else if (UNIV_UNLIKELY(table->id != mach_read_from_8(field))) {
00907 return("SYS_COLUMNS.TABLE_ID mismatch");
00908 }
00909
00910 field = rec_get_nth_field_old(rec, 1, &len);
00911 if (UNIV_UNLIKELY(len != 4)) {
00912
00913 goto err_len;
00914 }
00915
00916 pos = mach_read_from_4(field);
00917
00918 if (UNIV_UNLIKELY(table && table->n_def != pos)) {
00919 return("SYS_COLUMNS.POS mismatch");
00920 }
00921
00922 rec_get_nth_field_offs_old(rec, 2, &len);
00923 if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
00924 goto err_len;
00925 }
00926 rec_get_nth_field_offs_old(rec, 3, &len);
00927 if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
00928 goto err_len;
00929 }
00930
00931 field = rec_get_nth_field_old(rec, 4, &len);
00932 if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
00933 goto err_len;
00934 }
00935
00936 name = mem_heap_strdupl(heap, (const char*) field, len);
00937
00938 if (col_name) {
00939 *col_name = name;
00940 }
00941
00942 field = rec_get_nth_field_old(rec, 5, &len);
00943 if (UNIV_UNLIKELY(len != 4)) {
00944 goto err_len;
00945 }
00946
00947 mtype = mach_read_from_4(field);
00948
00949 field = rec_get_nth_field_old(rec, 6, &len);
00950 if (UNIV_UNLIKELY(len != 4)) {
00951 goto err_len;
00952 }
00953 prtype = mach_read_from_4(field);
00954
00955 if (dtype_get_charset_coll(prtype) == 0
00956 && dtype_is_string_type(mtype)) {
00957
00958
00959 if (dtype_is_binary_string_type(mtype, prtype)) {
00960
00961
00962
00963 prtype = dtype_form_prtype(
00964 prtype,
00965 DATA_MYSQL_BINARY_CHARSET_COLL);
00966 } else {
00967
00968
00969
00970 prtype = dtype_form_prtype(
00971 prtype,
00972 data_mysql_default_charset_coll);
00973 }
00974 }
00975
00976 field = rec_get_nth_field_old(rec, 7, &len);
00977 if (UNIV_UNLIKELY(len != 4)) {
00978 goto err_len;
00979 }
00980 col_len = mach_read_from_4(field);
00981 field = rec_get_nth_field_old(rec, 8, &len);
00982 if (UNIV_UNLIKELY(len != 4)) {
00983 goto err_len;
00984 }
00985
00986 if (!column) {
00987 dict_mem_table_add_col(table, heap, name, mtype,
00988 prtype, col_len);
00989 } else {
00990 dict_mem_fill_column_struct(column, pos, mtype,
00991 prtype, col_len);
00992 }
00993
00994 return(NULL);
00995 }
00996
00997
00999 static
01000 void
01001 dict_load_columns(
01002
01003 dict_table_t* table,
01004 mem_heap_t* heap)
01006 {
01007 dict_table_t* sys_columns;
01008 dict_index_t* sys_index;
01009 btr_pcur_t pcur;
01010 dtuple_t* tuple;
01011 dfield_t* dfield;
01012 const rec_t* rec;
01013 byte* buf;
01014 ulint i;
01015 mtr_t mtr;
01016
01017 ut_ad(mutex_own(&(dict_sys->mutex)));
01018
01019 mtr_start(&mtr);
01020
01021 sys_columns = dict_table_get_low("SYS_COLUMNS");
01022 sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
01023 ut_a(!dict_table_is_comp(sys_columns));
01024
01025 ut_a(name_of_col_is(sys_columns, sys_index, 4, "NAME"));
01026 ut_a(name_of_col_is(sys_columns, sys_index, 8, "PREC"));
01027
01028 tuple = dtuple_create(heap, 1);
01029 dfield = dtuple_get_nth_field(tuple, 0);
01030
01031 buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
01032 mach_write_to_8(buf, table->id);
01033
01034 dfield_set_data(dfield, buf, 8);
01035 dict_index_copy_types(tuple, sys_index, 1);
01036
01037 btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
01038 BTR_SEARCH_LEAF, &pcur, &mtr);
01039 for (i = 0; i + DATA_N_SYS_COLS < (ulint) table->n_cols; i++) {
01040 const char* err_msg;
01041
01042 rec = btr_pcur_get_rec(&pcur);
01043
01044 ut_a(btr_pcur_is_on_user_rec(&pcur));
01045
01046 err_msg = dict_load_column_low(table, heap, NULL, NULL,
01047 NULL, rec);
01048
01049 if (err_msg) {
01050 fprintf(stderr, "InnoDB: %s\n", err_msg);
01051 ut_error;
01052 }
01053
01054 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
01055 }
01056
01057 btr_pcur_close(&pcur);
01058 mtr_commit(&mtr);
01059 }
01060
01062 static const char* dict_load_field_del = "delete-marked record in SYS_FIELDS";
01063
01064
01068 UNIV_INTERN
01069 const char*
01070 dict_load_field_low(
01071
01072 byte* index_id,
01075 dict_index_t* index,
01079 dict_field_t* sys_field,
01081 ulint* pos,
01082 byte* last_index_id,
01083 mem_heap_t* heap,
01085 const rec_t* rec)
01086 {
01087 const byte* field;
01088 ulint len;
01089 ulint pos_and_prefix_len;
01090 ulint prefix_len;
01091 ibool first_field;
01092 ulint position;
01093
01094
01095 ut_a((!index) || (!sys_field));
01096
01097 if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
01098 return(dict_load_field_del);
01099 }
01100
01101 if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 5)) {
01102 return("wrong number of columns in SYS_FIELDS record");
01103 }
01104
01105 field = rec_get_nth_field_old(rec, 0, &len);
01106 if (UNIV_UNLIKELY(len != 8)) {
01107 err_len:
01108 return("incorrect column length in SYS_FIELDS");
01109 }
01110
01111 if (!index) {
01112 ut_a(last_index_id);
01113 memcpy(index_id, (const char*)field, 8);
01114 first_field = memcmp(index_id, last_index_id, 8);
01115 } else {
01116 first_field = (index->n_def == 0);
01117 if (memcmp(field, index_id, 8)) {
01118 return("SYS_FIELDS.INDEX_ID mismatch");
01119 }
01120 }
01121
01122 field = rec_get_nth_field_old(rec, 1, &len);
01123 if (UNIV_UNLIKELY(len != 4)) {
01124 goto err_len;
01125 }
01126
01127 rec_get_nth_field_offs_old(rec, 2, &len);
01128 if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
01129 goto err_len;
01130 }
01131 rec_get_nth_field_offs_old(rec, 3, &len);
01132 if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
01133 goto err_len;
01134 }
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144 pos_and_prefix_len = mach_read_from_4(field);
01145
01146 if (index && UNIV_UNLIKELY
01147 ((pos_and_prefix_len & 0xFFFFUL) != index->n_def
01148 && (pos_and_prefix_len >> 16 & 0xFFFF) != index->n_def)) {
01149 return("SYS_FIELDS.POS mismatch");
01150 }
01151
01152 if (first_field || pos_and_prefix_len > 0xFFFFUL) {
01153 prefix_len = pos_and_prefix_len & 0xFFFFUL;
01154 position = (pos_and_prefix_len & 0xFFFF0000UL) >> 16;
01155 } else {
01156 prefix_len = 0;
01157 position = pos_and_prefix_len & 0xFFFFUL;
01158 }
01159
01160 field = rec_get_nth_field_old(rec, 4, &len);
01161 if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
01162 goto err_len;
01163 }
01164
01165 if (index) {
01166 dict_mem_index_add_field(
01167 index, mem_heap_strdupl(heap, (const char*) field, len),
01168 prefix_len);
01169 } else {
01170 ut_a(sys_field);
01171 ut_a(pos);
01172
01173 sys_field->name = mem_heap_strdupl(
01174 heap, (const char*) field, len);
01175 sys_field->prefix_len = prefix_len;
01176 *pos = position;
01177 }
01178
01179 return(NULL);
01180 }
01181
01182
01185 static
01186 ulint
01187 dict_load_fields(
01188
01189 dict_index_t* index,
01190 mem_heap_t* heap)
01191 {
01192 dict_table_t* sys_fields;
01193 dict_index_t* sys_index;
01194 btr_pcur_t pcur;
01195 dtuple_t* tuple;
01196 dfield_t* dfield;
01197 const rec_t* rec;
01198 byte* buf;
01199 ulint i;
01200 mtr_t mtr;
01201 ulint error;
01202
01203 ut_ad(mutex_own(&(dict_sys->mutex)));
01204
01205 mtr_start(&mtr);
01206
01207 sys_fields = dict_table_get_low("SYS_FIELDS");
01208 sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
01209 ut_a(!dict_table_is_comp(sys_fields));
01210 ut_a(name_of_col_is(sys_fields, sys_index, 4, "COL_NAME"));
01211
01212 tuple = dtuple_create(heap, 1);
01213 dfield = dtuple_get_nth_field(tuple, 0);
01214
01215 buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
01216 mach_write_to_8(buf, index->id);
01217
01218 dfield_set_data(dfield, buf, 8);
01219 dict_index_copy_types(tuple, sys_index, 1);
01220
01221 btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
01222 BTR_SEARCH_LEAF, &pcur, &mtr);
01223 for (i = 0; i < index->n_fields; i++) {
01224 const char* err_msg;
01225
01226 rec = btr_pcur_get_rec(&pcur);
01227
01228 ut_a(btr_pcur_is_on_user_rec(&pcur));
01229
01230 err_msg = dict_load_field_low(buf, index, NULL, NULL, NULL,
01231 heap, rec);
01232
01233 if (err_msg == dict_load_field_del) {
01234
01235
01236
01237
01238 goto next_rec;
01239 } else if (err_msg) {
01240 fprintf(stderr, "InnoDB: %s\n", err_msg);
01241 error = DB_CORRUPTION;
01242 goto func_exit;
01243 }
01244 next_rec:
01245 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
01246 }
01247
01248 error = DB_SUCCESS;
01249 func_exit:
01250 btr_pcur_close(&pcur);
01251 mtr_commit(&mtr);
01252 return(error);
01253 }
01254
01256 static const char* dict_load_index_del = "delete-marked record in SYS_INDEXES";
01258 static const char* dict_load_index_id_err = "SYS_INDEXES.TABLE_ID mismatch";
01259
01260
01266 UNIV_INTERN
01267 const char*
01268 dict_load_index_low(
01269
01270 byte* table_id,
01273 const char* table_name,
01274 mem_heap_t* heap,
01275 const rec_t* rec,
01276 ibool allocate,
01279 dict_index_t** index)
01280 {
01281 const byte* field;
01282 ulint len;
01283 ulint name_len;
01284 char* name_buf;
01285 index_id_t id;
01286 ulint n_fields;
01287 ulint type;
01288 ulint space;
01289
01290 if (allocate) {
01291
01292
01293 *index = NULL;
01294 }
01295
01296 if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
01297 return(dict_load_index_del);
01298 }
01299
01300 if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 9)) {
01301 return("wrong number of columns in SYS_INDEXES record");
01302 }
01303
01304 field = rec_get_nth_field_old(rec, 0, &len);
01305 if (UNIV_UNLIKELY(len != 8)) {
01306 err_len:
01307 return("incorrect column length in SYS_INDEXES");
01308 }
01309
01310 if (!allocate) {
01311
01312 memcpy(table_id, (const char*)field, 8);
01313 } else if (memcmp(field, table_id, 8)) {
01314
01315
01316 return(dict_load_index_id_err);
01317 }
01318
01319 field = rec_get_nth_field_old(rec, 1, &len);
01320 if (UNIV_UNLIKELY(len != 8)) {
01321 goto err_len;
01322 }
01323
01324 id = mach_read_from_8(field);
01325
01326 rec_get_nth_field_offs_old(rec, 2, &len);
01327 if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
01328 goto err_len;
01329 }
01330 rec_get_nth_field_offs_old(rec, 3, &len);
01331 if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
01332 goto err_len;
01333 }
01334
01335 field = rec_get_nth_field_old(rec, 4, &name_len);
01336 if (UNIV_UNLIKELY(name_len == UNIV_SQL_NULL)) {
01337 goto err_len;
01338 }
01339
01340 name_buf = mem_heap_strdupl(heap, (const char*) field,
01341 name_len);
01342
01343 field = rec_get_nth_field_old(rec, 5, &len);
01344 if (UNIV_UNLIKELY(len != 4)) {
01345 goto err_len;
01346 }
01347 n_fields = mach_read_from_4(field);
01348
01349 field = rec_get_nth_field_old(rec, 6, &len);
01350 if (UNIV_UNLIKELY(len != 4)) {
01351 goto err_len;
01352 }
01353 type = mach_read_from_4(field);
01354
01355 field = rec_get_nth_field_old(rec, 7, &len);
01356 if (UNIV_UNLIKELY(len != 4)) {
01357 goto err_len;
01358 }
01359 space = mach_read_from_4(field);
01360
01361 field = rec_get_nth_field_old(rec, 8, &len);
01362 if (UNIV_UNLIKELY(len != 4)) {
01363 goto err_len;
01364 }
01365
01366 if (allocate) {
01367 *index = dict_mem_index_create(table_name, name_buf,
01368 space, type, n_fields);
01369 } else {
01370 ut_a(*index);
01371
01372 dict_mem_fill_index_struct(*index, NULL, NULL, name_buf,
01373 space, type, n_fields);
01374 }
01375
01376 (*index)->id = id;
01377 (*index)->page = mach_read_from_4(field);
01378 ut_ad((*index)->page);
01379
01380 return(NULL);
01381 }
01382
01383
01388 static
01389 ulint
01390 dict_load_indexes(
01391
01392 dict_table_t* table,
01393 mem_heap_t* heap)
01394 {
01395 dict_table_t* sys_indexes;
01396 dict_index_t* sys_index;
01397 btr_pcur_t pcur;
01398 dtuple_t* tuple;
01399 dfield_t* dfield;
01400 const rec_t* rec;
01401 byte* buf;
01402 mtr_t mtr;
01403 ulint error = DB_SUCCESS;
01404
01405 ut_ad(mutex_own(&(dict_sys->mutex)));
01406
01407 mtr_start(&mtr);
01408
01409 sys_indexes = dict_table_get_low("SYS_INDEXES");
01410 sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
01411 ut_a(!dict_table_is_comp(sys_indexes));
01412 ut_a(name_of_col_is(sys_indexes, sys_index, 4, "NAME"));
01413 ut_a(name_of_col_is(sys_indexes, sys_index, 8, "PAGE_NO"));
01414
01415 tuple = dtuple_create(heap, 1);
01416 dfield = dtuple_get_nth_field(tuple, 0);
01417
01418 buf = static_cast<unsigned char *>(mem_heap_alloc(heap, 8));
01419 mach_write_to_8(buf, table->id);
01420
01421 dfield_set_data(dfield, buf, 8);
01422 dict_index_copy_types(tuple, sys_index, 1);
01423
01424 btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
01425 BTR_SEARCH_LEAF, &pcur, &mtr);
01426 for (;;) {
01427 dict_index_t* index = NULL;
01428 const char* err_msg;
01429
01430 if (!btr_pcur_is_on_user_rec(&pcur)) {
01431
01432 break;
01433 }
01434
01435 rec = btr_pcur_get_rec(&pcur);
01436
01437 err_msg = dict_load_index_low(buf, table->name, heap, rec,
01438 TRUE, &index);
01439 ut_ad((index == NULL) == (err_msg != NULL));
01440
01441 if (err_msg == dict_load_index_id_err) {
01442
01443
01444 break;
01445 } else if (err_msg == dict_load_index_del) {
01446
01447 goto next_rec;
01448 } else if (err_msg) {
01449 fprintf(stderr, "InnoDB: %s\n", err_msg);
01450 error = DB_CORRUPTION;
01451 goto func_exit;
01452 }
01453
01454 ut_ad(index);
01455
01456
01457
01458 if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
01459
01460 fprintf(stderr,
01461 "InnoDB: Error: unknown type %lu"
01462 " of index %s of table %s\n",
01463 (ulong) index->type, index->name, table->name);
01464
01465 error = DB_UNSUPPORTED;
01466 dict_mem_index_free(index);
01467 goto func_exit;
01468 } else if (index->page == FIL_NULL) {
01469
01470 fprintf(stderr,
01471 "InnoDB: Error: trying to load index %s"
01472 " for table %s\n"
01473 "InnoDB: but the index tree has been freed!\n",
01474 index->name, table->name);
01475
01476 corrupted:
01477 dict_mem_index_free(index);
01478 error = DB_CORRUPTION;
01479 goto func_exit;
01480 } else if (!dict_index_is_clust(index)
01481 && NULL == dict_table_get_first_index(table)) {
01482
01483 fputs("InnoDB: Error: trying to load index ",
01484 stderr);
01485 ut_print_name(stderr, NULL, FALSE, index->name);
01486 fputs(" for table ", stderr);
01487 ut_print_name(stderr, NULL, TRUE, table->name);
01488 fputs("\nInnoDB: but the first index"
01489 " is not clustered!\n", stderr);
01490
01491 goto corrupted;
01492 } else if (table->id < DICT_HDR_FIRST_ID
01493 && (dict_index_is_clust(index)
01494 || ((table == dict_sys->sys_tables)
01495 && !strcmp("ID_IND", index->name)))) {
01496
01497
01498
01499 dict_mem_index_free(index);
01500 } else {
01501 dict_load_fields(index, heap);
01502 error = dict_index_add_to_cache(table, index,
01503 index->page, FALSE);
01504
01505
01506
01507
01508
01509 if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
01510
01511 goto func_exit;
01512 }
01513 }
01514
01515 next_rec:
01516 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
01517 }
01518
01519 func_exit:
01520 btr_pcur_close(&pcur);
01521 mtr_commit(&mtr);
01522
01523 return(error);
01524 }
01525
01526
01530 UNIV_INTERN
01531 const char*
01532 dict_load_table_low(
01533
01534 const char* name,
01535 const rec_t* rec,
01536 dict_table_t** table)
01537 {
01538 const byte* field;
01539 ulint len;
01540 ulint space;
01541 ulint n_cols;
01542 ulint flags;
01543
01544 if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) {
01545 return("delete-marked record in SYS_TABLES");
01546 }
01547
01548 if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != 10)) {
01549 return("wrong number of columns in SYS_TABLES record");
01550 }
01551
01552 rec_get_nth_field_offs_old(rec, 0, &len);
01553 if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) {
01554 err_len:
01555 return("incorrect column length in SYS_TABLES");
01556 }
01557 rec_get_nth_field_offs_old(rec, 1, &len);
01558 if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) {
01559 goto err_len;
01560 }
01561 rec_get_nth_field_offs_old(rec, 2, &len);
01562 if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) {
01563 goto err_len;
01564 }
01565
01566 rec_get_nth_field_offs_old(rec, 3, &len);
01567 if (UNIV_UNLIKELY(len != 8)) {
01568 goto err_len;
01569 }
01570
01571 field = rec_get_nth_field_old(rec, 4, &len);
01572 if (UNIV_UNLIKELY(len != 4)) {
01573 goto err_len;
01574 }
01575
01576 n_cols = mach_read_from_4(field);
01577
01578 rec_get_nth_field_offs_old(rec, 5, &len);
01579 if (UNIV_UNLIKELY(len != 4)) {
01580 goto err_len;
01581 }
01582
01583 rec_get_nth_field_offs_old(rec, 6, &len);
01584 if (UNIV_UNLIKELY(len != 8)) {
01585 goto err_len;
01586 }
01587
01588 rec_get_nth_field_offs_old(rec, 7, &len);
01589 if (UNIV_UNLIKELY(len != 4)) {
01590 goto err_len;
01591 }
01592
01593 rec_get_nth_field_offs_old(rec, 8, &len);
01594 if (UNIV_UNLIKELY(len != UNIV_SQL_NULL)) {
01595 goto err_len;
01596 }
01597
01598 field = rec_get_nth_field_old(rec, 9, &len);
01599
01600 if (UNIV_UNLIKELY(len != 4)) {
01601 goto err_len;
01602 }
01603
01604 space = mach_read_from_4(field);
01605
01606
01607 if (space != 0) {
01608 flags = dict_sys_tables_get_flags(rec);
01609
01610 if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
01611 field = rec_get_nth_field_old(rec, 5, &len);
01612 ut_ad(len == 4);
01613 flags = mach_read_from_4(field);
01614
01615 ut_print_timestamp(stderr);
01616 fputs(" InnoDB: Error: table ", stderr);
01617 ut_print_filename(stderr, name);
01618 fprintf(stderr, "\n"
01619 "InnoDB: in InnoDB data dictionary"
01620 " has unknown type %lx.\n",
01621 (ulong) flags);
01622 return(NULL);
01623 }
01624 } else {
01625 flags = 0;
01626 }
01627
01628
01629
01630 if (n_cols & 0x80000000UL) {
01631 ulint flags2;
01632
01633 flags |= DICT_TF_COMPACT;
01634
01635 field = rec_get_nth_field_old(rec, 7, &len);
01636
01637 if (UNIV_UNLIKELY(len != 4)) {
01638
01639 goto err_len;
01640 }
01641
01642 flags2 = mach_read_from_4(field);
01643
01644 if (flags2 & (SIZE_MAX << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
01645 ut_print_timestamp(stderr);
01646 fputs(" InnoDB: Warning: table ", stderr);
01647 ut_print_filename(stderr, name);
01648 fprintf(stderr, "\n"
01649 "InnoDB: in InnoDB data dictionary"
01650 " has unknown flags %lx.\n",
01651 (ulong) flags2);
01652
01653 flags2 &= ~(~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT));
01654 }
01655
01656 flags |= flags2 << DICT_TF2_SHIFT;
01657 }
01658
01659
01660 *table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,
01661 flags);
01662
01663 field = rec_get_nth_field_old(rec, 3, &len);
01664 ut_ad(len == 8);
01665
01666 (*table)->id = mach_read_from_8(field);
01667
01668 (*table)->ibd_file_missing = FALSE;
01669
01670 return(NULL);
01671 }
01672
01673
01682 UNIV_INTERN
01683 dict_table_t*
01684 dict_load_table(
01685
01686 const char* name,
01688 ibool cached)
01689 {
01690 dict_table_t* table;
01691 dict_table_t* sys_tables;
01692 btr_pcur_t pcur;
01693 dict_index_t* sys_index;
01694 dtuple_t* tuple;
01695 mem_heap_t* heap;
01696 dfield_t* dfield;
01697 const rec_t* rec;
01698 const byte* field;
01699 ulint len;
01700 ulint err;
01701 const char* err_msg;
01702 mtr_t mtr;
01703
01704 ut_ad(mutex_own(&(dict_sys->mutex)));
01705
01706 heap = mem_heap_create(32000);
01707
01708 mtr_start(&mtr);
01709
01710 sys_tables = dict_table_get_low("SYS_TABLES");
01711 sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
01712 ut_a(!dict_table_is_comp(sys_tables));
01713 ut_a(name_of_col_is(sys_tables, sys_index, 3, "ID"));
01714 ut_a(name_of_col_is(sys_tables, sys_index, 4, "N_COLS"));
01715 ut_a(name_of_col_is(sys_tables, sys_index, 5, "TYPE"));
01716 ut_a(name_of_col_is(sys_tables, sys_index, 7, "MIX_LEN"));
01717 ut_a(name_of_col_is(sys_tables, sys_index, 9, "SPACE"));
01718
01719 tuple = dtuple_create(heap, 1);
01720 dfield = dtuple_get_nth_field(tuple, 0);
01721
01722 dfield_set_data(dfield, name, ut_strlen(name));
01723 dict_index_copy_types(tuple, sys_index, 1);
01724
01725 btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
01726 BTR_SEARCH_LEAF, &pcur, &mtr);
01727 rec = btr_pcur_get_rec(&pcur);
01728
01729 if (!btr_pcur_is_on_user_rec(&pcur)
01730 || rec_get_deleted_flag(rec, 0)) {
01731
01732 err_exit:
01733 btr_pcur_close(&pcur);
01734 mtr_commit(&mtr);
01735 mem_heap_free(heap);
01736
01737 return(NULL);
01738 }
01739
01740 field = rec_get_nth_field_old(rec, 0, &len);
01741
01742
01743 if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
01744
01745 goto err_exit;
01746 }
01747
01748 err_msg = dict_load_table_low(name, rec, &table);
01749
01750 if (err_msg) {
01751
01752 ut_print_timestamp(stderr);
01753 fprintf(stderr, " InnoDB: %s\n", err_msg);
01754 goto err_exit;
01755 }
01756
01757 if (table->space == 0) {
01758
01759 } else if (!fil_space_for_table_exists_in_mem(
01760 table->space, name,
01761 (table->flags >> DICT_TF2_SHIFT)
01762 & DICT_TF2_TEMPORARY,
01763 FALSE, FALSE)) {
01764
01765 if (table->flags & (DICT_TF2_TEMPORARY << DICT_TF2_SHIFT)) {
01766
01767 table->ibd_file_missing = TRUE;
01768 } else {
01769 ut_print_timestamp(stderr);
01770 fprintf(stderr,
01771 " InnoDB: error: space object of table ");
01772 ut_print_filename(stderr, name);
01773 fprintf(stderr, ",\n"
01774 "InnoDB: space id %lu did not exist in memory."
01775 " Retrying an open.\n",
01776 (ulong) table->space);
01777
01778 if (!fil_open_single_table_tablespace(
01779 TRUE, table->space,
01780 table->flags == DICT_TF_COMPACT ? 0 :
01781 table->flags & ~(~0 << DICT_TF_BITS), name)) {
01782
01783
01784
01785 table->ibd_file_missing = TRUE;
01786 }
01787 }
01788 }
01789
01790 btr_pcur_close(&pcur);
01791 mtr_commit(&mtr);
01792
01793 dict_load_columns(table, heap);
01794
01795 if (cached) {
01796 dict_table_add_to_cache(table, heap);
01797 } else {
01798 dict_table_add_system_columns(table, heap);
01799 }
01800
01801 mem_heap_empty(heap);
01802
01803 err = dict_load_indexes(table, heap);
01804
01805
01806
01807 table->fk_max_recusive_level = 0;
01808
01809
01810
01811
01812
01813 if (!cached) {
01814 } else if (err == DB_SUCCESS) {
01815 err = dict_load_foreigns(table->name, TRUE, TRUE);
01816
01817 if (err != DB_SUCCESS) {
01818 dict_table_remove_from_cache(table);
01819 table = NULL;
01820 } else {
01821 table->fk_max_recusive_level = 0;
01822 }
01823 } else if (!srv_force_recovery) {
01824 dict_table_remove_from_cache(table);
01825 table = NULL;
01826 }
01827 #if 0
01828 if (err != DB_SUCCESS && table != NULL) {
01829
01830 mutex_enter(&dict_foreign_err_mutex);
01831
01832 ut_print_timestamp(stderr);
01833
01834 fprintf(stderr,
01835 " InnoDB: Error: could not make a foreign key"
01836 " definition to match\n"
01837 "InnoDB: the foreign key table"
01838 " or the referenced table!\n"
01839 "InnoDB: The data dictionary of InnoDB is corrupt."
01840 " You may need to drop\n"
01841 "InnoDB: and recreate the foreign key table"
01842 " or the referenced table.\n"
01843 "InnoDB: Submit a detailed bug report"
01844 " to http://bugs.mysql.com\n"
01845 "InnoDB: Latest foreign key error printout:\n%s\n",
01846 dict_foreign_err_buf);
01847
01848 mutex_exit(&dict_foreign_err_mutex);
01849 }
01850 #endif
01851 mem_heap_free(heap);
01852
01853 return(table);
01854 }
01855
01856
01859 UNIV_INTERN
01860 dict_table_t*
01861 dict_load_table_on_id(
01862
01863 table_id_t table_id)
01864 {
01865 byte id_buf[8];
01866 btr_pcur_t pcur;
01867 mem_heap_t* heap;
01868 dtuple_t* tuple;
01869 dfield_t* dfield;
01870 dict_index_t* sys_table_ids;
01871 dict_table_t* sys_tables;
01872 const rec_t* rec;
01873 const byte* field;
01874 ulint len;
01875 dict_table_t* table;
01876 mtr_t mtr;
01877
01878 ut_ad(mutex_own(&(dict_sys->mutex)));
01879
01880 table = NULL;
01881
01882
01883
01884
01885
01886 mtr_start(&mtr);
01887
01888
01889 sys_tables = dict_sys->sys_tables;
01890 sys_table_ids = dict_table_get_next_index(
01891 dict_table_get_first_index(sys_tables));
01892 ut_a(!dict_table_is_comp(sys_tables));
01893 heap = mem_heap_create(256);
01894
01895 tuple = dtuple_create(heap, 1);
01896 dfield = dtuple_get_nth_field(tuple, 0);
01897
01898
01899 mach_write_to_8(id_buf, table_id);
01900
01901 dfield_set_data(dfield, id_buf, 8);
01902 dict_index_copy_types(tuple, sys_table_ids, 1);
01903
01904 btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE,
01905 BTR_SEARCH_LEAF, &pcur, &mtr);
01906 rec = btr_pcur_get_rec(&pcur);
01907
01908 if (!btr_pcur_is_on_user_rec(&pcur)) {
01909
01910 goto func_exit;
01911 }
01912
01913
01914 while (rec_get_deleted_flag(rec, 0)) {
01915 if (!btr_pcur_move_to_next_user_rec(&pcur, &mtr)) {
01916 goto func_exit;
01917 }
01918 rec = btr_pcur_get_rec(&pcur);
01919 }
01920
01921
01922
01923
01924
01925 rec = btr_pcur_get_rec(&pcur);
01926 field = rec_get_nth_field_old(rec, 0, &len);
01927 ut_ad(len == 8);
01928
01929
01930 if (table_id != mach_read_from_8(field)) {
01931 goto func_exit;
01932 }
01933
01934
01935 field = rec_get_nth_field_old(rec, 1, &len);
01936
01937 table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len),
01938 TRUE);
01939 func_exit:
01940 btr_pcur_close(&pcur);
01941 mtr_commit(&mtr);
01942 mem_heap_free(heap);
01943
01944 return(table);
01945 }
01946
01947
01951 UNIV_INTERN
01952 void
01953 dict_load_sys_table(
01954
01955 dict_table_t* table)
01956 {
01957 mem_heap_t* heap;
01958
01959 ut_ad(mutex_own(&(dict_sys->mutex)));
01960
01961 heap = mem_heap_create(1000);
01962
01963 dict_load_indexes(table, heap);
01964
01965 mem_heap_free(heap);
01966 }
01967
01968
01970 static
01971 void
01972 dict_load_foreign_cols(
01973
01974 const char* id,
01976 dict_foreign_t* foreign)
01977 {
01978 dict_table_t* sys_foreign_cols;
01979 dict_index_t* sys_index;
01980 btr_pcur_t pcur;
01981 dtuple_t* tuple;
01982 dfield_t* dfield;
01983 const rec_t* rec;
01984 const byte* field;
01985 ulint len;
01986 ulint i;
01987 mtr_t mtr;
01988
01989 ut_ad(mutex_own(&(dict_sys->mutex)));
01990
01991 foreign->foreign_col_names = static_cast<const char **>(mem_heap_alloc(
01992 foreign->heap, foreign->n_fields * sizeof(void*)));
01993
01994 foreign->referenced_col_names = static_cast<const char **>(mem_heap_alloc(
01995 foreign->heap, foreign->n_fields * sizeof(void*)));
01996 mtr_start(&mtr);
01997
01998 sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
01999 sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
02000 ut_a(!dict_table_is_comp(sys_foreign_cols));
02001
02002 tuple = dtuple_create(foreign->heap, 1);
02003 dfield = dtuple_get_nth_field(tuple, 0);
02004
02005 dfield_set_data(dfield, id, ut_strlen(id));
02006 dict_index_copy_types(tuple, sys_index, 1);
02007
02008 btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
02009 BTR_SEARCH_LEAF, &pcur, &mtr);
02010 for (i = 0; i < foreign->n_fields; i++) {
02011
02012 rec = btr_pcur_get_rec(&pcur);
02013
02014 ut_a(btr_pcur_is_on_user_rec(&pcur));
02015 ut_a(!rec_get_deleted_flag(rec, 0));
02016
02017 field = rec_get_nth_field_old(rec, 0, &len);
02018 ut_a(len == ut_strlen(id));
02019 ut_a(ut_memcmp(id, field, len) == 0);
02020
02021 field = rec_get_nth_field_old(rec, 1, &len);
02022 ut_a(len == 4);
02023 ut_a(i == mach_read_from_4(field));
02024
02025 field = rec_get_nth_field_old(rec, 4, &len);
02026 foreign->foreign_col_names[i] = mem_heap_strdupl(
02027 foreign->heap, (char*) field, len);
02028
02029 field = rec_get_nth_field_old(rec, 5, &len);
02030 foreign->referenced_col_names[i] = mem_heap_strdupl(
02031 foreign->heap, (char*) field, len);
02032
02033 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
02034 }
02035
02036 btr_pcur_close(&pcur);
02037 mtr_commit(&mtr);
02038 }
02039
02040
02043 static
02044 ulint
02045 dict_load_foreign(
02046
02047 const char* id,
02049 ibool check_charsets,
02051 ibool check_recursive)
02055 {
02056 dict_foreign_t* foreign;
02057 dict_table_t* sys_foreign;
02058 btr_pcur_t pcur;
02059 dict_index_t* sys_index;
02060 dtuple_t* tuple;
02061 mem_heap_t* heap2;
02062 dfield_t* dfield;
02063 const rec_t* rec;
02064 const byte* field;
02065 ulint len;
02066 ulint n_fields_and_type;
02067 mtr_t mtr;
02068 dict_table_t* for_table;
02069 dict_table_t* ref_table;
02070
02071 ut_ad(mutex_own(&(dict_sys->mutex)));
02072
02073 heap2 = mem_heap_create(1000);
02074
02075 mtr_start(&mtr);
02076
02077 sys_foreign = dict_table_get_low("SYS_FOREIGN");
02078 sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
02079 ut_a(!dict_table_is_comp(sys_foreign));
02080
02081 tuple = dtuple_create(heap2, 1);
02082 dfield = dtuple_get_nth_field(tuple, 0);
02083
02084 dfield_set_data(dfield, id, ut_strlen(id));
02085 dict_index_copy_types(tuple, sys_index, 1);
02086
02087 btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
02088 BTR_SEARCH_LEAF, &pcur, &mtr);
02089 rec = btr_pcur_get_rec(&pcur);
02090
02091 if (!btr_pcur_is_on_user_rec(&pcur)
02092 || rec_get_deleted_flag(rec, 0)) {
02093
02094
02095 fprintf(stderr,
02096 "InnoDB: Error A: cannot load foreign constraint %s\n",
02097 id);
02098
02099 btr_pcur_close(&pcur);
02100 mtr_commit(&mtr);
02101 mem_heap_free(heap2);
02102
02103 return(DB_ERROR);
02104 }
02105
02106 field = rec_get_nth_field_old(rec, 0, &len);
02107
02108
02109 if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
02110
02111 fprintf(stderr,
02112 "InnoDB: Error B: cannot load foreign constraint %s\n",
02113 id);
02114
02115 btr_pcur_close(&pcur);
02116 mtr_commit(&mtr);
02117 mem_heap_free(heap2);
02118
02119 return(DB_ERROR);
02120 }
02121
02122
02123
02124
02125 mem_heap_free(heap2);
02126
02127 foreign = dict_mem_foreign_create();
02128
02129 n_fields_and_type = mach_read_from_4(
02130 rec_get_nth_field_old(rec, 5, &len));
02131
02132 ut_a(len == 4);
02133
02134
02135
02136 foreign->type = (unsigned int) (n_fields_and_type >> 24);
02137 foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
02138
02139 foreign->id = mem_heap_strdup(foreign->heap, id);
02140
02141 field = rec_get_nth_field_old(rec, 3, &len);
02142 foreign->foreign_table_name = mem_heap_strdupl(
02143 foreign->heap, (char*) field, len);
02144
02145 field = rec_get_nth_field_old(rec, 4, &len);
02146 foreign->referenced_table_name = mem_heap_strdupl(
02147 foreign->heap, (char*) field, len);
02148
02149 btr_pcur_close(&pcur);
02150 mtr_commit(&mtr);
02151
02152 dict_load_foreign_cols(id, foreign);
02153
02154 ref_table = dict_table_check_if_in_cache_low(
02155 foreign->referenced_table_name);
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181 if (!ref_table
02182 || ref_table->fk_max_recusive_level < DICT_FK_MAX_RECURSIVE_LOAD) {
02183
02184
02185
02186
02187
02188 for_table = dict_table_get_low(foreign->foreign_table_name);
02189
02190 if (for_table && ref_table && check_recursive) {
02191
02192
02193
02194
02195 if (ref_table->fk_max_recusive_level
02196 >= for_table->fk_max_recusive_level) {
02197 for_table->fk_max_recusive_level =
02198 ref_table->fk_max_recusive_level + 1;
02199 }
02200 }
02201 }
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211 return(dict_foreign_add_to_cache(foreign, check_charsets));
02212 }
02213
02214
02221 UNIV_INTERN
02222 ulint
02223 dict_load_foreigns(
02224
02225 const char* table_name,
02226 ibool check_recursive,
02228 ibool check_charsets)
02230 {
02231 btr_pcur_t pcur;
02232 mem_heap_t* heap;
02233 dtuple_t* tuple;
02234 dfield_t* dfield;
02235 dict_index_t* sec_index;
02236 dict_table_t* sys_foreign;
02237 const rec_t* rec;
02238 const byte* field;
02239 ulint len;
02240 char* id ;
02241 ulint err;
02242 mtr_t mtr;
02243
02244 ut_ad(mutex_own(&(dict_sys->mutex)));
02245
02246 sys_foreign = dict_table_get_low("SYS_FOREIGN");
02247
02248 if (sys_foreign == NULL) {
02249
02250
02251 fprintf(stderr,
02252 "InnoDB: Error: no foreign key system tables"
02253 " in the database\n");
02254
02255 return(DB_ERROR);
02256 }
02257
02258 ut_a(!dict_table_is_comp(sys_foreign));
02259 mtr_start(&mtr);
02260
02261
02262
02263
02264 sec_index = dict_table_get_next_index(
02265 dict_table_get_first_index(sys_foreign));
02266 start_load:
02267 heap = mem_heap_create(256);
02268
02269 tuple = dtuple_create(heap, 1);
02270 dfield = dtuple_get_nth_field(tuple, 0);
02271
02272 dfield_set_data(dfield, table_name, ut_strlen(table_name));
02273 dict_index_copy_types(tuple, sec_index, 1);
02274
02275 btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE,
02276 BTR_SEARCH_LEAF, &pcur, &mtr);
02277 loop:
02278 rec = btr_pcur_get_rec(&pcur);
02279
02280 if (!btr_pcur_is_on_user_rec(&pcur)) {
02281
02282
02283 goto load_next_index;
02284 }
02285
02286
02287
02288
02289 rec = btr_pcur_get_rec(&pcur);
02290 field = rec_get_nth_field_old(rec, 0, &len);
02291
02292
02293
02294
02295
02296 if (0 != cmp_data_data(dfield_get_type(dfield)->mtype,
02297 dfield_get_type(dfield)->prtype,
02298 static_cast<const unsigned char *>(dfield_get_data(dfield)),
02299 dfield_get_len(dfield),
02300 field, len)) {
02301
02302 goto load_next_index;
02303 }
02304
02305
02306
02307
02308
02309
02310 if (0 != ut_memcmp(field, table_name, len)) {
02311
02312 goto next_rec;
02313 }
02314
02315 if (rec_get_deleted_flag(rec, 0)) {
02316
02317 goto next_rec;
02318 }
02319
02320
02321 field = rec_get_nth_field_old(rec, 1, &len);
02322 id = mem_heap_strdupl(heap, (char*) field, len);
02323
02324 btr_pcur_store_position(&pcur, &mtr);
02325
02326 mtr_commit(&mtr);
02327
02328
02329
02330 err = dict_load_foreign(id, check_charsets, check_recursive);
02331
02332 if (err != DB_SUCCESS) {
02333 btr_pcur_close(&pcur);
02334 mem_heap_free(heap);
02335
02336 return(err);
02337 }
02338
02339 mtr_start(&mtr);
02340
02341 btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
02342 next_rec:
02343 btr_pcur_move_to_next_user_rec(&pcur, &mtr);
02344
02345 goto loop;
02346
02347 load_next_index:
02348 btr_pcur_close(&pcur);
02349 mtr_commit(&mtr);
02350 mem_heap_free(heap);
02351
02352 sec_index = dict_table_get_next_index(sec_index);
02353
02354 if (sec_index != NULL) {
02355
02356 mtr_start(&mtr);
02357
02358
02359
02360
02361 check_recursive = FALSE;
02362
02363 goto start_load;
02364 }
02365
02366 return(DB_SUCCESS);
02367 }