diff options
author | bar@mysql.com <> | 2005-12-31 09:01:26 +0400 |
---|---|---|
committer | bar@mysql.com <> | 2005-12-31 09:01:26 +0400 |
commit | 6ff211329f8c513c2b8ec7e3ef1652e1ff7d7b8c (patch) | |
tree | 6a3476c826545341821fbccb1f42ba381c5ca30a /sql | |
parent | 83d8979ca28da67a054fff6c8f9e127e38f26ecb (diff) | |
download | mariadb-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.cc | 6 | ||||
-rw-r--r-- | sql/ha_berkeley.cc | 25 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 2 | ||||
-rw-r--r-- | sql/ha_myisam.cc | 10 | ||||
-rw-r--r-- | sql/ha_myisammrg.cc | 13 | ||||
-rw-r--r-- | sql/ha_ndbcluster.cc | 3 | ||||
-rw-r--r-- | sql/ha_partition.cc | 7 | ||||
-rw-r--r-- | sql/handler.cc | 2 | ||||
-rw-r--r-- | sql/init.cc | 1 | ||||
-rw-r--r-- | sql/mysql_priv.h | 18 | ||||
-rw-r--r-- | sql/mysqld.cc | 4 | ||||
-rw-r--r-- | sql/parse_file.cc | 16 | ||||
-rw-r--r-- | sql/sql_acl.cc | 7 | ||||
-rw-r--r-- | sql/sql_base.cc | 5 | ||||
-rw-r--r-- | sql/sql_db.cc | 25 | ||||
-rw-r--r-- | sql/sql_delete.cc | 9 | ||||
-rw-r--r-- | sql/sql_rename.cc | 11 | ||||
-rw-r--r-- | sql/sql_show.cc | 39 | ||||
-rw-r--r-- | sql/sql_table.cc | 161 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 63 | ||||
-rw-r--r-- | sql/sql_view.cc | 25 | ||||
-rw-r--r-- | sql/strfunc.cc | 76 | ||||
-rw-r--r-- | sql/table.cc | 50 | ||||
-rw-r--r-- | sql/unireg.cc | 18 |
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, ¬_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, ¬_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 */ |