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;
......
This diff is collapsed.
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version. version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
...@@ -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
/* /*
** 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) ** 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);
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_info[Filedes].type = STREAM_BY_FDOPEN;
my_file_opened--; /* File is opened with my_open ! */
my_stream_opened++;
} }
pthread_mutex_unlock(&THR_LOCK_open); pthread_mutex_unlock(&THR_LOCK_open);
} }
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version. version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details. Library General Public License for more details.
You should have received a copy of the GNU Library General Public You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
......
...@@ -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,19 +343,19 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -342,19 +343,19 @@ 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;
errmsg = "failed in my_copy( Error %d)"; errmsg = "failed in my_copy( Error %d)";
goto err; goto err;
} }
tmp_check_opt.init(); tmp_check_opt.init();
tmp_check_opt.quick = 1; tmp_check_opt.quick = 1;
...@@ -373,26 +374,27 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -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) 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;
return HA_ADMIN_OK; return HA_ADMIN_OK;
...@@ -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,7 +201,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -200,7 +201,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
} }
else 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 (fill_record(table->field,*values))
{ {
if (values_list.elements != 1) if (values_list.elements != 1)
...@@ -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