Commit 63b7b45f authored by unknown's avatar unknown

First part of automatic repair of MyISAM tables.

Error on full disk on repair.
SIGHUP signal handling.
Update with keys on timestamp
Portability fixes


Docs/manual.texi:
  Added documentation about automatic repair of MyISAM tables
client/mysql.cc:
  Remove usage of tempnam.
include/my_sys.h:
  Added create_temp_file
include/myisam.h:
  Fix for disk full on repair
myisam/mi_check.c:
  Fix for disk full on repair
myisam/sort.c:
  Fix for disk full on repair & removed usage of tempnam()
mysys/mf_cache.c:
  Remove usage of tempnam()
mysys/mf_dirname.c:
  Changed convert_dirname to return end 0
mysys/my_fopen.c:
  Security fixes
mysys/my_tempnam.c:
  remove blanks
readline/bind.c:
  Portability fixes
readline/complete.c:
  Portability fixes
readline/histexpand.c:
  Portability fixes
readline/input.c:
  Portability fixes
readline/search.c:
  Portability fixes
readline/shell.c:
  Portability fixes
readline/terminal.c:
  Portability fixes
readline/tilde.c:
  Portability fixes
readline/undo.c:
  Portability fixes
regex/cname.h:
  Portability fixes
regex/debug.c:
  Portability fixes
regex/main.c:
  Portability fixes
regex/regcomp.c:
  Portability fixes
regex/regerror.c:
  Portability fixes
sql/filesort.cc:
  Remove dummy code
sql/ha_myisam.cc:
  Automatic repair of MyISAM tables
sql/ha_myisam.h:
  Automatic repair of MyISAM tables
sql/handler.cc:
  Automatic repair of MyISAM tables
sql/handler.h:
  Automatic repair of MyISAM tables
sql/key.cc:
  Fix for UPDATE with key on timestamp column
sql/mysql_priv.h:
  Automatic repair of MyISAM tables
sql/mysqld.cc:
  Automatic repair of MyISAM tables & signal SIGHUP handling
sql/sql_base.cc:
  Automatic repair of MyISAM tables
sql/sql_class.cc:
  Automatic repair of MyISAM tables
sql/sql_class.h:
  Fix for insert with reference to columns
sql/sql_insert.cc:
  Fix for insert with reference to columns
sql/table.cc:
  Automatic repair of MyISAM tables
BitKeeper/etc/logging_ok:
  Logging to logging@openlogging.org accepted
