Commit b74da90a authored by unknown's avatar unknown

Automatic repair of MyISAM tables + portability fixes


Docs/manual.texi:
  Changes for 3.23 and change Ansi mode -> ANSI mode
include/my_base.h:
  Automatic repair of MyISAM tables
include/myisam.h:
  Automatic repair of MyISAM tables
myisam/ft_update.c:
  Portability fix
myisam/mi_check.c:
  Automatic repair of MyISAM tables
myisam/mi_open.c:
  Automatic repair of MyISAM tables
myisam/myisamchk.c:
  Allow one to combine check with --old-repair
myisam/sort.c:
  Fix for usage of IO_CACHE
mysys/charset.c:
  Portability fixes
mysys/default.c:
  Added --defaults-extra-dir
mysys/mf_tempfile.c:
  Portability fixes
mysys/my_init.c:
  Remove compiler warning
mysys/my_pread.c:
  Remove compiler warning
sql-bench/server-cfg.sh:
  New benchmark tests
sql-bench/test-insert.sh:
  New benchmark tests
sql/ha_myisam.cc:
  Automatic repair of MyISAM tables
sql/ha_myisam.h:
  Automatic repair of MyISAM tables
sql/handler.h:
  Automatic repair of MyISAM tables
sql/lock.cc:
  Add missing free
sql/log_event.cc:
  Portability fixes
sql/sql_base.cc:
  Automatic repair of MyISAM tables
sql/sql_select.h:
  Remove compiler warning
sql/sql_table.cc:
  Clean up intendent
sql/sql_yacc.yy:
  New syntax for CHECK
sql/table.cc:
  Automatic repair of MyISAM tables
sql/table.h:
  Automatic repair of MyISAM tables
BitKeeper/etc/logging_ok:
  Logging to logging@openlogging.org accepted
