mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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.
This commit is contained in:
161
sql/sql_table.cc
161
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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user