From c35f246bd696366b272a51a2a86e3d17faabd3c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 15 Sep 2003 15:16:13 +0300 Subject: [PATCH 01/49] fixed server crash on moving query block with pointers to same table in it (BUG#988) removed server options BitKeeper/deleted/.del-query_cache-master.opt~c4daeaa5e40881: Delete: mysql-test/t/query_cache-master.opt mysql-test/r/query_cache.result: test for BUG#988 mysql-test/t/query_cache.test: test for BUG#988 removed server options sql/sql_cache.cc: fixed moving query block with pointers to same table in it --- mysql-test/r/query_cache.result | 43 +++++++++++++++++++++- mysql-test/t/query_cache-master.opt | 1 - mysql-test/t/query_cache.test | 55 ++++++++++++++++++++++++++++- sql/sql_cache.cc | 26 ++++++++++++-- 4 files changed, 120 insertions(+), 5 deletions(-) delete mode 100644 mysql-test/t/query_cache-master.opt diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 0b86c79afbf..83d2e439fbc 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1,8 +1,9 @@ +set GLOBAL query_cache_size=1355776; flush query cache; flush query cache; reset query cache; flush status; -drop table if exists t1,t2,t3; +drop table if exists t1,t2,t3,t4,t11,t21; drop database if exists mysqltest; create table t1 (a int not null); insert into t1 values (1),(2),(3); @@ -640,3 +641,43 @@ Variable_name Value Qcache_queries_in_cache 2 SET OPTION SQL_SELECT_LIMIT=DEFAULT; drop table t1; +flush query cache; +reset query cache; +flush status; +set GLOBAL query_cache_size=1048576; +create table t1 (a int not null); +insert into t1 values (1),(2),(3); +create table t2 (a text not null); +create table t3 (a text not null); +insert into t3 values("1111111111111111111111111111111111111111111111111111"); +insert into t2 select * from t3; +insert into t3 select * from t2; +insert into t2 select * from t3; +insert into t3 select * from t2; +insert into t2 select * from t3; +insert into t3 select * from t2; +insert into t2 select * from t3; +insert into t3 select * from t2; +insert into t2 select * from t3; +insert into t3 select * from t2; +drop table t2; +create table t2 (a int not null); +insert into t2 values (1),(2),(3); +create table t4 (a int not null); +insert into t4 values (1),(2),(3); +select * from t4; +select * from t2; +select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2; +select * from t2; +select * from t4; +select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2; +select * from t2; +select * from t4; +select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2; +delete from t2 where a=1; +flush query cache; +select * from t3; +delete from t4 where a=1; +flush query cache; +drop table t1,t2,t3,t4; +set GLOBAL query_cache_size=0; diff --git a/mysql-test/t/query_cache-master.opt b/mysql-test/t/query_cache-master.opt deleted file mode 100644 index cfdce628e74..00000000000 --- a/mysql-test/t/query_cache-master.opt +++ /dev/null @@ -1 +0,0 @@ ---set-variable=query_cache_size=1355776 diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 9e1c22ac642..2ab5504f84b 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -3,6 +3,7 @@ # # Tests with query cache # +set GLOBAL query_cache_size=1355776; # Reset query cache variables. @@ -10,7 +11,7 @@ flush query cache; # This crashed in some versions flush query cache; # This crashed in some versions reset query cache; flush status; -drop table if exists t1,t2,t3; +drop table if exists t1,t2,t3,t4,t11,t21; drop database if exists mysqltest; # @@ -450,3 +451,55 @@ select * from t1; show status like "Qcache_queries_in_cache"; SET OPTION SQL_SELECT_LIMIT=DEFAULT; drop table t1; + + +# +# query cache crash on using same table twice in one query test +# +flush query cache; +reset query cache; +flush status; +set GLOBAL query_cache_size=1048576; + + +create table t1 (a int not null); +insert into t1 values (1),(2),(3); +create table t2 (a text not null); +create table t3 (a text not null); +insert into t3 values("1111111111111111111111111111111111111111111111111111"); +insert into t2 select * from t3; +insert into t3 select * from t2; +insert into t2 select * from t3; +insert into t3 select * from t2; +insert into t2 select * from t3; +insert into t3 select * from t2; +insert into t2 select * from t3; +insert into t3 select * from t2; +insert into t2 select * from t3; +insert into t3 select * from t2; +drop table t2; +create table t2 (a int not null); +insert into t2 values (1),(2),(3); +create table t4 (a int not null); +insert into t4 values (1),(2),(3); + +disable_result_log; +select * from t4; +select * from t2; +select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2; +select * from t2; +select * from t4; +select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2; +select * from t2; +select * from t4; +select * from t1 as tt, t1 as ttt where tt.a=1 and ttt.a=2; + +delete from t2 where a=1; +flush query cache; +select * from t3; +enable_result_log; +delete from t4 where a=1; +flush query cache; + +drop table t1,t2,t3,t4; +set GLOBAL query_cache_size=0; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 97ec6033ad6..5d525c7be4e 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2666,11 +2666,33 @@ my_bool Query_cache::move_by_type(byte **border, relink(block, new_block, next, prev, pnext, pprev); if (queries_blocks == block) queries_blocks = new_block; + Query_cache_block_table *beg_of_table_table= block->table(0), + *end_of_table_table= block->table(n_tables); + byte *beg_of_new_table_table= (byte*) new_block->table(0); + for (TABLE_COUNTER_TYPE j=0; j < n_tables; j++) { Query_cache_block_table *block_table = new_block->table(j); - block_table->next->prev = block_table; - block_table->prev->next = block_table; + + // use aligment from begining of table if 'next' is in same block + if ((beg_of_table_table <= block_table->next) && + (block_table->next < end_of_table_table)) + ((Query_cache_block_table *)(beg_of_new_table_table + + (((byte*)block_table->next) - + ((byte*)beg_of_table_table))))->prev= + block_table; + else + block_table->next->prev= block_table; + + // use aligment from begining of table if 'prev' is in same block + if ((beg_of_table_table <= block_table->prev) && + (block_table->prev < end_of_table_table)) + ((Query_cache_block_table *)(beg_of_new_table_table + + (((byte*)block_table->prev) - + ((byte*)beg_of_table_table))))->next= + block_table; + else + block_table->prev->next = block_table; } DBUG_PRINT("qcache", ("after circle tt")); *border += len; From 52d80b769e6d599aab6848c087506362970d5124 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 27 Sep 2003 17:16:19 +0200 Subject: [PATCH 02/49] backport of a fix made in 4.0 to make replication work in 64-bit binaries. The 4.0 changeset was: ChangeSet@1.1579.3.1, 2003-09-26 23:43:22+02:00, guilhem@mysql.com Fix for 64-bit machines. I am almost sure this is the cause for BUG#1381 [Opn]: Bug in replication on HP-UX 64 bit binaries? BUG#1256 [CRp]: Replication slave fails to connect to master in 64-bit version (Solaris) The reason why I think it's wrong is that the normal client code has uint32 ip_addr. (of course on 32-bit machines it does not matter, but on 64-bit it does). sql/mini_client.cc: backport of a fix made in 4.0 to make replication work in 64-bit binaries. --- sql/mini_client.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mini_client.cc b/sql/mini_client.cc index 2c74eb96bf9..c7beeea37b8 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -496,7 +496,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, { char buff[100],*end,*host_info; my_socket sock; - ulong ip_addr; + uint32 ip_addr; struct sockaddr_in sock_addr; uint pkt_length; NET *net= &mysql->net; From 0cb0542ac53b97f20f45af73dfddaa7fb57ddc4a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 29 Sep 2003 15:42:33 -0400 Subject: [PATCH 03/49] fixed processing of COM_BINLOG_DUMP to use in mysqlbinlog sql/sql_repl.cc: fixed mysql_binlog_send to use COM_BINLOG_DUMP in mysqlbinlog --- sql/sql_parse.cc | 3 ++- sql/sql_repl.cc | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 81233c038a1..3f6fa8d24ad 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -929,7 +929,8 @@ bool do_command(THD *thd) pos = uint4korr(packet + 1); flags = uint2korr(packet + 5); pthread_mutex_lock(&LOCK_server_id); - kill_zombie_dump_threads(slave_server_id = uint4korr(packet+7)); + if ((slave_server_id = uint4korr(packet+7))) + kill_zombie_dump_threads(slave_server_id); thd->server_id = slave_server_id; pthread_mutex_unlock(&LOCK_server_id); mysql_binlog_send(thd, thd->strdup(packet + 11), pos, flags); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 1940ff360c2..ec5d45bca90 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -442,6 +442,11 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) break; case LOG_READ_EOF: DBUG_PRINT("wait",("waiting for data on binary log")); + if (thd->server_id==0) + { + pthread_mutex_unlock(log_lock); + goto end; + } if (!thd->killed) pthread_cond_wait(&COND_binlog_update, log_lock); break; @@ -523,6 +528,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) } } +end: end_io_cache(&log); (void)my_close(file, MYF(MY_WME)); @@ -532,7 +538,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) thd->current_linfo = 0; pthread_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; - err: +err: thd->proc_info = "waiting to finalize termination"; end_io_cache(&log); pthread_mutex_lock(&LOCK_thread_count); From 7e9e20e3c2f686778efe0d0e184cfaefd77821c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Oct 2003 21:02:53 +0300 Subject: [PATCH 04/49] Fixed memory leak in send_file mysql-test/t/myisam.test: Cleanup test BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + mysql-test/t/myisam.test | 3 +-- sql/sql_repl.cc | 9 +-------- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 8238e85a5be..777c590ce62 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -22,6 +22,7 @@ monty@bitch.mysql.fi monty@donna.mysql.fi monty@hundin.mysql.fi monty@mashka.mysql.fi +monty@mishka.mysql.fi monty@narttu. monty@narttu.mysql.fi monty@tik. diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index c9cb77d2a3a..e6772c4c0ac 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -284,5 +284,4 @@ insert into t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, "Sergei"); -drop table if exists t1; - +drop table t1; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 1940ff360c2..49e13f0e415 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -66,10 +66,10 @@ static int send_file(THD *thd) NET* net = &thd->net; int fd = -1,bytes, error = 1; char fname[FN_REFLEN+1]; - char *buf; const char *errmsg = 0; int old_timeout; uint packet_len; + char buf[IO_SIZE]; // It's safe to alloc this DBUG_ENTER("send_file"); // the client might be slow loading the data, give him wait_timeout to do @@ -77,13 +77,6 @@ static int send_file(THD *thd) old_timeout = thd->net.timeout; thd->net.timeout = thd->inactive_timeout; - // spare the stack - if(!(buf = alloc_root(&thd->mem_root,IO_SIZE))) - { - errmsg = "Out of memory"; - goto err; - } - // we need net_flush here because the client will not know it needs to send // us the file name until it has processed the load event entry if (net_flush(net) || (packet_len = my_net_read(net)) == packet_error) From a49ef9a555bcd3ec5d43298a2decbf1b41b674ff Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 15 Oct 2003 19:50:47 -0400 Subject: [PATCH 05/49] Created small scripts to manage in-tree diffs for NetWare platform, so changes are visible in the tree but cannot affect other platforms. --- netware/BUILD/apply-patch | 41 ++++++++++++++++++++++++++++ netware/BUILD/save-patch | 56 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100755 netware/BUILD/apply-patch create mode 100755 netware/BUILD/save-patch diff --git a/netware/BUILD/apply-patch b/netware/BUILD/apply-patch new file mode 100755 index 00000000000..3fe5a077f9a --- /dev/null +++ b/netware/BUILD/apply-patch @@ -0,0 +1,41 @@ +#! /bin/sh + +# debug +#set -x + +# stop on errors +set -e + +# repository directory +repo_dir=`pwd` + +# show usage +show_usage() +{ + cat << EOF + +usage: apply-patch + +Imports netware/current-changes.patch so that current changes +for the platform are present on the local repository. + +Use from the root directory of the repository, with BitKeeper +installed. + +EOF + exit 0; +} + +if test $1 || test -z $BK_USER +then + show_usage +fi + +echo "starting patch..." + +echo "user: $BK_USER" + +# import patch +# Note: In future this should be changed to check whether +# the repo already has this patch +bk import -tpatch $repo_dir/netware/current-changes.patch $repo_dir diff --git a/netware/BUILD/save-patch b/netware/BUILD/save-patch new file mode 100755 index 00000000000..9f9979ace5b --- /dev/null +++ b/netware/BUILD/save-patch @@ -0,0 +1,56 @@ +#! /bin/sh + +# debug +#set -x + +# stop on errors +set -e + +# repository directory +repo_dir=`pwd` + +# show usage +show_usage() +{ + cat << EOF + +usage: save-patch + +Creates a patch file between the latest revision of the current tree +and the latest revision not created by \$BK_USER and places it in +the tree as netware/current-changes.patch + +EOF + exit 0; +} + +if test $1 || test -z $BK_USER +then + show_usage +fi + +echo "starting patch..." + +echo "user: $BK_USER" + +# check for bk and repo_dir +bk help > /dev/null +repo_dir=`bk root $repo_dir` +cd $repo_dir + +# determine version +version=`grep -e "AM_INIT_AUTOMAKE(mysql, .*)" < configure.in | sed -e "s/AM_INIT_AUTOMAKE(mysql, \(.*\))/\1/"` +echo "version: $version" + +# user revision +user_rev=`bk changes -e -n -d':REV:' | head -1` +echo "latest revision: $user_rev" + +# tree revision +tree_rev=`bk changes -e -n -d':REV:' -U$BK_USER | head -1` +echo "latest non-$BK_USER revision: $tree_rev" + +# create patch +patch="$repo_dir/netware/current-changes.patch" +echo "creating \"$patch\"..." +bk export -tpatch -r$tree_rev..$user_rev -xnetware/current-changes.patch > $patch From ca5383cfe561afe80b20cfbb7ac7cc0f4e6c429c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Oct 2003 17:00:09 +0400 Subject: [PATCH 06/49] fix for one of the bugs spotted by #1274 sql/sql_select.cc: back to the bug #1274: the following query EXPLAIN SELECT SQL_CALC_FOUND_ROWS race_name FROM races WHERE race_name LIKE '%Madison%' ORDER BY race_date DESC LIMIT 0,100 +-------+------+---------------+------+---------+------+--------+-----------------------------+ | table | type | possible_keys | key | key_len | ref | rows | Extra | +-------+------+---------------+------+---------+------+--------+-----------------------------+ | races | ALL | NULL | NULL | NULL | NULL | 505821 | Using where; Using filesort | +-------+------+---------------+------+---------+------+--------+-----------------------------+ The query returns no rows. There are two problems with it: - wrong access plan is chosed (sequential index scan in reverse order, which is VERY SLOW in case of MyISAM table + packed keys) It's wrong, because it doesn't take into account that SQL_CALC_FOUND_ROWS is present, in other words, is based on assumtion that LIMIT clause decrease number of rows to access significantly, which is not true as all rows are accessed. - the access plan is not shown in the EXPLAIN (bug #1560). I'm not fixing it here --- sql/sql_select.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 353a4623962..f1ab998c0fa 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -968,10 +968,20 @@ mysql_select(THD *thd,TABLE_LIST *tables,List &fields,COND *conds, } } } + /* + Here we sort rows for ORDER BY/GROUP BY clause, if the optimiser + chose FILESORT to be faster than INDEX SCAN or there is no + suitable index present. + Note, that create_sort_index calls test_if_skip_sort_order and may + finally replace sorting with index scan if there is a LIMIT clause in + the query. XXX: it's never shown in EXPLAIN! + OPTION_FOUND_ROWS supersedes LIMIT and is taken into account. + */ if (create_sort_index(&join.join_tab[join.const_tables], group ? group : order, select_limit, - thd->select_limit)) + join.select_options & OPTION_FOUND_ROWS ? + HA_POS_ERROR : thd->select_limit)) goto err; } join.having=having; // Actually a parameter From 4f936a69a798483b318fad4124641256eb0ce380 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Oct 2003 20:55:15 +0300 Subject: [PATCH 07/49] Safety fix to detect multiple calls to my_thread_end() Portability fix (For Mac OS X) configure.in: Added detection of malloc / sys/malloc include/my_pthread.h: Safety fix to detect multiple calls to my_thread_end() libmysqld/lib_sql.cc: Remove duplicate call to my_thread_end() mysys/charset.c: Cleanup indentation Remove some short variable names mysys/my_thr_init.c: Safety fix to detect multiple calls to my_thread_end() sql/sql_test.cc: Portability fix (For Mac OS X) --- configure.in | 2 +- include/my_pthread.h | 1 + libmysqld/lib_sql.cc | 5 ---- mysys/charset.c | 66 +++++++++++++++++++++++++++++--------------- mysys/my_thr_init.c | 9 ++++-- sql/sql_test.cc | 4 +++ 6 files changed, 56 insertions(+), 31 deletions(-) diff --git a/configure.in b/configure.in index f085d365ed2..8ce3a9aea67 100644 --- a/configure.in +++ b/configure.in @@ -733,7 +733,7 @@ AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \ strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \ sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \ unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \ - sys/ioctl.h) + sys/ioctl.h malloc.h sys/malloc.h) #-------------------------------------------------------------------- # Check for system libraries. Adds the library to $LIBS diff --git a/include/my_pthread.h b/include/my_pthread.h index 4247b951d82..16a14ac5038 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -637,6 +637,7 @@ struct st_my_thread_var long id; int cmp_length; int volatile abort; + my_bool init; #ifndef DBUG_OFF gptr dbug; char name[THREAD_NAME_SIZE+1]; diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 52ff08b8787..d33f384f81e 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -621,11 +621,6 @@ void STDCALL mysql_server_end() my_free((char*) copy_arguments_ptr, MYF(MY_ALLOW_ZERO_PTR)); copy_arguments_ptr=0; clean_up(0); -#ifdef THREAD - /* Don't call my_thread_end() if the application is using MY_INIT() */ - if (!org_my_init_done) - my_thread_end(); -#endif /* If library called my_init(), free memory allocated by it */ if (!org_my_init_done) my_end(0); diff --git a/mysys/charset.c b/mysys/charset.c index 6a64730571c..ba6733185e0 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -453,20 +453,37 @@ static my_bool charset_in_string(const char *name, DYNAMIC_STRING *s) static void charset_append(DYNAMIC_STRING *s, const char *name) { - if (!charset_in_string(name, s)) { + if (!charset_in_string(name, s)) + { dynstr_append(s, name); dynstr_append(s, " "); } } -/* Returns a dynamically-allocated string listing the character sets - requested. The caller is responsible for freeing the memory. */ +/* + Returns a dynamically-allocated string listing the character sets + requested. + + SYNOPSIS + list_charsets() + want_flags Flags for which character sets to return: + MY_COMPILED_SETS: Return incompiled charsets + MY_INDEX_SETS: + MY_LOADED_SETS: + + NOTES + The caller is responsible for freeing the memory. + + + RETURN + A string with available character sets separated by space +*/ char * list_charsets(myf want_flags) { DYNAMIC_STRING s; - char *p; + char *result; (void)init_available_charsets(MYF(0)); init_dynamic_string(&s, NullS, 256, 1024); @@ -483,42 +500,45 @@ char * list_charsets(myf want_flags) if (want_flags & MY_CONFIG_SETS) { - CS_ID **c; + CS_ID **charset; char buf[FN_REFLEN]; MY_STAT status; - if((c=available_charsets)) - for (; *c; ++c) - { - if (charset_in_string((*c)->name, &s)) - continue; - get_charset_conf_name((*c)->number, buf); - if (!my_stat(buf, &status, MYF(0))) - continue; /* conf file doesn't exist */ - dynstr_append(&s, (*c)->name); - dynstr_append(&s, " "); - } + if ((charset=available_charsets)) + { + for (; *charset; charset++) + { + if (charset_in_string((*charset)->name, &s)) + continue; + get_charset_conf_name((*charset)->number, buf); + if (!my_stat(buf, &status, MYF(0))) + continue; /* conf file doesn't exist */ + dynstr_append(&s, (*charset)->name); + dynstr_append(&s, " "); + } + } } if (want_flags & MY_INDEX_SETS) { - CS_ID **c; - for (c = available_charsets; *c; ++c) - charset_append(&s, (*c)->name); + CS_ID **charset; + for (charset = available_charsets; *charset; charset++) + charset_append(&s, (*charset)->name); } if (want_flags & MY_LOADED_SETS) { uint i; for (i = 0; i < cs_info_table.elements; i++) - charset_append(&s, + charset_append(&s, dynamic_element(&cs_info_table, i, CHARSET_INFO *)->name); } - s.str[s.length - 1] = '\0'; /* chop trailing space */ - p = my_strdup(s.str, MYF(MY_WME)); + if (s.length) + s.length--; /* Remove end space */ + result= my_strdup_with_length(s.str, s.length, MYF(MY_WME)); dynstr_free(&s); - return p; + return result; } /**************************************************************************** diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 59466083b28..9f64e9dcb60 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -159,6 +159,7 @@ my_bool my_thread_init(void) tmp->id= ++thread_id; pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST); pthread_cond_init(&tmp->suspend, NULL); + tmp->init= 1; end: #if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX) @@ -170,12 +171,14 @@ end: void my_thread_end(void) { - struct st_my_thread_var *tmp=my_thread_var; + struct st_my_thread_var *tmp; + tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_end(): tmp=%p,thread_id=%ld\n", tmp,pthread_self()); #endif - if (tmp) + if (tmp && tmp->init) { #if !defined(DBUG_OFF) /* tmp->dbug is allocated inside DBUG library */ @@ -191,6 +194,8 @@ void my_thread_end(void) pthread_mutex_destroy(&tmp->mutex); #if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS) free(tmp); +#else + tmp->init= 0; #endif } /* The following free has to be done, even if my_thread_var() is 0 */ diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 6498a52cc09..a217d40246f 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -22,7 +22,11 @@ #include "sql_select.h" #include #include +#if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_H) #include +#elif defined(HAVE_MALLINFO) && defined(HAVE_SYS_MALLOC_H) +#include +#endif /* Intern key cache variables */ extern "C" pthread_mutex_t THR_LOCK_keycache; From de01431b1897b2d93e884fe18310b9a3cf3f31b9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Oct 2003 22:15:36 +0200 Subject: [PATCH 08/49] - fixed small typo to resolve "test: argument expected" error on Solaris and Tru64 when running "mysql_install_db" --- scripts/mysql_install_db.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 5a6b11fb19b..ba95ff3b5b9 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -136,7 +136,7 @@ then fi fi -if test "$ip_only" ="1" +if test "$ip_only" = "1" then ip=`echo "$resolved" | awk '/ /{print $6}'` hostname=$ip From 0b8743c1b2da849d876887ea102c44a7ca9c1c37 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Oct 2003 00:00:25 +0200 Subject: [PATCH 09/49] A fix for a random test failure rpl_trunc_binlog: don't RESET MASTER while the slave is connected. mysql-test/t/rpl_trunc_binlog.test: don't RESET MASTER while the slave is connected; this could confuse the master or slave. (In replication you don't RESET MASTER while a slave is connected!) sql/slave.cc: typo --- mysql-test/t/rpl_trunc_binlog.test | 2 -- sql/slave.cc | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/mysql-test/t/rpl_trunc_binlog.test b/mysql-test/t/rpl_trunc_binlog.test index 11ec0026560..2c34b7a442f 100644 --- a/mysql-test/t/rpl_trunc_binlog.test +++ b/mysql-test/t/rpl_trunc_binlog.test @@ -22,5 +22,3 @@ start slave; sleep 3; --replace_result $MASTER_MYPORT MASTER_PORT show slave status; -connection master; -reset master; diff --git a/sql/slave.cc b/sql/slave.cc index 9c380408291..b679ac2f6b8 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1337,7 +1337,7 @@ file '%s', errno %d)", fname, my_errno); if (init_relay_log_pos(rli,NullS,BIN_LOG_HEADER_SIZE,0 /* no data lock */, &msg)) { - sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4"); + sql_print_error("Failed to open the relay log 'FIRST' (relay_log_pos 4)"); goto err; } rli->master_log_name[0]= 0; From 246d37076e75a509829b160e6d306067955a023d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Oct 2003 02:32:09 +0200 Subject: [PATCH 10/49] - Updated rpl_trunc_binlog test result after last change --- mysql-test/r/rpl_trunc_binlog.result | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result index a006437207a..eb5dcf7c593 100644 --- a/mysql-test/r/rpl_trunc_binlog.result +++ b/mysql-test/r/rpl_trunc_binlog.result @@ -11,4 +11,3 @@ start slave; show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space 127.0.0.1 root MASTER_PORT 1 master-bin.002 4 slave-relay-bin.002 161 master-bin.001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. Probably cause is that the master died while writing the transaction to it's binary log. 0 79 317 -reset master; From a2128b247faaf6b9c68b95e1a3c895c6ec58f500 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Oct 2003 09:15:30 +0200 Subject: [PATCH 11/49] test update: what we want to detect in this test is if the slave stopped. mysql-test/r/rpl_trunc_binlog.result: result update mysql-test/t/rpl_trunc_binlog.test: what we want to detect in this test is if the slave stopped. --- mysql-test/r/rpl_trunc_binlog.result | 4 ---- mysql-test/t/rpl_trunc_binlog.test | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result index a006437207a..19d5e30addb 100644 --- a/mysql-test/r/rpl_trunc_binlog.result +++ b/mysql-test/r/rpl_trunc_binlog.result @@ -8,7 +8,3 @@ stop slave; flush logs; reset slave; start slave; -show slave status; -Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space -127.0.0.1 root MASTER_PORT 1 master-bin.002 4 slave-relay-bin.002 161 master-bin.001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. Probably cause is that the master died while writing the transaction to it's binary log. 0 79 317 -reset master; diff --git a/mysql-test/t/rpl_trunc_binlog.test b/mysql-test/t/rpl_trunc_binlog.test index 2c34b7a442f..59d8aed288c 100644 --- a/mysql-test/t/rpl_trunc_binlog.test +++ b/mysql-test/t/rpl_trunc_binlog.test @@ -20,5 +20,4 @@ reset slave; start slave; # can't sync_with_master so we must sleep sleep 3; ---replace_result $MASTER_MYPORT MASTER_PORT -show slave status; +wait_for_slave_to_stop; From 35e7a5400dc094aa95bd1415e40234d104850d8b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Oct 2003 09:26:38 +0200 Subject: [PATCH 12/49] cancelling a previous change I made in rpl_trunc_binlog.test (which I did not push), to enable SHOW SLAVE STATUS again. mysql-test/r/rpl_trunc_binlog.result: enabling SHOW SLAVE STATUS again. mysql-test/t/rpl_trunc_binlog.test: enabling SHOW SLAVE STATUS again --- mysql-test/r/rpl_trunc_binlog.result | 3 +++ mysql-test/t/rpl_trunc_binlog.test | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result index 19d5e30addb..eb5dcf7c593 100644 --- a/mysql-test/r/rpl_trunc_binlog.result +++ b/mysql-test/r/rpl_trunc_binlog.result @@ -8,3 +8,6 @@ stop slave; flush logs; reset slave; start slave; +show slave status; +Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space +127.0.0.1 root MASTER_PORT 1 master-bin.002 4 slave-relay-bin.002 161 master-bin.001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. Probably cause is that the master died while writing the transaction to it's binary log. 0 79 317 diff --git a/mysql-test/t/rpl_trunc_binlog.test b/mysql-test/t/rpl_trunc_binlog.test index 59d8aed288c..2c34b7a442f 100644 --- a/mysql-test/t/rpl_trunc_binlog.test +++ b/mysql-test/t/rpl_trunc_binlog.test @@ -20,4 +20,5 @@ reset slave; start slave; # can't sync_with_master so we must sleep sleep 3; -wait_for_slave_to_stop; +--replace_result $MASTER_MYPORT MASTER_PORT +show slave status; From 14affe7e2fa5287aa205353e80615d089861a104 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Oct 2003 23:44:34 +0300 Subject: [PATCH 13/49] thr0loc.c, srv0start.c, srv0srv.c, srv0srv.h, os0thread.h, ha_innodb.cc: Backport from 4.1: reduce InnoDB memory consumption if buf pool < 8 MB sql/ha_innodb.cc: Backport from 4.1: reduce InnoDB memory consumption if buf pool < 8 MB innobase/include/os0thread.h: Backport from 4.1: reduce InnoDB memory consumption if buf pool < 8 MB innobase/include/srv0srv.h: Backport from 4.1: reduce InnoDB memory consumption if buf pool < 8 MB innobase/srv/srv0srv.c: Backport from 4.1: reduce InnoDB memory consumption if buf pool < 8 MB innobase/srv/srv0start.c: Backport from 4.1: reduce InnoDB memory consumption if buf pool < 8 MB innobase/thr/thr0loc.c: Backport from 4.1: reduce InnoDB memory consumption if buf pool < 8 MB --- innobase/include/os0thread.h | 11 +++-------- innobase/include/srv0srv.h | 2 ++ innobase/srv/srv0srv.c | 14 +++++++++++--- innobase/srv/srv0start.c | 22 ++++++++++++++++++++++ innobase/thr/thr0loc.c | 1 + sql/ha_innodb.cc | 5 ----- 6 files changed, 39 insertions(+), 16 deletions(-) diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h index 491d8866af4..554ca0563e4 100644 --- a/innobase/include/os0thread.h +++ b/innobase/include/os0thread.h @@ -15,14 +15,9 @@ Created 9/8/1995 Heikki Tuuri /* Maximum number of threads which can be created in the program; this is also the size of the wait slot array for MySQL threads which can wait inside InnoDB */ -#if defined(__WIN__) || defined(__NETWARE__) -/* Create less event semaphores because Win 98/ME had difficult creating -40000 event semaphores */ -/* TODO: these just take a lot of memory on NetWare. should netware move up? */ -#define OS_THREAD_MAX_N 1000 -#else -#define OS_THREAD_MAX_N 10000 -#endif + +#define OS_THREAD_MAX_N srv_max_n_threads + /* Possible fixed priorities for threads */ #define OS_THREAD_PRIORITY_NONE 100 diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index f4255fc9a98..87df3904f19 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -80,6 +80,8 @@ extern ulint srv_max_dirty_pages_pct; extern ulint srv_force_recovery; extern ulint srv_thread_concurrency; +extern ulint srv_max_n_threads; + extern lint srv_conc_n_threads; extern ibool srv_fast_shutdown; diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index f31d275eff0..8aba1b4f414 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -142,7 +142,7 @@ byte srv_latin1_ordering[256] /* The sort order table of the latin1 ulint srv_pool_size = ULINT_MAX; /* size in database pages; MySQL originally sets this - value in megabytes */ + value in bytes */ ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */ ulint srv_lock_table_size = ULINT_MAX; @@ -169,6 +169,12 @@ the user from forgetting the innodb_force_recovery keyword to my.cnf */ ulint srv_force_recovery = 0; /*-----------------------*/ +/* We are prepared for a situation that we have this many threads waiting for +a semaphore inside InnoDB. innobase_start_or_create_for_mysql() sets the +value. */ + +ulint srv_max_n_threads = 0; + /* The following controls how many threads we let inside InnoDB concurrently: threads waiting for locks are not counted into the number because otherwise we could get a deadlock. MySQL creates a thread for each user session, and @@ -208,7 +214,7 @@ struct srv_conc_slot_struct{ UT_LIST_BASE_NODE_T(srv_conc_slot_t) srv_conc_queue; /* queue of threads waiting to get in */ -srv_conc_slot_t srv_conc_slots[OS_THREAD_MAX_N]; /* array of wait +srv_conc_slot_t* srv_conc_slots; /* array of wait slots */ /* Number of times a thread is allowed to enter InnoDB within the same @@ -1693,6 +1699,8 @@ srv_init(void) os_fast_mutex_init(&srv_conc_mutex); UT_LIST_INIT(srv_conc_queue); + + srv_conc_slots = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_conc_slot_t)); for (i = 0; i < OS_THREAD_MAX_N; i++) { conc_slot = srv_conc_slots + i; @@ -1740,7 +1748,7 @@ srv_conc_enter_innodb( thread */ { ibool has_slept = FALSE; - srv_conc_slot_t* slot; + srv_conc_slot_t* slot = NULL; ulint i; char err_buf[1000]; diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index a85c3615c1b..af4ca71d443 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1087,6 +1087,28 @@ innobase_start_or_create_for_mysql(void) return(DB_ERROR); } + /* Set the maximum number of threads which can wait for a semaphore + inside InnoDB */ +#if defined(__WIN__) || defined(__NETWARE__) + +/* Create less event semaphores because Win 98/ME had difficulty creating +40000 event semaphores. +Comment from Novell, Inc.: also, these just take a lot of memory on +NetWare. */ + srv_max_n_threads = 1000; +#else + if (srv_pool_size >= 8 * 1024 * 1024) { + /* Here we still have srv_pool_size counted + in bytes, srv_boot converts the value to + pages; if buffer pool is less than 8 MB, + assume fewer threads. */ + srv_max_n_threads = 10000; + } else { + srv_max_n_threads = 1000; /* saves several MB of memory, + especially in 64-bit + computers */ + } +#endif err = srv_boot(); if (err != DB_SUCCESS) { diff --git a/innobase/thr/thr0loc.c b/innobase/thr/thr0loc.c index fbf3e3a1dad..839cb024f25 100644 --- a/innobase/thr/thr0loc.c +++ b/innobase/thr/thr0loc.c @@ -14,6 +14,7 @@ Created 10/5/1995 Heikki Tuuri #include "sync0sync.h" #include "hash0hash.h" #include "mem0mem.h" +#include "srv0srv.h" /* IMPLEMENTATION OF THREAD LOCAL STORAGE diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 3619fefdd1b..47c49b79d77 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -17,11 +17,6 @@ /* This file defines the InnoDB handler: the interface between MySQL and InnoDB */ -/* TODO list for the InnoDB handler: - - Ask Monty if strings of different languages can exist in the same - database. Answer: in 4.1 yes. -*/ - #ifdef __GNUC__ #pragma implementation // gcc: Class implementation #endif From 931d4fccc0e1dc2a2c0882f54dbd1f2bcea885ef Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 19 Oct 2003 20:28:03 +0300 Subject: [PATCH 14/49] os0file.c: Check that writes to data files always happen in to addresses divisible by 16 kB, and the chunk size is also divisible by 16 kB; a user reported 2 corrupt pages from Linux-2.4.20 where an index page seemed displaced innobase/os/os0file.c: Check that writes to data files always happen in to addresses divisible by 16 kB, and the chunk size is also divisible by 16 kB; a user reported 2 corrupt pages from Linux-2.4.20 where an index page seemed displaced --- innobase/os/os0file.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 311937f2145..24bc0f1bdf9 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -2676,7 +2676,11 @@ consecutive_loop: /* Do the i/o with ordinary, synchronous i/o functions: */ if (slot->type == OS_FILE_WRITE) { if (array == os_aio_write_array) { - + if ((total_len % UNIV_PAGE_SIZE != 0) + || (slot->offset % UNIV_PAGE_SIZE != 0)) { + ut_a(0); + } + /* Do a 'last millisecond' check that the page end is sensible; reported page checksum errors from Linux seem to wipe over the page end */ From a2611f9ec61ab3de5177d389aa204db98548da14 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 19 Oct 2003 20:31:32 +0300 Subject: [PATCH 15/49] os0file.c: Check that writes to data files always happen in to addresses divisible by 16 kB, and the chunk size is also divisible by 16 kB; a user reported 2 corrupt pages from Linux-2.4.20 where an index page seemed displaced innobase/os/os0file.c: Check that writes to data files always happen in to addresses divisible by 16 kB, and the chunk size is also divisible by 16 kB; a user reported 2 corrupt pages from Linux-2.4.20 where an index page seemed displaced --- innobase/os/os0file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 24bc0f1bdf9..55d0ade1bf7 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -2678,6 +2678,10 @@ consecutive_loop: if (array == os_aio_write_array) { if ((total_len % UNIV_PAGE_SIZE != 0) || (slot->offset % UNIV_PAGE_SIZE != 0)) { + fprintf(stderr, +"InnoDB: Error: trying a displaced write to %s %lu %lu, len %lu\n", + slot->name, slot->offset_high, + slot->offset, total_len); ut_a(0); } From 409b8f35d43a23b660bc5a5f439a3375d2c20d36 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Oct 2003 15:35:03 +0200 Subject: [PATCH 16/49] Fix for Bug #1595 "mysqlbinlog can't read a password from the console". Make mysqlbinlog prompt for the password if mysqlbinlog -p instead of printing the usage(). This makes mysqlbinlog behave like other clients, which is the reason why we fix this in 3.23. This new code was almost copied from mysqldump. Note that before, one could use mysqlbinlog -p pass and now one must use mysqlbinlog -ppass (putting a space will ask for the password). client/mysqlbinlog.cc: Make mysqlbinlog prompt for the password if mysqlbinlog -p instead of printing the usage(). This makes mysqlbinlog behave like other clients, which is the reason why we fix this in 3.23. This new code was almost copied from mysqldump. Note that before, one could use mysqlbinlog -p pass and now one must use mysqlbinlog -ppass (putting a space will ask for the password). --- client/mysqlbinlog.cc | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 6d1e711fa98..e0cee438f1b 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -54,7 +54,7 @@ static struct option long_options[] = {"help", no_argument, 0, '?'}, {"host", required_argument, 0, 'h'}, {"offset", required_argument, 0, 'o'}, - {"password", required_argument, 0, 'p'}, + {"password", optional_argument, 0, 'p'}, {"port", required_argument, 0, 'P'}, {"position", required_argument, 0, 'j'}, {"result-file", required_argument, 0, 'r'}, @@ -71,7 +71,7 @@ static ulonglong offset = 0; static const char* host = "localhost"; static int port = MYSQL_PORT; static const char* user = "test"; -static const char* pass = ""; +static char* pass = 0; static ulonglong position = 0; static bool use_remote = 0; static short binlog_flags = 0; @@ -84,6 +84,7 @@ static void dump_log_entries(const char* logname); static void dump_remote_file(NET* net, const char* fname); static void dump_remote_table(NET* net, const char* db, const char* table); static void die(const char* fmt, ...); +static void cleanup(); static MYSQL* safe_connect(); @@ -97,6 +98,11 @@ void sql_print_error(const char *format,...) va_end(args); } +static void cleanup() +{ + my_free(pass,MYF(MY_ALLOW_ZERO_PTR)); +} + static void die(const char* fmt, ...) { va_list args; @@ -105,6 +111,7 @@ static void die(const char* fmt, ...) vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); + cleanup(); exit(1); } @@ -177,9 +184,10 @@ static void dump_remote_file(NET* net, const char* fname) static int parse_args(int *argc, char*** argv) { int c, opt_index = 0; + bool tty_password= 0; result_file = stdout; - while((c = getopt_long(*argc, *argv, "so:#::h:j:u:p:P:r:t:?V", long_options, + while((c = getopt_long(*argc, *argv, "so:#::h:j:u:p::P:r:t:?V", long_options, &opt_index)) != EOF) { switch(c) @@ -213,7 +221,17 @@ static int parse_args(int *argc, char*** argv) case 'p': use_remote = 1; - pass = my_strdup(optarg, MYF(0)); + if (optarg) + { + char *start=optarg; + my_free(pass,MYF(MY_ALLOW_ZERO_PTR)); + pass= my_strdup(optarg,MYF(MY_FAE)); + while (*optarg) *optarg++= 'x'; /* Destroy argument */ + if (*start) + start[1]=0; /* Cut length of argument */ + } + else + tty_password=1; break; case 'r': @@ -244,6 +262,8 @@ static int parse_args(int *argc, char*** argv) (*argc)-=optind; (*argv)+=optind; + if (tty_password) + pass= get_tty_password(NullS); return 0; } @@ -457,6 +477,7 @@ int main(int argc, char** argv) my_fclose(result_file, MYF(0)); if (use_remote) mysql_close(mysql); + cleanup(); return 0; } From 42de9a3ed95af04abfb0a77b79bddd6f2327d6b9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Oct 2003 15:14:06 +0500 Subject: [PATCH 17/49] Fix for bug #1271: Undefined variable in PASSWORD() function is not handled correctly --- mysql-test/r/func_crypt.result | 10 ++++++++++ mysql-test/t/func_crypt.test | 9 +++++++++ sql/item_func.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_crypt.result b/mysql-test/r/func_crypt.result index 742de833bf7..96bbaa6cae7 100644 --- a/mysql-test/r/func_crypt.result +++ b/mysql-test/r/func_crypt.result @@ -7,3 +7,13 @@ old_password('test') password('test') select length(encrypt('test')), encrypt('test','aa'); length(encrypt('test')) encrypt('test','aa') 13 aaqPiZY5xR5l. +drop table if exists t1; +create table t1 (name varchar(50), pw varchar(16)); +insert into t1 values ('tom', password('my_pass')); +set @pass='my_pass'; +select name from t1 where name='tom' and pw=password(@pass); +name +tom +select name from t1 where name='tom' and pw=password(@undefined); +name +drop table t1; diff --git a/mysql-test/t/func_crypt.test b/mysql-test/t/func_crypt.test index f403d96e885..e612405c5e9 100644 --- a/mysql-test/t/func_crypt.test +++ b/mysql-test/t/func_crypt.test @@ -4,3 +4,12 @@ select length(encrypt('foo', 'ff')) <> 0; --replace_result $1$aa$4OSUA5cjdx0RUQ08opV27/ aaqPiZY5xR5l. select old_password('test'), password('test'); select length(encrypt('test')), encrypt('test','aa'); + +drop table if exists t1; +create table t1 (name varchar(50), pw varchar(16)); +insert into t1 values ('tom', password('my_pass')); +set @pass='my_pass'; +select name from t1 where name='tom' and pw=password(@pass); +select name from t1 where name='tom' and pw=password(@undefined); +drop table t1; + diff --git a/sql/item_func.cc b/sql/item_func.cc index fd6d17d0cf2..8d7ee637d73 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2087,7 +2087,7 @@ void Item_func_get_user_var::fix_length_and_dec() bool Item_func_get_user_var::const_item() const { - return var_entry && current_thd->query_id != var_entry->update_query_id; + return (!var_entry || current_thd->query_id != var_entry->update_query_id); } From 3e937ef4e2b7104668e63a5fa11f2cd7460cff6f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Oct 2003 12:22:24 +0200 Subject: [PATCH 18/49] Fix for Bug #1595 "mysqlbinlog can't read a password from the console". ** I already fixed it in 3.23; I fix it in 4.0 separately because the code is a bit different (so the changeset 1.1422 of 3.23 should not be merged here) ** Make mysqlbinlog prompt for the password if mysqlbinlog -p instead of printing the usage(). This makes mysqlbinlog behave like other clients. This new code was almost copied from mysqldump. Note that before, one could use mysqlbinlog -p pass and now one must use mysqlbinlog -ppass (putting a space will ask for the password). client/mysqlbinlog.cc: Make mysqlbinlog prompt for the password if mysqlbinlog -p instead of printing the usage(). This makes mysqlbinlog behave like other clients. This new code was almost copied from mysqldump. Note that before, one could use mysqlbinlog -p pass and now one must use mysqlbinlog -ppass (putting a space will ask for the password). --- client/mysqlbinlog.cc | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 298521b5aa7..34b7ae11f74 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -52,7 +52,7 @@ static const char* host = 0; static int port = MYSQL_PORT; static const char* sock= 0; static const char* user = 0; -static const char* pass = ""; +static char* pass = 0; static ulonglong position = 0; static short binlog_flags = 0; static MYSQL* mysql = NULL; @@ -227,7 +227,7 @@ static struct my_option my_long_options[] = {"offset", 'o', "Skip the first N entries.", (gptr*) &offset, (gptr*) &offset, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to connect to remote server.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Use port to connect to the remote server.", (gptr*) &port, (gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, @@ -267,6 +267,11 @@ void sql_print_error(const char *format,...) va_end(args); } +static void cleanup() +{ + my_free(pass,MYF(MY_ALLOW_ZERO_PTR)); +} + static void die(const char* fmt, ...) { va_list args; @@ -275,6 +280,7 @@ static void die(const char* fmt, ...) vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); + cleanup(); exit(1); } @@ -334,6 +340,7 @@ extern "C" my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { + bool tty_password=0; switch (optid) { #ifndef DBUG_OFF case '#': @@ -344,7 +351,17 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), one_database = 1; break; case 'p': - pass = my_strdup(argument, MYF(0)); + if (argument) + { + my_free(pass,MYF(MY_ALLOW_ZERO_PTR)); + char *start=argument; + pass= my_strdup(argument,MYF(MY_FAE)); + while (*argument) *argument++= 'x'; /* Destroy argument */ + if (*start) + start[1]=0; /* Cut length of argument */ + } + else + tty_password=1; break; case 'r': if (!(result_file = my_fopen(argument, O_WRONLY | O_BINARY, MYF(MY_WME)))) @@ -360,6 +377,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), usage(); exit(0); } + if (tty_password) + pass= get_tty_password(NullS); + return 0; } @@ -778,6 +798,7 @@ int main(int argc, char** argv) my_fclose(result_file, MYF(0)); if (remote_opt) mysql_close(mysql); + cleanup(); free_defaults(defaults_argv); my_end(0); return 0; From 77c89711d20160e6f42aa512f45c1558a97e43e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Oct 2003 17:34:40 +0200 Subject: [PATCH 19/49] Bug#1271 - RAND_TABLE_BIT in expression and only const_tables in join --- sql/sql_select.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f1ab998c0fa..55813378b9c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2600,6 +2600,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) table_map used_tables; if (join->tables > 1) cond->update_used_tables(); // Tablenr may have changed + if (join->const_tables == join->tables) + join->const_table_map|=RAND_TABLE_BIT; { // Check const tables COND *const_cond= make_cond_for_table(cond,join->const_table_map,(table_map) 0); From 50baee8c0bb31e129df8021d5e80a1cdd2e87922 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Oct 2003 18:41:19 +0200 Subject: [PATCH 20/49] - bumped up version number in configure.in to to 4.0.17 now that 4.0.16 has been tagged and released - tagged ChangeSet 1.1576.1.5 as "mysql-4.0.16" configure.in: - bumped up version number to 4.0.17 now that 4.0.16 has been tagged and released --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 8ce3a9aea67..02825ce1424 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 4.0.16) +AM_INIT_AUTOMAKE(mysql, 4.0.17) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From 15988a374d9237e9111c07960b4e8c176530f66e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Oct 2003 16:02:27 +0300 Subject: [PATCH 21/49] Applied a patch from Travis Wheeler to mysqlhotcopy that allows using regexp with tablenames together with databasenames. --- scripts/mysqlhotcopy.sh | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index f23955da06a..3e53af32653 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -37,7 +37,7 @@ WARNING: THIS PROGRAM IS STILL IN BETA. Comments/patches welcome. # Documentation continued at end of file -my $VERSION = "1.19"; +my $VERSION = "1.20"; my $opt_tmpdir = $ENV{TMPDIR} || "/tmp"; @@ -235,10 +235,15 @@ else # --- resolve database names from regexp --- if ( defined $opt{regexp} ) { + my $t_regex = '.*'; + if ( $opt{regexp} =~ s{^/(.+)/\./(.+)/$}{$1} ) { + $t_regex = $2; + } + my $sth_dbs = $dbh->prepare("show databases"); $sth_dbs->execute; while ( my ($db_name) = $sth_dbs->fetchrow_array ) { - push @db_desc, { 'src' => $db_name } if ( $db_name =~ m/$opt{regexp}/o ); + push @db_desc, { 'src' => $db_name, 't_regex' => $t_regex } if ( $db_name =~ m/$opt{regexp}/o ); } } @@ -938,6 +943,14 @@ server in a mutual replication setup. Copy all databases with names matching the pattern +=item --regexp /pattern1/./pattern2/ + +Copy all tables with names matching pattern2 from all databases with +names matching pattern1. For example, to select all tables which +names begin with 'bar' from all databases which names end with 'foo': + + mysqlhotcopy --indices --method=cp --regexp /foo$/./^bar/ + =item db_name./pattern/ Copy only tables matching pattern. Shell metacharacters ( (, ), |, !, From cbc5304742cdb7da8cd3ef8dbcfe15eef01cdb1e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Oct 2003 18:19:59 +0300 Subject: [PATCH 22/49] Fixed bug #954 mysqlhotcopy permission problem. The database directory owner ship was not honored. --- scripts/mysqlhotcopy.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 3e53af32653..654e5466e12 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -418,6 +418,8 @@ foreach my $rdb ( @db_desc ) { else { mkdir($tgt_dirpath, 0750) or die "Can't create '$tgt_dirpath': $!\n" unless -d $tgt_dirpath; + my @f_info= stat "$datadir/$rdb->{src}"; + chown $f_info[4], $f_info[5], $tgt_dirpath; } } } From 3fdca01f2426b0c40324bed9e416f58733d96c57 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Oct 2003 18:40:37 +0300 Subject: [PATCH 23/49] Fixed a bug in mysqlhotcopy, which made special table names to cause program to abort. Such table name could have been one with a semicolon (:) in the middle. --- scripts/mysqlhotcopy.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 654e5466e12..160a2611374 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -453,13 +453,13 @@ if ( $opt{dryrun} ) { } else { my $start = time; - $dbh->do("LOCK TABLES $hc_locks"); + $dbh->do('LOCK TABLES $hc_locks'); printf "Locked $num_tables tables in %d seconds.\n", time-$start unless $opt{quiet}; $hc_started = time; # count from time lock is granted # flush tables to make on-disk copy uptodate $start = time; - $dbh->do("FLUSH TABLES /*!32323 $hc_tables */"); + $dbh->do('FLUSH TABLES /*!32323 $hc_tables */'); printf "Flushed tables ($hc_tables) in %d seconds.\n", time-$start unless $opt{quiet}; $dbh->do( "FLUSH LOGS" ) if ( $opt{flushlog} ); $dbh->do( "RESET MASTER" ) if ( $opt{resetmaster} ); @@ -467,7 +467,7 @@ else { if ( $opt{record_log_pos} ) { record_log_pos( $dbh, $opt{record_log_pos} ); - $dbh->do("FLUSH TABLES /*!32323 $hc_tables */"); + $dbh->do('FLUSH TABLES /*!32323 $hc_tables */'); } } From a6aeb62749b826093aed2862cd33ea71583a9d32 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Oct 2003 19:24:19 +0300 Subject: [PATCH 24/49] Reverted a wrong patch from mysqlhotcopy. This is a real bug in MySQL server... --- scripts/mysqlhotcopy.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 160a2611374..654e5466e12 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -453,13 +453,13 @@ if ( $opt{dryrun} ) { } else { my $start = time; - $dbh->do('LOCK TABLES $hc_locks'); + $dbh->do("LOCK TABLES $hc_locks"); printf "Locked $num_tables tables in %d seconds.\n", time-$start unless $opt{quiet}; $hc_started = time; # count from time lock is granted # flush tables to make on-disk copy uptodate $start = time; - $dbh->do('FLUSH TABLES /*!32323 $hc_tables */'); + $dbh->do("FLUSH TABLES /*!32323 $hc_tables */"); printf "Flushed tables ($hc_tables) in %d seconds.\n", time-$start unless $opt{quiet}; $dbh->do( "FLUSH LOGS" ) if ( $opt{flushlog} ); $dbh->do( "RESET MASTER" ) if ( $opt{resetmaster} ); @@ -467,7 +467,7 @@ else { if ( $opt{record_log_pos} ) { record_log_pos( $dbh, $opt{record_log_pos} ); - $dbh->do('FLUSH TABLES /*!32323 $hc_tables */'); + $dbh->do("FLUSH TABLES /*!32323 $hc_tables */"); } } From f1a9ebe932d560c6dfab6c5c17aec4cfbc54129a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Oct 2003 14:04:06 +0300 Subject: [PATCH 25/49] Fix results after merge --- mysql-test/r/myisam.result | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 3052af3499d..e113a48f4da 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -83,7 +83,6 @@ OPTIMIZE TABLE t1; Table Op Msg_type Msg_text test.t1 optimize status OK DROP TABLE t1; -drop table if exists t1; create table t1 ( t1 char(255), key(t1(250))); insert t1 values ('137513751375137513751375137513751375137569516951695169516951695169516951695169'); insert t1 values ('178417841784178417841784178417841784178403420342034203420342034203420342034203'); From 375f9514765c57b29a4a790c1526d580d417f39c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Oct 2003 15:24:48 +0200 Subject: [PATCH 26/49] Put username in the Subject line as well (with the changeset number). --- BitKeeper/triggers/post-commit | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index 636e4262693..7f803732d5b 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -19,7 +19,8 @@ BK_STATUS=$BK_STATUS$BK_COMMIT if [ "$BK_STATUS" = OK ] then -CHANGESET=`bk -R prs -r+ -h -d':I:' ChangeSet` +USRN=`echo $FROM | sed 's/\(..*\)@.*/\1/'` +CHANGESET=${USRN}:`bk -R prs -r+ -h -d':I:' ChangeSet` #++ # dev-public@ From e05ea7b8ea985dbb2daa56f7b02baa4b65dd9503 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Oct 2003 14:22:54 +0300 Subject: [PATCH 27/49] Move the pid file testing after arguments are parsed (previous patch was not correct) --- support-files/mysql.server.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 89d45e0f26d..36eb5c4dff6 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -108,19 +108,6 @@ else test -z "$print_defaults" && print_defaults="my_print_defaults" fi -# -# Set pid file if not given -# -if test -z "$pid_file" -then - pid_file=$datadir/`@HOSTNAME@`.pid -else - case "$pid_file" in - /* ) ;; - * ) pid_file="$datadir/$pid_file" ;; - esac -fi - # # Test if someone changed datadir; In this case we should also read the # default arguments from this directory @@ -134,6 +121,19 @@ fi parse_arguments `$print_defaults $extra_args mysqld mysql_server mysql.server` +# +# Set pid file if not given +# +if test -z "$pid_file" +then + pid_file=$datadir/`@HOSTNAME@`.pid +else + case "$pid_file" in + /* ) ;; + * ) pid_file="$datadir/$pid_file" ;; + esac +fi + # Safeguard (relative paths, core dumps..) cd $basedir From ddd5eebd1ecd6a2cdb81624d62bea588ece97d71 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Oct 2003 15:20:46 -0400 Subject: [PATCH 28/49] added to mysql_secure_installation changing root password on all hosts (bug 1228) scripts/mysql_secure_installation.sh: added changing root password on all hosts --- scripts/mysql_secure_installation.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh index d6392c57731..1c7ca34ad59 100644 --- a/scripts/mysql_secure_installation.sh +++ b/scripts/mysql_secure_installation.sh @@ -85,9 +85,13 @@ set_root_password() { return 1 fi - do_query "SET PASSWORD FOR root=PASSWORD('$password1');" + do_query "UPDATE mysql.user SET Password=PASSWORD('$password1') WHERE User='root';" if [ $? -eq 0 ]; then echo "Password updated successfully!" + echo "Reloading privilege tables.." + if ! reload_privilege_tables; then + exit 1 + fi echo rootpass=$password1 make_config @@ -144,11 +148,11 @@ reload_privilege_tables() { do_query "FLUSH PRIVILEGES;" if [ $? -eq 0 ]; then echo " ... Success!" + return 0 else echo " ... Failed!" + return 1 fi - - return 0 } interrupt() { From 800f2f46d16ecf467b9f65c6a35acde1ce9ea6ff Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Oct 2003 17:26:26 -0400 Subject: [PATCH 29/49] added quotas for database names (fixed bug #1348) client/mysqldump.c: added quotas for database names --- client/mysqldump.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index b28373ccd4a..40f88021c89 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1271,10 +1271,13 @@ static int init_dumping(char *database) { if (opt_databases || opt_alldbs) { + /* length of table name * 2 (if name contain quotas), 2 quotas and 0 */ + char quoted_database_buf[64*2+3]; + char *qdatabase= quote_name(database,quoted_database_buf,opt_quoted); fprintf(md_result_file,"\n--\n-- Current Database: %s\n--\n", database); if (!opt_create_db) fprintf(md_result_file,"\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n", - database); + qdatabase); fprintf(md_result_file,"\nUSE %s;\n", database); } } From 489b3926db788a9d28804b57012229ad78ceed95 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Oct 2003 22:43:19 +0200 Subject: [PATCH 30/49] cleanup --- BitKeeper/triggers/post-commit | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index 7f803732d5b..2dfefb5deb3 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -19,8 +19,7 @@ BK_STATUS=$BK_STATUS$BK_COMMIT if [ "$BK_STATUS" = OK ] then -USRN=`echo $FROM | sed 's/\(..*\)@.*/\1/'` -CHANGESET=${USRN}:`bk -R prs -r+ -h -d':I:' ChangeSet` +CHANGESET=`bk -R prs -r+ -h -d':P:::I:' ChangeSet` #++ # dev-public@ From 8f917ccd9d6aab3f6c57a3953a2f8daa0a1d2f8a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Oct 2003 11:18:44 +0100 Subject: [PATCH 31/49] correct casting in ulonglong2double --- include/config-win.h | 4 ++-- include/my_global.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/config-win.h b/include/config-win.h index 9f903b3bcd2..53dff5d63af 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -173,8 +173,8 @@ inline double rint(double nr) } #ifdef _WIN64 -#define ulonglong2double(A) ((double) (A)) -#define my_off_t2double(A) ((double) (A)) +#define ulonglong2double(A) ((double) (ulonglong) (A)) +#define my_off_t2double(A) ((double) (my_off_t) (A)) #else inline double ulonglong2double(ulonglong value) diff --git a/include/my_global.h b/include/my_global.h index 59e0c43f18d..349ac8ac82e 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -571,8 +571,8 @@ extern double my_atof(const char*); #define closesocket(A) close(A) #endif #ifndef ulonglong2double -#define ulonglong2double(A) ((double) (A)) -#define my_off_t2double(A) ((double) (A)) +#define ulonglong2double(A) ((double) (ulonglong) (A)) +#define my_off_t2double(A) ((double) (my_off_t) (A)) #endif #endif From 8507b00b34d4857cb702b1be1ea6b199007025d7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Oct 2003 15:14:03 +0100 Subject: [PATCH 32/49] fixes for max_user_connections (connections are now counted even if max_user_connections is not set - that is no limit - so that when max_user_connections is set (with SET) old connections are also taken into account mutexes are added where appropriate --- sql/sql_parse.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e068c309e21..ebcfc2bdec1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -156,7 +156,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, uc->user_len= user_len; uc->host=uc->user + uc->user_len + 1; uc->len = temp_len; - uc->connections = 1; + uc->connections = 0; uc->questions=uc->updates=uc->conn_per_hour=0; uc->user_resources=*mqh; if (max_user_connections && mqh->connections > max_user_connections) @@ -171,6 +171,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, } } thd->user_connect=uc; + uc->connections++; end: (void) pthread_mutex_unlock(&LOCK_user_conn); return return_val; @@ -255,8 +256,8 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, if ((ur.questions || ur.updates || ur.connections || max_user_connections) && get_or_create_user_conn(thd,user,thd->host_or_ip,&ur)) return -1; - if (thd->user_connect && ((thd->user_connect->user_resources.connections) || - max_user_connections) && + if (thd->user_connect && (thd->user_connect->user_resources.connections || + max_user_connections) && check_for_max_user_connections(thd->user_connect)) return -1; if (db && db[0]) @@ -303,16 +304,17 @@ static int check_for_max_user_connections(USER_CONN *uc) int error=0; DBUG_ENTER("check_for_max_user_connections"); + (void) pthread_mutex_lock(&LOCK_user_conn); if (max_user_connections && - (max_user_connections < (uint) uc->connections)) + max_user_connections <= uc->connections) { net_printf(&(current_thd->net),ER_TOO_MANY_USER_CONNECTIONS, uc->user); error=1; + uc->connections--; goto end; } - uc->connections++; if (uc->user_resources.connections && - uc->conn_per_hour++ >= uc->user_resources.connections) + uc->user_resources.connections <= uc->conn_per_hour) { net_printf(¤t_thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_connections", @@ -320,7 +322,9 @@ static int check_for_max_user_connections(USER_CONN *uc) error=1; goto end; } + uc->conn_per_hour++; end: + (void) pthread_mutex_unlock(&LOCK_user_conn); DBUG_RETURN(error); } @@ -328,13 +332,14 @@ end: static void decrease_user_connections(USER_CONN *uc) { DBUG_ENTER("decrease_user_connections"); - if ((uc->connections && !--uc->connections) && !mqh_used) + (void) pthread_mutex_lock(&LOCK_user_conn); + DBUG_ASSERT(uc->connections); + if (!--uc->connections && !mqh_used) { /* Last connection for user; Delete it */ - (void) pthread_mutex_lock(&LOCK_user_conn); (void) hash_delete(&hash_user_connections,(byte*) uc); - (void) pthread_mutex_unlock(&LOCK_user_conn); } + (void) pthread_mutex_unlock(&LOCK_user_conn); DBUG_VOID_RETURN; } @@ -1026,7 +1031,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->priv_user=save_priv_user; break; } - if (max_connections && save_uc) + if (save_uc) decrease_user_connections(save_uc); x_free((gptr) save_db); x_free((gptr) save_user); From 710418eb081b1ed1af2c5860b16cff2bbbeaf5dc Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Oct 2003 15:55:18 +0200 Subject: [PATCH 33/49] row0sel.c: If innodb_force_recovery >= 5, do not try to fetch an old version of a clustered index record: this reduces crashes when dumping tables from a corrupt database innobase/row/row0sel.c: If innodb_force_recovery >= 5, do not try to fetch an old version of a clustered index record: this reduces crashes when dumping tables from a corrupt database --- innobase/row/row0sel.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 482f82b02ba..f02fbeeb8fd 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -3222,8 +3222,14 @@ rec_loop: latest version of the record */ } else if (index == clust_index) { - - if (!lock_clust_rec_cons_read_sees(rec, index, + + /* Fetch a previous version of the row if the current + one is not visible in the snapshot; if we have a very + high force recovery level set, we try to avoid crashes + by skipping this lookup */ + + if (srv_force_recovery < 5 + && !lock_clust_rec_cons_read_sees(rec, index, trx->read_view)) { err = row_sel_build_prev_vers_for_mysql( From b11f9c1053733207073088223122c8b2fb3d1682 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Oct 2003 18:36:41 +0200 Subject: [PATCH 34/49] Fix for problem of installing MySQL as a service with mysql --install mysql --defualts-file=path-to-file (Bug #1643) include/mysql_com.h: MySQL should install as default service "mysqld" sql/mysqld.cc: Fix for problem of installing MySQL as a service with mysql --install mysql --defualts-file=path-to-file --- include/mysql_com.h | 2 +- sql/mysqld.cc | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index 6daf26bc2ac..27307b690b9 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -31,7 +31,7 @@ #if defined(__WIN__) && !defined( _CUSTOMCONFIG_) #define MYSQL_NAMEDPIPE "MySQL" -#define MYSQL_SERVICENAME "MySql" +#define MYSQL_SERVICENAME "mysqld" #endif /* __WIN__ */ enum enum_server_command { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 811984e50b4..5073f8e1c40 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1958,7 +1958,7 @@ extern "C" pthread_handler_decl(handle_shutdown,arg) #endif -const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0 }; +const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0,0}; bool open_log(MYSQL_LOG *log, const char *hostname, const char *opt_name, const char *extension, @@ -2561,7 +2561,7 @@ default_service_handling(char **argv, const char *extra_opt) { char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end; - end= path_and_service + sizeof(path_and_service)-1; + end= path_and_service + sizeof(path_and_service)-3; /* We have to quote filename if it contains spaces */ pos= add_quoted_string(path_and_service, file_path, end); @@ -2571,7 +2571,9 @@ default_service_handling(char **argv, *pos++= ' '; pos= add_quoted_string(pos, extra_opt, end); } - *pos= 0; // Ensure end null + /* We must have servicename last */ + *pos++= ' '; + strmake(pos, servicename, (uint) (end+2 - pos)); if (Service.got_service_option(argv, "install")) { @@ -2616,7 +2618,7 @@ int main(int argc, char **argv) if (Service.IsService(argv[1])) { /* start an optional service */ - load_default_groups[0]= argv[1]; + load_default_groups[3]= argv[1]; start_mode= 1; Service.Init(argv[1], mysql_service); return 0; @@ -2624,8 +2626,7 @@ int main(int argc, char **argv) } else if (argc == 3) /* install or remove any optional service */ { - if (!default_service_handling(argv, argv[2], argv[2], file_path, - argv[2])) + if (!default_service_handling(argv, argv[2], argv[2], file_path, "")) return 0; if (Service.IsService(argv[2])) { @@ -2637,6 +2638,7 @@ int main(int argc, char **argv) opt_argc= 2; // Skip service-name opt_argv=argv; start_mode= 1; + load_default_groups[3]= argv[2]; Service.Init(argv[2], mysql_service); return 0; } From 5f2611d318b59504813e9200b160d2b15bf6996e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Oct 2003 08:33:31 +0100 Subject: [PATCH 35/49] followup to max_user_connections fix, keep the count more accurate --- sql/sql_parse.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ebcfc2bdec1..e63e85e99c6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -303,14 +303,13 @@ static int check_for_max_user_connections(USER_CONN *uc) { int error=0; DBUG_ENTER("check_for_max_user_connections"); - + (void) pthread_mutex_lock(&LOCK_user_conn); if (max_user_connections && - max_user_connections <= uc->connections) + max_user_connections < uc->connections) { net_printf(&(current_thd->net),ER_TOO_MANY_USER_CONNECTIONS, uc->user); error=1; - uc->connections--; goto end; } if (uc->user_resources.connections && @@ -324,6 +323,8 @@ static int check_for_max_user_connections(USER_CONN *uc) } uc->conn_per_hour++; end: + if (error) + uc->connections--; // no need for decrease_user_connections() here (void) pthread_mutex_unlock(&LOCK_user_conn); DBUG_RETURN(error); } From 03dbf8ccbb649825d7aafd9f00234bee35111de9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Oct 2003 14:23:35 +0100 Subject: [PATCH 36/49] Fix for BUG#1686 "If 2 master threads with same-name temp table, slave makes bad binlog" and (two birds with one stone) for BUG#1240 "slave of slave breaks when STOP SLAVE was issud on parent slave and temp tables". Here is the design change: in a slave running with --log-slave-updates, events are now logged with the thread id they had on the master. So no more id conflicts between master threads, but introduces id conflicts between one master thread and one normal client thread connected to the slave. This is solved by storing the server id in the temp table's name. New test which requires mysql-test-run to be run with --manager, otherwise it will be skipped. Undoing a Monty's change (hum, a chill runs down my spine ;) which was "Cleanup temporary tables when slave ends" in ChangeSet 1.1572.1.1. mysql-test/mysql-test-run.sh: One new test which needs more than one slave so must be hardcoded in mysql-test-run.sh. sql/log_event.cc: The event needs to carry a slave_proxy_id (which is set at event's creation and used at event's logging). This is used for events created by ::exec_event() in the slave SQL thread: now we want to log these events with the thread id they had on the master. This is so that several same-name temp tables simultaneously created on the master end up with not the same thread id in the slave's binlog. sql/log_event.h: Query and Load need to carry a slave_proxy_id, like they carried a thread_id (to replicate temp tables well). sql/slave.cc: Do not free temp tables in the slave SQL thread. Or they will be lost when one does STOP SLAVE / START SLAVE. We even save them in rli->save_temporary_tables and set thd->temporary_tables=0 to prevent them to be freed. sql/sql_base.cc: Put the server id in the table cache key name for temp tables (we already put the slave_proxy_id, but we also need the server id in case normal clients (not slave threads) are using temp tables on the slave). sql/unireg.h: 4 more bytes, to store the server id. --- mysql-test/mysql-test-run.sh | 2 +- mysql-test/r/rpl_chain_temp_table.result | 30 ++++++++ mysql-test/t/rpl_chain_temp_table.test | 89 ++++++++++++++++++++++++ sql/log_event.cc | 56 ++++++++++++--- sql/log_event.h | 8 +++ sql/slave.cc | 2 - sql/sql_base.cc | 25 +++++-- sql/unireg.h | 2 +- 8 files changed, 197 insertions(+), 17 deletions(-) create mode 100644 mysql-test/r/rpl_chain_temp_table.result create mode 100644 mysql-test/t/rpl_chain_temp_table.test diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 6cba5eecddd..d155c02c652 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -1161,7 +1161,7 @@ run_testcase () echo $tname > $CURRENT_TEST SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0` if [ $USE_MANAGER = 1 ] ; then - many_slaves=`$EXPR \( $tname : rpl_failsafe \) != 0` + many_slaves=`$EXPR \( \( $tname : rpl_failsafe \) != 0 \) \| \( \( $tname : rpl_chain_temp_table \) != 0 \)` fi if [ -n "$SKIP_TEST" ] ; then diff --git a/mysql-test/r/rpl_chain_temp_table.result b/mysql-test/r/rpl_chain_temp_table.result new file mode 100644 index 00000000000..5ece80565c7 --- /dev/null +++ b/mysql-test/r/rpl_chain_temp_table.result @@ -0,0 +1,30 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +reset master; +change master to master_host='127.0.0.1',master_port=9307, master_user='root'; +start slave; +create temporary table t1 (a int); +create temporary table t1 (a int); +show status like 'slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 2 +create temporary table t1 (a int); +create temporary table t1 (a int); +show status like 'slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 4 +stop slave; +insert into t1 values(1); +create table t2 as select * from t1; +start slave; +show status like 'slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 4 +select * from t2; +a +1 +drop table t2; diff --git a/mysql-test/t/rpl_chain_temp_table.test b/mysql-test/t/rpl_chain_temp_table.test new file mode 100644 index 00000000000..65701d8a078 --- /dev/null +++ b/mysql-test/t/rpl_chain_temp_table.test @@ -0,0 +1,89 @@ + # This test makes some assumptions about values of thread ids, which should be +# true if the servers have been restarted for this test. So we want to +# stop/restart servers. Note that if assumptions are wrong, the test will not +# fail; it will just fail to test the error-prone scenario. +# Using the manager is the only way to have more than one slave server. + +require_manager; +server_stop master; +server_start master; +server_stop slave; +server_start slave; +# no need for slave_sec (no assumptions on thread ids for this server). + +source include/master-slave.inc; +connect (slave_sec,localhost,root,,test,0,slave.sock-1); +connection master; +save_master_pos; +connection slave; +sync_with_master; +reset master; +save_master_pos; +connection slave_sec; +eval change master to master_host='127.0.0.1',master_port=$SLAVE_MYPORT, master_user='root'; +start slave; +sync_with_master; + +# :P now we have a chain ready-to-test. + +connection master; +create temporary table t1 (a int); +save_master_pos; +connection slave; +sync_with_master; +connection master1; +create temporary table t1 (a int); +save_master_pos; +connection slave; +sync_with_master; +save_master_pos; + +# First test: + +connection slave_sec; +# Before BUG#1686 ("If 2 master threads with same-name temp table, slave makes +# bad binlog") was fixed, sync_with_master failed +sync_with_master; +show status like 'slave_open_temp_tables'; + +# 'master' and 'master1' usually have thread id 2-3 or 3-4. +# 'slave' and 'slave1' usually have thread id 2-3. +connection slave; +create temporary table t1 (a int); +connection slave1; +create temporary table t1 (a int); +# So it's likely that in the binlog of slave we get +# server_id=of_master thread_id=3 create temp... +# server_id=of_slave thread_id=3 create temp... +# which would confuse slave-sec unless slave-sec uses server id to distinguish +# between temp tables (here thread id is obviously not enough to distinguish). + +save_master_pos; + +# Second test: + +connection slave_sec; +# If we did not use the server id to distinguish between temp tables, +# sync_with_master would fail +sync_with_master; +show status like 'slave_open_temp_tables'; + +# Third test (BUG#1240 "slave of slave breaks when STOP SLAVE was issud on +# parent slave and temp tables"). +stop slave; +connection slave; +insert into t1 values(1); +create table t2 as select * from t1; +save_master_pos; +connection slave_sec; +start slave; +sync_with_master; +show status like 'slave_open_temp_tables'; +select * from t2; + +# clean up +connection slave; +drop table t2; +save_master_pos; +connection slave_sec; +sync_with_master; diff --git a/sql/log_event.cc b/sql/log_event.cc index 699d1ff866d..36d2d33ade6 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -834,8 +834,11 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans) :Log_event(thd_arg, 0, using_trans), data_buf(0), query(query_arg), db(thd_arg->db), q_len((uint32) query_length), - error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno), - thread_id(thd_arg->thread_id) + error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno), + thread_id(thd_arg->thread_id), + /* save the original thread id; we already know the server id */ + slave_proxy_id(thd_arg->slave_proxy_id) + { time_t end_time; time(&end_time); @@ -918,7 +921,42 @@ int Query_log_event::write_data(IO_CACHE* file) return -1; char buf[QUERY_HEADER_LEN]; - int4store(buf + Q_THREAD_ID_OFFSET, thread_id); + /* + We want to store the thread id: + (- as an information for the user when he reads the binlog) + - if the query uses temporary table: for the slave SQL thread to know to + which master connection the temp table belongs. + Now imagine we (write_data()) are called by the slave SQL thread (we are + logging a query executed by this thread; the slave runs with + --log-slave-updates). Then this query will be logged with + thread_id=the_thread_id_of_the_SQL_thread. Imagine that 2 temp tables of the + same name were created simultaneously on the master (in the master binlog + you have + CREATE TEMPORARY TABLE t; (thread 1) + CREATE TEMPORARY TABLE t; (thread 2) + ...) + then in the slave's binlog there will be + CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread) + CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread) + which is bad (same thread id!). + To avoid this, we log the thread's thread id EXCEPT for the SQL slave thread + for which we log the original (master's) thread id. + Now this moves the bug: what happens if the thread id on the master was 10 + and when the slave replicates the query, a connection number 10 is opened by + a normal client on the slave, and updates a temp table of the same name? We + get a problem again. To avoid this, in the handling of temp tables + (sql_base.cc) we use thread_id AND server_id. + TODO when this is merged into 4.1: in 4.1, slave_proxy_id has been renamed + to pseudo_thread_id and is a session variable: that's to make mysqlbinlog + work with temp tables. We probably need to introduce + SET PSEUDO_SERVER_ID + for mysqlbinlog in 4.1. mysqlbinlog would print: + SET PSEUDO_SERVER_ID= + SET PSEUDO_THREAD_ID= + for each query using temp tables. + */ + int4store(buf + Q_THREAD_ID_OFFSET, (slave_proxy_id ? slave_proxy_id : + thread_id)); int4store(buf + Q_EXEC_TIME_OFFSET, exec_time); buf[Q_DB_LEN_OFFSET] = (char) db_len; int2store(buf + Q_ERR_CODE_OFFSET, error_code); @@ -1019,7 +1057,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db) int Load_log_event::write_data_header(IO_CACHE* file) { char buf[LOAD_HEADER_LEN]; - int4store(buf + L_THREAD_ID_OFFSET, thread_id); + int4store(buf + L_THREAD_ID_OFFSET, (slave_proxy_id ? slave_proxy_id : + thread_id)); int4store(buf + L_EXEC_TIME_OFFSET, exec_time); int4store(buf + L_SKIP_LINES_OFFSET, skip_lines); buf[L_TBL_LEN_OFFSET] = (char)table_name_len; @@ -1143,10 +1182,11 @@ Load_log_event::Load_log_event(THD* thd_arg, sql_exchange* ex, enum enum_duplicates handle_dup, bool using_trans) :Log_event(thd_arg, 0, using_trans),thread_id(thd_arg->thread_id), - num_fields(0),fields(0), - field_lens(0),field_block_len(0), - table_name(table_name_arg ? table_name_arg : ""), - db(db_arg), fname(ex->file_name) + slave_proxy_id(thd_arg->slave_proxy_id), + num_fields(0),fields(0), + field_lens(0),field_block_len(0), + table_name(table_name_arg ? table_name_arg : ""), + db(db_arg), fname(ex->file_name) { time_t end_time; time(&end_time); diff --git a/sql/log_event.h b/sql/log_event.h index 227c0243b9c..2e6b7373dc2 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -320,6 +320,13 @@ public: uint32 db_len; uint16 error_code; ulong thread_id; + /* + For events created by Query_log_event::exec_event (and + Load_log_event::exec_event()) we need the *original* thread id, to be able + to log the event with the original (=master's) thread id (fix for + BUG#1686). + */ + ulong slave_proxy_id; #ifndef MYSQL_CLIENT Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, @@ -390,6 +397,7 @@ protected: public: ulong thread_id; + ulong slave_proxy_id; uint32 table_name_len; uint32 db_len; uint32 fname_len; diff --git a/sql/slave.cc b/sql/slave.cc index b679ac2f6b8..90b0cc74fd8 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2719,8 +2719,6 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ RPL_LOG_NAME, llstr(rli->master_log_pos,llbuff)); err: - /* Free temporary tables etc */ - thd->cleanup(); VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety VOID(pthread_mutex_unlock(&LOCK_thread_count)); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1010378825f..47529b90b67 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -589,6 +589,8 @@ TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name) uint key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1; TABLE *table,**prev; + int4store(key+key_length,thd->server_id); + key_length += 4; int4store(key+key_length,thd->slave_proxy_id); key_length += 4; @@ -617,18 +619,27 @@ bool close_temporary_table(THD *thd, const char *db, const char *table_name) return 0; } +/* + Used by ALTER TABLE when the table is a temporary one. It changes something + only if the ALTER contained a RENAME clause (otherwise, table_name is the old + name). + Prepares a table cache key, which is the concatenation of db, table_name and + thd->slave_proxy_id, separated by '\0'. +*/ bool rename_temporary_table(THD* thd, TABLE *table, const char *db, const char *table_name) { char *key; if (!(key=(char*) alloc_root(&table->mem_root, (uint) strlen(db)+ - (uint) strlen(table_name)+6))) + (uint) strlen(table_name)+6+4))) return 1; /* purecov: inspected */ table->key_length=(uint) (strmov((table->real_name=strmov(table->table_cache_key=key, db)+1), table_name) - table->table_cache_key)+1; + int4store(key+table->key_length,thd->server_id); + table->key_length += 4; int4store(key+table->key_length,thd->slave_proxy_id); table->key_length += 4; return 0; @@ -783,12 +794,13 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, if (thd->killed) DBUG_RETURN(0); key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1; - int4store(key + key_length, thd->slave_proxy_id); + int4store(key + key_length, thd->server_id); + int4store(key + key_length + 4, thd->slave_proxy_id); for (table=thd->temporary_tables; table ; table=table->next) { - if (table->key_length == key_length+4 && - !memcmp(table->table_cache_key,key,key_length+4)) + if (table->key_length == key_length+8 && + !memcmp(table->table_cache_key,key,key_length+8)) { if (table->query_id == thd->query_id) { @@ -1596,7 +1608,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, total of 6 extra bytes in my_malloc in addition to table/db stuff */ if (!(tmp_table=(TABLE*) my_malloc(sizeof(*tmp_table)+(uint) strlen(db)+ - (uint) strlen(table_name)+6, + (uint) strlen(table_name)+6+4, MYF(MY_WME)))) DBUG_RETURN(0); /* purecov: inspected */ @@ -1618,6 +1630,9 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, strmov(tmp_table->table_cache_key,db) +1), table_name) - tmp_table->table_cache_key)+1; + int4store(tmp_table->table_cache_key + tmp_table->key_length, + thd->server_id); + tmp_table->key_length += 4; int4store(tmp_table->table_cache_key + tmp_table->key_length, thd->slave_proxy_id); tmp_table->key_length += 4; diff --git a/sql/unireg.h b/sql/unireg.h index f2cace51fa7..37157311e15 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -43,7 +43,7 @@ #define ERRMAPP 1 /* Errormap f|r my_error */ #define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */ -#define MAX_DBKEY_LENGTH (FN_LEN*2+6) /* extra 4 bytes for slave tmp +#define MAX_DBKEY_LENGTH (FN_LEN*2+1+1+4+4) /* extra 4+4 bytes for slave tmp * tables */ #define MAX_FIELD_NAME 34 /* Max colum name length +2 */ #define MAX_SYS_VAR_LENGTH 32 From 7da08881a34b9c04dda6c0559742f360a5306224 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Oct 2003 01:01:53 +0200 Subject: [PATCH 37/49] Change back service name to MySQL Don't add service name to read config file segments if it's "MySQL" Fixed possible memory leak when CHANGE USER failed. include/mysql_com.h: Change back service name to MySQL (With new, better spelling) myisam/myisamchk.c: Improved --help sql/mysqld.cc: Don't add service name to read config file segments if it's "MySQL" sql/sql_parse.cc: Fixed possible memory leak when CHANGE USER failed. --- include/mysql_com.h | 2 +- myisam/myisamchk.c | 6 ++++-- sql/mysqld.cc | 12 +++++++++--- sql/sql_parse.cc | 12 ++++++++---- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index 27307b690b9..a874034ba46 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -31,7 +31,7 @@ #if defined(__WIN__) && !defined( _CUSTOMCONFIG_) #define MYSQL_NAMEDPIPE "MySQL" -#define MYSQL_SERVICENAME "mysqld" +#define MYSQL_SERVICENAME "MySQL" #endif /* __WIN__ */ enum enum_server_command { diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index b7627fc59fd..f1deda41f8b 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -401,7 +401,9 @@ static void usage(void) Change the character set used by the index\n\ -q, --quick Faster repair by not modifying the data file.\n\ One can give a second '-q' to force myisamchk to\n\ - modify the original datafile in case of duplicate keys\n\ + modify the original datafile in case of duplicate keys.\n\ + NOTE: Tables where the data file is currupted can't be\n\ + fixed with this option.\n\ -u, --unpack Unpack file packed with myisampack.\n\ "); @@ -1094,7 +1096,7 @@ end2: filename)); if (param->testflag & T_REP_ANY) VOID(fprintf(stderr, - "Try fixing it by using the --safe-recover (-o) or the --force (-f) option\n")); + "Try fixing it by using the --safe-recover (-o), the --force (-f) option or by not using the --quick (-q) flag\n")); } else if (!(param->error_printed & 2) && !(param->testflag & T_FORCE_CREATE)) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5073f8e1c40..cdcf13ca7bf 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2615,10 +2615,16 @@ int main(int argc, char **argv) if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME, file_path, "")) return 0; - if (Service.IsService(argv[1])) + if (Service.IsService(argv[1])) /* Start an optional service */ { - /* start an optional service */ - load_default_groups[3]= argv[1]; + /* + Only add the service name to the groups read from the config file + if it's not "MySQL". (The default service name should be 'mysqld' + but we started a bad tradition by calling it MySQL from the start + and we are now stuck with it. + */ + if (my_strcasecmp(argv[1],"mysql")) + load_default_groups[3]= argv[1]; start_mode= 1; Service.Init(argv[1], mysql_service); return 0; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e63e85e99c6..0789a1768d1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1013,14 +1013,17 @@ bool dispatch_command(enum enum_server_command command, THD *thd, char *save_user= thd->user; char *save_priv_user= thd->priv_user; char *save_db= thd->db; - thd->user=0; - USER_CONN *save_uc= thd->user_connect; + USER_CONN *save_user_connect= thd->user_connect; if ((uint) ((uchar*) db - net->read_pos) > packet_length) { // Check if protocol is ok send_error(net, ER_UNKNOWN_COM_ERROR); break; } + + /* Clear variables that are allocated */ + thd->user= 0; + thd->user_connect= 0; if (check_user(thd, COM_CHANGE_USER, user, passwd, db, 0)) { // Restore old user x_free(thd->user); @@ -1030,10 +1033,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->db_length=save_db_length; thd->user=save_user; thd->priv_user=save_priv_user; + thd->user_connect= save_user_connect; break; } - if (save_uc) - decrease_user_connections(save_uc); + if (save_user_connect) + decrease_user_connections(save_user_connect); x_free((gptr) save_db); x_free((gptr) save_user); break; From cee3ddb401579ff062ac349103fcfcb33cb247e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Oct 2003 01:20:38 +0200 Subject: [PATCH 38/49] Safety fix for adding service name to search config groups --- sql/mysqld.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index cdcf13ca7bf..e5ddbfe7a33 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2644,7 +2644,8 @@ int main(int argc, char **argv) opt_argc= 2; // Skip service-name opt_argv=argv; start_mode= 1; - load_default_groups[3]= argv[2]; + if (my_strcasecmp(argv[2],"mysql")) + load_default_groups[3]= argv[2]; Service.Init(argv[2], mysql_service); return 0; } From 55686819aa73b09a84da05a734dc810f969a9597 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Oct 2003 12:25:15 +0300 Subject: [PATCH 39/49] fix for bug #1634 '"operator new" in my_new wastes memory' BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + mysys/my_new.cc | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 4c1777f1434..afb9c5cff5c 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -48,6 +48,7 @@ jcole@sarvik.tfr.cafe.ee jcole@tetra.spaceapes.com jorge@linux.jorge.mysql.com kaj@work.mysql.com +konstantin@mysql.com kostja@oak.local lenz@kallisto.mysql.com lenz@mysql.com diff --git a/mysys/my_new.cc b/mysys/my_new.cc index 5cc291af9aa..5f2da90bbd1 100644 --- a/mysys/my_new.cc +++ b/mysys/my_new.cc @@ -25,12 +25,12 @@ void *operator new (size_t sz) { - return (void *) malloc (sz ? sz+1 : sz); + return (void *) malloc (sz ? sz : 1); } void *operator new[] (size_t sz) { - return (void *) malloc (sz ? sz+1 : sz); + return (void *) malloc (sz ? sz : 1); } void operator delete (void *ptr) From b4bc448eba986c5a1daecb8c70df8b093402bd10 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Oct 2003 16:12:21 +0100 Subject: [PATCH 40/49] Fix to be able to run mysql-test-run --manager --valgrind (without this fix, the manager fails to start mysqld and the tests hang). mysql-test/mysql-test-run.sh: When running with --manager: the MySQL manager wants the complete path of the executable (it uses execv(), not execvp(), so does not search in the $PATH, so telling him to start 'valgrind' is not enough, it wants '/usr/bin/valgrind' or so). So this is a fix to be able to mysql-test-run --manager --valgrind Plus a warning (previously, if valgrind was not installed, tests silently hanged when run with --valgrind). --- mysql-test/mysql-test-run.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index d155c02c652..cd409e1ace5 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -336,7 +336,13 @@ while test $# -gt 0; do EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --gdb" ;; --valgrind) - VALGRIND="valgrind --alignment=8 --leak-check=yes --num-callers=16" + VALGRIND=`which valgrind` # this will print an error if not found + # Give good warning to the user and stop + if [ -z "$VALGRIND" ] ; then + $ECHO "You need to have the 'valgrind' program in your PATH to run mysql-test-run with option --valgrind. Valgrind's home page is http://developer.kde.org/~sewardj ." + exit 1 + fi + VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16" EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc --skip-bdb" EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc --skip-bdb" SLEEP_TIME_AFTER_RESTART=10 From 1d1bdcc6fe61a0a2487e62dbc478ca9cd5650677 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Oct 2003 21:30:20 +0300 Subject: [PATCH 41/49] comments about designation of thd->where and thd->proc_info added sql/sql_class.h: comments about thd->where and thd->proc_info added --- sql/sql_class.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sql/sql_class.h b/sql/sql_class.h index 27258c025d8..58543a3d230 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -379,7 +379,11 @@ public: char priv_host[MAX_HOSTNAME]; /* remote (peer) port */ uint16 peer_port; - /* Points to info-string that will show in SHOW PROCESSLIST */ + /* + Points to info-string that we show in SHOW PROCESSLIST + You are supposed to update thd->proc_info only if you have coded + a time-consuming piece that MySQL can get stuck in for a long time. + */ const char *proc_info; /* points to host if host is available, otherwise points to ip */ const char *host_or_ip; @@ -408,6 +412,11 @@ public: enum enum_server_command command; uint32 server_id; uint32 file_id; // for LOAD DATA INFILE + /* + Used in error messages to tell user in what part of MySQL we found an + error. E. g. when where= "having clause", if fix_fields() fails, user + will know that the error was in having clause. + */ const char *where; time_t start_time,time_after_lock,user_time; time_t connect_time,thr_create_time; // track down slow pthread_create From 9396db013a543b3f26e4c53e5e02244a9a2031d5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 31 Oct 2003 17:03:08 +0300 Subject: [PATCH 42/49] thd->query assignment moved out of lock scope --- sql/log_event.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 36d2d33ade6..4f241c6b992 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1826,8 +1826,8 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) thd->set_time((time_t)when); thd->current_tablenr = 0; thd->query_length= q_len; + thd->query= (char *) query; VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query = (char*)query; thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->query_error = 0; // clear error From 40ed42e14a7911a879c11e0b23b0730d763f6651 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 31 Oct 2003 17:13:42 +0300 Subject: [PATCH 43/49] minor fix in rm libmysqld/Makefile.am: minor fix for rm --- libmysqld/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index d831d2a7a5a..54bfd6503d4 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -89,10 +89,10 @@ libmysqld.a: libmysqld_int.a $(INC_LIB) ar x $$file; \ for obj in *.o ; do mv $$obj $${bfile}_$$obj ; done ; \ ar q ../libmysqld_int2.a *.o ; \ - rm *.o ; \ + rm -f *.o ; \ done mv libmysqld_int2.a libmysqld.a - rm tmp/* + rm -f tmp/* $(RANLIB) libmysqld.a ## XXX: any time the client interface changes, we'll need to bump From b920ab261e7aea61a7b8a5b950faafa1ce719d4c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 31 Oct 2003 23:20:23 +0100 Subject: [PATCH 44/49] 4 small items in this: - when we don't have in_addr_t, use uint32. - a forgotten initialization of slave_proxy_id in sql/log_event.cc (was not really "forgot", was "we needn't init it there", but there was one case where we needed...). - made slave_proxy_id always meaningful in THD and Log_event, so we can rely more on it (no need to test if it's meaningful). THD::slave_proxy_id is equal to THD::thread_id except for the slave SQL thread. - clean up the slave's temporary table (i.e. free their memory) when slave server shuts down. extra/resolveip.c: removed #define as it is simpler to put it in my_net.h (because we need the #define elsewhere) include/my_net.h: When in_addr_t is not defined, use uint32. libmysql/libmysql.c: using in_addr_t is more generic. libmysql/manager.c: using in_addr_t is more generic. mysql-test/t/rpl_chain_temp_table.test: comments sql/log_event.cc: * Had forgot to initialize slave_proxy_id in the event constructor (char* buf...). Initializing is in fact only needed for Create_file_log_event, because it uses slave_proxy_id even if it does not write an event to the binlog (it uses slave_proxy_id to write it to SQL-LOAD.info). * When we write events we now always write slave_proxy_id, which is now always meaningful (as thd->slave_proxy_id is now always meaningful, see change in sql_class.cc). sql/mini_client.cc: in_addr_t is more generic. sql/slave.cc: A RELAY_LOG_INFO method to free the slave's temporary tables from memory at slave's server shutdown. It is called by end_slave(), which is called by close_connections(), which is called when the server terminates (close_connections() is just before clean_up(); putting the call in clean_up() was buggy, as active_mi is already deleted by close_connections(). sql/slave.h: new method sql/sql_class.cc: By default we set THD::slave_proxy_id to THD::thread_id, so THD::slave_proxy_id is always meaningful (not 0). It's always the same as the thread id except for the slave SQL thread. --- extra/resolveip.c | 4 ---- include/my_net.h | 9 +++++++++ libmysql/libmysql.c | 2 +- libmysql/manager.c | 2 +- mysql-test/t/rpl_chain_temp_table.test | 10 ++++++++++ sql/log_event.cc | 10 ++++------ sql/mini_client.cc | 2 +- sql/slave.cc | 21 +++++++++++++++++++++ sql/slave.h | 1 + sql/sql_class.cc | 5 +++++ 10 files changed, 53 insertions(+), 13 deletions(-) diff --git a/extra/resolveip.c b/extra/resolveip.c index 6d05152e20b..d3caa9e1d45 100644 --- a/extra/resolveip.c +++ b/extra/resolveip.c @@ -36,10 +36,6 @@ extern int h_errno; #endif -#ifndef HAVE_IN_ADDR_T -#define in_addr_t ulong -#endif - static my_bool silent; static struct my_option my_long_options[] = diff --git a/include/my_net.h b/include/my_net.h index 28d862d8528..7b42afa1f3a 100644 --- a/include/my_net.h +++ b/include/my_net.h @@ -63,6 +63,15 @@ C_MODE_START #define O_NONBLOCK 1 /* For emulation of fcntl() */ #endif +/* + On OSes which don't have the in_addr_t, we guess that using uint32 is the best + possible choice. We guess this from the fact that on HP-UX64bit & FreeBSD64bit + & Solaris64bit, in_addr_t is equivalent to uint32. And on Linux32bit too. +*/ +#ifndef HAVE_IN_ADDR_T +#define in_addr_t uint32 +#endif + /* Thread safe or portable version of some functions */ void my_inet_ntoa(struct in_addr in, char *buf); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index d8966b30fb9..5d809adf36a 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1623,7 +1623,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16]; char *end,*host_info,*charset_name; my_socket sock; - uint32 ip_addr; + in_addr_t ip_addr; struct sockaddr_in sock_addr; ulong pkt_length; NET *net= &mysql->net; diff --git a/libmysql/manager.c b/libmysql/manager.c index d4bd8d5520b..1a4ac718ef9 100644 --- a/libmysql/manager.c +++ b/libmysql/manager.c @@ -90,7 +90,7 @@ MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con, { my_socket sock; struct sockaddr_in sock_addr; - uint32 ip_addr; + in_addr_t ip_addr; char msg_buf[MAX_MYSQL_MANAGER_MSG]; int msg_len; Vio* vio; diff --git a/mysql-test/t/rpl_chain_temp_table.test b/mysql-test/t/rpl_chain_temp_table.test index 65701d8a078..007b018e9d8 100644 --- a/mysql-test/t/rpl_chain_temp_table.test +++ b/mysql-test/t/rpl_chain_temp_table.test @@ -3,6 +3,7 @@ # stop/restart servers. Note that if assumptions are wrong, the test will not # fail; it will just fail to test the error-prone scenario. # Using the manager is the only way to have more than one slave server. +# So you must run this test with --manager. require_manager; server_stop master; @@ -87,3 +88,12 @@ drop table t2; save_master_pos; connection slave_sec; sync_with_master; + +# On purpose, we don't delete the temporary tables explicitely. +# So temp tables remain on slave (remember they are not deleted when the slave +# SQL thread terminates). If you run this test with +# --valgrind --valgrind-options=--show-reachable=yes +# you will see if they get cleaned up at slave's shutdown (that is, if the +# memory they use is freed (it should) by mysqld before it terminates). +# If they wouldn't be cleaned up, you would see some "still reachable" blocks in +# Valgrind. diff --git a/sql/log_event.cc b/sql/log_event.cc index 4f241c6b992..d17c94a2b44 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -874,7 +874,7 @@ Query_log_event::Query_log_event(const char* buf, int event_len, return; memcpy(data_buf, buf + Q_DATA_OFFSET, data_len); - thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET); + slave_proxy_id= thread_id= uint4korr(buf + Q_THREAD_ID_OFFSET); db = data_buf; db_len = (uint)buf[Q_DB_LEN_OFFSET]; query=data_buf + db_len + 1; @@ -955,8 +955,7 @@ int Query_log_event::write_data(IO_CACHE* file) SET PSEUDO_THREAD_ID= for each query using temp tables. */ - int4store(buf + Q_THREAD_ID_OFFSET, (slave_proxy_id ? slave_proxy_id : - thread_id)); + int4store(buf + Q_THREAD_ID_OFFSET, slave_proxy_id); int4store(buf + Q_EXEC_TIME_OFFSET, exec_time); buf[Q_DB_LEN_OFFSET] = (char) db_len; int2store(buf + Q_ERR_CODE_OFFSET, error_code); @@ -1057,8 +1056,7 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db) int Load_log_event::write_data_header(IO_CACHE* file) { char buf[LOAD_HEADER_LEN]; - int4store(buf + L_THREAD_ID_OFFSET, (slave_proxy_id ? slave_proxy_id : - thread_id)); + int4store(buf + L_THREAD_ID_OFFSET, slave_proxy_id); int4store(buf + L_EXEC_TIME_OFFSET, exec_time); int4store(buf + L_SKIP_LINES_OFFSET, skip_lines); buf[L_TBL_LEN_OFFSET] = (char)table_name_len; @@ -1276,7 +1274,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, char* buf_end = (char*)buf + event_len; uint header_len= old_format ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN; const char* data_head = buf + header_len; - thread_id = uint4korr(data_head + L_THREAD_ID_OFFSET); + slave_proxy_id= thread_id= uint4korr(data_head + L_THREAD_ID_OFFSET); exec_time = uint4korr(data_head + L_EXEC_TIME_OFFSET); skip_lines = uint4korr(data_head + L_SKIP_LINES_OFFSET); table_name_len = (uint)data_head[L_TBL_LEN_OFFSET]; diff --git a/sql/mini_client.cc b/sql/mini_client.cc index f204c38c18c..2de5227a953 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -547,7 +547,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, { char buff[NAME_LEN+USERNAME_LENGTH+100],*end,*host_info; my_socket sock; - uint32 ip_addr; + in_addr_t ip_addr; struct sockaddr_in sock_addr; ulong pkt_length; NET *net= &mysql->net; diff --git a/sql/slave.cc b/sql/slave.cc index 90b0cc74fd8..da63ca71951 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -324,6 +324,20 @@ void init_slave_skip_errors(const char* arg) } } +void st_relay_log_info::close_temporary_tables() +{ + TABLE *table,*next; + + for (table=save_temporary_tables ; table ; table=next) + { + next=table->next; + /* + Don't ask for disk deletion. For now, anyway they will be deleted when + slave restarts, but it is a better intention to not delete them. + */ + close_temporary(table, 0); + } +} /* We assume we have a run lock on rli and that both slave thread @@ -790,6 +804,7 @@ static int end_slave_on_walk(MASTER_INFO* mi, gptr /*unused*/) void end_slave() { + /* This is called when the server terminates, in close_connections(). */ if (active_mi) { /* @@ -3092,6 +3107,12 @@ void end_relay_log_info(RELAY_LOG_INFO* rli) } rli->inited = 0; rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); + /* + Delete the slave's temporary tables from memory. + In the future there will be other actions than this, to ensure persistance + of slave's temp tables after shutdown. + */ + rli->close_temporary_tables(); DBUG_VOID_RETURN; } diff --git a/sql/slave.h b/sql/slave.h index 778ddf2ec72..8f7d96b23dd 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -239,6 +239,7 @@ typedef struct st_relay_log_info int wait_for_pos(THD* thd, String* log_name, longlong log_pos, longlong timeout); + void st_relay_log_info::close_temporary_tables(); } RELAY_LOG_INFO; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 132e0d7745f..3ea61da28fc 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -323,6 +323,11 @@ bool THD::store_globals() return 1; mysys_var=my_thread_var; dbug_thread_id=my_thread_id(); + /* + By default 'slave_proxy_id' is 'thread_id'. They may later become different + if this is the slave SQL thread. + */ + slave_proxy_id= thread_id; return 0; } From c97a38c4d3b2afd4c93771fca61eede965fe71cf Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 2 Nov 2003 15:55:02 +0200 Subject: [PATCH 45/49] Call my_sync() after all data is written to .frm file Added my_sync() to mysys which will do fsync/fdatasync/_commit() on a file. VC++Files/mysys/mysys.dsp: Added my_sync.c configure.in: Added testing of fsync and fdatasync include/my_sys.h: Added my_sync() include/mysys_err.h: Added my_sync() isam/extra.c: Added my_sync() myisam/mi_extra.c: Added my_sync() myisam/mi_locking.c: Added my_sync() mysql-test/mysql-test-run.sh: Added option --valgrind-all mysys/Makefile.am: Added my_sync.c mysys/errors.c: Added my_sync() mysys/my_symlink.c: Removed compiler warning mysys/thr_alarm.c: Fix for link error on windows sql/unireg.cc: Call my_sync() after all data is written to .frm file BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + VC++Files/mysys/mysys.dsp | 4 +++ configure.in | 2 +- include/my_sys.h | 1 + include/mysys_err.h | 3 +- isam/extra.c | 10 +++--- myisam/mi_extra.c | 20 +++--------- myisam/mi_locking.c | 20 +++--------- mysql-test/mysql-test-run.sh | 3 ++ mysys/Makefile.am | 2 +- mysys/errors.c | 8 +++-- mysys/my_symlink.c | 3 +- mysys/my_sync.c | 60 ++++++++++++++++++++++++++++++++++++ mysys/thr_alarm.c | 7 +++++ sql/unireg.cc | 9 ++++-- 15 files changed, 105 insertions(+), 48 deletions(-) create mode 100644 mysys/my_sync.c diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index afb9c5cff5c..f642821747f 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -66,6 +66,7 @@ monty@hundin.mysql.fi monty@mashka.(none) monty@mashka.mysql.fi monty@mishka.mysql.fi +monty@mysql.com monty@narttu. monty@narttu.mysql.fi monty@rescue. diff --git a/VC++Files/mysys/mysys.dsp b/VC++Files/mysys/mysys.dsp index 695e2cb2638..b410d0a7465 100644 --- a/VC++Files/mysys/mysys.dsp +++ b/VC++Files/mysys/mysys.dsp @@ -426,6 +426,10 @@ SOURCE=.\my_symlink2.c # End Source File # Begin Source File +SOURCE=.\my_sync.c +# End Source File +# Begin Source File + SOURCE=.\my_tempnam.c # End Source File # Begin Source File diff --git a/configure.in b/configure.in index 02825ce1424..a4fe75ce896 100644 --- a/configure.in +++ b/configure.in @@ -1817,7 +1817,7 @@ AC_CHECK_FUNCS(alarm bmove \ pthread_attr_create pthread_getsequence_np pthread_attr_setstacksize \ pthread_attr_getstacksize \ pthread_condattr_create rwlock_init pthread_rwlock_rdlock \ - fchmod getpass getpassphrase initgroups mlockall) + fsync fdatasync fchmod getpass getpassphrase initgroups mlockall) CFLAGS="$ORG_CFLAGS" diff --git a/include/my_sys.h b/include/my_sys.h index 7a3d22f3304..df8b9759e5d 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -566,6 +566,7 @@ extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags); extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags); extern int my_fclose(FILE *fd,myf MyFlags); extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); +extern int my_sync(File fd, myf my_flags); extern int my_error _VARARGS((int nr,myf MyFlags, ...)); extern int my_printf_error _VARARGS((uint my_err, const char *format, myf MyFlags, ...) diff --git a/include/mysys_err.h b/include/mysys_err.h index a86765c74fd..0ee89e91ee4 100644 --- a/include/mysys_err.h +++ b/include/mysys_err.h @@ -21,7 +21,7 @@ extern "C" { #endif #define GLOB 0 /* Error maps */ -#define GLOBERRS 27 /* Max number of error messages in map's */ +#define GLOBERRS 28 /* Max number of error messages in map's */ #define EE(X) globerrs[ X ] /* Defines to add error to right map */ extern const char * NEAR globerrs[]; /* my_error_messages is here */ @@ -53,6 +53,7 @@ extern const char * NEAR globerrs[]; /* my_error_messages is here */ #define EE_CANT_READLINK 24 #define EE_CANT_SYMLINK 25 #define EE_REALPATH 26 +#define EE_SYNC 27 /* exit codes for all MySQL programs */ diff --git a/isam/extra.c b/isam/extra.c index e2f13532ddf..3bf1dd012ed 100644 --- a/isam/extra.c +++ b/isam/extra.c @@ -250,17 +250,15 @@ int nisam_extra(N_INFO *info, enum ha_extra_function function) pthread_mutex_unlock(&THR_LOCK_isam); break; case HA_EXTRA_FLUSH: -#ifdef __WIN__ if (info->s->not_flushed) { info->s->not_flushed=0; - if (_commit(info->s->kfile)) - error=errno; - if (_commit(info->dfile)) - error=errno; + if (my_sync(info->s->kfile, MYF(0))) + error= my_errno; + if (my_sync(info->dfile, MYF(0))) + error= my_errno; } break; -#endif case HA_EXTRA_NORMAL: /* Theese isn't in use */ case HA_EXTRA_QUICK: case HA_EXTRA_KEY_CACHE: diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c index ef82a6ef61f..1d45fd300e7 100644 --- a/myisam/mi_extra.c +++ b/myisam/mi_extra.c @@ -336,22 +336,10 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) if (share->not_flushed) { share->not_flushed=0; -#if defined(__WIN__) - if (_commit(share->kfile)) - error=errno; - if (_commit(info->dfile)) - error=errno; -#elif defined(HAVE_FDATASYNC) - if (fdatasync(share->kfile)) - error=errno; - if (fdatasync(share->dfile)) - error=errno; -#elif defined(HAVE_FSYNC) - if ( fsync(share->kfile)) - error=errno; - if (fsync(share->dfile)) - error=errno; -#endif + if (my_sync(share->kfile, MYF(0))) + error= my_errno; + if (my_sync(info->dfile, MYF(0))) + error= my_errno; if (error) { share->changed=1; diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index a707eb294a9..f3bfa8deb90 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -88,22 +88,10 @@ int mi_lock_database(MI_INFO *info, int lock_type) share->changed=0; if (myisam_flush) { -#if defined(__WIN__) - if (_commit(share->kfile)) - error=errno; - if (_commit(info->dfile)) - error=errno; -#elif defined(HAVE_FDATASYNC) - if (fdatasync(share->kfile)) - error=errno; - if (fdatasync(share->dfile)) - error=errno; -#elif defined(HAVE_FSYNC) - if (fsync(share->kfile)) - error=errno; - if (fsync(share->dfile)) - error=errno; -#endif + if (my_sync(share->kfile, MYF(0))) + error= my_errno; + if (my_sync(info->dfile, MYF(0))) + error= my_errno; } else share->not_flushed=1; diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index cd409e1ace5..a298701dc7f 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -353,6 +353,9 @@ while test $# -gt 0; do TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"` VALGRIND="$VALGRIND $TMP" ;; + --valgrind-all) + VALGRIND="$VALGRIND -v --show-reachable=yes" + ;; --skip-*) EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1" EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT $1" diff --git a/mysys/Makefile.am b/mysys/Makefile.am index a927fa5e3a0..5dc54817fd7 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -47,7 +47,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\ my_delete.c my_rename.c my_redel.c my_tempnam.c \ my_chsize.c my_lread.c my_lwrite.c my_clock.c \ my_quick.c my_lockmem.c my_static.c \ - my_getopt.c my_mkdir.c \ + my_sync.c my_getopt.c my_mkdir.c \ default.c my_compress.c checksum.c raid.cc \ my_net.c my_semaphore.c my_port.c my_sleep.c \ my_vsnprintf.c charset.c my_bitmap.c my_bit.c md5.c \ diff --git a/mysys/errors.c b/mysys/errors.c index 8a120e0e869..7d755718b16 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -48,6 +48,7 @@ const char * NEAR globerrs[GLOBERRS]= "Can't read value for symlink '%s' (Error %d)", "Can't create symlink '%s' pointing at '%s' (Error %d)", "Error on realpath() on '%s' (Error %d)", + "Can't sync file '%s' to disk (Errcode: %d)", }; void init_glob_errs(void) @@ -84,8 +85,9 @@ void init_glob_errs() EE(EE_CANT_MKDIR) ="Can't create directory '%s' (Errcode: %d)"; EE(EE_UNKNOWN_CHARSET)= "Character set is not a compiled character set and is not specified in the %s file"; EE(EE_OUT_OF_FILERESOURCES)="Out of resources when opening file '%s' (Errcode: %d)"; - EE(EE_CANT_READLINK)="Can't read value for symlink '%s' (Error %d)"; - EE(EE_CANT_SYMLINK)="Can't create symlink '%s' pointing at '%s' (Error %d)"; - EE(EE_REALPATH)="Error on realpath() on '%s' (Error %d)"; + EE(EE_CANT_READLINK)= "Can't read value for symlink '%s' (Error %d)"; + EE(EE_CANT_SYMLINK)= "Can't create symlink '%s' pointing at '%s' (Error %d)"; + EE(EE_REALPATH)= "Error on realpath() on '%s' (Error %d)"; + EE(EE_SYNC)= "Can't sync file '%s' to disk (Errcode: %d)"; } #endif diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index e287930ff06..abef0096e28 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -103,7 +103,8 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags) #define BUFF_LEN FN_LEN #endif -int my_realpath(char *to, const char *filename, myf MyFlags) +int my_realpath(char *to, const char *filename, + myf MyFlags __attribute__((unused))) { #if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH) int result=0; diff --git a/mysys/my_sync.c b/mysys/my_sync.c new file mode 100644 index 00000000000..317ca039346 --- /dev/null +++ b/mysys/my_sync.c @@ -0,0 +1,60 @@ +/* Copyright (C) 2003 MySQL AB + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "mysys_priv.h" +#include "mysys_err.h" +#include + +/* + Sync data in file to disk + + SYNOPSIS + my_sync() + fd File descritor to sync + my_flags Flags (now only MY_WME is supported) + + NOTE + If file system supports its, only file data is synced, not inode date + + RETURN + 0 ok + -1 error +*/ + +int my_sync(File fd, myf my_flags) +{ + int res; + DBUG_ENTER("my_sync"); + DBUG_PRINT("my",("Fd: %d my_flags: %d", fd, my_flags)); + +#if defined(HAVE_FDATASYNC) + res= fdatasync(fd); +#elif defined(HAVE_FSYNC) + res=fsync(fd); +#elif defined(__WIN__) + res= _commit(fd); +#else + res= 0; /* No sync (strange OS) */ +#endif + if (res) + { + if (!(my_errno= errno)) + my_errno= -1; /* Unknown error */ + if (my_flags & MY_WME) + my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno); + } + DBUG_RETURN(res); +} /* my_read */ diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 36bbac16fef..bf40ffc5b4d 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -714,6 +714,9 @@ void thr_alarm_info(ALARM_INFO *info) bzero((char*) info, sizeof(*info)); } +void resize_thr_alarm(uint max_alarms) +{ +} /***************************************************************************** thr_alarm for win95 @@ -793,6 +796,10 @@ void thr_alarm_info(ALARM_INFO *info) bzero((char*) info, sizeof(*info)); } +void resize_thr_alarm(uint max_alarms) +{ +} + #endif /* __WIN__ */ #endif /* THREAD */ diff --git a/sql/unireg.cc b/sql/unireg.cc index 5183f471fa2..ff42bfae0f0 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -150,16 +150,19 @@ int rea_create_table(my_string file_name, my_free((gptr) screen_buff,MYF(0)); my_afree((gptr) keybuff); - VOID(my_close(file,MYF(MY_WME))); - if (ha_create_table(file_name,create_info,0)) + if (my_sync(file, MYF(MY_WME))) goto err2; + if (my_close(file,MYF(MY_WME)) || + ha_create_table(file_name,create_info,0)) + goto err3; DBUG_RETURN(0); err: my_free((gptr) screen_buff,MYF(0)); my_afree((gptr) keybuff); +err2: VOID(my_close(file,MYF(MY_WME))); - err2: +err3: my_delete(file_name,MYF(0)); DBUG_RETURN(1); } /* rea_create_table */ From 15cc0ad2ecfd9be44261f89cfe6d062f8a28e652 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 2 Nov 2003 16:38:27 +0200 Subject: [PATCH 46/49] Portability fix --- sql/slave.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/slave.h b/sql/slave.h index 8f7d96b23dd..ed34c12985a 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -239,7 +239,7 @@ typedef struct st_relay_log_info int wait_for_pos(THD* thd, String* log_name, longlong log_pos, longlong timeout); - void st_relay_log_info::close_temporary_tables(); + void close_temporary_tables(); } RELAY_LOG_INFO; From 22bc137c2ea9dbba8f2ce34f71a914534549ec8d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 3 Nov 2003 19:56:01 +0300 Subject: [PATCH 47/49] fix for bug #1724 'WHERE ... IN() optimizer behaviour has changed since 4.0.14' We need to calculate cost of RANGE scan if it is present instead of cost of FULL scan. mysql-test/r/order_by.result: more accurate row estimation for RANGE scan mysql-test/r/range.result: added test case for bug #1724 'WHERE ... IN() optimizer behaviour has changed since 4.0.14' mysql-test/r/select.result: please ignore mysql-test/t/range.test: added test case for bug #1724 'WHERE ... IN() optimizer behaviour has changed since 4.0.14' sql/sql_select.cc: fix for bug #1724 'WHERE ... IN() optimizer behaviour has changed since 4.0.14' We need to calculate cost of RANGE scan instead of cost of FULL scan if RANGE is present Few comments cleaned up. --- mysql-test/r/order_by.result | 6 ++-- mysql-test/r/range.result | 17 ++++++++++ mysql-test/r/select.result | 4 +-- mysql-test/t/range.test | 23 +++++++++++++ sql/sql_select.cc | 65 +++++++++++++++++++++++------------- 5 files changed, 87 insertions(+), 28 deletions(-) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 58f4972d08f..076c80035b2 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -307,17 +307,17 @@ table type possible_keys key key_len ref rows Extra t1 range a a 9 NULL 8 Using where; Using index explain select * from t1 where a = 2 and b >0 order by a desc,b desc; table type possible_keys key key_len ref rows Extra -t1 range a a 9 NULL 5 Using where; Using index +t1 range a a 9 NULL 4 Using where; Using index explain select * from t1 where a = 2 and b is null order by a desc,b desc; table type possible_keys key key_len ref rows Extra t1 ref a a 9 const,const 1 Using where; Using index; Using filesort explain select * from t1 where a = 2 and (b is null or b > 0) order by a desc,b desc; table type possible_keys key key_len ref rows Extra -t1 range a a 9 NULL 6 Using where; Using index +t1 range a a 9 NULL 5 Using where; Using index explain select * from t1 where a = 2 and b > 0 order by a desc,b desc; table type possible_keys key key_len ref rows Extra -t1 range a a 9 NULL 5 Using where; Using index +t1 range a a 9 NULL 4 Using where; Using index explain select * from t1 where a = 2 and b < 2 order by a desc,b desc; table type possible_keys key key_len ref rows Extra t1 range a a 9 NULL 2 Using where; Using index diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 2bd80cbfba3..68987009598 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -273,3 +273,20 @@ table type possible_keys key key_len ref rows Extra t2 ref j1 j1 4 const 1 Using where; Using index t1 ALL i2 NULL NULL NULL 4 Range checked for each record (index map: 2) DROP TABLE t1,t2; +CREATE TABLE t1 ( +a int(11) default NULL, +b int(11) default NULL, +KEY a (a), +KEY b (b) +) TYPE=MyISAM; +INSERT INTO t1 VALUES +(1,1),(2,1),(3,1),(4,1),(5,1),(6,1),(7,1),(8,1),(9,1),(10,2),(10,2), +(13,2),(14,2),(15,2),(16,2),(17,3),(17,3),(16,3),(17,3),(19,3),(20,3), +(21,4),(22,5),(23,5),(24,5),(25,5),(26,5),(30,5),(31,5),(32,5),(33,5), +(33,5),(33,5),(33,5),(33,5),(34,5),(35,5); +EXPLAIN SELECT * FROM t1 WHERE a IN(1,2) AND b=5; +table type possible_keys key key_len ref rows Extra +t1 range a,b a 5 NULL 2 Using where +SELECT * FROM t1 WHERE a IN(1,2) AND b=5; +a b +DROP TABLE t1; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 09a4ffdb88b..9cc5ad76ff0 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2136,10 +2136,10 @@ a a a select * from (t1 as t2 left join t1 as t3 using (a)) inner join t1 on t1.a>1; a a a 1 1 2 -2 2 2 -3 3 2 1 1 3 +2 2 2 2 2 3 +3 3 2 3 3 3 select * from t1 inner join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1; a a a diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index 75ca0fff5f2..a8b7679457b 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -214,3 +214,26 @@ explain select * from t1, t2 where (t1.key1 table->force_index && best_key)) { // Check full join ha_rows rnd_records= s->found_records; - /* Estimate cost of reading table. */ - tmp= s->table->file->scan_time(); /* If there is a restriction on the table, assume that 25% of the rows can be skipped on next part. @@ -2156,36 +2154,57 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, if (found_constraint) rnd_records-= rnd_records/4; - if (s->on_expr) // Can't use join cache + /* + Range optimizer never proposes a RANGE if it isn't better + than FULL: so if RANGE is present, it's always preferred to FULL. + Here we estimate its cost. + */ + if (s->quick) { + /* + For each record we: + - read record range through 'quick' + - skip rows which does not satisfy WHERE constraints + */ tmp= record_count * - /* We have to read the whole table for each record */ - (tmp + - /* - And we have to skip rows which does not satisfy join - condition for each record. - */ - (s->records - rnd_records)/(double) TIME_FOR_COMPARE); + (s->quick->read_time + + (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE); } else { - /* We read the table as many times as join buffer becomes full. */ - tmp*= (1.0 + floor((double) cache_record_length(join,idx) * - record_count / - (double) thd->variables.join_buff_size)); - /* - We don't make full cartesian product between rows in the scanned - table and existing records because we skip all rows from the - scanned table, which does not satisfy join condition when - we read the table (see flush_cached_records for details). Here we - take into account cost to read and skip these records. - */ - tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE; + /* Estimate cost of reading table. */ + tmp= s->table->file->scan_time(); + if (s->on_expr) // Can't use join cache + { + /* + For each record we have to: + - read the whole table record + - skip rows which does not satisfy join condition + */ + tmp= record_count * + (tmp + + (s->records - rnd_records)/(double) TIME_FOR_COMPARE); + } + else + { + /* We read the table as many times as join buffer becomes full. */ + tmp*= (1.0 + floor((double) cache_record_length(join,idx) * + record_count / + (double) thd->variables.join_buff_size)); + /* + We don't make full cartesian product between rows in the scanned + table and existing records because we skip all rows from the + scanned table, which does not satisfy join condition when + we read the table (see flush_cached_records for details). Here we + take into account cost to read and skip these records. + */ + tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE; + } } /* We estimate the cost of evaluating WHERE clause for found records - as record_count * rnd_records + TIME_FOR_COMPARE. This cost plus + as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus tmp give us total cost of using TABLE SCAN */ if (best == DBL_MAX || From 5ec3a67132eee6d57698ea61b3bbc547c6061d4f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 3 Nov 2003 18:24:01 +0100 Subject: [PATCH 48/49] When we delete the slave's temp tables from memory, we reset rli->save_temporary_tables and slave_open_temp_tables (in old 4.0 you could make "SHOW STATUS LIKE 'slave_open_temp_tables'" grow indefinitely by doing RESET SLAVE and replicating always the same CREATE TEMPORARY TABLE). It's critical to reset save_temporary_tables to 0 (otherwise you may later read memory which has been freed) so this changeset should go into 4.1. mysql-test/r/rpl_reset_slave.result: result update mysql-test/t/rpl_reset_slave.test: test for RESET SLAVE and creating twice the same temp table in the slave. sql/slave.cc: when we delete the slave's temp tables (when slave server shuts down and when RESET SLAVE), we reset 2 variables: rli->save_temporary_tables & slave_open_temp_tables. --- mysql-test/r/rpl_reset_slave.result | 10 ++++++++++ mysql-test/t/rpl_reset_slave.test | 18 ++++++++++++++++++ sql/slave.cc | 2 ++ 3 files changed, 30 insertions(+) diff --git a/mysql-test/r/rpl_reset_slave.result b/mysql-test/r/rpl_reset_slave.result index c1bc1e8e483..fb931064720 100644 --- a/mysql-test/r/rpl_reset_slave.result +++ b/mysql-test/r/rpl_reset_slave.result @@ -20,3 +20,13 @@ start slave; show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space 127.0.0.1 root MASTER_PORT 1 master-bin.001 79 slave-relay-bin.002 120 master-bin.001 Yes Yes 0 0 79 120 +stop slave; +reset slave; +start slave; +create temporary table t1 (a int); +stop slave; +reset slave; +start slave; +show status like 'slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 1 diff --git a/mysql-test/t/rpl_reset_slave.test b/mysql-test/t/rpl_reset_slave.test index 9c58ac0c787..083492c3fc0 100644 --- a/mysql-test/t/rpl_reset_slave.test +++ b/mysql-test/t/rpl_reset_slave.test @@ -2,6 +2,8 @@ # --master-* options from mysqld, as this is what is going to be used next time # slave threads will be started). In bug 985, it displayed old values (of before # RESET SLAVE). +# See if slave crashes when doing a CREATE TEMPORARY TABLE twice, separated by +# RESET SLAVE. source include/master-slave.inc; connection master; @@ -24,3 +26,19 @@ start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT show slave status; + +# test of crash with temp tables & RESET SLAVE +# (test to see if RESET SLAVE clears temp tables in memory and disk) +stop slave; +reset slave; +start slave; +connection master; +create temporary table t1 (a int); +save_master_pos; +connection slave; +sync_with_master; +stop slave; +reset slave; +start slave; +sync_with_master; +show status like 'slave_open_temp_tables'; diff --git a/sql/slave.cc b/sql/slave.cc index da63ca71951..6816d968007 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -337,6 +337,8 @@ void st_relay_log_info::close_temporary_tables() */ close_temporary(table, 0); } + save_temporary_tables= 0; + slave_open_temp_tables= 0; } /* From 91b22c5abe5c4c1b194c446050d399650c1a85b7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 3 Nov 2003 23:18:55 +0100 Subject: [PATCH 49/49] fixed a bug in boolean fts where a word queue was created based on min_word_len, while with trunc* operator one could get shorter words --- myisam/ft_boolean_search.c | 2 +- mysql-test/r/fulltext.result | 2 ++ mysql-test/t/fulltext.test | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index 6a7b7531d4d..72c54bd0c5b 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -308,7 +308,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, Hack: instead of init_queue, we'll use reinit queue to be able to alloc queue with alloc_root() */ - res=ftb->queue.max_elements=1+query_len/(ft_min_word_len+1); + res=ftb->queue.max_elements=1+query_len/(min(ft_min_word_len,2)+1); ftb->queue.root=(byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*)); reinit_queue(& ftb->queue, res, 0, 0, (int (*)(void*,byte*,byte*))FTB_WORD_cmp, 0); diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 737390865f1..df277a18615 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -266,4 +266,6 @@ insert into t2 values (3, 1, 'xxbuz'); select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode); t1_id name t2_id t1_id name 1 data1 1 1 xxfoo +select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode); +t2_id t1_id name drop table t1,t2; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 387a36f1f52..69c69794f4f 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -213,5 +213,11 @@ insert into t2 values (1, 1, 'xxfoo'); insert into t2 values (2, 1, 'xxbar'); insert into t2 values (3, 1, 'xxbuz'); select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('xxfoo' in boolean mode); + +# +# bug with many short (< ft_min_word_len) words in boolean search +# +select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode); + drop table t1,t2;