parent f3078422
monty@tramp.mysql.fi monty@tik.mysql.com
monty@donna.mysql.com
This diff is collapsed.
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#define HA_OPEN_TMP_TABLE 4 /* Table is a temp table */ #define HA_OPEN_TMP_TABLE 4 /* Table is a temp table */
#define HA_OPEN_DELAY_KEY_WRITE 8 /* Don't update index */ #define HA_OPEN_DELAY_KEY_WRITE 8 /* Don't update index */
#define HA_OPEN_ABORT_IF_CRASHED 16 #define HA_OPEN_ABORT_IF_CRASHED 16
#define HA_OPEN_FOR_REPAIR 32 /* open even if crashed */
/* The following is parameter to ha_rkey() how to use key */ /* The following is parameter to ha_rkey() how to use key */
......
...@@ -308,22 +308,23 @@ typedef struct st_sort_info { ...@@ -308,22 +308,23 @@ typedef struct st_sort_info {
typedef struct st_mi_check_param typedef struct st_mi_check_param
{ {
ulonglong auto_increment_value;
ulonglong max_data_file_length;
ulonglong keys_in_use;
my_off_t search_after_block;
my_off_t new_file_pos,key_file_blocks;
my_off_t keydata,totaldata,key_blocks,start_check_pos;
ha_rows total_records,total_deleted;
ha_checksum record_checksum,glob_crc;
ulong use_buffers,read_buffer_length,write_buffer_length, ulong use_buffers,read_buffer_length,write_buffer_length,
sort_buffer_length,sort_key_blocks; sort_buffer_length,sort_key_blocks;
uint out_flag,warning_printed,error_printed, uint out_flag,warning_printed,error_printed,
opt_rep_quick,verbose; opt_rep_quick,verbose;
uint opt_sort_key,total_files,max_level; uint opt_sort_key,total_files,max_level;
uint testflag;
uint8 language; uint8 language;
my_bool using_global_keycache, opt_lock_memory, opt_follow_links; my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
uint testflag; my_bool retry_repair,retry_without_quick;
ha_rows total_records,total_deleted;
ulonglong auto_increment_value;
my_off_t search_after_block;
ulonglong max_data_file_length;
ulonglong keys_in_use;
my_off_t new_file_pos,key_file_blocks;
my_off_t keydata,totaldata,key_blocks,start_check_pos;
ha_checksum record_checksum,glob_crc;
char temp_filename[FN_REFLEN],*isam_file_name,*tmpdir; char temp_filename[FN_REFLEN],*isam_file_name,*tmpdir;
int tmpfile_createflag; int tmpfile_createflag;
myf myf_rw; myf myf_rw;
......
...@@ -64,7 +64,7 @@ static FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, byte *keybuf, ...@@ -64,7 +64,7 @@ static FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, byte *keybuf,
return NULL; return NULL;
} }
/* Handle the case where all columns are NULL */ /* Handle the case where all columns are NULL */
if (!parsed && !(parsed=ft_parse(0, "", 0))) if (!parsed && !(parsed=ft_parse(0, (byte*) "", 0)))
return NULL; return NULL;
return ft_linearize(info, keynr, keybuf, parsed); return ft_linearize(info, keynr, keybuf, parsed);
} }
......
...@@ -192,6 +192,7 @@ int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag) ...@@ -192,6 +192,7 @@ int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag)
} }
DBUG_RETURN(0); DBUG_RETURN(0);
wrong: wrong:
param->retry_without_quick=1; // Don't use quick repair
if (test_flag & T_VERBOSE) puts(""); if (test_flag & T_VERBOSE) puts("");
mi_check_print_error(param,"record delete-link-chain corrupted"); mi_check_print_error(param,"record delete-link-chain corrupted");
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -291,6 +292,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info) ...@@ -291,6 +292,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
error=1; error=1;
mi_check_print_error(param,"Size of datafile is: %-8s Should be: %s", mi_check_print_error(param,"Size of datafile is: %-8s Should be: %s",
llstr(size,buff), llstr(skr,buff2)); llstr(size,buff), llstr(skr,buff2));
param->retry_without_quick=1; // Don't use quick repair
} }
else else
{ {
...@@ -750,8 +752,9 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) ...@@ -750,8 +752,9 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
{ {
if (block_info.block_len < info->s->base.min_block_length) if (block_info.block_len < info->s->base.min_block_length)
{ {
mi_check_print_error(param,"Deleted block with impossible length %lu at %s", mi_check_print_error(param,
block_info.block_len,llstr(pos,llbuff)); "Deleted block with impossible length %lu at %s",
block_info.block_len,llstr(pos,llbuff));
goto err2; goto err2;
} }
if ((block_info.next_filepos != HA_OFFSET_ERROR && if ((block_info.next_filepos != HA_OFFSET_ERROR &&
...@@ -1071,7 +1074,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1071,7 +1074,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
new_file= -1; new_file= -1;
if (!(param->testflag & T_SILENT)) if (!(param->testflag & T_SILENT))
{ {
printf("- recovering MyISAM-table '%s'\n",name); printf("- recovering (with keycache) MyISAM-table '%s'\n",name);
printf("Data records: %s\n", llstr(info->state->records,llbuff)); printf("Data records: %s\n", llstr(info->state->records,llbuff));
} }
...@@ -1211,6 +1214,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1211,6 +1214,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records"); mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
mi_check_print_error(param,"Run recovery again without -q"); mi_check_print_error(param,"Run recovery again without -q");
got_error=1; got_error=1;
param->retry_repair=param->retry_without_quick=1;
goto err; goto err;
} }
...@@ -1651,7 +1655,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1651,7 +1655,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
share->pack.header_length; share->pack.header_length;
if (!(param->testflag & T_SILENT)) if (!(param->testflag & T_SILENT))
{ {
printf("- recovering MyISAM-table '%s'\n",name); printf("- recovering (with sort) MyISAM-table '%s'\n",name);
printf("Data records: %s\n", llstr(start_records,llbuff)); printf("Data records: %s\n", llstr(start_records,llbuff));
} }
bzero((char*) sort_info,sizeof(*sort_info)); bzero((char*) sort_info,sizeof(*sort_info));
...@@ -1805,7 +1809,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1805,7 +1809,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
if (_create_index_by_sort(&sort_param, if (_create_index_by_sort(&sort_param,
(my_bool) (!(param->testflag & T_VERBOSE)), (my_bool) (!(param->testflag & T_VERBOSE)),
(uint) param->sort_buffer_length)) (uint) param->sort_buffer_length))
{
param->retry_repair=1;
goto err; goto err;
}
/* Set for next loop */ /* Set for next loop */
sort_param.max_records=sort_info->max_records= sort_param.max_records=sort_info->max_records=
...@@ -1862,6 +1869,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -1862,6 +1869,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records"); mi_check_print_error(param,"Couldn't fix table with quick recovery: Found wrong number of deleted records");
mi_check_print_error(param,"Run recovery again without -q"); mi_check_print_error(param,"Run recovery again without -q");
got_error=1; got_error=1;
param->retry_repair=param->retry_without_quick=1;
goto err; goto err;
} }
...@@ -3037,7 +3045,8 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows) ...@@ -3037,7 +3045,8 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows)
even if the temporary file would be quite big! even if the temporary file would be quite big!
*/ */
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, my_bool force) my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows,
my_bool force __attribute__((unused)))
{ {
MYISAM_SHARE *share=info->s; MYISAM_SHARE *share=info->s;
uint i; uint i;
......
...@@ -174,9 +174,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -174,9 +174,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
disk_pos=my_n_base_info_read(disk_cache+base_pos, &share->base); disk_pos=my_n_base_info_read(disk_cache+base_pos, &share->base);
share->state.state_length=base_pos; share->state.state_length=base_pos;
if ((open_flags & HA_OPEN_ABORT_IF_CRASHED) && if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
((share->state.changed & STATE_CRASHED) || ((share->state.changed & STATE_CRASHED) ||
(my_disable_locking && share->state.open_count))) ((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
(my_disable_locking && share->state.open_count))))
{ {
DBUG_PRINT("error",("Table is marked as crashed")); DBUG_PRINT("error",("Table is marked as crashed"));
my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ? my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
......
...@@ -92,7 +92,7 @@ int main(int argc, char **argv) ...@@ -92,7 +92,7 @@ int main(int argc, char **argv)
error=0; error=0;
while (--argc >= 0) while (--argc >= 0)
{ {
error|= myisamchk(&check_param, *(argv++)); int new_error=myisamchk(&check_param, *(argv++));
VOID(fflush(stdout)); VOID(fflush(stdout));
VOID(fflush(stderr)); VOID(fflush(stderr));
if ((check_param.error_printed | check_param.warning_printed) && if ((check_param.error_printed | check_param.warning_printed) &&
...@@ -101,13 +101,16 @@ int main(int argc, char **argv) ...@@ -101,13 +101,16 @@ int main(int argc, char **argv)
T_SORT_INDEX)))) T_SORT_INDEX))))
{ {
uint old_testflag=check_param.testflag; uint old_testflag=check_param.testflag;
check_param.testflag|=T_REP; if (!(check_param.testflag & T_REP))
check_param.testflag|= T_REP_BY_SORT;
check_param.testflag&= ~T_EXTEND; /* Don't needed */ check_param.testflag&= ~T_EXTEND; /* Don't needed */
error|=myisamchk(&check_param, argv[-1]); error|=myisamchk(&check_param, argv[-1]);
check_param.testflag= old_testflag; check_param.testflag= old_testflag;
VOID(fflush(stdout)); VOID(fflush(stdout));
VOID(fflush(stderr)); VOID(fflush(stderr));
} }
else
error|=new_error;
if (argc && (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO)) if (argc && (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO))
{ {
puts("\n---------\n"); puts("\n---------\n");
...@@ -193,7 +196,7 @@ static struct option long_options[] = ...@@ -193,7 +196,7 @@ static struct option long_options[] =
static void print_version(void) static void print_version(void)
{ {
printf("%s Ver 1.32 for %s at %s\n",my_progname,SYSTEM_TYPE, printf("%s Ver 1.34 for %s at %s\n",my_progname,SYSTEM_TYPE,
MACHINE_TYPE); MACHINE_TYPE);
} }
...@@ -229,7 +232,7 @@ static void usage(void) ...@@ -229,7 +232,7 @@ static void usage(void)
-f, --force Restart with -r if there are any errors in the table\n\ -f, --force Restart with -r if there are any errors in the table\n\
-i, --information Print statistics information about table that is checked\n\ -i, --information Print statistics information about table that is checked\n\
-m, --medium-check Faster than extended-check, but only finds 99.99% of\n\ -m, --medium-check Faster than extended-check, but only finds 99.99% of\n\
all errors. Should however be good enough for most cases\n\ all errors. Should be good enough for most cases\n\
-U --update-state Mark tables as crashed if you find any errors\n\ -U --update-state Mark tables as crashed if you find any errors\n\
-T, --read-only Don't mark table as checked\n"); -T, --read-only Don't mark table as checked\n");
...@@ -488,10 +491,11 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -488,10 +491,11 @@ static int myisamchk(MI_CHECK *param, my_string filename)
if (!(info=mi_open(filename, if (!(info=mi_open(filename,
(param->testflag & (T_DESCRIPT | T_READONLY)) ? (param->testflag & (T_DESCRIPT | T_READONLY)) ?
O_RDONLY : O_RDWR, O_RDONLY : O_RDWR,
(param->testflag & T_WAIT_FOREVER) ? HA_OPEN_FOR_REPAIR |
HA_OPEN_WAIT_IF_LOCKED : ((param->testflag & T_WAIT_FOREVER) ?
(param->testflag & T_DESCRIPT) ? HA_OPEN_WAIT_IF_LOCKED :
HA_OPEN_IGNORE_IF_LOCKED : HA_OPEN_ABORT_IF_LOCKED))) (param->testflag & T_DESCRIPT) ?
HA_OPEN_IGNORE_IF_LOCKED : HA_OPEN_ABORT_IF_LOCKED))))
{ {
/* Avoid twice printing of isam file name */ /* Avoid twice printing of isam file name */
param->error_printed=1; param->error_printed=1;
...@@ -748,8 +752,8 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -748,8 +752,8 @@ static int myisamchk(MI_CHECK *param, my_string filename)
error =chk_size(param,info); error =chk_size(param,info);
if (!error || !(param->testflag & (T_FAST | T_FORCE_CREATE))) if (!error || !(param->testflag & (T_FAST | T_FORCE_CREATE)))
error|=chk_del(param, info,param->testflag); error|=chk_del(param, info,param->testflag);
if ((!error || !(param->testflag & (T_FAST | T_FORCE_CREATE)) && if ((!error || (!(param->testflag & (T_FAST | T_FORCE_CREATE)) &&
!param->start_check_pos)) !param->start_check_pos)))
{ {
error|=chk_key(param, info); error|=chk_key(param, info);
if (!error && (param->testflag & (T_STATISTICS | T_AUTO_INC))) if (!error && (param->testflag & (T_STATISTICS | T_AUTO_INC)))
......
...@@ -155,10 +155,10 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ...@@ -155,10 +155,10 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
printf(" - Merging %lu keys\n",records); printf(" - Merging %lu keys\n",records);
if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile)) if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile))
goto err; goto err;
if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
goto err;
} }
if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
goto err;
if (!no_messages) if (!no_messages)
puts(" - Last merge and dumping keys"); puts(" - Last merge and dumping keys");
if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,&tempfile)) if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,&tempfile))
......
...@@ -67,7 +67,7 @@ static char *name_from_csnum(CS_ID **cs, uint number) ...@@ -67,7 +67,7 @@ static char *name_from_csnum(CS_ID **cs, uint number)
for (c = cs; *c; ++c) for (c = cs; *c; ++c)
if ((*c)->number == number) if ((*c)->number == number)
return (*c)->name; return (*c)->name;
return "?"; /* this mimics find_type() */ return (char*) "?"; /* this mimics find_type() */
} }
static my_bool get_word(struct simpleconfig_buf_st *fb, char *buf) static my_bool get_word(struct simpleconfig_buf_st *fb, char *buf)
...@@ -487,7 +487,7 @@ char * list_charsets(myf want_flags) ...@@ -487,7 +487,7 @@ char * list_charsets(myf want_flags)
{ {
CS_ID **c; CS_ID **c;
char buf[FN_REFLEN]; char buf[FN_REFLEN];
MY_STAT stat; MY_STAT status;
if((c=available_charsets)) if((c=available_charsets))
for (; *c; ++c) for (; *c; ++c)
...@@ -495,7 +495,7 @@ char * list_charsets(myf want_flags) ...@@ -495,7 +495,7 @@ char * list_charsets(myf want_flags)
if (charset_in_string((*c)->name, &s)) if (charset_in_string((*c)->name, &s))
continue; continue;
get_charset_conf_name((*c)->number, buf); get_charset_conf_name((*c)->number, buf);
if (!my_stat(buf, &stat, MYF(0))) if (!my_stat(buf, &status, MYF(0)))
continue; /* conf file doesn't exist */ continue; /* conf file doesn't exist */
dynstr_append(&s, (*c)->name); dynstr_append(&s, (*c)->name);
dynstr_append(&s, " "); dynstr_append(&s, " ");
......
...@@ -148,7 +148,7 @@ void load_defaults(const char *conf_file, const char **groups, ...@@ -148,7 +148,7 @@ void load_defaults(const char *conf_file, const char **groups,
#endif #endif
for (dirs=default_directories ; *dirs; dirs++) for (dirs=default_directories ; *dirs; dirs++)
{ {
int error; int error=0;
if (**dirs) if (**dirs)
error=search_default_file(&args, &alloc, *dirs, conf_file, error=search_default_file(&args, &alloc, *dirs, conf_file,
default_ext, &group); default_ext, &group);
...@@ -359,7 +359,12 @@ void print_defaults(const char *conf_file, const char **groups) ...@@ -359,7 +359,12 @@ void print_defaults(const char *conf_file, const char **groups)
#endif #endif
for (dirs=default_directories ; *dirs; dirs++) for (dirs=default_directories ; *dirs; dirs++)
{ {
strmov(name,*dirs); if (**dirs)
strmov(name,*dirs);
else if (defaults_extra_file)
strmov(name,defaults_extra_file);
else
continue;
convert_dirname(name); convert_dirname(name);
if (name[0] == FN_HOMELIB) /* Add . to filenames in home */ if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
strcat(name,"."); strcat(name,".");
...@@ -377,6 +382,7 @@ void print_defaults(const char *conf_file, const char **groups) ...@@ -377,6 +382,7 @@ void print_defaults(const char *conf_file, const char **groups)
puts("\nThe following options may be given as the first argument:\n\ puts("\nThe following options may be given as the first argument:\n\
--print-defaults Print the program argument list and exit\n\ --print-defaults Print the program argument list and exit\n\
--no-defaults Don't read default options from any options file\n\ --no-defaults Don't read default options from any options file\n\
--defaults-file=# Only read default options from the given file #"); --defaults-file=# Only read default options from the given file #\n\
--defaults-extra-file=# Read this file after the global files are read");
} }
...@@ -36,7 +36,8 @@ extern char **environ; ...@@ -36,7 +36,8 @@ extern char **environ;
*/ */
File create_temp_file(char *to, const char *dir, const char *prefix, File create_temp_file(char *to, const char *dir, const char *prefix,
int mode, myf MyFlags) int mode __attribute__((unused)),
myf MyFlags __attribute__((unused)))
{ {
File file= -1; File file= -1;
DBUG_ENTER("open_temp_file"); DBUG_ENTER("open_temp_file");
...@@ -85,12 +86,12 @@ File create_temp_file(char *to, const char *dir, const char *prefix, ...@@ -85,12 +86,12 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
} }
#elif defined(HAVE_MKSTEMP) #elif defined(HAVE_MKSTEMP)
{ {
char prefix[30]; char prefix_buff[30];
uint pfx_len; uint pfx_len;
pfx_len=(strmov(strnmov(prefix, pfx_len=(strmov(strnmov(prefix_buff,
prefix ? prefix : "tmp.", prefix ? prefix : "tmp.",
sizeof(prefix)-7),"XXXXXX") - prefix); sizeof(prefix_buff)-7),"XXXXXX") - prefix_buff);
if (!dir && ! (dir =getenv("TMPDIR"))) if (!dir && ! (dir =getenv("TMPDIR")))
dir=P_tmpdir; dir=P_tmpdir;
if (strlen(dir)+ pfx_len > FN_REFLEN-2) if (strlen(dir)+ pfx_len > FN_REFLEN-2)
......
...@@ -48,7 +48,7 @@ static my_bool win32_init_tcp_ip(); ...@@ -48,7 +48,7 @@ static my_bool win32_init_tcp_ip();
static my_bool my_init_done=0; static my_bool my_init_done=0;
ulong atoi_octal(const char *str) static ulong atoi_octal(const char *str)
{ {
long int tmp; long int tmp;
while (*str && isspace(*str)) while (*str && isspace(*str))
......
...@@ -80,7 +80,6 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, ...@@ -80,7 +80,6 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
myf MyFlags) myf MyFlags)
{ {
int error;
uint writenbytes,errors; uint writenbytes,errors;
ulong written; ulong written;
DBUG_ENTER("my_pwrite"); DBUG_ENTER("my_pwrite");
...@@ -91,6 +90,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, ...@@ -91,6 +90,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
for (;;) for (;;)
{ {
#ifndef HAVE_PREAD #ifndef HAVE_PREAD
int error;
writenbytes= (uint) -1; writenbytes= (uint) -1;
pthread_mutex_lock(&my_file_info[Filedes].mutex); pthread_mutex_lock(&my_file_info[Filedes].mutex);
error=(lseek(Filedes, offset, MY_SEEK_SET) != -1L && error=(lseek(Filedes, offset, MY_SEEK_SET) != -1L &&
......
...@@ -161,6 +161,7 @@ sub new ...@@ -161,6 +161,7 @@ sub new
$limits{'func_extra_in_num'} = 1; # Has function in $limits{'func_extra_in_num'} = 1; # Has function in
$limits{'limit'} = 1; # supports the limit attribute $limits{'limit'} = 1; # supports the limit attribute
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
$smds{'time'} = 1; $smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('') $smds{'q1'} = 'b'; # with time not supp by mysql ('')
...@@ -378,6 +379,7 @@ sub new ...@@ -378,6 +379,7 @@ sub new
$limits{'group_func_extra_std'} = 0; $limits{'group_func_extra_std'} = 0;
$limits{'limit'} = 1; # supports the limit attribute $limits{'limit'} = 1; # supports the limit attribute
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 0;
$limits{'func_odbc_mod'} = 0; $limits{'func_odbc_mod'} = 0;
$limits{'func_extra_%'} = 0; $limits{'func_extra_%'} = 0;
...@@ -576,6 +578,7 @@ sub new ...@@ -576,6 +578,7 @@ sub new
$limits{'max_text_size'} = 7000; # 8000 crashes pg 6.3 $limits{'max_text_size'} = 7000; # 8000 crashes pg 6.3
$limits{'query_size'} = 16777216; $limits{'query_size'} = 16777216;
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
# the different cases per query ... # the different cases per query ...
$smds{'q1'} = 'b'; # with time $smds{'q1'} = 'b'; # with time
...@@ -849,6 +852,7 @@ sub new ...@@ -849,6 +852,7 @@ sub new
$limits{'NEG'} = 1; $limits{'NEG'} = 1;
$limits{'func_extra_in_num'} = 1; $limits{'func_extra_in_num'} = 1;
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
# for the smds small benchmark test .... # for the smds small benchmark test ....
# the different cases per query ... # the different cases per query ...
...@@ -1087,6 +1091,7 @@ sub new ...@@ -1087,6 +1091,7 @@ sub new
$limits{'NEG'} = 1; $limits{'NEG'} = 1;
$limits{'func_extra_in_num'} = 0; $limits{'func_extra_in_num'} = 0;
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
# for the smds small benchmark test .... # for the smds small benchmark test ....
# the different cases per query ... EMPRESS # the different cases per query ... EMPRESS
...@@ -1364,6 +1369,7 @@ sub new ...@@ -1364,6 +1369,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 1; # Has function in $limits{'func_extra_in_num'} = 1; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
$smds{'time'} = 1; $smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('') $smds{'q1'} = 'b'; # with time not supp by mysql ('')
...@@ -1612,6 +1618,7 @@ sub new ...@@ -1612,6 +1618,7 @@ sub new
$limits{'subqueries'} = 1; # Doesn't support sub-queries. $limits{'subqueries'} = 1; # Doesn't support sub-queries.
$limits{'table_wildcard'} = 1; # Has SELECT table_name.* $limits{'table_wildcard'} = 1; # Has SELECT table_name.*
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
return $self; return $self;
} }
...@@ -1809,6 +1816,7 @@ sub new ...@@ -1809,6 +1816,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 1; # Has function in $limits{'func_extra_in_num'} = 1; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
return $self; return $self;
} }
...@@ -1980,6 +1988,7 @@ sub new ...@@ -1980,6 +1988,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 0; # Has function in $limits{'func_extra_in_num'} = 0; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
return $self; return $self;
} }
...@@ -2163,6 +2172,7 @@ sub new ...@@ -2163,6 +2172,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 0; # Has function in $limits{'func_extra_in_num'} = 0; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
return $self; return $self;
} }
...@@ -2349,6 +2359,7 @@ sub new ...@@ -2349,6 +2359,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 1; # Has function in $limits{'func_extra_in_num'} = 1; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
$smds{'time'} = 1; $smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('') $smds{'q1'} = 'b'; # with time not supp by mysql ('')
...@@ -2558,6 +2569,7 @@ sub new ...@@ -2558,6 +2569,7 @@ sub new
$limits{'NEG'} = 1; # Supports -id $limits{'NEG'} = 1; # Supports -id
$limits{'func_extra_in_num'} = 0; # Has function in $limits{'func_extra_in_num'} = 0; # Has function in
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
return $self; return $self;
} }
...@@ -2726,6 +2738,7 @@ sub new ...@@ -2726,6 +2738,7 @@ sub new
$limits{'func_extra_in_num'} = 1; # Has function in $limits{'func_extra_in_num'} = 1; # Has function in
$limits{'limit'} = 0; # Does not support the limit attribute $limits{'limit'} = 0; # Does not support the limit attribute
$limits{'unique_index'} = 1; # Unique index works or not $limits{'unique_index'} = 1; # Unique index works or not
$limits{'insert_select'} = 1;
$smds{'time'} = 1; $smds{'time'} = 1;
$smds{'q1'} = 'b'; # with time not supp by mysql ('') $smds{'q1'} = 'b'; # with time not supp by mysql ('')
......
...@@ -97,6 +97,8 @@ goto select_test if ($opt_skip_create); ...@@ -97,6 +97,8 @@ goto select_test if ($opt_skip_create);
print "Creating tables\n"; print "Creating tables\n";
$dbh->do("drop table bench1"); $dbh->do("drop table bench1");
$dbh->do("drop table bench2");
$dbh->do("drop table bench3");
do_many($dbh,$server->create("bench1", do_many($dbh,$server->create("bench1",
["id int NOT NULL", ["id int NOT NULL",
"id2 int NOT NULL", "id2 int NOT NULL",
...@@ -240,7 +242,7 @@ if ($limits->{'unique_index'}) ...@@ -240,7 +242,7 @@ if ($limits->{'unique_index'})
} }
$end_time=new Benchmark; $end_time=new Benchmark;
print "Time for insert_duplicates (" . ($total_rows) . "): " . print "Time for insert_duplicates (" . ($opt_loop_count) . "): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n"; timestr(timediff($end_time, $loop_time),"all") . "\n\n";
#if ($opt_fast && defined($server->{vacuum})) #if ($opt_fast && defined($server->{vacuum}))
...@@ -611,7 +613,7 @@ if ($limits->{'functions'}) ...@@ -611,7 +613,7 @@ if ($limits->{'functions'})
} }
$end_time=new Benchmark; $end_time=new Benchmark;
print "Time for update_of_key ($range_loop_count): " . print "Time for update_of_key ($update_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n"; timestr(timediff($end_time, $loop_time),"all") . "\n";
if ($opt_lock_tables) if ($opt_lock_tables)
...@@ -775,7 +777,7 @@ for ($i=0 ; $i < $opt_loop_count*3 ; $i++) ...@@ -775,7 +777,7 @@ for ($i=0 ; $i < $opt_loop_count*3 ; $i++)
} }
$end_time=new Benchmark; $end_time=new Benchmark;
print "Time for update_with_key ($opt_loop_count): " . print "Time for update_with_key (" . ($opt_loop_count*3) . "): " .
timestr(timediff($end_time, $loop_time),"all") . "\n"; timestr(timediff($end_time, $loop_time),"all") . "\n";
print "\nTesting update of all rows\n"; print "\nTesting update of all rows\n";
...@@ -785,7 +787,7 @@ for ($i=0 ; $i < $small_loop_count ; $i++) ...@@ -785,7 +787,7 @@ for ($i=0 ; $i < $small_loop_count ; $i++)
$sth = $dbh->do("update bench1 set dummy1='updated $i'") or die $DBI::errstr; $sth = $dbh->do("update bench1 set dummy1='updated $i'") or die $DBI::errstr;
} }
$end_time=new Benchmark; $end_time=new Benchmark;
print "Time for update_big ($range_loop_count): " . print "Time for update_big ($small_loop_count): " .
timestr(timediff($end_time, $loop_time),"all") . "\n"; timestr(timediff($end_time, $loop_time),"all") . "\n";
...@@ -859,6 +861,49 @@ if ($server->small_rollback_segment()) ...@@ -859,6 +861,49 @@ if ($server->small_rollback_segment())
$dbh = $server->connect(); $dbh = $server->connect();
} }
####
#### Test INSERT INTO ... SELECT
####
if ($limits->{'insert_select'})
{
print "\nTesting INSERT INTO ... SELECT\n";
do_many($dbh,$server->create("bench2",
["id int NOT NULL",
"id2 int NOT NULL",
"id3 int NOT NULL",
"dummy1 char(30)"],
["primary key (id,id2)"]));
do_many($dbh,$server->create("bench3",
["id int NOT NULL",
"id2 int NOT NULL",
"id3 int NOT NULL",
"dummy1 char(30)"],
["primary key (id,id2)",
"index index_id3 (id3)"]));
$loop_time=new Benchmark;
$sth = $dbh->do("INSERT INTO bench2 SELECT * from bench1") ||
die $DBI::errstr;
$end_time=new Benchmark;
print "Time for insert_select_1_key (1): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$loop_time=new Benchmark;
$sth = $dbh->do("INSERT INTO bench3 SELECT * from bench1") ||
die $DBI::errstr;
$end_time=new Benchmark;
print "Time for insert_select_2_keys (1): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
$loop_time=new Benchmark;
$sth = $dbh->do("DROP TABLE bench2") ||
die $DBI::errstr;
$sth = $dbh->do("DROP TABLE bench3") ||
die $DBI::errstr;
$end_time=new Benchmark;
print "Time for drop table(2): " .
timestr(timediff($end_time, $loop_time),"all") . "\n";
}
#### ####
#### Do some deletes on the table #### Do some deletes on the table
#### ####
......
...@@ -254,7 +254,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -254,7 +254,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
STATE_CRASHED_ON_REPAIR)) && STATE_CRASHED_ON_REPAIR)) &&
share->state.open_count == 0) || share->state.open_count == 0) ||
((param.testflag & T_FAST) && (share->state.open_count == ((param.testflag & T_FAST) && (share->state.open_count ==
(share->global_changed ? 1 : 0))))) (uint) (share->global_changed ? 1 : 0)))))
return HA_ADMIN_ALREADY_DONE; return HA_ADMIN_ALREADY_DONE;
error = chk_size(&param, file); error = chk_size(&param, file);
...@@ -298,6 +298,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -298,6 +298,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
mi_mark_crashed(file); mi_mark_crashed(file);
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
} }
check_opt->retry_without_quick=param.retry_without_quick;
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK; return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
} }
...@@ -317,7 +318,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) ...@@ -317,7 +318,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
myisamchk_init(&param); myisamchk_init(&param);
param.thd = thd; param.thd = thd;
param.op_name = (char*)" analyze"; param.op_name = (char*) "analyze";
param.table_name = table->table_name; param.table_name = table->table_name;
param.testflag=(T_FAST | T_CHECK | T_SILENT | T_STATISTICS | param.testflag=(T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
T_DONT_CHECK_CHECKSUM); T_DONT_CHECK_CHECKSUM);
...@@ -338,6 +339,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) ...@@ -338,6 +339,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK; return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
} }
int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
{ {
HA_CHECK_OPT tmp_check_opt; HA_CHECK_OPT tmp_check_opt;
...@@ -404,6 +406,7 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -404,6 +406,7 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
{ {
int error;
if (!file) return HA_ADMIN_INTERNAL_ERROR; if (!file) return HA_ADMIN_INTERNAL_ERROR;
MI_CHECK param; MI_CHECK param;
...@@ -415,7 +418,21 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -415,7 +418,21 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
if (check_opt->quick) if (check_opt->quick)
param.opt_rep_quick++; param.opt_rep_quick++;
param.sort_buffer_length= check_opt->sort_buffer_size; param.sort_buffer_length= check_opt->sort_buffer_size;
return repair(thd,param,0); while ((error=repair(thd,param,0)))
{
if (param.retry_without_quick && param.opt_rep_quick)
{
param.opt_rep_quick=0;
continue;
}
if ((param.testflag & T_REP_BY_SORT))
{
param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
continue;
}
break;
}
return error;
} }
int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt) int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
...@@ -576,19 +593,19 @@ bool ha_myisam::activate_all_index(THD *thd) ...@@ -576,19 +593,19 @@ bool ha_myisam::activate_all_index(THD *thd)
} }
bool ha_myisam::check_and_repair(THD *thd, const char *name) bool ha_myisam::check_and_repair(THD *thd)
{ {
int error=0; int error=0;
HA_CHECK_OPT check_opt; HA_CHECK_OPT check_opt;
DBUG_ENTER("ha_myisam::auto_check_and_repair"); DBUG_ENTER("ha_myisam::auto_check_and_repair");
if (open(name, O_RDWR, HA_OPEN_WAIT_IF_LOCKED))
DBUG_RETURN(1);
check_opt.init(); check_opt.init();
check_opt.flags=T_MEDIUM; check_opt.flags= T_MEDIUM;
check_opt.quick= !file->state->del; // Don't use quick if deleted rows
if (mi_is_crashed(file) || check(thd, &check_opt)) if (mi_is_crashed(file) || check(thd, &check_opt))
{ {
if (check_opt.retry_without_quick)
check_opt.quick=0;
check_opt.flags=(((myisam_recover_options & HA_RECOVER_BACKUP) ? check_opt.flags=(((myisam_recover_options & HA_RECOVER_BACKUP) ?
T_BACKUP_DATA : 0) | T_BACKUP_DATA : 0) |
(!(myisam_recover_options & HA_RECOVER_FORCE) ? (!(myisam_recover_options & HA_RECOVER_FORCE) ?
...@@ -596,11 +613,14 @@ bool ha_myisam::check_and_repair(THD *thd, const char *name) ...@@ -596,11 +613,14 @@ bool ha_myisam::check_and_repair(THD *thd, const char *name)
if (repair(thd, &check_opt)) if (repair(thd, &check_opt))
error=1; error=1;
} }
if (close())
error=1;
DBUG_RETURN(error); DBUG_RETURN(error);
} }
bool ha_myisam::is_crashed() const
{
return (file->s->state.changed & STATE_CRASHED ||
(my_disable_locking && file->s->state.open_count));
}
int ha_myisam::update_row(const byte * old_data, byte * new_data) int ha_myisam::update_row(const byte * old_data, byte * new_data)
{ {
......
...@@ -45,8 +45,7 @@ class ha_myisam: public handler ...@@ -45,8 +45,7 @@ class ha_myisam: public handler
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER | HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY | HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY |
HA_LONGLONG_KEYS | HA_NULL_KEY | HA_LONGLONG_KEYS | HA_NULL_KEY |
HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY | HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY)
HA_CHECK_AND_REPAIR)
{} {}
~ha_myisam() {} ~ha_myisam() {}
const char *table_type() const { return "MyISAM"; } const char *table_type() const { return "MyISAM"; }
...@@ -103,7 +102,9 @@ class ha_myisam: public handler ...@@ -103,7 +102,9 @@ class ha_myisam: public handler
int check(THD* thd, HA_CHECK_OPT* check_opt); int check(THD* thd, HA_CHECK_OPT* check_opt);
int analyze(THD* thd,HA_CHECK_OPT* check_opt); int analyze(THD* thd,HA_CHECK_OPT* check_opt);
int repair(THD* thd, HA_CHECK_OPT* check_opt); int repair(THD* thd, HA_CHECK_OPT* check_opt);
bool check_and_repair(THD *thd, const char *name); bool check_and_repair(THD *thd);
bool is_crashed() const;
bool auto_repair() const { return myisam_recover_options != 0; }
int optimize(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int restore(THD* thd, HA_CHECK_OPT* check_opt); int restore(THD* thd, HA_CHECK_OPT* check_opt);
int backup(THD* thd, HA_CHECK_OPT* check_opt); int backup(THD* thd, HA_CHECK_OPT* check_opt);
......
...@@ -66,7 +66,6 @@ ...@@ -66,7 +66,6 @@
#define HA_NO_WRITE_DELAYED (HA_NOT_EXACT_COUNT*2) #define HA_NO_WRITE_DELAYED (HA_NOT_EXACT_COUNT*2)
#define HA_PRIMARY_KEY_IN_READ_INDEX (HA_NO_WRITE_DELAYED*2) #define HA_PRIMARY_KEY_IN_READ_INDEX (HA_NO_WRITE_DELAYED*2)
#define HA_DROP_BEFORE_CREATE (HA_PRIMARY_KEY_IN_READ_INDEX*2) #define HA_DROP_BEFORE_CREATE (HA_PRIMARY_KEY_IN_READ_INDEX*2)
#define HA_CHECK_AND_REPAIR (HA_DROP_BEFORE_CREATE*2)
/* Parameters for open() (in register form->filestat) */ /* Parameters for open() (in register form->filestat) */
/* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */ /* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */
...@@ -146,9 +145,10 @@ typedef struct st_ha_check_opt ...@@ -146,9 +145,10 @@ typedef struct st_ha_check_opt
bool quick; bool quick;
bool changed_files; bool changed_files;
bool optimize; bool optimize;
bool retry_without_quick;
inline void init() inline void init()
{ {
flags= 0; quick= optimize=0; flags= 0; quick= optimize= retry_without_quick=0;
sort_buffer_size = myisam_sort_buffer_size; sort_buffer_size = myisam_sort_buffer_size;
} }
} HA_CHECK_OPT; } HA_CHECK_OPT;
...@@ -249,7 +249,7 @@ class handler :public Sql_alloc ...@@ -249,7 +249,7 @@ class handler :public Sql_alloc
virtual void update_create_info(HA_CREATE_INFO *create_info) {} virtual void update_create_info(HA_CREATE_INFO *create_info) {}
virtual int check(THD* thd, HA_CHECK_OPT* check_opt ); virtual int check(THD* thd, HA_CHECK_OPT* check_opt );
virtual int repair(THD* thd, HA_CHECK_OPT* check_opt); virtual int repair(THD* thd, HA_CHECK_OPT* check_opt);
virtual bool check_and_repair(THD *thd, const char *name) {return 1;} virtual bool check_and_repair(THD *thd) {return 1;}
virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt); virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt);
virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt); virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt);
virtual int backup(THD* thd, HA_CHECK_OPT* check_opt); virtual int backup(THD* thd, HA_CHECK_OPT* check_opt);
...@@ -274,6 +274,8 @@ class handler :public Sql_alloc ...@@ -274,6 +274,8 @@ class handler :public Sql_alloc
virtual uint max_key_length()const =0; virtual uint max_key_length()const =0;
virtual uint min_record_length(uint options) const { return 1; } virtual uint min_record_length(uint options) const { return 1; }
virtual bool low_byte_first() const { return 1; } virtual bool low_byte_first() const { return 1; }
virtual bool is_crashed() const { return 0; }
virtual bool auto_repair() const { return 0; }
virtual int rename_table(const char *from, const char *to); virtual int rename_table(const char *from, const char *to);
virtual int delete_table(const char *name); virtual int delete_table(const char *name);
......
...@@ -434,7 +434,10 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) ...@@ -434,7 +434,10 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
table_list->table=table; table_list->table=table;
if (hash_insert(&open_cache, (byte*) table)) if (hash_insert(&open_cache, (byte*) table))
{
my_free((gptr) table,MYF(0));
DBUG_RETURN(-1); DBUG_RETURN(-1);
}
if (remove_table_from_cache(thd, table_list->db, table_list->name)) if (remove_table_from_cache(thd, table_list->db, table_list->name))
DBUG_RETURN(1); // Table is in use DBUG_RETURN(1); // Table is in use
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -261,7 +261,7 @@ void Log_event::print_header(FILE* file) ...@@ -261,7 +261,7 @@ void Log_event::print_header(FILE* file)
{ {
fputc('#', file); fputc('#', file);
print_timestamp(file); print_timestamp(file);
fprintf(file, " server id %d ", server_id); fprintf(file, " server id %ld ", server_id);
} }
void Log_event::print_timestamp(FILE* file, time_t* ts = 0) void Log_event::print_timestamp(FILE* file, time_t* ts = 0)
...@@ -709,7 +709,7 @@ void Load_log_event::print(FILE* file, bool short_form) ...@@ -709,7 +709,7 @@ void Load_log_event::print(FILE* file, bool short_form)
} }
if((int)skip_lines > 0) if((int)skip_lines > 0)
fprintf(file, " IGNORE %d LINES ", skip_lines); fprintf(file, " IGNORE %ld LINES ", skip_lines);
if(num_fields) if(num_fields)
{ {
......
...@@ -34,7 +34,7 @@ HASH open_cache; /* Used by mysql_test */ ...@@ -34,7 +34,7 @@ HASH open_cache; /* Used by mysql_test */
static int open_unireg_entry(TABLE *entry,const char *db,const char *name, static int open_unireg_entry(TABLE *entry,const char *db,const char *name,
const char *alias); const char *alias, bool locked);
static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *table_name, static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *table_name,
List_iterator<Item> *it); List_iterator<Item> *it);
static void free_cache_entry(TABLE *entry); static void free_cache_entry(TABLE *entry);
...@@ -572,7 +572,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list) ...@@ -572,7 +572,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1; key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
if (open_unireg_entry(table, db, table_name, table_name) || if (open_unireg_entry(table, db, table_name, table_name,0) ||
!(table->table_cache_key =memdup_root(&table->mem_root,(char*) key, !(table->table_cache_key =memdup_root(&table->mem_root,(char*) key,
key_length))) key_length)))
{ {
...@@ -706,7 +706,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -706,7 +706,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
/* make a new table */ /* make a new table */
if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME))))
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
if (open_unireg_entry(table,db,table_name,alias) || if (open_unireg_entry(table,db,table_name,alias,0) ||
!(table->table_cache_key=memdup_root(&table->mem_root,(char*) key, !(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
key_length))) key_length)))
{ {
...@@ -816,7 +816,7 @@ bool reopen_table(TABLE *table,bool locked) ...@@ -816,7 +816,7 @@ bool reopen_table(TABLE *table,bool locked)
if (!locked) if (!locked)
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
if (open_unireg_entry(&tmp,db,table_name,table->table_name)) if (open_unireg_entry(&tmp,db,table_name,table->table_name,locked))
goto end; goto end;
free_io_cache(table); free_io_cache(table);
...@@ -1113,23 +1113,72 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name) ...@@ -1113,23 +1113,72 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name)
*/ */
static int open_unireg_entry(TABLE *entry,const char *db,const char *name, static int open_unireg_entry(TABLE *entry,const char *db,const char *name,
const char *alias) const char *alias, bool locked)
{ {
char path[FN_REFLEN]; char path[FN_REFLEN];
int error;
DBUG_ENTER("open_unireg_entry"); DBUG_ENTER("open_unireg_entry");
(void) sprintf(path,"%s/%s/%s",mysql_data_home,db,name); (void) sprintf(path,"%s/%s/%s",mysql_data_home,db,name);
if (openfrm(path,alias, if (openfrm(path,alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY), HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
ha_open_options, ha_open_options,
entry)) entry))
{ {
DBUG_RETURN(1); THD *thd=current_thd;
if (!entry->crashed)
goto err; // Can't repair the table
TABLE_LIST table_list;
table_list.db=(char*) db;
table_list.name=(char*) name;
table_list.next=0;
if (!locked)
pthread_mutex_lock(&LOCK_open);
if ((error=lock_table_name(thd,&table_list)))
{
if (error < 0)
{
if (!locked)
pthread_mutex_lock(&LOCK_open);
goto err;
}
if (wait_for_locked_table_names(thd,&table_list))
{
unlock_table_name(thd,&table_list);
if (!locked)
pthread_mutex_lock(&LOCK_open);
goto err;
}
}
pthread_mutex_unlock(&LOCK_open);
thd->net.last_error[0]=0; // Clear error message
thd->net.last_errno=0;
error=0;
sql_print_error("Warning: Repairing table: %s.%s",db,name);
if (openfrm(path,alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
ha_open_options | HA_OPEN_FOR_REPAIR,
entry) ||
(entry->file->is_crashed() && entry->file->check_and_repair(thd)))
{
sql_print_error("Error: Couldn't repair table: %s.%s",db,name);
error=1;
}
unlock_table_name(thd,&table_list);
if (locked)
pthread_mutex_lock(&LOCK_open); // Get back old lock
if (error)
goto err;
} }
(void) entry->file->extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL (void) entry->file->extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
DBUG_RETURN(0); DBUG_RETURN(0);
err:
DBUG_RETURN(1);
} }
......
...@@ -127,7 +127,7 @@ class TMP_TABLE_PARAM { ...@@ -127,7 +127,7 @@ class TMP_TABLE_PARAM {
uint group_parts,group_length; uint group_parts,group_length;
uint quick_group; uint quick_group;
TMP_TABLE_PARAM() :group_parts(0),group_length(0),copy_field(0) {} TMP_TABLE_PARAM() :copy_field(0), group_parts(0), group_length(0) {}
~TMP_TABLE_PARAM() ~TMP_TABLE_PARAM()
{ {
cleanup(); cleanup();
......
...@@ -745,61 +745,61 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table) ...@@ -745,61 +745,61 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table)
{ {
String *packet = &thd->packet; String *packet = &thd->packet;
if(table->table) // do not overwrite existing tables on restore if (table->table) // do not overwrite existing tables on restore
{ {
return send_check_errmsg(thd, table, "restore", return send_check_errmsg(thd, table, "restore",
"table exists, will not overwrite on restore" "table exists, will not overwrite on restore"
); );
} }
else else
{ {
char* backup_dir = thd->lex.backup_dir; char* backup_dir = thd->lex.backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->name; char* table_name = table->name;
char* db = thd->db ? thd->db : table->db; char* db = thd->db ? thd->db : table->db;
if(!fn_format(src_path, table_name, backup_dir, reg_ext, 4 + 64)) if (!fn_format(src_path, table_name, backup_dir, reg_ext, 4 + 64))
return -1; // protect buffer overflow return -1; // protect buffer overflow
sprintf(dst_path, "%s/%s/%s", mysql_real_data_home, db, table_name); sprintf(dst_path, "%s/%s/%s", mysql_real_data_home, db, table_name);
int lock_retcode; int lock_retcode;
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
if((lock_retcode = lock_table_name(thd, table)) < 0) if ((lock_retcode = lock_table_name(thd, table)) < 0)
{ {
pthread_mutex_unlock(&LOCK_open);
return -1;
}
if(lock_retcode && wait_for_locked_table_names(thd, table))
{
pthread_mutex_unlock(&LOCK_open);
return -1;
}
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
return -1;
}
if(my_copy(src_path, if (lock_retcode && wait_for_locked_table_names(thd, table))
fn_format(dst_path, dst_path,"", {
reg_ext, 4), pthread_mutex_unlock(&LOCK_open);
MYF(MY_WME))) return -1;
{ }
return send_check_errmsg(thd, table, "restore", pthread_mutex_unlock(&LOCK_open);
"Failed copying .frm file");
}
bool save_no_send_ok = thd->net.no_send_ok;
thd->net.no_send_ok = 1;
// generate table will try to send OK which messes up the output
// for the client
if(generate_table(thd, table, 0)) if (my_copy(src_path,
{ fn_format(dst_path, dst_path,"",
thd->net.no_send_ok = save_no_send_ok; reg_ext, 4),
return send_check_errmsg(thd, table, "restore", MYF(MY_WME)))
"Failed generating table from .frm file"); {
} return send_check_errmsg(thd, table, "restore",
"Failed copying .frm file");
}
bool save_no_send_ok = thd->net.no_send_ok;
thd->net.no_send_ok = 1;
// generate table will try to send OK which messes up the output
// for the client
if (generate_table(thd, table, 0))
{
thd->net.no_send_ok = save_no_send_ok; thd->net.no_send_ok = save_no_send_ok;
return send_check_errmsg(thd, table, "restore",
"Failed generating table from .frm file");
} }
thd->net.no_send_ok = save_no_send_ok;
}
return 0; return 0;
} }
......
...@@ -1134,8 +1134,13 @@ repair: ...@@ -1134,8 +1134,13 @@ repair:
opt_mi_check_type: opt_mi_check_type:
/* empty */ { Lex->check_opt.flags = T_MEDIUM; } /* empty */ { Lex->check_opt.flags = T_MEDIUM; }
| TYPE_SYM EQ mi_check_types {} | TYPE_SYM EQ mi_check_types {}
| mi_check_types {}
mi_check_types: mi_check_types:
mi_check_type {}
| mi_check_type mi_check_types {}
mi_check_type:
QUICK { Lex->check_opt.quick = 1; } QUICK { Lex->check_opt.quick = 1; }
| FAST_SYM { Lex->check_opt.flags|= T_FAST; } | FAST_SYM { Lex->check_opt.flags|= T_FAST; }
| EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; } | EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; }
......
...@@ -212,17 +212,24 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ...@@ -212,17 +212,24 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
error=2; error=2;
if (db_stat) if (db_stat)
{ {
if ((outparam->file-> int err;
ha_open(index_file, if ((err=(outparam->file->
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR), ha_open(index_file,
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE : (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
(db_stat & HA_WAIT_IF_LOCKED || (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
specialflag & SPECIAL_WAIT_IF_LOCKED) ? ((db_stat & HA_WAIT_IF_LOCKED) ||
HA_OPEN_WAIT_IF_LOCKED : (specialflag & SPECIAL_WAIT_IF_LOCKED)) ?
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ? HA_OPEN_WAIT_IF_LOCKED :
HA_OPEN_ABORT_IF_LOCKED : (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))) HA_OPEN_ABORT_IF_LOCKED :
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
{
/* Set a flag if the table is crashed and it can be auto. repaired */
outparam->crashed=(err == HA_ERR_CRASHED &&
outparam->file->auto_repair() &&
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
goto err_not_open; /* purecov: inspected */ goto err_not_open; /* purecov: inspected */
}
} }
outparam->db_low_byte_first=outparam->file->low_byte_first(); outparam->db_low_byte_first=outparam->file->low_byte_first();
...@@ -549,6 +556,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ...@@ -549,6 +556,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
delete crypted; delete crypted;
my_pthread_setspecific_ptr(THR_MALLOC,old_root); my_pthread_setspecific_ptr(THR_MALLOC,old_root);
frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG); frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG);
delete outparam->file;
outparam->file=0; // For easyer errorchecking outparam->file=0; // For easyer errorchecking
free_root(&outparam->mem_root,MYF(0)); free_root(&outparam->mem_root,MYF(0));
my_free(outparam->table_name,MYF(MY_ALLOW_ZERO_PTR)); my_free(outparam->table_name,MYF(MY_ALLOW_ZERO_PTR));
......
...@@ -92,6 +92,7 @@ struct st_table { ...@@ -92,6 +92,7 @@ struct st_table {
my_bool db_low_byte_first; /* Portable row format */ my_bool db_low_byte_first; /* Portable row format */
my_bool locked_by_flush; my_bool locked_by_flush;
my_bool locked_by_name; my_bool locked_by_name;
my_bool crashed;
Field *next_number_field, /* Set if next_number is activated */ Field *next_number_field, /* Set if next_number is activated */
*found_next_number_field, /* Set on open */ *found_next_number_field, /* Set on open */
*rowid_field; *rowid_field;
......
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