summaryrefslogtreecommitdiff
path: root/storage/innobase/dict
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/dict')
-rw-r--r--storage/innobase/dict/dict0crea.c59
-rw-r--r--storage/innobase/dict/dict0dict.c124
-rw-r--r--storage/innobase/dict/dict0load.c8
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);