summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.in10
-rw-r--r--myisam/mi_open.c7
-rw-r--r--mysql-test/r/repair.result3
-rw-r--r--mysql-test/r/repair_part2.result8
-rw-r--r--mysql-test/r/update.result16
-rw-r--r--mysql-test/t/repair.test4
-rw-r--r--mysql-test/t/repair_part2-master.sh1
-rw-r--r--mysql-test/t/repair_part2.test7
-rw-r--r--mysql-test/t/update.test15
-rw-r--r--sql/handler.cc10
-rw-r--r--sql/sql_table.cc142
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);
}