Commit 9f7c4563 authored by monty@tramp.mysql.fi's avatar monty@tramp.mysql.fi

First part of automatic repair of MyISAM tables.

Error on full disk on repair.
SIGHUP signal handling.
Update with keys on timestamp
Portability fixes
parent 69a249c0
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.
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
......@@ -18,66 +18,115 @@
/* Open a temporary file and cache it with io_cache. Delete it on close */
#include "mysys_priv.h"
#include <m_string.h>
#include "my_static.h"
#include "mysys_err.h"
#include <paths.h>
#define TMP_EXT ".tmp" /* Extension of tempfile */
#if ! defined(P_tmpdir)
#define P_tmpdir ""
#endif
#ifdef HAVE_TEMPNAM
#ifndef MSDOS
extern char **environ;
#endif
#endif
/*
** Open a cached tempfile by IO_CACHE
Remove an open tempfile so that it doesn't survive
if we crash; If the operating system doesn't support
this, just remember the file name for later removal
*/
static my_bool cache_remove_open_tmp(IO_CACHE *cache, const char *name)
{
#if O_TEMPORARY == 0
#if !defined(CANT_DELETE_OPEN_FILES)
/* The following should always succeed */
(void) my_delete(name,MYF(MY_WME | ME_NOINPUT));
#else
int length;
if (!(cache->file_name=
(char*) my_malloc((length=strlen(name)+1),MYF(MY_WME)))
{
my_close(cache->file,MYF(0));
cache->file = -1;
errno=my_error=ENOMEM;
return 1;
}
memcpy(cache->file_name,name,length);
#endif
#endif /* O_TEMPORARY == 0 */
return 0;
}
/*
** Open tempfile cached by IO_CACHE
** Should be used when no seeks are done (only reinit_io_buff)
** Return 0 if cache is inited ok
** The actual file is created when the IO_CACHE buffer gets filled
** If dir is not given, use TMPDIR.
*/
my_bool open_cached_file(IO_CACHE *cache, const char* dir, const char *prefix,
uint cache_size, myf cache_myflags)
{
DBUG_ENTER("open_cached_file");
cache->dir= dir ? my_strdup(dir,MYF(cache_myflags & MY_WME)) : (char*) 0;
cache->prefix= (prefix ? my_strdup(prefix,MYF(cache_myflags & MY_WME)) :
(char*) 0);
cache->file_name=0;
cache->buffer=0; /* Mark that not open */
if (!(cache->file_name=my_tempnam(dir,prefix,MYF(MY_WME))))
DBUG_RETURN(1);
if (!init_io_cache(cache,-1,cache_size,WRITE_CACHE,0L,0,
MYF(cache_myflags | MY_NABP)))
{
DBUG_RETURN(0);
}
(*free)(cache->file_name); /* my_tempnam uses malloc() */
cache->file_name=0;
my_free(cache->dir, MYF(MY_ALLOW_ZERO_PTR));
my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN(0);
}
/* Create the temporary file */
my_bool real_open_cached_file(IO_CACHE *cache)
{
char name_buff[FN_REFLEN];
int error=1;
DBUG_ENTER("real_open_cached_file");
if ((cache->file=my_create(cache->file_name,0,
(int) (O_RDWR | O_BINARY | O_TRUNC | O_TEMPORARY |
O_SHORT_LIVED),
MYF(MY_WME))) >= 0)
if ((cache->file=create_temp_file(name_buff, cache->dir, cache->prefix,
(O_RDWR | O_BINARY | O_TRUNC |
O_TEMPORARY | O_SHORT_LIVED),
MYF(MY_WME))) >= 0)
{
#if O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES)
VOID(my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT)));
#endif
DBUG_RETURN(0);
error=0;
cache_remove_open_tmp(cache, name_buff);
}
DBUG_RETURN(1);
DBUG_RETURN(error);
}
void close_cached_file(IO_CACHE *cache)
{
DBUG_ENTER("close_cached_file");
if (my_b_inited(cache))
{
VOID(end_io_cache(cache));
(void) end_io_cache(cache);
if (cache->file >= 0)
{
VOID(my_close(cache->file,MYF(MY_WME)));
(void) my_close(cache->file,MYF(0));
#ifdef CANT_DELETE_OPEN_FILES
VOID(my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT)));
if (cache->file_name)
{
(void) my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT));
my_free(cache->file_name,MYF(0));
}
#endif
}
if (cache->file_name)
(*free)(cache->file_name); /* my_tempnam uses malloc() */
my_free(cache->dir,MYF(MY_ALLOW_ZERO_PTR));
my_free(cache->prefix,MYF(MY_ALLOW_ZERO_PTR));
}
DBUG_VOID_RETURN;
}
......@@ -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);
if (my_file_info[Filedes].type != UNOPEN)
my_stream_opened++;
if (Filedes < MY_NFILE)
{
if (my_file_info[Filedes].type != UNOPEN)
{
my_file_opened--; /* File is opened with my_open ! */
}
else
{
my_file_info[Filedes].name= my_strdup(name,MyFlags);
}
my_file_info[Filedes].type = STREAM_BY_FDOPEN;
my_file_opened--; /* File is opened with my_open ! */
my_stream_opened++;
}
pthread_mutex_unlock(&THR_LOCK_open);
}
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
......
......@@ -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,19 +343,19 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
char* backup_dir = thd->lex.backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->real_name;
if(!fn_format(src_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
if (!fn_format(src_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
return HA_ADMIN_INVALID;
int error = 0;
const char* errmsg = "";
if(my_copy(src_path, fn_format(dst_path, table->path, "",
MI_NAME_DEXT, 4), MYF(MY_WME)))
{
error = HA_ADMIN_FAILED;
errmsg = "failed in my_copy( Error %d)";
goto err;
}
if (my_copy(src_path, fn_format(dst_path, table->path, "",
MI_NAME_DEXT, 4), MYF(MY_WME)))
{
error = HA_ADMIN_FAILED;
errmsg = "failed in my_copy( Error %d)";
goto err;
}
tmp_check_opt.init();
tmp_check_opt.quick = 1;
......@@ -373,26 +374,27 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
}
}
int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
{
char* backup_dir = thd->lex.backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->real_name;
if(!fn_format(dst_path, table_name, backup_dir, reg_ext, 4 + 64))
if (!fn_format(dst_path, table_name, backup_dir, reg_ext, 4 + 64))
return HA_ADMIN_INVALID;
if(my_copy(fn_format(src_path, table->path,"", reg_ext, 4),
if (my_copy(fn_format(src_path, table->path,"", reg_ext, 4),
dst_path,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )))
{
return HA_ADMIN_FAILED;
}
{
return HA_ADMIN_FAILED;
}
if(!fn_format(dst_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
if (!fn_format(dst_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64))
return HA_ADMIN_INVALID;
if(my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT, 4),
dst_path,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) )
if (my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT, 4),
dst_path,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) )
return HA_ADMIN_FAILED;
return HA_ADMIN_OK;
......@@ -572,6 +574,33 @@ bool ha_myisam::activate_all_index(THD *thd)
DBUG_RETURN(error);
}
bool ha_myisam::check_and_repair(THD *thd, const char *name)
{
int error=0;
HA_CHECK_OPT check_opt;
DBUG_ENTER("ha_myisam::auto_check_and_repair");
if (open(name, O_RDWR, HA_OPEN_WAIT_IF_LOCKED))
DBUG_RETURN(1);
check_opt.init();
check_opt.flags=T_MEDIUM;
if (mi_is_crashed(file) || check(thd, &check_opt))
{
check_opt.flags=(((myisam_recover_options & HA_RECOVER_BACKUP) ?
T_BACKUP_DATA : 0) |
(!(myisam_recover_options & HA_RECOVER_FORCE) ?
T_SAFE_REPAIR : 0));
if (repair(thd, &check_opt))
error=1;
}
if (close())
error=1;
DBUG_RETURN(error);
}
int ha_myisam::update_row(const byte * old_data, byte * new_data)
{
statistic_increment(ha_update_count,&LOCK_status);
......
......@@ -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,7 +201,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
}
else
{
table->record[0][0]=table->record[2][0]; // Fix delete marker
if (thd->used_tables) // Column used in values()
restore_record(table,2); // Get empty record
else
table->record[0][0]=table->record[2][0]; // Fix delete marker
if (fill_record(table->field,*values))
{
if (values_list.elements != 1)
......@@ -1166,12 +1170,7 @@ select_insert::prepare(List<Item> &values)
if (check_insert_fields(thd,table,*fields,values,1))
DBUG_RETURN(1);
if (fields->elements)
{
restore_record(table,2); // Get empty record
}
else
table->record[0][0]=table->record[2][0]; // Fix delete marker
restore_record(table,2); // Get empty record
table->next_number_field=table->found_next_number_field;
thd->count_cuted_fields=1; /* calc cuted fields */
thd->cuted_fields=0;
......
......@@ -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