diff options
50 files changed, 818 insertions, 449 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 4004210c803..5acbc173ec6 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -18,8 +18,8 @@ sasha@work.mysql.com serg@infomag.ape.relarn.ru serg@work.mysql.com sinisa@work.mysql.com +spurr@nslinux.bedford.progress.com tim@localhost.polyesthetic.msg +tim@threads.polyesthetic.msg tim@work.mysql.com tonu@work.mysql.com -spurr@nslinux.bedford.progress.com -tim@threads.polyesthetic.msg diff --git a/Docs/manual.texi b/Docs/manual.texi index 85263ff6701..3fd2aa0ef60 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -2157,7 +2157,7 @@ Webmerger - This CGI tool interprets files and generates dynamic output based on a set of simple tags. Ready-to-run drivers for @strong{MySQL} and PostgreSQL through ODBC. -@item @uref{http://phpclub.unet.ru/index_e.php3}@* +@item @uref{http://phpclub.net/}@* PHPclub - Tips and tricks for PHP. @item @uref{http://www.penguinservices.com/scripts}@* @@ -8987,6 +8987,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}. @@ -21068,6 +21086,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 @@ -21151,6 +21172,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 @@ -35829,7 +35862,7 @@ don't yet support: @table @code @item Sub select -@item Foregin keys +@item Foreign keys @item Stored procedures @item An extendable type system. @item A way to extend the SQL to handle new key types (like R-trees) @@ -36640,13 +36673,12 @@ only on Linux. You can always find the latest version @uref{http://www.trash.net/~ffischer/admin/index.html, here}. -@c Link temporary removed on request because of a bug in the current version -@c @item @uref{http://www.mysql.com/Downloads/Win32/MySQL-Maker092.zip,MySQL-Maker 092}. -@c Shareware @strong{MySQL} client for windows. It's WYSIWYG tool which allows -@c you to create, change and delete databases and tables. -@c You can change field - structure and add, change and delete data in -@c these tables directly without ODBC-driver. -@c @uref{http://62.26.183.157/presult/support/su_sweiche_download.html, MySQL Maker homepage} +@item @uref{http://www.mysql.com/Downloads/Win32/MySQL-Maker-1.0.zip,MySQL-Maker 1.0}. +Shareware @strong{MySQL} client for windows. It's WYSIWYG tool which allows +you to create, change and delete databases and tables. +You can change field - structure and add, change and delete data in +these tables directly without ODBC-driver. +@uref{http://www.presult.de/presult/frames/fs_mysqlmaker.html, MySQL Maker homepage} @item @uref{http://www.mysql.com/Downloads/Contrib/mysqlwinadmn.zip, mysqlwinadmn.zip} Windows GUI (binary only) to administrate a database, by David B. Mansel, @@ -36949,8 +36981,8 @@ Raw port of a SQL mode for XEmacs. Supports completion. Original by Peter D. Pezaris @email{pez@@atlantic2.sbi.com} and partial @strong{MySQL} port by David Axmark. -@item @uref{http://www.mysql.com/Downloads/Win32/myaccess97_1_1.zip, MyAccess97 1.1} -@item @uref{http://www.mysql.com/Downloads/Win32/myaccess2000_1_1.zip, MyAccess2000 1.1} +@item @uref{http://www.mysql.com/Downloads/Win32/myaccess97_1_3.zip, MyAccess97 1.3} +@item @uref{http://www.mysql.com/Downloads/Win32/myaccess2000_1_3.zip, MyAccess2000 1.3} MyAccess is an AddIn for MS Access 97/2000 which allows you to manage MySQL databases from within Access. Main functions are: @itemize @bullet @@ -37419,6 +37451,13 @@ though, so 3.23 is not released as a stable version yet. @appendixsubsec Changes in release 3.23.26 @itemize @bullet @item +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 @code{NULL} column. @item Changed to use @code{mkstemp()} instead of @code{tempnam()}. 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/config.guess b/config.guess index cd4de2b0090..eb88894019f 100755 --- a/config.guess +++ b/config.guess @@ -987,6 +987,9 @@ EOF *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 diff --git a/config.sub b/config.sub index a5b9229f850..8f28d3f7be8 100755 --- a/config.sub +++ b/config.sub @@ -919,7 +919,7 @@ case $os in | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -openstep* | -oskit*) + | -interix* | -uwin* | -rhapsody* | -darwin* | -openstep* | -oskit*) # Remember, each alternative MUST END IN *, to match a version number. ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ diff --git a/configure.in b/configure.in index 394b4f83a89..1842ac5d2fc 100644 --- a/configure.in +++ b/configure.in @@ -331,7 +331,13 @@ elif $PS $$ 2> /dev/null | grep $0 > /dev/null then FIND_PROC="$PS \$\$PID | grep mysqld > /dev/null" else - AC_MSG_ERROR([Could not find the right ps switches. Which OS is this ?. See the Installation chapter in the Reference Manual.]) + case $SYSTEM_TYPE in + *darwin*) + FIND_PROC="$PS -uaxww | grep mysqld | grep \" \$\$PID \" > /dev/null" + ;; + *) + AC_MSG_ERROR([Could not find the right ps switches. Which OS is this ?. See the Installation chapter in the Reference Manual.]) + esac fi AC_SUBST(FIND_PROC) AC_MSG_RESULT("$FIND_PROC") @@ -619,6 +625,7 @@ int main() # Some system specific hacks # +MAX_C_OPTIMIZE="-O6" case $SYSTEM_TYPE in *solaris2.7*) # Solaris 2.7 has a broken /usr/include/widec.h @@ -674,6 +681,15 @@ case $SYSTEM_TYPE in fi fi ;; + *darwin*) + if test "$ac_cv_prog_gcc" = "yes" + then + CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS" + CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS" + MAX_C_OPTIMIZE="-O" + with_named_curses="" + fi + ;; *freebsd*) echo "Adding fix for interrupted reads" CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000" @@ -1012,7 +1028,7 @@ if test "$ac_cv_prog_gcc" = "yes" then DEBUG_CFLAGS="-g" DEBUG_OPTIMIZE_CC="-O" - OPTIMIZE_CFLAGS="-O6" + OPTIMIZE_CFLAGS="$MAX_C_OPTIMIZE" else DEBUG_CFLAGS="-g" DEBUG_OPTIMIZE_CC="" @@ -1221,7 +1237,7 @@ AC_CHECK_FUNCS(alarm bmove \ getrusage getpwuid getcwd getrlimit getwd index stpcpy locking longjmp \ perror pread realpath rename \ socket strnlen madvise \ - strtoul strtoull snprintf tempnam thr_setconcurrency \ + strtol strtoul strtoull snprintf tempnam thr_setconcurrency \ gethostbyaddr_r gethostbyname_r getpwnam \ bfill bzero bcmp strstr strpbrk strerror\ tell atod memcpy memmove \ diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index a6e67e4949e..01fc4108352 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -48,7 +48,7 @@ static void usage(my_bool version) puts("Prints all arguments that is give to some program using the default files"); printf("Usage: %s [OPTIONS] groups\n",my_progname); printf("\n\ - -c, --config-file=# --defaults-file=#\n\ + -c, --config-file=#, --defaults-file=#\n\ The config file to use (default '%s')\n\ --no-defaults Return an empty string (useful for scripts)\n\ -?, --help Display this help message and exit.\n\ diff --git a/include/my_pthread.h b/include/my_pthread.h index e34fffbb239..2ecd4e20482 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -346,6 +346,19 @@ struct tm *localtime_r(const time_t *clock, struct tm *res); #define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); } #endif +#ifdef HAVE_DARWIN_THREADS +#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C)) +#define pthread_kill(A,B) pthread_dummy(0) +#define pthread_condattr_init(A) pthread_dummy(0) +#define pthread_condattr_destroy(A) pthread_dummy(0) +#define pthread_cond_init( A, B ) pthread_cond_init( (A), 0 ) +#define pthread_signal(A,B) pthread_dummy(0) +#undef pthread_detach_this_thread +#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); } +#undef sigset +#define sigset(A,B) pthread_signal((A),(void (*)(int)) (B)) +#endif + #if ((defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)) || defined(HAVE_DEC_3_2_THREADS)) && !defined(HAVE_CTHREADS_WRAPPER) /* This is set on AIX_3_2 and Siemens unix (and DEC OSF/1 3.2 too) */ #define pthread_key_create(A,B) \ 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 */ @@ -1798,7 +1798,7 @@ bsdi4*) finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - file_magic_cmd=/usr/bin/file + file_magic_cmd="/usr/bin/file -L" file_magic_test_file=/shlib/libc.so sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" diff --git a/myisam/mi_check.c b/myisam/mi_check.c index ce561e13bd2..c6a07ff9c36 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; @@ -2921,8 +2922,10 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, !(((ulonglong) 1 << (info->s->base.auto_key-1) & info->s->state.key_map))) { - mi_check_print_info(param,"Table: %s doesn't have an auto increment key\n", - param->isam_file_name); + if (!(param->testflag & T_VERY_SILENT)) + mi_check_print_info(param, + "Table: %s doesn't have an auto increment key\n", + param->isam_file_name); return; } if (!(param->testflag & T_SILENT) && 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/Makefile.am b/mysys/Makefile.am index 6697bfeeae4..6b38d9364f6 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -26,7 +26,8 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\ mf_path.c mf_loadpath.c\ my_open.c my_create.c my_seek.c my_read.c \ my_pread.c my_write.c \ - mf_reccache.c mf_keycache.c mf_iocache.c mf_cache.c \ + mf_reccache.c mf_keycache.c \ + mf_iocache.c mf_cache.c mf_tempfile.c \ my_lock.c mf_brkhant.c my_alarm.c \ my_malloc.c my_realloc.c my_once.c mulalloc.c \ my_alloc.c safemalloc.c my_fopen.c my_fstream.c \ diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c index c40cfa386d3..2c197f6fd20 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,103 @@ /* 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" + + /* + 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 a cached tempfile by IO_CACHE + ** 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/mf_tempfile.c b/mysys/mf_tempfile.c new file mode 100644 index 00000000000..a202dd13d8b --- /dev/null +++ b/mysys/mf_tempfile.c @@ -0,0 +1,173 @@ +/* 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, + MA 02111-1307, USA */ + +#include "mysys_priv.h" +#include <m_string.h> +#include "my_static.h" +#include "mysys_err.h" +#include <errno.h> +#ifdef HAVE_PATH_H +#include <paths.h> +#endif + +#ifdef HAVE_TEMPNAM +#ifndef MSDOS +extern char **environ; +#endif +#endif + +/* + Create a temporary file in a given directory + This function should be used instead of my_tempnam() ! +*/ + +File create_temp_file(char *to, const char *dir, const char *prefix, + int mode, myf MyFlags) +{ + File file= -1; + DBUG_ENTER("open_temp_file"); +#if defined(_MSC_VER) + { + char *end,*res,**old_env,*temp_env[1]; + old_env=environ; + if (dir) + { + end=strend(dir)-1; + if (!dir[0]) + { /* Change empty string to current dir */ + to[0]= FN_CURLIB; + to[1]= 0; + dir=to; + } + else if (*end == FN_DEVCHAR) + { /* Get current dir for drive */ + _fullpath(temp,dir,FN_REFLEN); + dir=to; + } + else if (*end == FN_LIBCHAR && dir < end && end[-1] != FN_DEVCHAR) + { + strmake(to,dir,(uint) (end-dir)); /* Copy and remove last '\' */ + dir=to; + } + environ=temp_env; /* Force use of dir (dir not checked) */ + temp_env[0]=0; + } + if ((res=tempnam((char*) dir,(char *) prefix))) + { + strnmov(to,res,FN_REFLEN); + (*free)(res); + file=my_create(to,0, mode, MyFlags); + } + environ=old_env; + } +#elif defined(_ZTC__) + if (!dir) + dir=getenv("TMPDIR"); + if ((res=tempnam((char*) dir,(char *) prefix))) + { + strnmov(to,res,FN_REFLEN); + (*free)(res); + file=my_create(to, 0, mode, MyFlags); + } +#elif defined(HAVE_MKSTEMP) + { + char prefix[30]; + uint pfx_len; + + pfx_len=(strmov(strnmov(prefix, + prefix ? prefix : "tmp.", + sizeof(prefix)-7),"XXXXXX") - prefix); + if (!dir && ! (dir =getenv("TMPDIR"))) + dir=P_tmpdir; + if (strlen(dir)+ pfx_len > FN_REFLEN-2) + { + errno=my_errno= ENAMETOOLONG; + return 1; + } + strmov(to,dir); + strmov(convert_dirname(to),prefix); + file=mkstemp(to); + } +#elif defined(HAVE_TEMPNAM) + { + char *res,**old_env,*temp_env[1]; + if (dir && !dir[0]) + { /* Change empty string to current dir */ + to[0]= FN_CURLIB; + to[1]= 0; + dir=to; + } + old_env=environ; + if (dir) + { /* Don't use TMPDIR if dir is given */ + environ=temp_env; + temp_env[0]=0; + } + if ((res=tempnam((char*) dir, (char*) prefix))) + { + strnmov(to,res,FN_REFLEN); + (*free)(res); + file=my_create(to,0, + (int) (O_RDWR | O_BINARY | O_TRUNC | + O_TEMPORARY | O_SHORT_LIVED), + MYF(MY_WME)); + + } + else + { + DBUG_PRINT("error",("Got error: %d from tempnam",errno)); + } + environ=old_env; + } +#else + { + register long uniq; + register int length; + my_string pos,end_pos; + /* Make an unique number */ + pthread_mutex_lock(&THR_LOCK_open); + uniq= ((long) getpid() << 20) + (long) _my_tempnam_used++ ; + pthread_mutex_unlock(&THR_LOCK_open); + if (!dir && !(dir=getenv("TMPDIR"))) /* Use this if possibly */ + dir=P_tmpdir; /* Use system default */ + length=strlen(dir)+strlen(pfx)+1; + + DBUG_PRINT("test",("mallocing %d byte",length+8+sizeof(TMP_EXT)+1)); + if (length+8+sizeof(TMP_EXT)+1 > FN_REFLENGTH) + errno=my_errno= ENAMETOOLONG; + else + { + end_pos=strmov(to,dir); + if (end_pos != to && end_pos[-1] != FN_LIBCHAR) + *end_pos++=FN_LIBCHAR; + end_pos=strmov(end_pos,pfx); + + for (length=0 ; length < 8 && uniq ; length++) + { + *end_pos++= _dig_vec[(int) (uniq & 31)]; + uniq >>= 5; + } + (void) strmov(end_pos,TMP_EXT); + file=my_create(to,0, + (int) (O_RDWR | O_BINARY | O_TRUNC | + O_TEMPORARY | O_SHORT_LIVED), + MYF(MY_WME)); + } + } +#endif + DBUG_RETURN(file); +} 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/log.cc b/sql/log.cc index 94cd553bfce..1f12bcacf6c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -149,7 +149,8 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, fn_format(index_file_name, name, mysql_data_home, ".index", 6); db[0]=0; - file=my_fopen(log_file_name,O_APPEND | O_WRONLY,MYF(MY_WME | ME_WAITTANG)); + file=my_fopen(log_file_name,O_APPEND | O_WRONLY | O_BINARY, + MYF(MY_WME | ME_WAITTANG)); if (!file) { my_free(name,MYF(0)); @@ -188,7 +189,7 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, { Start_log_event s; if(!index_file && - !(index_file = my_fopen(index_file_name,O_APPEND | O_RDWR, + !(index_file = my_fopen(index_file_name,O_APPEND | O_BINARY | O_RDWR, MYF(MY_WME)))) { my_fclose(file,MYF(MY_WME)); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index e9eb3f970d4..82674453c40 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -533,7 +533,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 38d8b5ddcab..8daea8aad88 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -284,7 +284,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 @@ -1066,6 +1066,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 @@ -2588,6 +2589,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\ @@ -2879,13 +2882,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; @@ -3052,13 +3055,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: @@ -3594,6 +3598,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 4a05f2370f6..ed018eb3337 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -388,7 +388,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) @@ -700,7 +700,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 */ @@ -1123,6 +1123,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); @@ -1288,6 +1289,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); @@ -1572,6 +1574,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_cache.cc b/sql/sql_cache.cc index 78053d0d3e3..09d436c0c9c 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -19,10 +19,10 @@ #include <my_dir.h> #include <hash.h> -#define SQL_CACHE_LENGTH 300 +#define SQL_CACHE_LENGTH 30 // 300 crashes apple gcc. HASH sql_cache; -LEX lex_array_static[SQL_CACHE_LENGTH]; +static LEX lex_array_static[SQL_CACHE_LENGTH]; LEX * lex_array = lex_array_static; int last_lex_array_item = SQL_CACHE_LENGTH - 1; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 64fd281ee3a..31d54a621ac 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -89,6 +89,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 212a641f335..0543221799f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -264,6 +264,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/sql_show.cc b/sql/sql_show.cc index ea6e09f6cb5..83a53467426 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -476,6 +476,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) DBUG_PRINT("enter",("db: %s table: %s",table_list->db, table_list->real_name)); + /* Only one table for now */ if (!(table = open_ltable(thd, table_list, TL_UNLOCK))) { send_error(&thd->net); @@ -490,34 +491,32 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) DBUG_RETURN(1); String *packet = &thd->packet; - for(;table; table = table->next) - { - packet->length(0); - net_store_data(packet, table->table_name); - // a hack - we need to reserve some space for the length before - // we know what it is - let's assume that the length of create table - // statement will fit into 3 bytes ( 16 MB max :-) ) - ulong store_len_offset = packet->length(); - packet->length(store_len_offset + 4); - if(store_create_info(thd, table, packet)) - DBUG_RETURN(-1); - ulong create_len = packet->length() - store_len_offset - 4; - if(create_len > 0x00ffffff) // better readable in HEX ... - DBUG_RETURN(1); // just in case somebody manages to create a table - // with *that* much stuff in the definition - - // now we have to store the length in three bytes, even if it would fit - // into fewer, so we cannot use net_store_data() anymore, - // and do it ourselves - char* p = (char*)packet->ptr() + store_len_offset; - *p++ = (char) 253; // The client the length is stored using 3-bytes - int3store(p, create_len); - - // now we are in business :-) - if(my_net_write(&thd->net, (char*)packet->ptr(), packet->length())) - DBUG_RETURN(1); - } - + { + packet->length(0); + net_store_data(packet, table->table_name); + // a hack - we need to reserve some space for the length before + // we know what it is - let's assume that the length of create table + // statement will fit into 3 bytes ( 16 MB max :-) ) + ulong store_len_offset = packet->length(); + packet->length(store_len_offset + 4); + if (store_create_info(thd, table, packet)) + DBUG_RETURN(-1); + ulong create_len = packet->length() - store_len_offset - 4; + if (create_len > 0x00ffffff) // better readable in HEX ... + DBUG_RETURN(1); // just in case somebody manages to create a table + // with *that* much stuff in the definition + + // now we have to store the length in three bytes, even if it would fit + // into fewer, so we cannot use net_store_data() anymore, + // and do it ourselves + char* p = (char*)packet->ptr() + store_len_offset; + *p++ = (char) 253; // The client the length is stored using 3-bytes + int3store(p, create_len); + + // now we are in business :-) + if (my_net_write(&thd->net, (char*)packet->ptr(), packet->length())) + DBUG_RETURN(1); + } send_eof(&thd->net); DBUG_RETURN(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(); diff --git a/strings/strtol.c b/strings/strtol.c index ae3fdd0e2b3..87fe0d22cf3 100644 --- a/strings/strtol.c +++ b/strings/strtol.c @@ -18,6 +18,6 @@ /* This defines strtol() if neaded */ #include <global.h> -#if !defined(MSDOS) && !defined(HAVE_STRTOUL) && !defined(__WIN__) +#if !defined(MSDOS) && !defined(HAVE_STRTOL) && !defined(__WIN__) #include "strto.c" #endif |