diff options
Diffstat (limited to 'storage/innobase/dict/dict0load.c')
-rw-r--r-- | storage/innobase/dict/dict0load.c | 162 |
1 files changed, 135 insertions, 27 deletions
diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c index 3caa05891b4..a76f1f93202 100644 --- a/storage/innobase/dict/dict0load.c +++ b/storage/innobase/dict/dict0load.c @@ -40,6 +40,7 @@ Created 4/24/1996 Heikki Tuuri #include "rem0cmp.h" #include "srv0start.h" #include "srv0srv.h" +#include "ha_prototypes.h" /* innobase_casedn_str() */ /** Following are six InnoDB system tables */ @@ -346,7 +347,8 @@ dict_process_sys_tables_rec( /* Update statistics if DICT_TABLE_UPDATE_STATS is set */ - dict_update_statistics_low(*table, TRUE); + dict_update_statistics(*table, FALSE /* update even if + initialized */); } return(NULL); @@ -427,17 +429,19 @@ dict_process_sys_fields_rec( mach_write_to_8(last_index_id, last_id); err_msg = dict_load_field_low(buf, NULL, sys_field, - pos, last_index_id, heap, rec); + pos, last_index_id, heap, rec, NULL, 0); *index_id = mach_read_from_8(buf); return(err_msg); } + +#ifdef FOREIGN_NOT_USED /********************************************************************//** This function parses a SYS_FOREIGN record and populate a dict_foreign_t structure with the information from the record. For detail information -about SYS_FOREIGN fields, please refer to dict_load_foreign() function +about SYS_FOREIGN fields, please refer to dict_load_foreign() function. @return error message, or NULL on success */ UNIV_INTERN const char* @@ -465,6 +469,11 @@ dict_process_sys_foreign_rec( err_len: return("incorrect column length in SYS_FOREIGN"); } + + /* This recieves a dict_foreign_t* that points to a stack variable. + So mem_heap_free(foreign->heap) is not used as elsewhere. + Since the heap used here is freed elsewhere, foreign->heap + is not assigned. */ foreign->id = mem_heap_strdupl(heap, (const char*) field, len); rec_get_nth_field_offs_old(rec, 1/*DB_TRX_ID*/, &len); @@ -476,6 +485,9 @@ err_len: goto err_len; } + /* The _lookup versions of the referenced and foreign table names + are not assigned since they are not used in this dict_foreign_t */ + field = rec_get_nth_field_old(rec, 3/*FOR_NAME*/, &len); if (UNIV_UNLIKELY(len < 1 || len == UNIV_SQL_NULL)) { goto err_len; @@ -501,6 +513,9 @@ err_len: return(NULL); } +#endif /* FOREIGN_NOT_USED */ + +#ifdef FOREIGN_NOT_USED /********************************************************************//** This function parses a SYS_FOREIGN_COLS record and extract necessary information from the record and return to caller. @@ -564,6 +579,8 @@ err_len: return(NULL); } +#endif /* FOREIGN_NOT_USED */ + /********************************************************************//** Determine the flags of a table described in SYS_TABLES. @return compressed page size in kilobytes; or 0 if the tablespace is @@ -977,6 +994,9 @@ dict_load_columns( /** Error message for a delete-marked record in dict_load_field_low() */ static const char* dict_load_field_del = "delete-marked record in SYS_FIELDS"; +static const char* dict_load_field_too_big = "column prefix exceeds maximum" + " limit"; + /********************************************************************//** Loads an index field definition from a SYS_FIELDS record to dict_index_t. @@ -998,7 +1018,12 @@ dict_load_field_low( byte* last_index_id, /*!< in: last index id */ mem_heap_t* heap, /*!< in/out: memory heap for temporary storage */ - const rec_t* rec) /*!< in: SYS_FIELDS record */ + const rec_t* rec, /*!< in: SYS_FIELDS record */ + char* addition_err_str,/*!< out: additional error message + that requires information to be + filled, or NULL */ + ulint err_str_len) /*!< in: length of addition_err_str + in bytes */ { const byte* field; ulint len; @@ -1078,6 +1103,19 @@ err_len: goto err_len; } + if (prefix_len > REC_VERSION_56_MAX_INDEX_COL_LEN) { + if (addition_err_str) { + ut_snprintf(addition_err_str, err_str_len, + "index field '%s' has a prefix length" + " of %lu bytes", + mem_heap_strdupl( + heap, (const char*) field, len), + (ulong) prefix_len); + } + + return(dict_load_field_too_big); + } + if (index) { dict_mem_index_add_field( index, mem_heap_strdupl(heap, (const char*) field, len), @@ -1137,14 +1175,16 @@ dict_load_fields( 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++) { - const char* err_msg; + const char* err_msg; + char addition_err_str[1024]; rec = btr_pcur_get_rec(&pcur); ut_a(btr_pcur_is_on_user_rec(&pcur)); err_msg = dict_load_field_low(buf, index, NULL, NULL, NULL, - heap, rec); + heap, rec, addition_err_str, + sizeof(addition_err_str)); if (err_msg == dict_load_field_del) { /* There could be delete marked records in @@ -1153,7 +1193,24 @@ dict_load_fields( goto next_rec; } else if (err_msg) { - fprintf(stderr, "InnoDB: %s\n", err_msg); + if (err_msg == dict_load_field_too_big) { + fprintf(stderr, "InnoDB: Error: load index" + " '%s' failed.\n" + "InnoDB: %s,\n" + "InnoDB: which exceeds the" + " maximum limit of %lu bytes.\n" + "InnoDB: Please use server that" + " supports long index prefix\n" + "InnoDB: or turn on" + " innodb_force_recovery to load" + " the table\n", + index->name, addition_err_str, + (ulong) (REC_VERSION_56_MAX_INDEX_COL_LEN)); + + } else { + fprintf(stderr, "InnoDB: %s\n", err_msg); + } + error = DB_CORRUPTION; goto func_exit; } @@ -1306,7 +1363,10 @@ ulint dict_load_indexes( /*==============*/ dict_table_t* table, /*!< in/out: table */ - mem_heap_t* heap) /*!< in: memory heap for temporary storage */ + mem_heap_t* heap, /*!< in: memory heap for temporary storage */ + dict_err_ignore_t ignore_err) + /*!< in: error to be ignored when + loading the index definition */ { dict_table_t* sys_indexes; dict_index_t* sys_index; @@ -1389,10 +1449,22 @@ dict_load_indexes( "InnoDB: but the index tree has been freed!\n", index->name, table->name); + if (ignore_err & DICT_ERR_IGNORE_INDEX_ROOT) { + /* If caller can tolerate this error, + we will continue to load the index and + let caller deal with this error. However + mark the index and table corrupted */ + index->corrupted = TRUE; + table->corrupted = TRUE; + fprintf(stderr, + "InnoDB: Index is corrupt but forcing" + " load into data dictionary\n"); + } else { corrupted: - dict_mem_index_free(index); - error = DB_CORRUPTION; - goto func_exit; + dict_mem_index_free(index); + error = DB_CORRUPTION; + goto func_exit; + } } else if (!dict_index_is_clust(index) && NULL == dict_table_get_first_index(table)) { @@ -1414,7 +1486,26 @@ corrupted: of the database server */ dict_mem_index_free(index); } else { - dict_load_fields(index, heap); + error = dict_load_fields(index, heap); + + if (error != DB_SUCCESS) { + + fprintf(stderr, "InnoDB: Error: load index '%s'" + " for table '%s' failed\n", + index->name, table->name); + + /* If the force recovery flag is set, and + if the failed index is not the primary index, we + will continue and open other indexes */ + if (srv_force_recovery + && !dict_index_is_clust(index)) { + error = DB_SUCCESS; + goto next_rec; + } else { + goto func_exit; + } + } + error = dict_index_add_to_cache(table, index, index->page, FALSE); /* The data dictionary tables should never contain @@ -1535,7 +1626,7 @@ err_len: "InnoDB: in InnoDB data dictionary" " has unknown type %lx.\n", (ulong) flags); - return(NULL); + return("incorrect flags in SYS_TABLES"); } } else { flags = 0; @@ -1601,7 +1692,10 @@ dict_load_table( /*============*/ const char* name, /*!< in: table name in the databasename/tablename format */ - ibool cached) /*!< in: TRUE=add to cache, FALSE=do not */ + ibool cached, /*!< in: TRUE=add to cache, FALSE=do not */ + dict_err_ignore_t ignore_err) + /*!< in: error to be ignored when loading + table and its indexes' definition */ { dict_table_t* table; dict_table_t* sys_tables; @@ -1716,7 +1810,7 @@ err_exit: mem_heap_empty(heap); - err = dict_load_indexes(table, heap); + err = dict_load_indexes(table, heap, ignore_err); /* Initialize table foreign_child value. Its value could be changed when dict_load_foreigns() is called below */ @@ -1733,13 +1827,22 @@ err_exit: if (err != DB_SUCCESS) { dict_table_remove_from_cache(table); table = NULL; + } else { + table->fk_max_recusive_level = 0; } - } else if (!srv_force_recovery) { - dict_table_remove_from_cache(table); - table = NULL; - } + } else { + dict_index_t* index; - table->fk_max_recusive_level = 0; + /* Make sure that at least the clustered index was loaded. + Otherwise refuse to load the table */ + index = dict_table_get_first_index(table); + + if (!srv_force_recovery || !index + || !dict_index_is_clust(index)) { + dict_table_remove_from_cache(table); + table = NULL; + } + } #if 0 if (err != DB_SUCCESS && table != NULL) { @@ -1851,7 +1954,7 @@ dict_load_table_on_id( 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), - TRUE); + TRUE, DICT_ERR_IGNORE_NONE); func_exit: btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -1876,7 +1979,7 @@ dict_load_sys_table( heap = mem_heap_create(1000); - dict_load_indexes(table, heap); + dict_load_indexes(table, heap, DICT_ERR_IGNORE_NONE); mem_heap_free(heap); } @@ -2055,12 +2158,15 @@ dict_load_foreign( 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); + dict_mem_foreign_table_name_lookup_set(foreign, TRUE); field = rec_get_nth_field_old(rec, 4, &len); foreign->referenced_table_name = mem_heap_strdupl( foreign->heap, (char*) field, len); + dict_mem_referenced_table_name_lookup_set(foreign, TRUE); btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -2068,7 +2174,7 @@ dict_load_foreign( dict_load_foreign_cols(id, foreign); ref_table = dict_table_check_if_in_cache_low( - foreign->referenced_table_name); + foreign->referenced_table_name_lookup); /* We could possibly wind up in a deep recursive calls if we call dict_table_get_low() again here if there @@ -2101,7 +2207,7 @@ dict_load_foreign( have to load it so that we are able to make type comparisons in the next function call. */ - for_table = dict_table_get_low(foreign->foreign_table_name); + for_table = dict_table_get_low(foreign->foreign_table_name_lookup); if (for_table && ref_table && check_recursive) { /* This is to record the longest chain of ancesters @@ -2220,10 +2326,12 @@ loop: /* 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)) { + in character case. If lower_case_table_names=2 then what is stored + may not be the same case, but the previous comparison showed that they + match with no-case. */ + if ((innobase_get_lower_case_table_names() != 2) + && (0 != ut_memcmp(field, table_name, len))) { goto next_rec; } |