Commit 8ac75806 authored by unknown's avatar unknown

Fix table renaming to not lowercase table names for all storage

engines when lower_case_table_names == 2, as it did previously
for InnoDB and MEMORY. (Bug #9660)


mysql-test/r/lowercase_table2.result:
  Fix results
sql/sql_table.cc:
  Add build_table_path() function to construct the path to
  a table, and use it to replace nearly all of the places
  where this was done with similar code.
  
  Fix mysql_rename_table() to not lowercase the .frm file
  name when lower_case_table_names == 2 and the storage
  engine does not set the HA_FILE_BASED flag (such as InnoDB).
parent edcc645b
......@@ -72,7 +72,7 @@ T1 CREATE TABLE `T1` (
RENAME TABLE T1 TO T2;
SHOW TABLES LIKE "T2";
Tables_in_test (T2)
t2
T2
SELECT * FROM t2;
a
1
......@@ -83,25 +83,25 @@ t3
RENAME TABLE T3 TO T1;
SHOW TABLES LIKE "T1";
Tables_in_test (T1)
t1
T1
ALTER TABLE T1 add b int;
SHOW TABLES LIKE "T1";
Tables_in_test (T1)
t1
T1
ALTER TABLE T1 RENAME T2;
SHOW TABLES LIKE "T2";
Tables_in_test (T2)
t2
T2
LOCK TABLE T2 WRITE;
ALTER TABLE T2 drop b;
SHOW TABLES LIKE "T2";
Tables_in_test (T2)
t2
T2
UNLOCK TABLES;
RENAME TABLE T2 TO T1;
SHOW TABLES LIKE "T1";
Tables_in_test (T1)
t1
T1
SELECT * from T1;
a
1
......
......@@ -40,6 +40,34 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted);
/*
Build the path to a file for a table (or the base path that can
then have various extensions stuck on to it).
SYNOPSIS
build_table_path()
buff Buffer to build the path into
bufflen sizeof(buff)
db Name of database
table Name of table
ext Filename extension
RETURN
FALSE Always -- see usage in mysql_create_indexes()
*/
static bool build_table_path(char *buff, size_t bufflen, const char *db,
const char *table, const char *ext)
{
strxnmov(buff, bufflen-1, mysql_data_home, "/", db, "/", table, ext,
NullS);
unpack_filename(buff,buff);
return FALSE;
}
/*
delete (drop) tables.
......@@ -214,8 +242,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
DBUG_RETURN(-1);
alias= (lower_case_table_names == 2) ? table->alias : table->real_name;
/* remove form file and isam files */
strxmov(path, mysql_data_home, "/", db, "/", alias, reg_ext, NullS);
(void) unpack_filename(path,path);
build_table_path(path, sizeof(path), db, alias, reg_ext);
}
if (drop_temporary ||
(access(path,F_OK) && ha_create_table_from_engine(thd,db,alias,TRUE)))
......@@ -295,13 +322,10 @@ int quick_rm_table(enum db_type base,const char *db,
{
char path[FN_REFLEN];
int error=0;
my_snprintf(path, sizeof(path), "%s/%s/%s%s",
mysql_data_home, db, table_name, reg_ext);
unpack_filename(path,path);
build_table_path(path, sizeof(path), db, table_name, reg_ext);
if (my_delete(path,MYF(0)))
error=1; /* purecov: inspected */
my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home, db, table_name);
unpack_filename(path,path);
build_table_path(path, sizeof(path), db, table_name, "");
return ha_delete_table(base,path) || error;
}
......@@ -1299,11 +1323,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (!create_info->default_table_charset)
{
HA_CREATE_INFO db_info;
uint length;
char path[FN_REFLEN];
strxmov(path, mysql_data_home, "/", db, NullS);
length= unpack_dirname(path,path); // Convert if not unix
strmov(path+length, MY_DB_OPT_FILE);
/* Abuse build_table_path() to build the path to the db.opt file */
build_table_path(path, sizeof(path), db, MY_DB_OPT_FILE, "");
load_db_opt(thd, path, &db_info);
create_info->default_table_charset= db_info.default_table_charset;
}
......@@ -1317,17 +1339,18 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* Check if table exists */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{
my_snprintf(path, sizeof(path), "%s%s%lx_%lx_%x%s",
mysql_tmpdir, tmp_file_prefix, current_pid, thd->thread_id,
thd->tmp_table++, reg_ext);
char tmp_table_name[NAME_LEN+1];
my_snprintf(tmp_table_name, sizeof(tmp_table_name), "%s%lx_%lx_%x",
tmp_file_prefix, current_pid, thd->thread_id,
thd->tmp_table++);
if (lower_case_table_names)
my_casedn_str(files_charset_info, path);
my_casedn_str(files_charset_info, tmp_table_name);
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
build_table_path(path, sizeof(path), db, tmp_table_name, reg_ext);
}
else
my_snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home, db,
alias, reg_ext);
unpack_filename(path,path);
build_table_path(path, sizeof(path), db, alias, reg_ext);
/* Check if table already exists */
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE)
&& find_temporary_table(thd,db,table_name))
......@@ -1560,37 +1583,42 @@ mysql_rename_table(enum db_type base,
const char *new_db,
const char *new_name)
{
char from[FN_REFLEN], to[FN_REFLEN];
char tmp_from[NAME_LEN+1], tmp_to[NAME_LEN+1];
char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
char *from_base= from, *to_base= to;
char tmp_name[NAME_LEN+1];
handler *file=get_new_handler((TABLE*) 0, base);
int error=0;
DBUG_ENTER("mysql_rename_table");
build_table_path(from, sizeof(from), old_db, old_name, "");
build_table_path(to, sizeof(to), new_db, new_name, "");
/*
If lower_case_table_names == 2 (case-preserving but case-insensitive
file system) and the storage is not HA_FILE_BASED, we need to provide
a lowercase file name, but we leave the .frm in mixed case.
*/
if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
{
/* Table handler expects to get all file names as lower case */
strmov(tmp_from, old_name);
my_casedn_str(files_charset_info, tmp_from);
old_name= tmp_from;
strmov(tmp_name, old_name);
my_casedn_str(files_charset_info, tmp_name);
build_table_path(lc_from, sizeof(lc_from), old_db, tmp_name, "");
from_base= lc_from;
strmov(tmp_to, new_name);
my_casedn_str(files_charset_info, tmp_to);
new_name= tmp_to;
strmov(tmp_name, new_name);
my_casedn_str(files_charset_info, tmp_name);
build_table_path(lc_to, sizeof(lc_to), new_db, tmp_name, "");
to_base= lc_to;
}
my_snprintf(from, sizeof(from), "%s/%s/%s",
mysql_data_home, old_db, old_name);
my_snprintf(to, sizeof(to), "%s/%s/%s",
mysql_data_home, new_db, new_name);
fn_format(from,from,"","",4);
fn_format(to,to, "","",4);
if (!(error=file->rename_table((const char*) from,(const char *) to)))
if (!(error=file->rename_table((const char*) from_base,
(const char *) to_base)))
{
if (rename_file_ext(from,to,reg_ext))
{
error=my_errno;
/* Restore old file name */
file->rename_table((const char*) to,(const char *) from);
file->rename_table((const char*) to_base, (const char *) from_base);
}
}
delete file;
......@@ -1768,8 +1796,8 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
if (!(table= table_list->table)) /* if open_ltable failed */
{
char name[FN_REFLEN];
strxmov(name, mysql_data_home, "/", table_list->db, "/",
table_list->real_name, NullS);
build_table_path(name, sizeof(name), table_list->db,
table_list->real_name, "");
if (openfrm(name, "", 0, 0, 0, &tmp_table))
DBUG_RETURN(0); // Can't open frm file
table= &tmp_table;
......@@ -2570,11 +2598,9 @@ int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
else
{
if (table->file->add_index(table, key_info_buffer, key_count)||
(my_snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home,
table_list->db, (lower_case_table_names == 2) ?
table_list->alias: table_list->real_name, reg_ext) >=
(int) sizeof(path)) ||
! unpack_filename(path, path) ||
build_table_path(path, sizeof(path), table_list->db,
(lower_case_table_names == 2) ?
table_list->alias : table_list->real_name, reg_ext) ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
/* don't need to free((gptr) key_info_buffer);*/
......@@ -2672,11 +2698,9 @@ int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
keys, /*tmp_table*/ 0, db_options, table->file,
key_info_buffer, key_count,
/*select_field_count*/ 0)||
(snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home,
table_list->db, (lower_case_table_names == 2)?
table_list->alias: table_list->real_name, reg_ext)>=
(int)sizeof(path))||
! unpack_filename(path, path)||
build_table_path(path, sizeof(path), table_list->db,
(lower_case_table_names == 2) ?
table_list->alias : table_list->real_name, reg_ext) ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
/*don't need to free((gptr) key_numbers);*/
......@@ -3199,9 +3223,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else
{
char path[FN_REFLEN];
my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
new_db, tmp_name);
fn_format(path,path,"","",4);
build_table_path(path, sizeof(path), new_db, tmp_name, "");
new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
}
if (!new_table)
......@@ -3406,9 +3428,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
shutdown.
*/
char path[FN_REFLEN];
my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
new_db, table_name);
fn_format(path,path,"","",4);
build_table_path(path, sizeof(path), new_db, table_name);
table=open_temporary_table(thd, path, new_db, tmp_name,0);
if (table)
{
......
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