diff options
Diffstat (limited to 'innobase/dict/dict0load.c')
-rw-r--r-- | innobase/dict/dict0load.c | 711 |
1 files changed, 362 insertions, 349 deletions
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index 221a6c7dabb..e9caa37fecc 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -21,33 +21,6 @@ Created 4/24/1996 Heikki Tuuri #include "dict0boot.h" /************************************************************************ -Loads definitions for table columns. */ -static -void -dict_load_columns( -/*==============*/ - dict_table_t* table, /* in: table */ - mem_heap_t* heap); /* in: memory heap for temporary storage */ -/************************************************************************ -Loads definitions for table indexes. */ -static -void -dict_load_indexes( -/*==============*/ - dict_table_t* table, /* in: table */ - mem_heap_t* heap); /* in: memory heap for temporary storage */ -/************************************************************************ -Loads definitions for index fields. */ -static -void -dict_load_fields( -/*=============*/ - dict_table_t* table, /* in: table */ - dict_index_t* index, /* in: index whose fields to load */ - mem_heap_t* heap); /* in: memory heap for temporary storage */ - - -/************************************************************************ Finds the first table name in the given database. */ char* @@ -194,7 +167,12 @@ loop: fprintf(stderr, "InnoDB: Failed to load table %s\n", table_name); } else { - dict_update_statistics_low(table, TRUE); + /* The table definition was corrupt if there + is no index */ + + if (dict_table_get_first_index(table)) { + dict_update_statistics_low(table, TRUE); + } dict_table_print_low(table); } @@ -208,6 +186,361 @@ loop: } /************************************************************************ +Loads definitions for table columns. */ +static +void +dict_load_columns( +/*==============*/ + dict_table_t* table, /* in: table */ + mem_heap_t* heap) /* in: memory heap for temporary storage */ +{ + dict_table_t* sys_columns; + dict_index_t* sys_index; + btr_pcur_t pcur; + dtuple_t* tuple; + dfield_t* dfield; + rec_t* rec; + byte* field; + ulint len; + byte* buf; + char* name_buf; + char* name; + ulint mtype; + ulint prtype; + ulint col_len; + ulint prec; + ulint i; + mtr_t mtr; + + ut_ad(mutex_own(&(dict_sys->mutex))); + + mtr_start(&mtr); + + sys_columns = dict_table_get_low((char*) "SYS_COLUMNS"); + sys_index = UT_LIST_GET_FIRST(sys_columns->indexes); + + tuple = dtuple_create(heap, 1); + dfield = dtuple_get_nth_field(tuple, 0); + + buf = mem_heap_alloc(heap, 8); + mach_write_to_8(buf, table->id); + + dfield_set_data(dfield, buf, 8); + 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 < table->n_cols - DATA_N_SYS_COLS; i++) { + + rec = btr_pcur_get_rec(&pcur); + + ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); + + ut_a(!rec_get_deleted_flag(rec)); + + field = rec_get_nth_field(rec, 0, &len); + ut_ad(len == 8); + ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0); + + field = rec_get_nth_field(rec, 1, &len); + ut_ad(len == 4); + ut_a(i == mach_read_from_4(field)); + + ut_a(0 == ut_strcmp((char*) "NAME", + dict_field_get_col( + dict_index_get_nth_field( + dict_table_get_first_index(sys_columns), 4))->name)); + + field = rec_get_nth_field(rec, 4, &len); + + name_buf = mem_heap_alloc(heap, len + 1); + ut_memcpy(name_buf, field, len); + name_buf[len] = '\0'; + + name = name_buf; + + field = rec_get_nth_field(rec, 5, &len); + mtype = mach_read_from_4(field); + + field = rec_get_nth_field(rec, 6, &len); + prtype = mach_read_from_4(field); + + field = rec_get_nth_field(rec, 7, &len); + col_len = mach_read_from_4(field); + + ut_a(0 == ut_strcmp((char*) "PREC", + dict_field_get_col( + dict_index_get_nth_field( + dict_table_get_first_index(sys_columns), 8))->name)); + + field = rec_get_nth_field(rec, 8, &len); + prec = mach_read_from_4(field); + + dict_mem_table_add_col(table, name, mtype, prtype, col_len, + prec); + btr_pcur_move_to_next_user_rec(&pcur, &mtr); + } + + btr_pcur_close(&pcur); + mtr_commit(&mtr); +} + +/************************************************************************ +Loads definitions for index fields. */ +static +void +dict_load_fields( +/*=============*/ + dict_table_t* table, /* in: table */ + dict_index_t* index, /* in: index whose fields to load */ + mem_heap_t* heap) /* in: memory heap for temporary storage */ +{ + dict_table_t* sys_fields; + dict_index_t* sys_index; + btr_pcur_t pcur; + dtuple_t* tuple; + dfield_t* dfield; + char* col_name; + rec_t* rec; + byte* field; + ulint len; + byte* buf; + ulint i; + mtr_t mtr; + + ut_ad(mutex_own(&(dict_sys->mutex))); + + UT_NOT_USED(table); + + mtr_start(&mtr); + + sys_fields = dict_table_get_low((char*) "SYS_FIELDS"); + sys_index = UT_LIST_GET_FIRST(sys_fields->indexes); + + tuple = dtuple_create(heap, 1); + dfield = dtuple_get_nth_field(tuple, 0); + + buf = mem_heap_alloc(heap, 8); + mach_write_to_8(buf, index->id); + + dfield_set_data(dfield, buf, 8); + 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 < index->n_fields; i++) { + + rec = btr_pcur_get_rec(&pcur); + + ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); + if (rec_get_deleted_flag(rec)) { + fprintf(stderr, +"InnoDB: Error: data dictionary entry for table %s is corrupt!\n", +"InnoDB: An index field is delete marked.\n", + table->name); + } + + field = rec_get_nth_field(rec, 0, &len); + ut_ad(len == 8); + ut_a(ut_memcmp(buf, field, len) == 0); + + field = rec_get_nth_field(rec, 1, &len); + ut_ad(len == 4); + ut_a(i == mach_read_from_4(field)); + + ut_a(0 == ut_strcmp((char*) "COL_NAME", + dict_field_get_col( + dict_index_get_nth_field( + dict_table_get_first_index(sys_fields), 4))->name)); + + field = rec_get_nth_field(rec, 4, &len); + + col_name = mem_heap_alloc(heap, len + 1); + ut_memcpy(col_name, field, len); + col_name[len] = '\0'; + + dict_mem_index_add_field(index, col_name, 0); + + btr_pcur_move_to_next_user_rec(&pcur, &mtr); + } + + btr_pcur_close(&pcur); + mtr_commit(&mtr); +} + +/************************************************************************ +Loads definitions for table indexes. Adds them to the data dictionary +cache. */ +static +ibool +dict_load_indexes( +/*==============*/ + /* out: TRUE if ok, FALSE if corruption + of dictionary table */ + dict_table_t* table, /* in: table */ + mem_heap_t* heap) /* in: memory heap for temporary storage */ +{ + dict_table_t* sys_indexes; + dict_index_t* sys_index; + dict_index_t* index; + btr_pcur_t pcur; + dtuple_t* tuple; + dfield_t* dfield; + rec_t* rec; + byte* field; + ulint len; + ulint name_len; + char* name_buf; + ulint type; + ulint space; + ulint page_no; + ulint n_fields; + byte* buf; + ibool is_sys_table; + dulint id; + mtr_t mtr; + + ut_ad(mutex_own(&(dict_sys->mutex))); + + if ((ut_dulint_get_high(table->id) == 0) + && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) { + is_sys_table = TRUE; + } else { + is_sys_table = FALSE; + } + + mtr_start(&mtr); + + sys_indexes = dict_table_get_low((char*) "SYS_INDEXES"); + sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes); + + tuple = dtuple_create(heap, 1); + dfield = dtuple_get_nth_field(tuple, 0); + + buf = mem_heap_alloc(heap, 8); + mach_write_to_8(buf, table->id); + + dfield_set_data(dfield, buf, 8); + 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 (;;) { + if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { + + break; + } + + rec = btr_pcur_get_rec(&pcur); + + field = rec_get_nth_field(rec, 0, &len); + ut_ad(len == 8); + + if (ut_memcmp(buf, field, len) != 0) { + break; + } + + if (rec_get_deleted_flag(rec)) { + fprintf(stderr, +"InnoDB: Error: data dictionary entry for table %s is corrupt!\n" +"InnoDB: An index is delete marked.\n", + table->name); + + btr_pcur_close(&pcur); + mtr_commit(&mtr); + + return(FALSE); + } + + field = rec_get_nth_field(rec, 1, &len); + ut_ad(len == 8); + id = mach_read_from_8(field); + + ut_a(0 == ut_strcmp("NAME", + dict_field_get_col( + dict_index_get_nth_field( + dict_table_get_first_index(sys_indexes), 4))->name)); + + field = rec_get_nth_field(rec, 4, &name_len); + + name_buf = mem_heap_alloc(heap, name_len + 1); + ut_memcpy(name_buf, field, name_len); + name_buf[name_len] = '\0'; + + field = rec_get_nth_field(rec, 5, &len); + n_fields = mach_read_from_4(field); + + field = rec_get_nth_field(rec, 6, &len); + type = mach_read_from_4(field); + + field = rec_get_nth_field(rec, 7, &len); + space = mach_read_from_4(field); + + ut_a(0 == ut_strcmp((char*) "PAGE_NO", + dict_field_get_col( + dict_index_get_nth_field( + dict_table_get_first_index(sys_indexes), 8))->name)); + + field = rec_get_nth_field(rec, 8, &len); + page_no = mach_read_from_4(field); + + if (page_no == FIL_NULL) { + + fprintf(stderr, + "InnoDB: Error: trying to load index %s for table %s\n" + "InnoDB: but the index tree has been freed!\n", + name_buf, table->name); + + btr_pcur_close(&pcur); + mtr_commit(&mtr); + + return(FALSE); + } + + if ((type & DICT_CLUSTERED) == 0 + && NULL == dict_table_get_first_index(table)) { + + fprintf(stderr, + "InnoDB: Error: trying to load index %s for table %s\n" + "InnoDB: but the first index was not clustered!\n", + name_buf, table->name); + + btr_pcur_close(&pcur); + mtr_commit(&mtr); + + return(FALSE); + } + + if (is_sys_table + && ((type & DICT_CLUSTERED) + || ((table == dict_sys->sys_tables) + && (name_len == ut_strlen("ID_IND")) + && (0 == ut_memcmp(name_buf, "ID_IND", + name_len))))) { + + /* The index was created in memory already in + booting */ + } else { + index = dict_mem_index_create(table->name, name_buf, + space, type, n_fields); + index->page_no = page_no; + index->id = id; + + dict_load_fields(table, index, heap); + + dict_index_add_to_cache(table, index); + } + + btr_pcur_move_to_next_user_rec(&pcur, &mtr); + } + + btr_pcur_close(&pcur); + mtr_commit(&mtr); + + return(TRUE); +} + +/************************************************************************ Loads a table definition and also all its index definitions, and also the cluster definition if the table is a member in a cluster. Also loads all foreign key constraints where the foreign key is in the table or where @@ -338,7 +671,7 @@ dict_load_table( dict_load_columns(table, heap); dict_table_add_to_cache(table); - + dict_load_indexes(table, heap); ut_a(DB_SUCCESS == dict_load_foreigns(table->name)); @@ -436,8 +769,6 @@ dict_load_table_on_id( /* Load the table definition to memory */ table = dict_load_table(name); - - ut_a(table); btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -468,324 +799,6 @@ dict_load_sys_table( } /************************************************************************ -Loads definitions for table columns. */ -static -void -dict_load_columns( -/*==============*/ - dict_table_t* table, /* in: table */ - mem_heap_t* heap) /* in: memory heap for temporary storage */ -{ - dict_table_t* sys_columns; - dict_index_t* sys_index; - btr_pcur_t pcur; - dtuple_t* tuple; - dfield_t* dfield; - rec_t* rec; - byte* field; - ulint len; - byte* buf; - char* name_buf; - char* name; - ulint mtype; - ulint prtype; - ulint col_len; - ulint prec; - ulint i; - mtr_t mtr; - - ut_ad(mutex_own(&(dict_sys->mutex))); - - mtr_start(&mtr); - - sys_columns = dict_table_get_low((char *) "SYS_COLUMNS"); - sys_index = UT_LIST_GET_FIRST(sys_columns->indexes); - - tuple = dtuple_create(heap, 1); - dfield = dtuple_get_nth_field(tuple, 0); - - buf = mem_heap_alloc(heap, 8); - mach_write_to_8(buf, table->id); - - dfield_set_data(dfield, buf, 8); - 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 < table->n_cols - DATA_N_SYS_COLS; i++) { - - rec = btr_pcur_get_rec(&pcur); - - ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); - - ut_a(!rec_get_deleted_flag(rec)); - - field = rec_get_nth_field(rec, 0, &len); - ut_ad(len == 8); - ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0); - - field = rec_get_nth_field(rec, 1, &len); - ut_ad(len == 4); - ut_a(i == mach_read_from_4(field)); - - ut_a(0 == ut_strcmp((char *) "NAME", - dict_field_get_col( - dict_index_get_nth_field( - dict_table_get_first_index(sys_columns), 4))->name)); - - field = rec_get_nth_field(rec, 4, &len); - - name_buf = mem_heap_alloc(heap, len + 1); - ut_memcpy(name_buf, field, len); - name_buf[len] = '\0'; - - name = name_buf; - - field = rec_get_nth_field(rec, 5, &len); - mtype = mach_read_from_4(field); - - field = rec_get_nth_field(rec, 6, &len); - prtype = mach_read_from_4(field); - - field = rec_get_nth_field(rec, 7, &len); - col_len = mach_read_from_4(field); - - ut_a(0 == ut_strcmp((char *) "PREC", - dict_field_get_col( - dict_index_get_nth_field( - dict_table_get_first_index(sys_columns), 8))->name)); - - field = rec_get_nth_field(rec, 8, &len); - prec = mach_read_from_4(field); - - dict_mem_table_add_col(table, name, mtype, prtype, col_len, - prec); - btr_pcur_move_to_next_user_rec(&pcur, &mtr); - } - - btr_pcur_close(&pcur); - mtr_commit(&mtr); -} - -/************************************************************************ -Loads definitions for table indexes. Adds them to the data dictionary cache. -*/ -static -void -dict_load_indexes( -/*==============*/ - dict_table_t* table, /* in: table */ - mem_heap_t* heap) /* in: memory heap for temporary storage */ -{ - dict_table_t* sys_indexes; - dict_index_t* sys_index; - dict_index_t* index; - btr_pcur_t pcur; - dtuple_t* tuple; - dfield_t* dfield; - rec_t* rec; - byte* field; - ulint len; - ulint name_len; - char* name_buf; - ulint type; - ulint space; - ulint page_no; - ulint n_fields; - byte* buf; - ibool is_sys_table; - dulint id; - mtr_t mtr; - - ut_ad(mutex_own(&(dict_sys->mutex))); - - if ((ut_dulint_get_high(table->id) == 0) - && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) { - is_sys_table = TRUE; - } else { - is_sys_table = FALSE; - } - - mtr_start(&mtr); - - sys_indexes = dict_table_get_low((char *) "SYS_INDEXES"); - sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes); - - tuple = dtuple_create(heap, 1); - dfield = dtuple_get_nth_field(tuple, 0); - - buf = mem_heap_alloc(heap, 8); - mach_write_to_8(buf, table->id); - - dfield_set_data(dfield, buf, 8); - 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 (;;) { - if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { - - break; - } - - rec = btr_pcur_get_rec(&pcur); - - field = rec_get_nth_field(rec, 0, &len); - ut_ad(len == 8); - - if (ut_memcmp(buf, field, len) != 0) { - break; - } - - ut_a(!rec_get_deleted_flag(rec)); - - field = rec_get_nth_field(rec, 1, &len); - ut_ad(len == 8); - id = mach_read_from_8(field); - - ut_a(0 == ut_strcmp((char *) "NAME", - dict_field_get_col( - dict_index_get_nth_field( - dict_table_get_first_index(sys_indexes), 4))->name)); - - field = rec_get_nth_field(rec, 4, &name_len); - - name_buf = mem_heap_alloc(heap, name_len + 1); - ut_memcpy(name_buf, field, name_len); - name_buf[name_len] = '\0'; - - field = rec_get_nth_field(rec, 5, &len); - n_fields = mach_read_from_4(field); - - field = rec_get_nth_field(rec, 6, &len); - type = mach_read_from_4(field); - - field = rec_get_nth_field(rec, 7, &len); - space = mach_read_from_4(field); - - ut_a(0 == ut_strcmp((char *) "PAGE_NO", - dict_field_get_col( - dict_index_get_nth_field( - dict_table_get_first_index(sys_indexes), 8))->name)); - - field = rec_get_nth_field(rec, 8, &len); - page_no = mach_read_from_4(field); - - if (is_sys_table - && ((type & DICT_CLUSTERED) - || ((table == dict_sys->sys_tables) - && (name_len == ut_strlen((char *) "ID_IND")) - && (0 == ut_memcmp(name_buf, (char *) "ID_IND", - name_len))))) { - - /* The index was created in memory already in - booting */ - } else { - index = dict_mem_index_create(table->name, name_buf, - space, type, n_fields); - index->page_no = page_no; - index->id = id; - - dict_load_fields(table, index, heap); - - if (index->type & DICT_CLUSTERED == 0 - && NULL == dict_table_get_first_index(table)) { - - fprintf(stderr, - "InnoDB: Error: trying to load index %s for table %s\n" - "InnoDB: but the first index was not clustered\n", - index->name, table->name); - } else { - dict_index_add_to_cache(table, index); - } - } - - btr_pcur_move_to_next_user_rec(&pcur, &mtr); - } - - btr_pcur_close(&pcur); - mtr_commit(&mtr); -} - -/************************************************************************ -Loads definitions for index fields. */ -static -void -dict_load_fields( -/*=============*/ - dict_table_t* table, /* in: table */ - dict_index_t* index, /* in: index whose fields to load */ - mem_heap_t* heap) /* in: memory heap for temporary storage */ -{ - dict_table_t* sys_fields; - dict_index_t* sys_index; - btr_pcur_t pcur; - dtuple_t* tuple; - dfield_t* dfield; - char* col_name; - rec_t* rec; - byte* field; - ulint len; - byte* buf; - ulint i; - mtr_t mtr; - - ut_ad(mutex_own(&(dict_sys->mutex))); - - UT_NOT_USED(table); - - mtr_start(&mtr); - - sys_fields = dict_table_get_low((char *) "SYS_FIELDS"); - sys_index = UT_LIST_GET_FIRST(sys_fields->indexes); - - tuple = dtuple_create(heap, 1); - dfield = dtuple_get_nth_field(tuple, 0); - - buf = mem_heap_alloc(heap, 8); - mach_write_to_8(buf, index->id); - - dfield_set_data(dfield, buf, 8); - 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 < index->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)); - - field = rec_get_nth_field(rec, 0, &len); - ut_ad(len == 8); - ut_a(ut_memcmp(buf, field, len) == 0); - - field = rec_get_nth_field(rec, 1, &len); - ut_ad(len == 4); - ut_a(i == mach_read_from_4(field)); - - ut_a(0 == ut_strcmp((char *) "COL_NAME", - dict_field_get_col( - dict_index_get_nth_field( - dict_table_get_first_index(sys_fields), 4))->name)); - - field = rec_get_nth_field(rec, 4, &len); - - col_name = mem_heap_alloc(heap, len + 1); - ut_memcpy(col_name, field, len); - col_name[len] = '\0'; - - dict_mem_index_add_field(index, col_name, 0); - - btr_pcur_move_to_next_user_rec(&pcur, &mtr); - } - - btr_pcur_close(&pcur); - mtr_commit(&mtr); -} - -/************************************************************************ Loads foreign key constraint col names (also for the referenced table). */ static void |