Commit 3e72b423 authored by monty@narttu.mysql.fi's avatar monty@narttu.mysql.fi

Fix for MacOSX and symlinks

Fix for USE_FRM and crashed index file
parent c4d32704
...@@ -1007,8 +1007,9 @@ case $SYSTEM_TYPE in ...@@ -1007,8 +1007,9 @@ case $SYSTEM_TYPE in
*darwin5*) *darwin5*)
if test "$ac_cv_prog_gcc" = "yes" if test "$ac_cv_prog_gcc" = "yes"
then 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" 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"
CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE" CFLAGS="$CFLAGS $FLAGS"
CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O" MAX_C_OPTIMIZE="-O"
with_named_curses="" with_named_curses=""
fi fi
...@@ -1016,8 +1017,9 @@ case $SYSTEM_TYPE in ...@@ -1016,8 +1017,9 @@ case $SYSTEM_TYPE in
*darwin6*) *darwin6*)
if test "$ac_cv_prog_gcc" = "yes" if test "$ac_cv_prog_gcc" = "yes"
then 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" 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"
CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE" CFLAGS="$CFLAGS $FLAGS"
CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O" MAX_C_OPTIMIZE="-O"
fi fi
;; ;;
......
...@@ -114,8 +114,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -114,8 +114,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
errpos=1; errpos=1;
if (my_read(kfile,(char*) share->state.header.file_version,head_length, if (my_read(kfile,(char*) share->state.header.file_version,head_length,
MYF(MY_NABP))) MYF(MY_NABP)))
{
my_errno= HA_ERR_NOT_A_TABLE;
goto err; goto err;
}
if (memcmp((byte*) share->state.header.file_version, if (memcmp((byte*) share->state.header.file_version,
(byte*) myisam_file_magic, 4)) (byte*) myisam_file_magic, 4))
{ {
...@@ -165,7 +167,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -165,7 +167,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
} }
errpos=3; errpos=3;
if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP))) if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
{
my_errno=HA_ERR_CRASHED;
goto err; goto err;
}
len=mi_uint2korr(share->state.header.state_info_length); len=mi_uint2korr(share->state.header.state_info_length);
keys= (uint) share->state.header.keys; keys= (uint) share->state.header.keys;
uniques= (uint) share->state.header.uniques; uniques= (uint) share->state.header.uniques;
......
...@@ -11,4 +11,5 @@ test.t1 repair error The handler for the table doesn't support repair ...@@ -11,4 +11,5 @@ test.t1 repair error The handler for the table doesn't support repair
drop table t1; drop table t1;
repair table t1 use_frm; repair table t1 use_frm;
Table Op Msg_type Msg_text 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";
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;
...@@ -150,3 +150,19 @@ select * from t1; ...@@ -150,3 +150,19 @@ select * from t1;
id_param nom_option valid id_param nom_option valid
185 test 1 185 test 1
drop table t1; 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;
...@@ -12,4 +12,8 @@ drop table t1; ...@@ -12,4 +12,8 @@ drop table t1;
# non-existent table # non-existent table
repair table t1 use_frm; 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";
echo "1" > $MYSQL_TEST_DIR/var/master-data/test/t1.MYI
#
# 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;
...@@ -108,3 +108,18 @@ INSERT INTO t1 (id_param,nom_option,valid) VALUES (185,'600x1200',1); ...@@ -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; UPDATE t1 SET nom_option='test' WHERE id_param=185 AND nom_option='600x1200' AND valid=1 LIMIT 1;
select * from t1; select * from t1;
drop table 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;
...@@ -830,7 +830,8 @@ void handler::print_error(int error, myf errflag) ...@@ -830,7 +830,8 @@ void handler::print_error(int error, myf errflag)
DBUG_VOID_RETURN; 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) uint handler::get_dup_key(int error)
{ {
...@@ -841,6 +842,7 @@ uint handler::get_dup_key(int error) ...@@ -841,6 +842,7 @@ uint handler::get_dup_key(int error)
DBUG_RETURN(table->file->errkey); DBUG_RETURN(table->file->errkey);
} }
int handler::delete_table(const char *name) int handler::delete_table(const char *name)
{ {
int error=0; int error=0;
...@@ -867,9 +869,10 @@ int handler::rename_table(const char * from, const char * to) ...@@ -867,9 +869,10 @@ int handler::rename_table(const char * from, const char * to)
DBUG_RETURN(0); 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 ha_recovery_logging(THD *thd, bool on)
{ {
int error=0; int error=0;
...@@ -914,7 +917,6 @@ int handler::delete_all_rows() ...@@ -914,7 +917,6 @@ int handler::delete_all_rows()
int ha_create_table(const char *name, HA_CREATE_INFO *create_info, int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
bool update_create_info) bool update_create_info)
{ {
int error; int error;
TABLE table; TABLE table;
......
...@@ -946,6 +946,7 @@ static void safe_remove_from_cache(THD *thd,TABLE *table) ...@@ -946,6 +946,7 @@ static void safe_remove_from_cache(THD *thd,TABLE *table)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
bool close_cached_table(THD *thd,TABLE *table) bool close_cached_table(THD *thd,TABLE *table)
{ {
DBUG_ENTER("close_cached_table"); DBUG_ENTER("close_cached_table");
...@@ -957,7 +958,8 @@ bool close_cached_table(THD *thd,TABLE *table) ...@@ -957,7 +958,8 @@ bool close_cached_table(THD *thd,TABLE *table)
/* Close lock if this is not got with LOCK TABLES */ /* Close lock if this is not got with LOCK TABLES */
if (thd->lock) 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 */ /* Close all copies of 'table'. This also frees all LOCK TABLES lock */
thd->open_tables=unlink_open_table(thd,thd->open_tables,table); 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, ...@@ -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) HA_CHECK_OPT *check_opt)
{ {
int error= 0;
TABLE tmp_table, *table;
DBUG_ENTER("prepare_for_repair"); 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)) if (!(check_opt->sql_flags & TT_USEFRM))
{
DBUG_RETURN(0); DBUG_RETURN(0);
}
else if (!(table= table_list->table)) /* if open_ltable failed */
{ {
/* char name[FN_REFLEN];
User gave us USE_FRM which means that the header in the index file is strxmov(name, mysql_data_home, "/", table_list->db, "/",
trashed. table_list->real_name, NullS);
In this case we will try to fix the table the following way: if (openfrm(name, "", 0, 0, 0, &tmp_table))
- Rename the data file to a temporary name DBUG_RETURN(0); // Can't open frm file
- Truncate the table table= &tmp_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 from[FN_REFLEN],tmp[FN_REFLEN+32]; /*
const char **ext= table->table->file->bas_ext(); User gave us USE_FRM which means that the header in the index file is
MY_STAT stat_info; 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 from[FN_REFLEN],tmp[FN_REFLEN+32];
Check if this is a table type that stores index and data separately, const char **ext= table->file->bas_ext();
like ISAM or MyISAM MY_STAT stat_info;
*/
if (!ext[0] || !ext[1])
DBUG_RETURN(0); // No data file
strxmov(from, table->table->path, ext[1], NullS); // Name of data file /*
if (!my_stat(from, &stat_info, MYF(0))) Check if this is a table type that stores index and data separately,
DBUG_RETURN(0); // Can't use USE_FRM flag 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); sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
close_cached_table(thd,table->table);
pthread_mutex_unlock(&LOCK_open);
if (lock_and_wait_for_table_name(thd,table)) pthread_mutex_lock(&LOCK_open);
DBUG_RETURN(-1); close_cached_table(thd,table_list->table);
pthread_mutex_unlock(&LOCK_open);
if (my_rename(from, tmp, MYF(MY_WME))) if (lock_and_wait_for_table_name(thd,table_list))
{ {
pthread_mutex_lock(&LOCK_open); error= -1;
unlock_table_name(thd, table); goto end;
pthread_mutex_unlock(&LOCK_open); }
DBUG_RETURN(send_check_errmsg(thd, table, "repair", if (my_rename(from, tmp, MYF(MY_WME)))
"Failed renaming data file")); {
} pthread_mutex_lock(&LOCK_open);
if (mysql_truncate(thd, table, 1)) unlock_table_name(thd, table_list);
{ pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair",
unlock_table_name(thd, table); "Failed renaming data file");
pthread_mutex_unlock(&LOCK_open); goto end;
DBUG_RETURN(send_check_errmsg(thd, table, "repair", }
"Failed generating table from .frm file")); if (mysql_truncate(thd, table_list, 1))
} {
if (my_rename(tmp, from, MYF(MY_WME))) pthread_mutex_lock(&LOCK_open);
{ unlock_table_name(thd, table_list);
pthread_mutex_lock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
unlock_table_name(thd, table); error= send_check_errmsg(thd, table_list, "repair",
pthread_mutex_unlock(&LOCK_open); "Failed generating table from .frm file");
DBUG_RETURN(send_check_errmsg(thd, table, "repair", goto end;
"Failed restoring .MYD file")); }
} 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 Now we should be able to open the partially repaired table
to finish the repair in the handler later on. 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); pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table); unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
} }
DBUG_RETURN(0);
end:
if (table == &tmp_table)
closefrm(table); // Free allocated memory
DBUG_RETURN(error);
} }
......
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