From 0c181b078684a44dd6d64fa4dcbe9aab1a0d8b78 Mon Sep 17 00:00:00 2001 From: "cmiller@zippy.cornsilk.net" <> Date: Tue, 2 Jan 2007 12:56:48 -0500 Subject: [PATCH 1/7] Bug#23950: misplaced code in mysqld.cc, main() We should initialize before anything else. --- sql/mysqld.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 95de1f91ecf..bcae6fd2ec8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3339,8 +3339,10 @@ int win_main(int argc, char **argv) int main(int argc, char **argv) #endif { - DEBUGGER_OFF; MY_INIT(argv[0]); // init my_sys library & pthreads + /* ^^^ Nothing should be before this line! */ + + DEBUGGER_OFF; #ifdef _CUSTOMSTARTUPCONFIG_ if (_cust_check_startup()) From f44d73a58d0d8232603d98ac14c08cc142538564 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 16 Jan 2007 09:35:14 +0100 Subject: [PATCH 2/7] Always use two masters for ndb tests --- mysql-test/lib/mtr_cases.pl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index a00d06d2e60..8c2dbdec804 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -537,6 +537,8 @@ sub collect_one_test_case($$$$$$$) { $tinfo->{'comment'}= "No ndbcluster tests(--skip-ndbcluster)"; return; } + # Ndb tests run with two mysqld masters + $tinfo->{'master_num'}= 2; } else { @@ -552,7 +554,7 @@ sub collect_one_test_case($$$$$$$) { if ( $tinfo->{'innodb_test'} ) { - # This is a test that need inndob + # This is a test that need innodb if ( $::mysqld_variables{'innodb'} eq "FALSE" ) { # innodb is not supported, skip it @@ -578,7 +580,6 @@ our @tags= ["include/have_debug.inc", "need_debug", 1], ["include/have_ndb.inc", "ndb_test", 1], ["include/have_ndb_extra.inc", "ndb_extra", 1], - ["include/have_multi_ndb.inc", "master_num", 2], ["require_manager", "require_manager", 1], ); From f507bb2cb3d698435d13336a5ebd5ecf797a770e Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 16 Jan 2007 13:39:42 +0100 Subject: [PATCH 3/7] Bug#15518 Reusing a stmt that has failed during prepare does not clear error - Always reset error when calling mysql_stmt_prepare a second time - Set stmt->state to MYSQL_STMT_INIT_DONE before closing prepared stmt in server. - Add test to mysql_client_test - Remove mysql_stmt_close in mysqltest after each query - Close all open statements in mysqltest if disable_ps_protocol is called. --- client/mysqltest.c | 25 +++++++++-- libmysql/libmysql.c | 14 ++++-- tests/mysql_client_test.c | 93 +++++++++++++++++++++++++++++++++++---- 3 files changed, 117 insertions(+), 15 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 005f204d571..b163b5887e4 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -719,6 +719,20 @@ void close_connections() } +void close_statements() +{ + struct st_connection *con; + DBUG_ENTER("close_statements"); + for (con= connections; con < next_con; con++) + { + if (con->stmt) + mysql_stmt_close(con->stmt); + con->stmt= 0; + } + DBUG_VOID_RETURN; +} + + void close_files() { DBUG_ENTER("close_files"); @@ -2855,6 +2869,10 @@ void do_close_connection(struct st_command *command) } } #endif + if (next_con->stmt) + mysql_stmt_close(next_con->stmt); + next_con->stmt= 0; + mysql_close(&con->mysql); if (con->util_mysql) mysql_close(con->util_mysql); @@ -5050,10 +5068,7 @@ end: */ var_set_errno(mysql_stmt_errno(stmt)); -#ifndef BUG15518_FIXED - mysql_stmt_close(stmt); - cur_con->stmt= NULL; -#endif + DBUG_VOID_RETURN; } @@ -5838,6 +5853,8 @@ int main(int argc, char **argv) break; case Q_DISABLE_PS_PROTOCOL: ps_protocol_enabled= 0; + /* Close any open statements */ + close_statements(); break; case Q_ENABLE_PS_PROTOCOL: ps_protocol_enabled= ps_protocol; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 6a592f64e49..a5dcb66f002 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2038,6 +2038,13 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length) DBUG_RETURN(1); } + /* + Reset the last error in any case: that would clear the statement + if the previous prepare failed. + */ + stmt->last_errno= 0; + stmt->last_error[0]= '\0'; + if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE) { /* This is second prepare with another statement */ @@ -2051,23 +2058,24 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length) */ stmt->bind_param_done= stmt->bind_result_done= FALSE; stmt->param_count= stmt->field_count= 0; - stmt->last_errno= 0; - stmt->last_error[0]= '\0'; free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC)); int4store(buff, stmt->stmt_id); + /* + Close statement in server + If there was a 'use' result from another statement, or from mysql_use_result it won't be freed in mysql_stmt_free_result and we should get 'Commands out of sync' here. */ + stmt->state= MYSQL_STMT_INIT_DONE; if (stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt)) { set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, mysql->net.sqlstate); DBUG_RETURN(1); } - stmt->state= MYSQL_STMT_INIT_DONE; } if (stmt_command(mysql, COM_STMT_PREPARE, query, length, stmt)) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index aa993230a7f..22aa1e6ef21 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11014,7 +11014,7 @@ static void test_view() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); rc= my_process_stmt_result(stmt); - assert(1 == rc); + DIE_UNLESS(1 == rc); } mysql_stmt_close(stmt); @@ -11057,7 +11057,7 @@ static void test_view_where() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); rc= my_process_stmt_result(stmt); - assert(4 == rc); + DIE_UNLESS(4 == rc); } mysql_stmt_close(stmt); @@ -11140,7 +11140,7 @@ static void test_view_2where() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); rc= my_process_stmt_result(stmt); - assert(0 == rc); + DIE_UNLESS(0 == rc); mysql_stmt_close(stmt); @@ -11193,7 +11193,7 @@ static void test_view_star() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); rc= my_process_stmt_result(stmt); - assert(0 == rc); + DIE_UNLESS(0 == rc); } mysql_stmt_close(stmt); @@ -11256,7 +11256,7 @@ static void test_view_insert() rc= mysql_stmt_execute(select_stmt); check_execute(select_stmt, rc); rowcount= (int)my_process_stmt_result(select_stmt); - assert((i+1) == rowcount); + DIE_UNLESS((i+1) == rowcount); } mysql_stmt_close(insert_stmt); mysql_stmt_close(select_stmt); @@ -11297,7 +11297,7 @@ static void test_left_join_view() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); rc= my_process_stmt_result(stmt); - assert(3 == rc); + DIE_UNLESS(3 == rc); } mysql_stmt_close(stmt); @@ -11373,7 +11373,7 @@ static void test_view_insert_fields() rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); rc= my_process_stmt_result(stmt); - assert(1 == rc); + DIE_UNLESS(1 == rc); mysql_stmt_close(stmt); rc= mysql_query(mysql, "DROP VIEW v1"); @@ -12851,6 +12851,82 @@ static void test_bug7990() DIE_UNLESS(!mysql_errno(mysql)); } +/* + Bug #15518 - Reusing a stmt that has failed during prepare + does not clear error +*/ + +static void test_bug15518() +{ + MYSQL_STMT *stmt; + MYSQL* mysql1; + int rc; + myheader("test_bug15518"); + + mysql1= mysql_init(NULL); + + if (!mysql_real_connect(mysql1, opt_host, opt_user, opt_password, + opt_db ? opt_db : "test", opt_port, opt_unix_socket, + CLIENT_MULTI_STATEMENTS)) + { + fprintf(stderr, "Failed to connect to the database\n"); + DIE_UNLESS(0); + } + + stmt= mysql_stmt_init(mysql1); + + /* + The prepare of foo should fail with errno 1064 since + it's not a valid query + */ + rc= mysql_stmt_prepare(stmt, "foo", 3); + if (!opt_silent) + fprintf(stdout, "rc: %d, mysql_stmt_errno: %d, mysql_errno: %d\n", + rc, mysql_stmt_errno(stmt), mysql_errno(mysql1)); + DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql1)); + + /* + Use the same stmt and reprepare with another query that + suceeds + */ + rc= mysql_stmt_prepare(stmt, "SHOW STATUS", 12); + if (!opt_silent) + fprintf(stdout, "rc: %d, mysql_stmt_errno: %d, mysql_errno: %d\n", + rc, mysql_stmt_errno(stmt), mysql_errno(mysql1)); + DIE_UNLESS(!rc || mysql_stmt_errno(stmt) || mysql_errno(mysql1)); + + mysql_stmt_close(stmt); + DIE_UNLESS(!mysql_errno(mysql1)); + + /* + part2, when connection to server has been closed + after first prepare + */ + stmt= mysql_stmt_init(mysql1); + rc= mysql_stmt_prepare(stmt, "foo", 3); + if (!opt_silent) + fprintf(stdout, "rc: %d, mysql_stmt_errno: %d, mysql_errno: %d\n", + rc, mysql_stmt_errno(stmt), mysql_errno(mysql1)); + DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql1)); + + /* Close connection to server */ + mysql_close(mysql1); + + /* + Use the same stmt and reprepare with another query that + suceeds. The prepare should fail with error 2013 since + connection to server has been closed. + */ + rc= mysql_stmt_prepare(stmt, "SHOW STATUS", 12); + if (!opt_silent) + fprintf(stdout, "rc: %d, mysql_stmt_errno: %d\n", + rc, mysql_stmt_errno(stmt)); + DIE_UNLESS(rc && mysql_stmt_errno(stmt)); + + mysql_stmt_close(stmt); + DIE_UNLESS(mysql_errno(mysql1)); +} + static void test_view_sp_list_fields() { @@ -15009,7 +15085,7 @@ static void test_bug17667() } else { - assert(0==1); + DIE_UNLESS(0==1); } } @@ -15588,6 +15664,7 @@ static struct my_tests_st my_tests[]= { { "test_bug15752", test_bug15752 }, { "test_bug21206", test_bug21206 }, { "test_bug21726", test_bug21726 }, + { "test_bug15518", test_bug15518 }, { 0, 0 } }; From ae03f5d382f127297a9799a221851288f6f73ae7 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 16 Jan 2007 17:47:41 +0100 Subject: [PATCH 4/7] Don't reuse prepared statements if running with reconnect enabled --- client/mysqltest.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/mysqltest.c b/client/mysqltest.c index b163b5887e4..266c21d7880 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -5061,6 +5061,14 @@ end: dynstr_free(&ds_execute_warnings); } + + /* Close the statement if - no reconnect, need new prepare */ + if (mysql->reconnect) + { + mysql_stmt_close(stmt); + cur_con->stmt= NULL; + } + /* We save the return code (mysql_stmt_errno(stmt)) from the last call sent to the server into the mysqltest builtin variable $mysql_errno. This @@ -5864,6 +5872,8 @@ int main(int argc, char **argv) break; case Q_ENABLE_RECONNECT: set_reconnect(&cur_con->mysql, 1); + /* Close any open statements - no reconnect, need new prepare */ + close_statements(); break; case Q_DISABLE_PARSING: if (parsing_disabled == 0) From c36a5390e4731986ca212ee6fcc9410fa77405a9 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 16 Jan 2007 17:52:17 +0100 Subject: [PATCH 5/7] Update xid's as an effect of not closing the prepared statements all the time --- mysql-test/t/mix_innodb_myisam_binlog.test | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mysql-test/t/mix_innodb_myisam_binlog.test b/mysql-test/t/mix_innodb_myisam_binlog.test index 66440f1236e..73b59409a90 100644 --- a/mysql-test/t/mix_innodb_myisam_binlog.test +++ b/mysql-test/t/mix_innodb_myisam_binlog.test @@ -29,7 +29,7 @@ insert into t2 select * from t1; commit; --replace_column 5 # ---replace_result "xid=15" "xid=8" +--replace_result "xid=14" "xid=8" show binlog events from 98; delete from t1; @@ -58,7 +58,7 @@ rollback to savepoint my_savepoint; commit; --replace_column 5 # ---replace_result "xid=48" "xid=25" +--replace_result "xid=47" "xid=25" show binlog events from 98; delete from t1; @@ -76,7 +76,7 @@ commit; select a from t1 order by a; # check that savepoints work :) --replace_column 5 # ---replace_result "xid=70" "xid=37" +--replace_result "xid=69" "xid=37" show binlog events from 98; # and when ROLLBACK is not explicit? @@ -109,7 +109,7 @@ insert into t1 values(9); insert into t2 select * from t1; --replace_column 5 # ---replace_result "xid=119" "xid=60" +--replace_result "xid=117" "xid=60" show binlog events from 98; # Check that when the query updat1ng the MyISAM table is the first in the @@ -122,13 +122,13 @@ insert into t1 values(10); # first make t1 non-empty begin; insert into t2 select * from t1; --replace_column 5 # ---replace_result "xid=133" "xid=66" +--replace_result "xid=131" "xid=66" show binlog events from 98; insert into t1 values(11); commit; --replace_column 5 # ---replace_result "xid=133" "xid=66" "xid=136" "xid=68" +--replace_result "xid=131" "xid=66" "xid=134" "xid=68" show binlog events from 98; @@ -147,7 +147,7 @@ insert into t2 select * from t1; commit; --replace_column 5 # ---replace_result "xid=155" "xid=78" +--replace_result "xid=153" "xid=78" show binlog events from 98; delete from t1; @@ -175,7 +175,7 @@ rollback to savepoint my_savepoint; commit; --replace_column 5 # ---replace_result "xid=187" "xid=94" +--replace_result "xid=185" "xid=94" show binlog events from 98; delete from t1; @@ -193,7 +193,7 @@ commit; select a from t1 order by a; # check that savepoints work :) --replace_column 5 # ---replace_result "xid=208" "xid=105" +--replace_result "xid=206" "xid=105" show binlog events from 98; # Test for BUG#5714, where a MyISAM update in the transaction used to @@ -254,7 +254,7 @@ disconnect con2; connection con3; select get_lock("lock1",60); --replace_column 5 # ---replace_result "xid=208" "xid=105" "xid=227" "xid=114" "xid=230" "xid=115" "xid=234" "xid=117" "xid=261" "xid=132" +--replace_result "xid=206" "xid=105" "xid=224" "xid=114" "xid=227" "xid=115" "xid=231" "xid=117" "xid=258" "xid=132" show binlog events from 98; do release_lock("lock1"); drop table t0,t2; From 29be5ce83641ff65adc7f2059efb0e5adec1079c Mon Sep 17 00:00:00 2001 From: "msvensson@pilot.mysql.com" <> Date: Wed, 17 Jan 2007 11:51:52 +0100 Subject: [PATCH 6/7] Bug#25505 Myisam library compiler error on Windows --- myisam/mi_packrec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index 5363a3ecf23..51b0222e876 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -590,8 +590,7 @@ static void fill_quick_table(uint16 *table, uint bits, uint max_bits, static uint copy_decode_table(uint16 *to_pos, uint offset, uint16 *decode_table) { - uint prev_offset; - prev_offset= offset; + uint prev_offset= offset; DBUG_ENTER("copy_decode_table"); /* Descent on the left side. */ From c4a86761b0651b13b989468064890e52697fa71b Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Wed, 17 Jan 2007 13:43:03 +0100 Subject: [PATCH 7/7] Replace the --exec in a while loop that causes 3400 executions of cygwin/bash on windows with a small perl script that does exactly the same. --- mysql-test/t/mysql.test | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 3d022eb27e4..829be665e09 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -145,21 +145,24 @@ drop table t1; # # Bug #19216: Client crashes on long SELECT # ---exec echo "select" > $MYSQLTEST_VARDIR/tmp/b19216.tmp -# 3400 * 20 makes 68000 columns that is more than the max number that can fit -# in a 16 bit number. -let $i= 3400; -while ($i) -{ - --exec echo "'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'," >> $MYSQLTEST_VARDIR/tmp/b19216.tmp - dec $i; -} +# Create large SELECT +# - 3400 * 20 makes 68000 columns that is more than the +# max number that can fit in a 16 bit number. + +--perl +open(FILE,">","$ENV{'MYSQLTEST_VARDIR'}/tmp/b19216.tmp") or die; +print FILE "select\n"; +print FILE "'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',\n" x 3400; +print FILE "'b';\n"; +close FILE; +EOF ---exec echo "'b';" >> $MYSQLTEST_VARDIR/tmp/b19216.tmp --disable_query_log --exec $MYSQL < $MYSQLTEST_VARDIR/tmp/b19216.tmp >/dev/null --enable_query_log +--remove_file $MYSQLTEST_VARDIR/tmp/b19216.tmp + # # Bug #20103: Escaping with backslash does not work #