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
davida@work.mysql.com
jamppa@work.mysql.com
jcole@ham.spaceapes.com
jcole@jcole.burghcom.com
jcole@nslinux.bedford.progress.com
jcole@tetra.bedford.progress.com
jcole@tetra.spaceapes.com
matt@work.mysql.com
monty@donna.mysql.com
monty@work.mysql.com
mwagner@evoq.home.mwagner.org
nusphere@main.burghcom.com
paul@central.snake.net
paul@work.mysql.com
sasha@mysql.sashanet.com
sasha@work.mysql.com
serg@infomag.ape.relarn.ru
serg@work.mysql.com
sinisa@work.mysql.com
tim@localhost.polyesthetic.msg
tim@work.mysql.com
tonu@work.mysql.com
spurr@nslinux.bedford.progress.com
monty@tramp.mysql.fi
......@@ -8984,6 +8984,24 @@ Lock the @code{mysqld} process in memory. This works only if your system
supports the @code{mlockall()} system call. This may help if you have
a problem where the opearting system is causing @code{mysqld} to swap on disk.
@item --myisam-recover [=option[,option...]]] where option is one of DEFAULT, BACKUP or FORCE.
If this option is used, @code{mysqld} will on open check if the table is
marked as crashed or if if the table wasn't closed properly
(The last option only works if you are running with @code{--skip-locking}).
If this is the case mysqld will run check on the table. If the table was
corrupted, @code{mysqld} will attempt to repair it.
The following options affects how the repair works.
@multitable @columnfractions .3 .7
@item DEFAULT @tab The same as not giving any option to @code{--myisam-recover}.
@item BACKUP @tab If the data table was changed during recover, save a backup of the @file{table_name.MYD} data file as @file{table_name-datetime.BAK}.
@item FORCE @tab Run recover even if we will loose more than one row from the .MYD file.
@end multitable
Before a table is automaticly repaired, mysqld will add a note about this
in the error log.
@item --pid-file=path
Path to pid file used by @code{safe_mysqld}.
......@@ -21065,6 +21083,9 @@ The following is new in @code{MyISAM}:
@itemize @bullet
@item
If @code{mysqld} is started with @code{--myisam-recover}, @code{MyISAM} tables
will automaticly be repaired on open if the table wasn't closed properly.
@item
You can @code{INSERT} new rows in a table without deleted rows,
while other threads are reading from the table.
@item
......@@ -21148,6 +21169,18 @@ Note that index files are usually much smaller with @code{MyISAM} than with
system resources than @code{ISAM}, but will need more CPU when inserting
data into compressed index.
The following options to @code{mysqld} can be used to change the behavior of
@code{MyISAM} tables:
@multitable @columnfractions .40 .60
@item @strong{Option} @tab @strong{Meaning}
@item @code{--myisam-recover} @tab Automatic recover of crashed tables.
@item @code{-O myisam_sort_buffer_size=#} @tab Buffer used when recovering tables.
@item @code{--delay-key-write-for-all-tables} @tab Don't flush key buffers between writes for any MyISAM table
@end multitable
@xref{Command-line options}.
@menu
* Key space:: Space needed for keys
* MyISAM table formats:: MyISAM table formats
......@@ -37416,7 +37449,14 @@ though, so 3.23 is not released as a stable version yet.
@appendixsubsec Changes in release 3.23.26
@itemize @bullet
@item
Fixed bug in @code{FULLTEXT} index when inserting a NULL column.
Automatic repair of @code{MyISAM} tables.
@item
Columns referenced in @code{INSERT} are are now properly initialized.
@item
@code{UPDATE} didn't always work when used with a range on a timestamp that
was part of the key that was used to find rows.
@item
Fixed bug in @code{FULLTEXT} index when inserting a NULL value.
@item
Changed to use @code{mkstemp()} instead of @code{tempnam()}.
@end itemize
......@@ -1543,12 +1543,12 @@ com_edit(String *buffer,char *line __attribute__((unused)))
put_info("Sorry, you can't send the result to an editor in Win32",
INFO_ERROR);
#else
char *filename,buff[160];
char filename[FN_REFLEN],buff[160];
int fd,tmp;
const char *editor;
filename = my_tempnam(NullS,"sql",MYF(MY_WME));
if ((fd = my_create(filename,0,O_CREAT | O_WRONLY, MYF(MY_WME))) < 0)
if ((fd=create_temp_file(filename,NullS,"sql", O_CREAT | O_WRONLY,
MYF(MY_WME))) < 0)
goto err;
if (buffer->is_empty() && !old_buffer.is_empty())
(void) my_write(fd,(byte*) old_buffer.ptr(),old_buffer.length(),
......@@ -1576,7 +1576,6 @@ com_edit(String *buffer,char *line __attribute__((unused)))
(void) my_close(fd,MYF(0));
(void) my_delete(filename,MYF(MY_WME));
err:
free(filename);
#endif
return 0;
}
......
......@@ -266,20 +266,21 @@ typedef struct st_dynamic_string {
typedef struct st_io_cache /* Used when cacheing files */
{
my_off_t pos_in_file,end_of_file;
byte *rc_pos,*rc_end,*buffer,*rc_request_pos;
int (*read_function)(struct st_io_cache *,byte *,uint);
char *file_name; /* if used with 'open_cached_file' */
char *dir,*prefix;
File file;
int seek_not_done,error;
uint buffer_length,read_length;
my_off_t pos_in_file,end_of_file;
myf myflags; /* Flags used to my_read/my_write */
enum cache_type type;
#ifdef HAVE_AIOWAIT
uint inited;
my_off_t aio_read_pos;
my_aio_result aio_result;
#endif
enum cache_type type;
int (*read_function)(struct st_io_cache *,byte *,uint);
char *file_name; /* if used with 'open_cached_file' */
} IO_CACHE;
typedef int (*qsort2_cmp)(const void *, const void *, const void *);
......@@ -399,7 +400,7 @@ extern void TERMINATE(FILE *file);
#endif
extern void init_glob_errs(void);
extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags);
extern FILE *my_fdopen(File Filedes,int Flags,myf MyFlags);
extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags);
extern int my_fclose(FILE *fd,myf MyFlags);
extern int my_chsize(File fd,my_off_t newlength,myf MyFlags);
extern int my_error _VARARGS((int nr,myf MyFlags, ...));
......@@ -430,7 +431,7 @@ extern uint dirname_part(my_string to,const char *name);
extern uint dirname_length(const char *name);
#define base_name(A) (A+dirname_length(A))
extern int test_if_hard_path(const char *dir_name);
extern void convert_dirname(my_string name);
extern char *convert_dirname(my_string name);
extern void to_unix_path(my_string name);
extern my_string fn_ext(const char *name);
extern my_string fn_same(my_string toname,const char *name,int flag);
......@@ -507,6 +508,8 @@ extern my_bool open_cached_file(IO_CACHE *cache,const char *dir,
myf cache_myflags);
extern my_bool real_open_cached_file(IO_CACHE *cache);
extern void close_cached_file(IO_CACHE *cache);
File create_temp_file(char *to, const char *dir, const char *pfx,
int mode, myf MyFlags);
extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array,uint element_size,
uint init_alloc,uint alloc_increment);
extern my_bool insert_dynamic(DYNAMIC_ARRAY *array,gptr element);
......
......@@ -339,7 +339,6 @@ typedef struct st_mi_check_param
typedef struct st_mi_sortinfo {
uint key_length;
ha_rows max_records;
SORT_INFO *sort_info;
char *tmpdir;
......@@ -347,6 +346,8 @@ typedef struct st_mi_sortinfo {
int (*key_read)(SORT_INFO *info,void *buff);
int (*key_write)(SORT_INFO *info, const void *buff);
void (*lock_in_memory)(MI_CHECK *info);
uint key_length;
myf myf_rw;
} MI_SORT_PARAM;
/* functions in mi_check */
......
......@@ -1759,6 +1759,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
sort_param.key_read=sort_key_read;
sort_param.lock_in_memory=lock_memory;
sort_param.tmpdir=param->tmpdir;
sort_param.myf_rw=param->myf_rw;
sort_param.sort_info=sort_info;
del=info->state->del;
......
This diff is collapsed.
......@@ -18,66 +18,115 @@
/* Open a temporary file and cache it with io_cache. Delete it on close */
#include "mysys_priv.h"
#include <m_string.h>
#include "my_static.h"
#include "mysys_err.h"
#include <paths.h>
#define TMP_EXT ".tmp" /* Extension of tempfile */
#if ! defined(P_tmpdir)
#define P_tmpdir ""
#endif
#ifdef HAVE_TEMPNAM
#ifndef MSDOS
extern char **environ;
#endif
#endif
/*
Remove an open tempfile so that it doesn't survive
if we crash; If the operating system doesn't support
this, just remember the file name for later removal
*/
static my_bool cache_remove_open_tmp(IO_CACHE *cache, const char *name)
{
#if O_TEMPORARY == 0
#if !defined(CANT_DELETE_OPEN_FILES)
/* The following should always succeed */
(void) my_delete(name,MYF(MY_WME | ME_NOINPUT));
#else
int length;
if (!(cache->file_name=
(char*) my_malloc((length=strlen(name)+1),MYF(MY_WME)))
{
my_close(cache->file,MYF(0));
cache->file = -1;
errno=my_error=ENOMEM;
return 1;
}
memcpy(cache->file_name,name,length);
#endif
#endif /* O_TEMPORARY == 0 */
return 0;
}
/*
** Open a cached tempfile by IO_CACHE
** Open tempfile cached by IO_CACHE
** Should be used when no seeks are done (only reinit_io_buff)
** Return 0 if cache is inited ok
** The actual file is created when the IO_CACHE buffer gets filled
** If dir is not given, use TMPDIR.
*/
my_bool open_cached_file(IO_CACHE *cache, const char* dir, const char *prefix,
uint cache_size, myf cache_myflags)
{
DBUG_ENTER("open_cached_file");
cache->dir= dir ? my_strdup(dir,MYF(cache_myflags & MY_WME)) : (char*) 0;
cache->prefix= (prefix ? my_strdup(prefix,MYF(cache_myflags & MY_WME)) :
(char*) 0);
cache->file_name=0;
cache->buffer=0; /* Mark that not open */
if (!(cache->file_name=my_tempnam(dir,prefix,MYF(MY_WME))))
DBUG_RETURN(1);
if (!init_io_cache(cache,-1,cache_size,WRITE_CACHE,0L,0,
MYF(cache_myflags | MY_NABP)))
{
DBUG_RETURN(0);
}
(*free)(cache->file_name); /* my_tempnam uses malloc() */
cache->file_name=0;
my_free(cache->dir, MYF(MY_ALLOW_ZERO_PTR));
my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN(0);
}
/* Create the temporary file */
my_bool real_open_cached_file(IO_CACHE *cache)
{
char name_buff[FN_REFLEN];
int error=1;
DBUG_ENTER("real_open_cached_file");
if ((cache->file=my_create(cache->file_name,0,
(int) (O_RDWR | O_BINARY | O_TRUNC | O_TEMPORARY |
O_SHORT_LIVED),
if ((cache->file=create_temp_file(name_buff, cache->dir, cache->prefix,
(O_RDWR | O_BINARY | O_TRUNC |
O_TEMPORARY | O_SHORT_LIVED),
MYF(MY_WME))) >= 0)
{
#if O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES)
VOID(my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT)));
#endif
DBUG_RETURN(0);
error=0;
cache_remove_open_tmp(cache, name_buff);
}
DBUG_RETURN(1);
DBUG_RETURN(error);
}
void close_cached_file(IO_CACHE *cache)
{
DBUG_ENTER("close_cached_file");
if (my_b_inited(cache))
{
VOID(end_io_cache(cache));
(void) end_io_cache(cache);
if (cache->file >= 0)
{
VOID(my_close(cache->file,MYF(MY_WME)));
(void) my_close(cache->file,MYF(0));
#ifdef CANT_DELETE_OPEN_FILES
VOID(my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT)));
if (cache->file_name)
{
(void) my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT));
my_free(cache->file_name,MYF(0));
}
#endif
}
if (cache->file_name)
(*free)(cache->file_name); /* my_tempnam uses malloc() */
my_free(cache->dir,MYF(MY_ALLOW_ZERO_PTR));
my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR));
}
DBUG_VOID_RETURN;
}
......@@ -66,8 +66,9 @@ uint dirname_part(my_string to, const char *name)
#define FN_DEVCHAR '\0' /* For easier code */
#endif
void convert_dirname(my_string to)
char *convert_dirname(my_string to)
{
reg1 char *pos;
#ifdef FN_UPPER_CASE
caseup_str(to);
#endif
......@@ -76,7 +77,6 @@ void convert_dirname(my_string to)
#endif
#if FN_LIBCHAR != '/'
{
reg1 my_string pos;
pos=to-1; /* Change from '/' */
while ((pos=strchr(pos+1,'/')) != 0)
*pos=FN_LIBCHAR;
......@@ -84,7 +84,6 @@ void convert_dirname(my_string to)
#endif
#ifdef FN_C_BEFORE_DIR_2
{
reg1 my_string pos;
for (pos=to ; *pos ; pos++)
{
if (*pos == FN_C_BEFORE_DIR_2)
......@@ -95,12 +94,13 @@ void convert_dirname(my_string to)
}
#else
{ /* Append FN_LIBCHAR if not there */
char *end=strend(to);
if (end != to && (end[-1] != FN_LIBCHAR && end[-1] != FN_DEVCHAR))
pos=strend(to);
if (pos != to && (pos[-1] != FN_LIBCHAR && pos[-1] != FN_DEVCHAR))
{
end[0]=FN_LIBCHAR;
end[1]=0;
*pos++=FN_LIBCHAR;
*pos=0;
}
}
#endif
return pos; /* Pointer to end of dir */
} /* convert_dirname */
......@@ -95,7 +95,7 @@ int my_fclose(FILE *fd, myf MyFlags)
if ((uint) file < MY_NFILE && my_file_info[file].type != UNOPEN)
{
my_file_info[file].type = UNOPEN;
my_free(my_file_info[file].name, MYF(0));
my_free(my_file_info[file].name, MYF(MY_ALLOW_ZERO_PTR));
}
pthread_mutex_unlock(&THR_LOCK_open);
DBUG_RETURN(err);
......@@ -103,11 +103,9 @@ int my_fclose(FILE *fd, myf MyFlags)
/* Make a stream out of a file handle */
/* Name may be 0 */
FILE *my_fdopen(File Filedes, int Flags, myf MyFlags)
/* Read | write .. */
/* Special flags */
FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags)
{
FILE *fd;
char type[5];
......@@ -125,11 +123,18 @@ FILE *my_fdopen(File Filedes, int Flags, myf MyFlags)
else
{
pthread_mutex_lock(&THR_LOCK_open);
my_stream_opened++;
if (Filedes < MY_NFILE)
{
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_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);
}
......
......@@ -351,7 +351,7 @@ rl_translate_keyseq (seq, array, len)
{
register int i, c, l, temp;
for (i = l = 0; c = seq[i]; i++)
for (i = l = 0; (c = seq[i]); i++)
{
if (c == '\\')
{
......@@ -1028,7 +1028,7 @@ rl_parse_and_bind (string)
{
int passc = 0;
for (i = 1; c = string[i]; i++)
for (i = 1; (c = string[i]); i++)
{
if (passc)
{
......@@ -1104,7 +1104,7 @@ rl_parse_and_bind (string)
{
int delimiter = string[i++], passc;
for (passc = 0; c = string[i]; i++)
for (passc = 0; (c = string[i]); i++)
{
if (passc)
{
......@@ -1721,7 +1721,7 @@ rl_function_dumper (print_readably)
fprintf (rl_outstream, "\n");
for (i = 0; name = names[i]; i++)
for (i = 0; (name = names[i]); i++)
{
Function *function;
char **invokers;
......
......@@ -1377,7 +1377,7 @@ completion_matches (text, entry_function)
match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
match_list[1] = (char *)NULL;
while (string = (*entry_function) (text, matches))
while ((string = (*entry_function) (text, matches)))
{
if (matches + 1 == match_list_size)
match_list = (char **)xrealloc
......@@ -1427,7 +1427,7 @@ username_completion_function (text, state)
setpwent ();
}
while (entry = getpwent ())
while ((entry = getpwent ()))
{
/* Null usernames should result in all users as possible completions. */
if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
......
......@@ -200,7 +200,7 @@ get_history_event (string, caller_index, delimiting_quote)
}
/* Only a closing `?' or a newline delimit a substring search string. */
for (local_index = i; c = string[i]; i++)
for (local_index = i; (c = string[i]); i++)
if ((!substring_okay && (whitespace (c) || c == ':' ||
(history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
string[i] == delimiting_quote)) ||
......
......@@ -368,7 +368,7 @@ rl_read_key ()
else
{
/* If input is coming from a macro, then use that. */
if (c = _rl_next_macro_key ())
if ((c = _rl_next_macro_key ()))
return (c);
/* If the user has an event function, then call it periodically. */
......
......@@ -174,7 +174,7 @@ noninc_search (dir, pchar)
#define SEARCH_RETURN rl_restore_prompt (); return
/* Read the search string. */
while (c = rl_read_key ())
while ((c = rl_read_key ()))
{
switch (c)
{
......
......@@ -38,6 +38,10 @@
# include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */
#if defined (HAVE_STDIO_H)
# include <stdio.h>
#endif /* HAVE_STDIO_H */
#if defined (HAVE_STRING_H)
# include <string.h>
#else
......
......@@ -232,6 +232,8 @@ _rl_set_screen_size (rows, cols)
screenchars = screenwidth * screenheight;
}
extern void _rl_redisplay_after_sigwinch();
void
rl_resize_terminal ()
{
......@@ -251,32 +253,32 @@ struct _tc_string {
search algorithm to something smarter. */
static struct _tc_string tc_strings[] =
{
"DC", &term_DC,
"IC", &term_IC,
"ce", &term_clreol,
"cl", &term_clrpag,
"cr", &term_cr,
"dc", &term_dc,
"ei", &term_ei,
"ic", &term_ic,
"im", &term_im,
"kd", &term_kd,
"kh", &term_kh, /* home */
"kH", &term_kH, /* end */
"kl", &term_kl,
"kr", &term_kr,
"ku", &term_ku,
"ks", &term_ks,
"ke", &term_ke,
"le", &term_backspace,
"mm", &term_mm,
"mo", &term_mo,
{"DC", &term_DC},
{"IC", &term_IC},
{"ce", &term_clreol},
{"cl", &term_clrpag},
{"cr", &term_cr},
{"dc", &term_dc},
{"ei", &term_ei},
{"ic", &term_ic},
{"im", &term_im},
{"kd", &term_kd},
{"kh", &term_kh}, /* home */
{"kH", &term_kH}, /* end */
{"kl", &term_kl},
{"kr", &term_kr},
{"ku", &term_ku},
{"ks", &term_ks},
{"ke", &term_ke},
{"le", &term_backspace},
{"mm", &term_mm},
{"mo", &term_mo},
#if defined (HACK_TERMCAP_MOTION)
"nd", &term_forward_char,
{"nd", &term_forward_char},
#endif
"pc", &term_pc,
"up", &term_up,
"vb", &visible_bell,
{"pc", &term_pc},
{"up", &term_up},
{"vb", &visible_bell},
};
#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
......
......@@ -182,7 +182,7 @@ tilde_expand (string)
int result_size, result_index;
result_index = result_size = 0;
if (result = strchr (string, '~'))
if ((result = strchr (string, '~')))
result = xmalloc (result_size = (strlen (string) + 16));
else
result = xmalloc (result_size = (strlen (string) + 1));
......
......@@ -106,7 +106,7 @@ rl_do_undo ()
{
UNDO_LIST *release;
int waiting_for_begin = 0;
int start, end;
int start = 0, end = 0;
#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
......
......@@ -3,100 +3,102 @@ static struct cname {
char *name;
char code;
} cnames[] = {
"NUL", '\0',
"SOH", '\001',
"STX", '\002',
"ETX", '\003',
"EOT", '\004',
"ENQ", '\005',
"ACK", '\006',
"BEL", '\007',
"alert", '\007',
"BS", '\010',
"backspace", '\b',
"HT", '\011',
"tab", '\t',
"LF", '\012',
"newline", '\n',
"VT", '\013',
"vertical-tab", '\v',
"FF", '\014',
"form-feed", '\f',
"CR", '\015',
"carriage-return", '\r',
"SO", '\016',
"SI", '\017',
"DLE", '\020',
"DC1", '\021',
"DC2", '\022',
"DC3", '\023',
"DC4", '\024',
"NAK", '\025',
"SYN", '\026',
"ETB", '\027',
"CAN", '\030',
"EM", '\031',
"SUB", '\032',
"ESC", '\033',
"IS4", '\034',
"FS", '\034',
"IS3", '\035',
"GS", '\035',
"IS2", '\036',
"RS", '\036',
"IS1", '\037',
"US", '\037',
"space", ' ',
"exclamation-mark", '!',
"quotation-mark", '"',
"number-sign", '#',
"dollar-sign", '$',
"percent-sign", '%',
"ampersand", '&',
"apostrophe", '\'',
"left-parenthesis", '(',
"right-parenthesis", ')',
"asterisk", '*',
"plus-sign", '+',
"comma", ',',
"hyphen", '-',
"hyphen-minus", '-',
"period", '.',
"full-stop", '.',
"slash", '/',
"solidus", '/',
"zero", '0',
"one", '1',
"two", '2',
"three", '3',
"four", '4',
"five", '5',
"six", '6',
"seven", '7',
"eight", '8',
"nine", '9',
"colon", ':',
"semicolon", ';',
"less-than-sign", '<',
"equals-sign", '=',
"greater-than-sign", '>',
"question-mark", '?',
"commercial-at", '@',
"left-square-bracket", '[',
"backslash", '\\',
"reverse-solidus", '\\',
"right-square-bracket", ']',
"circumflex", '^',
"circumflex-accent", '^',
"underscore", '_',
"low-line", '_',
"grave-accent", '`',
"left-brace", '{',
"left-curly-bracket", '{',
"vertical-line", '|',
"right-brace", '}',
"right-curly-bracket", '}',
"tilde", '~',
"DEL", '\177',
NULL, 0,
{"NUL", '\0'},
{"SOH", '\001'},
{"STX", '\002'},
{"ETX", '\003'},
{"EOT", '\004'},
{"ENQ", '\005'},
{"ACK", '\006'},
{"BEL", '\007'},
{"alert", '\007'},
{"BS", '\010'},
{"backspace", '\b'},
{"HT", '\011'},
{"tab", '\t'},
{"LF", '\012'},
{"newline", '\n'},
{"VT", '\013'},
{"vertical-tab",'\v'},
{"FF", '\014'},
{"form-feed", '\f'},
{"CR", '\015'},
{"carriage-return", '\r'},
{"SO", '\016'},
{"SI", '\017'},
{"DLE", '\020'},
{"DC1", '\021'},
{"DC2", '\022'},
{"DC3", '\023'},
{"DC4", '\024'},
{"NAK", '\025'},
{"SYN", '\026'},
{"ETB", '\027'},
{"CAN", '\030'},
{"EM", '\031'},
{"SUB", '\032'},
{"ESC", '\033'},
{"IS4", '\034'},
{"FS", '\034'},
{"IS3", '\035'},
{"GS", '\035'},
{"IS2", '\036'},
{"RS", '\036'},
{"IS1", '\037'},
{"US", '\037'},
{"space", ' '},
{"exclamation-mark", '!'},
{"quotation-mark", '"'},
{"number-sign", '#'},
{"dollar-sign", '$'},
{"percent-sign", '%'},
{"ampersand", '&'},
{"apostrophe", '\''},
{"left-parenthesis", '('},
{"right-parenthesis", ')'},
{"asterisk", '*'},
{"plus-sign", '+'},
{"comma", ','},
{"hyphen", '-'},
{"hyphen-minus", '-'},
{"period", '.'},
{"full-stop", '.'},
{"slash", '/'},
{"solidus", '/'},
{"zero", '0'},
{"one", '1'},
{"two", '2'},
{"three", '3'},
{"four", '4'},
{"five", '5'},
{"six", '6'},
{"seven", '7'},
{"eight", '8'},
{"nine", '9'},
{"colon", ':'},
{"semicolon", ';'},
{"less-than-sign", '<'},
{"equals-sign", '='},
{"greater-than-sign", '>'},
{"question-mark", '?'},
{"commercial-at", '@'},
{"left-square-bracket", '['},
{"backslash", '\\'},
{"reverse-solidus", '\\'},
{"right-square-bracket",']'},
{"circumflex", '^'},
{"circumflex-accent", '^'},
{"underscore", '_'},
{"low-line", '_'},
{"grave-accent", '`'},
{"left-brace", '{'},
{"left-curly-bracket", '{'},
{"vertical-line", '|'},
{"right-brace", '}'},
{"right-curly-bracket", '}'},
{"tilde", '~'},
{"DEL", '\177'},
{NULL, 0},
};
......@@ -217,7 +217,7 @@ FILE *d;
fprintf(d, ">");
break;
default:
fprintf(d, "!%d(%d)!", OP(*s), opnd);
fprintf(d, "!%ld(%ld)!", OP(*s), opnd);
break;
}
if (!done)
......
......@@ -103,7 +103,7 @@ char *argv[];
len = (int)(subs[0].rm_eo - subs[0].rm_so);
if (subs[0].rm_so != -1) {
if (len != 0)
printf("match `%.*s'\n", len,
printf("match `%.*s'\n", (int)len,
argv[optind] + subs[0].rm_so);
else
printf("match `'@%.1s\n",
......
......@@ -219,7 +219,7 @@ int stop; /* character this ERE should end at */
conc = HERE();
while (MORE() && (c = PEEK()) != '|' && c != stop)
p_ere_exp(p);
REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */
if(REQUIRE(HERE() != conc, REG_EMPTY)); /* require nonempty */
if (!EAT('|'))
break; /* NOTE BREAK OUT */
......@@ -266,7 +266,7 @@ register struct parse *p;
pos = HERE();
switch (c) {
case '(':
REQUIRE(MORE(), REG_EPAREN);
if(REQUIRE(MORE(), REG_EPAREN));
p->g->nsub++;
subno = (sopno) p->g->nsub;
if (subno < NPAREN)
......@@ -279,7 +279,7 @@ register struct parse *p;
assert(p->pend[subno] != 0);
}
EMIT(ORPAREN, subno);
MUSTEAT(')', REG_EPAREN);
if(MUSTEAT(')', REG_EPAREN));
break;
#ifndef POSIX_MISTAKE
case ')': /* happens only if no current unmatched ( */
......@@ -322,12 +322,12 @@ register struct parse *p;
p_bracket(p);
break;
case '\\':
REQUIRE(MORE(), REG_EESCAPE);
if(REQUIRE(MORE(), REG_EESCAPE));
c = GETNEXT();
ordinary(p, c);
break;
case '{': /* okay as ordinary except if digit follows */
REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT);
if(REQUIRE(!MORE() || !isdigit(PEEK()), REG_BADRPT));
/* FALLTHROUGH */
default:
ordinary(p, c);
......@@ -343,7 +343,7 @@ register struct parse *p;
return; /* no repetition, we're done */
NEXT();
REQUIRE(!wascaret, REG_BADRPT);
if(REQUIRE(!wascaret, REG_BADRPT));
switch (c) {
case '*': /* implemented as +? */
/* this case does not require the (y|) trick, noKLUDGE */
......@@ -370,7 +370,7 @@ register struct parse *p;
if (EAT(',')) {
if (isdigit(PEEK())) {
count2 = p_count(p);
REQUIRE(count <= count2, REG_BADBR);
if(REQUIRE(count <= count2, REG_BADBR));
} else /* single number with comma */
count2 = RE_INFINITY;
} else /* just a single number */
......@@ -379,7 +379,7 @@ register struct parse *p;
if (!EAT('}')) { /* error heuristics */
while (MORE() && PEEK() != '}')
NEXT();
REQUIRE(MORE(), REG_EBRACE);
if(REQUIRE(MORE(), REG_EBRACE));
SETERROR(REG_BADBR);
}
break;
......@@ -402,7 +402,7 @@ static void
p_str(p)
register struct parse *p;
{
REQUIRE(MORE(), REG_EMPTY);
if(REQUIRE(MORE(), REG_EMPTY));
while (MORE())
ordinary(p, GETNEXT());
}
......@@ -445,7 +445,7 @@ register int end2; /* second terminating character */
p->g->neol++;
}
REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */
if(REQUIRE(HERE() != start, REG_EMPTY)); /* require nonempty */
}
/*
......@@ -470,7 +470,7 @@ int starordinary; /* is a leading * an ordinary character? */
assert(MORE()); /* caller should have ensured this */
c = GETNEXT();
if (c == '\\') {
REQUIRE(MORE(), REG_EESCAPE);
if(REQUIRE(MORE(), REG_EESCAPE));
c = BACKSL | (unsigned char)GETNEXT();
}
switch (c) {
......@@ -500,7 +500,7 @@ int starordinary; /* is a leading * an ordinary character? */
assert(p->pend[subno] != 0);
}
EMIT(ORPAREN, subno);
REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
if(REQUIRE(EATTWO('\\', ')'), REG_EPAREN));
break;
case BACKSL|')': /* should not get here -- must be user */
case BACKSL|'}':
......@@ -530,7 +530,7 @@ int starordinary; /* is a leading * an ordinary character? */
p->g->backrefs = 1;
break;
case '*':
REQUIRE(starordinary, REG_BADRPT);
if(REQUIRE(starordinary, REG_BADRPT));
/* FALLTHROUGH */
default:
ordinary(p, c &~ BACKSL);
......@@ -548,7 +548,7 @@ int starordinary; /* is a leading * an ordinary character? */
if (EAT(',')) {
if (MORE() && isdigit(PEEK())) {
count2 = p_count(p);
REQUIRE(count <= count2, REG_BADBR);
if(REQUIRE(count <= count2, REG_BADBR));
} else /* single number with comma */
count2 = RE_INFINITY;
} else /* just a single number */
......@@ -557,7 +557,7 @@ int starordinary; /* is a leading * an ordinary character? */
if (!EATTWO('\\', '}')) { /* error heuristics */
while (MORE() && !SEETWO('\\', '}'))
NEXT();
REQUIRE(MORE(), REG_EBRACE);
if(REQUIRE(MORE(), REG_EBRACE));
SETERROR(REG_BADBR);
}
} else if (c == (unsigned char)'$') /* $ (but not \$) ends it */
......@@ -582,7 +582,7 @@ register struct parse *p;
ndigits++;
}
REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
if(REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR));
return(count);
}
......@@ -622,7 +622,7 @@ register struct parse *p;
p_b_term(p, cs);
if (EAT('-'))
CHadd(cs, '-');
MUSTEAT(']', REG_EBRACK);
if(MUSTEAT(']', REG_EBRACK));
if (p->error != 0) /* don't mess things up further */
return;
......@@ -693,21 +693,21 @@ register cset *cs;
switch (c) {
case ':': /* character class */
NEXT2();
REQUIRE(MORE(), REG_EBRACK);
if(REQUIRE(MORE(), REG_EBRACK));
c = PEEK();
REQUIRE(c != '-' && c != ']', REG_ECTYPE);
if(REQUIRE(c != '-' && c != ']', REG_ECTYPE));
p_b_cclass(p, cs);
REQUIRE(MORE(), REG_EBRACK);
REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
if(REQUIRE(MORE(), REG_EBRACK));
if(REQUIRE(EATTWO(':', ']'), REG_ECTYPE));
break;
case '=': /* equivalence class */
NEXT2();
REQUIRE(MORE(), REG_EBRACK);
if(REQUIRE(MORE(), REG_EBRACK));
c = PEEK();
REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
if(REQUIRE(c != '-' && c != ']', REG_ECOLLATE));
p_b_eclass(p, cs);
REQUIRE(MORE(), REG_EBRACK);
REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
if(REQUIRE(MORE(), REG_EBRACK));
if(REQUIRE(EATTWO('=', ']'), REG_ECOLLATE));
break;
default: /* symbol, ordinary character, or range */
/* xxx revision needed for multichar stuff */
......@@ -722,7 +722,7 @@ register cset *cs;
} else
finish = start;
/* xxx what about signed chars here... */
REQUIRE(start <= finish, REG_ERANGE);
if(REQUIRE(start <= finish, REG_ERANGE));
for (i = start; i <= finish; i++)
CHadd(cs, i);
break;
......@@ -790,13 +790,13 @@ register struct parse *p;
{
register char value;
REQUIRE(MORE(), REG_EBRACK);
if(REQUIRE(MORE(), REG_EBRACK));
if (!EATTWO('[', '.'))
return(GETNEXT());
/* collating symbol */
value = p_b_coll_elem(p, '.');
REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
if(REQUIRE(EATTWO('.', ']'), REG_ECOLLATE));
return(value);
}
......
......@@ -31,23 +31,23 @@ static struct rerr {
char *name;
char *explain;
} rerrs[] = {
REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match",
REG_BADPAT, "REG_BADPAT", "invalid regular expression",
REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element",
REG_ECTYPE, "REG_ECTYPE", "invalid character class",
REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)",
REG_ESUBREG, "REG_ESUBREG", "invalid backreference number",
REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced",
REG_EPAREN, "REG_EPAREN", "parentheses not balanced",
REG_EBRACE, "REG_EBRACE", "braces not balanced",
REG_BADBR, "REG_BADBR", "invalid repetition count(s)",
REG_ERANGE, "REG_ERANGE", "invalid character range",
REG_ESPACE, "REG_ESPACE", "out of memory",
REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid",
REG_EMPTY, "REG_EMPTY", "empty (sub)expression",
REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug",
REG_INVARG, "REG_INVARG", "invalid argument to regex routine",
0, "", "*** unknown regexp error code ***",
{REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"},
{REG_BADPAT, "REG_BADPAT", "invalid regular expression"},
{REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"},
{REG_ECTYPE, "REG_ECTYPE", "invalid character class"},
{REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)"},
{REG_ESUBREG, "REG_ESUBREG", "invalid backreference number"},
{REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced"},
{REG_EPAREN, "REG_EPAREN", "parentheses not balanced"},
{REG_EBRACE, "REG_EBRACE", "braces not balanced"},
{REG_BADBR, "REG_BADBR", "invalid repetition count(s)"},
{REG_ERANGE, "REG_ERANGE", "invalid character range"},
{REG_ESPACE, "REG_ESPACE", "out of memory"},
{REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid"},
{REG_EMPTY, "REG_EMPTY", "empty (sub)expression"},
{REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug"},
{REG_INVARG, "REG_INVARG", "invalid argument to regex routine"},
{0, "", "*** unknown regexp error code ***"},
};
/*
......
......@@ -861,7 +861,6 @@ static int merge_index(SORTPARAM *param, uchar **sort_keys,
buffpek+maxbuffer,1))
DBUG_RETURN(1); /* purecov: inspected */
DBUG_RETURN(0);
/* Was: DBUG_RETURN(my_b_write(outfile,last_ref,param->ref_length)); */
} /* merge_index */
......
......@@ -31,10 +31,11 @@
#endif
ulong myisam_sort_buffer_size;
myisam_recover_types myisam_recover_type= HA_RECOVER_NONE;
ulong myisam_recover_options= HA_RECOVER_NONE;
/* bits in myisam_recover_options */
const char *myisam_recover_names[] =
{ "NO","DEFAULT", "BACKUP"};
{ "DEFAULT", "BACKUP", "FORCE"};
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names),"",
myisam_recover_names};
......@@ -152,7 +153,7 @@ int ha_myisam::dump(THD* thd, int fd)
my_off_t bytes_to_read = share->state.state.data_file_length;
int data_fd = file->dfile;
byte * buf = (byte*) my_malloc(blocksize, MYF(MY_WME));
if(!buf)
if (!buf)
return ENOMEM;
int error = 0;
......@@ -342,13 +343,13 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
char* backup_dir = thd->lex.backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->real_name;
if(!fn_format(src_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
if (!fn_format(src_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
return HA_ADMIN_INVALID;
int error = 0;
const char* errmsg = "";
if(my_copy(src_path, fn_format(dst_path, table->path, "",
if (my_copy(src_path, fn_format(dst_path, table->path, "",
MI_NAME_DEXT, 4), MYF(MY_WME)))
{
error = HA_ADMIN_FAILED;
......@@ -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)
{
char* backup_dir = thd->lex.backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->real_name;
if(!fn_format(dst_path, table_name, backup_dir, reg_ext, 4 + 64))
if (!fn_format(dst_path, table_name, backup_dir, reg_ext, 4 + 64))
return HA_ADMIN_INVALID;
if(my_copy(fn_format(src_path, table->path,"", reg_ext, 4),
if (my_copy(fn_format(src_path, table->path,"", reg_ext, 4),
dst_path,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )))
{
return HA_ADMIN_FAILED;
}
if(!fn_format(dst_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
if (!fn_format(dst_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
return HA_ADMIN_INVALID;
if(my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT, 4),
if (my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT, 4),
dst_path,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) )
return HA_ADMIN_FAILED;
......@@ -572,6 +574,33 @@ bool ha_myisam::activate_all_index(THD *thd)
DBUG_RETURN(error);
}
bool ha_myisam::check_and_repair(THD *thd, const char *name)
{
int error=0;
HA_CHECK_OPT check_opt;
DBUG_ENTER("ha_myisam::auto_check_and_repair");
if (open(name, O_RDWR, HA_OPEN_WAIT_IF_LOCKED))
DBUG_RETURN(1);
check_opt.init();
check_opt.flags=T_MEDIUM;
if (mi_is_crashed(file) || check(thd, &check_opt))
{
check_opt.flags=(((myisam_recover_options & HA_RECOVER_BACKUP) ?
T_BACKUP_DATA : 0) |
(!(myisam_recover_options & HA_RECOVER_FORCE) ?
T_SAFE_REPAIR : 0));
if (repair(thd, &check_opt))
error=1;
}
if (close())
error=1;
DBUG_RETURN(error);
}
int ha_myisam::update_row(const byte * old_data, byte * new_data)
{
statistic_increment(ha_update_count,&LOCK_status);
......
......@@ -24,12 +24,14 @@
#include <myisam.h>
#include <ft_global.h>
enum myisam_recover_types { HA_RECOVER_NONE, HA_RECOVER_DEFAULT,
HA_RECOVER_BACKUP};
#define HA_RECOVER_NONE 0 // No automatic recover
#define HA_RECOVER_DEFAULT 1 // Automatic recover active
#define HA_RECOVER_BACKUP 2 // Make a backupfile on recover
#define HA_RECOVER_FORCE 4 // Recover even if we loose rows
extern ulong myisam_sort_buffer_size;
extern TYPELIB myisam_recover_typelib;
extern myisam_recover_types myisam_recover_type;
extern ulong myisam_recover_options;
class ha_myisam: public handler
{
......@@ -39,11 +41,12 @@ class ha_myisam: public handler
public:
ha_myisam(TABLE *table): handler(table), file(0),
int_option_flag(HA_READ_NEXT+HA_READ_PREV+HA_READ_RND_SAME+
HA_KEYPOS_TO_RNDPOS+ HA_READ_ORDER+ HA_LASTKEY_ORDER+
HA_HAVE_KEY_READ_ONLY+ HA_READ_NOT_EXACT_KEY+
HA_LONGLONG_KEYS+ HA_NULL_KEY +
HA_DUPP_POS + HA_BLOB_KEY + HA_AUTO_PART_KEY)
int_option_flag(HA_READ_NEXT | HA_READ_PREV | HA_READ_RND_SAME |
HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | HA_LASTKEY_ORDER |
HA_HAVE_KEY_READ_ONLY | HA_READ_NOT_EXACT_KEY |
HA_LONGLONG_KEYS | HA_NULL_KEY |
HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY |
HA_CHECK_AND_REPAIR)
{}
~ha_myisam() {}
const char *table_type() const { return "MyISAM"; }
......@@ -100,6 +103,7 @@ class ha_myisam: public handler
int check(THD* thd, HA_CHECK_OPT* check_opt);
int analyze(THD* thd,HA_CHECK_OPT* check_opt);
int repair(THD* thd, HA_CHECK_OPT* check_opt);
bool check_and_repair(THD *thd, const char *name);
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int restore(THD* thd, HA_CHECK_OPT* check_opt);
int backup(THD* thd, HA_CHECK_OPT* check_opt);
......
......@@ -594,7 +594,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
TABLE table;
DBUG_ENTER("ha_create_table");
if (openfrm(name,"",0,(uint) READ_ALL,&table))
if (openfrm(name,"",0,(uint) READ_ALL, 0, &table))
DBUG_RETURN(1);
if (update_create_info)
{
......
......@@ -66,6 +66,7 @@
#define HA_NO_WRITE_DELAYED (HA_NOT_EXACT_COUNT*2)
#define HA_PRIMARY_KEY_IN_READ_INDEX (HA_NO_WRITE_DELAYED*2)
#define HA_DROP_BEFORE_CREATE (HA_PRIMARY_KEY_IN_READ_INDEX*2)
#define HA_CHECK_AND_REPAIR (HA_DROP_BEFORE_CREATE*2)
/* Parameters for open() (in register form->filestat) */
/* HA_GET_INFO does a implicit HA_ABORT_IF_LOCKED */
......@@ -248,6 +249,7 @@ class handler :public Sql_alloc
virtual void update_create_info(HA_CREATE_INFO *create_info) {}
virtual int check(THD* thd, HA_CHECK_OPT* check_opt );
virtual int repair(THD* thd, HA_CHECK_OPT* check_opt);
virtual bool check_and_repair(THD *thd, const char *name) {return 1;}
virtual int optimize(THD* thd,HA_CHECK_OPT* check_opt);
virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt);
virtual int backup(THD* thd, HA_CHECK_OPT* check_opt);
......
......@@ -243,7 +243,10 @@ void key_unpack(String *to,TABLE *table,uint idx)
}
/* Return 1 if any field in a list is part of key */
/*
Return 1 if any field in a list is part of key or the key uses a field
that is automaticly updated (like a timestamp)
*/
bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
{
......@@ -255,6 +258,10 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
key_part++)
{
Item_field *field;
if (key_part->field == table->timestamp_field)
return 1; // Can't be used for update
f.rewind();
while ((field=(Item_field*) f++))
{
......
......@@ -531,7 +531,7 @@ int rea_create_table(my_string file_name,HA_CREATE_INFO *create_info,
int format_number(uint inputflag,uint max_length,my_string pos,uint length,
my_string *errpos);
int openfrm(const char *name,const char *alias,uint filestat,uint prgflag,
TABLE *outparam);
uint ha_open_flags, TABLE *outparam);
int closefrm(TABLE *table);
db_type get_table_type(const char *name);
int read_string(File file, gptr *to, uint length);
......
......@@ -282,7 +282,7 @@ extern pthread_handler_decl(handle_slave,arg);
#ifdef SET_RLIMIT_NOFILE
static uint set_maximum_open_files(uint max_file_limit);
#endif
static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
/****************************************************************************
** Code to end mysqld
......@@ -1064,6 +1064,7 @@ static void init_signals(void)
sigaddset(&set,SIGTERM);
sigaddset(&set,SIGHUP);
signal(SIGTERM,SIG_DFL); // If it's blocked by parent
signal(SIGHUP,SIG_DFL); // If it's blocked by parent
#ifdef SIGTSTP
sigaddset(&set,SIGTSTP);
#endif
......@@ -2568,6 +2569,8 @@ static void usage(void)
Log slow queries to this log file. Defaults logging\n\
to hostname-slow.log\n\
--pid-file=path Pid file used by safe_mysqld\n\
--myisam-recover[=option[,option...]] where options is one of DEAULT,\n\
BACKUP or FORCE.\n\
--memlock Lock mysqld in memory\n\
-n, --new Use very new possible 'unsafe' functions\n\
-o, --old-protocol Use the old (3.20) protocol\n\
......@@ -2856,13 +2859,13 @@ static void get_options(int argc,char **argv)
default_table_type=DB_TYPE_ISAM;
myisam_delay_key_write=0;
myisam_concurrent_insert=0;
myisam_recover_type= HA_RECOVER_NONE;
myisam_recover_options= 0;
break;
case (int) OPT_SAFE:
opt_specialflag|= SPECIAL_SAFE_MODE;
myisam_delay_key_write=0;
myisam_concurrent_insert=0;
myisam_recover_type= HA_RECOVER_NONE; // For now
myisam_recover_options= HA_RECOVER_NONE; // To be changed
break;
case (int) OPT_SKIP_CONCURRENT_INSERT:
myisam_concurrent_insert=0;
......@@ -3026,13 +3029,14 @@ static void get_options(int argc,char **argv)
#endif
case OPT_MYISAM_RECOVER:
{
int type;
if ((type=find_type(optarg, &myisam_recover_typelib, 2)) <= 0)
if (!optarg || !optarg[0])
myisam_recover_options=HA_RECOVER_DEFAULT;
else if ((myisam_recover_options=
find_bit_type(optarg, &myisam_recover_typelib)) == ~(ulong) 0)
{
fprintf(stderr,"Unknown option to myisam-recover: %s\n",optarg);
fprintf(stderr, "Unknown option to myisam-recover: %s\n",optarg);
exit(1);
}
myisam_recover_type=(myisam_recover_types) (type-1);
break;
}
case OPT_MASTER_HOST:
......@@ -3568,6 +3572,64 @@ static uint set_maximum_open_files(uint max_file_limit)
#endif
/*
Return a bitfield from a string of substrings separated by ','
returns ~(ulong) 0 on error.
*/
static ulong find_bit_type(const char *x, TYPELIB *bit_lib)
{
bool found_end;
int found_count;
const char *end,*i,*j;
const char **array, *pos;
ulong found,found_int,bit;
DBUG_ENTER("find_bit_type");
DBUG_PRINT("enter",("x: '%s'",x));
found=0;
found_end= 0;
pos=(my_string) x;
do
{
if (!*(end=strcend(pos,','))) /* Let end point at fieldend */
{
while (end > pos && end[-1] == ' ')
end--; /* Skipp end-space */
found_end=1;
}
found_int=0; found_count=0;
for (array=bit_lib->type_names, bit=1 ; (i= *array++) ; bit<<=1)
{
j=pos;
while (j != end)
{
if (toupper(*i++) != toupper(*j++))
goto skipp;
}
found_int=bit;
if (! *i)
{
found_count=1;
break;
}
else if (j != pos) // Half field found
{
found_count++; // Could be one of two values
}
skipp: ;
}
if (found_count != 1)
DBUG_RETURN(~(ulong) 0); // No unique value
found|=found_int;
pos=end+1;
} while (! found_end);
DBUG_PRINT("exit",("bit-field: %ld",(ulong) found));
DBUG_RETURN(found);
} /* find_bit_type */
/*****************************************************************************
** Instantiate templates
*****************************************************************************/
......
......@@ -675,7 +675,7 @@ void close_thread_tables(THD *thd, bool locked)
}
thd->open_tables=0;
/* Free tables to hold down open files */
while (open_cache.records >= table_cache_size && unused_tables)
while (open_cache.records > table_cache_size && unused_tables)
VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */
check_unused();
if (found_old_table)
......@@ -987,7 +987,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
else
{
/* Free cache if too big */
while (open_cache.records >= table_cache_size && unused_tables)
while (open_cache.records > table_cache_size && unused_tables)
VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */
/* make a new table */
......@@ -1410,6 +1410,7 @@ static int open_unireg_entry(TABLE *entry,const char *db,const char *name,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
ha_open_options,
entry))
{
DBUG_RETURN(1);
......@@ -1575,6 +1576,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
ha_open_options,
tmp_table))
{
DBUG_RETURN(0);
......@@ -1859,6 +1861,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
DBUG_RETURN(-1); /* purecov: inspected */
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
item->split_sum_func(*sum_func_list);
thd->used_tables|=item->used_tables();
}
}
DBUG_RETURN(test(thd->fatal_error));
......
......@@ -88,6 +88,7 @@ THD::THD()
open_tables=temporary_tables=0;
tmp_table=0;
lock=locked_tables=0;
used_tables=0;
cuted_fields=0L;
options=thd_startup_options;
update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE;
......
......@@ -263,6 +263,7 @@ class THD :public ilink {
ulonglong next_insert_id,last_insert_id,current_insert_id;
ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
max_join_size,sent_row_count;
table_map used_tables;
ulong query_id,version, inactive_timeout,options,thread_id;
long dbug_thread_id;
pthread_t real_id;
......
......@@ -140,6 +140,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
if (!table)
DBUG_RETURN(-1);
thd->proc_info="init";
thd->used_tables=0;
save_time_stamp=table->time_stamp;
values= its++;
if (check_insert_fields(thd,table,fields,*values,1) ||
......@@ -200,6 +201,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
}
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
if (fill_record(table->field,*values))
{
......@@ -1166,12 +1170,7 @@ select_insert::prepare(List<Item> &values)
if (check_insert_fields(thd,table,*fields,values,1))
DBUG_RETURN(1);
if (fields->elements)
{
restore_record(table,2); // Get empty record
}
else
table->record[0][0]=table->record[2][0]; // Fix delete marker
table->next_number_field=table->found_next_number_field;
thd->count_cuted_fields=1; /* calc cuted fields */
thd->cuted_fields=0;
......
......@@ -40,7 +40,7 @@ static byte* get_field_name(Field *buff,uint *length,
/* Open a .frm file */
int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
TABLE *outparam)
uint ha_open_flags, TABLE *outparam)
{
reg1 uint i;
reg2 uchar *strpos;
......@@ -216,12 +216,12 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
ha_open(index_file,
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
db_stat & HA_WAIT_IF_LOCKED ||
specialflag & SPECIAL_WAIT_IF_LOCKED ?
(db_stat & HA_WAIT_IF_LOCKED ||
specialflag & SPECIAL_WAIT_IF_LOCKED) ?
HA_OPEN_WAIT_IF_LOCKED :
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
HA_OPEN_ABORT_IF_LOCKED :
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_options)))
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags)))
goto err_not_open; /* purecov: inspected */
}
outparam->db_low_byte_first=outparam->file->low_byte_first();
......
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