diff options
-rw-r--r-- | configure.in | 10 | ||||
-rw-r--r-- | myisam/mi_open.c | 7 | ||||
-rw-r--r-- | mysql-test/r/repair.result | 3 | ||||
-rw-r--r-- | mysql-test/r/repair_part2.result | 8 | ||||
-rw-r--r-- | mysql-test/r/update.result | 16 | ||||
-rw-r--r-- | mysql-test/t/repair.test | 4 | ||||
-rw-r--r-- | mysql-test/t/repair_part2-master.sh | 1 | ||||
-rw-r--r-- | mysql-test/t/repair_part2.test | 7 | ||||
-rw-r--r-- | mysql-test/t/update.test | 15 | ||||
-rw-r--r-- | sql/handler.cc | 10 | ||||
-rw-r--r-- | sql/sql_table.cc | 142 |
11 files changed, 149 insertions, 74 deletions
diff --git a/configure.in b/configure.in index a1ea566435b..3b00f5343ce 100644 --- a/configure.in +++ b/configure.in @@ -1007,8 +1007,9 @@ case $SYSTEM_TYPE in *darwin5*) if test "$ac_cv_prog_gcc" = "yes" then - CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE" - CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE" + FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE" + CFLAGS="$CFLAGS $FLAGS" + CXXFLAGS="$CXXFLAGS $FLAGS" MAX_C_OPTIMIZE="-O" with_named_curses="" fi @@ -1016,8 +1017,9 @@ case $SYSTEM_TYPE in *darwin6*) if test "$ac_cv_prog_gcc" = "yes" then - CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE" - CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE" + FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE" + CFLAGS="$CFLAGS $FLAGS" + CXXFLAGS="$CXXFLAGS $FLAGS" MAX_C_OPTIMIZE="-O" fi ;; diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 0ccc8a3bf40..99b97db3fbd 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -114,8 +114,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) errpos=1; if (my_read(kfile,(char*) share->state.header.file_version,head_length, MYF(MY_NABP))) + { + my_errno= HA_ERR_NOT_A_TABLE; goto err; - + } if (memcmp((byte*) share->state.header.file_version, (byte*) myisam_file_magic, 4)) { @@ -165,7 +167,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) } errpos=3; if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP))) + { + my_errno=HA_ERR_CRASHED; goto err; + } len=mi_uint2korr(share->state.header.state_info_length); keys= (uint) share->state.header.keys; uniques= (uint) share->state.header.uniques; diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index ad869787b8a..6c2107b2cf3 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -11,4 +11,5 @@ test.t1 repair error The handler for the table doesn't support repair drop table t1; repair table t1 use_frm; Table Op Msg_type Msg_text -t1 repair error table is read-only or does not exists +test.t1 repair error Table 'test.t1' doesn't exist +create table t1 type=myisam SELECT 1,"table 1"; diff --git a/mysql-test/r/repair_part2.result b/mysql-test/r/repair_part2.result new file mode 100644 index 00000000000..77aa98c3da9 --- /dev/null +++ b/mysql-test/r/repair_part2.result @@ -0,0 +1,8 @@ +repair table t1; +Table Op Msg_type Msg_text +test.t1 repair error Can't open file: 't1.MYI'. (errno: 130) +repair table t1 use_frm; +Table Op Msg_type Msg_text +test.t1 repair warning Number of rows changed from 0 to 1 +test.t1 repair status OK +drop table t1; diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 5357e8367e3..11aff8fe50a 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -150,3 +150,19 @@ select * from t1; id_param nom_option valid 185 test 1 drop table t1; +create table t1 (F1 VARCHAR(30), F2 VARCHAR(30), F3 VARCHAR(30), cnt int, groupid int, KEY groupid_index (groupid)); +insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6), +('0','1','2',1,5), ('0','2','0',1,3), ('1','0','1',1,2), +('1','2','1',1,1), ('1','2','2',1,1), ('2','0','1',2,4), +('2','2','0',1,7); +delete from t1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3); +select * from t1; +F1 F2 F3 cnt groupid +0 0 0 1 6 +0 1 2 1 5 +0 2 0 1 3 +1 0 1 1 2 +1 2 1 1 1 +2 0 1 2 4 +2 2 0 1 7 +drop table t1; diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test index e7da79d8c9e..159fc090653 100644 --- a/mysql-test/t/repair.test +++ b/mysql-test/t/repair.test @@ -12,4 +12,8 @@ drop table t1; # non-existent table repair table t1 use_frm; +# +# Create test table for repair2 +# The following must be last in this file +create table t1 type=myisam SELECT 1,"table 1"; diff --git a/mysql-test/t/repair_part2-master.sh b/mysql-test/t/repair_part2-master.sh new file mode 100644 index 00000000000..964bde06c18 --- /dev/null +++ b/mysql-test/t/repair_part2-master.sh @@ -0,0 +1 @@ +echo "1" > $MYSQL_TEST_DIR/var/master-data/test/t1.MYI diff --git a/mysql-test/t/repair_part2.test b/mysql-test/t/repair_part2.test new file mode 100644 index 00000000000..8c27e382dff --- /dev/null +++ b/mysql-test/t/repair_part2.test @@ -0,0 +1,7 @@ +# +# This test starts with a crashed t1.MYI file left over from repair.test +# + +repair table t1; +repair table t1 use_frm; +drop table t1; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 6ac8543ec93..a455b308158 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -108,3 +108,18 @@ INSERT INTO t1 (id_param,nom_option,valid) VALUES (185,'600x1200',1); UPDATE t1 SET nom_option='test' WHERE id_param=185 AND nom_option='600x1200' AND valid=1 LIMIT 1; select * from t1; drop table t1; + +# +# Multi table update test from bugs +# + +create table t1 (F1 VARCHAR(30), F2 VARCHAR(30), F3 VARCHAR(30), cnt int, groupid int, KEY groupid_index (groupid)); + +insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6), +('0','1','2',1,5), ('0','2','0',1,3), ('1','0','1',1,2), +('1','2','1',1,1), ('1','2','2',1,1), ('2','0','1',2,4), +('2','2','0',1,7); + +delete from t1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3); +select * from t1; +drop table t1; diff --git a/sql/handler.cc b/sql/handler.cc index ba7799fef4a..45c83355c94 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -830,7 +830,8 @@ void handler::print_error(int error, myf errflag) DBUG_VOID_RETURN; } - /* Return key if error because of duplicated keys */ + +/* Return key if error because of duplicated keys */ uint handler::get_dup_key(int error) { @@ -841,6 +842,7 @@ uint handler::get_dup_key(int error) DBUG_RETURN(table->file->errkey); } + int handler::delete_table(const char *name) { int error=0; @@ -867,9 +869,10 @@ int handler::rename_table(const char * from, const char * to) DBUG_RETURN(0); } -/* Tell the handler to turn on or off logging to the handler's - recovery log +/* + Tell the handler to turn on or off logging to the handler's recovery log */ + int ha_recovery_logging(THD *thd, bool on) { int error=0; @@ -914,7 +917,6 @@ int handler::delete_all_rows() int ha_create_table(const char *name, HA_CREATE_INFO *create_info, bool update_create_info) - { int error; TABLE table; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 90239c1c7ea..07ec1d67538 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -946,6 +946,7 @@ static void safe_remove_from_cache(THD *thd,TABLE *table) DBUG_VOID_RETURN; } + bool close_cached_table(THD *thd,TABLE *table) { DBUG_ENTER("close_cached_table"); @@ -957,7 +958,8 @@ bool close_cached_table(THD *thd,TABLE *table) /* Close lock if this is not got with LOCK TABLES */ if (thd->lock) { - mysql_unlock_tables(thd, thd->lock); thd->lock=0; // Start locked threads + mysql_unlock_tables(thd, thd->lock); + thd->lock=0; // Start locked threads } /* Close all copies of 'table'. This also frees all LOCK TABLES lock */ thd->open_tables=unlink_open_table(thd,thd->open_tables,table); @@ -1045,93 +1047,105 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table, } -static int prepare_for_repair(THD* thd, TABLE_LIST* table, +static int prepare_for_repair(THD* thd, TABLE_LIST *table_list, HA_CHECK_OPT *check_opt) { + int error= 0; + TABLE tmp_table, *table; DBUG_ENTER("prepare_for_repair"); - if (!table->table) - { - DBUG_RETURN(send_check_errmsg(thd, table, "repair", "table is read-only or does not exists")); - } - if (!(check_opt->sql_flags & TT_USEFRM)) - { DBUG_RETURN(0); - } - else + + if (!(table= table_list->table)) /* if open_ltable failed */ { - /* - User gave us USE_FRM which means that the header in the index file is - trashed. - In this case we will try to fix the table the following way: - - Rename the data file to a temporary name - - Truncate the table - - Replace the new data file with the old one - - Run a normal repair using the new index file and the old data file - */ + char name[FN_REFLEN]; + strxmov(name, mysql_data_home, "/", table_list->db, "/", + table_list->real_name, NullS); + if (openfrm(name, "", 0, 0, 0, &tmp_table)) + DBUG_RETURN(0); // Can't open frm file + table= &tmp_table; + } - char from[FN_REFLEN],tmp[FN_REFLEN+32]; - const char **ext= table->table->file->bas_ext(); - MY_STAT stat_info; + /* + User gave us USE_FRM which means that the header in the index file is + trashed. + In this case we will try to fix the table the following way: + - Rename the data file to a temporary name + - Truncate the table + - Replace the new data file with the old one + - Run a normal repair using the new index file and the old data file + */ - /* - Check if this is a table type that stores index and data separately, - like ISAM or MyISAM - */ - if (!ext[0] || !ext[1]) - DBUG_RETURN(0); // No data file + char from[FN_REFLEN],tmp[FN_REFLEN+32]; + const char **ext= table->file->bas_ext(); + MY_STAT stat_info; - strxmov(from, table->table->path, ext[1], NullS); // Name of data file - if (!my_stat(from, &stat_info, MYF(0))) - DBUG_RETURN(0); // Can't use USE_FRM flag + /* + Check if this is a table type that stores index and data separately, + like ISAM or MyISAM + */ + if (!ext[0] || !ext[1]) + goto end; // No data file - sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id); + strxmov(from, table->path, ext[1], NullS); // Name of data file + if (!my_stat(from, &stat_info, MYF(0))) + goto end; // Can't use USE_FRM flag - pthread_mutex_lock(&LOCK_open); - close_cached_table(thd,table->table); - pthread_mutex_unlock(&LOCK_open); + sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id); - if (lock_and_wait_for_table_name(thd,table)) - DBUG_RETURN(-1); + pthread_mutex_lock(&LOCK_open); + close_cached_table(thd,table_list->table); + pthread_mutex_unlock(&LOCK_open); - if (my_rename(from, tmp, MYF(MY_WME))) - { - pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, table); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(send_check_errmsg(thd, table, "repair", - "Failed renaming data file")); - } - if (mysql_truncate(thd, table, 1)) - { - pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, table); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(send_check_errmsg(thd, table, "repair", - "Failed generating table from .frm file")); - } - if (my_rename(tmp, from, MYF(MY_WME))) - { - pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, table); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(send_check_errmsg(thd, table, "repair", - "Failed restoring .MYD file")); - } + if (lock_and_wait_for_table_name(thd,table_list)) + { + error= -1; + goto end; + } + if (my_rename(from, tmp, MYF(MY_WME))) + { + pthread_mutex_lock(&LOCK_open); + unlock_table_name(thd, table_list); + pthread_mutex_unlock(&LOCK_open); + error= send_check_errmsg(thd, table_list, "repair", + "Failed renaming data file"); + goto end; + } + if (mysql_truncate(thd, table_list, 1)) + { + pthread_mutex_lock(&LOCK_open); + unlock_table_name(thd, table_list); + pthread_mutex_unlock(&LOCK_open); + error= send_check_errmsg(thd, table_list, "repair", + "Failed generating table from .frm file"); + goto end; + } + if (my_rename(tmp, from, MYF(MY_WME))) + { + pthread_mutex_lock(&LOCK_open); + unlock_table_name(thd, table_list); + pthread_mutex_unlock(&LOCK_open); + error= send_check_errmsg(thd, table_list, "repair", + "Failed restoring .MYD file"); + goto end; } /* Now we should be able to open the partially repaired table to finish the repair in the handler later on. */ - if (!(table->table = reopen_name_locked_table(thd, table))) + if (!(table_list->table = reopen_name_locked_table(thd, table_list))) { pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, table); + unlock_table_name(thd, table_list); pthread_mutex_unlock(&LOCK_open); } - DBUG_RETURN(0); + +end: + if (table == &tmp_table) + closefrm(table); // Free allocated memory + DBUG_RETURN(error); } |