summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnnamalai Gurusami <annamalai.gurusami@oracle.com>2013-05-06 19:57:49 +0530
committerAnnamalai Gurusami <annamalai.gurusami@oracle.com>2013-05-06 19:57:49 +0530
commit1b26d59192f8c9ec6adf49f1d40a8658a7b1d61d (patch)
treeb6b12d03101e07f8bb8be846adc44567a4ec32e5
parent05ca7f082327fc3d4cfb240598e9c04117c522bf (diff)
parentbf7325bb6b1efbe5802fa3bf13154a28dbbffd1a (diff)
downloadmariadb-git-1b26d59192f8c9ec6adf49f1d40a8658a7b1d61d.tar.gz
Merge from mysql-5.1 to mysql-5.5
-rw-r--r--storage/innobase/dict/dict0crea.c59
-rw-r--r--storage/innobase/dict/dict0dict.c102
-rw-r--r--storage/innobase/handler/ha_innodb.cc82
-rw-r--r--storage/innobase/include/dict0types.h5
-rw-r--r--storage/innobase/include/ha_prototypes.h22
-rw-r--r--storage/innobase/row/row0mysql.c31
6 files changed, 250 insertions, 51 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 215ac35ae5b..aec2264ad1c 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -1116,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,
@@ -1139,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 */
@@ -4691,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;
@@ -4713,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/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index fea4ae05ae3..5df84d7cd04 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1159,33 +1159,27 @@ innobase_convert_from_table_id(
/**********************************************************************
Check if the length of the identifier exceeds the maximum allowed.
-The input to this function is an identifier in charset my_charset_filename.
return true when length of identifier is too long. */
-extern "C" UNIV_INTERN
+extern "C"
my_bool
innobase_check_identifier_length(
/*=============================*/
- const char* id) /* in: identifier to check. it must belong
- to charset my_charset_filename */
+ const char* id) /* in: FK identifier to check excluding the
+ database portion. */
{
- char tmp[MAX_TABLE_NAME_LEN + 10];
- uint errors;
- uint len;
int well_formed_error = 0;
- CHARSET_INFO* cs1 = &my_charset_filename;
- CHARSET_INFO* cs2 = thd_charset(current_thd);
+ CHARSET_INFO *cs = system_charset_info;
+ DBUG_ENTER("innobase_check_identifier_length");
- len = strconvert(cs1, id, cs2, tmp, MAX_TABLE_NAME_LEN + 10, &errors);
+ uint res = cs->cset->well_formed_len(cs, id, id + strlen(id),
+ NAME_CHAR_LEN,
+ &well_formed_error);
- uint res = cs2->cset->well_formed_len(cs2, tmp, tmp + len,
- NAME_CHAR_LEN,
- &well_formed_error);
-
- if (well_formed_error || res != len) {
- my_error(ER_TOO_LONG_IDENT, MYF(0), tmp);
- return(true);
+ if (well_formed_error || res == NAME_CHAR_LEN) {
+ my_error(ER_TOO_LONG_IDENT, MYF(0), id);
+ DBUG_RETURN(true);
}
- return(false);
+ DBUG_RETURN(false);
}
/******************************************************************//**
@@ -11966,3 +11960,55 @@ test_innobase_convert_name()
}
#endif /* UNIV_COMPILE_TEST_FUNCS */
+
+/**********************************************************************
+Converts an identifier from my_charset_filename to UTF-8 charset. */
+extern "C"
+uint
+innobase_convert_to_filename_charset(
+/*=================================*/
+ char* to, /* out: converted identifier */
+ const char* from, /* in: identifier to convert */
+ ulint len) /* in: length of 'to', in bytes */
+{
+ uint errors;
+ uint rlen;
+ CHARSET_INFO* cs_to = &my_charset_filename;
+ CHARSET_INFO* cs_from = system_charset_info;
+
+ rlen = strconvert(cs_from, from, cs_to, to, len, &errors);
+
+ if (errors) {
+ fprintf(stderr, "InnoDB: There was a problem in converting"
+ "'%s' in charset %s to charset %s", from, cs_from->name,
+ cs_to->name);
+ }
+
+ return(rlen);
+}
+
+/**********************************************************************
+Converts an identifier from my_charset_filename to UTF-8 charset. */
+extern "C"
+uint
+innobase_convert_to_system_charset(
+/*===============================*/
+ char* to, /* out: converted identifier */
+ const char* from, /* in: identifier to convert */
+ ulint len, /* in: length of 'to', in bytes */
+ uint* errors) /* out: error return */
+{
+ uint rlen;
+ CHARSET_INFO* cs1 = &my_charset_filename;
+ CHARSET_INFO* cs2 = system_charset_info;
+
+ rlen = strconvert(cs1, from, cs2, to, len, errors);
+
+ if (*errors) {
+ fprintf(stderr, "InnoDB: There was a problem in converting"
+ "'%s' in charset %s to charset %s", from, cs1->name,
+ cs2->name);
+ }
+
+ return(rlen);
+}
diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h
index f0a05a38070..8e3a04f7956 100644
--- a/storage/innobase/include/dict0types.h
+++ b/storage/innobase/include/dict0types.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2009, Innobase Oy. 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
@@ -58,4 +58,7 @@ enum dict_err_ignore {
typedef enum dict_err_ignore dict_err_ignore_t;
+#define TEMP_TABLE_PREFIX "#sql"
+#define TEMP_TABLE_PATH_PREFIX "/" TEMP_TABLE_PREFIX
+
#endif
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index ae0188fdaa1..dc730f9b6b3 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 2000, 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
@@ -307,4 +307,24 @@ innobase_check_identifier_length(
const char* id); /* in: identifier to check. it must belong
to charset my_charset_filename */
+/**********************************************************************
+Converts an identifier from my_charset_filename to UTF-8 charset. */
+uint
+innobase_convert_to_system_charset(
+/*===============================*/
+ char* to, /* out: converted identifier */
+ const char* from, /* in: identifier to convert */
+ ulint len, /* in: length of 'to', in bytes */
+ uint* errors); /* out: error return */
+
+/**********************************************************************
+Converts an identifier from my_charset_filename to UTF-8 charset. */
+uint
+innobase_convert_to_filename_charset(
+/*=================================*/
+ char* to, /* out: converted identifier */
+ const char* from, /* in: identifier to convert */
+ ulint len); /* in: length of 'to', in bytes */
+
+
#endif
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index d97476dcdb1..ff8f79f4f3f 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -53,7 +53,7 @@ Created 9/17/2000 Heikki Tuuri
#include "ibuf0ibuf.h"
#include "m_string.h"
#include "my_sys.h"
-
+#include "ha_prototypes.h"
/** Provide optional 4.x backwards compatibility for 5.0 and above */
UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
@@ -3956,12 +3956,29 @@ row_rename_table_for_mysql(
goto end;
} else if (!new_is_tmp) {
/* Rename all constraints. */
+ char new_table_name[MAX_TABLE_NAME_LEN] = "";
+ uint errors = 0;
info = pars_info_create();
pars_info_add_str_literal(info, "new_table_name", new_name);
pars_info_add_str_literal(info, "old_table_name", old_name);
+ strncpy(new_table_name, new_name, MAX_TABLE_NAME_LEN);
+ innobase_convert_to_system_charset(
+ strchr(new_table_name, '/') + 1,
+ strchr(new_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(new_table_name, new_name, MAX_TABLE_NAME_LEN);
+ }
+
+ pars_info_add_str_literal(info, "new_table_utf8", new_table_name);
+
err = que_eval_sql(
info,
"PROCEDURE RENAME_CONSTRAINT_IDS () IS\n"
@@ -3973,6 +3990,7 @@ row_rename_table_for_mysql(
"old_t_name_len INT;\n"
"new_db_name_len INT;\n"
"id_len INT;\n"
+ "offset INT;\n"
"found INT;\n"
"BEGIN\n"
"found := 1;\n"
@@ -3981,8 +3999,6 @@ row_rename_table_for_mysql(
"new_db_name := SUBSTR(:new_table_name, 0,\n"
" new_db_name_len);\n"
"old_t_name_len := LENGTH(:old_table_name);\n"
- "gen_constr_prefix := CONCAT(:old_table_name,\n"
- " '_ibfk_');\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
@@ -3999,12 +4015,13 @@ row_rename_table_for_mysql(
" id_len := LENGTH(foreign_id);\n"
" IF (INSTR(foreign_id, '/') > 0) THEN\n"
" IF (INSTR(foreign_id,\n"
- " gen_constr_prefix) > 0)\n"
+ " '_ibfk_') > 0)\n"
" THEN\n"
+ " offset := INSTR(foreign_id, '_ibfk_') - 1;\n"
" new_foreign_id :=\n"
- " CONCAT(:new_table_name,\n"
- " SUBSTR(foreign_id, old_t_name_len,\n"
- " id_len - old_t_name_len));\n"
+ " CONCAT(:new_table_utf8,\n"
+ " SUBSTR(foreign_id, offset,\n"
+ " id_len - offset));\n"
" ELSE\n"
" new_foreign_id :=\n"
" CONCAT(new_db_name,\n"