diff options
Diffstat (limited to 'storage/innobase/dict')
-rw-r--r-- | storage/innobase/dict/dict0crea.c | 59 | ||||
-rw-r--r-- | storage/innobase/dict/dict0dict.c | 124 | ||||
-rw-r--r-- | storage/innobase/dict/dict0load.c | 8 |
3 files changed, 159 insertions, 32 deletions
diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c index cb3dbcbe4ac..bd4e449d11b 100644 --- a/storage/innobase/dict/dict0crea.c +++ b/storage/innobase/dict/dict0crea.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -44,6 +44,21 @@ Created 1/8/1996 Heikki Tuuri #include "ut0vec.h" #include "ha_prototypes.h" +/************************************************************************* +Checks if a table name contains the string TEMP_TABLE_PATH_PREFIX which +denotes temporary tables in MySQL. */ +static +ibool +row_is_mysql_tmp_table_name( +/*========================*/ + /* out: TRUE if temporary table */ + const char* name) /* in: table name in the form + 'database/tablename' */ +{ + return(strstr(name, TEMP_TABLE_PATH_PREFIX) != NULL); +} + + /*****************************************************************//** Based on a table object, this function builds the entry to be inserted in the SYS_TABLES system table. @@ -1424,26 +1439,46 @@ dict_create_add_foreign_to_dictionary( { ulint error; ulint i; - - pars_info_t* info = pars_info_create(); + pars_info_t* info; if (foreign->id == NULL) { - char* stripped_name; /* Generate a new constraint id */ ulint namelen = strlen(table->name); char* id = mem_heap_alloc(foreign->heap, namelen + 20); - /* no overflow if number < 1e13 */ - sprintf(id, "%s_ibfk_%lu", table->name, (ulong) (*id_nr)++); - foreign->id = id; - stripped_name = strchr(foreign->id, '/') + 1; - if (innobase_check_identifier_length(stripped_name)) { - fprintf(stderr, "InnoDB: Generated foreign key " - "name (%s) is too long\n", foreign->id); - return(DB_IDENTIFIER_TOO_LONG); + if (row_is_mysql_tmp_table_name(table->name)) { + sprintf(id, "%s_ibfk_%lu", table->name, + (ulong) (*id_nr)++); + } else { + char table_name[MAX_TABLE_NAME_LEN + 20] = ""; + uint errors = 0; + + strncpy(table_name, table->name, + MAX_TABLE_NAME_LEN + 20); + + innobase_convert_to_system_charset( + strchr(table_name, '/') + 1, + strchr(table->name, '/') + 1, + MAX_TABLE_NAME_LEN, &errors); + + if (errors) { + strncpy(table_name, table->name, + MAX_TABLE_NAME_LEN + 20); + } + + sprintf(id, "%s_ibfk_%lu", table_name, + (ulong) (*id_nr)++); + + if (innobase_check_identifier_length( + strchr(id,'/') + 1)) { + return(DB_IDENTIFIER_TOO_LONG); + } } + foreign->id = id; } + info = pars_info_create(); + pars_info_add_str_literal(info, "id", foreign->id); pars_info_add_str_literal(info, "for_name", table->name); diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index a887ff0b1ca..aec2264ad1c 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -770,8 +770,10 @@ dict_table_get( /* If table->ibd_file_missing == TRUE, this will print an error message and return without doing anything. */ - dict_update_statistics(table, TRUE /* only update stats - if they have not been initialized */); + dict_update_statistics( + table, + TRUE, /* only update stats if not initialized */ + FALSE /* update even if not changed too much */); } return(table); @@ -1114,22 +1116,78 @@ dict_table_rename_in_cache( dict_mem_foreign_table_name_lookup_set(foreign, FALSE); } if (strchr(foreign->id, '/')) { + /* This is a >= 4.0.18 format id */ + ulint db_len; char* old_id; + char old_name_cs_filename[MAX_TABLE_NAME_LEN+20]; + uint errors = 0; + + /* All table names are internally stored in charset + my_charset_filename (except the temp tables and the + partition identifier suffix in partition tables). The + foreign key constraint names are internally stored + in UTF-8 charset. The variable fkid here is used + to store foreign key constraint name in charset + my_charset_filename for comparison further below. */ + char fkid[MAX_TABLE_NAME_LEN+20]; + ibool on_tmp = FALSE; + + /* The old table name in my_charset_filename is stored + in old_name_cs_filename */ + + strncpy(old_name_cs_filename, old_name, + MAX_TABLE_NAME_LEN); + if (strstr(old_name, TEMP_TABLE_PATH_PREFIX) == NULL) { + + innobase_convert_to_system_charset( + strchr(old_name_cs_filename, '/') + 1, + strchr(old_name, '/') + 1, + MAX_TABLE_NAME_LEN, &errors); + + if (errors) { + /* There has been an error to convert + old table into UTF-8. This probably + means that the old table name is + actually in UTF-8. */ + innobase_convert_to_filename_charset( + strchr(old_name_cs_filename, + '/') + 1, + strchr(old_name, '/') + 1, + MAX_TABLE_NAME_LEN); + } else { + /* Old name already in + my_charset_filename */ + strncpy(old_name_cs_filename, old_name, + MAX_TABLE_NAME_LEN); + } + } - /* This is a >= 4.0.18 format id */ + strncpy(fkid, foreign->id, MAX_TABLE_NAME_LEN); + + if (strstr(fkid, TEMP_TABLE_PATH_PREFIX) == NULL) { + innobase_convert_to_filename_charset( + strchr(fkid, '/') + 1, + strchr(foreign->id, '/') + 1, + MAX_TABLE_NAME_LEN+20); + } else { + on_tmp = TRUE; + } old_id = mem_strdup(foreign->id); - if (ut_strlen(foreign->id) > ut_strlen(old_name) + if (ut_strlen(fkid) > ut_strlen(old_name_cs_filename) + ((sizeof dict_ibfk) - 1) - && !memcmp(foreign->id, old_name, - ut_strlen(old_name)) - && !memcmp(foreign->id + ut_strlen(old_name), + && !memcmp(fkid, old_name_cs_filename, + ut_strlen(old_name_cs_filename)) + && !memcmp(fkid + ut_strlen(old_name_cs_filename), dict_ibfk, (sizeof dict_ibfk) - 1)) { /* This is a generated >= 4.0.18 format id */ + char table_name[MAX_TABLE_NAME_LEN] = ""; + uint errors = 0; + if (strlen(table->name) > strlen(old_name)) { foreign->id = mem_heap_alloc( foreign->heap, @@ -1137,11 +1195,36 @@ dict_table_rename_in_cache( + strlen(old_id) + 1); } + /* Convert the table name to UTF-8 */ + strncpy(table_name, table->name, + MAX_TABLE_NAME_LEN); + innobase_convert_to_system_charset( + strchr(table_name, '/') + 1, + strchr(table->name, '/') + 1, + MAX_TABLE_NAME_LEN, &errors); + + if (errors) { + /* Table name could not be converted + from charset my_charset_filename to + UTF-8. This means that the table name + is already in UTF-8 (#mysql#50). */ + strncpy(table_name, table->name, + MAX_TABLE_NAME_LEN); + } + /* Replace the prefix 'databasename/tablename' with the new names */ - strcpy(foreign->id, table->name); - strcat(foreign->id, - old_id + ut_strlen(old_name)); + strcpy(foreign->id, table_name); + if (on_tmp) { + strcat(foreign->id, + old_id + ut_strlen(old_name)); + } else { + sprintf(strchr(foreign->id, '/') + 1, + "%s%s", + strchr(table_name, '/') +1, + strstr(old_id, "_ibfk_") ); + } + } else { /* This is a >= 4.0.18 format id where the user gave the id name */ @@ -4340,10 +4423,14 @@ void dict_update_statistics( /*===================*/ dict_table_t* table, /*!< in/out: table */ - ibool only_calc_if_missing_stats)/*!< in: only + ibool only_calc_if_missing_stats,/*!< in: only update/recalc the stats if they have not been initialized yet, otherwise do nothing */ + ibool only_calc_if_changed_too_much)/*!< in: only + update/recalc the stats if the table + has been changed too much since the + last stats update/recalc */ { dict_index_t* index; ulint sum_of_index_sizes = 0; @@ -4373,7 +4460,10 @@ dict_update_statistics( dict_table_stats_lock(table, RW_X_LATCH); - if (only_calc_if_missing_stats && table->stat_initialized) { + if ((only_calc_if_missing_stats && table->stat_initialized) + || (only_calc_if_changed_too_much + && !DICT_TABLE_CHANGED_TOO_MUCH(table))) { + dict_table_stats_unlock(table, RW_X_LATCH); return; } @@ -4532,7 +4622,10 @@ dict_table_print_low( ut_ad(mutex_own(&(dict_sys->mutex))); - dict_update_statistics(table, FALSE /* update even if initialized */); + dict_update_statistics( + table, + FALSE, /* update even if initialized */ + FALSE /* update even if not changed too much */); dict_table_stats_lock(table, RW_S_LATCH); @@ -4679,7 +4772,6 @@ dict_print_info_on_foreign_key_in_create_format( dict_foreign_t* foreign, /*!< in: foreign key constraint */ ibool add_newline) /*!< in: whether to add a newline */ { - char constraint_name[MAX_TABLE_NAME_LEN]; const char* stripped_id; ulint i; @@ -4701,9 +4793,7 @@ dict_print_info_on_foreign_key_in_create_format( } fputs(" CONSTRAINT ", file); - innobase_convert_from_id(&my_charset_filename, constraint_name, - stripped_id, MAX_TABLE_NAME_LEN); - ut_print_name(file, trx, FALSE, constraint_name); + ut_print_name(file, trx, FALSE, stripped_id); fputs(" FOREIGN KEY (", file); for (i = 0;;) { diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c index 208d013e82d..f6e7a417f88 100644 --- a/storage/innobase/dict/dict0load.c +++ b/storage/innobase/dict/dict0load.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2013, Innobase Oy. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -352,8 +352,10 @@ dict_process_sys_tables_rec( /* Update statistics if DICT_TABLE_UPDATE_STATS is set */ - dict_update_statistics(*table, FALSE /* update even if - initialized */); + dict_update_statistics( + *table, + FALSE, /* update even if initialized */ + FALSE /* update even if not changed too much */); } return(NULL); |