Bug #29325:

By default MyISAM overwrites .MYD and .MYI files no 
DATA DIRECTORY option is used. This can lead to two tables
using the same .MYD and .MYI files (that can't be dropped).

To prevent CREATE TABLE from overwriting a file a new option
is introduced : keep_files_on_create
When this is on the CREATE TABLE throws an error if either
the .MYD or .MYI exists for a MyISAM table.
The option is off by default (resulting in compatible behavior).
parent 5b1e1eea
...@@ -279,6 +279,7 @@ enum ha_base_keytype { ...@@ -279,6 +279,7 @@ enum ha_base_keytype {
#define HA_PACK_RECORD 2 /* Request packed record format */ #define HA_PACK_RECORD 2 /* Request packed record format */
#define HA_CREATE_TMP_TABLE 4 #define HA_CREATE_TMP_TABLE 4
#define HA_CREATE_CHECKSUM 8 #define HA_CREATE_CHECKSUM 8
#define HA_CREATE_KEEP_FILES 16 /* don't overwrite .MYD and MYI */
#define HA_CREATE_DELAY_KEY_WRITE 64 #define HA_CREATE_DELAY_KEY_WRITE 64
/* /*
......
...@@ -586,7 +586,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, ...@@ -586,7 +586,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
32 : 0)); 32 : 0));
linkname_ptr=0; linkname_ptr=0;
/* Replace the current file */ /* Replace the current file */
create_flag=MY_DELETE_OLD; if (!(flags & HA_CREATE_KEEP_FILES))
create_flag=MY_DELETE_OLD;
} }
/* /*
...@@ -647,7 +648,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, ...@@ -647,7 +648,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
{ {
fn_format(filename,name,"",MI_NAME_DEXT,4); fn_format(filename,name,"",MI_NAME_DEXT,4);
linkname_ptr=0; linkname_ptr=0;
create_flag=MY_DELETE_OLD; if (!(flags & HA_CREATE_KEEP_FILES))
create_flag=MY_DELETE_OLD;
} }
if ((dfile= if ((dfile=
my_create_with_symlink(linkname_ptr, filename, 0, create_mode, my_create_with_symlink(linkname_ptr, filename, 0, create_mode,
......
...@@ -1503,4 +1503,21 @@ t1 CREATE TABLE `t1` ( ...@@ -1503,4 +1503,21 @@ t1 CREATE TABLE `t1` (
`c17` int(11) default NULL `c17` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
CREATE DATABASE db1;
CREATE DATABASE db2;
USE db2;
INSERT INTO db2.t1 VALUES (1);
SELECT * FROM db2.t1;
b
1
RESET QUERY CACHE;
USE db1;
SET SESSION keep_files_on_create = TRUE;
CREATE TABLE t1 (a INT) ENGINE MYISAM;
ERROR HY000: Can't create/write to file './db1/t1.MYD' (Errcode: 17)
SET SESSION keep_files_on_create = DEFAULT;
DROP TABLE db2.t1;
DROP DATABASE db1;
DROP DATABASE db2;
USE test;
End of 5.0 tests End of 5.0 tests
...@@ -1118,5 +1118,36 @@ show create table t1; ...@@ -1118,5 +1118,36 @@ show create table t1;
drop table t1; drop table t1;
#
# Bug #29325: create table overwrites .MYD file of other table (datadir)
#
CREATE DATABASE db1;
CREATE DATABASE db2;
USE db2;
--disable_query_log
eval CREATE TABLE t1 (b INT) ENGINE MYISAM
DATA DIRECTORY = '$MYSQLTEST_VARDIR/master-data/db1/';
--enable_query_log
INSERT INTO db2.t1 VALUES (1);
SELECT * FROM db2.t1;
RESET QUERY CACHE;
USE db1;
#no warning from create table
SET SESSION keep_files_on_create = TRUE;
--disable_abort_on_error
CREATE TABLE t1 (a INT) ENGINE MYISAM;
--enable_abort_on_error
SET SESSION keep_files_on_create = DEFAULT;
DROP TABLE db2.t1;
DROP DATABASE db1;
DROP DATABASE db2;
USE test;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -1809,6 +1809,8 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, ...@@ -1809,6 +1809,8 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE) if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= HA_CREATE_TMP_TABLE; create_flags|= HA_CREATE_TMP_TABLE;
if (ha_create_info->options & HA_CREATE_KEEP_FILES)
create_flags|= HA_CREATE_KEEP_FILES;
if (options & HA_OPTION_PACK_RECORD) if (options & HA_OPTION_PACK_RECORD)
create_flags|= HA_PACK_RECORD; create_flags|= HA_PACK_RECORD;
if (options & HA_OPTION_CHECKSUM) if (options & HA_OPTION_CHECKSUM)
......
...@@ -592,6 +592,10 @@ sys_var_const_str sys_license("license", STRINGIFY_ARG(LICENSE)); ...@@ -592,6 +592,10 @@ sys_var_const_str sys_license("license", STRINGIFY_ARG(LICENSE));
/* Global read-only variable containing hostname */ /* Global read-only variable containing hostname */
sys_var_const_str sys_hostname("hostname", glob_hostname); sys_var_const_str sys_hostname("hostname", glob_hostname);
sys_var_thd_bool sys_keep_files_on_create("keep_files_on_create",
&SV::keep_files_on_create);
/* /*
...@@ -637,6 +641,7 @@ sys_var *sys_variables[]= ...@@ -637,6 +641,7 @@ sys_var *sys_variables[]=
&sys_delayed_insert_limit, &sys_delayed_insert_limit,
&sys_delayed_insert_timeout, &sys_delayed_insert_timeout,
&sys_delayed_queue_size, &sys_delayed_queue_size,
&sys_keep_files_on_create,
&sys_error_count, &sys_error_count,
&sys_expire_logs_days, &sys_expire_logs_days,
&sys_flush, &sys_flush,
...@@ -849,6 +854,7 @@ struct show_var_st init_vars[]= { ...@@ -849,6 +854,7 @@ struct show_var_st init_vars[]= {
{sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS}, {sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS},
{sys_delayed_queue_size.name,(char*) &sys_delayed_queue_size, SHOW_SYS}, {sys_delayed_queue_size.name,(char*) &sys_delayed_queue_size, SHOW_SYS},
{sys_div_precincrement.name,(char*) &sys_div_precincrement,SHOW_SYS}, {sys_div_precincrement.name,(char*) &sys_div_precincrement,SHOW_SYS},
{sys_keep_files_on_create.name,(char*) &sys_keep_files_on_create, SHOW_SYS},
{sys_engine_condition_pushdown.name, {sys_engine_condition_pushdown.name,
(char*) &sys_engine_condition_pushdown, SHOW_SYS}, (char*) &sys_engine_condition_pushdown, SHOW_SYS},
{sys_expire_logs_days.name, (char*) &sys_expire_logs_days, SHOW_SYS}, {sys_expire_logs_days.name, (char*) &sys_expire_logs_days, SHOW_SYS},
......
...@@ -566,6 +566,7 @@ struct system_variables ...@@ -566,6 +566,7 @@ struct system_variables
my_bool new_mode; my_bool new_mode;
my_bool query_cache_wlock_invalidate; my_bool query_cache_wlock_invalidate;
my_bool engine_condition_pushdown; my_bool engine_condition_pushdown;
my_bool keep_files_on_create;
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
my_bool innodb_table_locks; my_bool innodb_table_locks;
......
...@@ -2841,6 +2841,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST *src_table, ...@@ -2841,6 +2841,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST *src_table,
and temporary tables). and temporary tables).
*/ */
*fn_ext(dst_path)= 0; *fn_ext(dst_path)= 0;
if (thd->variables.keep_files_on_create)
create_info->options|= HA_CREATE_KEEP_FILES;
err= ha_create_table(dst_path, create_info, 1); err= ha_create_table(dst_path, create_info, 1);
if (create_info->options & HA_LEX_CREATE_TMP_TABLE) if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
......
...@@ -285,6 +285,8 @@ int rea_create_table(THD *thd, my_string file_name, ...@@ -285,6 +285,8 @@ int rea_create_table(THD *thd, my_string file_name,
if (mysql_create_frm(thd, file_name, db, table, create_info, if (mysql_create_frm(thd, file_name, db, table, create_info,
create_fields, keys, key_info, NULL)) create_fields, keys, key_info, NULL))
DBUG_RETURN(1); DBUG_RETURN(1);
if (thd->variables.keep_files_on_create)
create_info->options|= HA_CREATE_KEEP_FILES;
if (!create_info->frm_only && ha_create_table(file_name,create_info,0)) if (!create_info->frm_only && ha_create_table(file_name,create_info,0))
{ {
my_delete(file_name,MYF(0)); my_delete(file_name,MYF(0));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment