diff options
author | unknown <monty@hundin.mysql.fi> | 2002-06-27 11:35:50 +0300 |
---|---|---|
committer | unknown <monty@hundin.mysql.fi> | 2002-06-27 11:35:50 +0300 |
commit | 8d07955f3d2e7c5f66f6cfb8eb542e7d86f5cd2f (patch) | |
tree | fcda9d9f9918ae09a9b19e81888a83f9d56ab370 | |
parent | 90c5ac46009fdd2412a32dea64b02c358c32a76e (diff) | |
parent | 835a75c97bbc31e35e25171db9c046ec1dae5b87 (diff) | |
download | mariadb-git-8d07955f3d2e7c5f66f6cfb8eb542e7d86f5cd2f.tar.gz |
merge
BitKeeper/etc/ignore:
added scripts/mysql_tableinfo
sql/sql_parse.cc:
Auto merged
-rw-r--r-- | .bzrignore | 8 | ||||
-rw-r--r-- | Docs/manual.texi | 11 | ||||
-rw-r--r-- | include/mysql.h | 41 | ||||
-rw-r--r-- | include/thr_alarm.h | 9 | ||||
-rw-r--r-- | libmysql/libmysql.c | 6 | ||||
-rw-r--r-- | libmysql/libmysql.def | 2 | ||||
-rw-r--r-- | libmysqld/libmysqld.def | 7 | ||||
-rw-r--r-- | myisam/myisampack.c | 2 | ||||
-rw-r--r-- | mysys/thr_alarm.c | 95 | ||||
-rw-r--r-- | scripts/Makefile.am | 2 | ||||
-rw-r--r-- | scripts/mysql_tableinfo.sh | 478 | ||||
-rw-r--r-- | sql-bench/crash-me.sh | 35 | ||||
-rw-r--r-- | sql-bench/limits/mysql.cfg | 10 | ||||
-rw-r--r-- | sql/hostname.cc | 4 | ||||
-rw-r--r-- | sql/item_func.cc | 6 | ||||
-rw-r--r-- | sql/item_func.h | 19 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/opt_range.cc | 4 | ||||
-rw-r--r-- | sql/sql_parse.cc | 25 | ||||
-rw-r--r-- | sql/sql_test.cc | 12 |
20 files changed, 679 insertions, 99 deletions
diff --git a/.bzrignore b/.bzrignore index b95586a64ee..9f97c9ca9bf 100644 --- a/.bzrignore +++ b/.bzrignore @@ -472,3 +472,11 @@ vio/viotest-ssl mysys/getopt.c mysys/getopt1.c scripts/mysql_secure_installation +mit-pthreads/include/bits +mit-pthreads/include/pthread/machdep.h +mit-pthreads/include/pthread/posix.h +mit-pthreads/include/sys +mit-pthreads/machdep.c +mit-pthreads/pg++ +mit-pthreads/pgcc +scripts/mysql_tableinfo diff --git a/Docs/manual.texi b/Docs/manual.texi index cf8f7d1a983..b707c7d426d 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -3951,10 +3951,6 @@ Automatic output from @code{mysql} to Netscape. @item @code{LOCK DATABASES} (with various options.) @item -@code{DECIMAL} and @code{NUMERIC} types can't read exponential numbers; -@code{Field_decimal::store(const char *from,uint len)} must be recoded -to fix this. -@item Functions: ADD_TO_SET(value,set) and REMOVE_FROM_SET(value,set). @item @@ -49451,6 +49447,9 @@ Emulation of @code{pthread_mutex()} for OS/2. @item Benjamin Pflugmann Extended @code{MERGE} tables to handle @code{INSERTS}. Active member on the MySQL mailing lists. +@item Guilhem Bichot +Fixed handling of exponents for @code{DECIMAL}. +Author of @code{mysql_tableinfo}. @end table Other contributors, bugfinders, and testers: James H. Thompson, Maurizio @@ -49579,6 +49578,10 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}. @itemize @bullet @item +Removed @code{mysql_ssl_clear()}, as this was not needed. +@item +@code{DECIMAL} and @code{NUMERIC} types can now read exponential numbers. +@item Added @code{SHA1()} function to calculate 160 bit hash value as described in RFC 3174 (Secure Hash Algorithm). This function can be considered a cryptographically more secure equivalent of @code{MD5()}. diff --git a/include/mysql.h b/include/mysql.h index 5bcdca636c0..af3e8c773ef 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -122,17 +122,17 @@ struct st_mysql_options { my_bool use_ssl; /* if to use SSL or not */ my_bool compress,named_pipe; /* - on connect, find out the replication role of the server, and + On connect, find out the replication role of the server, and establish connections to all the peers */ my_bool rpl_probe; - /* - each call to mysql_real_query() will parse it to tell if it is a read - or a write, and direct it to the slave or the master + /* + Each call to mysql_real_query() will parse it to tell if it is a read + or a write, and direct it to the slave or the master */ my_bool rpl_parse; /* - if set, never read from a master,only from slave, when doing + If set, never read from a master,only from slave, when doing a read that is replication-aware */ my_bool no_master_reads; @@ -185,8 +185,10 @@ typedef struct st_mysql { added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave() */ my_bool rpl_pivot; - /* pointers to the master, and the next slave - connections, points to itself if lone connection */ + /* + Pointers to the master, and the next slave connections, points to + itself if lone connection. + */ struct st_mysql* master, *next_slave; struct st_mysql* last_used_slave; /* needed for round-robin slave pick */ @@ -234,21 +236,27 @@ typedef struct st_mysql_manager char last_error[MAX_MYSQL_MANAGER_ERR]; } MYSQL_MANAGER; -/* Set up and bring down the server; to ensure that applications will - * work when linked against either the standard client library or the - * embedded server library, these functions should be called. */ +/* + Set up and bring down the server; to ensure that applications will + work when linked against either the standard client library or the + embedded server library, these functions should be called. +*/ int STDCALL mysql_server_init(int argc, char **argv, char **groups); void STDCALL mysql_server_end(void); -/* Set up and bring down a thread; these function should be called - * for each thread in an application which opens at least one MySQL - * connection. All uses of the connection(s) should be between these - * function calls. */ +/* + Set up and bring down a thread; these function should be called + for each thread in an application which opens at least one MySQL + connection. All uses of the connection(s) should be between these + function calls. +*/ my_bool STDCALL mysql_thread_init(void); void STDCALL mysql_thread_end(void); -/* Functions to get information from the MYSQL and MYSQL_RES structures */ -/* Should definitely be used if one uses shared libraries */ +/* + Functions to get information from the MYSQL and MYSQL_RES structures + Should definitely be used if one uses shared libraries. +*/ my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res); unsigned int STDCALL mysql_num_fields(MYSQL_RES *res); @@ -272,7 +280,6 @@ MYSQL * STDCALL mysql_init(MYSQL *mysql); int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher); -int STDCALL mysql_ssl_clear(MYSQL *mysql); my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, const char *passwd, const char *db); MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host, diff --git a/include/thr_alarm.h b/include/thr_alarm.h index 5caf552718c..30825d49158 100644 --- a/include/thr_alarm.h +++ b/include/thr_alarm.h @@ -38,6 +38,15 @@ extern "C" { #define THR_SERVER_ALARM SIGALRM #endif +typedef struct st_alarm_info +{ + ulong next_alarm_time; + uint active_alarms; + uint max_used_alarms; +} ALARM_INFO; + +void thr_alarm_info(ALARM_INFO *info); + #if defined(DONT_USE_THR_ALARM) || !defined(THREAD) #define USE_ALARM_THREAD diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 646c165d512..fa505063deb 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1448,8 +1448,8 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , NB! Errors are not reported until you do mysql_real_connect. **************************************************************************/ -int STDCALL -mysql_ssl_clear(MYSQL *mysql __attribute__((unused))) +static int +mysql_ssl_free(MYSQL *mysql __attribute__((unused))) { #ifdef HAVE_OPENSSL my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); @@ -2051,7 +2051,7 @@ mysql_close(MYSQL *mysql) my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); #ifdef HAVE_OPENSSL - mysql_ssl_clear(mysql); + mysql_ssl_free(mysql); #endif /* HAVE_OPENSSL */ /* Clear pointers for better safety */ mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 9405ecd58ff..988f2b09195 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -90,7 +90,7 @@ EXPORTS mysql_real_escape_string mysql_ssl_set mysql_ssl_clear - mysql_real_connect + mysql_real_connect mysql_master_query mysql_master_send_query mysql_slave_query diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def index 0e126aa9ceb..c6615ee971c 100644 --- a/libmysqld/libmysqld.def +++ b/libmysqld/libmysqld.def @@ -63,10 +63,3 @@ EXPORTS mysql_refresh mysql_odbc_escape_string myodbc_remove_escape - - - - - - - diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 0064b50348f..b7dd788821a 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -275,7 +275,7 @@ static void print_version(void) static void usage(void) { print_version(); - puts("Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB"); + puts("Copyright (C) 2002 MySQL AB"); puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,"); puts("and you are welcome to modify and redistribute it under the GPL license\n"); diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index ef514efe39e..c75b43ad0fc 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -44,6 +44,7 @@ my_bool thr_alarm_inited=0; static pthread_mutex_t LOCK_alarm; static sigset_t full_signal_set; static QUEUE alarm_queue; +static uint max_used_alarms=0; pthread_t alarm_thread; #ifdef USE_ALARM_THREAD @@ -116,10 +117,10 @@ void init_thr_alarm(uint max_alarms) } /* -** Request alarm after sec seconds. -** A pointer is returned with points to a non-zero int when the alarm has been -** given. This can't be called from the alarm-handling thread. -** Returns 0 if no more alarms are allowed (aborted by process) + Request alarm after sec seconds. + A pointer is returned with points to a non-zero int when the alarm has been + given. This can't be called from the alarm-handling thread. + Returns 0 if no more alarms are allowed (aborted by process) */ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) @@ -140,13 +141,17 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) pthread_sigmask(SIG_SETMASK,&old_mask,NULL); DBUG_RETURN(1); } - if (alarm_queue.elements == alarm_queue.max_elements) + if (alarm_queue.elements >= max_used_alarms) { - DBUG_PRINT("info", ("alarm queue full")); - fprintf(stderr,"Warning: thr_alarm queue is full\n"); - pthread_mutex_unlock(&LOCK_alarm); - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); - DBUG_RETURN(1); + if (alarm_queue.elements == alarm_queue.max_elements) + { + DBUG_PRINT("info", ("alarm queue full")); + fprintf(stderr,"Warning: thr_alarm queue is full\n"); + pthread_mutex_unlock(&LOCK_alarm); + pthread_sigmask(SIG_SETMASK,&old_mask,NULL); + DBUG_RETURN(1); + } + max_used_alarms=alarm_queue.elements+1; } reschedule= (!alarm_queue.elements || (int) (((ALARM*) queue_top(&alarm_queue))->expire_time - now) > @@ -186,7 +191,7 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) /* -** Remove alarm from list of alarms + Remove alarm from list of alarms */ void thr_end_alarm(thr_alarm_t *alarmed) @@ -227,13 +232,13 @@ void thr_end_alarm(thr_alarm_t *alarmed) DBUG_VOID_RETURN; } - /* - Come here when some alarm in queue is due. - Mark all alarms with are finnished in list. - Shedule alarms to be sent again after 1-10 sec (many alarms at once) - If alarm_aborted is set then all alarms are given and resent - every second. - */ +/* + Come here when some alarm in queue is due. + Mark all alarms with are finnished in list. + Shedule alarms to be sent again after 1-10 sec (many alarms at once) + If alarm_aborted is set then all alarms are given and resent + every second. +*/ sig_handler process_alarm(int sig __attribute__((unused))) { @@ -334,8 +339,8 @@ sig_handler process_alarm(int sig __attribute__((unused))) /* -** Shedule all alarms now. -** When all alarms are given, Free alarm memory and don't allow more alarms. + Shedule all alarms now. + When all alarms are given, Free alarm memory and don't allow more alarms. */ void end_thr_alarm(void) @@ -359,7 +364,7 @@ void end_thr_alarm(void) /* -** Remove another thread from the alarm + Remove another thread from the alarm */ void thr_alarm_kill(pthread_t thread_id) @@ -382,9 +387,25 @@ void thr_alarm_kill(pthread_t thread_id) } +void thr_alarm_info(ALARM_INFO *info) +{ + pthread_mutex_lock(&LOCK_alarm); + info->next_alarm_time= 0; + info->max_used_alarms= max_used_alarms; + if ((info->active_alarms= alarm_queue.elements)) + { + ulong now=(ulong) time((time_t*) 0); + long time_diff; + ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue); + time_diff= (long) (alarm_data->expire_time - now); + info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff); + } + pthread_mutex_unlock(&LOCK_alarm); +} + /* -** This is here for thread to get interruptet from read/write/fcntl -** ARGSUSED + This is here for thread to get interruptet from read/write/fcntl + ARGSUSED */ #if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) @@ -459,7 +480,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) #endif /* USE_ALARM_THREAD */ /***************************************************************************** -** thr_alarm for OS/2 + thr_alarm for OS/2 *****************************************************************************/ #elif defined(__EMX__) || defined(OS2) @@ -490,7 +511,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) /* -** Remove another thread from the alarm + Remove another thread from the alarm */ void thr_alarm_kill(pthread_t thread_id) @@ -588,8 +609,14 @@ void init_thr_alarm(uint max_alarm) DBUG_VOID_RETURN; } +void thr_alarm_info(ALARM_INFO *info) +{ + bzero((char*) info, sizeof(*info)); +} + + /***************************************************************************** -** thr_alarm for win95 + thr_alarm for win95 *****************************************************************************/ #else /* __WIN__ */ @@ -661,13 +688,18 @@ void init_thr_alarm(uint max_alarm) DBUG_VOID_RETURN; } +void thr_alarm_info(ALARM_INFO *info) +{ + bzero((char*) info, sizeof(*info)); +} + #endif /* __WIN__ */ #endif /* THREAD */ /**************************************************************************** -** Handling of MAIN + Handling of test case (when compiled with -DMAIN) ***************************************************************************/ #ifdef MAIN @@ -867,6 +899,7 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) pthread_attr_t thr_attr; int i,*param,error; sigset_t set; + ALARM_INFO alarm_info; MY_INIT(argv[0]); if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#') @@ -927,6 +960,10 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) pthread_attr_destroy(&thr_attr); pthread_mutex_lock(&LOCK_thread_count); + thr_alarm_info(&alarm_info); + printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", + alarm_info.active_alarms, alarm_info.max_used_alarms, + alarm_info.next_alarm_time); while (thread_count) { VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)); @@ -937,6 +974,10 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) } } pthread_mutex_unlock(&LOCK_thread_count); + thr_alarm_info(&alarm_info); + printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", + alarm_info.active_alarms, alarm_info.max_used_alarms, + alarm_info.next_alarm_time); printf("Test succeeded\n"); return 0; } diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 913e62050fa..1469f3f2f2d 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -31,6 +31,7 @@ bin_SCRIPTS = @server_scripts@ \ mysqlhotcopy \ mysqldumpslow \ mysql_explain_log \ + mysql_tableinfo \ mysqld_multi EXTRA_SCRIPTS = make_binary_distribution.sh \ @@ -50,6 +51,7 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \ mysqldumpslow.sh \ mysql_explain_log.sh \ mysqld_multi.sh \ + mysql_tableinfo.sh \ mysqld_safe.sh EXTRA_DIST = $(EXTRA_SCRIPTS) \ diff --git a/scripts/mysql_tableinfo.sh b/scripts/mysql_tableinfo.sh new file mode 100644 index 00000000000..bfe9be377c7 --- /dev/null +++ b/scripts/mysql_tableinfo.sh @@ -0,0 +1,478 @@ +#!@PERL@ -w + +use strict; +use Getopt::Long; +use DBI; + +=head1 NAME + +mysql_tableinfo - creates and populates information tables with +the output of SHOW DATABASES, SHOW TABLES (or SHOW TABLE STATUS), +SHOW COLUMNS and SHOW INDEX. + +This is version 1.0. + +=head1 SYNOPSIS + + mysql_tableinfo [OPTIONS] database_to_write [database_like_wild] [table_like_wild] + + Do not backquote (``) database_to_write, + and do not quote ('') database_like_wild or table_like_wild + + Examples: + + mysql_tableinfo info + + mysql_tableinfo info this_db + + mysql_tableinfo info %a% b% + + mysql_tableinfo info --clear-only + + mysql_tableinfo info --col --idx --table-status + +=cut + +# Documentation continued at end of file + + +sub usage { + die @_,"\nExecute 'perldoc $0' for documentation\n"; +} + +my %opt = ( + 'user' => scalar getpwuid($>), + 'host' => "localhost", + 'prefix' => "", #to avoid 'use of uninitialized value...' +); +Getopt::Long::Configure(qw(no_ignore_case)); # disambuguate -p and -P +GetOptions( \%opt, + "help", + "user|u=s", + "password|p=s", + "host|h=s", + "port|P=s", + "socket|S=s", + "tbl-status", + "col", + "idx", + "clear", + "clear-only", + "prefix=s", + "quiet|q", +) or usage("Invalid option"); + +if ($opt{help}) {usage();} + +my ($db_to_write,$db_like_wild,$tbl_like_wild); +if (@ARGV==0) +{ + usage("Not enough arguments"); +} +$db_to_write="`$ARGV[0]`"; shift @ARGV; +$db_like_wild=($ARGV[0])?$ARGV[0]:"%"; shift @ARGV; +$tbl_like_wild=($ARGV[0])?$ARGV[0]:"%"; shift @ARGV; +if (@ARGV>0) { usage("Too many arguments"); } + +my $info_db="`".$opt{'prefix'}."db`"; +my $info_tbl="`".$opt{'prefix'}."tbl". + (($opt{'tbl-status'})?"_status":"")."`"; +my $info_col="`".$opt{'prefix'}."col`"; +my $info_idx="`".$opt{'prefix'}."idx`"; + + +# --- connect to the database --- + +my $dsn = ";host=$opt{'host'}"; +$dsn .= ";port=$opt{port}" if $opt{port}; +$dsn .= ";mysql_socket=$opt{socket}" if $opt{socket}; + +my $dbh = DBI->connect("dbi:mysql:$dsn;mysql_read_default_group=perl", + $opt{user}, $opt{password}, +{ + RaiseError => 1, + PrintError => 0, + AutoCommit => 1, +}); + +$db_like_wild=$dbh->quote($db_like_wild); +$tbl_like_wild=$dbh->quote($tbl_like_wild); + +#Ask + +if (!$opt{'quiet'}) +{ + print "\n!! This program is doing to do:\n\n"; + print "**DROP** TABLE ...\n" if ($opt{'clear'} or $opt{'clear-only'}); + print "**DELETE** FROM ... WHERE `Database LIKE $db_like_wild AND `Table` LIKE $tbl_like_wild +**INSERT** INTO ... + +on the following tables :\n"; + my $i; + foreach $i (($info_db, $info_tbl), + (($opt{'col'})?$info_col:()), + (($opt{'idx'})?$info_idx:())) + { + print(" $db_to_write.$i\n"); + } + print "\nContinue (you can skip this confirmation step with --quiet) ? (y|n) [n]"; + my $answer=<STDIN>; + unless ($answer =~ /^\s*y\s*$/i) + { + print "Nothing done!\n";exit; + } +} + +if ($opt{'clear'} or $opt{'clear-only'}) +{ +#do not drop the $db_to_write database ! + my $i; + foreach $i (($info_db, $info_tbl), + (($opt{'col'})?$info_col:()), + (($opt{'idx'})?$info_idx:())) + { + $dbh->do("DROP TABLE IF EXISTS $db_to_write.$i"); + } + if ($opt{'clear-only'}) + { + print "Wrote to database $db_to_write .\n" unless ($opt{'quiet'}); + exit(); + } +} + + +my %sth; +my %extra_col_desc; +my %row; +my %done_create_table; + +#create the $db_to_write database +$dbh->do("CREATE DATABASE IF NOT EXISTS $db_to_write"); +$dbh->do("USE $db_to_write"); + +#get databases +$sth{db}=$dbh->prepare("SHOW DATABASES LIKE $db_like_wild"); +$sth{db}->execute; + +#create $info_db which will receive info about databases. +#Ensure that the first column to be called "Database" (as SHOW DATABASES LIKE +#returns a varying +#column name (of the form "Database (%...)") which is not suitable) +$extra_col_desc{db}=do_create_table("db",$info_db,undef,"`Database`"); +#we'll remember the type of the `Database` column (as returned by +#SHOW DATABASES), which we will need when creating the next tables. + +#clear out-of-date info from this table +$dbh->do("DELETE FROM $info_db WHERE `Database` LIKE $db_like_wild"); + + +while (@{$row{db}}=$sth{db}->fetchrow_array) #go through all databases +{ + +#insert the database name + $dbh->do("INSERT INTO $info_db VALUES(" + .join_quote(@{$row{db}}).")"); + +#for each database, get tables + + $sth{tbl}=$dbh->prepare("SHOW TABLE" + .( ($opt{'tbl-status'}) ? + " STATUS" + : "S" ) + ." from `${$row{db}}[0]` LIKE $tbl_like_wild"); + $sth{tbl}->execute; + unless ($done_create_table{$info_tbl}) + +#tables must be created only once, and out-of-date info must be +#cleared once + { + $done_create_table{$info_tbl}=1; + $extra_col_desc{table}= + do_create_table("tbl",$info_tbl, +#add an extra column (database name) at the left +#and ensure that the table name will be called "Table" +#(this is unncessesary with +#SHOW TABLE STATUS, but necessary with SHOW TABLES (which returns a column +#named "Tables_in_...")) + "`Database` ".$extra_col_desc{db},"`Table`"); + $dbh->do("DELETE FROM $info_tbl WHERE `Database` LIKE $db_like_wild AND `Table` LIKE $tbl_like_wild"); + } + + while (@{$row{tbl}}=$sth{tbl}->fetchrow_array) + { + $dbh->do("INSERT INTO $info_tbl VALUES(" + .$dbh->quote(${$row{db}}[0]).",".join_quote(@{$row{tbl}}).")"); + +#for each table, get columns... + + if ($opt{'col'}) + { + $sth{col}=$dbh->prepare("SHOW COLUMNS FROM `${$row{tbl}}[0]` FROM `${$row{db}}[0]`"); + $sth{col}->execute; + unless ($done_create_table{$info_col}) + { + $done_create_table{$info_col}=1; + do_create_table("col",$info_col, + "`Database` ".$extra_col_desc{db}."," + ."`Table` ".$extra_col_desc{table}."," + ."`Seq_in_table` BIGINT(3)"); +#We need to add a sequence number (1 for the first column of the table, +#2 for the second etc) so that users are able to retrieve columns in order +#if they want. This is not needed for INDEX +#(where there is already Seq_in_index) + $dbh->do("DELETE FROM $info_col WHERE `Database` + LIKE $db_like_wild + AND `Table` LIKE $tbl_like_wild"); + } + my $col_number=0; + while (@{$row{col}}=$sth{col}->fetchrow_array) + { + $dbh->do("INSERT INTO $info_col VALUES(" + .$dbh->quote(${$row{db}}[0])."," + .$dbh->quote(${$row{tbl}}[0])."," + .++$col_number."," + .join_quote(@{$row{col}}).")"); + } + } + +#and get index. + + if ($opt{'idx'}) + { + $sth{idx}=$dbh->prepare("SHOW INDEX FROM `${$row{tbl}}[0]` FROM `${$row{db}}[0]`"); + $sth{idx}->execute; + unless ($done_create_table{$info_idx}) + { + $done_create_table{$info_idx}=1; + do_create_table("idx",$info_idx, + "`Database` ".$extra_col_desc{db}); + $dbh->do("DELETE FROM $info_idx WHERE `Database` + LIKE $db_like_wild + AND `Table` LIKE $tbl_like_wild"); + } + while (@{$row{idx}}=$sth{idx}->fetchrow_array) + { + $dbh->do("INSERT INTO $info_idx VALUES(" + .$dbh->quote(${$row{db}}[0])."," + .join_quote(@{$row{idx}}).")"); + } + } + } +} + +print "Wrote to database $db_to_write .\n" unless ($opt{'quiet'}); +exit; + +sub join_quote +{ + my (@list)=@_; my $i; + foreach $i (@list) { $i=$dbh->quote($i); } + return (join ',',@list); +} + +sub do_create_table +{ + my ($sth_key,$target_tbl,$extra_col_desc,$first_col_name)=@_; + my $create_table_query=$extra_col_desc; + my ($i,$type,$first_col_desc,$col_desc); + + for ($i=0;$i<$sth{$sth_key}->{NUM_OF_FIELDS};$i++) + { + if ($create_table_query) { $create_table_query.=", "; } + $type=$sth{$sth_key}->{mysql_type_name}->[$i]; + $col_desc=$type; + if ($type =~ /char|int/i) + { + $col_desc.="($sth{$sth_key}->{PRECISION}->[$i])"; + } + elsif ($type =~ /decimal|numeric/i) #(never seen that) + { + $col_desc.= + "($sth{$sth_key}->{PRECISION}->[$i],$sth{$sth_key}->{SCALE}->[$i])"; + } + elsif ($type !~ /date/i) #date and datetime are OK, + #no precision or scale for them + { + warn "unexpected column type '$type' +(neither 'char','int','decimal|numeric') +when creating $target_tbl, hope table creation will go OK\n"; + } + if ($i==0) {$first_col_desc=$col_desc}; + $create_table_query.= + ( ($i==0 and $first_col_name) ? + "$first_col_name " :"`$sth{$sth_key}->{NAME}->[$i]` " ) + .$col_desc; + } +if ($create_table_query) +{ + $dbh->do("CREATE TABLE IF NOT EXISTS $target_tbl ($create_table_query)"); +} +return $first_col_desc; +} + +__END__ + + +=head1 DESCRIPTION + +mysql_tableinfo asks a MySQL server information about its +databases, tables, table columns and index, and stores this +in tables called `db`, `tbl` (or `tbl_status`), `col`, `idx` +(with an optional prefix specified with --prefix). +After that, you can query these information tables, for example +to build your admin scripts with SQL queries, like + +SELECT CONCAT("CHECK TABLE ",`database`,".",`table`," EXTENDED;") +FROM info.tbl WHERE ... ; + +as people usually do with some other RDBMS +(note: to increase the speed of your queries on the info tables, +you may add some index on them). + +The database_like_wild and table_like_wild instructs the program +to gather information only about databases and tables +whose names match these patterns. If the info +tables already exist, their rows matching the patterns are simply +deleted and replaced by the new ones. That is, +old rows not matching the patterns are not touched. +If the database_like_wild and table_like_wild arguments +are not specified on the command-line they default to "%". + +The program : + +- does CREATE DATABASE IF NOT EXISTS database_to_write +where database_to_write is the database name specified on the command-line. + +- does CREATE TABLE IF NOT EXISTS database_to_write.`db` + +- fills database_to_write.`db` with the output of +SHOW DATABASES LIKE database_like_wild + +- does CREATE TABLE IF NOT EXISTS database_to_write.`tbl` +(respectively database_to_write.`tbl_status` +if the --tbl-status option is on) + +- for every found database, +fills database_to_write.`tbl` (respectively database_to_write.`tbl_status`) +with the output of +SHOW TABLES FROM found_db LIKE table_like_wild +(respectively SHOW TABLE STATUS FROM found_db LIKE table_like_wild) + +- if the --col option is on, + * does CREATE TABLE IF NOT EXISTS database_to_write.`col` + * for every found table, + fills database_to_write.`col` with the output of + SHOW COLUMNS FROM found_tbl FROM found_db + +- if the --idx option is on, + * does CREATE TABLE IF NOT EXISTS database_to_write.`idx` + * for every found table, + fills database_to_write.`idx` with the output of + SHOW INDEX FROM found_tbl FROM found_db + +Some options may modify this general scheme (see below). + +As mentioned, the contents of the info tables are the output of +SHOW commands. In fact the contents are slightly more complete : + +- the `tbl` (or `tbl_status`) info table + has an extra column which contains the database name, + +- the `col` info table + has an extra column which contains the table name, + and an extra column which contains, for each described column, + the number of this column in the table owning it (this extra column + is called `Seq_in_table`). `Seq_in_table` makes it possible for you + to retrieve your columns in sorted order, when you are querying + the `col` table. + +- the `index` info table + has an extra column which contains the database name. + +Caution: info tables contain certain columns (e.g. +Database, Table, Null...) whose names, as they are MySQL reserved words, +need to be backquoted (`...`) when used in SQL statements. + +=head1 OPTIONS + +=over 4 + +=item --clear + +Does DROP TABLE on the info tables (only those that the program is +going to fill, for example if you do not use --col it won't drop +the `col` table) and processes normally. Does not drop database_to_write. + +=item --clear-only + +Same as --clear but exits after the DROPs. + +=item --col + +Adds columns information (into table `col`). + +=item --idx + +Adds index information (into table `idx`). + +=item --prefix prefix + +The info tables are named from the concatenation of prefix and, +respectively, db, tbl (or tbl_status), col, idx. Do not quote ('') +or backquote (``) prefix. + +=item -q, --quiet + +Does not warn you about what the script is going to do (DROP TABLE etc) +and does not ask for a confirmation before starting. + +=item --tbl-status + +Instead of using SHOW TABLES, uses SHOW TABLE STATUS +(much more complete information, but slower). + +=item --help + +Display helpscreen and exit + +=item -u, --user=# + +user for database login if not current user. Give a user +who has sufficient privileges (CREATE, ...). + +=item -p, --password=# + +password to use when connecting to server + +=item -h, --host=# + +host to connect to + +=item -P, --port=# + +port to use when connecting to server + +=item -S, --socket=# + +UNIX domain socket to use when connecting to server + +=head1 WARRANTY + +This software is free and comes without warranty of any kind. You +should never trust backup software without studying the code yourself. +Study the code inside this script and only rely on it if I<you> believe +that it does the right thing for you. + +Patches adding bug fixes, documentation and new features are welcome. + +=head1 TO DO + +Use extended inserts to be faster (for servers with many databases +or tables). But to do that, must care about net-buffer-length. + +=head1 AUTHOR + +2002-06-18 Guilhem Bichot (guilhem.bichot@mines-paris.org) + +And all the authors of mysqlhotcopy, which served as a model for +the structure of the program. diff --git a/sql-bench/crash-me.sh b/sql-bench/crash-me.sh index 9572143ae53..d66e8f47d6a 100644 --- a/sql-bench/crash-me.sh +++ b/sql-bench/crash-me.sh @@ -38,7 +38,7 @@ # as such, and clarify ones such as "mediumint" with comments such as # "3-byte int" or "same as xxx". -$version="1.57"; +$version="1.58"; use DBI; use Getopt::Long; @@ -2186,20 +2186,20 @@ EOF print <<EOF; Some of the tests you are about to execute may require a lot of -memory. Your tests WILL adversely affect system performance. It's +memory. Your tests WILL adversely affect system performance. It\'s not uncommon that either this crash-me test program, or the actual database back-end, will DIE with an out-of-memory error. So might any other program on your system if it requests more memory at the wrong time. Note also that while crash-me tries to find limits for the database server -it will make a lot of queries that can't be categorized as 'normal'. It's +it will make a lot of queries that can\'t be categorized as \'normal\'. It\'s not unlikely that crash-me finds some limit bug in your server so if you run this test you have to be prepared that your server may die during it! We, the creators of this utility, are not responsible in any way if your database server unexpectedly crashes while this program tries to find the -limitations of your server. By accepting the following question with 'yes', +limitations of your server. By accepting the following question with \'yes\', you agree to the above! You have been warned! @@ -2468,7 +2468,6 @@ sub report print "$prompt: "; if (!defined($limits{$limit})) { - save_config_data($limit,"incompleted",$prompt); save_config_data($limit,safe_query(\@queries) ? "yes" : "no",$prompt); } print "$limits{$limit}\n"; @@ -2481,7 +2480,6 @@ sub report_fail print "$prompt: "; if (!defined($limits{$limit})) { - save_config_data($limit,"incompleted",$prompt); save_config_data($limit,safe_query(\@queries) ? "no" : "yes",$prompt); } print "$limits{$limit}\n"; @@ -2498,7 +2496,7 @@ sub report_one print "$prompt: "; if (!defined($limits{$limit})) { - save_config_data($limit,"incompleted",$prompt); + save_incomplete($limit,$prompt); $result="no"; foreach $query (@$queries) { @@ -2524,7 +2522,7 @@ sub report_result print "$prompt: "; if (!defined($limits{$limit})) { - save_config_data($limit,"incompleted",$prompt); + save_incomplete($limit,$prompt); $error=safe_query_result($query,"1",2); save_config_data($limit,$error ? "not supported" : $last_result,$prompt); } @@ -2537,7 +2535,7 @@ sub report_trans my ($limit,$queries,$check,$clear)=@_; if (!defined($limits{$limit})) { - save_config_data($limit,"incompleted",$prompt); + save_incomplete($limit,$prompt); eval {undef($dbh->{AutoCommit})}; if (!$@) { @@ -2579,7 +2577,7 @@ sub check_and_report print "$prompt: " if (!defined($skip_prompt)); if (!defined($limits{$limit})) { - save_config_data($limit,"incompleted",$prompt); + save_incomplete($limit,$prompt); $tmp=1-safe_query(\@$pre); $tmp=safe_query_result($query,$answer,$string_type) if (!$tmp); safe_query(\@$post); @@ -2615,7 +2613,7 @@ sub try_and_report if (!defined($limits{$limit})) { - save_config_data($limit,"incompleted",$prompt); + save_incomplete($limit,$prompt); $type="no"; # Not supported foreach $test (@tests) { @@ -2695,7 +2693,8 @@ sub safe_query_result $sth->finish; return ($result_type == 8) ? 0 : 1; } - if($result_type == 8) { + if ($result_type == 8) + { $sth->finish; return 1; } @@ -2787,7 +2786,7 @@ sub find_limit() print "$end (cache)\n"; return $end; } - save_config_data($limit,"incompleted",$prompt); + save_incomplete($limit,$prompt); if (defined($query->{'init'}) && !defined($end=$limits{'restart'}{'tohigh'})) { @@ -2961,6 +2960,16 @@ sub save_all_config_data close CONFIG_FILE; } +# +# Save 'incomplete' in the limits file to be able to continue if +# crash-me dies because of a bug in perl/DBI + +sub save_incomplete +{ + my ($limit,$prompt)= @_; + save_config_data($limit,"incompleted",$prompt) if ($opt_restart); +} + sub check_repeat { diff --git a/sql-bench/limits/mysql.cfg b/sql-bench/limits/mysql.cfg index cd4aea7dcf5..306ce2d7b33 100644 --- a/sql-bench/limits/mysql.cfg +++ b/sql-bench/limits/mysql.cfg @@ -1,4 +1,4 @@ -#This file is automaticly generated by crash-me 1.57 +#This file is automaticly generated by crash-me 1.58 NEG=yes # update of column= -column Need_cast_for_null=no # Need to cast NULL for arithmetic @@ -36,7 +36,7 @@ constraint_check=no # Column constraints constraint_check_table=no # Table constraints constraint_null=yes # NULL constraint (SyBase style) crash_me_safe=yes # crash me safe -crash_me_version=1.57 # crash me version +crash_me_version=1.58 # crash me version create_default=yes # default value for column create_default_func=no # default value function for column create_if_not_exists=yes # create table if not exists @@ -333,7 +333,7 @@ max_char_size=255 # max char() size max_column_name=64 # column name length max_columns=3398 # Columns in table max_conditions=85660 # OR and AND in WHERE -max_expressions=856 # simple expressions +max_expressions=686 # simple expressions max_index=32 # max index max_index_length=500 # index length max_index_name=64 # index name length @@ -343,7 +343,7 @@ max_index_varchar_part_length=255 # index varchar part length max_row_length=65534 # max table row length (without blobs) max_row_length_with_null=65502 # table row length with nulls (without blobs) max_select_alias_name=+512 # select alias name length -max_stack_expression=856 # stacked expressions +max_stack_expression=490 # stacked expressions max_table_alias_name=+512 # table alias name length max_table_name=64 # table name length max_text_size=1048543 # max text or blob size @@ -396,7 +396,7 @@ select_limit2=yes # SELECT with LIMIT #,# select_string_size=1048565 # constant string size in SELECT select_table_update=no # Update with sub select select_without_from=yes # SELECT without FROM -server_version=MySQL 4.0.2 alpha debug # server version +server_version=MySQL 4.0.2 alpha # server version simple_joins=yes # ANSI SQL simple joins storage_of_float=round # Storage of float values subqueries=no # subqueries diff --git a/sql/hostname.cc b/sql/hostname.cc index a93af8b273e..abccc466a22 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -57,8 +57,8 @@ void hostname_cache_refresh() bool hostname_cache_init() { - host_entry *tmp; - uint offset= (uint) ((char*) (&tmp->ip) - (char*) tmp); + host_entry tmp; + uint offset= (uint) ((char*) (&tmp.ip) - (char*) &tmp); (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW); if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset, diff --git a/sql/item_func.cc b/sql/item_func.cc index accc5219a71..2d800cddb0d 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2047,13 +2047,14 @@ err: return 0; } + void Item_func_match::init_search(bool no_order) { if (ft_handler) return; if (key == NO_SUCH_KEY) - concat=new Item_func_concat_ws (new Item_string(" ",1), fields); + concat= new Item_func_concat_ws(new Item_string(" ",1), fields); if (master) { @@ -2071,7 +2072,7 @@ void Item_func_match::init_search(bool no_order) // MATCH ... AGAINST (NULL) is meaningless, but possible if (!(ft_tmp=key_item()->val_str(&tmp2))) { - ft_tmp=&tmp2; + ft_tmp= &tmp2; tmp2.set("",0); } @@ -2087,6 +2088,7 @@ void Item_func_match::init_search(bool no_order) } } + bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) { List_iterator<Item> li(fields); diff --git a/sql/item_func.h b/sql/item_func.h index 35f17d1686b..57147b6336f 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -171,9 +171,22 @@ class Item_num_op :public Item_func bool is_null() { (void) val(); return null_value; } Field *tmp_table_field(TABLE *t_arg) { - if (!t_arg) return result_field; - return args[0]->result_type() == INT_RESULT ? ((max_length > 11) ? (Field *)new Field_longlong(max_length,maybe_null,name, t_arg,unsigned_flag) : (Field *)new Field_long(max_length,maybe_null,name, t_arg,unsigned_flag)) : (Field *) new Field_double(max_length, maybe_null, name,t_arg,decimals); - } + Field *res; + if (!t_arg) + return result_field; + if (args[0]->result_type() == INT_RESULT) + { + if (max_length > 11) + res= new Field_longlong(max_length, maybe_null, name, t_arg, + unsigned_flag); + else + res= new Field_long(max_length, maybe_null, name, t_arg, + unsigned_flag); + } + else + res= new Field_double(max_length, maybe_null, name, t_arg, decimals); + return res; + } }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 1637546e09c..a22299b0af0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -75,7 +75,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); #define MAX_FIELDS_BEFORE_HASH 32 #define USER_VARS_HASH_SIZE 16 #define STACK_MIN_SIZE 8192 // Abort if less stack during eval. -#define STACK_BUFF_ALLOC 32 // For stack overrun checks +#define STACK_BUFF_ALLOC 64 // For stack overrun checks #ifndef MYSQLD_NET_RETRY_COUNT #define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. #endif diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 33574a81431..2a76229ecf9 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -67,7 +67,9 @@ public: SEL_ARG(Field *field, uint8 part, char *min_value, char *max_value, uint8 min_flag, uint8 max_flag, uint8 maybe_flag); SEL_ARG(enum Type type_arg) - :elements(1),use_count(1),left(0),next_key_part(0),type(type_arg) {} + :elements(1),use_count(1),left(0),next_key_part(0),color(BLACK), + type(type_arg) + {} inline bool is_same(SEL_ARG *arg) { if (type != arg->type) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7124066bd3b..783a1631fad 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -345,13 +345,12 @@ char uc_update_queries[SQLCOM_END]; static bool check_mqh(THD *thd, uint check_command) { bool error=0; - DBUG_ENTER("check_mqh"); + time_t check_time = thd->start_time ? thd->start_time : time(NULL); USER_CONN *uc=thd->user_connect; + DBUG_ENTER("check_mqh"); DBUG_ASSERT(uc != 0); - bool my_start = thd->start_time != 0; - time_t check_time = (my_start) ? thd->start_time : time(NULL); - + /* If more than a hour since last check, reset resource checking */ if (check_time - uc->intime >= 3600) { (void) pthread_mutex_lock(&LOCK_user_conn); @@ -361,6 +360,7 @@ static bool check_mqh(THD *thd, uint check_command) uc->intime=check_time; (void) pthread_mutex_unlock(&LOCK_user_conn); } + /* Check that we have not done too many questions / hour */ if (uc->user_resources.questions && uc->questions++ >= uc->user_resources.questions) { @@ -371,14 +371,15 @@ static bool check_mqh(THD *thd, uint check_command) } if (check_command < (uint) SQLCOM_END) { - if (uc->user_resources.updates && uc_update_queries[check_command] && - ++(uc->updates) > uc->user_resources.updates) - { - net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_updates", - (long) uc->user_resources.updates); - error=1; - goto end; - } + /* Check that we have not done too many updates / hour */ + if (uc->user_resources.updates && uc_update_queries[check_command] && + uc->updates++ >= uc->user_resources.updates) + { + net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_updates", + (long) uc->user_resources.updates); + error=1; + goto end; + } } end: DBUG_RETURN(error); diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 43c24da85a2..9c458c27b95 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -21,6 +21,7 @@ #include "mysql_priv.h" #include "sql_select.h" #include <hash.h> +#include <thr_alarm.h> /* Intern key cache variables */ extern "C" pthread_mutex_t THR_LOCK_keycache; @@ -239,6 +240,17 @@ Open streams: %10lu\n", (ulong) cached_tables(), (ulong) my_file_opened, (ulong) my_stream_opened); + + ALARM_INFO alarm_info; + thr_alarm_info(&alarm_info); + printf("\nAlarm status:\n\ +Active alarms: %u\n\ +Max used alarms: %u\n\ +Next alarm time: %lu\n", + alarm_info.active_alarms, + alarm_info.max_used_alarms, + alarm_info.next_alarm_time); + fflush(stdout); if (thd) thd->proc_info="malloc"; |