parent 27a17a6e
bk@work.mysql.com monty@tramp.mysql.fi
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
...@@ -8984,6 +8984,24 @@ Lock the @code{mysqld} process in memory. This works only if your system ...@@ -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 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. 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 @item --pid-file=path
Path to pid file used by @code{safe_mysqld}. Path to pid file used by @code{safe_mysqld}.
...@@ -21065,6 +21083,9 @@ The following is new in @code{MyISAM}: ...@@ -21065,6 +21083,9 @@ The following is new in @code{MyISAM}:
@itemize @bullet @itemize @bullet
@item @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, You can @code{INSERT} new rows in a table without deleted rows,
while other threads are reading from the table. while other threads are reading from the table.
@item @item
...@@ -21148,6 +21169,18 @@ Note that index files are usually much smaller with @code{MyISAM} than with ...@@ -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 system resources than @code{ISAM}, but will need more CPU when inserting
data into compressed index. 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 @menu
* Key space:: Space needed for keys * Key space:: Space needed for keys
* MyISAM table formats:: MyISAM table formats * MyISAM table formats:: MyISAM table formats
...@@ -37416,7 +37449,14 @@ though, so 3.23 is not released as a stable version yet. ...@@ -37416,7 +37449,14 @@ though, so 3.23 is not released as a stable version yet.
@appendixsubsec Changes in release 3.23.26 @appendixsubsec Changes in release 3.23.26
@itemize @bullet @itemize @bullet
@item @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 @item
Changed to use @code{mkstemp()} instead of @code{tempnam()}. Changed to use @code{mkstemp()} instead of @code{tempnam()}.
@end itemize @end itemize
...@@ -1543,12 +1543,12 @@ com_edit(String *buffer,char *line __attribute__((unused))) ...@@ -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", put_info("Sorry, you can't send the result to an editor in Win32",
INFO_ERROR); INFO_ERROR);
#else #else
char *filename,buff[160]; char filename[FN_REFLEN],buff[160];
int fd,tmp; int fd,tmp;
const char *editor; const char *editor;
filename = my_tempnam(NullS,"sql",MYF(MY_WME)); if ((fd=create_temp_file(filename,NullS,"sql", O_CREAT | O_WRONLY,
if ((fd = my_create(filename,0,O_CREAT | O_WRONLY, MYF(MY_WME))) < 0) MYF(MY_WME))) < 0)
goto err; goto err;
if (buffer->is_empty() && !old_buffer.is_empty()) if (buffer->is_empty() && !old_buffer.is_empty())
(void) my_write(fd,(byte*) old_buffer.ptr(),old_buffer.length(), (void) my_write(fd,(byte*) old_buffer.ptr(),old_buffer.length(),
...@@ -1576,7 +1576,6 @@ com_edit(String *buffer,char *line __attribute__((unused))) ...@@ -1576,7 +1576,6 @@ com_edit(String *buffer,char *line __attribute__((unused)))
(void) my_close(fd,MYF(0)); (void) my_close(fd,MYF(0));
(void) my_delete(filename,MYF(MY_WME)); (void) my_delete(filename,MYF(MY_WME));
err: err:
free(filename);
#endif #endif
return 0; return 0;
} }
......
...@@ -266,20 +266,21 @@ typedef struct st_dynamic_string { ...@@ -266,20 +266,21 @@ typedef struct st_dynamic_string {
typedef struct st_io_cache /* Used when cacheing files */ 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; 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; File file;
int seek_not_done,error; int seek_not_done,error;
uint buffer_length,read_length; uint buffer_length,read_length;
my_off_t pos_in_file,end_of_file;
myf myflags; /* Flags used to my_read/my_write */ myf myflags; /* Flags used to my_read/my_write */
enum cache_type type;
#ifdef HAVE_AIOWAIT #ifdef HAVE_AIOWAIT
uint inited; uint inited;
my_off_t aio_read_pos; my_off_t aio_read_pos;
my_aio_result aio_result; my_aio_result aio_result;
#endif #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; } IO_CACHE;
typedef int (*qsort2_cmp)(const void *, const void *, const void *); typedef int (*qsort2_cmp)(const void *, const void *, const void *);
...@@ -399,7 +400,7 @@ extern void TERMINATE(FILE *file); ...@@ -399,7 +400,7 @@ extern void TERMINATE(FILE *file);
#endif #endif
extern void init_glob_errs(void); extern void init_glob_errs(void);
extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags); 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_fclose(FILE *fd,myf MyFlags);
extern int my_chsize(File fd,my_off_t newlength,myf MyFlags); extern int my_chsize(File fd,my_off_t newlength,myf MyFlags);
extern int my_error _VARARGS((int nr,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); ...@@ -430,7 +431,7 @@ extern uint dirname_part(my_string to,const char *name);
extern uint dirname_length(const char *name); extern uint dirname_length(const char *name);
#define base_name(A) (A+dirname_length(A)) #define base_name(A) (A+dirname_length(A))
extern int test_if_hard_path(const char *dir_name); 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 void to_unix_path(my_string name);
extern my_string fn_ext(const char *name); extern my_string fn_ext(const char *name);
extern my_string fn_same(my_string toname,const char *name,int flag); 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, ...@@ -507,6 +508,8 @@ extern my_bool open_cached_file(IO_CACHE *cache,const char *dir,
myf cache_myflags); myf cache_myflags);
extern my_bool real_open_cached_file(IO_CACHE *cache); extern my_bool real_open_cached_file(IO_CACHE *cache);
extern void close_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, extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array,uint element_size,
uint init_alloc,uint alloc_increment); uint init_alloc,uint alloc_increment);
extern my_bool insert_dynamic(DYNAMIC_ARRAY *array,gptr element); extern my_bool insert_dynamic(DYNAMIC_ARRAY *array,gptr element);
......
...@@ -339,7 +339,6 @@ typedef struct st_mi_check_param ...@@ -339,7 +339,6 @@ typedef struct st_mi_check_param
typedef struct st_mi_sortinfo { typedef struct st_mi_sortinfo {
uint key_length;
ha_rows max_records; ha_rows max_records;
SORT_INFO *sort_info; SORT_INFO *sort_info;
char *tmpdir; char *tmpdir;
...@@ -347,6 +346,8 @@ typedef struct st_mi_sortinfo { ...@@ -347,6 +346,8 @@ typedef struct st_mi_sortinfo {
int (*key_read)(SORT_INFO *info,void *buff); int (*key_read)(SORT_INFO *info,void *buff);
int (*key_write)(SORT_INFO *info, const void *buff); int (*key_write)(SORT_INFO *info, const void *buff);
void (*lock_in_memory)(MI_CHECK *info); void (*lock_in_memory)(MI_CHECK *info);
uint key_length;
myf myf_rw;
} MI_SORT_PARAM; } MI_SORT_PARAM;
/* functions in mi_check */ /* functions in mi_check */
......
...@@ -1759,6 +1759,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -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.key_read=sort_key_read;
sort_param.lock_in_memory=lock_memory; sort_param.lock_in_memory=lock_memory;
sort_param.tmpdir=param->tmpdir; sort_param.tmpdir=param->tmpdir;
sort_param.myf_rw=param->myf_rw;
sort_param.sort_info=sort_info; sort_param.sort_info=sort_info;
del=info->state->del; del=info->state->del;
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#define MERGEBUFF2 31 #define MERGEBUFF2 31
#define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD) #define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD)
#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) #define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
#define DISK_BUFFER_SIZE (IO_SIZE*16)
typedef struct st_buffpek { typedef struct st_buffpek {
my_off_t file_pos; /* position to buffer */ my_off_t file_pos; /* position to buffer */
...@@ -47,30 +48,26 @@ extern void print_error _VARARGS((const char *fmt,...)); ...@@ -47,30 +48,26 @@ extern void print_error _VARARGS((const char *fmt,...));
/* functions defined in this file */ /* functions defined in this file */
static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info,uint keys, static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info,uint keys,
uchar * *sort_keys, uchar **sort_keys,
BUFFPEK *buffpek,int *maxbuffer, 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, static int NEAR_F write_keys(MI_SORT_PARAM *info,uchar * *sort_keys,
uint count, BUFFPEK *buffpek,FILE **tempfile, uint count, BUFFPEK *buffpek,IO_CACHE *tempfile);
my_string tempname);
static int NEAR_F write_index(MI_SORT_PARAM *info,uchar * *sort_keys, static int NEAR_F write_index(MI_SORT_PARAM *info,uchar * *sort_keys,
uint count); uint count);
static int NEAR_F merge_many_buff(MI_SORT_PARAM *info,uint keys, static int NEAR_F merge_many_buff(MI_SORT_PARAM *info,uint keys,
uchar * *sort_keys, uchar * *sort_keys,
BUFFPEK *buffpek,int *maxbuffer, BUFFPEK *buffpek,int *maxbuffer,
FILE * *t_file, my_string tempname); IO_CACHE *t_file);
static uint NEAR_F read_to_buffer(FILE *fromfile,BUFFPEK *buffpek, static uint NEAR_F read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
uint sort_length); uint sort_length);
static int NEAR_F merge_buffers(MI_SORT_PARAM *info,uint keys,FILE *from_file, static int NEAR_F merge_buffers(MI_SORT_PARAM *info,uint keys,
FILE *to_file, uchar * *sort_keys, IO_CACHE *from_file, IO_CACHE *to_file,
BUFFPEK *lastbuff,BUFFPEK *Fb, uchar * *sort_keys, BUFFPEK *lastbuff,
BUFFPEK *Tb); BUFFPEK *Fb, BUFFPEK *Tb);
static int NEAR_F merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int, 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 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 */ /* Creates a index of sorted keys */
/* Returns 0 if everything went ok */ /* Returns 0 if everything went ok */
...@@ -81,14 +78,14 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ...@@ -81,14 +78,14 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
int error,maxbuffer,skr; int error,maxbuffer,skr;
uint memavl,old_memavl,keys,sort_length; uint memavl,old_memavl,keys,sort_length;
BUFFPEK *buffpek; BUFFPEK *buffpek;
char tempname[FN_REFLEN];
ha_rows records; ha_rows records;
uchar **sort_keys; uchar **sort_keys;
FILE *tempfile; IO_CACHE tempfile;
DBUG_ENTER("_create_index_by_sort"); DBUG_ENTER("_create_index_by_sort");
DBUG_PRINT("enter",("sort_length: %d", info->key_length)); 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; maxbuffer=1;
memavl=max(sortbuff_size,MIN_SORT_MEMORY); memavl=max(sortbuff_size,MIN_SORT_MEMORY);
...@@ -139,8 +136,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ...@@ -139,8 +136,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
if (!no_messages) if (!no_messages)
printf(" - Searching for keys, allocating buffer for %d keys\n",keys); printf(" - Searching for keys, allocating buffer for %d keys\n",keys);
if ((records=find_all_keys(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile, if ((records=find_all_keys(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile))
tempname))
== HA_POS_ERROR) == HA_POS_ERROR)
goto err; goto err;
if (maxbuffer == 0) if (maxbuffer == 0)
...@@ -157,13 +153,15 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ...@@ -157,13 +153,15 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
{ {
if (!no_messages) if (!no_messages)
printf(" - Merging %lu keys\n",records); printf(" - Merging %lu keys\n",records);
if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile, if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile))
tempname)) goto err;
if (flush_io_cache(&tempfile) ||
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
goto err; goto err;
} }
if (!no_messages) if (!no_messages)
puts(" - Last merge and dumping keys"); puts(" - Last merge and dumping keys");
if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,tempfile)) if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,&tempfile))
goto err; goto err;
} }
error =0; error =0;
...@@ -173,8 +171,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ...@@ -173,8 +171,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
my_free((gptr) sort_keys,MYF(0)); my_free((gptr) sort_keys,MYF(0));
if (buffpek) if (buffpek)
my_free((gptr) buffpek,MYF(0)); my_free((gptr) buffpek,MYF(0));
if (tempfile) close_cached_file(&tempfile);
closetemp(tempname,tempfile);
DBUG_RETURN(error ? -1 : 0); DBUG_RETURN(error ? -1 : 0);
} /* _create_index_by_sort */ } /* _create_index_by_sort */
...@@ -184,8 +181,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ...@@ -184,8 +181,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys,
uchar **sort_keys, BUFFPEK *buffpek, uchar **sort_keys, BUFFPEK *buffpek,
int *maxbuffer, FILE **tempfile, int *maxbuffer, IO_CACHE *tempfile)
my_string tempname)
{ {
int error; int error;
uint idx,indexpos; uint idx,indexpos;
...@@ -198,8 +194,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, ...@@ -198,8 +194,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys,
if ((uint) ++idx == keys) if ((uint) ++idx == keys)
{ {
if (indexpos >= (uint) *maxbuffer || if (indexpos >= (uint) *maxbuffer ||
write_keys(info,sort_keys,idx-1,buffpek+indexpos,tempfile, write_keys(info,sort_keys,idx-1,buffpek+indexpos,tempfile))
tempname))
DBUG_RETURN((ha_rows) -1); DBUG_RETURN((ha_rows) -1);
memcpy(sort_keys[0],sort_keys[idx-1],(size_t) info->key_length); memcpy(sort_keys[0],sort_keys[idx-1],(size_t) info->key_length);
idx=1; indexpos++; idx=1; indexpos++;
...@@ -209,7 +204,7 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, ...@@ -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 */ DBUG_RETURN(HA_POS_ERROR); /* Aborted by get_key */
if (indexpos) if (indexpos)
if (indexpos >= (uint) *maxbuffer || 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); DBUG_RETURN(HA_POS_ERROR);
*maxbuffer=(int) indexpos; *maxbuffer=(int) indexpos;
DBUG_RETURN(indexpos*(keys-1)+idx); DBUG_RETURN(indexpos*(keys-1)+idx);
...@@ -220,18 +215,23 @@ static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys, ...@@ -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, static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys,
uint count, BUFFPEK *buffpek, 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"); DBUG_ENTER("write_keys");
qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp, qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp,
info->sort_info); 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); DBUG_RETURN(1);
buffpek->file_pos=my_ftell(*tempfile,MYF(0)); buffpek->file_pos=my_b_tell(tempfile);
buffpek->count=count; 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(1);
DBUG_RETURN(0); DBUG_RETURN(0);
} /* write_keys */ } /* write_keys */
...@@ -239,7 +239,8 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys, ...@@ -239,7 +239,8 @@ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys,
/* Write index */ /* 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"); DBUG_ENTER("write_index");
...@@ -256,22 +257,25 @@ static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys, r ...@@ -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, static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys,
uchar **sort_keys, BUFFPEK *buffpek, uchar **sort_keys, BUFFPEK *buffpek,
int *maxbuffer, FILE **t_file, int *maxbuffer, IO_CACHE *t_file)
my_string t_name)
{ {
register int i; register int i;
FILE *from_file,*to_file,*temp; IO_CACHE t_file2, *from_file, *to_file, *temp;
FILE *t_file2;
char t_name2[FN_REFLEN];
BUFFPEK *lastbuff; BUFFPEK *lastbuff;
DBUG_ENTER("merge_many_buff"); DBUG_ENTER("merge_many_buff");
if (!(t_file2=opentemp(t_name2,info->tmpdir))) if (*maxbuffer < MERGEBUFF2)
DBUG_RETURN(1); 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) 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; lastbuff=buffpek;
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF) 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, ...@@ -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++, if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
buffpek+i,buffpek+ *maxbuffer)) buffpek+i,buffpek+ *maxbuffer))
break; 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; temp=from_file; from_file=to_file; to_file=temp;
VOID(my_fseek(to_file,0L,MY_SEEK_SET,MYF(0))); *maxbuffer= (int) (lastbuff-buffpek)-1;
}
if (to_file == *t_file)
{
closetemp(t_name,to_file);
*t_file=t_file2;
VOID(strmov(t_name,t_name2));
} }
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 */ DBUG_RETURN(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
} /* merge_many_buff */ } /* merge_many_buff */
...@@ -301,20 +302,17 @@ static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys, ...@@ -301,20 +302,17 @@ static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys,
/* Read data to buffer */ /* Read data to buffer */
/* This returns (uint) -1 if something goes wrong */ /* 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; register uint count;
uint length; uint length;
count=buffpek->max_keys; if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
if ((ha_rows) count > buffpek->count)
count=(uint) buffpek->count;
if (count)
{ {
VOID(my_fseek(fromfile,buffpek->file_pos,MY_SEEK_SET,MYF(0))); if (my_pread(fromfile->file,(byte*) buffpek->base,
if (my_fread(fromfile,(byte*) buffpek->base, (length= sort_length*count),buffpek->file_pos,MYF_RW))
(length= sort_length*count),MYF_RW)) return((uint) -1); /* purecov: inspected */
return((uint) -1);
buffpek->key=buffpek->base; buffpek->key=buffpek->base;
buffpek->file_pos+= length; /* New filepos */ buffpek->file_pos+= length; /* New filepos */
buffpek->count-= count; buffpek->count-= count;
...@@ -328,8 +326,9 @@ static uint NEAR_F read_to_buffer(FILE *fromfile, BUFFPEK *buffpek, uint sort_le ...@@ -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 */ /* If to_file == 0 then use info->key_write */
static int NEAR_F static int NEAR_F
merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
uchar **sort_keys, BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb) IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff,
BUFFPEK *Fb, BUFFPEK *Tb)
{ {
int error; int error;
uint sort_length,maxcount; uint sort_length,maxcount;
...@@ -342,12 +341,11 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, ...@@ -342,12 +341,11 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file,
count=error=0; count=error=0;
maxcount=keys/((uint) (Tb-Fb) +1); maxcount=keys/((uint) (Tb-Fb) +1);
sort_length=info->key_length;
LINT_INIT(to_start_filepos); LINT_INIT(to_start_filepos);
if (to_file) if (to_file)
to_start_filepos=my_ftell(to_file,MYF(0)); to_start_filepos=my_b_tell(to_file);
strpos=(uchar*) sort_keys; strpos=(uchar*) sort_keys;
sort_length=info->key_length;
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
(int (*)(void*, byte *,byte*)) info->key_cmp, (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, ...@@ -373,8 +371,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file,
buffpek=(BUFFPEK*) queue_top(&queue); buffpek=(BUFFPEK*) queue_top(&queue);
if (to_file) if (to_file)
{ {
if (my_fwrite(to_file,(byte*) buffpek->key,(uint) sort_length, if (my_b_write(to_file,(byte*) buffpek->key,(uint) sort_length))
MYF_RW | MY_WAIT_IF_FULL))
{ {
error=1; goto err; error=1; goto err;
} }
...@@ -417,6 +414,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, ...@@ -417,6 +414,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file,
break; /* One buffer have been removed */ break; /* One buffer have been removed */
} }
} }
else if (error == -1)
goto err; /* purecov: inspected */
queue_replaced(&queue); /* Top element has been replaced */ 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, ...@@ -427,9 +426,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file,
{ {
if (to_file) if (to_file)
{ {
if (my_fwrite(to_file,(byte*) buffpek->key, if (my_b_write(to_file,(byte*) buffpek->key,
(uint) (sort_length*buffpek->mem_count), (sort_length*buffpek->mem_count)))
MYF_RW | MY_WAIT_IF_FULL))
{ {
error=1; goto err; error=1; goto err;
} }
...@@ -454,7 +452,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, ...@@ -454,7 +452,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file,
lastbuff->count=count; lastbuff->count=count;
if (to_file) if (to_file)
lastbuff->file_pos=to_start_filepos; /* New block starts here */ lastbuff->file_pos=to_start_filepos;
err: err:
delete_queue(&queue); delete_queue(&queue);
DBUG_RETURN(error); DBUG_RETURN(error);
...@@ -465,10 +463,10 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file, ...@@ -465,10 +463,10 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, FILE *from_file, FILE *to_file,
static int NEAR_F static int NEAR_F
merge_index(MI_SORT_PARAM *info, uint keys, uchar **sort_keys, 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"); 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)) buffpek+maxbuffer))
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -492,40 +490,3 @@ static char **make_char_array(register uint fields, uint length, myf my_flag) ...@@ -492,40 +490,3 @@ static char **make_char_array(register uint fields, uint length, myf my_flag)
DBUG_RETURN(old_pos); DBUG_RETURN(old_pos);
} /* make_char_array */ } /* 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 */
...@@ -18,66 +18,115 @@ ...@@ -18,66 +18,115 @@
/* Open a temporary file and cache it with io_cache. Delete it on close */ /* Open a temporary file and cache it with io_cache. Delete it on close */
#include "mysys_priv.h" #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
/*
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) ** Should be used when no seeks are done (only reinit_io_buff)
** Return 0 if cache is inited ok ** Return 0 if cache is inited ok
** The actual file is created when the IO_CACHE buffer gets filled ** 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, my_bool open_cached_file(IO_CACHE *cache, const char* dir, const char *prefix,
uint cache_size, myf cache_myflags) uint cache_size, myf cache_myflags)
{ {
DBUG_ENTER("open_cached_file"); 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 */ 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, if (!init_io_cache(cache,-1,cache_size,WRITE_CACHE,0L,0,
MYF(cache_myflags | MY_NABP))) MYF(cache_myflags | MY_NABP)))
{ {
DBUG_RETURN(0); DBUG_RETURN(0);
} }
(*free)(cache->file_name); /* my_tempnam uses malloc() */ my_free(cache->dir, MYF(MY_ALLOW_ZERO_PTR));
cache->file_name=0; my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/* Create the temporary file */
my_bool real_open_cached_file(IO_CACHE *cache) my_bool real_open_cached_file(IO_CACHE *cache)
{ {
char name_buff[FN_REFLEN];
int error=1;
DBUG_ENTER("real_open_cached_file"); DBUG_ENTER("real_open_cached_file");
if ((cache->file=my_create(cache->file_name,0, if ((cache->file=create_temp_file(name_buff, cache->dir, cache->prefix,
(int) (O_RDWR | O_BINARY | O_TRUNC | O_TEMPORARY | (O_RDWR | O_BINARY | O_TRUNC |
O_SHORT_LIVED), O_TEMPORARY | O_SHORT_LIVED),
MYF(MY_WME))) >= 0) MYF(MY_WME))) >= 0)
{ {
#if O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES) error=0;
VOID(my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT))); cache_remove_open_tmp(cache, name_buff);
#endif
DBUG_RETURN(0);
} }
DBUG_RETURN(1); DBUG_RETURN(error);
} }
void close_cached_file(IO_CACHE *cache) void close_cached_file(IO_CACHE *cache)
{ {
DBUG_ENTER("close_cached_file"); DBUG_ENTER("close_cached_file");
if (my_b_inited(cache)) if (my_b_inited(cache))
{ {
VOID(end_io_cache(cache)); (void) end_io_cache(cache);
if (cache->file >= 0) if (cache->file >= 0)
{ {
VOID(my_close(cache->file,MYF(MY_WME))); (void) my_close(cache->file,MYF(0));
#ifdef CANT_DELETE_OPEN_FILES #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 #endif
} }
if (cache->file_name) my_free(cache->dir,MYF(MY_ALLOW_ZERO_PTR));
(*free)(cache->file_name); /* my_tempnam uses malloc() */ my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR));
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -66,8 +66,9 @@ uint dirname_part(my_string to, const char *name) ...@@ -66,8 +66,9 @@ uint dirname_part(my_string to, const char *name)
#define FN_DEVCHAR '\0' /* For easier code */ #define FN_DEVCHAR '\0' /* For easier code */
#endif #endif
void convert_dirname(my_string to) char *convert_dirname(my_string to)
{ {
reg1 char *pos;
#ifdef FN_UPPER_CASE #ifdef FN_UPPER_CASE
caseup_str(to); caseup_str(to);
#endif #endif
...@@ -76,7 +77,6 @@ void convert_dirname(my_string to) ...@@ -76,7 +77,6 @@ void convert_dirname(my_string to)
#endif #endif
#if FN_LIBCHAR != '/' #if FN_LIBCHAR != '/'
{ {
reg1 my_string pos;
pos=to-1; /* Change from '/' */ pos=to-1; /* Change from '/' */
while ((pos=strchr(pos+1,'/')) != 0) while ((pos=strchr(pos+1,'/')) != 0)
*pos=FN_LIBCHAR; *pos=FN_LIBCHAR;
...@@ -84,7 +84,6 @@ void convert_dirname(my_string to) ...@@ -84,7 +84,6 @@ void convert_dirname(my_string to)
#endif #endif
#ifdef FN_C_BEFORE_DIR_2 #ifdef FN_C_BEFORE_DIR_2
{ {
reg1 my_string pos;
for (pos=to ; *pos ; pos++) for (pos=to ; *pos ; pos++)
{ {
if (*pos == FN_C_BEFORE_DIR_2) if (*pos == FN_C_BEFORE_DIR_2)
...@@ -95,12 +94,13 @@ void convert_dirname(my_string to) ...@@ -95,12 +94,13 @@ void convert_dirname(my_string to)
} }
#else #else
{ /* Append FN_LIBCHAR if not there */ { /* Append FN_LIBCHAR if not there */
char *end=strend(to); pos=strend(to);
if (end != to && (end[-1] != FN_LIBCHAR && end[-1] != FN_DEVCHAR)) if (pos != to && (pos[-1] != FN_LIBCHAR && pos[-1] != FN_DEVCHAR))
{ {
end[0]=FN_LIBCHAR; *pos++=FN_LIBCHAR;
end[1]=0; *pos=0;
} }
} }
#endif #endif
return pos; /* Pointer to end of dir */
} /* convert_dirname */ } /* convert_dirname */
...@@ -95,7 +95,7 @@ int my_fclose(FILE *fd, myf MyFlags) ...@@ -95,7 +95,7 @@ int my_fclose(FILE *fd, myf MyFlags)
if ((uint) file < MY_NFILE && my_file_info[file].type != UNOPEN) if ((uint) file < MY_NFILE && my_file_info[file].type != UNOPEN)
{ {
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); pthread_mutex_unlock(&THR_LOCK_open);
DBUG_RETURN(err); DBUG_RETURN(err);
...@@ -103,11 +103,9 @@ int my_fclose(FILE *fd, myf MyFlags) ...@@ -103,11 +103,9 @@ int my_fclose(FILE *fd, myf MyFlags)
/* Make a stream out of a file handle */ /* Make a stream out of a file handle */
/* Name may be 0 */
FILE *my_fdopen(File Filedes, int Flags, myf MyFlags) FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags)
/* Read | write .. */
/* Special flags */
{ {
FILE *fd; FILE *fd;
char type[5]; char type[5];
...@@ -125,11 +123,18 @@ FILE *my_fdopen(File Filedes, int Flags, myf MyFlags) ...@@ -125,11 +123,18 @@ FILE *my_fdopen(File Filedes, int Flags, myf MyFlags)
else else
{ {
pthread_mutex_lock(&THR_LOCK_open); pthread_mutex_lock(&THR_LOCK_open);
my_stream_opened++;
if (Filedes < MY_NFILE)
{
if (my_file_info[Filedes].type != UNOPEN) if (my_file_info[Filedes].type != UNOPEN)
{ {
my_file_info[Filedes].type = STREAM_BY_FDOPEN;
my_file_opened--; /* File is opened with my_open ! */ my_file_opened--; /* File is opened with my_open ! */
my_stream_opened++; }
else
{
my_file_info[Filedes].name= my_strdup(name,MyFlags);
}
my_file_info[Filedes].type = STREAM_BY_FDOPEN;
} }
pthread_mutex_unlock(&THR_LOCK_open); pthread_mutex_unlock(&THR_LOCK_open);
} }
......
...@@ -351,7 +351,7 @@ rl_translate_keyseq (seq, array, len) ...@@ -351,7 +351,7 @@ rl_translate_keyseq (seq, array, len)
{ {
register int i, c, l, temp; register int i, c, l, temp;
for (i = l = 0; c = seq[i]; i++) for (i = l = 0; (c = seq[i]); i++)
{ {
if (c == '\\') if (c == '\\')
{ {
...@@ -1028,7 +1028,7 @@ rl_parse_and_bind (string) ...@@ -1028,7 +1028,7 @@ rl_parse_and_bind (string)
{ {
int passc = 0; int passc = 0;
for (i = 1; c = string[i]; i++) for (i = 1; (c = string[i]); i++)
{ {
if (passc) if (passc)
{ {
...@@ -1104,7 +1104,7 @@ rl_parse_and_bind (string) ...@@ -1104,7 +1104,7 @@ rl_parse_and_bind (string)
{ {
int delimiter = string[i++], passc; int delimiter = string[i++], passc;
for (passc = 0; c = string[i]; i++) for (passc = 0; (c = string[i]); i++)
{ {
if (passc) if (passc)
{ {
...@@ -1721,7 +1721,7 @@ rl_function_dumper (print_readably) ...@@ -1721,7 +1721,7 @@ rl_function_dumper (print_readably)
fprintf (rl_outstream, "\n"); fprintf (rl_outstream, "\n");
for (i = 0; name = names[i]; i++) for (i = 0; (name = names[i]); i++)
{ {
Function *function; Function *function;
char **invokers; char **invokers;
......
...@@ -1377,7 +1377,7 @@ completion_matches (text, entry_function) ...@@ -1377,7 +1377,7 @@ completion_matches (text, entry_function)
match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
match_list[1] = (char *)NULL; match_list[1] = (char *)NULL;
while (string = (*entry_function) (text, matches)) while ((string = (*entry_function) (text, matches)))
{ {
if (matches + 1 == match_list_size) if (matches + 1 == match_list_size)
match_list = (char **)xrealloc match_list = (char **)xrealloc
...@@ -1427,7 +1427,7 @@ username_completion_function (text, state) ...@@ -1427,7 +1427,7 @@ username_completion_function (text, state)
setpwent (); setpwent ();
} }
while (entry = getpwent ()) while ((entry = getpwent ()))
{ {
/* Null usernames should result in all users as possible completions. */ /* Null usernames should result in all users as possible completions. */
if (namelen == 0 || (STREQN (username, entry->pw_name, namelen))) if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
......
...@@ -200,7 +200,7 @@ get_history_event (string, caller_index, delimiting_quote) ...@@ -200,7 +200,7 @@ get_history_event (string, caller_index, delimiting_quote)
} }
/* Only a closing `?' or a newline delimit a substring search string. */ /* 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 == ':' || if ((!substring_okay && (whitespace (c) || c == ':' ||
(history_search_delimiter_chars && member (c, history_search_delimiter_chars)) || (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
string[i] == delimiting_quote)) || string[i] == delimiting_quote)) ||
......
...@@ -368,7 +368,7 @@ rl_read_key () ...@@ -368,7 +368,7 @@ rl_read_key ()
else else
{ {
/* If input is coming from a macro, then use that. */ /* If input is coming from a macro, then use that. */
if (c = _rl_next_macro_key ()) if ((c = _rl_next_macro_key ()))
return (c); return (c);
/* If the user has an event function, then call it periodically. */ /* If the user has an event function, then call it periodically. */
......
...@@ -174,7 +174,7 @@ noninc_search (dir, pchar) ...@@ -174,7 +174,7 @@ noninc_search (dir, pchar)
#define SEARCH_RETURN rl_restore_prompt (); return #define SEARCH_RETURN rl_restore_prompt (); return
/* Read the search string. */ /* Read the search string. */
while (c = rl_read_key ()) while ((c = rl_read_key ()))
{ {
switch (c) switch (c)
{ {
......
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
# include "ansi_stdlib.h" # include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */ #endif /* HAVE_STDLIB_H */
#if defined (HAVE_STDIO_H)
# include <stdio.h>
#endif /* HAVE_STDIO_H */
#if defined (HAVE_STRING_H) #if defined (HAVE_STRING_H)
# include <string.h> # include <string.h>
#else #else
......
...@@ -232,6 +232,8 @@ _rl_set_screen_size (rows, cols) ...@@ -232,6 +232,8 @@ _rl_set_screen_size (rows, cols)
screenchars = screenwidth * screenheight; screenchars = screenwidth * screenheight;
} }
extern void _rl_redisplay_after_sigwinch();
void void
rl_resize_terminal () rl_resize_terminal ()
{ {
...@@ -251,32 +253,32 @@ struct _tc_string { ...@@ -251,32 +253,32 @@ struct _tc_string {
search algorithm to something smarter. */ search algorithm to something smarter. */
static struct _tc_string tc_strings[] = static struct _tc_string tc_strings[] =
{ {
"DC", &term_DC, {"DC", &term_DC},
"IC", &term_IC, {"IC", &term_IC},
"ce", &term_clreol, {"ce", &term_clreol},
"cl", &term_clrpag, {"cl", &term_clrpag},
"cr", &term_cr, {"cr", &term_cr},
"dc", &term_dc, {"dc", &term_dc},
"ei", &term_ei, {"ei", &term_ei},
"ic", &term_ic, {"ic", &term_ic},
"im", &term_im, {"im", &term_im},
"kd", &term_kd, {"kd", &term_kd},
"kh", &term_kh, /* home */ {"kh", &term_kh}, /* home */
"kH", &term_kH, /* end */ {"kH", &term_kH}, /* end */
"kl", &term_kl, {"kl", &term_kl},
"kr", &term_kr, {"kr", &term_kr},
"ku", &term_ku, {"ku", &term_ku},
"ks", &term_ks, {"ks", &term_ks},
"ke", &term_ke, {"ke", &term_ke},
"le", &term_backspace, {"le", &term_backspace},
"mm", &term_mm, {"mm", &term_mm},
"mo", &term_mo, {"mo", &term_mo},
#if defined (HACK_TERMCAP_MOTION) #if defined (HACK_TERMCAP_MOTION)
"nd", &term_forward_char, {"nd", &term_forward_char},
#endif #endif
"pc", &term_pc, {"pc", &term_pc},
"up", &term_up, {"up", &term_up},
"vb", &visible_bell, {"vb", &visible_bell},
}; };
#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string)) #define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
......
...@@ -182,7 +182,7 @@ tilde_expand (string) ...@@ -182,7 +182,7 @@ tilde_expand (string)
int result_size, result_index; int result_size, result_index;
result_index = result_size = 0; result_index = result_size = 0;
if (result = strchr (string, '~')) if ((result = strchr (string, '~')))
result = xmalloc (result_size = (strlen (string) + 16)); result = xmalloc (result_size = (strlen (string) + 16));
else else
result = xmalloc (result_size = (strlen (string) + 1)); result = xmalloc (result_size = (strlen (string) + 1));
......
...@@ -106,7 +106,7 @@ rl_do_undo () ...@@ -106,7 +106,7 @@ rl_do_undo ()
{ {
UNDO_LIST *release; UNDO_LIST *release;
int waiting_for_begin = 0; 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))) #define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
......
...@@ -3,100 +3,102 @@ static struct cname { ...@@ -3,100 +3,102 @@ static struct cname {
char *name; char *name;
char code; char code;
} cnames[] = { } cnames[] = {
"NUL", '\0', {"NUL", '\0'},
"SOH", '\001', {"SOH", '\001'},
"STX", '\002', {"STX", '\002'},
"ETX", '\003', {"ETX", '\003'},
"EOT", '\004', {"EOT", '\004'},
"ENQ", '\005', {"ENQ", '\005'},
"ACK", '\006', {"ACK", '\006'},
"BEL", '\007', {"BEL", '\007'},
"alert", '\007', {"alert", '\007'},
"BS", '\010', {"BS", '\010'},
"backspace", '\b', {"backspace", '\b'},
"HT", '\011', {"HT", '\011'},
"tab", '\t', {"tab", '\t'},
"LF", '\012', {"LF", '\012'},
"newline", '\n', {"newline", '\n'},
"VT", '\013', {"VT", '\013'},
"vertical-tab", '\v', {"vertical-tab",'\v'},
"FF", '\014', {"FF", '\014'},
"form-feed", '\f', {"form-feed", '\f'},
"CR", '\015', {"CR", '\015'},
"carriage-return", '\r', {"carriage-return", '\r'},
"SO", '\016', {"SO", '\016'},
"SI", '\017', {"SI", '\017'},
"DLE", '\020', {"DLE", '\020'},
"DC1", '\021', {"DC1", '\021'},
"DC2", '\022', {"DC2", '\022'},
"DC3", '\023', {"DC3", '\023'},
"DC4", '\024', {"DC4", '\024'},
"NAK", '\025', {"NAK", '\025'},
"SYN", '\026', {"SYN", '\026'},
"ETB", '\027', {"ETB", '\027'},
"CAN", '\030', {"CAN", '\030'},
"EM", '\031', {"EM", '\031'},
"SUB", '\032', {"SUB", '\032'},
"ESC", '\033', {"ESC", '\033'},
"IS4", '\034', {"IS4", '\034'},
"FS", '\034', {"FS", '\034'},
"IS3", '\035', {"IS3", '\035'},
"GS", '\035', {"GS", '\035'},
"IS2", '\036', {"IS2", '\036'},
"RS", '\036', {"RS", '\036'},
"IS1", '\037', {"IS1", '\037'},
"US", '\037', {"US", '\037'},
"space", ' ', {"space", ' '},
"exclamation-mark", '!', {"exclamation-mark", '!'},
"quotation-mark", '"', {"quotation-mark", '"'},
"number-sign", '#', {"number-sign", '#'},
"dollar-sign", '$', {"dollar-sign", '$'},
"percent-sign", '%', {"percent-sign", '%'},
"ampersand", '&', {"ampersand", '&'},
"apostrophe", '\'', {"apostrophe", '\''},
"left-parenthesis", '(', {"left-parenthesis", '('},
"right-parenthesis", ')', {"right-parenthesis", ')'},
"asterisk", '*', {"asterisk", '*'},
"plus-sign", '+', {"plus-sign", '+'},
"comma", ',', {"comma", ','},
"hyphen", '-', {"hyphen", '-'},
"hyphen-minus", '-', {"hyphen-minus", '-'},
"period", '.', {"period", '.'},
"full-stop", '.', {"full-stop", '.'},
"slash", '/', {"slash", '/'},
"solidus", '/', {"solidus", '/'},
"zero", '0', {"zero", '0'},
"one", '1', {"one", '1'},
"two", '2', {"two", '2'},
"three", '3', {"three", '3'},
"four", '4', {"four", '4'},
"five", '5', {"five", '5'},
"six", '6', {"six", '6'},
"seven", '7', {"seven", '7'},
"eight", '8', {"eight", '8'},
"nine", '9', {"nine", '9'},
"colon", ':', {"colon", ':'},
"semicolon", ';', {"semicolon", ';'},
"less-than-sign", '<', {"less-than-sign", '<'},
"equals-sign", '=', {"equals-sign", '='},
"greater-than-sign", '>', {"greater-than-sign", '>'},
"question-mark", '?', {"question-mark", '?'},
"commercial-at", '@', {"commercial-at", '@'},
"left-square-bracket", '[', {"left-square-bracket", '['},
"backslash", '\\', {"backslash", '\\'},
"reverse-solidus", '\\', {"reverse-solidus", '\\'},
"right-square-bracket", ']', {"right-square-bracket",']'},
"circumflex", '^', {"circumflex", '^'},
"circumflex-accent", '^', {"circumflex-accent", '^'},
"underscore", '_', {"underscore", '_'},
"low-line", '_', {"low-line", '_'},
"grave-accent", '`', {"grave-accent", '`'},
"left-brace", '{', {"left-brace", '{'},
"left-curly-bracket", '{', {"left-curly-bracket", '{'},
"vertical-line", '|', {"vertical-line", '|'},
"right-brace", '}', {"right-brace", '}'},
"right-curly-bracket", '}', {"right-curly-bracket", '}'},
"tilde", '~', {"tilde", '~'},
"DEL", '\177', {"DEL", '\177'},
NULL, 0, {NULL, 0},
}; };
...@@ -217,7 +217,7 @@ FILE *d; ...@@ -217,7 +217,7 @@ FILE *d;
fprintf(d, ">"); fprintf(d, ">");
break; break;
default: default:
fprintf(d, "!%d(%d)!", OP(*s), opnd); fprintf(d, "!%ld(%ld)!", OP(*s), opnd);
break; break;
} }
if (!done) if (!done)
......
...@@ -103,7 +103,7 @@ char *argv[]; ...@@ -103,7 +103,7 @@ char *argv[];
len = (int)(subs[0].rm_eo - subs[0].rm_so); len = (int)(subs[0].rm_eo - subs[0].rm_so);
if (subs[0].rm_so != -1) { if (subs[0].rm_so != -1) {
if (len != 0) if (len != 0)
printf("match `%.*s'\n", len, printf("match `%.*s'\n", (int)len,
argv[optind] + subs[0].rm_so); argv[optind] + subs[0].rm_so);
else else
printf("match `'@%.1s\n", printf("match `'@%.1s\n",
......
...@@ -219,7 +219,7 @@ int stop; /* character this ERE should end at */ ...@@ -219,7 +219,7 @@ int stop; /* character this ERE should end at */
conc = HERE(); conc = HERE();
while (MORE() && (c = PEEK()) != '|' && c != stop) while (MORE() && (c = PEEK()) != '|' && c != stop)
p_ere_exp(p); p_ere_exp(p);
REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ if(REQUIRE(HERE() != conc, REG_EMPTY)); /* require nonempty */
if (!EAT('|')) if (!EAT('|'))
break; /* NOTE BREAK OUT */ break; /* NOTE BREAK OUT */
...@@ -266,7 +266,7 @@ register struct parse *p; ...@@ -266,7 +266,7 @@ register struct parse *p;
pos = HERE(); pos = HERE();
switch (c) { switch (c) {
case '(': case '(':
REQUIRE(MORE(), REG_EPAREN); if(REQUIRE(MORE(), REG_EPAREN));
p->g->nsub++; p->g->nsub++;
subno = (sopno) p->g->nsub; subno = (sopno) p->g->nsub;
if (subno < NPAREN) if (subno < NPAREN)
...@@ -279,7 +279,7 @@ register struct parse *p; ...@@ -279,7 +279,7 @@ register struct parse *p;
assert(p->pend[subno] != 0); assert(p->pend[subno] != 0);
} }
EMIT(ORPAREN, subno); EMIT(ORPAREN, subno);
MUSTEAT(')', REG_EPAREN); if(MUSTEAT(')', REG_EPAREN));
break; break;
#ifndef POSIX_MISTAKE #ifndef POSIX_MISTAKE
case ')': /* happens only if no current unmatched ( */ case ')': /* happens only if no current unmatched ( */
...@@ -322,12 +322,12 @@ register struct parse *p; ...@@ -322,12 +322,12 @@ register struct parse *p;
p_bracket(p); p_bracket(p);
break; break;
case '\\': case '\\':
REQUIRE(MORE(), REG_EESCAPE); if(REQUIRE(MORE(), REG_EESCAPE));
c = GETNEXT(); c = GETNEXT();
ordinary(p, c); ordinary(p, c);
break; break;
case '{': /* okay as ordinary except if digit follows */ case '{': /* okay as ordinary except if digit follows */
REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT); if(REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT));
/* FALLTHROUGH */ /* FALLTHROUGH */
default: default:
ordinary(p, c); ordinary(p, c);
...@@ -343,7 +343,7 @@ register struct parse *p; ...@@ -343,7 +343,7 @@ register struct parse *p;
return; /* no repetition, we're done */ return; /* no repetition, we're done */
NEXT(); NEXT();
REQUIRE(!wascaret, REG_BADRPT); if(REQUIRE(!wascaret, REG_BADRPT));
switch (c) { switch (c) {
case '*': /* implemented as +? */ case '*': /* implemented as +? */
/* this case does not require the (y|) trick, noKLUDGE */ /* this case does not require the (y|) trick, noKLUDGE */
...@@ -370,7 +370,7 @@ register struct parse *p; ...@@ -370,7 +370,7 @@ register struct parse *p;
if (EAT(',')) { if (EAT(',')) {
if (isdigit(PEEK())) { if (isdigit(PEEK())) {
count2 = p_count(p); count2 = p_count(p);
REQUIRE(count <= count2, REG_BADBR); if(REQUIRE(count <= count2, REG_BADBR));
} else /* single number with comma */ } else /* single number with comma */
count2 = RE_INFINITY; count2 = RE_INFINITY;
} else /* just a single number */ } else /* just a single number */
...@@ -379,7 +379,7 @@ register struct parse *p; ...@@ -379,7 +379,7 @@ register struct parse *p;
if (!EAT('}')) { /* error heuristics */ if (!EAT('}')) { /* error heuristics */
while (MORE() && PEEK() != '}') while (MORE() && PEEK() != '}')
NEXT(); NEXT();
REQUIRE(MORE(), REG_EBRACE); if(REQUIRE(MORE(), REG_EBRACE));
SETERROR(REG_BADBR); SETERROR(REG_BADBR);
} }
break; break;
...@@ -402,7 +402,7 @@ static void ...@@ -402,7 +402,7 @@ static void
p_str(p) p_str(p)
register struct parse *p; register struct parse *p;
{ {
REQUIRE(MORE(), REG_EMPTY); if(REQUIRE(MORE(), REG_EMPTY));
while (MORE()) while (MORE())
ordinary(p, GETNEXT()); ordinary(p, GETNEXT());
} }
...@@ -445,7 +445,7 @@ register int end2; /* second terminating character */ ...@@ -445,7 +445,7 @@ register int end2; /* second terminating character */
p->g->neol++; 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? */ ...@@ -470,7 +470,7 @@ int starordinary; /* is a leading * an ordinary character? */
assert(MORE()); /* caller should have ensured this */ assert(MORE()); /* caller should have ensured this */
c = GETNEXT(); c = GETNEXT();
if (c == '\\') { if (c == '\\') {
REQUIRE(MORE(), REG_EESCAPE); if(REQUIRE(MORE(), REG_EESCAPE));
c = BACKSL | (unsigned char)GETNEXT(); c = BACKSL | (unsigned char)GETNEXT();
} }
switch (c) { switch (c) {
...@@ -500,7 +500,7 @@ int starordinary; /* is a leading * an ordinary character? */ ...@@ -500,7 +500,7 @@ int starordinary; /* is a leading * an ordinary character? */
assert(p->pend[subno] != 0); assert(p->pend[subno] != 0);
} }
EMIT(ORPAREN, subno); EMIT(ORPAREN, subno);
REQUIRE(EATTWO('\\', ')'), REG_EPAREN); if(REQUIRE(EATTWO('\\', ')'), REG_EPAREN));
break; break;
case BACKSL|')': /* should not get here -- must be user */ case BACKSL|')': /* should not get here -- must be user */
case BACKSL|'}': case BACKSL|'}':
...@@ -530,7 +530,7 @@ int starordinary; /* is a leading * an ordinary character? */ ...@@ -530,7 +530,7 @@ int starordinary; /* is a leading * an ordinary character? */
p->g->backrefs = 1; p->g->backrefs = 1;
break; break;
case '*': case '*':
REQUIRE(starordinary, REG_BADRPT); if(REQUIRE(starordinary, REG_BADRPT));
/* FALLTHROUGH */ /* FALLTHROUGH */
default: default:
ordinary(p, c &~ BACKSL); ordinary(p, c &~ BACKSL);
...@@ -548,7 +548,7 @@ int starordinary; /* is a leading * an ordinary character? */ ...@@ -548,7 +548,7 @@ int starordinary; /* is a leading * an ordinary character? */
if (EAT(',')) { if (EAT(',')) {
if (MORE() && isdigit(PEEK())) { if (MORE() && isdigit(PEEK())) {
count2 = p_count(p); count2 = p_count(p);
REQUIRE(count <= count2, REG_BADBR); if(REQUIRE(count <= count2, REG_BADBR));
} else /* single number with comma */ } else /* single number with comma */
count2 = RE_INFINITY; count2 = RE_INFINITY;
} else /* just a single number */ } else /* just a single number */
...@@ -557,7 +557,7 @@ int starordinary; /* is a leading * an ordinary character? */ ...@@ -557,7 +557,7 @@ int starordinary; /* is a leading * an ordinary character? */
if (!EATTWO('\\', '}')) { /* error heuristics */ if (!EATTWO('\\', '}')) { /* error heuristics */
while (MORE() && !SEETWO('\\', '}')) while (MORE() && !SEETWO('\\', '}'))
NEXT(); NEXT();
REQUIRE(MORE(), REG_EBRACE); if(REQUIRE(MORE(), REG_EBRACE));
SETERROR(REG_BADBR); SETERROR(REG_BADBR);
} }
} else if (c == (unsigned char)'$') /* $ (but not \$) ends it */ } else if (c == (unsigned char)'$') /* $ (but not \$) ends it */
...@@ -582,7 +582,7 @@ register struct parse *p; ...@@ -582,7 +582,7 @@ register struct parse *p;
ndigits++; ndigits++;
} }
REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); if(REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR));
return(count); return(count);
} }
...@@ -622,7 +622,7 @@ register struct parse *p; ...@@ -622,7 +622,7 @@ register struct parse *p;
p_b_term(p, cs); p_b_term(p, cs);
if (EAT('-')) if (EAT('-'))
CHadd(cs, '-'); CHadd(cs, '-');
MUSTEAT(']', REG_EBRACK); if(MUSTEAT(']', REG_EBRACK));
if (p->error != 0) /* don't mess things up further */ if (p->error != 0) /* don't mess things up further */
return; return;
...@@ -693,21 +693,21 @@ register cset *cs; ...@@ -693,21 +693,21 @@ register cset *cs;
switch (c) { switch (c) {
case ':': /* character class */ case ':': /* character class */
NEXT2(); NEXT2();
REQUIRE(MORE(), REG_EBRACK); if(REQUIRE(MORE(), REG_EBRACK));
c = PEEK(); c = PEEK();
REQUIRE(c != '-' && c != ']', REG_ECTYPE); if(REQUIRE(c != '-' && c != ']', REG_ECTYPE));
p_b_cclass(p, cs); p_b_cclass(p, cs);
REQUIRE(MORE(), REG_EBRACK); if(REQUIRE(MORE(), REG_EBRACK));
REQUIRE(EATTWO(':', ']'), REG_ECTYPE); if(REQUIRE(EATTWO(':', ']'), REG_ECTYPE));
break; break;
case '=': /* equivalence class */ case '=': /* equivalence class */
NEXT2(); NEXT2();
REQUIRE(MORE(), REG_EBRACK); if(REQUIRE(MORE(), REG_EBRACK));
c = PEEK(); c = PEEK();
REQUIRE(c != '-' && c != ']', REG_ECOLLATE); if(REQUIRE(c != '-' && c != ']', REG_ECOLLATE));
p_b_eclass(p, cs); p_b_eclass(p, cs);
REQUIRE(MORE(), REG_EBRACK); if(REQUIRE(MORE(), REG_EBRACK));
REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); if(REQUIRE(EATTWO('=', ']'), REG_ECOLLATE));
break; break;
default: /* symbol, ordinary character, or range */ default: /* symbol, ordinary character, or range */
/* xxx revision needed for multichar stuff */ /* xxx revision needed for multichar stuff */
...@@ -722,7 +722,7 @@ register cset *cs; ...@@ -722,7 +722,7 @@ register cset *cs;
} else } else
finish = start; finish = start;
/* xxx what about signed chars here... */ /* xxx what about signed chars here... */
REQUIRE(start <= finish, REG_ERANGE); if(REQUIRE(start <= finish, REG_ERANGE));
for (i = start; i <= finish; i++) for (i = start; i <= finish; i++)
CHadd(cs, i); CHadd(cs, i);
break; break;
...@@ -790,13 +790,13 @@ register struct parse *p; ...@@ -790,13 +790,13 @@ register struct parse *p;
{ {
register char value; register char value;
REQUIRE(MORE(), REG_EBRACK); if(REQUIRE(MORE(), REG_EBRACK));
if (!EATTWO('[', '.')) if (!EATTWO('[', '.'))
return(GETNEXT()); return(GETNEXT());
/* collating symbol */ /* collating symbol */
value = p_b_coll_elem(p, '.'); value = p_b_coll_elem(p, '.');
REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); if(REQUIRE(EATTWO('.', ']'), REG_ECOLLATE));
return(value); return(value);
} }
......
...@@ -31,23 +31,23 @@ static struct rerr { ...@@ -31,23 +31,23 @@ static struct rerr {
char *name; char *name;
char *explain; char *explain;
} rerrs[] = { } rerrs[] = {
REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match", {REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"},
REG_BADPAT, "REG_BADPAT", "invalid regular expression", {REG_BADPAT, "REG_BADPAT", "invalid regular expression"},
REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element", {REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"},
REG_ECTYPE, "REG_ECTYPE", "invalid character class", {REG_ECTYPE, "REG_ECTYPE", "invalid character class"},
REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)", {REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)"},
REG_ESUBREG, "REG_ESUBREG", "invalid backreference number", {REG_ESUBREG, "REG_ESUBREG", "invalid backreference number"},
REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced", {REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced"},
REG_EPAREN, "REG_EPAREN", "parentheses not balanced", {REG_EPAREN, "REG_EPAREN", "parentheses not balanced"},
REG_EBRACE, "REG_EBRACE", "braces not balanced", {REG_EBRACE, "REG_EBRACE", "braces not balanced"},
REG_BADBR, "REG_BADBR", "invalid repetition count(s)", {REG_BADBR, "REG_BADBR", "invalid repetition count(s)"},
REG_ERANGE, "REG_ERANGE", "invalid character range", {REG_ERANGE, "REG_ERANGE", "invalid character range"},
REG_ESPACE, "REG_ESPACE", "out of memory", {REG_ESPACE, "REG_ESPACE", "out of memory"},
REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid", {REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid"},
REG_EMPTY, "REG_EMPTY", "empty (sub)expression", {REG_EMPTY, "REG_EMPTY", "empty (sub)expression"},
REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug", {REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug"},
REG_INVARG, "REG_INVARG", "invalid argument to regex routine", {REG_INVARG, "REG_INVARG", "invalid argument to regex routine"},
0, "", "*** unknown regexp error code ***", {0, "", "*** unknown regexp error code ***"},
}; };
/* /*
......
...@@ -861,7 +861,6 @@ static int merge_index(SORTPARAM *param, uchar **sort_keys, ...@@ -861,7 +861,6 @@ static int merge_index(SORTPARAM *param, uchar **sort_keys,
buffpek+maxbuffer,1)) buffpek+maxbuffer,1))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
DBUG_RETURN(0); DBUG_RETURN(0);
/* Was: DBUG_RETURN(my_b_write(outfile,last_ref,param->ref_length)); */
} /* merge_index */ } /* merge_index */
......
...@@ -31,10 +31,11 @@ ...@@ -31,10 +31,11 @@
#endif #endif
ulong myisam_sort_buffer_size; 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[] = const char *myisam_recover_names[] =
{ "NO","DEFAULT", "BACKUP"}; { "DEFAULT", "BACKUP", "FORCE"};
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names),"", TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names),"",
myisam_recover_names}; myisam_recover_names};
...@@ -152,7 +153,7 @@ int ha_myisam::dump(THD* thd, int fd) ...@@ -152,7 +153,7 @@ int ha_myisam::dump(THD* thd, int fd)
my_off_t bytes_to_read = share->state.state.data_file_length; my_off_t bytes_to_read = share->state.state.data_file_length;
int data_fd = file->dfile; int data_fd = file->dfile;
byte * buf = (byte*) my_malloc(blocksize, MYF(MY_WME)); byte * buf = (byte*) my_malloc(blocksize, MYF(MY_WME));
if(!buf) if (!buf)
return ENOMEM; return ENOMEM;
int error = 0; int error = 0;
...@@ -342,13 +343,13 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -342,13 +343,13 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
char* backup_dir = thd->lex.backup_dir; char* backup_dir = thd->lex.backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->real_name; 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; return HA_ADMIN_INVALID;
int error = 0; int error = 0;
const char* errmsg = ""; const char* errmsg = "";
if(my_copy(src_path, fn_format(dst_path, table->path, "", if (my_copy(src_path, fn_format(dst_path, table->path, "",
MI_NAME_DEXT, 4), MYF(MY_WME))) MI_NAME_DEXT, 4), MYF(MY_WME)))
{ {
error = HA_ADMIN_FAILED; error = HA_ADMIN_FAILED;
...@@ -373,24 +374,25 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -373,24 +374,25 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
} }
} }
int ha_myisam::backup(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* backup_dir = thd->lex.backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN]; char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->real_name; 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; 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, dst_path,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES ))) 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; return HA_ADMIN_INVALID;
if(my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT, 4), if (my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT, 4),
dst_path, dst_path,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) ) MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) )
return HA_ADMIN_FAILED; return HA_ADMIN_FAILED;
...@@ -572,6 +574,33 @@ bool ha_myisam::activate_all_index(THD *thd) ...@@ -572,6 +574,33 @@ bool ha_myisam::activate_all_index(THD *thd)
DBUG_RETURN(error); 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) int ha_myisam::update_row(const byte * old_data, byte * new_data)
{ {
statistic_increment(ha_update_count,&LOCK_status); statistic_increment(ha_update_count,&LOCK_status);
......
...@@ -24,12 +24,14 @@ ...@@ -24,12 +24,14 @@
#include <myisam.h> #include <myisam.h>
#include <ft_global.h> #include <ft_global.h>
enum myisam_recover_types { HA_RECOVER_NONE, HA_RECOVER_DEFAULT, #define HA_RECOVER_NONE 0 // No automatic recover
HA_RECOVER_BACKUP}; #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 ulong myisam_sort_buffer_size;
extern TYPELIB myisam_recover_typelib; extern TYPELIB myisam_recover_typelib;
extern myisam_recover_types myisam_recover_type; extern ulong myisam_recover_options;
class ha_myisam: public handler class ha_myisam: public handler
{ {
...@@ -39,11 +41,12 @@ class ha_myisam: public handler ...@@ -39,11 +41,12 @@ class ha_myisam: public handler
public: public:
ha_myisam(TABLE *table): handler(table), file(0), ha_myisam(TABLE *table): handler(table), file(0),
int_option_flag(HA_READ_NEXT+HA_READ_PREV+HA_READ_RND_SAME+ int_option_flag(HA_READ_NEXT | HA_READ_PREV | HA_READ_RND_SAME |
HA_KEYPOS_TO_RNDPOS+ HA_READ_ORDER+ HA_LASTKEY_ORDER+ HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
HA_HAVE_KEY_READ_ONLY+ HA_READ_NOT_EXACT_KEY+ HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY |
HA_LONGLONG_KEYS+ HA_NULL_KEY + HA_LONGLONG_KEYS | HA_NULL_KEY |
HA_DUPP_POS + HA_BLOB_KEY + HA_AUTO_PART_KEY) HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY |
HA_CHECK_AND_REPAIR)
{} {}
~ha_myisam() {} ~ha_myisam() {}
const char *table_type() const { return "MyISAM"; } const char *table_type() const { return "MyISAM"; }
...@@ -100,6 +103,7 @@ class ha_myisam: public handler ...@@ -100,6 +103,7 @@ class ha_myisam: public handler
int check(THD* thd, HA_CHECK_OPT* check_opt); int check(THD* thd, HA_CHECK_OPT* check_opt);
int analyze(THD* thd,HA_CHECK_OPT* check_opt); int analyze(THD* thd,HA_CHECK_OPT* check_opt);
int repair(THD* thd, HA_CHECK_OPT* check_opt); int repair(THD* thd, HA_CHECK_OPT* check_opt);
bool check_and_repair(THD *thd, const char *name);
int optimize(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int restore(THD* thd, HA_CHECK_OPT* check_opt); int restore(THD* thd, HA_CHECK_OPT* check_opt);
int backup(THD* thd, HA_CHECK_OPT* check_opt); int backup(THD* thd, HA_CHECK_OPT* check_opt);
......
...@@ -594,7 +594,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info, ...@@ -594,7 +594,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
TABLE table; TABLE table;
DBUG_ENTER("ha_create_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); DBUG_RETURN(1);
if (update_create_info) if (update_create_info)
{ {
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
#define HA_NO_WRITE_DELAYED (HA_NOT_EXACT_COUNT*2) #define HA_NO_WRITE_DELAYED (HA_NOT_EXACT_COUNT*2)
#define HA_PRIMARY_KEY_IN_READ_INDEX (HA_NO_WRITE_DELAYED*2) #define HA_PRIMARY_KEY_IN_READ_INDEX (HA_NO_WRITE_DELAYED*2)
#define HA_DROP_BEFORE_CREATE (HA_PRIMARY_KEY_IN_READ_INDEX*2) #define HA_DROP_BEFORE_CREATE (HA_PRIMARY_KEY_IN_READ_INDEX*2)
#define HA_CHECK_AND_REPAIR (HA_DROP_BEFORE_CREATE*2)
/* Parameters for open() (in register form->filestat) */ /* Parameters for open() (in register form->filestat) */
/* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */ /* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */
...@@ -248,6 +249,7 @@ class handler :public Sql_alloc ...@@ -248,6 +249,7 @@ class handler :public Sql_alloc
virtual void update_create_info(HA_CREATE_INFO *create_info) {} virtual void update_create_info(HA_CREATE_INFO *create_info) {}
virtual int check(THD* thd, HA_CHECK_OPT* check_opt ); virtual int check(THD* thd, HA_CHECK_OPT* check_opt );
virtual int repair(THD* thd, HA_CHECK_OPT* check_opt); virtual int repair(THD* thd, HA_CHECK_OPT* check_opt);
virtual bool check_and_repair(THD *thd, const char *name) {return 1;}
virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt); virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt);
virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt); virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt);
virtual int backup(THD* thd, HA_CHECK_OPT* check_opt); virtual int backup(THD* thd, HA_CHECK_OPT* check_opt);
......
...@@ -243,7 +243,10 @@ void key_unpack(String *to,TABLE *table,uint idx) ...@@ -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) 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) ...@@ -255,6 +258,10 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
key_part++) key_part++)
{ {
Item_field *field; Item_field *field;
if (key_part->field == table->timestamp_field)
return 1; // Can't be used for update
f.rewind(); f.rewind();
while ((field=(Item_field*) f++)) while ((field=(Item_field*) f++))
{ {
......
...@@ -531,7 +531,7 @@ int rea_create_table(my_string file_name,HA_CREATE_INFO *create_info, ...@@ -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, int format_number(uint inputflag,uint max_length,my_string pos,uint length,
my_string *errpos); my_string *errpos);
int openfrm(const char *name,const char *alias,uint filestat,uint prgflag, int openfrm(const char *name,const char *alias,uint filestat,uint prgflag,
TABLE *outparam); uint ha_open_flags, TABLE *outparam);
int closefrm(TABLE *table); int closefrm(TABLE *table);
db_type get_table_type(const char *name); db_type get_table_type(const char *name);
int read_string(File file, gptr *to, uint length); int read_string(File file, gptr *to, uint length);
......
...@@ -282,7 +282,7 @@ extern pthread_handler_decl(handle_slave,arg); ...@@ -282,7 +282,7 @@ extern pthread_handler_decl(handle_slave,arg);
#ifdef SET_RLIMIT_NOFILE #ifdef SET_RLIMIT_NOFILE
static uint set_maximum_open_files(uint max_file_limit); static uint set_maximum_open_files(uint max_file_limit);
#endif #endif
static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
/**************************************************************************** /****************************************************************************
** Code to end mysqld ** Code to end mysqld
...@@ -1064,6 +1064,7 @@ static void init_signals(void) ...@@ -1064,6 +1064,7 @@ static void init_signals(void)
sigaddset(&set,SIGTERM); sigaddset(&set,SIGTERM);
sigaddset(&set,SIGHUP); sigaddset(&set,SIGHUP);
signal(SIGTERM,SIG_DFL); // If it's blocked by parent signal(SIGTERM,SIG_DFL); // If it's blocked by parent
signal(SIGHUP,SIG_DFL); // If it's blocked by parent
#ifdef SIGTSTP #ifdef SIGTSTP
sigaddset(&set,SIGTSTP); sigaddset(&set,SIGTSTP);
#endif #endif
...@@ -2568,6 +2569,8 @@ static void usage(void) ...@@ -2568,6 +2569,8 @@ static void usage(void)
Log slow queries to this log file. Defaults logging\n\ Log slow queries to this log file. Defaults logging\n\
to hostname-slow.log\n\ to hostname-slow.log\n\
--pid-file=path Pid file used by safe_mysqld\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\ --memlock Lock mysqld in memory\n\
-n, --new Use very new possible 'unsafe' functions\n\ -n, --new Use very new possible 'unsafe' functions\n\
-o, --old-protocol Use the old (3.20) protocol\n\ -o, --old-protocol Use the old (3.20) protocol\n\
...@@ -2856,13 +2859,13 @@ static void get_options(int argc,char **argv) ...@@ -2856,13 +2859,13 @@ static void get_options(int argc,char **argv)
default_table_type=DB_TYPE_ISAM; default_table_type=DB_TYPE_ISAM;
myisam_delay_key_write=0; myisam_delay_key_write=0;
myisam_concurrent_insert=0; myisam_concurrent_insert=0;
myisam_recover_type= HA_RECOVER_NONE; myisam_recover_options= 0;
break; break;
case (int) OPT_SAFE: case (int) OPT_SAFE:
opt_specialflag|= SPECIAL_SAFE_MODE; opt_specialflag|= SPECIAL_SAFE_MODE;
myisam_delay_key_write=0; myisam_delay_key_write=0;
myisam_concurrent_insert=0; myisam_concurrent_insert=0;
myisam_recover_type= HA_RECOVER_NONE; // For now myisam_recover_options= HA_RECOVER_NONE; // To be changed
break; break;
case (int) OPT_SKIP_CONCURRENT_INSERT: case (int) OPT_SKIP_CONCURRENT_INSERT:
myisam_concurrent_insert=0; myisam_concurrent_insert=0;
...@@ -3026,13 +3029,14 @@ static void get_options(int argc,char **argv) ...@@ -3026,13 +3029,14 @@ static void get_options(int argc,char **argv)
#endif #endif
case OPT_MYISAM_RECOVER: case OPT_MYISAM_RECOVER:
{ {
int type; if (!optarg || !optarg[0])
if ((type=find_type(optarg, &myisam_recover_typelib, 2)) <= 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); exit(1);
} }
myisam_recover_type=(myisam_recover_types) (type-1);
break; break;
} }
case OPT_MASTER_HOST: case OPT_MASTER_HOST:
...@@ -3568,6 +3572,64 @@ static uint set_maximum_open_files(uint max_file_limit) ...@@ -3568,6 +3572,64 @@ static uint set_maximum_open_files(uint max_file_limit)
#endif #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 ** Instantiate templates
*****************************************************************************/ *****************************************************************************/
......
...@@ -675,7 +675,7 @@ void close_thread_tables(THD *thd, bool locked) ...@@ -675,7 +675,7 @@ void close_thread_tables(THD *thd, bool locked)
} }
thd->open_tables=0; thd->open_tables=0;
/* Free tables to hold down open files */ /* 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 */ VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */
check_unused(); check_unused();
if (found_old_table) if (found_old_table)
...@@ -987,7 +987,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -987,7 +987,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
else else
{ {
/* Free cache if too big */ /* 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 */ VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */
/* make a new table */ /* make a new table */
...@@ -1410,6 +1410,7 @@ static int open_unireg_entry(TABLE *entry,const char *db,const char *name, ...@@ -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 | (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY), HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
ha_open_options,
entry)) entry))
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -1575,6 +1576,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, ...@@ -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 | (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY), HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
ha_open_options,
tmp_table)) tmp_table))
{ {
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -1859,6 +1861,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -1859,6 +1861,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
item->split_sum_func(*sum_func_list); item->split_sum_func(*sum_func_list);
thd->used_tables|=item->used_tables();
} }
} }
DBUG_RETURN(test(thd->fatal_error)); DBUG_RETURN(test(thd->fatal_error));
......
...@@ -88,6 +88,7 @@ THD::THD() ...@@ -88,6 +88,7 @@ THD::THD()
open_tables=temporary_tables=0; open_tables=temporary_tables=0;
tmp_table=0; tmp_table=0;
lock=locked_tables=0; lock=locked_tables=0;
used_tables=0;
cuted_fields=0L; cuted_fields=0L;
options=thd_startup_options; options=thd_startup_options;
update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE; update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE;
......
...@@ -263,6 +263,7 @@ class THD :public ilink { ...@@ -263,6 +263,7 @@ class THD :public ilink {
ulonglong next_insert_id,last_insert_id,current_insert_id; ulonglong next_insert_id,last_insert_id,current_insert_id;
ha_rows select_limit,offset_limit,default_select_limit,cuted_fields, ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
max_join_size,sent_row_count; max_join_size,sent_row_count;
table_map used_tables;
ulong query_id,version, inactive_timeout,options,thread_id; ulong query_id,version, inactive_timeout,options,thread_id;
long dbug_thread_id; long dbug_thread_id;
pthread_t real_id; pthread_t real_id;
......
...@@ -140,6 +140,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -140,6 +140,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
if (!table) if (!table)
DBUG_RETURN(-1); DBUG_RETURN(-1);
thd->proc_info="init"; thd->proc_info="init";
thd->used_tables=0;
save_time_stamp=table->time_stamp; save_time_stamp=table->time_stamp;
values= its++; values= its++;
if (check_insert_fields(thd,table,fields,*values,1) || if (check_insert_fields(thd,table,fields,*values,1) ||
...@@ -200,6 +201,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -200,6 +201,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
} }
else else
{ {
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 table->record[0][0]=table->record[2][0]; // Fix delete marker
if (fill_record(table->field,*values)) if (fill_record(table->field,*values))
{ {
...@@ -1166,12 +1170,7 @@ select_insert::prepare(List<Item> &values) ...@@ -1166,12 +1170,7 @@ select_insert::prepare(List<Item> &values)
if (check_insert_fields(thd,table,*fields,values,1)) if (check_insert_fields(thd,table,*fields,values,1))
DBUG_RETURN(1); DBUG_RETURN(1);
if (fields->elements)
{
restore_record(table,2); // Get empty record restore_record(table,2); // Get empty record
}
else
table->record[0][0]=table->record[2][0]; // Fix delete marker
table->next_number_field=table->found_next_number_field; table->next_number_field=table->found_next_number_field;
thd->count_cuted_fields=1; /* calc cuted fields */ thd->count_cuted_fields=1; /* calc cuted fields */
thd->cuted_fields=0; thd->cuted_fields=0;
......
...@@ -40,7 +40,7 @@ static byte* get_field_name(Field *buff,uint *length, ...@@ -40,7 +40,7 @@ static byte* get_field_name(Field *buff,uint *length,
/* Open a .frm file */ /* Open a .frm file */
int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
TABLE *outparam) uint ha_open_flags, TABLE *outparam)
{ {
reg1 uint i; reg1 uint i;
reg2 uchar *strpos; reg2 uchar *strpos;
...@@ -216,12 +216,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ...@@ -216,12 +216,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
ha_open(index_file, ha_open(index_file,
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR), (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE : (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
db_stat & HA_WAIT_IF_LOCKED || (db_stat & HA_WAIT_IF_LOCKED ||
specialflag & SPECIAL_WAIT_IF_LOCKED ? specialflag & SPECIAL_WAIT_IF_LOCKED) ?
HA_OPEN_WAIT_IF_LOCKED : HA_OPEN_WAIT_IF_LOCKED :
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ? (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
HA_OPEN_ABORT_IF_LOCKED : 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 */ goto err_not_open; /* purecov: inspected */
} }
outparam->db_low_byte_first=outparam->file->low_byte_first(); outparam->db_low_byte_first=outparam->file->low_byte_first();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment