mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Bug fixes for 3.23.23
This commit is contained in:
@ -143,6 +143,65 @@ same tables.
|
|||||||
and then we read the rows in the sorted order into a row buffer
|
and then we read the rows in the sorted order into a row buffer
|
||||||
(record_buffer) .
|
(record_buffer) .
|
||||||
|
|
||||||
|
@node Coding guidelines
|
||||||
|
@chapter Coding guidelines
|
||||||
|
|
||||||
|
- We are using bitkeeper (www.bitkeeper.com) for source management.
|
||||||
|
- You should use the MySQL 3.23 or MySQL 4.0 source for all developments.
|
||||||
|
- If you have any questions about the MySQL source, you can post these
|
||||||
|
to developers@mysql.com and we will answer them.
|
||||||
|
Note that we will shortly change the name of this list to
|
||||||
|
internals@mysql.com, to more accurately reflect what should be
|
||||||
|
posted to this list.
|
||||||
|
|
||||||
|
- Try to write code in a lot of black boxes that can be reused or at
|
||||||
|
least have a clean interface
|
||||||
|
- Reuse code; There is already in MySQL a lot of algorithms for list handling,
|
||||||
|
queues, dynamic and hashed arrays, sorting...) that can be reused.
|
||||||
|
- Try to always write optimized code, so that you don't have to
|
||||||
|
go back and rewrite it a couple of months later. It's better to
|
||||||
|
spend 3 times as much time designing and writing and optimal function than
|
||||||
|
having to do it all over again later on.
|
||||||
|
- Avoid CPU wasteful code, even where it does not matter, so that
|
||||||
|
you will not develop sloppy coding habits.
|
||||||
|
- If you can write it in fewer lines, do it (as long as the code will not
|
||||||
|
be slower or much harder to read)
|
||||||
|
- do not check the same pointer for NULL more than once.
|
||||||
|
- Use long function and variable names in English; This makes your
|
||||||
|
code easier to read.
|
||||||
|
- Think assembly - make it easier for the compiler to optimize your code.
|
||||||
|
- Comment your code when you do something that someone else may think
|
||||||
|
is 'not trivial'.
|
||||||
|
- Use the my_ functions like my_read/my_write/my_malloc() that you can
|
||||||
|
find in the mysys library instead of the direct system calls; This
|
||||||
|
will make your code easier to debug and more portable.
|
||||||
|
- use libstring functions instead of standard libc string functions
|
||||||
|
whenever possible
|
||||||
|
- Avoid using alloc (its REAL slow); For memory allocations that only
|
||||||
|
needs to live for the lifetime of one thread, on should use
|
||||||
|
sql_alloc() instead.
|
||||||
|
- Before doing big design decision, please first post a summary of
|
||||||
|
what you want to do, why you want to do it and how you plan to do
|
||||||
|
it. This way we can easily provide you with feedback and also
|
||||||
|
easily discuss is throughly if some other developer thinks there is better
|
||||||
|
way to do the same thing!
|
||||||
|
|
||||||
|
- Use my_var as opposed to myVar or MyVar ( _ rather than dancing SHIFT
|
||||||
|
to spearate words in identifiers)
|
||||||
|
- class names start with a capital
|
||||||
|
- structure types are typedefed to all caps identifier
|
||||||
|
- #defines are capitalized
|
||||||
|
- matching { are in the same column
|
||||||
|
- functions return 0 on success , non-zero on error, so you can do
|
||||||
|
if(a() || b() || c()) { error("something went wrong");}
|
||||||
|
- goto is ok if not abused
|
||||||
|
- avoid default variable initalizations, use LINT_INIT() if the
|
||||||
|
compiler complains after making sure that there is really no way
|
||||||
|
the variable can be used uninitialized
|
||||||
|
- Do not instantiate a class if you do not have to
|
||||||
|
- Use pointers rather than array indexing when operating on strings
|
||||||
|
|
||||||
|
|
||||||
@node Index
|
@node Index
|
||||||
@unnumbered Index
|
@unnumbered Index
|
||||||
|
|
||||||
|
424
Docs/manual.texi
424
Docs/manual.texi
File diff suppressed because it is too large
Load Diff
@ -114,7 +114,7 @@ static bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0,
|
|||||||
no_rehash=0,skip_updates=0,safe_updates=0,one_database=0,
|
no_rehash=0,skip_updates=0,safe_updates=0,one_database=0,
|
||||||
opt_compress=0,
|
opt_compress=0,
|
||||||
vertical=0,skip_line_numbers=0,skip_column_names=0,opt_html=0,
|
vertical=0,skip_line_numbers=0,skip_column_names=0,opt_html=0,
|
||||||
no_named_cmds=0;
|
no_named_cmds=1; // we want this to be the default
|
||||||
static uint verbose=0,opt_silent=0,opt_mysql_port=0;
|
static uint verbose=0,opt_silent=0,opt_mysql_port=0;
|
||||||
static my_string opt_mysql_unix_port=0;
|
static my_string opt_mysql_unix_port=0;
|
||||||
static int connect_flag=CLIENT_INTERACTIVE;
|
static int connect_flag=CLIENT_INTERACTIVE;
|
||||||
@ -160,7 +160,7 @@ typedef struct {
|
|||||||
|
|
||||||
static COMMANDS commands[] = {
|
static COMMANDS commands[] = {
|
||||||
{ "help", 'h', com_help, 0, "Display this text" },
|
{ "help", 'h', com_help, 0, "Display this text" },
|
||||||
{ "?", 'h', com_help, 0, "Synonym for `help'" },
|
{ "?", '?', com_help, 0, "Synonym for `help'" },
|
||||||
{ "clear", 'c', com_clear, 0, "Clear command"},
|
{ "clear", 'c', com_clear, 0, "Clear command"},
|
||||||
{ "connect",'r', com_connect,1,
|
{ "connect",'r', com_connect,1,
|
||||||
"Reconnect to the server. Optional arguments are db and host" },
|
"Reconnect to the server. Optional arguments are db and host" },
|
||||||
@ -300,7 +300,7 @@ int main(int argc,char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sprintf(buff, "Type '%s' for help.\n", no_named_cmds ? "\\h" : "help");
|
sprintf(buff, "Type 'help;' or '\\h' for help.\n");
|
||||||
put_info(buff,INFO_INFO);
|
put_info(buff,INFO_INFO);
|
||||||
status.exit_status=read_lines(1); // read lines and execute them
|
status.exit_status=read_lines(1); // read lines and execute them
|
||||||
mysql_end(0);
|
mysql_end(0);
|
||||||
@ -352,6 +352,7 @@ static struct option long_options[] =
|
|||||||
{"database", required_argument, 0, 'D'},
|
{"database", required_argument, 0, 'D'},
|
||||||
{"debug-info", no_argument, 0, 'T'},
|
{"debug-info", no_argument, 0, 'T'},
|
||||||
{"default-character-set", required_argument, 0, OPT_DEFAULT_CHARSET},
|
{"default-character-set", required_argument, 0, OPT_DEFAULT_CHARSET},
|
||||||
|
{"enable-named-commands", no_argument, 0, 'G'},
|
||||||
{"execute", required_argument, 0, 'e'},
|
{"execute", required_argument, 0, 'e'},
|
||||||
{"force", no_argument, 0, 'f'},
|
{"force", no_argument, 0, 'f'},
|
||||||
{"help", no_argument, 0, '?'},
|
{"help", no_argument, 0, '?'},
|
||||||
@ -401,7 +402,7 @@ CHANGEABLE_VAR changeable_vars[] = {
|
|||||||
|
|
||||||
static void usage(int version)
|
static void usage(int version)
|
||||||
{
|
{
|
||||||
printf("%s Ver 10.8 Distrib %s, for %s (%s)\n",
|
printf("%s Ver 10.10 Distrib %s, for %s (%s)\n",
|
||||||
my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
|
my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
|
||||||
if (version)
|
if (version)
|
||||||
return;
|
return;
|
||||||
@ -426,11 +427,17 @@ static void usage(int version)
|
|||||||
-D, --database=.. Database to use.\n\
|
-D, --database=.. Database to use.\n\
|
||||||
--default-character-set=...\n\
|
--default-character-set=...\n\
|
||||||
Set the default character set.\n\
|
Set the default character set.\n\
|
||||||
|
-G, --enable-named-commands\n\
|
||||||
|
Named commands are enabled. Opposite to -g.\n\
|
||||||
-e, --execute=... Execute command and quit. (Output like with --batch)\n\
|
-e, --execute=... Execute command and quit. (Output like with --batch)\n\
|
||||||
-E, --vertical Print the output of a query (rows) vertically.\n\
|
-E, --vertical Print the output of a query (rows) vertically.\n\
|
||||||
-f, --force Continue even if we get an sql error.\n\
|
-f, --force Continue even if we get an sql error.\n\
|
||||||
-g, --no-named-commands\n\
|
-g, --no-named-commands\n\
|
||||||
Named commands are disabled. Use \\* form only.\n\
|
Named commands are disabled. Use \\* form only, or\n\
|
||||||
|
use named commands only in the beginning of a line\n\
|
||||||
|
ending with a semicolon (;)\n\
|
||||||
|
Since version 10.9 the client now starts with this\n\
|
||||||
|
option ENABLED by default! Disable with '-G'\n\
|
||||||
-i, --ignore-space Ignore space after function names.\n\
|
-i, --ignore-space Ignore space after function names.\n\
|
||||||
-h, --host=... Connect to host.\n\
|
-h, --host=... Connect to host.\n\
|
||||||
-H, --html Produce HTML output.\n\
|
-H, --html Produce HTML output.\n\
|
||||||
@ -486,7 +493,7 @@ static int get_options(int argc, char **argv)
|
|||||||
bool tty_password=0;
|
bool tty_password=0;
|
||||||
|
|
||||||
set_all_changeable_vars(changeable_vars);
|
set_all_changeable_vars(changeable_vars);
|
||||||
while ((c=getopt_long(argc,argv,"?ABCD:LfgHinNoqrstTUvVwWEe:h:O:P:S:u:#::p::",
|
while ((c=getopt_long(argc,argv,"?ABCD:LfgGHinNoqrstTUvVwWEe:h:O:P:S:u:#::p::",
|
||||||
long_options, &option_index)) != EOF)
|
long_options, &option_index)) != EOF)
|
||||||
{
|
{
|
||||||
switch(c) {
|
switch(c) {
|
||||||
@ -565,6 +572,7 @@ static int get_options(int argc, char **argv)
|
|||||||
case 'E': vertical=1; break;
|
case 'E': vertical=1; break;
|
||||||
case 'w': wait_flag=1; break;
|
case 'w': wait_flag=1; break;
|
||||||
case 'A': no_rehash=1; break;
|
case 'A': no_rehash=1; break;
|
||||||
|
case 'G': no_named_cmds=0; break;
|
||||||
case 'g': no_named_cmds=1; break;
|
case 'g': no_named_cmds=1; break;
|
||||||
case 'H': opt_html=1; break;
|
case 'H': opt_html=1; break;
|
||||||
case 'i': connect_flag|= CLIENT_IGNORE_SPACE; break;
|
case 'i': connect_flag|= CLIENT_IGNORE_SPACE; break;
|
||||||
@ -1171,11 +1179,13 @@ com_help (String *buffer __attribute__((unused)),
|
|||||||
reg1 int i;
|
reg1 int i;
|
||||||
|
|
||||||
put_info("\nMySQL commands:",INFO_INFO);
|
put_info("\nMySQL commands:",INFO_INFO);
|
||||||
|
if (no_named_cmds)
|
||||||
|
put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO);
|
||||||
for (i = 0; commands[i].name; i++)
|
for (i = 0; commands[i].name; i++)
|
||||||
{
|
{
|
||||||
if (commands[i].func)
|
if (commands[i].func)
|
||||||
printf("%s\t(\\%c)\t%s\n", commands[i].name,commands[i].cmd_char,
|
printf("%s\t(\\%c)\t%s\n", commands[i].name,
|
||||||
commands[i].doc);
|
commands[i].cmd_char, commands[i].doc);
|
||||||
}
|
}
|
||||||
if (connected)
|
if (connected)
|
||||||
printf("\nConnection id: %ld (Can be used with mysqladmin kill)\n\n",
|
printf("\nConnection id: %ld (Can be used with mysqladmin kill)\n\n",
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
** * *
|
** * *
|
||||||
** *************************
|
** *************************
|
||||||
*/
|
*/
|
||||||
#define IMPORT_VERSION "2.3"
|
#define IMPORT_VERSION "2.4"
|
||||||
|
|
||||||
#include <global.h>
|
#include <global.h>
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
@ -514,7 +514,6 @@ int main(int argc, char **argv)
|
|||||||
exitcode = error;
|
exitcode = error;
|
||||||
db_disconnect(current_host, sock);
|
db_disconnect(current_host, sock);
|
||||||
my_free(password,MYF(MY_ALLOW_ZERO_PTR));
|
my_free(password,MYF(MY_ALLOW_ZERO_PTR));
|
||||||
my_free(current_user,MYF(MY_ALLOW_ZERO_PTR));
|
|
||||||
free_defaults(argv_to_free);
|
free_defaults(argv_to_free);
|
||||||
my_end(0);
|
my_end(0);
|
||||||
return(exitcode);
|
return(exitcode);
|
||||||
|
@ -250,6 +250,8 @@ inline double ulonglong2double(ulonglong value)
|
|||||||
#define HAVE_RINT /* defined in this file */
|
#define HAVE_RINT /* defined in this file */
|
||||||
#define NO_FCNTL_NONBLOCK /* No FCNTL */
|
#define NO_FCNTL_NONBLOCK /* No FCNTL */
|
||||||
#define HAVE_ALLOCA
|
#define HAVE_ALLOCA
|
||||||
|
#define HAVE_STRPBRK
|
||||||
|
#define HAVE_STRSTR
|
||||||
#define HAVE_COMPRESS
|
#define HAVE_COMPRESS
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
|
@ -110,7 +110,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* In Linux-alpha we have atomic.h if we are using gcc */
|
/* In Linux-alpha we have atomic.h if we are using gcc */
|
||||||
#if defined(HAVE_LINUXTHREADS) && defined(__GNUC__) && defined(__alpha__) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95))
|
#if defined(HAVE_LINUXTHREADS) && defined(__GNUC__) && defined(__alpha__) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95)) && !defined(HAVE_ATOMIC_ADD)
|
||||||
#define HAVE_ATOMIC_ADD
|
#define HAVE_ATOMIC_ADD
|
||||||
#define HAVE_ATOMIC_SUB
|
#define HAVE_ATOMIC_SUB
|
||||||
#endif
|
#endif
|
||||||
|
@ -112,7 +112,8 @@ static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
|
|||||||
* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
|
* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
static int connect2(File s, const struct sockaddr *name, uint namelen, uint to)
|
static int connect2(my_socket s, const struct sockaddr *name, uint namelen,
|
||||||
|
uint to)
|
||||||
{
|
{
|
||||||
#if defined(__WIN__)
|
#if defined(__WIN__)
|
||||||
return connect(s, (struct sockaddr*) name, namelen);
|
return connect(s, (struct sockaddr*) name, namelen);
|
||||||
@ -1138,7 +1139,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
|||||||
uint port, const char *unix_socket,uint client_flag)
|
uint port, const char *unix_socket,uint client_flag)
|
||||||
{
|
{
|
||||||
char buff[100],charset_name_buff[16],*end,*host_info, *charset_name;
|
char buff[100],charset_name_buff[16],*end,*host_info, *charset_name;
|
||||||
int sock;
|
my_socket sock;
|
||||||
uint32 ip_addr;
|
uint32 ip_addr;
|
||||||
struct sockaddr_in sock_addr;
|
struct sockaddr_in sock_addr;
|
||||||
uint pkt_length;
|
uint pkt_length;
|
||||||
@ -1270,7 +1271,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
|||||||
sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host);
|
sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host);
|
||||||
DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port));
|
DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host,port));
|
||||||
/* _WIN64 ; Assume that the (int) range is enough for socket() */
|
/* _WIN64 ; Assume that the (int) range is enough for socket() */
|
||||||
if ((sock = (int) socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR)
|
if ((sock = (my_socket) socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
net->last_errno=CR_IPSOCK_ERROR;
|
net->last_errno=CR_IPSOCK_ERROR;
|
||||||
sprintf(net->last_error,ER(net->last_errno),ERRNO);
|
sprintf(net->last_error,ER(net->last_errno),ERRNO);
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2000-08-23 Michael Widenius <monty@mysql.com>
|
||||||
|
|
||||||
|
* Fixed bug when comparing DECIMAL/NUMERIC key parts.
|
||||||
|
|
||||||
2000-08-17 Michael Widenius <monty@mysql.com>
|
2000-08-17 Michael Widenius <monty@mysql.com>
|
||||||
|
|
||||||
* Add a new flag in share.staus so that we can quickly check if a table
|
* Add a new flag in share.staus so that we can quickly check if a table
|
||||||
|
@ -43,7 +43,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
|
|||||||
mi_rsamepos.c mi_panic.c mi_close.c mi_create.c\
|
mi_rsamepos.c mi_panic.c mi_close.c mi_create.c\
|
||||||
mi_range.c mi_dbug.c mi_checksum.c mi_log.c \
|
mi_range.c mi_dbug.c mi_checksum.c mi_log.c \
|
||||||
mi_changed.c mi_static.c mi_delete_all.c \
|
mi_changed.c mi_static.c mi_delete_all.c \
|
||||||
mi_delete_table.c mi_rename.c mi_check.c \
|
mi_delete_table.c mi_rename.c mi_check.c mi_debug.c \
|
||||||
ft_parser.c ft_search.c ft_stopwords.c ft_static.c \
|
ft_parser.c ft_search.c ft_stopwords.c ft_static.c \
|
||||||
ft_update.c sort.c
|
ft_update.c sort.c
|
||||||
CLEANFILES = test?.IS? isam.log mi_test_all
|
CLEANFILES = test?.IS? isam.log mi_test_all
|
||||||
|
@ -48,7 +48,7 @@ int ft_init_stopwords(const char **sws)
|
|||||||
|
|
||||||
for(;*sws;sws++)
|
for(;*sws;sws++)
|
||||||
{
|
{
|
||||||
if( (sw.len=strlen(sw.pos=*sws)) < MIN_WORD_LEN) continue;
|
if( (sw.len= (uint) strlen(sw.pos=*sws)) < MIN_WORD_LEN) continue;
|
||||||
if(!tree_insert(stopwords3, &sw, 0))
|
if(!tree_insert(stopwords3, &sw, 0))
|
||||||
{
|
{
|
||||||
delete_tree(stopwords3);
|
delete_tree(stopwords3);
|
||||||
|
@ -30,6 +30,10 @@ int mi_delete_table(const char *name)
|
|||||||
uint raid_type=0,raid_chunks=0;
|
uint raid_type=0,raid_chunks=0;
|
||||||
#endif
|
#endif
|
||||||
DBUG_ENTER("mi_delete_table");
|
DBUG_ENTER("mi_delete_table");
|
||||||
|
|
||||||
|
#ifdef EXTRA_DEBUG
|
||||||
|
check_table_is_closed(name,"delete");
|
||||||
|
#endif
|
||||||
#ifdef USE_RAID
|
#ifdef USE_RAID
|
||||||
{
|
{
|
||||||
MI_INFO *info;
|
MI_INFO *info;
|
||||||
@ -39,7 +43,10 @@ int mi_delete_table(const char *name)
|
|||||||
raid_chunks = info->s->base.raid_chunks;
|
raid_chunks = info->s->base.raid_chunks;
|
||||||
mi_close(info);
|
mi_close(info);
|
||||||
}
|
}
|
||||||
|
#ifdef EXTRA_DEBUG
|
||||||
|
check_table_is_closed(name,"delete");
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* USE_RAID */
|
||||||
|
|
||||||
fn_format(from,name,"",MI_NAME_IEXT,4);
|
fn_format(from,name,"",MI_NAME_IEXT,4);
|
||||||
if (my_delete(from, MYF(MY_WME)))
|
if (my_delete(from, MYF(MY_WME)))
|
||||||
|
@ -30,6 +30,11 @@ int mi_rename(const char *old_name, const char *new_name)
|
|||||||
uint raid_type=0,raid_chunks=0;
|
uint raid_type=0,raid_chunks=0;
|
||||||
#endif
|
#endif
|
||||||
DBUG_ENTER("mi_rename");
|
DBUG_ENTER("mi_rename");
|
||||||
|
|
||||||
|
#ifdef EXTRA_DEBUG
|
||||||
|
check_table_is_closed(old_name,"rename old_table");
|
||||||
|
check_table_is_closed(new_name,"rename new table2");
|
||||||
|
#endif
|
||||||
#ifdef USE_RAID
|
#ifdef USE_RAID
|
||||||
{
|
{
|
||||||
MI_INFO *info;
|
MI_INFO *info;
|
||||||
@ -39,7 +44,10 @@ int mi_rename(const char *old_name, const char *new_name)
|
|||||||
raid_chunks = info->s->base.raid_chunks;
|
raid_chunks = info->s->base.raid_chunks;
|
||||||
mi_close(info);
|
mi_close(info);
|
||||||
}
|
}
|
||||||
|
#ifdef EXTRA_DEBUG
|
||||||
|
check_table_is_closed(old_name,"rename raidcheck");
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* USE_RAID */
|
||||||
|
|
||||||
fn_format(from,old_name,"",MI_NAME_IEXT,4);
|
fn_format(from,old_name,"",MI_NAME_IEXT,4);
|
||||||
fn_format(to,new_name,"",MI_NAME_IEXT,4);
|
fn_format(to,new_name,"",MI_NAME_IEXT,4);
|
||||||
|
@ -57,7 +57,7 @@ int mi_rnext(MI_INFO *info, byte *buf, int inx)
|
|||||||
/* Skip rows that are inserted by other threads since we got a lock */
|
/* Skip rows that are inserted by other threads since we got a lock */
|
||||||
if ((error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
|
if ((error=_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
|
||||||
info->lastkey_length,
|
info->lastkey_length,
|
||||||
flag,
|
SEARCH_BIGGER,
|
||||||
info->s->state.key_root[inx])))
|
info->s->state.key_root[inx])))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ int mi_rprev(MI_INFO *info, byte *buf, int inx)
|
|||||||
/* Skip rows that are inserted by other threads since we got a lock */
|
/* Skip rows that are inserted by other threads since we got a lock */
|
||||||
if ((error=_mi_search_next(info,share->keyinfo+inx,info->lastkey,
|
if ((error=_mi_search_next(info,share->keyinfo+inx,info->lastkey,
|
||||||
info->lastkey_length,
|
info->lastkey_length,
|
||||||
flag,
|
SEARCH_SMALLER,
|
||||||
share->state.key_root[inx])))
|
share->state.key_root[inx])))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -716,6 +716,7 @@ int _mi_key_cmp(register MI_KEYSEG *keyseg, register uchar *a,
|
|||||||
{
|
{
|
||||||
alength= *a++; blength= *b++;
|
alength= *a++; blength= *b++;
|
||||||
end=a+alength;
|
end=a+alength;
|
||||||
|
next_key_length=key_length-blength-1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -622,6 +622,8 @@ void mi_dectivate_non_unique_index(MI_INFO *info, ha_rows rows);
|
|||||||
int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
|
||||||
enum ha_rkey_function search_flag, bool raw_key);
|
enum ha_rkey_function search_flag, bool raw_key);
|
||||||
|
|
||||||
|
my_bool check_table_is_closed(const char *name, const char *where);
|
||||||
|
|
||||||
/* Functions needed by mi_check */
|
/* Functions needed by mi_check */
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -48,7 +48,7 @@ rm $BASE/include/Makefile*; rm $BASE/include/*.in
|
|||||||
|
|
||||||
cp -p tests/*.res tests/*.tst tests/*.pl $BASE/tests
|
cp -p tests/*.res tests/*.tst tests/*.pl $BASE/tests
|
||||||
cp -p support-files/* $BASE/support-files
|
cp -p support-files/* $BASE/support-files
|
||||||
cp -p libmysql/.libs/libmysqlclient.a libmysql/.libs/libmysqlclient.so* libmysql/libmysqlclient.* mysys/libmysys.a strings/libmystrings.a dbug/libdbug.a $BASE/lib
|
cp -p libmysql/.libs/libmysqlclient.a libmysql/.libs/libmysqlclient.so* libmysql/libmysqlclient.* libmysql_r/.libs/libmysqlclient_a.a libmysql_r/.libs/libmysqlclient.so* libmysql_r/libmysqlclient.* mysys/libmysys.a strings/libmystrings.a dbug/libdbug.a $BASE/lib
|
||||||
cp -r -p sql/share/* $BASE/share/mysql; rm -f $BASE/share/mysql/Makefile* $BASE/share/mysql/*/*.OLD $BASE/share/CVS $BASE/share/*/CVS
|
cp -r -p sql/share/* $BASE/share/mysql; rm -f $BASE/share/mysql/Makefile* $BASE/share/mysql/*/*.OLD $BASE/share/CVS $BASE/share/*/CVS
|
||||||
|
|
||||||
cp -p scripts/* $BASE/bin
|
cp -p scripts/* $BASE/bin
|
||||||
|
@ -251,6 +251,21 @@ int ha_heap::rename_table(const char * from, const char * to)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ha_rows ha_heap::records_in_range(int inx,
|
||||||
|
const byte *start_key,uint start_key_len,
|
||||||
|
enum ha_rkey_function start_search_flag,
|
||||||
|
const byte *end_key,uint end_key_len,
|
||||||
|
enum ha_rkey_function end_search_flag)
|
||||||
|
{
|
||||||
|
KEY *pos=table->key_info+inx;
|
||||||
|
if (start_key_len != end_key_len ||
|
||||||
|
start_key_len != pos->key_length ||
|
||||||
|
start_search_flag != HA_READ_KEY_EXACT ||
|
||||||
|
end_search_flag != HA_READ_KEY_EXACT)
|
||||||
|
return HA_POS_ERROR; // Can't only use exact keys
|
||||||
|
return 10; // Good guess
|
||||||
|
}
|
||||||
|
|
||||||
/* We can just delete the heap on creation */
|
/* We can just delete the heap on creation */
|
||||||
|
|
||||||
int ha_heap::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info)
|
int ha_heap::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info)
|
||||||
|
@ -65,7 +65,10 @@ class ha_heap: public handler
|
|||||||
int reset(void);
|
int reset(void);
|
||||||
int external_lock(THD *thd, int lock_type);
|
int external_lock(THD *thd, int lock_type);
|
||||||
int delete_all_rows(void);
|
int delete_all_rows(void);
|
||||||
|
ha_rows records_in_range(int inx, const byte *start_key,uint start_key_len,
|
||||||
|
enum ha_rkey_function start_search_flag,
|
||||||
|
const byte *end_key,uint end_key_len,
|
||||||
|
enum ha_rkey_function end_search_flag);
|
||||||
int delete_table(const char *from);
|
int delete_table(const char *from);
|
||||||
int rename_table(const char * from, const char * to);
|
int rename_table(const char * from, const char * to);
|
||||||
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
|
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
|
||||||
|
@ -317,8 +317,8 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
|
|||||||
}
|
}
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
|
if (!(ref=(byte*) alloc_root(&table->mem_root,
|
||||||
if (!(ref=(byte*) my_malloc(ALIGN_SIZE(ref_length)*2,MYF(0))))
|
ALIGN_SIZE(ref_length)*2)))
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
error=HA_ERR_OUT_OF_MEM;
|
error=HA_ERR_OUT_OF_MEM;
|
||||||
|
@ -200,7 +200,7 @@ public:
|
|||||||
create_time(0), check_time(0), update_time(0), mean_rec_length(0),
|
create_time(0), check_time(0), update_time(0), mean_rec_length(0),
|
||||||
ft_handler(0)
|
ft_handler(0)
|
||||||
{}
|
{}
|
||||||
virtual ~handler(void) { my_free((char*) ref,MYF(MY_ALLOW_ZERO_PTR)); }
|
virtual ~handler(void) {}
|
||||||
int ha_open(const char *name, int mode, int test_if_locked);
|
int ha_open(const char *name, int mode, int test_if_locked);
|
||||||
void update_timestamp(byte *record);
|
void update_timestamp(byte *record);
|
||||||
void update_auto_increment();
|
void update_auto_increment();
|
||||||
|
22
sql/lock.cc
22
sql/lock.cc
@ -407,15 +407,17 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
|
|||||||
TABLE *table;
|
TABLE *table;
|
||||||
char key[MAX_DBKEY_LENGTH];
|
char key[MAX_DBKEY_LENGTH];
|
||||||
uint key_length;
|
uint key_length;
|
||||||
key_length=(uint) (strmov(strmov(key,table_list->db)+1,table_list->name)-key)+
|
DBUG_ENTER("lock_table_name");
|
||||||
1;
|
|
||||||
|
key_length=(uint) (strmov(strmov(key,table_list->db)+1,table_list->name)
|
||||||
|
-key)+ 1;
|
||||||
|
|
||||||
/* Only insert the table if we haven't insert it already */
|
/* Only insert the table if we haven't insert it already */
|
||||||
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
|
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
|
||||||
table ;
|
table ;
|
||||||
table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
|
table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
|
||||||
if (table->in_use == thd)
|
if (table->in_use == thd)
|
||||||
return 0;
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
/* Create a table entry with the right key and with an old refresh version */
|
/* Create a table entry with the right key and with an old refresh version */
|
||||||
/* Note that we must use my_malloc() here as this is freed by the table
|
/* Note that we must use my_malloc() here as this is freed by the table
|
||||||
@ -423,17 +425,18 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
|
|||||||
|
|
||||||
if (!(table= (TABLE*) my_malloc(sizeof(*table)+key_length,
|
if (!(table= (TABLE*) my_malloc(sizeof(*table)+key_length,
|
||||||
MYF(MY_WME | MY_ZEROFILL))))
|
MYF(MY_WME | MY_ZEROFILL))))
|
||||||
return -1;
|
DBUG_RETURN(-1);
|
||||||
memcpy((table->table_cache_key= (char*) (table+1)), key, key_length);
|
memcpy((table->table_cache_key= (char*) (table+1)), key, key_length);
|
||||||
table->key_length=key_length;
|
table->key_length=key_length;
|
||||||
table->in_use=thd;
|
table->in_use=thd;
|
||||||
|
table->locked_by_name=1;
|
||||||
table_list->table=table;
|
table_list->table=table;
|
||||||
|
|
||||||
if (hash_insert(&open_cache, (byte*) table))
|
if (hash_insert(&open_cache, (byte*) table))
|
||||||
return -1;
|
DBUG_RETURN(-1);
|
||||||
if (remove_table_from_cache(thd, table_list->db, table_list->name))
|
if (remove_table_from_cache(thd, table_list->db, table_list->name))
|
||||||
return 1; // Table is in use
|
DBUG_RETURN(1); // Table is in use
|
||||||
return 0;
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock_table_name(THD *thd, TABLE_LIST *table_list)
|
void unlock_table_name(THD *thd, TABLE_LIST *table_list)
|
||||||
@ -446,7 +449,7 @@ static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
|
|||||||
{
|
{
|
||||||
for ( ; table_list ; table_list=table_list->next)
|
for ( ; table_list ; table_list=table_list->next)
|
||||||
{
|
{
|
||||||
if (table_list->table && table_is_used(table_list->table))
|
if (table_list->table && table_is_used(table_list->table,0))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0; // All tables are locked
|
return 0; // All tables are locked
|
||||||
@ -456,6 +459,7 @@ static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
|
|||||||
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
|
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
|
||||||
{
|
{
|
||||||
bool result=0;
|
bool result=0;
|
||||||
|
DBUG_ENTER("wait_for_locked_table_names");
|
||||||
|
|
||||||
while (locked_named_table(thd,table_list))
|
while (locked_named_table(thd,table_list))
|
||||||
{
|
{
|
||||||
@ -467,5 +471,5 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
|
|||||||
wait_for_refresh(thd);
|
wait_for_refresh(thd);
|
||||||
pthread_mutex_lock(&LOCK_open);
|
pthread_mutex_lock(&LOCK_open);
|
||||||
}
|
}
|
||||||
return result;
|
DBUG_RETURN(result);
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,8 @@ static void mc_free_old_query(MYSQL *mysql)
|
|||||||
* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
|
* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
static int mc_sock_connect(File s, const struct sockaddr *name, uint namelen, uint to)
|
static int mc_sock_connect(my_socket s, const struct sockaddr *name,
|
||||||
|
uint namelen, uint to)
|
||||||
{
|
{
|
||||||
#if defined(__WIN__)
|
#if defined(__WIN__)
|
||||||
return connect(s, (struct sockaddr*) name, namelen);
|
return connect(s, (struct sockaddr*) name, namelen);
|
||||||
@ -451,7 +452,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
|
|||||||
uint port, const char *unix_socket,uint client_flag)
|
uint port, const char *unix_socket,uint client_flag)
|
||||||
{
|
{
|
||||||
char buff[100],*end,*host_info;
|
char buff[100],*end,*host_info;
|
||||||
int sock;
|
my_socket sock;
|
||||||
ulong ip_addr;
|
ulong ip_addr;
|
||||||
struct sockaddr_in sock_addr;
|
struct sockaddr_in sock_addr;
|
||||||
uint pkt_length;
|
uint pkt_length;
|
||||||
|
@ -319,10 +319,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias,
|
|||||||
TABLE *find_locked_table(THD *thd, const char *db,const char *table_name);
|
TABLE *find_locked_table(THD *thd, const char *db,const char *table_name);
|
||||||
bool reopen_table(TABLE *table,bool locked=0);
|
bool reopen_table(TABLE *table,bool locked=0);
|
||||||
bool reopen_tables(THD *thd,bool get_locks,bool in_refresh);
|
bool reopen_tables(THD *thd,bool get_locks,bool in_refresh);
|
||||||
void close_old_data_files(THD *thd, TABLE *table, bool abort_locks);
|
void close_old_data_files(THD *thd, TABLE *table, bool abort_locks,
|
||||||
|
bool send_refresh);
|
||||||
bool close_data_tables(THD *thd,const char *db, const char *table_name);
|
bool close_data_tables(THD *thd,const char *db, const char *table_name);
|
||||||
bool wait_for_tables(THD *thd);
|
bool wait_for_tables(THD *thd);
|
||||||
bool table_is_used(TABLE *table);
|
bool table_is_used(TABLE *table, bool wait_for_name_lock);
|
||||||
bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
|
bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
|
||||||
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
|
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
|
||||||
Field *find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables);
|
Field *find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables);
|
||||||
|
@ -2407,6 +2407,12 @@ static void print_version(void)
|
|||||||
server_version,SYSTEM_TYPE,MACHINE_TYPE);
|
server_version,SYSTEM_TYPE,MACHINE_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void use_help(void)
|
||||||
|
{
|
||||||
|
print_version();
|
||||||
|
printf("Use %s --help for a list of available options\n",my_progname);
|
||||||
|
}
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
print_version();
|
print_version();
|
||||||
@ -2621,7 +2627,7 @@ static void get_options(int argc,char **argv)
|
|||||||
case 'O':
|
case 'O':
|
||||||
if (set_changeable_var(optarg, changeable_vars))
|
if (set_changeable_var(optarg, changeable_vars))
|
||||||
{
|
{
|
||||||
usage();
|
use_help();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2666,7 +2672,8 @@ static void get_options(int argc,char **argv)
|
|||||||
opt_noacl=1;
|
opt_noacl=1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
usage();
|
fprintf(stderr,"%s: Unrecognized option: %s\n",my_progname,optarg);
|
||||||
|
use_help();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2910,7 +2917,7 @@ static void get_options(int argc,char **argv)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,"%s: Unrecognized option: %c\n",my_progname,c);
|
fprintf(stderr,"%s: Unrecognized option: %c\n",my_progname,c);
|
||||||
usage();
|
use_help();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2920,7 +2927,7 @@ static void get_options(int argc,char **argv)
|
|||||||
if (argc != optind)
|
if (argc != optind)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"%s: Too many parameters\n",my_progname);
|
fprintf(stderr,"%s: Too many parameters\n",my_progname);
|
||||||
usage();
|
use_help();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
fix_paths();
|
fix_paths();
|
||||||
|
@ -14,6 +14,16 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
Fix that MAYBE_KEY are stored in the tree so that we can detect use
|
||||||
|
of full hash keys for queries like:
|
||||||
|
|
||||||
|
select s.id, kws.keyword_id from sites as s,kws where s.id=kws.site_id and kws.keyword_id in (204,205);
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma implementation // gcc: Class implementation
|
#pragma implementation // gcc: Class implementation
|
||||||
@ -557,7 +567,7 @@ SEL_ARG *SEL_ARG::clone_tree()
|
|||||||
** Returns:
|
** Returns:
|
||||||
** -1 if impossible select
|
** -1 if impossible select
|
||||||
** 0 if can't use quick_select
|
** 0 if can't use quick_select
|
||||||
** 1 if found usably range
|
** 1 if found usable range
|
||||||
** Updates the following in the select parameter:
|
** Updates the following in the select parameter:
|
||||||
** needed_reg ; Bits for keys with may be used if all prev regs are read
|
** needed_reg ; Bits for keys with may be used if all prev regs are read
|
||||||
** quick ; Parameter to use when reading records.
|
** quick ; Parameter to use when reading records.
|
||||||
|
@ -582,9 +582,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
|||||||
thd->mysys_var->current_cond= &COND_refresh;
|
thd->mysys_var->current_cond= &COND_refresh;
|
||||||
thd->proc_info="Flushing tables";
|
thd->proc_info="Flushing tables";
|
||||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
||||||
VOID(pthread_cond_broadcast(&COND_refresh)); // If one flush is locked
|
|
||||||
|
|
||||||
close_old_data_files(thd,thd->open_tables,1);
|
close_old_data_files(thd,thd->open_tables,1,1);
|
||||||
bool found=1;
|
bool found=1;
|
||||||
/* Wait until all threads has closed all the tables we had locked */
|
/* Wait until all threads has closed all the tables we had locked */
|
||||||
DBUG_PRINT("info", ("Waiting for others threads to close their open tables"));
|
DBUG_PRINT("info", ("Waiting for others threads to close their open tables"));
|
||||||
@ -921,7 +920,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
|
|||||||
** There is a refresh in progress for this table
|
** There is a refresh in progress for this table
|
||||||
** Wait until the table is freed or the thread is killed.
|
** Wait until the table is freed or the thread is killed.
|
||||||
*/
|
*/
|
||||||
close_old_data_files(thd,thd->open_tables,0);
|
close_old_data_files(thd,thd->open_tables,0,0);
|
||||||
if (table->in_use != thd)
|
if (table->in_use != thd)
|
||||||
wait_for_refresh(thd);
|
wait_for_refresh(thd);
|
||||||
else
|
else
|
||||||
@ -1216,9 +1215,11 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
|
|||||||
abort_locks is set if called from flush_tables.
|
abort_locks is set if called from flush_tables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void close_old_data_files(THD *thd, TABLE *table, bool abort_locks)
|
void close_old_data_files(THD *thd, TABLE *table, bool abort_locks,
|
||||||
|
bool send_refresh)
|
||||||
{
|
{
|
||||||
bool found=0;
|
DBUG_ENTER("close_old_data_files");
|
||||||
|
bool found=send_refresh;
|
||||||
for (; table ; table=table->next)
|
for (; table ; table=table->next)
|
||||||
{
|
{
|
||||||
if (table->version != refresh_version)
|
if (table->version != refresh_version)
|
||||||
@ -1241,6 +1242,7 @@ void close_old_data_files(THD *thd, TABLE *table, bool abort_locks)
|
|||||||
}
|
}
|
||||||
if (found)
|
if (found)
|
||||||
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
|
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1250,17 +1252,19 @@ void close_old_data_files(THD *thd, TABLE *table, bool abort_locks)
|
|||||||
if the table is closed
|
if the table is closed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool table_is_used(TABLE *table)
|
bool table_is_used(TABLE *table, bool wait_for_name_lock)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
char *key= table->table_cache_key;
|
char *key= table->table_cache_key;
|
||||||
uint key_length=table->key_length;
|
uint key_length=table->key_length;
|
||||||
for (TABLE *search=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
|
for (TABLE *search=(TABLE*) hash_search(&open_cache,
|
||||||
|
(byte*) key,key_length) ;
|
||||||
search ;
|
search ;
|
||||||
search = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
|
search = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
|
||||||
{
|
{
|
||||||
if (search->locked_by_flush ||
|
if (search->locked_by_flush ||
|
||||||
|
search->locked_by_name && wait_for_name_lock ||
|
||||||
search->db_stat && search->version < refresh_version)
|
search->db_stat && search->version < refresh_version)
|
||||||
return 1; // Table is used
|
return 1; // Table is used
|
||||||
}
|
}
|
||||||
@ -1278,19 +1282,14 @@ bool wait_for_tables(THD *thd)
|
|||||||
|
|
||||||
thd->proc_info="Waiting for tables";
|
thd->proc_info="Waiting for tables";
|
||||||
pthread_mutex_lock(&LOCK_open);
|
pthread_mutex_lock(&LOCK_open);
|
||||||
thd->some_tables_deleted=0;
|
while (!thd->killed)
|
||||||
close_old_data_files(thd,thd->open_tables,0);
|
|
||||||
if (dropping_tables)
|
|
||||||
{
|
|
||||||
(void) pthread_cond_broadcast(&COND_refresh); // Signal to refresh/delete
|
|
||||||
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (table_is_used(thd->open_tables) && ! thd->killed)
|
|
||||||
{
|
{
|
||||||
|
thd->some_tables_deleted=0;
|
||||||
|
close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0);
|
||||||
|
if (!table_is_used(thd->open_tables,1))
|
||||||
|
break;
|
||||||
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
|
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thd->killed)
|
if (thd->killed)
|
||||||
result= 1; // aborted
|
result= 1; // aborted
|
||||||
else
|
else
|
||||||
|
@ -1170,9 +1170,8 @@ mysql_execute_command(void)
|
|||||||
#endif
|
#endif
|
||||||
case SQLCOM_REPAIR:
|
case SQLCOM_REPAIR:
|
||||||
{
|
{
|
||||||
if (!tables->db)
|
if (check_db_used(thd,tables) ||
|
||||||
tables->db=thd->db;
|
check_table_access(thd,SELECT_ACL | INSERT_ACL, tables))
|
||||||
if (check_table_access(thd,SELECT_ACL | INSERT_ACL, tables))
|
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
res = mysql_repair_table(thd, tables, &lex->check_opt);
|
res = mysql_repair_table(thd, tables, &lex->check_opt);
|
||||||
break;
|
break;
|
||||||
@ -1695,6 +1694,10 @@ error:
|
|||||||
** Get the user (global) and database privileges for all used tables
|
** Get the user (global) and database privileges for all used tables
|
||||||
** Returns true (error) if we can't get the privileges and we don't use
|
** Returns true (error) if we can't get the privileges and we don't use
|
||||||
** table/column grants.
|
** table/column grants.
|
||||||
|
** The idea of EXTRA_ACL is that one will be granted access to the table if
|
||||||
|
** one has the asked privilege on any column combination of the table; For
|
||||||
|
** example to be able to check a table one needs to have SELECT privilege on
|
||||||
|
** any column of the table.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1760,7 +1763,8 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables)
|
|||||||
TABLE_LIST *org_tables=tables;
|
TABLE_LIST *org_tables=tables;
|
||||||
for (; tables ; tables=tables->next)
|
for (; tables ; tables=tables->next)
|
||||||
{
|
{
|
||||||
if ((thd->master_access & want_access) == want_access && thd->db)
|
if ((thd->master_access & want_access) == (want_access & ~EXTRA_ACL) &&
|
||||||
|
thd->db)
|
||||||
tables->grant.privilege= want_access;
|
tables->grant.privilege= want_access;
|
||||||
else if (tables->db && tables->db == thd->db)
|
else if (tables->db && tables->db == thd->db)
|
||||||
{
|
{
|
||||||
|
@ -800,6 +800,14 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
|||||||
if ((s->on_expr=tables->on_expr))
|
if ((s->on_expr=tables->on_expr))
|
||||||
{
|
{
|
||||||
// table->maybe_null=table->outer_join=1; // Mark for send fields
|
// table->maybe_null=table->outer_join=1; // Mark for send fields
|
||||||
|
if (!table->file->records)
|
||||||
|
{ // Empty table
|
||||||
|
s->key_dependent=s->dependent=0;
|
||||||
|
s->type=JT_SYSTEM;
|
||||||
|
const_table_map|=table->map;
|
||||||
|
set_position(join,const_count++,s,(KEYUSE*) 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
s->key_dependent=s->dependent=
|
s->key_dependent=s->dependent=
|
||||||
s->on_expr->used_tables() & ~(table->map);
|
s->on_expr->used_tables() & ~(table->map);
|
||||||
s->dependent|=stat_vector[i-1]->dependent | table_vector[i-1]->map;
|
s->dependent|=stat_vector[i-1]->dependent | table_vector[i-1]->map;
|
||||||
|
@ -91,6 +91,7 @@ struct st_table {
|
|||||||
my_bool crypted;
|
my_bool crypted;
|
||||||
my_bool db_low_byte_first; /* Portable row format */
|
my_bool db_low_byte_first; /* Portable row format */
|
||||||
my_bool locked_by_flush;
|
my_bool locked_by_flush;
|
||||||
|
my_bool locked_by_name;
|
||||||
Field *next_number_field, /* Set if next_number is activated */
|
Field *next_number_field, /* Set if next_number is activated */
|
||||||
*found_next_number_field, /* Set on open */
|
*found_next_number_field, /* Set on open */
|
||||||
*rowid_field;
|
*rowid_field;
|
||||||
|
220
tests/drop_test.pl
Executable file
220
tests/drop_test.pl
Executable file
@ -0,0 +1,220 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
#
|
||||||
|
# This is a test with uses processes to insert, select and drop tables.
|
||||||
|
#
|
||||||
|
|
||||||
|
$opt_loop_count=100000; # Change this to make test harder/easier
|
||||||
|
|
||||||
|
##################### Standard benchmark inits ##############################
|
||||||
|
|
||||||
|
use DBI;
|
||||||
|
use Getopt::Long;
|
||||||
|
use Benchmark;
|
||||||
|
|
||||||
|
package main;
|
||||||
|
|
||||||
|
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
|
||||||
|
$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0;
|
||||||
|
$opt_host=""; $opt_db="test";
|
||||||
|
|
||||||
|
GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in","skip-delete",
|
||||||
|
"verbose","fast-insert","lock-tables","debug","fast","force") || die "Aborted";
|
||||||
|
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
|
||||||
|
|
||||||
|
print "Testing 5 multiple connections to a server with 1 insert, 2 drop/rename\n";
|
||||||
|
print "1 select and 1 flush thread\n";
|
||||||
|
|
||||||
|
$firsttable = "bench_f1";
|
||||||
|
|
||||||
|
####
|
||||||
|
#### Start timeing and start test
|
||||||
|
####
|
||||||
|
|
||||||
|
$start_time=new Benchmark;
|
||||||
|
if (!$opt_skip_create)
|
||||||
|
{
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
$dbh->do("drop table if exists $firsttable, ${firsttable}_1, ${firsttable}_2");
|
||||||
|
|
||||||
|
print "Creating table $firsttable in database $opt_db\n";
|
||||||
|
$dbh->do("create table $firsttable (id int(6) not null, info varchar(32), marker char(1), primary key(id))") || die $DBI::errstr;
|
||||||
|
$dbh->disconnect; $dbh=0; # Close handler
|
||||||
|
}
|
||||||
|
$|= 1; # Autoflush
|
||||||
|
|
||||||
|
####
|
||||||
|
#### Start the tests
|
||||||
|
####
|
||||||
|
|
||||||
|
test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
|
||||||
|
test_drop(1) if (($pid=fork()) == 0); $work{$pid}="drop 1";
|
||||||
|
test_drop(2) if (($pid=fork()) == 0); $work{$pid}="drop 2";
|
||||||
|
test_select() if (($pid=fork()) == 0); $work{$pid}="select";
|
||||||
|
test_flush() if (($pid=fork()) == 0); $work{$pid}="flush";
|
||||||
|
|
||||||
|
$errors=0;
|
||||||
|
while (($pid=wait()) != -1)
|
||||||
|
{
|
||||||
|
$ret=$?/256;
|
||||||
|
print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
|
||||||
|
$errors++ if ($ret != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$opt_skip_delete && !$errors)
|
||||||
|
{
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
$dbh->do("drop table $firsttable");
|
||||||
|
$dbh->disconnect; $dbh=0; # Close handler
|
||||||
|
}
|
||||||
|
print ($errors ? "Test failed\n" :"Test ok\n");
|
||||||
|
|
||||||
|
$end_time=new Benchmark;
|
||||||
|
print "Total time: " .
|
||||||
|
timestr(timediff($end_time, $start_time),"noc") . "\n";
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Insert records in the table
|
||||||
|
#
|
||||||
|
|
||||||
|
sub test_insert
|
||||||
|
{
|
||||||
|
my ($dbh,$i);
|
||||||
|
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
for ($i=0 ; $i < $opt_loop_count; $i++)
|
||||||
|
{
|
||||||
|
if (!$dbh->do("insert into $firsttable values ($i,'This is entry $i','')"))
|
||||||
|
{
|
||||||
|
print "Warning; Got error on insert: " . $dbh->errstr . "\n" if (! ($dbh->errstr =~ /doesn't exist/));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dbh->disconnect; $dbh=0;
|
||||||
|
print "Test_insert: Inserted $i rows\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub test_drop
|
||||||
|
{
|
||||||
|
my ($id) = @_;
|
||||||
|
my ($dbh,$i,$sth,$error_counter,$sleep_time);
|
||||||
|
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
$error_counter=0;
|
||||||
|
$sleep_time=2;
|
||||||
|
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||||
|
{
|
||||||
|
sleep($sleep_time);
|
||||||
|
# Check if insert thread is ready
|
||||||
|
$sth=$dbh->prepare("select count(*) from $firsttable") || die "Got error on select from $firsttable: $dbh->errstr\n";
|
||||||
|
if (!$sth->execute || !(@row = $sth->fetchrow_array()) ||
|
||||||
|
!$row[0])
|
||||||
|
{
|
||||||
|
$sth->finish;
|
||||||
|
$sleep_time=1;
|
||||||
|
last if ($error_counter++ == 5);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
$sleep_time=2;
|
||||||
|
$sth->finish;
|
||||||
|
|
||||||
|
# Change to use a new table
|
||||||
|
$dbh->do("create table ${firsttable}_$id (id int(6) not null, info varchar(32), marker char(1), primary key(id))") || die $DBI::errstr;
|
||||||
|
$dbh->do("drop table if exists $firsttable") || die "Got error on drop table: $dbh->errstr\n";
|
||||||
|
if (!$dbh->do("alter table ${firsttable}_$id rename to $firsttable"))
|
||||||
|
{
|
||||||
|
print "Warning; Got error from alter table: " . $dbh->errstr . "\n" if (! ($dbh->errstr =~ /already exist/));
|
||||||
|
$dbh->do("drop table if exists ${firsttable}_$id") || die "Got error on drop table: $dbh->errstr\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dbh->do("drop table if exists $firsttable,${firsttable}_$id") || die "Got error on drop table: $dbh->errstr\n";
|
||||||
|
$dbh->disconnect; $dbh=0;
|
||||||
|
print "Test_drop: Did a drop $i times\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# select records
|
||||||
|
#
|
||||||
|
|
||||||
|
sub test_select
|
||||||
|
{
|
||||||
|
my ($dbh,$i,$sth,@row,$error_counter,$sleep_time);
|
||||||
|
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
|
||||||
|
$error_counter=0;
|
||||||
|
$sleep_time=3;
|
||||||
|
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||||
|
{
|
||||||
|
sleep($sleep_time);
|
||||||
|
$sth=$dbh->prepare("select sum(t.id) from $firsttable as t,$firsttable as t2") || die "Got error on select: $dbh->errstr;\n";
|
||||||
|
if ($sth->execute)
|
||||||
|
{
|
||||||
|
@row = $sth->fetchrow_array();
|
||||||
|
$sth->finish;
|
||||||
|
$sleep_time=3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print "Warning; Got error from select: " . $dbh->errstr . "\n" if (! ($dbh->errstr =~ /doesn't exist/));
|
||||||
|
$sth->finish;
|
||||||
|
last if ($error_counter++ == 5);
|
||||||
|
$sleep_time=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dbh->disconnect; $dbh=0;
|
||||||
|
print "Test_select: ok\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# flush records
|
||||||
|
#
|
||||||
|
|
||||||
|
sub test_flush
|
||||||
|
{
|
||||||
|
my ($dbh,$i,$sth,@row,$error_counter,$sleep_time);
|
||||||
|
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
|
||||||
|
$error_counter=0;
|
||||||
|
$sleep_time=5;
|
||||||
|
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||||
|
{
|
||||||
|
sleep($sleep_time);
|
||||||
|
$sth=$dbh->prepare("select count(*) from $firsttable") || die "Got error on prepar: $dbh->errstr;\n";
|
||||||
|
if ($sth->execute)
|
||||||
|
{
|
||||||
|
@row = $sth->fetchrow_array();
|
||||||
|
$sth->finish;
|
||||||
|
$sleep_time=5;
|
||||||
|
$dbh->do("flush tables $firsttable") || die "Got error on flush table: " . $dbh->errstr . "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
print "Warning; Got error from select: " . $dbh->errstr . "\n" if (! ($dbh->errstr =~ /doesn't exist/));
|
||||||
|
$sth->finish;
|
||||||
|
last if ($error_counter++ == 5);
|
||||||
|
$sleep_time=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dbh->disconnect; $dbh=0;
|
||||||
|
print "Test_select: ok\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
@ -67,7 +67,7 @@ $errors=0;
|
|||||||
while (($pid=wait()) != -1)
|
while (($pid=wait()) != -1)
|
||||||
{
|
{
|
||||||
$ret=$?/256;
|
$ret=$?/256;
|
||||||
print "thread '" . $work{$pid} . "' finnished with exit code $ret\n";
|
print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
|
||||||
$errors++ if ($ret != 0);
|
$errors++ if ($ret != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
204
tests/rename_test.pl
Executable file
204
tests/rename_test.pl
Executable file
@ -0,0 +1,204 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
#
|
||||||
|
# This is a test with uses processes to insert, select and drop tables.
|
||||||
|
#
|
||||||
|
|
||||||
|
$opt_loop_count=100000; # Change this to make test harder/easier
|
||||||
|
|
||||||
|
##################### Standard benchmark inits ##############################
|
||||||
|
|
||||||
|
use DBI;
|
||||||
|
use Getopt::Long;
|
||||||
|
use Benchmark;
|
||||||
|
|
||||||
|
package main;
|
||||||
|
|
||||||
|
$opt_skip_create=$opt_skip_delete=$opt_skip_flush=0;
|
||||||
|
$opt_host=""; $opt_db="test";
|
||||||
|
|
||||||
|
GetOptions("host=s","db=s","loop-count=i","skip-create","skip-delete",
|
||||||
|
"skip-flush") || die "Aborted";
|
||||||
|
|
||||||
|
print "Testing 5 multiple connections to a server with 1 insert, 1 rename\n";
|
||||||
|
print "1 select and 1 flush thread\n";
|
||||||
|
|
||||||
|
$firsttable = "bench_f1";
|
||||||
|
|
||||||
|
####
|
||||||
|
#### Start timing and start test
|
||||||
|
####
|
||||||
|
|
||||||
|
$start_time=new Benchmark;
|
||||||
|
if (!$opt_skip_create)
|
||||||
|
{
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
$dbh->do("drop table if exists $firsttable, ${firsttable}_1, ${firsttable}_2");
|
||||||
|
|
||||||
|
print "Creating table $firsttable in database $opt_db\n";
|
||||||
|
$dbh->do("create table $firsttable (id int(6) not null, info varchar(32), marker char(1), primary key(id))") || die $DBI::errstr;
|
||||||
|
$dbh->disconnect; $dbh=0; # Close handler
|
||||||
|
}
|
||||||
|
$|= 1; # Autoflush
|
||||||
|
|
||||||
|
####
|
||||||
|
#### Start the tests
|
||||||
|
####
|
||||||
|
|
||||||
|
test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
|
||||||
|
test_rename(1) if (($pid=fork()) == 0); $work{$pid}="rename 1";
|
||||||
|
test_rename(2) if (($pid=fork()) == 0); $work{$pid}="rename 2";
|
||||||
|
test_select() if (($pid=fork()) == 0); $work{$pid}="select";
|
||||||
|
if (!$opt_skip_flush)
|
||||||
|
{
|
||||||
|
test_flush() if (($pid=fork()) == 0); $work{$pid}="flush";
|
||||||
|
}
|
||||||
|
$errors=0;
|
||||||
|
while (($pid=wait()) != -1)
|
||||||
|
{
|
||||||
|
$ret=$?/256;
|
||||||
|
print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
|
||||||
|
$errors++ if ($ret != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$opt_skip_delete && !$errors)
|
||||||
|
{
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
$dbh->do("drop table $firsttable");
|
||||||
|
$dbh->disconnect; $dbh=0; # Close handler
|
||||||
|
}
|
||||||
|
print ($errors ? "Test failed\n" :"Test ok\n");
|
||||||
|
|
||||||
|
$end_time=new Benchmark;
|
||||||
|
print "Total time: " .
|
||||||
|
timestr(timediff($end_time, $start_time),"noc") . "\n";
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
#
|
||||||
|
# Insert records in the table. Delete table when test is finnished
|
||||||
|
#
|
||||||
|
|
||||||
|
sub test_insert
|
||||||
|
{
|
||||||
|
my ($dbh,$i,$error);
|
||||||
|
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
for ($i=0 ; $i < $opt_loop_count; $i++)
|
||||||
|
{
|
||||||
|
if (!$dbh->do("insert into $firsttable values ($i,'This is entry $i','')"))
|
||||||
|
{
|
||||||
|
$error=$dbh->errstr;
|
||||||
|
$dbh->do("drop table ${firsttable}"); # End other threads
|
||||||
|
die "Warning; Got error on insert: " . $error . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sleep(1);
|
||||||
|
$dbh->do("drop table ${firsttable}") || die "Got error on drop table: " . $dbh->errstr . "\n";
|
||||||
|
$dbh->disconnect; $dbh=0;
|
||||||
|
print "Test_insert: Inserted $i rows\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub test_rename
|
||||||
|
{
|
||||||
|
my ($id) = @_;
|
||||||
|
my ($dbh,$i,$error_counter,$sleep_time);
|
||||||
|
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
$error_counter=0;
|
||||||
|
$sleep_time=2;
|
||||||
|
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||||
|
{
|
||||||
|
sleep($sleep_time);
|
||||||
|
$dbh->do("create table ${firsttable}_$id (id int(6) not null, info varchar(32), marker char(1), primary key(id))") || die $DBI::errstr;
|
||||||
|
if (!$dbh->do("rename table $firsttable to ${firsttable}_${id}_1, ${firsttable}_$id to ${firsttable}"))
|
||||||
|
{
|
||||||
|
last if ($dbh->errstr =~ /^Can\'t find/);
|
||||||
|
die "Got error on rename: " . $dbh->errstr . "\n";
|
||||||
|
}
|
||||||
|
$dbh->do("drop table ${firsttable}_${id}_1") || die "Got error on drop table: " . $dbh->errstr . "\n";
|
||||||
|
}
|
||||||
|
$dbh->disconnect; $dbh=0;
|
||||||
|
print "Test_drop: Did a drop $i times\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# select records
|
||||||
|
#
|
||||||
|
|
||||||
|
sub test_select
|
||||||
|
{
|
||||||
|
my ($dbh,$i,$sth,@row,$sleep_time);
|
||||||
|
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
|
||||||
|
$sleep_time=3;
|
||||||
|
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||||
|
{
|
||||||
|
sleep($sleep_time);
|
||||||
|
$sth=$dbh->prepare("select sum(t.id) from $firsttable as t,$firsttable as t2") || die "Got error on select: $dbh->errstr;\n";
|
||||||
|
if ($sth->execute)
|
||||||
|
{
|
||||||
|
@row = $sth->fetchrow_array();
|
||||||
|
$sth->finish;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sth->finish;
|
||||||
|
last if (! ($dbh->errstr =~ /doesn\'t exist/));
|
||||||
|
die "Got error on select: " . $dbh->errstr . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dbh->disconnect; $dbh=0;
|
||||||
|
print "Test_select: ok\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# flush records
|
||||||
|
#
|
||||||
|
|
||||||
|
sub test_flush
|
||||||
|
{
|
||||||
|
my ($dbh,$i,$sth,@row,$error_counter,$sleep_time);
|
||||||
|
|
||||||
|
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
|
||||||
|
$opt_user, $opt_password,
|
||||||
|
{ PrintError => 0}) || die $DBI::errstr;
|
||||||
|
|
||||||
|
$error_counter=0;
|
||||||
|
$sleep_time=5;
|
||||||
|
for ($i=0 ; $i < $opt_loop_count ; $i++)
|
||||||
|
{
|
||||||
|
sleep($sleep_time);
|
||||||
|
$sth=$dbh->prepare("select count(*) from $firsttable") || die "Got error on prepar: $dbh->errstr;\n";
|
||||||
|
if ($sth->execute)
|
||||||
|
{
|
||||||
|
@row = $sth->fetchrow_array();
|
||||||
|
$sth->finish;
|
||||||
|
$sleep_time=5;
|
||||||
|
$dbh->do("flush tables $firsttable") || die "Got error on flush table: " . $dbh->errstr . "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last if (! ($dbh->errstr =~ /doesn\'t exist/));
|
||||||
|
die "Got error on flush: " . $dbh->errstr . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dbh->disconnect; $dbh=0;
|
||||||
|
print "Test_select: ok\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
Reference in New Issue
Block a user