summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorbar@mysql.com <>2005-12-31 09:01:26 +0400
committerbar@mysql.com <>2005-12-31 09:01:26 +0400
commit6ff211329f8c513c2b8ec7e3ef1652e1ff7d7b8c (patch)
tree6a3476c826545341821fbccb1f42ba381c5ca30a /sql
parent83d8979ca28da67a054fff6c8f9e127e38f26ecb (diff)
downloadmariadb-git-6ff211329f8c513c2b8ec7e3ef1652e1ff7d7b8c.tar.gz
WL#1324 table name to file name encoding
- Encoding itself, implemented as a charset "filename". Originally planned to use '.' as an escape character, but now changed to '@' for two reasons: "ls" does not return file names starting with '.' considering them as a kind of hidden files; some platforms do not allow several dots in a file name. - replacing many calls of my_snprintf() and strnxmov() to the new build_table_filename(). - Adding MY_APPEND_EXT mysys flag, to append an extention rather that replace it. - Replacing all numeric constants in fn_format flag arguments to their mysys definitions, e.g. MY_UNPACK_FILENAME, - Predictability in several function/methods: when a table name can appear with or withot .frm extension. Some functions/methods were changed so accept names strictly with .frm, other - strictly without .frm extensions. Several DBUG_ASSERTs were added to check whether an extension is passed. Many files: table name to file name encoding mysql_priv.h: Prototypes for new table name encoding tools. ctype-utf8.c: Implementing "filename" charset for table name to file name encoding. row0mysql.c: Fixing table name prefix. mf_format.c: Adding MY_APPEND_EXT processing. Many files: Fixing tests. my_sys.h: Adding new flag to append rather than replace an extension. m_ctype.h: Adding "filename" charset definition.
Diffstat (limited to 'sql')
-rw-r--r--sql/discover.cc6
-rw-r--r--sql/ha_berkeley.cc25
-rw-r--r--sql/ha_innodb.cc2
-rw-r--r--sql/ha_myisam.cc10
-rw-r--r--sql/ha_myisammrg.cc13
-rw-r--r--sql/ha_ndbcluster.cc3
-rw-r--r--sql/ha_partition.cc7
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/init.cc1
-rw-r--r--sql/mysql_priv.h18
-rw-r--r--sql/mysqld.cc4
-rw-r--r--sql/parse_file.cc16
-rw-r--r--sql/sql_acl.cc7
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_db.cc25
-rw-r--r--sql/sql_delete.cc9
-rw-r--r--sql/sql_rename.cc11
-rw-r--r--sql/sql_show.cc39
-rw-r--r--sql/sql_table.cc161
-rw-r--r--sql/sql_trigger.cc63
-rw-r--r--sql/sql_view.cc25
-rw-r--r--sql/strfunc.cc76
-rw-r--r--sql/table.cc50
-rw-r--r--sql/unireg.cc18
24 files changed, 392 insertions, 204 deletions
diff --git a/sql/discover.cc b/sql/discover.cc
index 1251055c70e..2a3da55f154 100644
--- a/sql/discover.cc
+++ b/sql/discover.cc
@@ -55,7 +55,8 @@ int readfrm(const char *name,
*frmdata= NULL; // In case of errors
*len= 0;
error= 1;
- if ((file=my_open(fn_format(index_file,name,"",reg_ext,4),
+ if ((file=my_open(fn_format(index_file,name,"",reg_ext,
+ MY_UNPACK_FILENAME|MY_APPEND_EXT),
O_RDONLY | O_SHARE,
MYF(0))) < 0)
goto err_end;
@@ -112,7 +113,8 @@ int writefrm(const char *name, const void *frmdata, uint len)
//DBUG_DUMP("frmdata", (char*)frmdata, len);
error= 0;
- if ((file=my_create(fn_format(index_file,name,"",reg_ext,4),
+ if ((file=my_create(fn_format(index_file,name,"",reg_ext,
+ MY_UNPACK_FILENAME|MY_APPEND_EXT),
CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
{
if (my_write(file,(byte*)frmdata,len,MYF(MY_WME | MY_NABP)))
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 900372a2204..01d6ceed3f2 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -699,7 +699,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
if ((error= db_env->txn_begin(db_env, NULL, (DB_TXN**) &transaction, 0)) ||
(error= (file->open(file, transaction,
fn_format(name_buff, name, "", ha_berkeley_ext,
- 2 | 4),
+ MY_UNPACK_FILENAME|MY_APPEND_EXT),
"main", DB_BTREE, open_mode, 0))) ||
(error= transaction->commit(transaction, 0)))
{
@@ -2093,7 +2093,8 @@ int ha_berkeley::create(const char *name, register TABLE *form,
int error;
DBUG_ENTER("ha_berkeley::create");
- fn_format(name_buff,name,"", ha_berkeley_ext,2 | 4);
+ fn_format(name_buff,name,"", ha_berkeley_ext,
+ MY_UNPACK_FILENAME|MY_APPEND_EXT);
/* Create the main table that will hold the real rows */
if ((error= create_sub_table(name_buff,"main",DB_BTREE,0)))
@@ -2142,8 +2143,9 @@ int ha_berkeley::delete_table(const char *name)
if ((error=db_create(&file, db_env, 0)))
my_errno=error; /* purecov: inspected */
else
- error=file->remove(file,fn_format(name_buff,name,"",ha_berkeley_ext,2 | 4),
- NULL,0);
+ error=file->remove(file,fn_format(name_buff,name,"",ha_berkeley_ext,
+ MY_UNPACK_FILENAME|MY_APPEND_EXT),
+ NULL,0);
file=0; // Safety
DBUG_RETURN(error);
}
@@ -2161,9 +2163,11 @@ int ha_berkeley::rename_table(const char * from, const char * to)
{
/* On should not do a file->close() after rename returns */
error= file->rename(file,
- fn_format(from_buff, from, "", ha_berkeley_ext, 2 | 4),
+ fn_format(from_buff, from, "",
+ ha_berkeley_ext,
+ MY_UNPACK_FILENAME|MY_APPEND_EXT),
NULL, fn_format(to_buff, to, "", ha_berkeley_ext,
- 2 | 4), 0);
+ MY_UNPACK_FILENAME|MY_APPEND_EXT), 0);
}
return error;
}
@@ -2413,7 +2417,8 @@ int ha_berkeley::check(THD* thd, HA_CHECK_OPT* check_opt)
(hidden_primary_key ? berkeley_cmp_hidden_key :
berkeley_cmp_packed_key));
tmp_file->app_private= (void*) (table->key_info+table->primary_key);
- fn_format(name_buff,share->table_name.str,"", ha_berkeley_ext, 2 | 4);
+ fn_format(name_buff,share->table_name.str,"", ha_berkeley_ext,
+ MY_UNPACK_FILENAME|MY_APPEND_EXT);
if ((error=tmp_file->verify(tmp_file, name_buff, NullS, (FILE*) 0,
hidden_primary_key ? 0 : DB_NOORDERCHK)))
{
@@ -2559,7 +2564,8 @@ void ha_berkeley::get_status()
char name_buff[FN_REFLEN];
uint open_mode= (((table->db_stat & HA_READ_ONLY) ? DB_RDONLY : 0)
| DB_THREAD);
- fn_format(name_buff, share->table_name, "", ha_berkeley_ext, 2 | 4);
+ fn_format(name_buff, share->table_name, "", ha_berkeley_ext,
+ MY_UNPACK_FILENAME|MY_APPEND_EXT);
if (!db_create(&share->status_block, db_env, 0))
{
if (share->status_block->open(share->status_block, NULL, name_buff,
@@ -2641,7 +2647,8 @@ static void update_status(BDB_SHARE *share, TABLE *table)
share->status_block->set_flags(share->status_block,0); /* purecov: inspected */
if (share->status_block->open(share->status_block, NULL,
fn_format(name_buff,share->table_name,
- "", ha_berkeley_ext,2 | 4),
+ "", ha_berkeley_ext,
+ MY_UNPACK_FILENAME|MY_APPEND_EXT),
"status", DB_BTREE,
DB_THREAD | DB_CREATE, my_umask)) /* purecov: inspected */
goto end; /* purecov: inspected */
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 7909f39154f..27262e6f197 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -4857,7 +4857,7 @@ ha_innobase::create(
srv_lower_case_table_names = FALSE;
}
- fn_format(name2, name, "", "", 2); // Remove the .frm extension
+ strcpy(name2, name);
normalize_table_name(norm_name, name2);
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 5fe82e9ccae..41000564e53 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -539,8 +539,8 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
}
/* Change extension */
- if (!fn_format(dst_path, dst_path, "", MI_NAME_DEXT,
- MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH))
+ if (fn_format_relative_to_data_home(dst_path, table_name, backup_dir,
+ MI_NAME_DEXT))
{
errmsg = "Failed in fn_format() for .MYD file (errno: %d)";
error = HA_ADMIN_INVALID;
@@ -1361,10 +1361,10 @@ void ha_myisam::info(uint flag)
if table is symlinked (Ie; Real name is not same as generated name)
*/
data_file_name= index_file_name= 0;
- fn_format(name_buff, file->filename, "", MI_NAME_DEXT, 2);
+ fn_format(name_buff, file->filename, "", MI_NAME_DEXT, MY_APPEND_EXT);
if (strcmp(name_buff, info.data_file_name))
data_file_name=info.data_file_name;
- strmov(fn_ext(name_buff),MI_NAME_IEXT);
+ fn_format(name_buff, file->filename, "", MI_NAME_IEXT, MY_APPEND_EXT);
if (strcmp(name_buff, info.index_file_name))
index_file_name=info.index_file_name;
}
@@ -1647,7 +1647,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
create_flags|= HA_CREATE_DELAY_KEY_WRITE;
/* TODO: Check that the following fn_format is really needed */
- error=mi_create(fn_format(buff,name,"","",2+4),
+ error=mi_create(fn_format(buff,name,"","",MY_UNPACK_FILENAME|MY_APPEND_EXT),
share->keys,keydef,
(uint) (recinfo_pos-recinfo), recinfo,
0, (MI_UNIQUEDEF*) 0,
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 1be4fb62fa1..ccb3475e34f 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -105,8 +105,9 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
char name_buff[FN_REFLEN];
DBUG_PRINT("info", ("ha_myisammrg::open"));
- if (!(file=myrg_open(fn_format(name_buff,name,"","",2 | 4), mode,
- test_if_locked)))
+ if (!(file=myrg_open(fn_format(name_buff,name,"","",
+ MY_UNPACK_FILENAME|MY_APPEND_EXT),
+ mode, test_if_locked)))
{
DBUG_PRINT("info", ("ha_myisammrg::open exit %d", my_errno));
return (my_errno ? my_errno : -1);
@@ -469,8 +470,8 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
This means that it might not be possible to move the DATADIR of
an embedded server without changing the paths in the .MRG file.
*/
- uint length= my_snprintf(buff, FN_REFLEN, "%s/%s/%s", mysql_data_home,
- tables->db, tables->table_name);
+ uint length= build_table_filename(buff, sizeof(buff),
+ tables->db, tables->table_name, "");
/*
If a MyISAM table is in the same directory as the MERGE table,
we use the table name without a path. This means that the
@@ -488,7 +489,9 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
*pos++= table_name;
}
*pos=0;
- DBUG_RETURN(myrg_create(fn_format(buff,name,"","",2+4+16),
+ DBUG_RETURN(myrg_create(fn_format(buff,name,"","",
+ MY_RESOLVE_SYMLINKS|
+ MY_UNPACK_FILENAME|MY_APPEND_EXT),
table_names,
create_info->merge_insert_method,
(my_bool) 0));
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 31548ef0d61..dfbe1993ea8 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -3961,7 +3961,8 @@ int ha_ndbcluster::create(const char *name,
DBUG_ENTER("ha_ndbcluster::create");
DBUG_PRINT("enter", ("name: %s", name));
- fn_format(name2, name, "", "",2); // Remove the .frm extension
+ strcpy(name2, name);
+ DBUG_ASSERT(*fn_rext((char*)name2) == 0);
set_dbname(name2);
set_tabname(name2);
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 3b8f26d88f2..4784a0c7530 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -399,7 +399,8 @@ int ha_partition::create(const char *name, TABLE *table_arg,
DBUG_ENTER("ha_partition::create");
strmov(t_name, name);
- *fn_ext(t_name)= 0;
+// *fn_ext(t_name)= 0;
+ DBUG_ASSERT(*fn_rext((char*)name) == '\0');
if (del_ren_cre_table(t_name, NULL, table_arg, create_info))
{
handler::delete_table(t_name);
@@ -677,7 +678,7 @@ bool ha_partition::create_handler_file(const char *name)
Create and write and close file
to be used at open, delete_table and rename_table
*/
- fn_format(file_name, name, "", ".par", MYF(MY_REPLACE_EXT));
+ fn_format(file_name, name, "", ".par", MY_APPEND_EXT);
if ((file= my_create(file_name, CREATE_MODE, O_RDWR | O_TRUNC,
MYF(MY_WME))) >= 0)
{
@@ -802,7 +803,7 @@ bool ha_partition::get_from_handler_file(const char *name)
if (m_file_buffer)
DBUG_RETURN(FALSE);
- fn_format(buff, name, "", ha_par_ext, MYF(0));
+ fn_format(buff, name, "", ha_par_ext, MY_APPEND_EXT);
/* Following could be done with my_stat to read in whole file */
if ((file= my_open(buff, O_RDONLY | O_SHARE, MYF(0))) < 0)
diff --git a/sql/handler.cc b/sql/handler.cc
index 59445a1b2f1..db97b14da2a 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -2023,7 +2023,7 @@ int handler::delete_table(const char *name)
for (const char **ext=bas_ext(); *ext ; ext++)
{
- fn_format(buff, name, "", *ext, 2 | 4);
+ fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT);
if (my_delete_with_symlink(buff, MYF(0)))
{
if ((error= my_errno) != ENOENT)
diff --git a/sql/init.cc b/sql/init.cc
index e53eeab8902..9f975296cb6 100644
--- a/sql/init.cc
+++ b/sql/init.cc
@@ -39,6 +39,7 @@ void unireg_init(ulong options)
#endif
VOID(strmov(reg_ext,".frm"));
+ reg_ext_length= 4;
specialflag=SPECIAL_SAME_DB_NAME | options; /* Set options from argv */
/* Make a tab of powers of 10 */
for (i=0,nr=1.0; i < array_elements(log_10) ; i++)
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index c815cb22495..fabc2e2e1cd 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1174,6 +1174,7 @@ extern Lt_creator lt_creator;
extern Ge_creator ge_creator;
extern Le_creator le_creator;
extern char language[FN_REFLEN], reg_ext[FN_EXTLEN];
+extern uint reg_ext_length;
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
extern char log_error_file[FN_REFLEN], *opt_tc_log_file;
@@ -1499,6 +1500,23 @@ bool check_table_name(const char *name, uint length);
char *get_field(MEM_ROOT *mem, Field *field);
bool get_field(MEM_ROOT *mem, Field *field, class String *res);
int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
+char *fn_rext(char *name);
+
+/* Conversion functions */
+uint strconvert(CHARSET_INFO *from_cs, const char *from,
+ CHARSET_INFO *to_cs, char *to, uint to_length);
+uint build_table_filename(char *buff, size_t bufflen, const char *db,
+ const char *table, const char *ext);
+inline uint filename_to_tablename(const char *from, char *to, uint to_length)
+{
+ return strconvert(&my_charset_filename, from,
+ system_charset_info, to, to_length);
+}
+inline uint tablename_to_filename(const char *from, char *to, uint to_length)
+{
+ return strconvert(system_charset_info, from,
+ &my_charset_filename, to, to_length);
+}
/* from hostname.cc */
struct in_addr;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 7e25ea51823..6bceb51809e 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -511,7 +511,7 @@ char mysql_real_data_home[FN_REFLEN],
language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
*opt_init_file, *opt_tc_log_file,
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
-
+uint reg_ext_length;
const key_map key_map_empty(0);
key_map key_map_full(0); // Will be initialized later
@@ -7455,7 +7455,7 @@ fn_format_relative_to_data_home(my_string to, const char *name,
dir=tmp_path;
}
return !fn_format(to, name, dir, extension,
- MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
+ MY_APPEND_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
}
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index fe82054c528..0b2bfe83b6f 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -226,8 +226,20 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
DBUG_PRINT("enter", ("Dir: %s, file: %s, base 0x%lx",
dir->str, file_name->str, (ulong) base));
- fn_format(path, file_name->str, dir->str, 0, MY_UNPACK_FILENAME);
- path_end= strlen(path);
+ if (dir)
+ {
+ fn_format(path, file_name->str, dir->str, 0, MY_UNPACK_FILENAME);
+ path_end= strlen(path);
+ }
+ else
+ {
+ /*
+ if not dir is passed, it means file_name is a full path,
+ including dir name, file name itself, and an extension,
+ and with unpack_filename() executed over it.
+ */
+ path_end= strxnmov(path, FN_REFLEN, file_name->str, NullS) - path;
+ }
// temporary file name
path[path_end]='~';
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 4d12922f75d..f24b30729b1 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2796,9 +2796,10 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if (!(rights & CREATE_ACL))
{
char buf[FN_REFLEN];
- sprintf(buf,"%s/%s/%s.frm",mysql_data_home, table_list->db,
- table_list->table_name);
- fn_format(buf,buf,"","",4+16+32);
+ build_table_filename(buf, sizeof(buf), table_list->db,
+ table_list->table_name, reg_ext);
+ fn_format(buf, buf, "", "", MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS |
+ MY_RETURN_REAL_PATH | MY_APPEND_EXT);
if (access(buf,F_OK))
{
my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 032cf485862..c1fad0a9bbf 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1819,9 +1819,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
{
char path[FN_REFLEN];
enum legacy_db_type not_used;
- strxnmov(path, FN_REFLEN-1, mysql_data_home, "/", table_list->db, "/",
- table_list->table_name, reg_ext, NullS);
- (void) unpack_filename(path, path);
+ build_table_filename(path, sizeof(path) - 1,
+ table_list->db, table_list->table_name, reg_ext);
if (mysql_frm_type(thd, path, &not_used) == FRMTYPE_VIEW)
{
/*
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 0e6c0c45cf1..d91f091174f 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -425,8 +425,7 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
}
/* Check directory */
- strxmov(path, mysql_data_home, "/", db, NullS);
- path_len= unpack_dirname(path,path); // Convert if not unix
+ path_len= build_table_filename(path, sizeof(path), db, "", "");
path[path_len-1]= 0; // Remove last '/' from path
if (my_stat(path,&stat_info,MYF(0)))
@@ -549,9 +548,12 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
if ((error=wait_if_global_read_lock(thd,0,1)))
goto exit2;
- /* Check directory */
- strxmov(path, mysql_data_home, "/", db, "/", MY_DB_OPT_FILE, NullS);
- fn_format(path, path, "", "", MYF(MY_UNPACK_FILENAME));
+ /*
+ Recreate db options file: /dbpath/.db.opt
+ We pass MY_DB_OPT_FILE as "extension" to avoid
+ "table name to file name" encoding.
+ */
+ build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE);
if ((error=write_db_opt(thd, path, create_info)))
goto exit;
@@ -629,8 +631,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
goto exit2;
}
- (void) sprintf(path,"%s/%s",mysql_data_home,db);
- length= unpack_dirname(path,path); // Convert if not unix
+ length= build_table_filename(path, sizeof(path), db, "", "");
strmov(path+length, MY_DB_OPT_FILE); // Append db option file name
del_dbopt(path); // Remove dboption hash entry
path[length]= '\0'; // Remove file name
@@ -852,7 +853,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
found_other_files++;
continue;
}
- extension= fn_ext(file->name);
+ if (!(extension= strrchr(file->name, '.')))
+ extension= strend(file->name);
if (find_type(extension, &deletable_extentions,1+2) <= 0)
{
if (find_type(extension, ha_known_exts(),1+2) <= 0)
@@ -870,7 +872,9 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
if (!table_list)
goto err;
table_list->db= (char*) (table_list+1);
- strmov(table_list->table_name= strmov(table_list->db,db)+1, file->name);
+ table_list->table_name= strmov(table_list->db, db) + 1;
+ VOID(filename_to_tablename(file->name, table_list->table_name,
+ strlen(file->name) + 1));
table_list->alias= table_list->table_name; // If lower_case_table_names=2
/* Link into list */
(*tot_list_next)= table_list;
@@ -1151,8 +1155,7 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
}
}
#endif
- (void) sprintf(path,"%s/%s",mysql_data_home,dbname);
- length=unpack_dirname(path,path); // Convert if not unix
+ length= build_table_filename(path, sizeof(path), dbname, "", "");
if (length && path[length-1] == FN_LIBCHAR)
path[length-1]=0; // remove ending '\'
if (my_access(path,F_OK))
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 66644abe9e3..ba1cce3abfe 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -837,6 +837,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
char path[FN_REFLEN];
TABLE *table;
bool error;
+ uint path_length;
DBUG_ENTER("mysql_truncate");
bzero((char*) &create_info,sizeof(create_info));
@@ -867,9 +868,8 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
goto end;
}
- (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,table_list->db,
- table_list->table_name,reg_ext);
- fn_format(path, path, "", "", MY_UNPACK_FILENAME);
+ path_length= build_table_filename(path, sizeof(path), table_list->db,
+ table_list->table_name, reg_ext);
if (!dont_send_ok)
{
@@ -889,7 +889,8 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
DBUG_RETURN(TRUE);
}
- *fn_ext(path)=0; // Remove the .frm extension
+ // Remove the .frm extension
+ *(path + path_length - reg_ext_length)= '\0';
error= ha_create_table(thd, path, table_list->db, table_list->table_name,
&create_info, 1);
query_cache_invalidate3(thd, table_list, 0);
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index a1bbb69bc17..150c1dba1c9 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -155,18 +155,15 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
old_alias= ren_table->table_name;
new_alias= new_table->table_name;
}
- sprintf(name,"%s/%s/%s%s",mysql_data_home,
- new_table->db, new_alias, reg_ext);
- unpack_filename(name, name);
+ build_table_filename(name, sizeof(name),
+ new_table->db, new_alias, reg_ext);
if (!access(name,F_OK))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
DBUG_RETURN(ren_table); // This can't be skipped
}
- sprintf(name,"%s/%s/%s%s",mysql_data_home,
- ren_table->db, old_alias,
- reg_ext);
- unpack_filename(name, name);
+ build_table_filename(name, sizeof(name),
+ ren_table->db, old_alias, reg_ext);
frm_type= mysql_frm_type(thd, name, &table_type);
switch (frm_type)
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index b7f7f1b9487..16a783a2ad0 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -413,9 +413,14 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
for (i=0 ; i < (uint) dirp->number_off_files ; i++)
{
+ char uname[NAME_LEN*3+1]; /* Unencoded name */
file=dirp->dir_entry+i;
if (dir)
{ /* Return databases */
+ if ((file->name[0] == '.' &&
+ ((file->name[1] == '.' && file->name[2] == '\0') ||
+ file->name[1] == '\0')))
+ continue; /* . or .. */
#ifdef USE_SYMDIR
char *ext;
char buff[FN_REFLEN];
@@ -432,17 +437,21 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
continue;
}
#endif
- if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat->st_mode) ||
- (wild && wild_compare(file->name,wild,0)))
- continue;
+ VOID(filename_to_tablename(file->name, uname, sizeof(uname)));
+ if (!MY_S_ISDIR(file->mystat->st_mode) ||
+ (wild && wild_compare(uname, wild, 0)))
+ continue;
+ file->name= uname;
}
else
{
// Return only .frm files which aren't temp files.
- if (my_strcasecmp(system_charset_info, ext=fn_ext(file->name),reg_ext) ||
+ if (my_strcasecmp(system_charset_info, ext=fn_rext(file->name),reg_ext) ||
is_prefix(file->name,tmp_file_prefix))
continue;
*ext=0;
+ VOID(filename_to_tablename(file->name, uname, sizeof(uname)));
+ file->name= uname;
if (wild)
{
if (lower_case_table_names)
@@ -604,8 +613,7 @@ bool mysqld_show_create_db(THD *thd, char *dbname,
}
else
{
- (void) sprintf(path,"%s/%s",mysql_data_home, dbname);
- length=unpack_dirname(path,path); // Convert if not unix
+ length= build_table_filename(path, sizeof(path), dbname, "", "");
found_libchar= 0;
if (length && path[length-1] == FN_LIBCHAR)
{
@@ -883,7 +891,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
HA_CREATE_INFO *create_info_arg)
{
List<Item> field_list;
- char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end;
+ char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, uname[NAME_LEN*3+1];
const char *alias;
String type(tmp, sizeof(tmp), system_charset_info);
Field **ptr,*field;
@@ -914,8 +922,14 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
if (table_list->schema_table)
alias= table_list->schema_table->table_name;
else
- alias= (lower_case_table_names == 2 ? table->alias :
- share->table_name.str);
+ {
+ if (lower_case_table_names == 2)
+ alias= table->alias;
+ else
+ {
+ alias= share->table_name.str;
+ }
+ }
append_identifier(thd, packet, alias, strlen(alias));
packet->append(STRING_WITH_LEN(" (\n"));
@@ -2312,8 +2326,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
}
else
{
- strxmov(path, mysql_data_home, "/", base_name, NullS);
- end= path + (len= unpack_dirname(path,path));
+ len= build_table_filename(path, sizeof(path), base_name, "", "");
+ end= path + len;
len= FN_LEN - len;
if (mysql_find_files(thd, &files, base_name,
path, idx_field_vals.table_value, 0))
@@ -2460,8 +2474,7 @@ int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond)
(grant_option && !check_grant_db(thd, file_name)))
#endif
{
- strxmov(path, mysql_data_home, "/", file_name, NullS);
- length=unpack_dirname(path,path); // Convert if not unix
+ length= build_table_filename(path, sizeof(path), file_name, "", "");
found_libchar= 0;
if (length && path[length-1] == FN_LIBCHAR)
{
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index be30e487f28..5a083fcdd22 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -103,28 +103,53 @@ static bool abort_and_upgrade_lock(THD *thd, TABLE *table, const char *db,
}
/*
- Build the path to a file for a table (or the base path that can
- then have various extensions stuck on to it).
+ Creates path to a file: mysql_data_dir/db/table.ext
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
+ build_table_filename()
+ buff where to write result
+ bufflen buff size
+ db database name, in system_charset_info
+ table table name, in system_charset_info
+ ext file extension
+
+ NOTES
+
+ Uses database and table name, and extension to create
+ a file name in mysql_data_dir. Database and table
+ names are converted from system_charset_info into "fscs".
+ 'ext' is not converted.
RETURN
- 0 Error
- # Size of path
- */
-static uint build_table_path(char *buff, size_t bufflen, const char *db,
+*/
+
+
+uint build_table_filename(char *buff, size_t bufflen, const char *db,
+ const char *table, const char *ext)
+{
+ uint length;
+ char dbbuff[FN_REFLEN];
+ char tbbuff[FN_REFLEN];
+ VOID(tablename_to_filename(table, tbbuff, sizeof(tbbuff)));
+ VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff)));
+ strxnmov(buff, bufflen,
+ mysql_data_home, "/", dbbuff, "/", tbbuff, ext, NullS);
+ length= unpack_filename(buff, buff);
+ return length;
+}
+
+
+uint build_tmptable_filename(char *buff, size_t bufflen,
+ const char *tmpdir,
const char *table, const char *ext)
{
- strxnmov(buff, bufflen-1, mysql_data_home, "/", db, "/", table, ext,
- NullS);
- return unpack_filename(buff,buff);
+ uint length;
+ char tbbuff[FN_REFLEN];
+ VOID(tablename_to_filename(table, tbbuff, sizeof(tbbuff)));
+ strxnmov(buff, bufflen, tmpdir, "/", tbbuff, ext, NullS);
+ length= unpack_filename(buff, buff);
+ return length;
}
@@ -276,7 +301,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool dont_log_query)
{
TABLE_LIST *table;
- char path[FN_REFLEN], *alias;
+ char path[FN_REFLEN], *alias;
+ uint path_length;
String wrong_tables;
int error;
int non_temp_tables_count= 0;
@@ -365,7 +391,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
/* remove .frm file and engine files */
- build_table_path(path, sizeof(path), db, alias, reg_ext);
+ path_length= build_table_filename(path, sizeof(path),
+ db, alias, reg_ext);
}
if (table_type == NULL &&
(drop_temporary ||
@@ -390,7 +417,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
mysql_frm_type(thd, path, &frm_db_type);
table_type= ha_resolve_by_legacy_type(thd, frm_db_type);
}
- *(end=fn_ext(path))=0; // Remove extension for delete
+ // Remove extension for delete
+ *(end= path + path_length - reg_ext_length)= '\0';
error= ha_delete_table(thd, table_type, path, db, table->table_name,
!dont_log_query);
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
@@ -495,10 +523,11 @@ bool quick_rm_table(handlerton *base,const char *db,
bool error= 0;
DBUG_ENTER("quick_rm_table");
- build_table_path(path, sizeof(path), db, table_name, reg_ext);
+ uint path_length= build_table_filename(path, sizeof(path),
+ db, table_name, reg_ext);
if (my_delete(path,MYF(0)))
error= 1; /* purecov: inspected */
- *fn_ext(path)= 0; // Remove reg_ext
+ path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
DBUG_RETURN(ha_delete_table(current_thd, base, path, db, table_name, 0) ||
error);
}
@@ -1562,8 +1591,8 @@ static void set_table_default_charset(THD *thd,
{
HA_CREATE_INFO db_info;
char path[FN_REFLEN];
- /* Abuse build_table_path() to build the path to the db.opt file */
- build_table_path(path, sizeof(path), db, MY_DB_OPT_FILE, "");
+ /* Abuse build_table_filename() to build the path to the db.opt file */
+ build_table_filename(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;
}
@@ -1707,6 +1736,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
uint select_field_count)
{
char path[FN_REFLEN];
+ uint path_length;
const char *alias;
uint db_options, key_count;
KEY *key_info_buffer;
@@ -1822,15 +1852,18 @@ bool 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[tmp_file_prefix_length+22+22+22+3];
+ my_snprintf(tmp_table_name, sizeof(tmp_table_name), "%s%lx_%lx_%x",
+ tmp_file_prefix, current_pid, thd->thread_id,
+ thd->tmp_table++);
+ path_length= build_tmptable_filename(path, sizeof(path), mysql_tmpdir,
+ tmp_table_name, reg_ext);
if (lower_case_table_names)
my_casedn_str(files_charset_info, path);
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
}
else
- build_table_path(path, sizeof(path), db, alias, reg_ext);
+ path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext);
/* Check if table already exists */
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
@@ -1894,6 +1927,7 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
create_info->data_file_name= create_info->index_file_name= 0;
create_info->table_options=db_options;
+ path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
if (rea_create_table(thd, path, db, table_name, create_info, fields,
key_count, key_info_buffer, file))
goto unlock_and_end;
@@ -1901,7 +1935,6 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{
/* Open table and put in temporary table list */
- *fn_ext(path)= 0;
if (!(open_temporary_table(thd, path, db, table_name, 1)))
{
(void) rm_temporary_table(create_info->db_type, path);
@@ -2105,8 +2138,8 @@ mysql_rename_table(handlerton *base,
file= (base == NULL ? 0 :
get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
- build_table_path(from, sizeof(from), old_db, old_name, "");
- build_table_path(to, sizeof(to), new_db, new_name, "");
+ build_table_filename(from, sizeof(from), old_db, old_name, "");
+ build_table_filename(to, sizeof(to), new_db, new_name, "");
/*
If lower_case_table_names == 2 (case-preserving but case-insensitive
@@ -2118,12 +2151,12 @@ mysql_rename_table(handlerton *base,
{
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, "");
+ build_table_filename(lc_from, sizeof(lc_from), old_db, tmp_name, "");
from_base= lc_from;
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, "");
+ build_table_filename(lc_to, sizeof(lc_to), new_db, tmp_name, "");
to_base= lc_to;
}
@@ -2248,23 +2281,21 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
else
{
char* backup_dir= thd->lex->backup_dir;
- char src_path[FN_REFLEN], dst_path[FN_REFLEN];
+ char src_path[FN_REFLEN], dst_path[FN_REFLEN], uname[FN_REFLEN];
char* table_name= table->table_name;
char* db= table->db;
- if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
- reg_ext))
+ VOID(tablename_to_filename(table->table_name, uname, sizeof(uname)));
+
+ if (fn_format_relative_to_data_home(src_path, uname, backup_dir, reg_ext))
DBUG_RETURN(-1); // protect buffer overflow
- my_snprintf(dst_path, sizeof(dst_path), "%s%s/%s",
- mysql_real_data_home, db, table_name);
+ build_table_filename(dst_path, sizeof(dst_path), db, table_name, reg_ext);
if (lock_and_wait_for_table_name(thd,table))
DBUG_RETURN(-1);
- if (my_copy(src_path,
- fn_format(dst_path, dst_path,"", reg_ext, 4),
- MYF(MY_WME)))
+ if (my_copy(src_path, dst_path, MYF(MY_WME)))
{
pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table);
@@ -2937,6 +2968,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
{
TABLE *tmp_table;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
+ uint dst_path_length;
char *db= table->db;
char *table_name= table->table_name;
char *src_db;
@@ -2976,8 +3008,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
strxmov(src_path, tmp_table->s->path.str, reg_ext, NullS);
else
{
- strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table,
- reg_ext, NullS);
+ build_table_filename(src_path, sizeof(src_path),
+ src_db, src_table, reg_ext);
/* Resolve symlinks (for windows) */
unpack_filename(src_path, src_path);
if (lower_case_table_names)
@@ -3008,18 +3040,18 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
{
if (find_temporary_table(thd, db, table_name))
goto table_exists;
- my_snprintf(dst_path, sizeof(dst_path), "%s%s%lx_%lx_%x%s",
- mysql_tmpdir, tmp_file_prefix, current_pid,
- thd->thread_id, thd->tmp_table++, reg_ext);
+ dst_path_length= my_snprintf(dst_path, sizeof(dst_path),
+ "%s%s%lx_%lx_%x%s",
+ mysql_tmpdir, tmp_file_prefix, current_pid,
+ thd->thread_id, thd->tmp_table++, reg_ext);
if (lower_case_table_names)
my_casedn_str(files_charset_info, dst_path);
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
}
else
{
- strxmov(dst_path, mysql_data_home, "/", db, "/", table_name,
- reg_ext, NullS);
- unpack_filename(dst_path, dst_path);
+ dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
+ db, table_name, reg_ext);
if (!access(dst_path, F_OK))
goto table_exists;
}
@@ -3041,7 +3073,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
creation, instead create the table directly (for both normal
and temporary tables).
*/
- *fn_ext(dst_path)= 0; // Remove .frm
+ dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -3324,10 +3356,10 @@ 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)||
- build_table_path(path, sizeof(path), table_list->db,
- (lower_case_table_names == 2) ?
- table_list->alias : table_list->table_name,
- reg_ext) == 0 ||
+ build_table_filename(path, sizeof(path), table_list->db,
+ (lower_case_table_names == 2) ?
+ table_list->alias : table_list->table_name,
+ reg_ext) == 0 ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
/* don't need to free((gptr) key_info_buffer);*/
@@ -3425,10 +3457,10 @@ 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)||
- build_table_path(path, sizeof(path), table_list->db,
- (lower_case_table_names == 2) ?
- table_list->alias : table_list->table_name,
- reg_ext) == 0 ||
+ build_table_filename(path, sizeof(path), table_list->db,
+ (lower_case_table_names == 2) ?
+ table_list->alias : table_list->table_name,
+ reg_ext) == 0 ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
/*don't need to free((gptr) key_numbers);*/
@@ -4532,7 +4564,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/
uint old_lock_type;
partition_info *part_info= table->part_info;
- char path[FN_REFLEN+1];
+ char path[FN_REFLEN+1], noext_path[FN_REFLEN+1];
uint db_options= 0, key_count, syntax_len;
KEY *key_info_buffer;
char *part_syntax_buf;
@@ -4555,7 +4587,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
part_info->part_info_string= part_syntax_buf;
part_info->part_info_len= syntax_len;
- build_table_path(path, sizeof(path), db, table_name, reg_ext);
+ build_table_filename(path, sizeof(path), db, table_name, reg_ext);
if (mysql_create_frm(thd, path, db, table_name, create_info,
create_list, key_count, key_info_buffer,
table->file))
@@ -4563,7 +4595,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_RETURN(TRUE);
}
thd->lex->part_info= part_info;
- build_table_path(path, sizeof(path), db, table_name, "");
+ build_table_filename(path, sizeof(path), db, table_name, "");
if (table->file->drop_partitions(path))
{
DBUG_RETURN(TRUE);
@@ -4591,11 +4623,12 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
part_info->part_info_string= part_syntax_buf;
part_info->part_info_len= syntax_len;
- build_table_path(path, sizeof(path), db, table_name, reg_ext);
+ build_table_filename(path, sizeof(path), db, table_name, reg_ext);
+ build_table_filename(noext_path, sizeof(noext_path), db, table_name, "");
if (mysql_create_frm(thd, path, db, table_name, create_info,
create_list, key_count, key_info_buffer,
table->file) ||
- table->file->create_handler_files(path))
+ table->file->create_handler_files(noext_path))
{
DBUG_RETURN(TRUE);
}
@@ -4688,9 +4721,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
char path[FN_REFLEN];
/* table is a normal table: Create temporary table in same directory */
- strxnmov(path, sizeof(path)-1, mysql_data_home, "/",new_db, "/",
- tmp_name, NullS);
- unpack_filename(path, path);
+ build_table_filename(path, sizeof(path), new_db, tmp_name, "");
new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
}
if (!new_table)
@@ -4906,7 +4937,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
shutdown.
*/
char path[FN_REFLEN];
- build_table_path(path, sizeof(path), new_db, table_name, "");
+ build_table_filename(path, sizeof(path), new_db, table_name, "");
table=open_temporary_table(thd, path, new_db, tmp_name,0);
if (table)
{
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 7b501364701..2b124fb5bb4 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -305,9 +305,9 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
{
LEX *lex= thd->lex;
TABLE *table= tables->table;
- char dir_buff[FN_REFLEN], file_buff[FN_REFLEN], trigname_buff[FN_REFLEN],
+ char file_buff[FN_REFLEN], trigname_buff[FN_REFLEN],
trigname_path[FN_REFLEN];
- LEX_STRING dir, file, trigname_file;
+ LEX_STRING file, trigname_file;
LEX_STRING *trg_def, *name;
ulonglong *trg_sql_mode;
char trg_definer_holder[HOSTNAME_LENGTH + USERNAME_LENGTH + 2];
@@ -386,20 +386,18 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
sql_create_definition_file() files handles renaming and backup of older
versions
*/
- strxnmov(dir_buff, FN_REFLEN-1, mysql_data_home, "/", tables->db, "/", NullS);
- dir.length= unpack_filename(dir_buff, dir_buff);
- dir.str= dir_buff;
- file.length= strxnmov(file_buff, FN_REFLEN-1, tables->table_name,
- triggers_file_ext, NullS) - file_buff;
+ file.length= build_table_filename(file_buff, FN_REFLEN-1,
+ tables->db, tables->table_name,
+ triggers_file_ext);
file.str= file_buff;
- trigname_file.length= strxnmov(trigname_buff, FN_REFLEN-1,
- lex->spname->m_name.str,
- trigname_file_ext, NullS) - trigname_buff;
+ trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1,
+ tables->db,
+ lex->spname->m_name.str,
+ trigname_file_ext);
trigname_file.str= trigname_buff;
- strxnmov(trigname_path, FN_REFLEN-1, dir_buff, trigname_buff, NullS);
/* Use the filesystem to enforce trigger namespace constraints. */
- if (!access(trigname_path, F_OK))
+ if (!access(trigname_buff, F_OK))
{
my_error(ER_TRG_ALREADY_EXISTS, MYF(0));
return 1;
@@ -408,7 +406,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
trigname.trigger_table.str= tables->table_name;
trigname.trigger_table.length= tables->table_name_length;
- if (sql_create_definition_file(&dir, &trigname_file, &trigname_file_type,
+ if (sql_create_definition_file(NULL, &trigname_file, &trigname_file_type,
(gptr)&trigname, trigname_file_parameters, 0))
return 1;
@@ -455,7 +453,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
trg_definer->length= strxmov(trg_definer->str, definer_user->str, "@",
definer_host->str, NullS) - trg_definer->str;
- if (!sql_create_definition_file(&dir, &file, &triggers_file_type,
+ if (!sql_create_definition_file(NULL, &file, &triggers_file_type,
(gptr)this, triggers_file_parameters,
TRG_MAX_VERSIONS))
return 0;
@@ -483,9 +481,7 @@ err_with_cleanup:
static bool rm_trigger_file(char *path, char *db, char *table_name)
{
- strxnmov(path, FN_REFLEN-1, mysql_data_home, "/", db, "/", table_name,
- triggers_file_ext, NullS);
- unpack_filename(path, path);
+ build_table_filename(path, FN_REFLEN-1, db, table_name, triggers_file_ext);
return my_delete(path, MYF(MY_WME));
}
@@ -507,9 +503,7 @@ static bool rm_trigger_file(char *path, char *db, char *table_name)
static bool rm_trigname_file(char *path, char *db, char *trigger_name)
{
- strxnmov(path, FN_REFLEN-1, mysql_data_home, "/", db, "/", trigger_name,
- trigname_file_ext, NullS);
- unpack_filename(path, path);
+ build_table_filename(path, FN_REFLEN-1, db, trigger_name, trigname_file_ext);
return my_delete(path, MYF(MY_WME));
}
@@ -567,18 +561,14 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
}
else
{
- char dir_buff[FN_REFLEN], file_buff[FN_REFLEN];
- LEX_STRING dir, file;
-
- strxnmov(dir_buff, FN_REFLEN-1, mysql_data_home, "/", tables->db,
- "/", NullS);
- dir.length= unpack_filename(dir_buff, dir_buff);
- dir.str= dir_buff;
- file.length= strxnmov(file_buff, FN_REFLEN-1, tables->table_name,
- triggers_file_ext, NullS) - file_buff;
- file.str= file_buff;
+ char file_buff[FN_REFLEN];
+ LEX_STRING file;
- if (sql_create_definition_file(&dir, &file, &triggers_file_type,
+ file.length= build_table_filename(file_buff, FN_REFLEN-1,
+ tables->db, tables->table_name,
+ triggers_file_ext);
+ file.str= file_buff;
+ if (sql_create_definition_file(NULL, &file, &triggers_file_type,
(gptr)this, triggers_file_parameters,
TRG_MAX_VERSIONS))
return 1;
@@ -692,9 +682,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
DBUG_ENTER("Table_triggers_list::check_n_load");
- strxnmov(path_buff, FN_REFLEN-1, mysql_data_home, "/", db, "/", table_name,
- triggers_file_ext, NullS);
- path.length= unpack_filename(path_buff, path_buff);
+ path.length= build_table_filename(path_buff, FN_REFLEN-1,
+ db, table_name, triggers_file_ext);
path.str= path_buff;
// QQ: should we analyze errno somehow ?
@@ -1026,9 +1015,9 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
struct st_trigname trigname;
DBUG_ENTER("add_table_for_trigger");
- strxnmov(path_buff, FN_REFLEN-1, mysql_data_home, "/", trig->m_db.str, "/",
- trig->m_name.str, trigname_file_ext, NullS);
- path.length= unpack_filename(path_buff, path_buff);
+ path.length= build_table_filename(path_buff, FN_REFLEN-1,
+ trig->m_db.str, trig->m_name.str,
+ trigname_file_ext);
path.str= path_buff;
if (access(path_buff, F_OK))
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index aea07be1eda..78497a2cf8b 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -568,8 +568,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
String str(buff,(uint32) sizeof(buff), system_charset_info);
char md5[MD5_BUFF_LENGTH];
bool can_be_merged;
- char dir_buff[FN_REFLEN], file_buff[FN_REFLEN];
- LEX_STRING dir, file;
+ char dir_buff[FN_REFLEN], file_buff[FN_REFLEN], path_buff[FN_REFLEN];
+ LEX_STRING dir, file, path;
DBUG_ENTER("mysql_register_view");
/* print query */
@@ -584,15 +584,17 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
DBUG_PRINT("info", ("View: %s", str.ptr()));
/* print file name */
- (void) my_snprintf(dir_buff, FN_REFLEN, "%s/%s/",
- mysql_data_home, view->db);
- unpack_filename(dir_buff, dir_buff);
+ dir.length= build_table_filename(dir_buff, sizeof(dir_buff),
+ view->db, "", "");
dir.str= dir_buff;
- dir.length= strlen(dir_buff);
- file.str= file_buff;
- file.length= (strxnmov(file_buff, FN_REFLEN-1, view->table_name, reg_ext,
- NullS) - file_buff);
+ path.length= build_table_filename(path_buff, sizeof(path_buff),
+ view->db, view->table_name, reg_ext);
+ path.str= path_buff;
+
+ file.str= path.str + dir.length;
+ file.length= path.length - dir.length;
+
/* init timestamp */
if (!view->timestamp.str)
view->timestamp.str= view->timestamp_buffer;
@@ -1184,9 +1186,8 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
{
TABLE_SHARE *share;
bool type= 0;
- strxnmov(path, FN_REFLEN-1, mysql_data_home, "/", view->db, "/",
- view->table_name, reg_ext, NullS);
- (void) unpack_filename(path, path);
+ build_table_filename(path, sizeof(path),
+ view->db, view->table_name, reg_ext);
VOID(pthread_mutex_lock(&LOCK_open));
if (access(path, F_OK) ||
(type= (mysql_frm_type(thd, path, &not_used) != FRMTYPE_VIEW)))
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
index c822d10af46..4eb20faa97c 100644
--- a/sql/strfunc.cc
+++ b/sql/strfunc.cc
@@ -235,3 +235,79 @@ uint check_word(TYPELIB *lib, const char *val, const char *end,
*end_of_word= ptr;
return res;
}
+
+
+/*
+ Converts a string between character sets
+
+ SYNOPSIS
+ strconvert()
+ from_cs source character set
+ from source, a null terminated string
+ to destination buffer
+ to_length destination buffer length
+
+ NOTES
+ 'to' is always terminated with a '\0' character.
+ If there is no enough space to convert whole string,
+ only prefix is converted, and terminated with '\0'.
+
+ RETURN VALUES
+ result string length
+*/
+
+
+uint strconvert(CHARSET_INFO *from_cs, const char *from,
+ CHARSET_INFO *to_cs, char *to, uint to_length)
+{
+ int cnvres;
+ my_wc_t wc;
+ char *to_start= to;
+ uchar *to_end= (uchar*) to + to_length - 1;
+ int (*mb_wc)(struct charset_info_st *, my_wc_t *, const uchar *,
+ const uchar *)= from_cs->cset->mb_wc;
+ int (*wc_mb)(struct charset_info_st *, my_wc_t, uchar *s, uchar *e)=
+ to_cs->cset->wc_mb;
+ uint error_count= 0;
+
+ while (1)
+ {
+ /*
+ Using 'from + 10' is safe:
+ - it is enough to scan a single character in any character set.
+ - if remaining string is shorter than 10, then mb_wc will return
+ with error because of unexpected '\0' character.
+ */
+ if ((cnvres= (*mb_wc)(from_cs, &wc,
+ (uchar*) from, (uchar*) from + 10)) > 0)
+ {
+ if (!wc)
+ break;
+ from+= cnvres;
+ }
+ else if (cnvres == MY_CS_ILSEQ)
+ {
+ error_count++;
+ from++;
+ wc= '?';
+ }
+ else
+ break; // Impossible char.
+
+outp:
+
+ if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
+ to+= cnvres;
+ else if (cnvres == MY_CS_ILUNI && wc != '?')
+ {
+ error_count++;
+ wc= '?';
+ goto outp;
+ }
+ else
+ break;
+ }
+ *to= '\0';
+ return (uint32) (to - to_start);
+
+}
diff --git a/sql/table.cc b/sql/table.cc
index bf208918346..02d56eb01e8 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -43,6 +43,37 @@ static byte *get_field_name(Field **buff, uint *length,
}
+
+/*
+ Returns pointer to '.frm' extension of the file name.
+
+ SYNOPSIS
+ fn_rext()
+ name file name
+
+ DESCRIPTION
+ Checks file name part starting with the rightmost '.' character,
+ and returns it if it is equal to '.frm'.
+
+ TODO
+ It is a good idea to get rid of this function modifying the code
+ to garantee that the functions presently calling fn_rext() always
+ get arguments in the same format: either with '.frm' or without '.frm'.
+
+ RETURN VALUES
+ Pointer to the '.frm' extension. If there is no extension,
+ or extension is not '.frm', pointer at the end of file name.
+*/
+
+char *fn_rext(char *name)
+{
+ char *res= strrchr(name, '.');
+ if (res && !strcmp(res, ".frm"))
+ return res;
+ return name + strlen(name);
+}
+
+
/*
Allocate a setup TABLE_SHARE structure
@@ -65,9 +96,13 @@ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key,
char path[FN_REFLEN], normalized_path[FN_REFLEN];
uint path_length, normalized_length;
- path_length= (uint) (strxmov(path, mysql_data_home, "/", table_list->db,
- "/", table_list->table_name, NullS) - path);
- normalized_length= unpack_filename(normalized_path, path);
+ path_length= build_table_filename(path, sizeof(path) - 1,
+ table_list->db,
+ table_list->table_name, "");
+ normalized_length= build_table_filename(normalized_path,
+ sizeof(normalized_path) - 1,
+ table_list->db,
+ table_list->table_name, "");
init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
if ((share= (TABLE_SHARE*) alloc_root(&mem_root,
@@ -1883,6 +1918,7 @@ void append_unescaped(String *res, const char *pos, uint length)
res->append('\'');
}
+
/* Create a .frm file */
File create_frm(THD *thd, const char *name, const char *db,
@@ -2103,9 +2139,6 @@ bool check_db_name(char *name)
#else
last_char_is_space= *name==' ';
#endif
- if (*name == '/' || *name == '\\' || *name == FN_LIBCHAR ||
- *name == FN_EXTCHAR)
- return 1;
name++;
}
return last_char_is_space || (uint) (name - start) > NAME_LEN;
@@ -2114,8 +2147,7 @@ bool check_db_name(char *name)
/*
Allow anything as a table name, as long as it doesn't contain an
- a '/', or a '.' character
- or ' ' at the end
+ ' ' at the end
returns 1 on error
*/
@@ -2146,8 +2178,6 @@ bool check_table_name(const char *name, uint length)
}
}
#endif
- if (*name == '/' || *name == '\\' || *name == FN_EXTCHAR)
- return 1;
name++;
}
#if defined(USE_MB) && defined(USE_MB_IDENT)
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 66be20736e8..7b15e14bdaf 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -93,6 +93,7 @@ bool mysql_create_frm(THD *thd, const char *file_name,
thd->lex->part_info= NULL;
#endif
+ DBUG_ASSERT(*fn_rext((char*)file_name)); // Check .frm extension
formnames.type_names=0;
if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0)))
DBUG_RETURN(1);
@@ -289,7 +290,7 @@ err3:
SYNOPSIS
rea_create_table()
thd Thread handler
- path Name of file (including database and .frm)
+ path Name of file (including database, without .frm)
db Data base name
table_name Table name
create_info create info parameters
@@ -309,25 +310,26 @@ int rea_create_table(THD *thd, const char *path,
List<create_field> &create_fields,
uint keys, KEY *key_info, handler *file)
{
- char *ext;
DBUG_ENTER("rea_create_table");
- if (mysql_create_frm(thd, path, db, table_name, create_info,
+ char frm_name[FN_REFLEN];
+ strxmov(frm_name, path, reg_ext, NullS);
+ if (mysql_create_frm(thd, frm_name, db, table_name, create_info,
create_fields, keys, key_info, file))
+
DBUG_RETURN(1);
+
+ // Make sure mysql_create_frm din't remove extension
+ DBUG_ASSERT(*fn_rext(frm_name));
if (file->create_handler_files(path))
goto err_handler;
- *(ext= fn_ext(path))= 0; // Remove .frm
if (!create_info->frm_only && ha_create_table(thd, path, db, table_name,
create_info,0))
- {
- *ext= FN_EXTCHAR; // Add extension back
goto err_handler;
- }
DBUG_RETURN(0);
err_handler:
- my_delete(path, MYF(0));
+ my_delete(frm_name, MYF(0));
DBUG_RETURN(1);
} /* rea_create_table */