Commit 068e6673 authored by Annamalai Gurusami's avatar Annamalai Gurusami

Bug #16722314 FOREIGN KEY ID MODIFIED DURING EXPORT

Bug #16754901 PARS_INFO_FREE NOT CALLED IN DICT_CREATE_ADD_FOREIGN_TO_DICTIONARY

Problem:

There are two situations here.  The constraint name is explicitly
given by the user and the constraint name is automatically generated
by InnoDB.  In the case of generated constraint name, it is formed by
adding table name as prefix.  The table names are stored internally in
my_charset_filename.  In the case of constraint name explicitly given
by the user, it is stored in UTF8 format itself.  So, in some
situations the constraint name is in utf8 and in some situations it is
in my_charset_filename format.  Hence this problem.

Solution:

Always store the foreign key constraint name in UTF-8 even when
automatically generated.

Bug #16754901 PARS_INFO_FREE NOT CALLED IN DICT_CREATE_ADD_FOREIGN_TO_DICTIONARY

Problem:

There was a memory leak in the function dict_create_add_foreign_to_dictionary().
The allocated pars_info_t object is not freed in the error code path.

Solution:

Allocate the pars_info_t object after the error checking.

rb#2368 in review
parent ce38f6b4
......@@ -27,6 +27,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. */
......@@ -1347,25 +1362,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);
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);
......
......@@ -1052,6 +1052,7 @@ dict_table_rename_in_cache(
foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign != NULL) {
if (ut_strlen(foreign->foreign_table_name)
< ut_strlen(table->name)) {
/* Allocate a longer name buffer;
......@@ -1065,34 +1066,115 @@ dict_table_rename_in_cache(
strcpy(foreign->foreign_table_name, table->name);
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)) {
char table_name[MAX_TABLE_NAME_LEN] = "";
uint errors = 0;
/* This is a generated >= 4.0.18 format id */
if (strlen(table->name) > strlen(old_name)) {
foreign->id = mem_heap_alloc(
foreign->id = mem_heap_zalloc(
foreign->heap,
strlen(table->name)
+ 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);
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 */
......@@ -4108,7 +4190,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;
......@@ -4130,9 +4211,7 @@ dict_print_info_on_foreign_key_in_create_format(
}
fputs(" CONSTRAINT ", file);
innobase_convert_to_system_charset(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;;) {
......
......@@ -901,33 +901,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"
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 = cs2->cset->well_formed_len(cs2, tmp, tmp + len,
uint res = cs->cset->well_formed_len(cs, id, id + strlen(id),
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);
}
/**********************************************************************
......@@ -957,17 +951,17 @@ 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 */
ulint len, /* in: length of 'to', in bytes */
uint* errors) /* out: error return */
{
uint errors;
uint rlen;
CHARSET_INFO* cs1 = &my_charset_filename;
CHARSET_INFO* cs2 = system_charset_info;
rlen = strconvert(cs1, from, cs2, to, len, &errors);
rlen = strconvert(cs1, from, cs2, to, len, errors);
if (errors) {
fprintf(stderr, " InnoDB: There was a problem in converting"
if (*errors) {
fprintf(stderr, "InnoDB: There was a problem in converting"
"'%s' in charset %s to charset %s", from, cs1->name,
cs2->name);
}
......@@ -975,6 +969,32 @@ innobase_convert_to_system_charset(
return(rlen);
}
/**********************************************************************
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);
}
/**********************************************************************
Compares NUL-terminated UTF-8 strings case insensitively.
......
......@@ -19,4 +19,7 @@ typedef struct dict_foreign_struct dict_foreign_t;
typedef struct ind_node_struct ind_node_t;
typedef struct tab_node_struct tab_node_t;
#define TEMP_TABLE_PREFIX "#sql"
#define TEMP_TABLE_PATH_PREFIX "/" TEMP_TABLE_PREFIX
#endif
......@@ -94,8 +94,17 @@ 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 */
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
#endif
......@@ -33,6 +33,7 @@ Created 9/17/2000 Heikki Tuuri
#include "ibuf0ibuf.h"
#include "m_string.h"
#include "my_sys.h"
#include "ha_prototypes.h"
/* A dummy variable used to fool the compiler */
ibool row_mysql_identically_false = FALSE;
......@@ -3657,6 +3658,7 @@ row_rename_table_for_mysql(
ibool old_is_tmp, new_is_tmp;
pars_info_t* info = NULL;
ulint retry = 0;
DBUG_ENTER("row_rename_table_for_mysql");
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
ut_a(old_name != NULL);
......@@ -3672,7 +3674,7 @@ row_rename_table_for_mysql(
stderr);
trx_commit_for_mysql(trx);
return(DB_ERROR);
DBUG_RETURN(DB_ERROR);
}
if (row_mysql_is_system_table(new_name)) {
......@@ -3685,7 +3687,7 @@ row_rename_table_for_mysql(
new_name);
trx_commit_for_mysql(trx);
return(DB_ERROR);
DBUG_RETURN(DB_ERROR);
}
trx->op_info = "renaming table";
......@@ -3799,12 +3801,29 @@ row_rename_table_for_mysql(
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"
......@@ -3816,6 +3835,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"
......@@ -3824,8 +3844,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"
......@@ -3842,12 +3860,12 @@ 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, id_len - offset));\n"
" ELSE\n"
" new_foreign_id :=\n"
" CONCAT(new_db_name,\n"
......@@ -4005,7 +4023,7 @@ row_rename_table_for_mysql(
trx->op_info = "";
return((int) err);
DBUG_RETURN((int) err);
}
/*************************************************************************
......
......@@ -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.
......@@ -1426,25 +1441,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);
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);
......
......@@ -1092,22 +1092,78 @@ dict_table_rename_in_cache(
strcpy(foreign->foreign_table_name, table->name);
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,
......@@ -1115,11 +1171,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);
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 */
......@@ -4602,7 +4683,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;
......@@ -4624,9 +4704,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;;) {
......
......@@ -1013,33 +1013,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);
len = strconvert(cs1, id, cs2, tmp, MAX_TABLE_NAME_LEN + 10, &errors);
CHARSET_INFO *cs = system_charset_info;
DBUG_ENTER("innobase_check_identifier_length");
uint res = cs2->cset->well_formed_len(cs2, tmp, tmp + len,
uint res = cs->cset->well_formed_len(cs, id, id + strlen(id),
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);
}
/******************************************************************//**
......@@ -11614,4 +11608,30 @@ test_innobase_convert_name()
}
}
/**********************************************************************
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);
}
#endif /* UNIV_COMPILE_TEST_FUNCS */
......@@ -40,4 +40,7 @@ typedef struct tab_node_struct tab_node_t;
#define DICT_HDR_SPACE 0 /* the SYSTEM tablespace */
#define DICT_HDR_PAGE_NO FSP_DICT_HDR_PAGE_NO
#define TEMP_TABLE_PREFIX "#sql"
#define TEMP_TABLE_PATH_PREFIX "/" TEMP_TABLE_PREFIX
#endif
......@@ -279,4 +279,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
......@@ -51,6 +51,7 @@ Created 9/17/2000 Heikki Tuuri
#include "btr0sea.h"
#include "fil0fil.h"
#include "ibuf0ibuf.h"
#include "ha_prototypes.h"
#ifdef __WIN__
/* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */
......@@ -3902,12 +3903,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"
......@@ -3919,6 +3937,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"
......@@ -3927,8 +3946,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"
......@@ -3945,12 +3962,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"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment