Commit 1f340779 authored by unknown's avatar unknown

Merge jcole@work.mysql.com:/home/bk/mysql

into ham.spaceapes.com:/usr/home/jcole/bk/mysql


Docs/manual.texi:
  Auto merged
parents 542e7e57 a6ec1f09
...@@ -4,7 +4,7 @@ make -k clean ...@@ -4,7 +4,7 @@ make -k clean
/bin/rm -f config.cache mysql-*.tar.gz /bin/rm -f config.cache mysql-*.tar.gz
aclocal; autoheader; aclocal; automake; autoconf aclocal; autoheader; aclocal; automake; autoconf
CC=ccc CFLAGS="-fast -O3 -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti -mcpu=ev6 -Wa,-mev6" CXXLDFLAGS='/usr/lib/compaq/libots-2.2.7/libots.so /usr/lib/compaq/cpml-5.0.0/libcpml_ev6.a' ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex CC=ccc CFLAGS="-fast -O3 -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti -mcpu=ev6 -Wa,-mev6" CXXLDFLAGS='/usr/lib/compaq/libots-2.2.7/libots.so /usr/lib/compaq/cpml-5.0.0/libcpml_ev6.a' ./configure --prefix=/usr/local/mysql --disable-shared --with-extra-charsets=complex --enable-thread-safe-client
make make
if [ $? = 0 ] if [ $? = 0 ]
then then
......
Mail by sasha, should be rewritten as a HOWTO sometimes
-----------
I have set up a repository with BitKeeper on work. There are still some things
about it that I would like to learn, but I have gotten far enough with it to
replace CVS functionality were are currently using, so let's just go ahead and
get started on it. Please follow the instructions below (make sure to save the
message for future reference):
a) http://www.bitmover.com/download
user: beta
password: get bitkeeper
get the version appropriate for your platform - download it to a temp
directory, chmod +x and then run it. You will have to tell it which directory
to install, for consistency, let's use /usr/local/bin
b) we will take advantage of bk capablity of working with master/slave
repositories. The master will be on work.mysql.com, the slaves will be our
individual machines. The master repository has already been set up on work, so
you will need just to set up a slave repository on your machine:
mkdir bk
cd bk
bk clone yourusername@work:/home/bk/mysql mysql
cd mysql
bk -r edit
Now you have the entire source tree in the current directory. Let's compile it:
BUILD/compile-pentium-debug
After you edit a file, you need to check it in using bk citool or bk ci
filename. Note that ci is different than commit - you ci a file, but you commit
a change set. This is a very nice concept - instead of thinking of each
individual file as CVS does, bk groups the changes you are making and allows you
to document what you actually did between the commits as a whole, rather than
just commenting on every file. When you commit, bk will ask you to comment on
the change set.
Commit is done just to your local repository. To make your changes global, you
will need to run bk push. Be careful with that - it is a good idea to run bk
push -l -n first too see what you are just about to push to the master
repository.
When somebody does a push, you will be getting a email ( I will set this up to
day). You will then need to execute bk pull to update your sources. If there are
any conflicts, bk will force you to resolve them by asking you questions on what
to do with each conflict.
To learn more about bk, use bk helptool - I will be doing this a lot in the next
couple of days :-) If you find bugs or have questions/feature
suggestions/comments for developers, feel free to e-mail dev@bitmover.com .
Their developers, and especially the president of the company Larry McCoy really
like MySQL and are very anxious to help us. Make sure it is obvious that you
work for MySQL, of course. And, of course, do not bug them with little things
that you can figure out on your own or with my help - they were nice to offer us
support, but we should not abuse it.
If you are working on 3.23 MySQL source, please make sure to convert to bk ASAP
before you do any further developement - otherwise, things will get
exponentially worse as the code mass increases. I will work on mysql-4.0 next
and try to set it up so that when we update 3.23 source tree, the update makes
it to mysql-4.0.
...@@ -143,6 +143,65 @@ same tables. ...@@ -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
......
This diff is collapsed.
...@@ -26,7 +26,7 @@ SUBDIRS = include @docs_dirs@ @readline_dir@ @sql_client_dirs@ \ ...@@ -26,7 +26,7 @@ SUBDIRS = include @docs_dirs@ @readline_dir@ @sql_client_dirs@ \
@bench_dirs@ support-files @bench_dirs@ support-files
# Relink after clean # Relink after clean
CLEANFILES = linked_client_sources linked_server_sources CLEANFILES = linked_client_sources linked_server_sources linked_libmysql_sources linked_libmysql_r_sources
# This is just so that the linking is done early. # This is just so that the linking is done early.
config.h: linked_client_sources linked_server_sources config.h: linked_client_sources linked_server_sources
...@@ -36,9 +36,11 @@ linked_client_sources: @linked_client_targets@ ...@@ -36,9 +36,11 @@ linked_client_sources: @linked_client_targets@
linked_libmysql_sources: linked_libmysql_sources:
cd libmysql; $(MAKE) link_sources cd libmysql; $(MAKE) link_sources
echo timestamp > linked_libmysql_sources
linked_libmysql_r_sources: linked_libmysql_sources linked_libmysql_r_sources: linked_libmysql_sources
cd libmysql_r; $(MAKE) link_sources cd libmysql_r; $(MAKE) link_sources
echo timestamp > linked_libmysql_r_sources
#avoid recursive make calls in sql directory #avoid recursive make calls in sql directory
linked_server_sources: linked_server_sources:
......
...@@ -114,7 +114,7 @@ static bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0, ...@@ -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 { ...@@ -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[]) ...@@ -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[] = ...@@ -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[] = { ...@@ -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.11 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,18 @@ static void usage(int version) ...@@ -426,11 +427,18 @@ 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 (;) Since version 10.9 the\n\
client now starts with this option ENABLED by\n\
default! Disable with '-G'. Long format commands\n\
still work from the first line.\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 +494,7 @@ static int get_options(int argc, char **argv) ...@@ -486,7 +494,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 +573,7 @@ static int get_options(int argc, char **argv) ...@@ -565,6 +573,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;
...@@ -682,12 +691,12 @@ static int read_lines(bool execute_commands) ...@@ -682,12 +691,12 @@ static int read_lines(bool execute_commands)
if (!in_string && (line[0] == '#' || if (!in_string && (line[0] == '#' ||
(line[0] == '-' && line[1] == '-') || (line[0] == '-' && line[1] == '-') ||
line[0] == 0)) line[0] == 0))
continue; // Skipp comment lines continue; // Skip comment lines
/* Check if line is a mysql command line */ /* Check if line is a mysql command line */
/* (We want to allow help, print and clear anywhere at line start */ /* (We want to allow help, print and clear anywhere at line start */
if (execute_commands && !no_named_cmds && !in_string && if (execute_commands && (!no_named_cmds || glob_buffer.is_empty())
(com=find_command(line,0))) && !in_string && (com=find_command(line,0)))
{ {
if ((*com->func)(&glob_buffer,line) > 0) if ((*com->func)(&glob_buffer,line) > 0)
break; break;
...@@ -1171,11 +1180,13 @@ com_help (String *buffer __attribute__((unused)), ...@@ -1171,11 +1180,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 @@ ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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);
......
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
......
...@@ -46,7 +46,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \ ...@@ -46,7 +46,7 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \
mi_delete_table.c mi_rename.c mi_check.c \ mi_delete_table.c mi_rename.c mi_check.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?.MY? FT?.MY? isam.log mi_test_all
DEFS = -DMAP_TO_USE_RAID DEFS = -DMAP_TO_USE_RAID
# Omit dependency for ../mit-pthreads/include/sys that only exits if # Omit dependency for ../mit-pthreads/include/sys that only exits if
# mit-pthreads are used # mit-pthreads are used
......
...@@ -48,7 +48,7 @@ int ft_init_stopwords(const char **sws) ...@@ -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);
......
...@@ -16,8 +16,7 @@ ...@@ -16,8 +16,7 @@
/* Descript, check and repair of ISAM tables */ /* Descript, check and repair of ISAM tables */
#include "myisamdef.h" #include "fulltext.h"
#include <m_ctype.h> #include <m_ctype.h>
#include <stdarg.h> #include <stdarg.h>
#include <getopt.h> #include <getopt.h>
......
...@@ -147,3 +147,26 @@ void _mi_print_key(FILE *stream, register MI_KEYSEG *keyseg, ...@@ -147,3 +147,26 @@ void _mi_print_key(FILE *stream, register MI_KEYSEG *keyseg,
VOID(fputs("\"\n",stream)); VOID(fputs("\"\n",stream));
return; return;
} /* print_key */ } /* print_key */
#ifdef EXTRA_DEBUG
my_bool check_table_is_closed(const char *name, const char *where)
{
char filename[FN_REFLEN];
LIST *pos;
(void) fn_format(filename,name,"",MI_NAME_IEXT,4+16+32);
for (pos=myisam_open_list ; pos ; pos=pos->next)
{
MI_INFO *info=(MI_INFO*) pos->data;
MYISAM_SHARE *share=info->s;
if (!strcmp(share->filename,filename))
{
fprintf(stderr,"Warning: Table: %s is open on %s\n", name,where);
return 1;
}
}
return 0;
}
#endif /* EXTRA_DEBUG */
...@@ -30,6 +30,10 @@ int mi_delete_table(const char *name) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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); ...@@ -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" {
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key, int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key,
uint key_len, enum ha_rkey_function search_flag) uint key_len, enum ha_rkey_function search_flag)
{ {
uchar *key_buff; byte *key_buff;
uint pack_key_length; uint pack_key_length;
MYRG_TABLE *table; MYRG_TABLE *table;
MI_INFO *mi; MI_INFO *mi;
...@@ -45,7 +45,7 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key, ...@@ -45,7 +45,7 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key,
if (table == info->open_tables) if (table == info->open_tables)
{ {
err=mi_rkey(mi,buf,inx,key,key_len,search_flag); err=mi_rkey(mi,buf,inx,key,key_len,search_flag);
key_buff=mi->lastkey+mi->s->base.max_key_length; key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length;
pack_key_length=mi->last_rkey_length; pack_key_length=mi->last_rkey_length;
} }
else else
......
...@@ -24,7 +24,7 @@ int myrg_rnext(MYRG_INFO *info, byte *buf, int inx) ...@@ -24,7 +24,7 @@ int myrg_rnext(MYRG_INFO *info, byte *buf, int inx)
{ {
MYRG_TABLE *table; MYRG_TABLE *table;
MI_INFO *mi; MI_INFO *mi;
uchar *key_buff; byte *key_buff;
uint pack_key_length; uint pack_key_length;
int err; int err;
...@@ -50,7 +50,7 @@ int myrg_rnext(MYRG_INFO *info, byte *buf, int inx) ...@@ -50,7 +50,7 @@ int myrg_rnext(MYRG_INFO *info, byte *buf, int inx)
if (table < info->end_table) if (table < info->end_table)
{ {
mi=info->last_used_table->table; mi=info->last_used_table->table;
key_buff=mi->lastkey+mi->s->base.max_key_length; key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length;
pack_key_length=mi->last_rkey_length; pack_key_length=mi->last_rkey_length;
for (; table < info->end_table ; table++) for (; table < info->end_table ; table++)
{ {
......
...@@ -24,7 +24,7 @@ int myrg_rprev(MYRG_INFO *info, byte *buf, int inx) ...@@ -24,7 +24,7 @@ int myrg_rprev(MYRG_INFO *info, byte *buf, int inx)
{ {
MYRG_TABLE *table; MYRG_TABLE *table;
MI_INFO *mi; MI_INFO *mi;
uchar *key_buff; byte *key_buff;
uint pack_key_length; uint pack_key_length;
int err; int err;
...@@ -50,12 +50,13 @@ int myrg_rprev(MYRG_INFO *info, byte *buf, int inx) ...@@ -50,12 +50,13 @@ int myrg_rprev(MYRG_INFO *info, byte *buf, int inx)
if (table < info->end_table) if (table < info->end_table)
{ {
mi=info->last_used_table->table; mi=info->last_used_table->table;
key_buff=mi->lastkey+mi->s->base.max_key_length; key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length;
pack_key_length=mi->last_rkey_length; pack_key_length=mi->last_rkey_length;
for (; table < info->end_table ; table++) for (; table < info->end_table ; table++)
{ {
mi=table->table; mi=table->table;
err=_mi_rkey(mi,NULL,inx,key_buff,pack_key_length,HA_READ_KEY_OR_PREV,FALSE); err=_mi_rkey(mi,NULL,inx,key_buff,pack_key_length,
HA_READ_KEY_OR_PREV,FALSE);
info->last_used_table=table; info->last_used_table=table;
if (err == HA_ERR_KEY_NOT_FOUND) if (err == HA_ERR_KEY_NOT_FOUND)
......
...@@ -193,7 +193,9 @@ static my_bool init_available_charsets(myf myflags) ...@@ -193,7 +193,9 @@ static my_bool init_available_charsets(myf myflags)
charset_initialized=1; charset_initialized=1;
pthread_mutex_unlock(&THR_LOCK_charset); pthread_mutex_unlock(&THR_LOCK_charset);
} }
return error || !available_charsets[0]; if(!available_charsets || !available_charsets[0])
error = TRUE;
return error;
} }
...@@ -467,6 +469,7 @@ char * list_charsets(myf want_flags) ...@@ -467,6 +469,7 @@ char * list_charsets(myf want_flags)
DYNAMIC_STRING s; DYNAMIC_STRING s;
char *p; char *p;
(void)init_available_charsets(MYF(0));
init_dynamic_string(&s, NullS, 256, 1024); init_dynamic_string(&s, NullS, 256, 1024);
if (want_flags & MY_COMPILED_SETS) if (want_flags & MY_COMPILED_SETS)
...@@ -485,16 +488,17 @@ char * list_charsets(myf want_flags) ...@@ -485,16 +488,17 @@ char * list_charsets(myf want_flags)
char buf[FN_REFLEN]; char buf[FN_REFLEN];
MY_STAT stat; MY_STAT stat;
for (c = available_charsets; *c; ++c) if((c=available_charsets))
{ for (; *c; ++c)
if (charset_in_string((*c)->name, &s)) {
continue; if (charset_in_string((*c)->name, &s))
get_charset_conf_name((*c)->number, buf); continue;
if (!my_stat(buf, &stat, MYF(0))) get_charset_conf_name((*c)->number, buf);
continue; /* conf file doesn't exist */ if (!my_stat(buf, &stat, MYF(0)))
dynstr_append(&s, (*c)->name); continue; /* conf file doesn't exist */
dynstr_append(&s, " "); dynstr_append(&s, (*c)->name);
} dynstr_append(&s, " ");
}
} }
if (want_flags & MY_INDEX_SETS) if (want_flags & MY_INDEX_SETS)
......
...@@ -48,7 +48,7 @@ rm $BASE/include/Makefile*; rm $BASE/include/*.in ...@@ -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) ...@@ -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 ...@@ -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) ...@@ -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 @@ class handler :public Sql_alloc ...@@ -200,7 +200,7 @@ class handler :public Sql_alloc
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();
......
...@@ -407,15 +407,17 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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,13 +225,14 @@ static void mc_free_old_query(MYSQL *mysql) ...@@ -225,13 +225,14 @@ 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);
#else #else
int flags, res, s_err; int flags, res, s_err;
socklen_t s_err_size = sizeof(uint); size_socket s_err_size = sizeof(uint);
fd_set sfds; fd_set sfds;
struct timeval tv; struct timeval tv;
...@@ -451,7 +452,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, ...@@ -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;
......
...@@ -127,7 +127,7 @@ void sql_element_free(void *ptr); ...@@ -127,7 +127,7 @@ void sql_element_free(void *ptr);
#define TEST_NO_THREADS 32 /* For debugging under Linux */ #define TEST_NO_THREADS 32 /* For debugging under Linux */
#define TEST_READCHECK 64 /* Force use of readcheck */ #define TEST_READCHECK 64 /* Force use of readcheck */
#define TEST_NO_EXTRA 128 #define TEST_NO_EXTRA 128
#define TEST_KILL_ON_DEBUG 256 /* Kill server */ #define TEST_CORE_ON_SIGNAL 256 /* Give core if signal */
/* options for select set by the yacc parser */ /* options for select set by the yacc parser */
#define SELECT_DISTINCT 1 #define SELECT_DISTINCT 1
...@@ -319,10 +319,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias, ...@@ -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);
......
...@@ -1003,6 +1003,20 @@ static void init_signals(void) ...@@ -1003,6 +1003,20 @@ static void init_signals(void)
} }
#else #else
#ifdef HAVE_LINUXTHREADS
/* Produce a core for the thread */
static sig_handler write_core(int sig)
{
fprintf(stderr,"Got signal %s in thread %d\n",sys_siglist[sig],getpid());
signal(sig, SIG_DFL);
if (fork() != 0) exit(1); // Abort main program
// Core will be written at exit
}
#endif
static void init_signals(void) static void init_signals(void)
{ {
sigset_t set; sigset_t set;
...@@ -1012,6 +1026,16 @@ static void init_signals(void) ...@@ -1012,6 +1026,16 @@ static void init_signals(void)
sigset(THR_KILL_SIGNAL,end_thread_signal); sigset(THR_KILL_SIGNAL,end_thread_signal);
sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called! sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
#ifdef HAVE_LINUXTHREADS
if (test_flags & TEST_CORE_ON_SIGNAL)
{
struct sigaction sa; sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
sa.sa_handler=write_core;
sigaction(SIGSEGV, &sa, NULL);
}
#endif
(void) sigemptyset(&set); (void) sigemptyset(&set);
#ifdef THREAD_SPECIFIC_SIGPIPE #ifdef THREAD_SPECIFIC_SIGPIPE
sigset(SIGPIPE,abort_thread); sigset(SIGPIPE,abort_thread);
...@@ -2134,7 +2158,7 @@ enum options {OPT_ISAM_LOG=256,OPT_SKIP_NEW,OPT_SKIP_GRANT, ...@@ -2134,7 +2158,7 @@ enum options {OPT_ISAM_LOG=256,OPT_SKIP_NEW,OPT_SKIP_GRANT,
OPT_MASTER_PORT, OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY, OPT_MASTER_PORT, OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY,
OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB, OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES, OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB}; OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB, OPT_WANT_CORE};
static struct option long_options[] = static struct option long_options[] =
{ {
...@@ -2156,6 +2180,7 @@ static struct option long_options[] = ...@@ -2156,6 +2180,7 @@ static struct option long_options[] =
#ifdef __WIN__ #ifdef __WIN__
{"console", no_argument, 0, OPT_CONSOLE}, {"console", no_argument, 0, OPT_CONSOLE},
#endif #endif
{"core-file", no_argument, 0, OPT_WANT_CORE},
{"chroot", required_argument,0, 'r'}, {"chroot", required_argument,0, 'r'},
{"character-sets-dir",required_argument,0, OPT_CHARSETS_DIR}, {"character-sets-dir",required_argument,0, OPT_CHARSETS_DIR},
{"datadir", required_argument, 0, 'h'}, {"datadir", required_argument, 0, 'h'},
...@@ -2188,8 +2213,10 @@ static struct option long_options[] = ...@@ -2188,8 +2213,10 @@ static struct option long_options[] =
{"master-connect-retry", required_argument, 0, (int) OPT_MASTER_CONNECT_RETRY}, {"master-connect-retry", required_argument, 0, (int) OPT_MASTER_CONNECT_RETRY},
{"master-info-file", required_argument, 0, (int) OPT_MASTER_INFO_FILE}, {"master-info-file", required_argument, 0, (int) OPT_MASTER_INFO_FILE},
{"new", no_argument, 0, 'n'}, {"new", no_argument, 0, 'n'},
{"old-protocol", no_argument, 0, 'o'}, {"old-protocol", no_argument, 0, 'o'},
#ifndef DBUG_OFF
{"one-thread", no_argument, 0, OPT_ONE_THREAD}, {"one-thread", no_argument, 0, OPT_ONE_THREAD},
#endif
{"pid-file", required_argument, 0, (int) OPT_PID_FILE}, {"pid-file", required_argument, 0, (int) OPT_PID_FILE},
{"port", required_argument, 0, 'P'}, {"port", required_argument, 0, 'P'},
{"replicate-do-db", required_argument, 0, OPT_REPLICATE_DO_DB}, {"replicate-do-db", required_argument, 0, OPT_REPLICATE_DO_DB},
...@@ -2407,6 +2434,12 @@ static void print_version(void) ...@@ -2407,6 +2434,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();
...@@ -2426,6 +2459,7 @@ static void usage(void) ...@@ -2426,6 +2459,7 @@ static void usage(void)
--character-sets-dir=...\n\ --character-sets-dir=...\n\
Directory where character sets are\n\ Directory where character sets are\n\
--chroot=path Chroot mysqld daemon during startup\n\ --chroot=path Chroot mysqld daemon during startup\n\
--core-file Write core on errors\n\
-h, --datadir=path Path to the database root"); -h, --datadir=path Path to the database root");
#ifndef DBUG_OFF #ifndef DBUG_OFF
printf("\ printf("\
...@@ -2454,11 +2488,17 @@ static void usage(void) ...@@ -2454,11 +2488,17 @@ static void usage(void)
--log-isam[=file] Log all isam changes to file\n\ --log-isam[=file] Log all isam changes to file\n\
--log-long-format Log some extra information to update log\n\ --log-long-format Log some extra information to update log\n\
--low-priority-updates INSERT/DELETE/UPDATE has lower priority than selects\n\ --low-priority-updates INSERT/DELETE/UPDATE has lower priority than selects\n\
--log-slow-queries=[file]\n\
Log slow queries to this log file\n\
--pid-file=path Pid file used by safe_mysqld\n\ --pid-file=path Pid file used by safe_mysqld\n\
-P, --port=... Port number to use for connection\n\ -P, --port=... Port number to use for connection\n\
-n, --new Use very new possible 'unsafe' functions\n\ -n, --new Use very new possible 'unsafe' functions\n\
-o, --old-protocol Use the old (3.20) protocol\n\ -o, --old-protocol Use the old (3.20) protocol\n");
--one-thread Only use one thread (for debugging under Linux)\n\ #ifndef DBUG_OFF
puts("\
--one-thread Only use one thread (for debugging under Linux)\n");
#endif
puts("\
-O, --set-variable var=option\n\ -O, --set-variable var=option\n\
Give a variable an value. --help lists variables\n\ Give a variable an value. --help lists variables\n\
-Sg, --skip-grant-tables\n\ -Sg, --skip-grant-tables\n\
...@@ -2621,7 +2661,7 @@ static void get_options(int argc,char **argv) ...@@ -2621,7 +2661,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 +2706,8 @@ static void get_options(int argc,char **argv) ...@@ -2666,7 +2706,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;
...@@ -2718,8 +2759,6 @@ static void get_options(int argc,char **argv) ...@@ -2718,8 +2759,6 @@ static void get_options(int argc,char **argv)
binlog_do_db.push_back(db); binlog_do_db.push_back(db);
break; break;
} }
case (int) OPT_SQL_BIN_UPDATE_SAME: case (int) OPT_SQL_BIN_UPDATE_SAME:
opt_sql_bin_update = 1; opt_sql_bin_update = 1;
break; break;
...@@ -2774,6 +2813,9 @@ static void get_options(int argc,char **argv) ...@@ -2774,6 +2813,9 @@ static void get_options(int argc,char **argv)
case (int) OPT_ONE_THREAD: case (int) OPT_ONE_THREAD:
test_flags |= TEST_NO_THREADS; test_flags |= TEST_NO_THREADS;
break; break;
case (int) OPT_WANT_CORE:
test_flags |= TEST_CORE_ON_SIGNAL;
break;
case (int) OPT_BIND_ADDRESS: case (int) OPT_BIND_ADDRESS:
if (optarg && isdigit(optarg[0])) if (optarg && isdigit(optarg[0]))
{ {
...@@ -2910,7 +2952,7 @@ static void get_options(int argc,char **argv) ...@@ -2910,7 +2952,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 +2962,7 @@ static void get_options(int argc,char **argv) ...@@ -2920,7 +2962,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 @@ ...@@ -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() ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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)
{ {
(void) pthread_cond_wait(&COND_refresh,&LOCK_open); 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);
} }
if (thd->killed) if (thd->killed)
result= 1; // aborted result= 1; // aborted
else else
......
...@@ -1137,16 +1137,21 @@ mysql_execute_command(void) ...@@ -1137,16 +1137,21 @@ mysql_execute_command(void)
goto error; goto error;
for (table=tables ; table ; table=table->next->next) for (table=tables ; table ; table=table->next->next)
{ {
if (check_access(thd, ALTER_ACL, table->db, &table->grant.privilege) || if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
&table->grant.privilege) ||
check_access(thd, INSERT_ACL | CREATE_ACL, table->next->db, check_access(thd, INSERT_ACL | CREATE_ACL, table->next->db,
&table->next->grant.privilege)) &table->next->grant.privilege))
goto error; goto error;
if (grant_option) if (grant_option)
{ {
if (check_grant(thd,ALTER_ACL,table) || TABLE_LIST old_list,new_list;
old_list=table[0];
new_list=table->next[0];
old_list.next=new_list.next=0;
if (check_grant(thd,ALTER_ACL,&old_list) ||
(!test_all_bits(table->next->grant.privilege, (!test_all_bits(table->next->grant.privilege,
INSERT_ACL | CREATE_ACL) && INSERT_ACL | CREATE_ACL) &&
check_grant(thd,INSERT_ACL | CREATE_ACL, table->next))) check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list)))
goto error; goto error;
} }
} }
...@@ -1170,9 +1175,8 @@ mysql_execute_command(void) ...@@ -1170,9 +1175,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 +1699,10 @@ mysql_execute_command(void) ...@@ -1695,6 +1699,10 @@ mysql_execute_command(void)
** 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 +1768,8 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables) ...@@ -1760,7 +1768,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)
{ {
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include <assert.h> #include <assert.h>
const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref", const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
"MAYBE_REF","ALL","range","index" }; "MAYBE_REF","ALL","range","index","fulltext" };
static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DYNAMIC_ARRAY *keyuse,List<Item_func_match> &ftfuncs); DYNAMIC_ARRAY *keyuse,List<Item_func_match> &ftfuncs);
...@@ -800,6 +800,14 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, ...@@ -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;
...@@ -1272,15 +1280,54 @@ static void ...@@ -1272,15 +1280,54 @@ static void
add_ft_keys(DYNAMIC_ARRAY *keyuse_array, add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
JOIN_TAB *stat,COND *cond,table_map usable_tables) JOIN_TAB *stat,COND *cond,table_map usable_tables)
{ {
/* for now, handling only the simples WHERE MATCH (...) case */ Item_func_match *cond_func=NULL;
/* a bit more complex WHERE MATCH (...) > const,
AND's and (perhaps) OR's are on the way SerG */ if (cond->type() == Item::FUNC_ITEM)
{
Item_func *func=(Item_func *)cond,
*arg0=(Item_func *)(func->arguments()[0]),
*arg1=(Item_func *)(func->arguments()[1]);
if (func->functype() == Item_func::FT_FUNC)
cond_func=(Item_func_match *)cond;
else if (arg0->type() == Item::FUNC_ITEM &&
arg0->functype() == Item_func::FT_FUNC &&
(func->functype() == Item_func::GE_FUNC ||
func->functype() == Item_func::GT_FUNC) &&
arg1->const_item() && arg1->val()>=0)
cond_func=(Item_func_match *)arg0;
else if (arg1->type() == Item::FUNC_ITEM &&
arg1->functype() == Item_func::FT_FUNC &&
(func->functype() == Item_func::LE_FUNC ||
func->functype() == Item_func::LT_FUNC) &&
arg0->const_item() && arg0->val()>=0)
cond_func=(Item_func_match *)arg1;
}
else if (cond->type() == Item::COND_ITEM)
{
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
if (cond->type() != Item::FUNC_ITEM || if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
((Item_func*) cond)->functype() != Item_func::FT_FUNC) {
return; Item *item;
/* I'm too lazy to implement proper recursive descent here,
and anyway, nobody will use such a stupid queries
that will require it :-)
May be later...
*/
while ((item=li++))
if (item->type() == Item::FUNC_ITEM &&
((Item_func *)item)->functype() == Item_func::FT_FUNC)
{
cond_func=(Item_func_match *)item;
break;
}
}
}
if(!cond_func)
return;
Item_func_match *cond_func= (Item_func_match *) cond;
KEYUSE keyuse; KEYUSE keyuse;
keyuse.table= cond_func->table; keyuse.table= cond_func->table;
...@@ -1928,8 +1975,7 @@ get_best_combination(JOIN *join) ...@@ -1928,8 +1975,7 @@ get_best_combination(JOIN *join)
if (ftkey) if (ftkey)
{ {
j->ref.items[0]=((Item_func*)(keyuse->val))->key_item(); j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
if (!keyuse->used_tables && if (!keyuse->used_tables)
!(join->select_options & SELECT_DESCRIBE))
{ {
// AFAIK key_buff is zeroed... // AFAIK key_buff is zeroed...
// We don't need to free ft_tmp as the buffer will be freed atom. // We don't need to free ft_tmp as the buffer will be freed atom.
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
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 */
...@@ -488,7 +488,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) ...@@ -488,7 +488,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
if (send_fields(thd,field_list,1)) if (send_fields(thd,field_list,1))
DBUG_RETURN(1); DBUG_RETURN(1);
String *packet = &thd->packet; String *packet = &thd->packet;
for(;table; table = table->next) for(;table; table = table->next)
{ {
...@@ -510,7 +510,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) ...@@ -510,7 +510,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
// into fewer, so we cannot use net_store_data() anymore, // into fewer, so we cannot use net_store_data() anymore,
// and do it ourselves // and do it ourselves
char* p = (char*)packet->ptr() + store_len_offset; char* p = (char*)packet->ptr() + store_len_offset;
*p++ = (char) 253; // The client the length is stored using 3-bytes *p++ = (char) 253; // The client the length is stored using 3-bytes
int3store(p, create_len); int3store(p, create_len);
// now we are in business :-) // now we are in business :-)
...@@ -649,10 +649,10 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) ...@@ -649,10 +649,10 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
DBUG_PRINT("enter",("table: %s",table->real_name)); DBUG_PRINT("enter",("table: %s",table->real_name));
String* packet = &thd->packet; String* packet = &thd->packet;
packet->length(0); packet->length(0);
if(store_create_info(thd,table,packet)) if(store_create_info(thd,table,packet))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if(fd < 0) if(fd < 0)
{ {
if(my_net_write(&thd->net, (char*)packet->ptr(), packet->length())) if(my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
...@@ -661,14 +661,14 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) ...@@ -661,14 +661,14 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
} }
else else
{ {
if(my_write(fd, (const byte*) packet->ptr(), packet->length(), if(my_write(fd, (const byte*) packet->ptr(), packet->length(),
MYF(MY_WME))) MYF(MY_WME)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
} }
static int static int
store_create_info(THD *thd, TABLE *table, String* packet) store_create_info(THD *thd, TABLE *table, String* packet)
{ {
...@@ -676,37 +676,37 @@ store_create_info(THD *thd, TABLE *table, String* packet) ...@@ -676,37 +676,37 @@ store_create_info(THD *thd, TABLE *table, String* packet)
DBUG_PRINT("enter",("table: %s",table->real_name)); DBUG_PRINT("enter",("table: %s",table->real_name));
restore_record(table,2); // Get empty record restore_record(table,2); // Get empty record
List<Item> field_list; List<Item> field_list;
char tmp[MAX_FIELD_WIDTH]; char tmp[MAX_FIELD_WIDTH];
String type(tmp, sizeof(tmp)); String type(tmp, sizeof(tmp));
packet->append("create table ", 13); packet->append("create table ", 13);
packet->append(table->real_name); packet->append(table->real_name);
packet->append('('); packet->append('(');
Field **ptr,*field; Field **ptr,*field;
for (ptr=table->field ; (field= *ptr); ptr++) for (ptr=table->field ; (field= *ptr); ptr++)
{ {
if(ptr != table->field) if(ptr != table->field)
packet->append(','); packet->append(',');
uint flags = field->flags; uint flags = field->flags;
packet->append(field->field_name); packet->append(field->field_name);
packet->append(' '); packet->append(' ');
// check for surprises from the previous call to Field::sql_type() // check for surprises from the previous call to Field::sql_type()
if(type.ptr() != tmp) if(type.ptr() != tmp)
type.set(tmp, sizeof(tmp)); type.set(tmp, sizeof(tmp));
field->sql_type(type); field->sql_type(type);
packet->append(type.ptr(),type.length()); packet->append(type.ptr(),type.length());
bool null_default_value = (field->type() == FIELD_TYPE_TIMESTAMP || bool null_default_value = (field->type() == FIELD_TYPE_TIMESTAMP ||
field->unireg_check == Field::NEXT_NUMBER); field->unireg_check == Field::NEXT_NUMBER);
bool has_default = (field->type() != FIELD_TYPE_BLOB); bool has_default = (field->type() != FIELD_TYPE_BLOB);
if((flags & NOT_NULL_FLAG) && !null_default_value) if((flags & NOT_NULL_FLAG) && !null_default_value)
packet->append(" not null", 9); packet->append(" not null", 9);
if(has_default) if(has_default)
{ {
...@@ -724,51 +724,54 @@ store_create_info(THD *thd, TABLE *table, String* packet) ...@@ -724,51 +724,54 @@ store_create_info(THD *thd, TABLE *table, String* packet)
else else
packet->append(tmp,0); packet->append(tmp,0);
} }
if (field->unireg_check == Field::NEXT_NUMBER) if (field->unireg_check == Field::NEXT_NUMBER)
packet->append(" auto_increment", 15 ); packet->append(" auto_increment", 15 );
} }
KEY *key_info=table->key_info; KEY *key_info=table->key_info;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
uint primary_key = table->primary_key; uint primary_key = table->primary_key;
for (uint i=0 ; i < table->keys ; i++,key_info++) for (uint i=0 ; i < table->keys ; i++,key_info++)
{ {
packet->append(','); packet->append(',');
KEY_PART_INFO *key_part= key_info->key_part; KEY_PART_INFO *key_part= key_info->key_part;
if(i == primary_key) if(i == primary_key)
packet->append("primary", 7); packet->append("primary", 7);
else if(key_info->flags & HA_NOSAME) else if(key_info->flags & HA_NOSAME)
packet->append("unique", 6); packet->append("unique", 6);
else if(key_info->flags & HA_FULLTEXT)
packet->append("fulltext", 8);
packet->append(" key ", 5); packet->append(" key ", 5);
if(i != primary_key) if(i != primary_key)
packet->append(key_info->name); packet->append(key_info->name);
packet->append('('); packet->append('(');
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{ {
if(j) if(j)
packet->append(','); packet->append(',');
if(key_part->field) if(key_part->field)
packet->append(key_part->field->field_name); packet->append(key_part->field->field_name);
KEY *key=table->key_info+i; KEY *key=table->key_info+i;
if (!key_part->field || if (!key_part->field ||
key_part->length != (key_part->length !=
table->field[key_part->fieldnr-1]->key_length()) table->field[key_part->fieldnr-1]->key_length() &&
!(key_info->flags & HA_FULLTEXT)))
{ {
char buff[64]; char buff[64];
buff[0] = '('; buff[0] = '(';
char* end=int10_to_str((long) key_part->length, buff + 1,10); char* end=int10_to_str((long) key_part->length, buff + 1,10);
*end++ = ')'; *end++ = ')';
packet->append(buff,(uint) (end-buff)); packet->append(buff,(uint) (end-buff));
} }
} }
...@@ -776,13 +779,13 @@ store_create_info(THD *thd, TABLE *table, String* packet) ...@@ -776,13 +779,13 @@ store_create_info(THD *thd, TABLE *table, String* packet)
} }
packet->append(')'); packet->append(')');
handler *file = table->file; handler *file = table->file;
packet->append(" type=", 6); packet->append(" type=", 6);
packet->append(file->table_type()); packet->append(file->table_type());
char buff[128]; char buff[128];
char* p; char* p;
if(table->min_rows) if(table->min_rows)
{ {
packet->append(" min_rows="); packet->append(" min_rows=");
...@@ -796,7 +799,7 @@ store_create_info(THD *thd, TABLE *table, String* packet) ...@@ -796,7 +799,7 @@ store_create_info(THD *thd, TABLE *table, String* packet)
p = longlong10_to_str(table->max_rows, buff, 10); p = longlong10_to_str(table->max_rows, buff, 10);
packet->append(buff, (uint) (p - buff)); packet->append(buff, (uint) (p - buff));
} }
if (table->db_create_options & HA_OPTION_PACK_KEYS) if (table->db_create_options & HA_OPTION_PACK_KEYS)
packet->append(" pack_keys=1", 12); packet->append(" pack_keys=1", 12);
if (table->db_create_options & HA_OPTION_NO_PACK_KEYS) if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
...@@ -806,7 +809,7 @@ store_create_info(THD *thd, TABLE *table, String* packet) ...@@ -806,7 +809,7 @@ store_create_info(THD *thd, TABLE *table, String* packet)
if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE) if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
packet->append(" delay_key_write=1",18); packet->append(" delay_key_write=1",18);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
......
...@@ -91,6 +91,7 @@ struct st_table { ...@@ -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;
......
#!/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; ...@@ -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);
} }
......
...@@ -40,9 +40,9 @@ $columns_cols="Host, Db, User, Table_name, Column_name, Column_priv"; ...@@ -40,9 +40,9 @@ $columns_cols="Host, Db, User, Table_name, Column_name, Column_priv";
# clear grant tables # clear grant tables
# #
$dbh = DBI->connect("DBI:mysql:mysql:$opt_host;mysql_read_default_group=perl", $dbh = DBI->connect("DBI:mysql:mysql:$opt_host",
$opt_root_user,$opt_password, $opt_root_user,$opt_password,
{ PrintError => 0}) || die "Can't connect to mysql server: $DBI::errstr\n"; { PrintError => 0}) || die "Can't connect to mysql server with user '$opt_root_user': $DBI::errstr\n";
safe_query("delete from user where user='$opt_user' or user='${opt_user}2'"); safe_query("delete from user where user='$opt_user' or user='${opt_user}2'");
safe_query("delete from db where user='$opt_user'"); safe_query("delete from db where user='$opt_user'");
...@@ -171,8 +171,7 @@ user_query("create table $opt_database.test2 (a int not null)"); ...@@ -171,8 +171,7 @@ user_query("create table $opt_database.test2 (a int not null)");
user_query("alter table $opt_database.test2 add b int"); user_query("alter table $opt_database.test2 add b int");
user_query("create index dummy on $opt_database.test2 (a)"); user_query("create index dummy on $opt_database.test2 (a)");
user_query("drop table $opt_database.test2"); user_query("drop table $opt_database.test2");
user_query("show tables"); user_query("show tables from grant_test");
# These should fail # These should fail
user_query("insert into mysql.user (host,user) values ('error','$opt_user',0)",1); user_query("insert into mysql.user (host,user) values ('error','$opt_user',0)",1);
...@@ -242,7 +241,22 @@ user_query("grant select on $opt_database.test2 to $user with grant option",1); ...@@ -242,7 +241,22 @@ user_query("grant select on $opt_database.test2 to $user with grant option",1);
safe_query("grant drop on $opt_database.test2 to $user with grant option"); safe_query("grant drop on $opt_database.test2 to $user with grant option");
user_query("grant drop on $opt_database.test2 to $user with grant option"); user_query("grant drop on $opt_database.test2 to $user with grant option");
user_query("grant select on $opt_database.test2 to $user with grant option",1); user_query("grant select on $opt_database.test2 to $user with grant option",1);
user_query("drop table $opt_database.test2");
# check rename privileges
user_query("rename table $opt_database.test2 to $opt_database.test3",1);
safe_query("grant CREATE,DROP on $opt_database.test3 to $user");
user_query("rename table $opt_database.test2 to $opt_database.test3",1);
user_query("create table $opt_database.test3 (a int)");
safe_query("grant INSERT on $opt_database.test3 to $user");
user_query("drop table $opt_database.test3");
user_query("rename table $opt_database.test2 to $opt_database.test3");
user_query("rename table $opt_database.test3 to $opt_database.test2",1);
safe_query("grant ALTER on $opt_database.test3 to $user");
user_query("rename table $opt_database.test3 to $opt_database.test2");
safe_query("revoke DROP on $opt_database.test2 from $user");
user_query("rename table $opt_database.test2 to $opt_database.test3");
user_query("drop table if exists $opt_database.test2,$opt_database.test3",1);
safe_query("drop table if exists $opt_database.test2,$opt_database.test3");
# Check that the user doesn't have some user privileges # Check that the user doesn't have some user privileges
user_query("create database $opt_database",1); user_query("create database $opt_database",1);
...@@ -253,9 +267,9 @@ safe_query("flush privileges"); ...@@ -253,9 +267,9 @@ safe_query("flush privileges");
safe_query("select $tables_cols from mysql.tables_priv"); safe_query("select $tables_cols from mysql.tables_priv");
safe_query("revoke ALL PRIVILEGES on $opt_database.test from $user"); safe_query("revoke ALL PRIVILEGES on $opt_database.test from $user");
safe_query("revoke ALL PRIVILEGES on $opt_database.test2 from $user"); safe_query("revoke ALL PRIVILEGES on $opt_database.test2 from $user");
safe_query("revoke ALL PRIVILEGES on $opt_database.test3 from $user");
safe_query("revoke GRANT OPTION on $opt_database.test2 from $user"); safe_query("revoke GRANT OPTION on $opt_database.test2 from $user");
safe_query("select $tables_cols from mysql.tables_priv"); safe_query("select $tables_cols from mysql.tables_priv");
user_query("select count(a) from test",1); user_query("select count(a) from test",1);
# #
...@@ -435,7 +449,8 @@ sub print_info ...@@ -435,7 +449,8 @@ sub print_info
my $tmp; my $tmp;
print <<EOF; print <<EOF;
This test will clear your table and column grant table and recreate the This test will clear your table and column grant table and recreate the
$opt_database database ! All privileges for $user will be destroyed ! $opt_database database !
All privileges for $user will be destroyed !
Don\'t run this test if you have done any GRANT commands that you want to keep! Don\'t run this test if you have done any GRANT commands that you want to keep!
EOF EOF
......
...@@ -119,7 +119,7 @@ Error in execute: Access denied for user: 'grant_user@localhost' to database 'gr ...@@ -119,7 +119,7 @@ Error in execute: Access denied for user: 'grant_user@localhost' to database 'gr
drop table grant_test.test drop table grant_test.test
Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
grant ALL PRIVILEGES on grant_test.* to grant_user2@localhost grant ALL PRIVILEGES on grant_test.* to grant_user2@localhost
Error in execute: Access denied for user: 'grant_user@localhost' (Using password: NO) Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
grant ALL PRIVILEGES on grant_test.* to grant_user@localhost WITH GRANT OPTION grant ALL PRIVILEGES on grant_test.* to grant_user@localhost WITH GRANT OPTION
Connecting grant_user Connecting grant_user
insert into grant_test.test values (5,0) insert into grant_test.test values (5,0)
...@@ -145,7 +145,9 @@ create table grant_test.test2 (a int not null) ...@@ -145,7 +145,9 @@ create table grant_test.test2 (a int not null)
alter table grant_test.test2 add b int alter table grant_test.test2 add b int
create index dummy on grant_test.test2 (a) create index dummy on grant_test.test2 (a)
drop table grant_test.test2 drop table grant_test.test2
show tables show tables from grant_test
test
insert into mysql.user (host,user) values ('error','grant_user',0) insert into mysql.user (host,user) values ('error','grant_user',0)
Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql' Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql'
revoke ALL PRIVILEGES on grant_test.* from grant_user@localhost revoke ALL PRIVILEGES on grant_test.* from grant_user@localhost
...@@ -239,7 +241,24 @@ grant drop on grant_test.test2 to grant_user@localhost with grant option ...@@ -239,7 +241,24 @@ grant drop on grant_test.test2 to grant_user@localhost with grant option
grant drop on grant_test.test2 to grant_user@localhost with grant option grant drop on grant_test.test2 to grant_user@localhost with grant option
grant select on grant_test.test2 to grant_user@localhost with grant option grant select on grant_test.test2 to grant_user@localhost with grant option
Error in execute: select command denied to user: 'grant_user@localhost' for table 'test2' Error in execute: select command denied to user: 'grant_user@localhost' for table 'test2'
drop table grant_test.test2 rename table grant_test.test2 to grant_test.test3
Error in execute: insert command denied to user: 'grant_user@localhost' for table 'test3'
grant CREATE,DROP on grant_test.test3 to grant_user@localhost
rename table grant_test.test2 to grant_test.test3
Error in execute: insert command denied to user: 'grant_user@localhost' for table 'test3'
create table grant_test.test3 (a int)
grant INSERT on grant_test.test3 to grant_user@localhost
drop table grant_test.test3
rename table grant_test.test2 to grant_test.test3
rename table grant_test.test3 to grant_test.test2
Error in execute: alter command denied to user: 'grant_user@localhost' for table 'test3'
grant ALTER on grant_test.test3 to grant_user@localhost
rename table grant_test.test3 to grant_test.test2
revoke DROP on grant_test.test2 from grant_user@localhost
rename table grant_test.test2 to grant_test.test3
drop table if exists grant_test.test2,grant_test.test3
Error in execute: drop command denied to user: 'grant_user@localhost' for table 'test2'
drop table if exists grant_test.test2,grant_test.test3
create database grant_test create database grant_test
Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test' Error in execute: Access denied for user: 'grant_user@localhost' to database 'grant_test'
drop database grant_test drop database grant_test
...@@ -248,15 +267,15 @@ flush tables ...@@ -248,15 +267,15 @@ flush tables
Error in execute: Access denied for user: 'grant_user@localhost' (Using password: NO) Error in execute: Access denied for user: 'grant_user@localhost' (Using password: NO)
flush privileges flush privileges
select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv
localhost grant_test grant_user test2 grant_user@localhost Update,Delete,Create,Drop,Grant,Index,Alter Insert localhost grant_test grant_user test2 root@localhost Update,Delete,Create,Grant,Index,Alter Insert
localhost grant_test grant_user test root@localhost Select,Insert,Update,Delete localhost grant_test grant_user test root@localhost Select,Insert,Update,Delete
localhost grant_test grant_user test3 root@localhost Insert,Create,Drop,Alter
revoke ALL PRIVILEGES on grant_test.test from grant_user@localhost revoke ALL PRIVILEGES on grant_test.test from grant_user@localhost
revoke ALL PRIVILEGES on grant_test.test2 from grant_user@localhost revoke ALL PRIVILEGES on grant_test.test2 from grant_user@localhost
revoke ALL PRIVILEGES on grant_test.test3 from grant_user@localhost
revoke GRANT OPTION on grant_test.test2 from grant_user@localhost revoke GRANT OPTION on grant_test.test2 from grant_user@localhost
select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv
localhost grant_test grant_user test2 root@localhost Grant,Index,Alter
select count(a) from test select count(a) from test
Error in execute: select command denied to user: 'grant_user@localhost' for table 'test' Error in execute: select command denied to user: 'grant_user@localhost' for table 'test'
delete from grant_test.test where a=2 delete from grant_test.test where a=2
...@@ -284,13 +303,10 @@ select a,A from test ...@@ -284,13 +303,10 @@ select a,A from test
7 7 7 7
select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv
localhost grant_test grant_user test2 root@localhost Grant,Index,Alter
localhost grant_test grant_user test root@localhost Delete Select,Update localhost grant_test grant_user test root@localhost Delete Select,Update
revoke ALL PRIVILEGES on grant_test.test from grant_user@localhost revoke ALL PRIVILEGES on grant_test.test from grant_user@localhost
select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv
localhost grant_test grant_user test2 root@localhost Grant,Index,Alter
revoke GRANT OPTION on grant_test.test from grant_user@localhost revoke GRANT OPTION on grant_test.test from grant_user@localhost
Error in execute: There is no such grant defined for user 'grant_user' on host 'localhost' on table 'test' Error in execute: There is no such grant defined for user 'grant_user' on host 'localhost' on table 'test'
grant select(a) on grant_test.test to grant_user@localhost grant select(a) on grant_test.test to grant_user@localhost
...@@ -328,7 +344,6 @@ Error in execute: select command denied to user: 'grant_user@localhost' for colu ...@@ -328,7 +344,6 @@ Error in execute: select command denied to user: 'grant_user@localhost' for colu
update test set b=3 where b > 0 update test set b=3 where b > 0
Error in execute: select command denied to user: 'grant_user@localhost' for column 'b' in table 'test' Error in execute: select command denied to user: 'grant_user@localhost' for column 'b' in table 'test'
select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv
localhost grant_test grant_user test2 root@localhost Grant,Index,Alter
localhost grant_test grant_user test root@localhost Select,Insert,Update localhost grant_test grant_user test root@localhost Select,Insert,Update
select Host, Db, User, Table_name, Column_name, Column_priv from mysql.columns_priv select Host, Db, User, Table_name, Column_name, Column_priv from mysql.columns_priv
...@@ -337,7 +352,6 @@ localhost grant_test grant_user test a Select ...@@ -337,7 +352,6 @@ localhost grant_test grant_user test a Select
revoke select(a), update (b) on grant_test.test from grant_user@localhost revoke select(a), update (b) on grant_test.test from grant_user@localhost
select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv
localhost grant_test grant_user test2 root@localhost Grant,Index,Alter
localhost grant_test grant_user test root@localhost Insert localhost grant_test grant_user test root@localhost Insert
select Host, Db, User, Table_name, Column_name, Column_priv from mysql.columns_priv select Host, Db, User, Table_name, Column_name, Column_priv from mysql.columns_priv
...@@ -355,7 +369,6 @@ insert into test (b) values (9) ...@@ -355,7 +369,6 @@ insert into test (b) values (9)
update test set b=6 where b > 0 update test set b=6 where b > 0
flush privileges flush privileges
select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv
localhost grant_test grant_user test2 root@localhost Grant,Index,Alter
localhost grant_test grant_user test root@localhost Select,Insert,Update localhost grant_test grant_user test root@localhost Select,Insert,Update
select Host, Db, User, Table_name, Column_name, Column_priv from mysql.columns_priv select Host, Db, User, Table_name, Column_name, Column_priv from mysql.columns_priv
...@@ -402,7 +415,6 @@ select * from mysql.db where user = 'grant_user' ...@@ -402,7 +415,6 @@ select * from mysql.db where user = 'grant_user'
localhost grant_test grant_user N Y N N N N N N N N localhost grant_test grant_user N Y N N N N N N N N
select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv where user = 'grant_user' select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv where user = 'grant_user'
localhost grant_test grant_user test2 root@localhost Grant,Index,Alter
localhost grant_test grant_user test root@localhost Select,Insert,Update localhost grant_test grant_user test root@localhost Select,Insert,Update
select Host, Db, User, Table_name, Column_name, Column_priv from mysql.columns_priv where user = 'grant_user' select Host, Db, User, Table_name, Column_name, Column_priv from mysql.columns_priv where user = 'grant_user'
...@@ -418,8 +430,6 @@ select * from mysql.db where user = 'grant_user' ...@@ -418,8 +430,6 @@ select * from mysql.db where user = 'grant_user'
localhost grant_test grant_user N Y N N N N N N N N localhost grant_test grant_user N Y N N N N N N N N
select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv where user = 'grant_user' select Host, Db, User, Table_name, Grantor, Table_priv, Column_priv from mysql.tables_priv where user = 'grant_user'
localhost grant_test grant_user test2 root@localhost Grant,Index,Alter
select Host, Db, User, Table_name, Column_name, Column_priv from mysql.columns_priv where user = 'grant_user' select Host, Db, User, Table_name, Column_name, Column_priv from mysql.columns_priv where user = 'grant_user'
delete from user where user='grant_user' delete from user where user='grant_user'
flush privileges flush privileges
......
#!/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);
}
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