mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 03:21:53 +01:00
Merging the changes from 5.1 branch to release branch.
Includes bug fixes for: Bug #16722314 FOREIGN KEY ID MODIFIED DURING EXPORT Bug #16754901 PARS_INFO_FREE NOT CALLED IN DICT_CREATE_ADD_FOREIGN_TO_DICTIONARY
This commit is contained in:
parent
0fdc37cad0
commit
9e1474fe34
12 changed files with 444 additions and 104 deletions
|
@ -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,26 +1362,47 @@ 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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
/* This is a >= 4.0.18 format id */
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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 */
|
||||
|
@ -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 = 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);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -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
|
||||
|
|
|
@ -92,10 +92,19 @@ 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 */
|
||||
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
|
||||
#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 @@ funct_exit:
|
|||
|
||||
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,26 +1441,47 @@ 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)++);
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
info = pars_info_create();
|
||||
|
||||
pars_info_add_str_literal(info, "id", foreign->id);
|
||||
|
||||
pars_info_add_str_literal(info, "for_name", table->name);
|
||||
|
|
|
@ -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;
|
||||
|
||||
/* This is a >= 4.0.18 format id */
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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 */
|
||||
|
@ -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);
|
||||
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);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
|
@ -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"
|
||||
|
|
Loading…
Add table
Reference in a new issue