mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Fix for MacOSX and symlinks
Fix for USE_FRM and crashed index file configure.in: Fix for MacOSX and symlinks myisam/mi_open.c: Give better error message in case of of crashed index file mysql-test/r/repair.result: new test case mysql-test/r/update.result: new test case mysql-test/t/repair.test: Added test with crashed MyISAM index header mysql-test/t/update.test: Added test case from bugs system sql/handler.cc: Indentation changes sql/sql_table.cc: Fix for USE_FRM and crashed index file
This commit is contained in:
10
configure.in
10
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
|
||||
;;
|
||||
|
@ -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";
|
||||
|
8
mysql-test/r/repair_part2.result
Normal file
8
mysql-test/r/repair_part2.result
Normal file
@ -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;
|
@ -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";
|
||||
|
1
mysql-test/t/repair_part2-master.sh
Normal file
1
mysql-test/t/repair_part2-master.sh
Normal file
@ -0,0 +1 @@
|
||||
echo "1" > $MYSQL_TEST_DIR/var/master-data/test/t1.MYI
|
7
mysql-test/t/repair_part2.test
Normal file
7
mysql-test/t/repair_part2.test
Normal file
@ -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;
|
@ -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;
|
||||
|
142
sql/sql_table.cc
142
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
|
||||
|
||||
sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
|
||||
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
close_cached_table(thd,table_list->table);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
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);
|
||||
close_cached_table(thd,table->table);
|
||||
unlock_table_name(thd, table_list);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
if (lock_and_wait_for_table_name(thd,table))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
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"));
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user