📄 dict0load.c
字号:
{ byte id_buf[8]; btr_pcur_t pcur; mem_heap_t* heap; dtuple_t* tuple; dfield_t* dfield; dict_index_t* sys_table_ids; dict_table_t* sys_tables; rec_t* rec; byte* field; ulint len; dict_table_t* table; mtr_t mtr; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ /* NOTE that the operation of this function is protected by the dictionary mutex, and therefore no deadlocks can occur with other dictionary operations. */ mtr_start(&mtr); /*---------------------------------------------------*/ /* Get the secondary index based on ID for table SYS_TABLES */ sys_tables = dict_sys->sys_tables; sys_table_ids = dict_table_get_next_index( dict_table_get_first_index(sys_tables)); ut_a(!sys_tables->comp); heap = mem_heap_create(256); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); /* Write the table id in byte format to id_buf */ mach_write_to_8(id_buf, table_id); dfield_set_data(dfield, id_buf, 8); dict_index_copy_types(tuple, sys_table_ids, 1); btr_pcur_open_on_user_rec(sys_table_ids, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); rec = btr_pcur_get_rec(&pcur); if (!btr_pcur_is_on_user_rec(&pcur, &mtr) || rec_get_deleted_flag(rec, sys_tables->comp)) { /* Not found */ btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); return(NULL); } /*---------------------------------------------------*/ /* Now we have the record in the secondary index containing the table ID and NAME */ rec = btr_pcur_get_rec(&pcur); field = rec_get_nth_field_old(rec, 0, &len); ut_ad(len == 8); /* Check if the table id in record is the one searched for */ if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) { btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); return(NULL); } /* Now we get the table name from the record */ field = rec_get_nth_field_old(rec, 1, &len); /* Load the table definition to memory */ table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len)); btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); return(table);}/************************************************************************This function is called when the database is booted. Loads system tableindex definitions except for the clustered index which is added to thedictionary cache at booting before calling this function. */voiddict_load_sys_table(/*================*/ dict_table_t* table) /* in: system table */{ mem_heap_t* heap;#ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ heap = mem_heap_create(1000); dict_load_indexes(table, heap); mem_heap_free(heap);}/************************************************************************Loads foreign key constraint col names (also for the referenced table). */staticvoiddict_load_foreign_cols(/*===================*/ const char* id, /* in: foreign constraint id as a null- terminated string */ dict_foreign_t* foreign)/* in: foreign constraint object */{ dict_table_t* sys_foreign_cols; dict_index_t* sys_index; btr_pcur_t pcur; dtuple_t* tuple; dfield_t* dfield; rec_t* rec; byte* field; ulint len; ulint i; mtr_t mtr; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ foreign->foreign_col_names = mem_heap_alloc(foreign->heap, foreign->n_fields * sizeof(void*)); foreign->referenced_col_names = mem_heap_alloc(foreign->heap, foreign->n_fields * sizeof(void*)); mtr_start(&mtr); sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS"); sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes); ut_a(!sys_foreign_cols->comp); tuple = dtuple_create(foreign->heap, 1); dfield = dtuple_get_nth_field(tuple, 0); dfield_set_data(dfield, id, ut_strlen(id)); dict_index_copy_types(tuple, sys_index, 1); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); for (i = 0; i < foreign->n_fields; i++) { rec = btr_pcur_get_rec(&pcur); ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); ut_a(!rec_get_deleted_flag(rec, sys_foreign_cols->comp)); field = rec_get_nth_field_old(rec, 0, &len); ut_a(len == ut_strlen(id)); ut_a(ut_memcmp(id, field, len) == 0); field = rec_get_nth_field_old(rec, 1, &len); ut_a(len == 4); ut_a(i == mach_read_from_4(field)); field = rec_get_nth_field_old(rec, 4, &len); foreign->foreign_col_names[i] = mem_heap_strdupl(foreign->heap, (char*) field, len); field = rec_get_nth_field_old(rec, 5, &len); foreign->referenced_col_names[i] = mem_heap_strdupl(foreign->heap, (char*) field, len); btr_pcur_move_to_next_user_rec(&pcur, &mtr); } btr_pcur_close(&pcur); mtr_commit(&mtr);}/***************************************************************************Loads a foreign key constraint to the dictionary cache. */staticulintdict_load_foreign(/*==============*/ /* out: DB_SUCCESS or error code */ const char* id, /* in: foreign constraint id as a null-terminated string */ ibool check_charsets)/* in: TRUE=check charset compatibility */{ dict_foreign_t* foreign; dict_table_t* sys_foreign; btr_pcur_t pcur; dict_index_t* sys_index; dtuple_t* tuple; mem_heap_t* heap2; dfield_t* dfield; rec_t* rec; byte* field; ulint len; mtr_t mtr; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ heap2 = mem_heap_create(1000); mtr_start(&mtr); sys_foreign = dict_table_get_low("SYS_FOREIGN"); sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes); ut_a(!sys_foreign->comp); tuple = dtuple_create(heap2, 1); dfield = dtuple_get_nth_field(tuple, 0); dfield_set_data(dfield, id, ut_strlen(id)); dict_index_copy_types(tuple, sys_index, 1); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); rec = btr_pcur_get_rec(&pcur); if (!btr_pcur_is_on_user_rec(&pcur, &mtr) || rec_get_deleted_flag(rec, sys_foreign->comp)) { /* Not found */ fprintf(stderr, "InnoDB: Error A: cannot load foreign constraint %s\n", id); btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap2); return(DB_ERROR); } field = rec_get_nth_field_old(rec, 0, &len); /* Check if the id in record is the searched one */ if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) { fprintf(stderr, "InnoDB: Error B: cannot load foreign constraint %s\n", id); btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap2); return(DB_ERROR); } /* Read the table names and the number of columns associated with the constraint */ mem_heap_free(heap2); foreign = dict_mem_foreign_create(); foreign->n_fields = mach_read_from_4(rec_get_nth_field_old(rec, 5, &len)); ut_a(len == 4); /* We store the type to the bits 24-31 of n_fields */ foreign->type = foreign->n_fields >> 24; foreign->n_fields = foreign->n_fields & 0xFFFFFFUL; foreign->id = mem_heap_strdup(foreign->heap, id); field = rec_get_nth_field_old(rec, 3, &len); foreign->foreign_table_name = mem_heap_strdupl(foreign->heap, (char*) field, len); field = rec_get_nth_field_old(rec, 4, &len); foreign->referenced_table_name = mem_heap_strdupl(foreign->heap, (char*) field, len); btr_pcur_close(&pcur); mtr_commit(&mtr); dict_load_foreign_cols(id, foreign); /* If the foreign table is not yet in the dictionary cache, we have to load it so that we are able to make type comparisons in the next function call. */ dict_table_get_low(foreign->foreign_table_name); /* Note that there may already be a foreign constraint object in the dictionary cache for this constraint: then the following call only sets the pointers in it to point to the appropriate table and index objects and frees the newly created object foreign. Adding to the cache should always succeed since we are not creating a new foreign key constraint but loading one from the data dictionary. */ return(dict_foreign_add_to_cache(foreign, check_charsets));}/***************************************************************************Loads foreign key constraints where the table is either the foreign keyholder or where the table is referenced by a foreign key. Adds theseconstraints to the data dictionary. Note that we know that the dictionarycache already contains all constraints where the other relevant table isalready in the dictionary cache. */ulintdict_load_foreigns(/*===============*/ /* out: DB_SUCCESS or error code */ const char* table_name, /* in: table name */ ibool check_charsets) /* in: TRUE=check charset compatibility */{ btr_pcur_t pcur; mem_heap_t* heap; dtuple_t* tuple; dfield_t* dfield; dict_index_t* sec_index; dict_table_t* sys_foreign; rec_t* rec; byte* field; ulint len; char* id ; ulint err; mtr_t mtr; #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */ sys_foreign = dict_table_get_low("SYS_FOREIGN"); if (sys_foreign == NULL) { /* No foreign keys defined yet in this database */ fprintf(stderr, "InnoDB: Error: no foreign key system tables in the database\n"); return(DB_ERROR); } ut_a(!sys_foreign->comp); mtr_start(&mtr); /* Get the secondary index based on FOR_NAME from table SYS_FOREIGN */ sec_index = dict_table_get_next_index( dict_table_get_first_index(sys_foreign));start_load: heap = mem_heap_create(256); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); dfield_set_data(dfield, table_name, ut_strlen(table_name)); dict_index_copy_types(tuple, sec_index, 1); btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);loop: rec = btr_pcur_get_rec(&pcur); if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { /* End of index */ goto load_next_index; } /* Now we have the record in the secondary index containing a table name and a foreign constraint ID */ rec = btr_pcur_get_rec(&pcur); field = rec_get_nth_field_old(rec, 0, &len); /* Check if the table name in the record is the one searched for; the following call does the comparison in the latin1_swedish_ci charset-collation, in a case-insensitive way. */ if (0 != cmp_data_data(dfield_get_type(dfield), dfield_get_data(dfield), dfield_get_len(dfield), field, len)) { goto load_next_index; } /* Since table names in SYS_FOREIGN are stored in a case-insensitive order, we have to check that the table name matches also in a binary string comparison. On Unix, MySQL allows table names that only differ in character case. */ if (0 != ut_memcmp(field, table_name, len)) { goto next_rec; } if (rec_get_deleted_flag(rec, sys_foreign->comp)) { goto next_rec; } /* Now we get a foreign key constraint id */ field = rec_get_nth_field_old(rec, 1, &len); id = mem_heap_strdupl(heap, (char*) field, len); btr_pcur_store_position(&pcur, &mtr); mtr_commit(&mtr); /* Load the foreign constraint definition to the dictionary cache */ err = dict_load_foreign(id, check_charsets); if (err != DB_SUCCESS) { btr_pcur_close(&pcur); mem_heap_free(heap); return(err); } mtr_start(&mtr); btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);next_rec: btr_pcur_move_to_next_user_rec(&pcur, &mtr); goto loop;load_next_index: btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); sec_index = dict_table_get_next_index(sec_index); if (sec_index != NULL) { mtr_start(&mtr); goto start_load; } return(DB_SUCCESS);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -