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
*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
;;
......
......@@ -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;
......
......@@ -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";
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;
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;
......@@ -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";
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);
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;
......@@ -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;
......
......@@ -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);
}
......
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