summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BitKeeper/etc/logging_ok25
-rw-r--r--Docs/manual.texi42
-rw-r--r--client/mysql.cc7
-rw-r--r--include/my_sys.h15
-rw-r--r--include/myisam.h3
-rw-r--r--myisam/mi_check.c1
-rw-r--r--myisam/sort.c183
-rw-r--r--mysys/mf_cache.c97
-rw-r--r--mysys/mf_dirname.c14
-rw-r--r--mysys/my_fopen.c21
-rw-r--r--mysys/my_tempnam.c6
-rw-r--r--readline/bind.c8
-rw-r--r--readline/complete.c4
-rw-r--r--readline/histexpand.c2
-rw-r--r--readline/input.c2
-rw-r--r--readline/search.c2
-rw-r--r--readline/shell.c4
-rw-r--r--readline/terminal.c50
-rw-r--r--readline/tilde.c2
-rw-r--r--readline/undo.c2
-rw-r--r--regex/cname.h194
-rw-r--r--regex/debug.c2
-rw-r--r--regex/main.c2
-rw-r--r--regex/regcomp.c56
-rw-r--r--regex/regerror.c34
-rw-r--r--sql/filesort.cc1
-rw-r--r--sql/ha_myisam.cc69
-rw-r--r--sql/ha_myisam.h20
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/handler.h2
-rw-r--r--sql/key.cc9
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/mysqld.cc76
-rw-r--r--sql/sql_base.cc7
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_insert.cc13
-rw-r--r--sql/table.cc8
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();