diff options
author | monty@tramp.mysql.fi <> | 2000-10-03 14:18:03 +0300 |
---|---|---|
committer | monty@tramp.mysql.fi <> | 2000-10-03 14:18:03 +0300 |
commit | 9f7c4563f78f74999efd94768ec483d8c24c3761 (patch) | |
tree | c02cc6a9c6585038615c596332aae70354b44aac | |
parent | 69a249c054b3c1dd4c1aadeb735291ea63862c98 (diff) | |
download | mariadb-git-9f7c4563f78f74999efd94768ec483d8c24c3761.tar.gz |
First part of automatic repair of MyISAM tables.
Error on full disk on repair.
SIGHUP signal handling.
Update with keys on timestamp
Portability fixes
38 files changed, 570 insertions, 419 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index d592707df9e..a3e121b77e3 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -1,24 +1 @@ -bk@work.mysql.com -davida@work.mysql.com -jamppa@work.mysql.com -jcole@ham.spaceapes.com -jcole@jcole.burghcom.com -jcole@nslinux.bedford.progress.com -jcole@tetra.bedford.progress.com -jcole@tetra.spaceapes.com -matt@work.mysql.com -monty@donna.mysql.com -monty@work.mysql.com -mwagner@evoq.home.mwagner.org -nusphere@main.burghcom.com -paul@central.snake.net -paul@work.mysql.com -sasha@mysql.sashanet.com -sasha@work.mysql.com -serg@infomag.ape.relarn.ru -serg@work.mysql.com -sinisa@work.mysql.com -tim@localhost.polyesthetic.msg -tim@work.mysql.com -tonu@work.mysql.com -spurr@nslinux.bedford.progress.com +monty@tramp.mysql.fi diff --git a/Docs/manual.texi b/Docs/manual.texi index 59f36feea77..e74c919731e 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -8984,6 +8984,24 @@ Lock the @code{mysqld} process in memory. This works only if your system supports the @code{mlockall()} system call. This may help if you have a problem where the opearting system is causing @code{mysqld} to swap on disk. +@item --myisam-recover [=option[,option...]]] where option is one of DEFAULT, BACKUP or FORCE. +If this option is used, @code{mysqld} will on open check if the table is +marked as crashed or if if the table wasn't closed properly +(The last option only works if you are running with @code{--skip-locking}). +If this is the case mysqld will run check on the table. If the table was +corrupted, @code{mysqld} will attempt to repair it. + +The following options affects how the repair works. + +@multitable @columnfractions .3 .7 +@item DEFAULT @tab The same as not giving any option to @code{--myisam-recover}. +@item BACKUP @tab If the data table was changed during recover, save a backup of the @file{table_name.MYD} data file as @file{table_name-datetime.BAK}. +@item FORCE @tab Run recover even if we will loose more than one row from the .MYD file. +@end multitable + +Before a table is automaticly repaired, mysqld will add a note about this +in the error log. + @item --pid-file=path Path to pid file used by @code{safe_mysqld}. @@ -21065,6 +21083,9 @@ The following is new in @code{MyISAM}: @itemize @bullet @item +If @code{mysqld} is started with @code{--myisam-recover}, @code{MyISAM} tables +will automaticly be repaired on open if the table wasn't closed properly. +@item You can @code{INSERT} new rows in a table without deleted rows, while other threads are reading from the table. @item @@ -21148,6 +21169,18 @@ Note that index files are usually much smaller with @code{MyISAM} than with system resources than @code{ISAM}, but will need more CPU when inserting data into compressed index. +The following options to @code{mysqld} can be used to change the behavior of +@code{MyISAM} tables: + +@multitable @columnfractions .40 .60 +@item @strong{Option} @tab @strong{Meaning} +@item @code{--myisam-recover} @tab Automatic recover of crashed tables. +@item @code{-O myisam_sort_buffer_size=#} @tab Buffer used when recovering tables. +@item @code{--delay-key-write-for-all-tables} @tab Don't flush key buffers between writes for any MyISAM table +@end multitable + +@xref{Command-line options}. + @menu * Key space:: Space needed for keys * MyISAM table formats:: MyISAM table formats @@ -37416,7 +37449,14 @@ though, so 3.23 is not released as a stable version yet. @appendixsubsec Changes in release 3.23.26 @itemize @bullet @item -Fixed bug in @code{FULLTEXT} index when inserting a NULL column. +Automatic repair of @code{MyISAM} tables. +@item +Columns referenced in @code{INSERT} are are now properly initialized. +@item +@code{UPDATE} didn't always work when used with a range on a timestamp that +was part of the key that was used to find rows. +@item +Fixed bug in @code{FULLTEXT} index when inserting a NULL value. @item Changed to use @code{mkstemp()} instead of @code{tempnam()}. @end itemize diff --git a/client/mysql.cc b/client/mysql.cc index 7a0b645147c..8adb65ab3a6 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1543,12 +1543,12 @@ com_edit(String *buffer,char *line __attribute__((unused))) put_info("Sorry, you can't send the result to an editor in Win32", INFO_ERROR); #else - char *filename,buff[160]; + char filename[FN_REFLEN],buff[160]; int fd,tmp; const char *editor; - filename = my_tempnam(NullS,"sql",MYF(MY_WME)); - if ((fd = my_create(filename,0,O_CREAT | O_WRONLY, MYF(MY_WME))) < 0) + if ((fd=create_temp_file(filename,NullS,"sql", O_CREAT | O_WRONLY, + MYF(MY_WME))) < 0) goto err; if (buffer->is_empty() && !old_buffer.is_empty()) (void) my_write(fd,(byte*) old_buffer.ptr(),old_buffer.length(), @@ -1576,7 +1576,6 @@ com_edit(String *buffer,char *line __attribute__((unused))) (void) my_close(fd,MYF(0)); (void) my_delete(filename,MYF(MY_WME)); err: - free(filename); #endif return 0; } diff --git a/include/my_sys.h b/include/my_sys.h index 05c63df1d77..77057ffa439 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -266,20 +266,21 @@ typedef struct st_dynamic_string { typedef struct st_io_cache /* Used when cacheing files */ { + my_off_t pos_in_file,end_of_file; byte *rc_pos,*rc_end,*buffer,*rc_request_pos; + int (*read_function)(struct st_io_cache *,byte *,uint); + char *file_name; /* if used with 'open_cached_file' */ + char *dir,*prefix; File file; int seek_not_done,error; uint buffer_length,read_length; - my_off_t pos_in_file,end_of_file; myf myflags; /* Flags used to my_read/my_write */ + enum cache_type type; #ifdef HAVE_AIOWAIT uint inited; my_off_t aio_read_pos; my_aio_result aio_result; #endif - enum cache_type type; - int (*read_function)(struct st_io_cache *,byte *,uint); - char *file_name; /* if used with 'open_cached_file' */ } IO_CACHE; typedef int (*qsort2_cmp)(const void *, const void *, const void *); @@ -399,7 +400,7 @@ extern void TERMINATE(FILE *file); #endif extern void init_glob_errs(void); extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags); -extern FILE *my_fdopen(File Filedes,int Flags,myf MyFlags); +extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags); extern int my_fclose(FILE *fd,myf MyFlags); extern int my_chsize(File fd,my_off_t newlength,myf MyFlags); extern int my_error _VARARGS((int nr,myf MyFlags, ...)); @@ -430,7 +431,7 @@ extern uint dirname_part(my_string to,const char *name); extern uint dirname_length(const char *name); #define base_name(A) (A+dirname_length(A)) extern int test_if_hard_path(const char *dir_name); -extern void convert_dirname(my_string name); +extern char *convert_dirname(my_string name); extern void to_unix_path(my_string name); extern my_string fn_ext(const char *name); extern my_string fn_same(my_string toname,const char *name,int flag); @@ -507,6 +508,8 @@ extern my_bool open_cached_file(IO_CACHE *cache,const char *dir, myf cache_myflags); extern my_bool real_open_cached_file(IO_CACHE *cache); extern void close_cached_file(IO_CACHE *cache); +File create_temp_file(char *to, const char *dir, const char *pfx, + int mode, myf MyFlags); extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array,uint element_size, uint init_alloc,uint alloc_increment); extern my_bool insert_dynamic(DYNAMIC_ARRAY *array,gptr element); diff --git a/include/myisam.h b/include/myisam.h index 885ded085ca..5d7ef6325db 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -339,7 +339,6 @@ typedef struct st_mi_check_param typedef struct st_mi_sortinfo { - uint key_length; ha_rows max_records; SORT_INFO *sort_info; char *tmpdir; @@ -347,6 +346,8 @@ typedef struct st_mi_sortinfo { int (*key_read)(SORT_INFO *info,void *buff); int (*key_write)(SORT_INFO *info, const void *buff); void (*lock_in_memory)(MI_CHECK *info); + uint key_length; + myf myf_rw; } MI_SORT_PARAM; /* functions in mi_check */ diff --git a/myisam/mi_check.c b/myisam/mi_check.c index ce561e13bd2..f2787546a31 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -1759,6 +1759,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, sort_param.key_read=sort_key_read; sort_param.lock_in_memory=lock_memory; sort_param.tmpdir=param->tmpdir; + sort_param.myf_rw=param->myf_rw; sort_param.sort_info=sort_info; del=info->state->del; diff --git a/myisam/sort.c b/myisam/sort.c index 0a5b575242f..80f9b0b0363 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -33,6 +33,7 @@ #define MERGEBUFF2 31 #define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD) #define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) +#define DISK_BUFFER_SIZE (IO_SIZE*16) typedef struct st_buffpek { my_off_t file_pos; /* position to buffer */ @@ -47,30 +48,26 @@ extern void print_error _VARARGS((const char *fmt,...)); /* functions defined in this file */ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info,uint keys, - uchar * *sort_keys, + uchar **sort_keys, BUFFPEK *buffpek,int *maxbuffer, - FILE **tempfile, my_string tempname); + IO_CACHE *tempfile); static int NEAR_F write_keys(MI_SORT_PARAM *info,uchar * *sort_keys, - uint count, BUFFPEK *buffpek,FILE **tempfile, - my_string tempname); + uint count, BUFFPEK *buffpek,IO_CACHE *tempfile); static int NEAR_F write_index(MI_SORT_PARAM *info,uchar * *sort_keys, uint count); static int NEAR_F merge_many_buff(MI_SORT_PARAM *info,uint keys, uchar * *sort_keys, BUFFPEK *buffpek,int *maxbuffer, - FILE * *t_file, my_string tempname); -static uint NEAR_F read_to_buffer(FILE *fromfile,BUFFPEK *buffpek, + IO_CACHE *t_file); +static uint NEAR_F read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek, uint sort_length); -static int NEAR_F merge_buffers(MI_SORT_PARAM *info,uint keys,FILE *from_file, - FILE *to_file, uchar * *sort_keys, - BUFFPEK *lastbuff,BUFFPEK *Fb, - BUFFPEK *Tb); +static int NEAR_F merge_buffers(MI_SORT_PARAM *info,uint keys, + IO_CACHE *from_file, IO_CACHE *to_file, + uchar * *sort_keys, BUFFPEK *lastbuff, + BUFFPEK *Fb, BUFFPEK *Tb); static int NEAR_F merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int, - FILE *); + IO_CACHE *); static char **make_char_array(uint fields,uint length,myf my_flag); -static FILE *opentemp(my_string name,const char *temp_dir); -static void closetemp(my_string name,FILE *stream); - /* Creates a index of sorted keys */ /* Returns 0 if everything went ok */ @@ -81,14 +78,14 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, int error,maxbuffer,skr; uint memavl,old_memavl,keys,sort_length; BUFFPEK *buffpek; - char tempname[FN_REFLEN]; ha_rows records; uchar **sort_keys; - FILE *tempfile; + IO_CACHE tempfile; DBUG_ENTER("_create_index_by_sort"); DBUG_PRINT("enter",("sort_length: %d", info->key_length)); - tempfile=0; buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1; + my_b_clear(&tempfile); + buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1; maxbuffer=1; memavl=max(sortbuff_size,MIN_SORT_MEMORY); @@ -139,8 +136,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, if (!no_messages) printf(" - Searching for keys, allocating buffer for %d keys\n",keys); - if ((records=find_all_keys(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile, - tempname)) + if ((records=find_all_keys(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile)) == HA_POS_ERROR) goto err; if (maxbuffer == 0) @@ -157,13 +153,15 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, { if (!no_messages) printf(" - Merging %lu keys\n",records); - if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile, - tempname)) + if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile)) goto err; + if (flush_io_cache(&tempfile) || + reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) + goto err; } if (!no_messages) 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)) goto err; } error =0; @@ -173,8 +171,7 @@ err: my_free((gptr) sort_keys,MYF(0)); if (buffpek) my_free((gptr) buffpek,MYF(0)); - if (tempfile) - closetemp(tempname,tempfile); + close_cached_file(&tempfile); DBUG_RETURN(error ? -1 : 0); } /* _create_index_by_sort */ @@ -184,8 +181,7 @@ err: static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, BUFFPEK *buffpek, - int *maxbuffer, FILE **tempfile, - my_string tempname) + int *maxbuffer, IO_CACHE *tempfile) { int error; uint idx,indexpos; @@ -198,8 +194,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, if ((uint) ++idx == keys) { if (indexpos >= (uint) *maxbuffer || - write_keys(info,sort_keys,idx-1,buffpek+indexpos,tempfile, - tempname)) + write_keys(info,sort_keys,idx-1,buffpek+indexpos,tempfile)) DBUG_RETURN((ha_rows) -1); memcpy(sort_keys[0],sort_keys[idx-1],(size_t) info->key_length); idx=1; indexpos++; @@ -209,7 +204,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, DBUG_RETURN(HA_POS_ERROR); /* Aborted by get_key */ if (indexpos) if (indexpos >= (uint) *maxbuffer || - write_keys(info,sort_keys,idx,buffpek+indexpos,tempfile,tempname)) + write_keys(info,sort_keys,idx,buffpek+indexpos,tempfile)) DBUG_RETURN(HA_POS_ERROR); *maxbuffer=(int) indexpos; DBUG_RETURN(indexpos*(keys-1)+idx); @@ -220,18 +215,23 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys, uint count, BUFFPEK *buffpek, - register FILE **tempfile, my_string tempname) + IO_CACHE *tempfile) { + uchar **end; + uint sort_length=info->key_length; DBUG_ENTER("write_keys"); qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp, info->sort_info); - if (! *tempfile && ! (*tempfile=opentemp(tempname,info->tmpdir))) + if (!my_b_inited(tempfile) && + open_cached_file(tempfile, info->tmpdir, "ST", DISK_BUFFER_SIZE, + info->myf_rw)) DBUG_RETURN(1); - buffpek->file_pos=my_ftell(*tempfile,MYF(0)); + buffpek->file_pos=my_b_tell(tempfile); buffpek->count=count; - while (count--) - if (my_fwrite(*tempfile,(byte*)*sort_keys++,info->key_length,MYF_RW)) + + for (end=sort_keys+count ; sort_keys != end ; sort_keys++) + if (my_b_write(tempfile,(byte*) *sort_keys,(uint) sort_length)) DBUG_RETURN(1); DBUG_RETURN(0); } /* write_keys */ @@ -239,7 +239,8 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys, /* Write index */ -static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys, register uint count) +static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys, + register uint count) { DBUG_ENTER("write_index"); @@ -256,22 +257,25 @@ static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys, r static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, BUFFPEK *buffpek, - int *maxbuffer, FILE **t_file, - my_string t_name) + int *maxbuffer, IO_CACHE *t_file) { register int i; - FILE *from_file,*to_file,*temp; - FILE *t_file2; - char t_name2[FN_REFLEN]; + IO_CACHE t_file2, *from_file, *to_file, *temp; BUFFPEK *lastbuff; DBUG_ENTER("merge_many_buff"); - if (!(t_file2=opentemp(t_name2,info->tmpdir))) - DBUG_RETURN(1); + if (*maxbuffer < MERGEBUFF2) + DBUG_RETURN(0); /* purecov: inspected */ + if (flush_io_cache(t_file) || + open_cached_file(&t_file2,info->tmpdir,"ST",DISK_BUFFER_SIZE, + info->myf_rw)) + DBUG_RETURN(1); /* purecov: inspected */ - from_file= *t_file ; to_file= t_file2; + from_file= t_file ; to_file= &t_file2; while (*maxbuffer >= MERGEBUFF2) { + reinit_io_cache(from_file,READ_CACHE,0L,0,0); + reinit_io_cache(to_file,WRITE_CACHE,0L,0,0); lastbuff=buffpek; for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF) { @@ -282,17 +286,14 @@ static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys, if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++, buffpek+i,buffpek+ *maxbuffer)) break; - *maxbuffer= (int) (lastbuff-buffpek)-1; + if (flush_io_cache(to_file)) + break; /* purecov: inspected */ temp=from_file; from_file=to_file; to_file=temp; - VOID(my_fseek(to_file,0L,MY_SEEK_SET,MYF(0))); - } - if (to_file == *t_file) - { - closetemp(t_name,to_file); - *t_file=t_file2; - VOID(strmov(t_name,t_name2)); + *maxbuffer= (int) (lastbuff-buffpek)-1; } - else closetemp(t_name2,to_file); + close_cached_file(to_file); // This holds old result + if (to_file == t_file) + *t_file=t_file2; // Copy result file DBUG_RETURN(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */ } /* merge_many_buff */ @@ -301,20 +302,17 @@ static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys, /* Read data to buffer */ /* This returns (uint) -1 if something goes wrong */ -static uint NEAR_F read_to_buffer(FILE *fromfile, BUFFPEK *buffpek, uint sort_length) +static uint NEAR_F read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, + uint sort_length) { register uint count; uint length; - count=buffpek->max_keys; - if ((ha_rows) count > buffpek->count) - count=(uint) buffpek->count; - if (count) + if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count))) { - VOID(my_fseek(fromfile,buffpek->file_pos,MY_SEEK_SET,MYF(0))); - if (my_fread(fromfile,(byte*) buffpek->base, - (length= sort_length*count),MYF_RW)) - return((uint) -1); + if (my_pread(fromfile->file,(byte*) buffpek->base, + (length= sort_length*count),buffpek->file_pos,MYF_RW)) + return((uint) -1); /* purecov: inspected */ buffpek->key=buffpek->base; buffpek->file_pos+= length; /* New filepos */ buffpek->count-= count; @@ -328,8 +326,9 @@ static uint NEAR_F read_to_buffer(FILE *fromfile, BUFFPEK *buffpek, uint sort_le /* If to_file == 0 then use info->key_write */ static int NEAR_F -merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, - uchar **sort_keys, BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb) +merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, + IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff, + BUFFPEK *Fb, BUFFPEK *Tb) { int error; uint sort_length,maxcount; @@ -342,12 +341,11 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, count=error=0; maxcount=keys/((uint) (Tb-Fb) +1); - sort_length=info->key_length; - LINT_INIT(to_start_filepos); if (to_file) - to_start_filepos=my_ftell(to_file,MYF(0)); + to_start_filepos=my_b_tell(to_file); strpos=(uchar*) sort_keys; + sort_length=info->key_length; if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, (int (*)(void*, byte *,byte*)) info->key_cmp, @@ -373,8 +371,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, buffpek=(BUFFPEK*) queue_top(&queue); if (to_file) { - if (my_fwrite(to_file,(byte*) buffpek->key,(uint) sort_length, - MYF_RW | MY_WAIT_IF_FULL)) + if (my_b_write(to_file,(byte*) buffpek->key,(uint) sort_length)) { error=1; goto err; } @@ -417,6 +414,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, break; /* One buffer have been removed */ } } + else if (error == -1) + goto err; /* purecov: inspected */ queue_replaced(&queue); /* Top element has been replaced */ } } @@ -427,9 +426,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, { if (to_file) { - if (my_fwrite(to_file,(byte*) buffpek->key, - (uint) (sort_length*buffpek->mem_count), - MYF_RW | MY_WAIT_IF_FULL)) + if (my_b_write(to_file,(byte*) buffpek->key, + (sort_length*buffpek->mem_count))) { error=1; goto err; } @@ -454,7 +452,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, lastbuff->count=count; if (to_file) - lastbuff->file_pos=to_start_filepos; /* New block starts here */ + lastbuff->file_pos=to_start_filepos; err: delete_queue(&queue); DBUG_RETURN(error); @@ -465,10 +463,10 @@ err: static int NEAR_F merge_index(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, - BUFFPEK *buffpek, int maxbuffer, FILE *tempfile) + BUFFPEK *buffpek, int maxbuffer, IO_CACHE *tempfile) { DBUG_ENTER("merge_index"); - if (merge_buffers(info,keys,tempfile,(FILE*) 0,sort_keys,buffpek,buffpek, + if (merge_buffers(info,keys,tempfile,(IO_CACHE*) 0,sort_keys,buffpek,buffpek, buffpek+maxbuffer)) DBUG_RETURN(1); DBUG_RETURN(0); @@ -492,40 +490,3 @@ static char **make_char_array(register uint fields, uint length, myf my_flag) DBUG_RETURN(old_pos); } /* make_char_array */ - - -/* Open a temporary file that will be deleted on close */ - -static FILE *opentemp(my_string name,const char *temp_dir) -{ - FILE *stream; - reg1 my_string str_pos; - DBUG_ENTER("opentemp"); - - if (!(str_pos=my_tempnam(temp_dir,"ST",MYF(MY_WME)))) - DBUG_RETURN(0); - VOID(strmov(name,str_pos)); - (*free)(str_pos); /* Avoid the 'free' macro */ - - stream=my_fopen(name,(int) (O_RDWR | FILE_BINARY | O_CREAT | O_TEMPORARY), - MYF(MY_WME)); -#if O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES) - VOID(my_delete(name,MYF(MY_WME | ME_NOINPUT))); -#endif - DBUG_PRINT("exit",("stream: %lx",stream)); - DBUG_RETURN (stream); -} /* opentemp */ - - -static void closetemp(my_string name __attribute__((unused)), FILE *stream) -{ - DBUG_ENTER("closetemp"); - - if (stream) - VOID(my_fclose(stream,MYF(MY_WME))); -#if !(O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES)) - if (name) - VOID(my_delete(name,MYF(MY_WME))); -#endif - DBUG_VOID_RETURN; -} /* closetemp */ diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c index c40cfa386d3..9017bf4f18c 100644 --- a/mysys/mf_cache.c +++ b/mysys/mf_cache.c @@ -1,15 +1,15 @@ /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - + You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, @@ -18,66 +18,115 @@ /* Open a temporary file and cache it with io_cache. Delete it on close */ #include "mysys_priv.h" +#include <m_string.h> +#include "my_static.h" +#include "mysys_err.h" +#include <paths.h> + +#define TMP_EXT ".tmp" /* Extension of tempfile */ +#if ! defined(P_tmpdir) +#define P_tmpdir "" +#endif + +#ifdef HAVE_TEMPNAM +#ifndef MSDOS +extern char **environ; +#endif +#endif /* - ** Open a cached tempfile by IO_CACHE + Remove an open tempfile so that it doesn't survive + if we crash; If the operating system doesn't support + this, just remember the file name for later removal + */ + +static my_bool cache_remove_open_tmp(IO_CACHE *cache, const char *name) +{ +#if O_TEMPORARY == 0 +#if !defined(CANT_DELETE_OPEN_FILES) + /* The following should always succeed */ + (void) my_delete(name,MYF(MY_WME | ME_NOINPUT)); +#else + int length; + if (!(cache->file_name= + (char*) my_malloc((length=strlen(name)+1),MYF(MY_WME))) + { + my_close(cache->file,MYF(0)); + cache->file = -1; + errno=my_error=ENOMEM; + return 1; + } + memcpy(cache->file_name,name,length); +#endif +#endif /* O_TEMPORARY == 0 */ + return 0; +} + + /* + ** Open tempfile cached by IO_CACHE ** Should be used when no seeks are done (only reinit_io_buff) ** Return 0 if cache is inited ok ** The actual file is created when the IO_CACHE buffer gets filled + ** If dir is not given, use TMPDIR. */ my_bool open_cached_file(IO_CACHE *cache, const char* dir, const char *prefix, uint cache_size, myf cache_myflags) { DBUG_ENTER("open_cached_file"); - + cache->dir= dir ? my_strdup(dir,MYF(cache_myflags & MY_WME)) : (char*) 0; + cache->prefix= (prefix ? my_strdup(prefix,MYF(cache_myflags & MY_WME)) : + (char*) 0); + cache->file_name=0; cache->buffer=0; /* Mark that not open */ - if (!(cache->file_name=my_tempnam(dir,prefix,MYF(MY_WME)))) - DBUG_RETURN(1); if (!init_io_cache(cache,-1,cache_size,WRITE_CACHE,0L,0, MYF(cache_myflags | MY_NABP))) { DBUG_RETURN(0); } - (*free)(cache->file_name); /* my_tempnam uses malloc() */ - cache->file_name=0; + my_free(cache->dir, MYF(MY_ALLOW_ZERO_PTR)); + my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR)); DBUG_RETURN(0); } + /* Create the temporary file */ my_bool real_open_cached_file(IO_CACHE *cache) { + char name_buff[FN_REFLEN]; + int error=1; DBUG_ENTER("real_open_cached_file"); - if ((cache->file=my_create(cache->file_name,0, - (int) (O_RDWR | O_BINARY | O_TRUNC | O_TEMPORARY | - O_SHORT_LIVED), - MYF(MY_WME))) >= 0) + if ((cache->file=create_temp_file(name_buff, cache->dir, cache->prefix, + (O_RDWR | O_BINARY | O_TRUNC | + O_TEMPORARY | O_SHORT_LIVED), + MYF(MY_WME))) >= 0) { -#if O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES) - VOID(my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT))); -#endif - DBUG_RETURN(0); + error=0; + cache_remove_open_tmp(cache, name_buff); } - DBUG_RETURN(1); + DBUG_RETURN(error); } void close_cached_file(IO_CACHE *cache) { DBUG_ENTER("close_cached_file"); - if (my_b_inited(cache)) { - VOID(end_io_cache(cache)); + (void) end_io_cache(cache); if (cache->file >= 0) { - VOID(my_close(cache->file,MYF(MY_WME))); + (void) my_close(cache->file,MYF(0)); #ifdef CANT_DELETE_OPEN_FILES - VOID(my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT))); + if (cache->file_name) + { + (void) my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT)); + my_free(cache->file_name,MYF(0)); + } #endif } - if (cache->file_name) - (*free)(cache->file_name); /* my_tempnam uses malloc() */ + my_free(cache->dir,MYF(MY_ALLOW_ZERO_PTR)); + my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR)); } DBUG_VOID_RETURN; } diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c index 1bd6d256cfe..f4b9e011215 100644 --- a/mysys/mf_dirname.c +++ b/mysys/mf_dirname.c @@ -66,8 +66,9 @@ uint dirname_part(my_string to, const char *name) #define FN_DEVCHAR '\0' /* For easier code */ #endif -void convert_dirname(my_string to) +char *convert_dirname(my_string to) { + reg1 char *pos; #ifdef FN_UPPER_CASE caseup_str(to); #endif @@ -76,7 +77,6 @@ void convert_dirname(my_string to) #endif #if FN_LIBCHAR != '/' { - reg1 my_string pos; pos=to-1; /* Change from '/' */ while ((pos=strchr(pos+1,'/')) != 0) *pos=FN_LIBCHAR; @@ -84,7 +84,6 @@ void convert_dirname(my_string to) #endif #ifdef FN_C_BEFORE_DIR_2 { - reg1 my_string pos; for (pos=to ; *pos ; pos++) { if (*pos == FN_C_BEFORE_DIR_2) @@ -95,12 +94,13 @@ void convert_dirname(my_string to) } #else { /* Append FN_LIBCHAR if not there */ - char *end=strend(to); - if (end != to && (end[-1] != FN_LIBCHAR && end[-1] != FN_DEVCHAR)) + pos=strend(to); + if (pos != to && (pos[-1] != FN_LIBCHAR && pos[-1] != FN_DEVCHAR)) { - end[0]=FN_LIBCHAR; - end[1]=0; + *pos++=FN_LIBCHAR; + *pos=0; } } #endif + return pos; /* Pointer to end of dir */ } /* convert_dirname */ diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 30424874aa0..e1575b0af48 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -95,7 +95,7 @@ int my_fclose(FILE *fd, myf MyFlags) if ((uint) file < MY_NFILE && my_file_info[file].type != UNOPEN) { my_file_info[file].type = UNOPEN; - my_free(my_file_info[file].name, MYF(0)); + my_free(my_file_info[file].name, MYF(MY_ALLOW_ZERO_PTR)); } pthread_mutex_unlock(&THR_LOCK_open); DBUG_RETURN(err); @@ -103,11 +103,9 @@ int my_fclose(FILE *fd, myf MyFlags) /* Make a stream out of a file handle */ + /* Name may be 0 */ -FILE *my_fdopen(File Filedes, int Flags, myf MyFlags) - - /* Read | write .. */ - /* Special flags */ +FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) { FILE *fd; char type[5]; @@ -125,11 +123,18 @@ FILE *my_fdopen(File Filedes, int Flags, myf MyFlags) else { pthread_mutex_lock(&THR_LOCK_open); - if (my_file_info[Filedes].type != UNOPEN) + my_stream_opened++; + if (Filedes < MY_NFILE) { + if (my_file_info[Filedes].type != UNOPEN) + { + my_file_opened--; /* File is opened with my_open ! */ + } + else + { + my_file_info[Filedes].name= my_strdup(name,MyFlags); + } my_file_info[Filedes].type = STREAM_BY_FDOPEN; - my_file_opened--; /* File is opened with my_open ! */ - my_stream_opened++; } pthread_mutex_unlock(&THR_LOCK_open); } diff --git a/mysys/my_tempnam.c b/mysys/my_tempnam.c index 7e5b953fe53..ac982538668 100644 --- a/mysys/my_tempnam.c +++ b/mysys/my_tempnam.c @@ -1,15 +1,15 @@ /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - + You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, diff --git a/readline/bind.c b/readline/bind.c index 3b311a9e920..bbbbd1b15c4 100644 --- a/readline/bind.c +++ b/readline/bind.c @@ -351,7 +351,7 @@ rl_translate_keyseq (seq, array, len) { register int i, c, l, temp; - for (i = l = 0; c = seq[i]; i++) + for (i = l = 0; (c = seq[i]); i++) { if (c == '\\') { @@ -1028,7 +1028,7 @@ rl_parse_and_bind (string) { int passc = 0; - for (i = 1; c = string[i]; i++) + for (i = 1; (c = string[i]); i++) { if (passc) { @@ -1104,7 +1104,7 @@ rl_parse_and_bind (string) { int delimiter = string[i++], passc; - for (passc = 0; c = string[i]; i++) + for (passc = 0; (c = string[i]); i++) { if (passc) { @@ -1721,7 +1721,7 @@ rl_function_dumper (print_readably) fprintf (rl_outstream, "\n"); - for (i = 0; name = names[i]; i++) + for (i = 0; (name = names[i]); i++) { Function *function; char **invokers; diff --git a/readline/complete.c b/readline/complete.c index dfb1ce0375c..ade317ff578 100644 --- a/readline/complete.c +++ b/readline/complete.c @@ -1377,7 +1377,7 @@ completion_matches (text, entry_function) match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); match_list[1] = (char *)NULL; - while (string = (*entry_function) (text, matches)) + while ((string = (*entry_function) (text, matches))) { if (matches + 1 == match_list_size) match_list = (char **)xrealloc @@ -1427,7 +1427,7 @@ username_completion_function (text, state) setpwent (); } - while (entry = getpwent ()) + while ((entry = getpwent ())) { /* Null usernames should result in all users as possible completions. */ if (namelen == 0 || (STREQN (username, entry->pw_name, namelen))) diff --git a/readline/histexpand.c b/readline/histexpand.c index 392e6d38d9e..30c6131801d 100644 --- a/readline/histexpand.c +++ b/readline/histexpand.c @@ -200,7 +200,7 @@ get_history_event (string, caller_index, delimiting_quote) } /* Only a closing `?' or a newline delimit a substring search string. */ - for (local_index = i; c = string[i]; i++) + for (local_index = i; (c = string[i]); i++) if ((!substring_okay && (whitespace (c) || c == ':' || (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) || string[i] == delimiting_quote)) || diff --git a/readline/input.c b/readline/input.c index 3b48483d262..2813c1b9903 100644 --- a/readline/input.c +++ b/readline/input.c @@ -368,7 +368,7 @@ rl_read_key () else { /* If input is coming from a macro, then use that. */ - if (c = _rl_next_macro_key ()) + if ((c = _rl_next_macro_key ())) return (c); /* If the user has an event function, then call it periodically. */ diff --git a/readline/search.c b/readline/search.c index 6c76e1a1c96..f198e7409e5 100644 --- a/readline/search.c +++ b/readline/search.c @@ -174,7 +174,7 @@ noninc_search (dir, pchar) #define SEARCH_RETURN rl_restore_prompt (); return /* Read the search string. */ - while (c = rl_read_key ()) + while ((c = rl_read_key ())) { switch (c) { diff --git a/readline/shell.c b/readline/shell.c index 091ec08f645..4d9e0064d3f 100644 --- a/readline/shell.c +++ b/readline/shell.c @@ -38,6 +38,10 @@ # include "ansi_stdlib.h" #endif /* HAVE_STDLIB_H */ +#if defined (HAVE_STDIO_H) +# include <stdio.h> +#endif /* HAVE_STDIO_H */ + #if defined (HAVE_STRING_H) # include <string.h> #else diff --git a/readline/terminal.c b/readline/terminal.c index c22ec5170bd..6e94bdc4011 100644 --- a/readline/terminal.c +++ b/readline/terminal.c @@ -232,6 +232,8 @@ _rl_set_screen_size (rows, cols) screenchars = screenwidth * screenheight; } +extern void _rl_redisplay_after_sigwinch(); + void rl_resize_terminal () { @@ -251,32 +253,32 @@ struct _tc_string { search algorithm to something smarter. */ static struct _tc_string tc_strings[] = { - "DC", &term_DC, - "IC", &term_IC, - "ce", &term_clreol, - "cl", &term_clrpag, - "cr", &term_cr, - "dc", &term_dc, - "ei", &term_ei, - "ic", &term_ic, - "im", &term_im, - "kd", &term_kd, - "kh", &term_kh, /* home */ - "kH", &term_kH, /* end */ - "kl", &term_kl, - "kr", &term_kr, - "ku", &term_ku, - "ks", &term_ks, - "ke", &term_ke, - "le", &term_backspace, - "mm", &term_mm, - "mo", &term_mo, + {"DC", &term_DC}, + {"IC", &term_IC}, + {"ce", &term_clreol}, + {"cl", &term_clrpag}, + {"cr", &term_cr}, + {"dc", &term_dc}, + {"ei", &term_ei}, + {"ic", &term_ic}, + {"im", &term_im}, + {"kd", &term_kd}, + {"kh", &term_kh}, /* home */ + {"kH", &term_kH}, /* end */ + {"kl", &term_kl}, + {"kr", &term_kr}, + {"ku", &term_ku}, + {"ks", &term_ks}, + {"ke", &term_ke}, + {"le", &term_backspace}, + {"mm", &term_mm}, + {"mo", &term_mo}, #if defined (HACK_TERMCAP_MOTION) - "nd", &term_forward_char, + {"nd", &term_forward_char}, #endif - "pc", &term_pc, - "up", &term_up, - "vb", &visible_bell, + {"pc", &term_pc}, + {"up", &term_up}, + {"vb", &visible_bell}, }; #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string)) diff --git a/readline/tilde.c b/readline/tilde.c index d1853bd63d6..65a1e2f3902 100644 --- a/readline/tilde.c +++ b/readline/tilde.c @@ -182,7 +182,7 @@ tilde_expand (string) int result_size, result_index; result_index = result_size = 0; - if (result = strchr (string, '~')) + if ((result = strchr (string, '~'))) result = xmalloc (result_size = (strlen (string) + 16)); else result = xmalloc (result_size = (strlen (string) + 1)); diff --git a/readline/undo.c b/readline/undo.c index 28ebcc85b93..68710b667ed 100644 --- a/readline/undo.c +++ b/readline/undo.c @@ -106,7 +106,7 @@ rl_do_undo () { UNDO_LIST *release; int waiting_for_begin = 0; - int start, end; + int start = 0, end = 0; #define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i))) diff --git a/regex/cname.h b/regex/cname.h index 02e86e912e3..2b6a1a8496f 100644 --- a/regex/cname.h +++ b/regex/cname.h @@ -3,100 +3,102 @@ static struct cname { char *name; char code; } cnames[] = { - "NUL", '\0', - "SOH", '\001', - "STX", '\002', - "ETX", '\003', - "EOT", '\004', - "ENQ", '\005', - "ACK", '\006', - "BEL", '\007', - "alert", '\007', - "BS", '\010', - "backspace", '\b', - "HT", '\011', - "tab", '\t', - "LF", '\012', - "newline", '\n', - "VT", '\013', - "vertical-tab", '\v', - "FF", '\014', - "form-feed", '\f', - "CR", '\015', - "carriage-return", '\r', - "SO", '\016', - "SI", '\017', - "DLE", '\020', - "DC1", '\021', - "DC2", '\022', - "DC3", '\023', - "DC4", '\024', - "NAK", '\025', - "SYN", '\026', - "ETB", '\027', - "CAN", '\030', - "EM", '\031', - "SUB", '\032', - "ESC", '\033', - "IS4", '\034', - "FS", '\034', - "IS3", '\035', - "GS", '\035', - "IS2", '\036', - "RS", '\036', - "IS1", '\037', - "US", '\037', - "space", ' ', - "exclamation-mark", '!', - "quotation-mark", '"', - "number-sign", '#', - "dollar-sign", '$', - "percent-sign", '%', - "ampersand", '&', - "apostrophe", '\'', - "left-parenthesis", '(', - "right-parenthesis", ')', - "asterisk", '*', - "plus-sign", '+', - "comma", ',', - "hyphen", '-', - "hyphen-minus", '-', - "period", '.', - "full-stop", '.', - "slash", '/', - "solidus", '/', - "zero", '0', - "one", '1', - "two", '2', - "three", '3', - "four", '4', - "five", '5', - "six", '6', - "seven", '7', - "eight", '8', - "nine", '9', - "colon", ':', - "semicolon", ';', - "less-than-sign", '<', - "equals-sign", '=', - "greater-than-sign", '>', - "question-mark", '?', - "commercial-at", '@', - "left-square-bracket", '[', - "backslash", '\\', - "reverse-solidus", '\\', - "right-square-bracket", ']', - "circumflex", '^', - "circumflex-accent", '^', - "underscore", '_', - "low-line", '_', - "grave-accent", '`', - "left-brace", '{', - "left-curly-bracket", '{', - "vertical-line", '|', - "right-brace", '}', - "right-curly-bracket", '}', - "tilde", '~', - "DEL", '\177', - NULL, 0, + {"NUL", '\0'}, + {"SOH", '\001'}, + {"STX", '\002'}, + {"ETX", '\003'}, + {"EOT", '\004'}, + {"ENQ", '\005'}, + {"ACK", '\006'}, + {"BEL", '\007'}, + {"alert", '\007'}, + {"BS", '\010'}, + {"backspace", '\b'}, + {"HT", '\011'}, + {"tab", '\t'}, + {"LF", '\012'}, + {"newline", '\n'}, + {"VT", '\013'}, + {"vertical-tab",'\v'}, + {"FF", '\014'}, + {"form-feed", '\f'}, + {"CR", '\015'}, + {"carriage-return", '\r'}, + {"SO", '\016'}, + {"SI", '\017'}, + {"DLE", '\020'}, + {"DC1", '\021'}, + {"DC2", '\022'}, + {"DC3", '\023'}, + {"DC4", '\024'}, + {"NAK", '\025'}, + {"SYN", '\026'}, + {"ETB", '\027'}, + {"CAN", '\030'}, + {"EM", '\031'}, + {"SUB", '\032'}, + {"ESC", '\033'}, + {"IS4", '\034'}, + {"FS", '\034'}, + {"IS3", '\035'}, + {"GS", '\035'}, + {"IS2", '\036'}, + {"RS", '\036'}, + {"IS1", '\037'}, + {"US", '\037'}, + {"space", ' '}, + {"exclamation-mark", '!'}, + {"quotation-mark", '"'}, + {"number-sign", '#'}, + {"dollar-sign", '$'}, + {"percent-sign", '%'}, + {"ampersand", '&'}, + {"apostrophe", '\''}, + {"left-parenthesis", '('}, + {"right-parenthesis", ')'}, + {"asterisk", '*'}, + {"plus-sign", '+'}, + {"comma", ','}, + {"hyphen", '-'}, + {"hyphen-minus", '-'}, + {"period", '.'}, + {"full-stop", '.'}, + {"slash", '/'}, + {"solidus", '/'}, + {"zero", '0'}, + {"one", '1'}, + {"two", '2'}, + {"three", '3'}, + {"four", '4'}, + {"five", '5'}, + {"six", '6'}, + {"seven", '7'}, + {"eight", '8'}, + {"nine", '9'}, + {"colon", ':'}, + {"semicolon", ';'}, + {"less-than-sign", '<'}, + {"equals-sign", '='}, + {"greater-than-sign", '>'}, + {"question-mark", '?'}, + {"commercial-at", '@'}, + {"left-square-bracket", '['}, + {"backslash", '\\'}, + {"reverse-solidus", '\\'}, + {"right-square-bracket",']'}, + {"circumflex", '^'}, + {"circumflex-accent", '^'}, + {"underscore", '_'}, + {"low-line", '_'}, + {"grave-accent", '`'}, + {"left-brace", '{'}, + {"left-curly-bracket", '{'}, + {"vertical-line", '|'}, + {"right-brace", '}'}, + {"right-curly-bracket", '}'}, + {"tilde", '~'}, + {"DEL", '\177'}, + {NULL, 0}, }; + + diff --git a/regex/debug.c b/regex/debug.c index 145a9736d39..8c6fd14a209 100644 --- a/regex/debug.c +++ b/regex/debug.c @@ -217,7 +217,7 @@ FILE *d; fprintf(d, ">"); break; default: - fprintf(d, "!%d(%d)!", OP(*s), opnd); + fprintf(d, "!%ld(%ld)!", OP(*s), opnd); break; } if (!done) diff --git a/regex/main.c b/regex/main.c index beed2738b1d..4b607f401ca 100644 --- a/regex/main.c +++ b/regex/main.c @@ -103,7 +103,7 @@ char *argv[]; len = (int)(subs[0].rm_eo - subs[0].rm_so); if (subs[0].rm_so != -1) { if (len != 0) - printf("match `%.*s'\n", len, + printf("match `%.*s'\n", (int)len, argv[optind] + subs[0].rm_so); else printf("match `'@%.1s\n", diff --git a/regex/regcomp.c b/regex/regcomp.c index 885c6a7cbc8..048f45ca71c 100644 --- a/regex/regcomp.c +++ b/regex/regcomp.c @@ -219,7 +219,7 @@ int stop; /* character this ERE should end at */ conc = HERE(); while (MORE() && (c = PEEK()) != '|' && c != stop) p_ere_exp(p); - REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ + if(REQUIRE(HERE() != conc, REG_EMPTY)); /* require nonempty */ if (!EAT('|')) break; /* NOTE BREAK OUT */ @@ -266,7 +266,7 @@ register struct parse *p; pos = HERE(); switch (c) { case '(': - REQUIRE(MORE(), REG_EPAREN); + if(REQUIRE(MORE(), REG_EPAREN)); p->g->nsub++; subno = (sopno) p->g->nsub; if (subno < NPAREN) @@ -279,7 +279,7 @@ register struct parse *p; assert(p->pend[subno] != 0); } EMIT(ORPAREN, subno); - MUSTEAT(')', REG_EPAREN); + if(MUSTEAT(')', REG_EPAREN)); break; #ifndef POSIX_MISTAKE case ')': /* happens only if no current unmatched ( */ @@ -322,12 +322,12 @@ register struct parse *p; p_bracket(p); break; case '\\': - REQUIRE(MORE(), REG_EESCAPE); + if(REQUIRE(MORE(), REG_EESCAPE)); c = GETNEXT(); ordinary(p, c); break; case '{': /* okay as ordinary except if digit follows */ - REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT); + if(REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT)); /* FALLTHROUGH */ default: ordinary(p, c); @@ -343,7 +343,7 @@ register struct parse *p; return; /* no repetition, we're done */ NEXT(); - REQUIRE(!wascaret, REG_BADRPT); + if(REQUIRE(!wascaret, REG_BADRPT)); switch (c) { case '*': /* implemented as +? */ /* this case does not require the (y|) trick, noKLUDGE */ @@ -370,7 +370,7 @@ register struct parse *p; if (EAT(',')) { if (isdigit(PEEK())) { count2 = p_count(p); - REQUIRE(count <= count2, REG_BADBR); + if(REQUIRE(count <= count2, REG_BADBR)); } else /* single number with comma */ count2 = RE_INFINITY; } else /* just a single number */ @@ -379,7 +379,7 @@ register struct parse *p; if (!EAT('}')) { /* error heuristics */ while (MORE() && PEEK() != '}') NEXT(); - REQUIRE(MORE(), REG_EBRACE); + if(REQUIRE(MORE(), REG_EBRACE)); SETERROR(REG_BADBR); } break; @@ -402,7 +402,7 @@ static void p_str(p) register struct parse *p; { - REQUIRE(MORE(), REG_EMPTY); + if(REQUIRE(MORE(), REG_EMPTY)); while (MORE()) ordinary(p, GETNEXT()); } @@ -445,7 +445,7 @@ register int end2; /* second terminating character */ p->g->neol++; } - REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */ + if(REQUIRE(HERE() != start, REG_EMPTY)); /* require nonempty */ } /* @@ -470,7 +470,7 @@ int starordinary; /* is a leading * an ordinary character? */ assert(MORE()); /* caller should have ensured this */ c = GETNEXT(); if (c == '\\') { - REQUIRE(MORE(), REG_EESCAPE); + if(REQUIRE(MORE(), REG_EESCAPE)); c = BACKSL | (unsigned char)GETNEXT(); } switch (c) { @@ -500,7 +500,7 @@ int starordinary; /* is a leading * an ordinary character? */ assert(p->pend[subno] != 0); } EMIT(ORPAREN, subno); - REQUIRE(EATTWO('\\', ')'), REG_EPAREN); + if(REQUIRE(EATTWO('\\', ')'), REG_EPAREN)); break; case BACKSL|')': /* should not get here -- must be user */ case BACKSL|'}': @@ -530,7 +530,7 @@ int starordinary; /* is a leading * an ordinary character? */ p->g->backrefs = 1; break; case '*': - REQUIRE(starordinary, REG_BADRPT); + if(REQUIRE(starordinary, REG_BADRPT)); /* FALLTHROUGH */ default: ordinary(p, c &~ BACKSL); @@ -548,7 +548,7 @@ int starordinary; /* is a leading * an ordinary character? */ if (EAT(',')) { if (MORE() && isdigit(PEEK())) { count2 = p_count(p); - REQUIRE(count <= count2, REG_BADBR); + if(REQUIRE(count <= count2, REG_BADBR)); } else /* single number with comma */ count2 = RE_INFINITY; } else /* just a single number */ @@ -557,7 +557,7 @@ int starordinary; /* is a leading * an ordinary character? */ if (!EATTWO('\\', '}')) { /* error heuristics */ while (MORE() && !SEETWO('\\', '}')) NEXT(); - REQUIRE(MORE(), REG_EBRACE); + if(REQUIRE(MORE(), REG_EBRACE)); SETERROR(REG_BADBR); } } else if (c == (unsigned char)'$') /* $ (but not \$) ends it */ @@ -582,7 +582,7 @@ register struct parse *p; ndigits++; } - REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); + if(REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR)); return(count); } @@ -622,7 +622,7 @@ register struct parse *p; p_b_term(p, cs); if (EAT('-')) CHadd(cs, '-'); - MUSTEAT(']', REG_EBRACK); + if(MUSTEAT(']', REG_EBRACK)); if (p->error != 0) /* don't mess things up further */ return; @@ -693,21 +693,21 @@ register cset *cs; switch (c) { case ':': /* character class */ NEXT2(); - REQUIRE(MORE(), REG_EBRACK); + if(REQUIRE(MORE(), REG_EBRACK)); c = PEEK(); - REQUIRE(c != '-' && c != ']', REG_ECTYPE); + if(REQUIRE(c != '-' && c != ']', REG_ECTYPE)); p_b_cclass(p, cs); - REQUIRE(MORE(), REG_EBRACK); - REQUIRE(EATTWO(':', ']'), REG_ECTYPE); + if(REQUIRE(MORE(), REG_EBRACK)); + if(REQUIRE(EATTWO(':', ']'), REG_ECTYPE)); break; case '=': /* equivalence class */ NEXT2(); - REQUIRE(MORE(), REG_EBRACK); + if(REQUIRE(MORE(), REG_EBRACK)); c = PEEK(); - REQUIRE(c != '-' && c != ']', REG_ECOLLATE); + if(REQUIRE(c != '-' && c != ']', REG_ECOLLATE)); p_b_eclass(p, cs); - REQUIRE(MORE(), REG_EBRACK); - REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); + if(REQUIRE(MORE(), REG_EBRACK)); + if(REQUIRE(EATTWO('=', ']'), REG_ECOLLATE)); break; default: /* symbol, ordinary character, or range */ /* xxx revision needed for multichar stuff */ @@ -722,7 +722,7 @@ register cset *cs; } else finish = start; /* xxx what about signed chars here... */ - REQUIRE(start <= finish, REG_ERANGE); + if(REQUIRE(start <= finish, REG_ERANGE)); for (i = start; i <= finish; i++) CHadd(cs, i); break; @@ -790,13 +790,13 @@ register struct parse *p; { register char value; - REQUIRE(MORE(), REG_EBRACK); + if(REQUIRE(MORE(), REG_EBRACK)); if (!EATTWO('[', '.')) return(GETNEXT()); /* collating symbol */ value = p_b_coll_elem(p, '.'); - REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); + if(REQUIRE(EATTWO('.', ']'), REG_ECOLLATE)); return(value); } diff --git a/regex/regerror.c b/regex/regerror.c index 4810db23f12..a356912564a 100644 --- a/regex/regerror.c +++ b/regex/regerror.c @@ -31,23 +31,23 @@ static struct rerr { char *name; char *explain; } rerrs[] = { - REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match", - REG_BADPAT, "REG_BADPAT", "invalid regular expression", - REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element", - REG_ECTYPE, "REG_ECTYPE", "invalid character class", - REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)", - REG_ESUBREG, "REG_ESUBREG", "invalid backreference number", - REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced", - REG_EPAREN, "REG_EPAREN", "parentheses not balanced", - REG_EBRACE, "REG_EBRACE", "braces not balanced", - REG_BADBR, "REG_BADBR", "invalid repetition count(s)", - REG_ERANGE, "REG_ERANGE", "invalid character range", - REG_ESPACE, "REG_ESPACE", "out of memory", - REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid", - REG_EMPTY, "REG_EMPTY", "empty (sub)expression", - REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug", - REG_INVARG, "REG_INVARG", "invalid argument to regex routine", - 0, "", "*** unknown regexp error code ***", + {REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"}, + {REG_BADPAT, "REG_BADPAT", "invalid regular expression"}, + {REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"}, + {REG_ECTYPE, "REG_ECTYPE", "invalid character class"}, + {REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)"}, + {REG_ESUBREG, "REG_ESUBREG", "invalid backreference number"}, + {REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced"}, + {REG_EPAREN, "REG_EPAREN", "parentheses not balanced"}, + {REG_EBRACE, "REG_EBRACE", "braces not balanced"}, + {REG_BADBR, "REG_BADBR", "invalid repetition count(s)"}, + {REG_ERANGE, "REG_ERANGE", "invalid character range"}, + {REG_ESPACE, "REG_ESPACE", "out of memory"}, + {REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid"}, + {REG_EMPTY, "REG_EMPTY", "empty (sub)expression"}, + {REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug"}, + {REG_INVARG, "REG_INVARG", "invalid argument to regex routine"}, + {0, "", "*** unknown regexp error code ***"}, }; /* diff --git a/sql/filesort.cc b/sql/filesort.cc index 96ce57fc683..10984af5510 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -861,7 +861,6 @@ static int merge_index(SORTPARAM *param, uchar **sort_keys, buffpek+maxbuffer,1)) DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(0); - /* Was: DBUG_RETURN(my_b_write(outfile,last_ref,param->ref_length)); */ } /* merge_index */ diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 768e663bfa5..1c5356e0c32 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -31,10 +31,11 @@ #endif ulong myisam_sort_buffer_size; -myisam_recover_types myisam_recover_type= HA_RECOVER_NONE; +ulong myisam_recover_options= HA_RECOVER_NONE; +/* bits in myisam_recover_options */ const char *myisam_recover_names[] = -{ "NO","DEFAULT", "BACKUP"}; +{ "DEFAULT", "BACKUP", "FORCE"}; TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names),"", myisam_recover_names}; @@ -152,7 +153,7 @@ int ha_myisam::dump(THD* thd, int fd) my_off_t bytes_to_read = share->state.state.data_file_length; int data_fd = file->dfile; byte * buf = (byte*) my_malloc(blocksize, MYF(MY_WME)); - if(!buf) + if (!buf) return ENOMEM; int error = 0; @@ -342,19 +343,19 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) char* backup_dir = thd->lex.backup_dir; char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char* table_name = table->real_name; - if(!fn_format(src_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64)) + if (!fn_format(src_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64)) return HA_ADMIN_INVALID; int error = 0; const char* errmsg = ""; - if(my_copy(src_path, fn_format(dst_path, table->path, "", - MI_NAME_DEXT, 4), MYF(MY_WME))) - { - error = HA_ADMIN_FAILED; - errmsg = "failed in my_copy( Error %d)"; - goto err; - } + if (my_copy(src_path, fn_format(dst_path, table->path, "", + MI_NAME_DEXT, 4), MYF(MY_WME))) + { + error = HA_ADMIN_FAILED; + errmsg = "failed in my_copy( Error %d)"; + goto err; + } tmp_check_opt.init(); tmp_check_opt.quick = 1; @@ -373,26 +374,27 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) } } + int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) { char* backup_dir = thd->lex.backup_dir; char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char* table_name = table->real_name; - if(!fn_format(dst_path, table_name, backup_dir, reg_ext, 4 + 64)) + if (!fn_format(dst_path, table_name, backup_dir, reg_ext, 4 + 64)) return HA_ADMIN_INVALID; - if(my_copy(fn_format(src_path, table->path,"", reg_ext, 4), + if (my_copy(fn_format(src_path, table->path,"", reg_ext, 4), dst_path, MYF(MY_WME | MY_HOLD_ORIGINAL_MODES ))) - { - return HA_ADMIN_FAILED; - } + { + return HA_ADMIN_FAILED; + } - if(!fn_format(dst_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64)) + if (!fn_format(dst_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64)) return HA_ADMIN_INVALID; - if(my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT, 4), - dst_path, - MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) ) + if (my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT, 4), + dst_path, + MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) ) return HA_ADMIN_FAILED; return HA_ADMIN_OK; @@ -572,6 +574,33 @@ bool ha_myisam::activate_all_index(THD *thd) DBUG_RETURN(error); } + +bool ha_myisam::check_and_repair(THD *thd, const char *name) +{ + int error=0; + HA_CHECK_OPT check_opt; + 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.flags=T_MEDIUM; + if (mi_is_crashed(file) || check(thd, &check_opt)) + { + check_opt.flags=(((myisam_recover_options & HA_RECOVER_BACKUP) ? + T_BACKUP_DATA : 0) | + (!(myisam_recover_options & HA_RECOVER_FORCE) ? + T_SAFE_REPAIR : 0)); + if (repair(thd, &check_opt)) + error=1; + } + if (close()) + error=1; + DBUG_RETURN(error); +} + + int ha_myisam::update_row(const byte * old_data, byte * new_data) { statistic_increment(ha_update_count,&LOCK_status); diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h index f1e5b217762..d33fc52c937 100644 --- a/sql/ha_myisam.h +++ b/sql/ha_myisam.h @@ -24,12 +24,14 @@ #include <myisam.h> #include <ft_global.h> -enum myisam_recover_types { HA_RECOVER_NONE, HA_RECOVER_DEFAULT, - HA_RECOVER_BACKUP}; +#define HA_RECOVER_NONE 0 // No automatic recover +#define HA_RECOVER_DEFAULT 1 // Automatic recover active +#define HA_RECOVER_BACKUP 2 // Make a backupfile on recover +#define HA_RECOVER_FORCE 4 // Recover even if we loose rows extern ulong myisam_sort_buffer_size; extern TYPELIB myisam_recover_typelib; -extern myisam_recover_types myisam_recover_type; +extern ulong myisam_recover_options; class ha_myisam: public handler { @@ -39,11 +41,12 @@ class ha_myisam: public handler public: ha_myisam(TABLE *table): handler(table), file(0), - int_option_flag(HA_READ_NEXT+HA_READ_PREV+HA_READ_RND_SAME+ - HA_KEYPOS_TO_RNDPOS+ HA_READ_ORDER+ HA_LASTKEY_ORDER+ - HA_HAVE_KEY_READ_ONLY+ HA_READ_NOT_EXACT_KEY+ - HA_LONGLONG_KEYS+ HA_NULL_KEY + - HA_DUPP_POS + HA_BLOB_KEY + HA_AUTO_PART_KEY) + int_option_flag(HA_READ_NEXT | HA_READ_PREV | HA_READ_RND_SAME | + HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER | + HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY | + HA_LONGLONG_KEYS | HA_NULL_KEY | + HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY | + HA_CHECK_AND_REPAIR) {} ~ha_myisam() {} const char *table_type() const { return "MyISAM"; } @@ -100,6 +103,7 @@ class ha_myisam: public handler int check(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); + bool check_and_repair(THD *thd, const char *name); int optimize(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); diff --git a/sql/handler.cc b/sql/handler.cc index 68d12a96f98..a0ec18d3614 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -594,7 +594,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info, TABLE table; DBUG_ENTER("ha_create_table"); - if (openfrm(name,"",0,(uint) READ_ALL,&table)) + if (openfrm(name,"",0,(uint) READ_ALL, 0, &table)) DBUG_RETURN(1); if (update_create_info) { diff --git a/sql/handler.h b/sql/handler.h index 7f39b78deee..d256ee944e7 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -66,6 +66,7 @@ #define HA_NO_WRITE_DELAYED (HA_NOT_EXACT_COUNT*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_CHECK_AND_REPAIR (HA_DROP_BEFORE_CREATE*2) /* Parameters for open() (in register form->filestat) */ /* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */ @@ -248,6 +249,7 @@ public: virtual void update_create_info(HA_CREATE_INFO *create_info) {} virtual int check(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 int optimize(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); diff --git a/sql/key.cc b/sql/key.cc index df3f0fe25d5..8678202922e 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -243,7 +243,10 @@ void key_unpack(String *to,TABLE *table,uint idx) } -/* Return 1 if any field in a list is part of key */ +/* + Return 1 if any field in a list is part of key or the key uses a field + that is automaticly updated (like a timestamp) +*/ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields) { @@ -255,6 +258,10 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields) key_part++) { Item_field *field; + + if (key_part->field == table->timestamp_field) + return 1; // Can't be used for update + f.rewind(); while ((field=(Item_field*) f++)) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index dd87f40efe9..c428cb2936b 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -531,7 +531,7 @@ int rea_create_table(my_string file_name,HA_CREATE_INFO *create_info, int format_number(uint inputflag,uint max_length,my_string pos,uint length, my_string *errpos); int openfrm(const char *name,const char *alias,uint filestat,uint prgflag, - TABLE *outparam); + uint ha_open_flags, TABLE *outparam); int closefrm(TABLE *table); db_type get_table_type(const char *name); int read_string(File file, gptr *to, uint length); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index aa3aa0b0bf4..90afdcd42d5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -282,7 +282,7 @@ extern pthread_handler_decl(handle_slave,arg); #ifdef SET_RLIMIT_NOFILE static uint set_maximum_open_files(uint max_file_limit); #endif - +static ulong find_bit_type(const char *x, TYPELIB *bit_lib); /**************************************************************************** ** Code to end mysqld @@ -1064,6 +1064,7 @@ static void init_signals(void) sigaddset(&set,SIGTERM); sigaddset(&set,SIGHUP); signal(SIGTERM,SIG_DFL); // If it's blocked by parent + signal(SIGHUP,SIG_DFL); // If it's blocked by parent #ifdef SIGTSTP sigaddset(&set,SIGTSTP); #endif @@ -2568,6 +2569,8 @@ static void usage(void) Log slow queries to this log file. Defaults logging\n\ to hostname-slow.log\n\ --pid-file=path Pid file used by safe_mysqld\n\ + --myisam-recover[=option[,option...]] where options is one of DEAULT,\n\ + BACKUP or FORCE.\n\ --memlock Lock mysqld in memory\n\ -n, --new Use very new possible 'unsafe' functions\n\ -o, --old-protocol Use the old (3.20) protocol\n\ @@ -2856,13 +2859,13 @@ static void get_options(int argc,char **argv) default_table_type=DB_TYPE_ISAM; myisam_delay_key_write=0; myisam_concurrent_insert=0; - myisam_recover_type= HA_RECOVER_NONE; + myisam_recover_options= 0; break; case (int) OPT_SAFE: opt_specialflag|= SPECIAL_SAFE_MODE; myisam_delay_key_write=0; myisam_concurrent_insert=0; - myisam_recover_type= HA_RECOVER_NONE; // For now + myisam_recover_options= HA_RECOVER_NONE; // To be changed break; case (int) OPT_SKIP_CONCURRENT_INSERT: myisam_concurrent_insert=0; @@ -3026,13 +3029,14 @@ static void get_options(int argc,char **argv) #endif case OPT_MYISAM_RECOVER: { - int type; - if ((type=find_type(optarg, &myisam_recover_typelib, 2)) <= 0) + if (!optarg || !optarg[0]) + myisam_recover_options=HA_RECOVER_DEFAULT; + else if ((myisam_recover_options= + find_bit_type(optarg, &myisam_recover_typelib)) == ~(ulong) 0) { - fprintf(stderr,"Unknown option to myisam-recover: %s\n",optarg); + fprintf(stderr, "Unknown option to myisam-recover: %s\n",optarg); exit(1); } - myisam_recover_type=(myisam_recover_types) (type-1); break; } case OPT_MASTER_HOST: @@ -3568,6 +3572,64 @@ static uint set_maximum_open_files(uint max_file_limit) #endif + /* + Return a bitfield from a string of substrings separated by ',' + returns ~(ulong) 0 on error. + */ + +static ulong find_bit_type(const char *x, TYPELIB *bit_lib) +{ + bool found_end; + int found_count; + const char *end,*i,*j; + const char **array, *pos; + ulong found,found_int,bit; + DBUG_ENTER("find_bit_type"); + DBUG_PRINT("enter",("x: '%s'",x)); + + found=0; + found_end= 0; + pos=(my_string) x; + do + { + if (!*(end=strcend(pos,','))) /* Let end point at fieldend */ + { + while (end > pos && end[-1] == ' ') + end--; /* Skipp end-space */ + found_end=1; + } + found_int=0; found_count=0; + for (array=bit_lib->type_names, bit=1 ; (i= *array++) ; bit<<=1) + { + j=pos; + while (j != end) + { + if (toupper(*i++) != toupper(*j++)) + goto skipp; + } + found_int=bit; + if (! *i) + { + found_count=1; + break; + } + else if (j != pos) // Half field found + { + found_count++; // Could be one of two values + } +skipp: ; + } + if (found_count != 1) + DBUG_RETURN(~(ulong) 0); // No unique value + found|=found_int; + pos=end+1; + } while (! found_end); + + DBUG_PRINT("exit",("bit-field: %ld",(ulong) found)); + DBUG_RETURN(found); +} /* find_bit_type */ + + /***************************************************************************** ** Instantiate templates *****************************************************************************/ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index eb3952be281..e216d771063 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -675,7 +675,7 @@ void close_thread_tables(THD *thd, bool locked) } thd->open_tables=0; /* Free tables to hold down open files */ - while (open_cache.records >= table_cache_size && unused_tables) + while (open_cache.records > table_cache_size && unused_tables) VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */ check_unused(); if (found_old_table) @@ -987,7 +987,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, else { /* Free cache if too big */ - while (open_cache.records >= table_cache_size && unused_tables) + while (open_cache.records > table_cache_size && unused_tables) VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */ /* make a new table */ @@ -1410,6 +1410,7 @@ static int open_unireg_entry(TABLE *entry,const char *db,const char *name, (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | HA_TRY_READ_ONLY), READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, + ha_open_options, entry)) { DBUG_RETURN(1); @@ -1575,6 +1576,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | HA_TRY_READ_ONLY), READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, + ha_open_options, tmp_table)) { DBUG_RETURN(0); @@ -1859,6 +1861,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, DBUG_RETURN(-1); /* purecov: inspected */ if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) item->split_sum_func(*sum_func_list); + thd->used_tables|=item->used_tables(); } } DBUG_RETURN(test(thd->fatal_error)); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 2db08045d89..31390066e2e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -88,6 +88,7 @@ THD::THD() open_tables=temporary_tables=0; tmp_table=0; lock=locked_tables=0; + used_tables=0; cuted_fields=0L; options=thd_startup_options; update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE; diff --git a/sql/sql_class.h b/sql/sql_class.h index 9e4293c7b62..2e3f9252377 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -263,6 +263,7 @@ public: ulonglong next_insert_id,last_insert_id,current_insert_id; ha_rows select_limit,offset_limit,default_select_limit,cuted_fields, max_join_size,sent_row_count; + table_map used_tables; ulong query_id,version, inactive_timeout,options,thread_id; long dbug_thread_id; pthread_t real_id; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 13feba9ab9c..26d110ba31c 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -140,6 +140,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, if (!table) DBUG_RETURN(-1); thd->proc_info="init"; + thd->used_tables=0; save_time_stamp=table->time_stamp; values= its++; if (check_insert_fields(thd,table,fields,*values,1) || @@ -200,7 +201,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, } else { - table->record[0][0]=table->record[2][0]; // Fix delete marker + if (thd->used_tables) // Column used in values() + restore_record(table,2); // Get empty record + else + table->record[0][0]=table->record[2][0]; // Fix delete marker if (fill_record(table->field,*values)) { if (values_list.elements != 1) @@ -1166,12 +1170,7 @@ select_insert::prepare(List<Item> &values) if (check_insert_fields(thd,table,*fields,values,1)) DBUG_RETURN(1); - if (fields->elements) - { - restore_record(table,2); // Get empty record - } - else - table->record[0][0]=table->record[2][0]; // Fix delete marker + restore_record(table,2); // Get empty record table->next_number_field=table->found_next_number_field; thd->count_cuted_fields=1; /* calc cuted fields */ thd->cuted_fields=0; diff --git a/sql/table.cc b/sql/table.cc index 66a2ef767b0..c7fe81c182c 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -40,7 +40,7 @@ static byte* get_field_name(Field *buff,uint *length, /* Open a .frm file */ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, - TABLE *outparam) + uint ha_open_flags, TABLE *outparam) { reg1 uint i; reg2 uchar *strpos; @@ -216,12 +216,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ha_open(index_file, (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR), (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE : - db_stat & HA_WAIT_IF_LOCKED || - specialflag & SPECIAL_WAIT_IF_LOCKED ? + (db_stat & HA_WAIT_IF_LOCKED || + specialflag & SPECIAL_WAIT_IF_LOCKED) ? HA_OPEN_WAIT_IF_LOCKED : (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ? HA_OPEN_ABORT_IF_LOCKED : - HA_OPEN_IGNORE_IF_LOCKED) | ha_open_options))) + HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))) goto err_not_open; /* purecov: inspected */ } outparam->db_low_byte_first=outparam->file->low_byte_first(); |