diff --git a/client/mysqltest.c b/client/mysqltest.c index 510fe6a3f4c..4ae74d129b9 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -192,6 +192,7 @@ Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG, Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG, Q_SERVER_START, Q_SERVER_STOP,Q_REQUIRE_MANAGER, Q_WAIT_FOR_SLAVE_TO_STOP, +Q_REQUIRE_VERSION, Q_UNKNOWN, /* Unknown command. */ Q_COMMENT, /* Comments, ignored. */ Q_COMMENT_WITH_COMMAND @@ -228,6 +229,7 @@ const char *command_names[] = { "enable_result_log", "disable_result_log", "server_start", "server_stop", "require_manager", "wait_for_slave_to_stop", + "require_version", 0 }; @@ -748,6 +750,42 @@ int do_server_op(struct st_query* q,const char* op) } #endif +int do_require_version(struct st_query* q) +{ + MYSQL* mysql = &cur_con->mysql; + MYSQL_RES* res; + MYSQL_ROW row; + char* p=q->first_argument, *ver_arg; + uint ver_arg_len,ver_len; + LINT_INIT(res); + + if (!*p) + die("Missing version argument in require_version\n"); + ver_arg = p; + while (*p && !isspace(*p)) + p++; + *p = 0; + ver_arg_len = p - ver_arg; + + if (mysql_query(mysql, "select version()") || + !(res=mysql_store_result(mysql))) + die("Query failed while check server version: %s", + mysql_error(mysql)); + if (!(row=mysql_fetch_row(res)) || !row[0]) + { + mysql_free_result(res); + die("Strange result from query while checking version"); + } + ver_len = strlen(row[0]); + if (ver_len < ver_arg_len || memcmp(row[0],ver_arg,ver_arg_len)) + { + mysql_free_result(res); + abort_not_supported_test(); + } + mysql_free_result(res); + return 0; +} + int do_source(struct st_query* q) { char* p=q->first_argument, *name; @@ -2379,6 +2417,7 @@ int main(int argc, char** argv) case Q_DISABLE_RESULT_LOG: disable_result_log=1; break; case Q_SOURCE: do_source(q); break; case Q_SLEEP: do_sleep(q); break; + case Q_REQUIRE_VERSION: do_require_version(q); break; case Q_WAIT_FOR_SLAVE_TO_STOP: do_wait_for_slave_to_stop(q); break; case Q_REQUIRE_MANAGER: do_require_manager(q); break; #ifndef EMBEDDED_LIBRARY diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index c36e4e532af..465c1cfdaa2 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -20,6 +20,7 @@ TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work #-- PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin +MASTER_40_ARGS="--rpl-recovery-rank=1 --init-rpl-role=master" # Standard functions @@ -58,7 +59,7 @@ sleep_until_file_deleted () done } -sleep_until_file_exists () +sleep_until_file_created () { file=$1 loop=$2 @@ -190,6 +191,11 @@ while test $# -gt 0; do --user=*) DBUSER=`$ECHO "$1" | $SED -e "s;--user=;;"` ;; --force) FORCE=1 ;; --verbose-manager) MANAGER_QUIET_OPT="" ;; + --old-master) MASTER_40_ARGS="";; + --master-binary=*) + MASTER_MYSQLD=`$ECHO "$1" | $SED -e "s;--master-binary=;;"` ;; + --slave-binary=*) + SLAVE_MYSQLD=`$ECHO "$1" | $SED -e "s;--slave-binary=;;"` ;; --local) USE_RUNNING_SERVER="" ;; --tmpdir=*) MYSQL_TMP_DIR=`$ECHO "$1" | $SED -e "s;--tmpdir=;;"` ;; --local-master) @@ -394,6 +400,16 @@ else fi fi +if [ -z "$MASTER_MYSQLD" ] +then +MASTER_MYSQLD=$MYSQLD +fi + +if [ -z "$SLAVE_MYSQLD" ] +then +SLAVE_MYSQLD=$MYSQLD +fi + # If we should run all tests cases, we will use a local server for that if [ -z "$1" ] @@ -430,7 +446,6 @@ GPROF_DIR=$MYSQL_TMP_DIR/gprof GPROF_MASTER=$GPROF_DIR/master.gprof GPROF_SLAVE=$GPROF_DIR/slave.gprof TIMEFILE="$MYSQL_TEST_DIR/var/log/mysqltest-time" -SLAVE_MYSQLD=$MYSQLD #this can be changed later if we are doing gcov XTERM=`which xterm` #++ @@ -564,11 +579,11 @@ gprof_prepare () gprof_collect () { if [ -f $MASTER_MYDDIR/gmon.out ]; then - gprof $MYSQLD $MASTER_MYDDIR/gmon.out > $GPROF_MASTER + gprof $MASTER_MYSQLD $MASTER_MYDDIR/gmon.out > $GPROF_MASTER echo "Master execution profile has been saved in $GPROF_MASTER" fi if [ -f $SLAVE_MYDDIR/gmon.out ]; then - gprof $MYSQLD $SLAVE_MYDDIR/gmon.out > $GPROF_SLAVE + gprof $SLAVE_MYSQLD $SLAVE_MYDDIR/gmon.out > $GPROF_SLAVE echo "Slave execution profile has been saved in $GPROF_SLAVE" fi } @@ -708,8 +723,8 @@ start_master() if [ -z "$DO_BENCH" ] then master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin \ - --server-id=1 --rpl-recovery-rank=1 \ - --basedir=$MY_BASEDIR --init-rpl-role=master \ + --server-id=1 \ + --basedir=$MY_BASEDIR \ --port=$MASTER_MYPORT \ --exit-info=256 \ --core \ @@ -722,6 +737,7 @@ start_master() --tmpdir=$MYSQL_TMP_DIR \ --language=$LANGUAGE \ --innodb_data_file_path=ibdata1:50M \ + $MASTER_40_ARGS \ $SMALL_SERVER \ $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT" else @@ -738,6 +754,7 @@ start_master() --tmpdir=$MYSQL_TMP_DIR \ --language=$LANGUAGE \ --innodb_data_file_path=ibdata1:50M \ + $MASTER_40_ARGS \ $SMALL_SERVER \ $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT" fi @@ -749,14 +766,14 @@ start_master() then $ECHO "set args $master_args" > $GDB_MASTER_INIT manager_launch master ddd -display $DISPLAY --debugger \ - "gdb -x $GDB_MASTER_INIT" $MYSQLD + "gdb -x $GDB_MASTER_INIT" $MASTER_MYSQLD elif [ x$DO_GDB = x1 ] then if [ x$MANUAL_GDB = x1 ] then $ECHO "set args $master_args" > $GDB_MASTER_INIT $ECHO "To start gdb for the master , type in another window:" - $ECHO "cd $CWD ; gdb -x $GDB_MASTER_INIT $MYSQLD" + $ECHO "cd $CWD ; gdb -x $GDB_MASTER_INIT $MASTER_MYSQLD" wait_for_master=1500 else ( $ECHO set args $master_args; @@ -770,12 +787,12 @@ r EOF fi ) > $GDB_MASTER_INIT manager_launch master $XTERM -display $DISPLAY \ - -title "Master" -e gdb -x $GDB_MASTER_INIT $MYSQLD + -title "Master" -e gdb -x $GDB_MASTER_INIT $MASTER_MYSQLD fi else - manager_launch master $MYSQLD $master_args + manager_launch master $MASTER_MYSQLD $master_args fi - sleep_until_file_exists $MASTER_MYPID $wait_for_master + sleep_until_file_created $MASTER_MYPID $wait_for_master wait_for_master=$SLEEP_TIME_FOR_SECOND_MASTER MASTER_RUNNING=1 } @@ -866,7 +883,7 @@ start_slave() if [ x$MANUAL_GDB = x1 ] then echo "To start gdb for the slave, type in another window:" - echo "cd $CWD ; gdb -x $GDB_SLAVE_INIT $MYSQLD" + echo "cd $CWD ; gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD" wait_for_slave=1500 else manager_launch $slave_ident $XTERM -display $DISPLAY -title "Slave" -e \ @@ -876,7 +893,7 @@ start_slave() manager_launch $slave_ident $SLAVE_MYSQLD $slave_args fi eval "SLAVE$1_RUNNING=1" - sleep_until_file_exists $slave_pid $wait_for_slave + sleep_until_file_created $slave_pid $wait_for_slave wait_for_slave=$SLEEP_TIME_FOR_SECOND_SLAVE } diff --git a/mysql-test/r/rpl_compat.result b/mysql-test/r/rpl_compat.result new file mode 100644 index 00000000000..5e497791771 --- /dev/null +++ b/mysql-test/r/rpl_compat.result @@ -0,0 +1,77 @@ +slave stop; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +use test; +drop table if exists t1,t3; +create table t1 (word char(20) not null); +load data infile '../../std_data/words.dat' into table t1; +select * from t1; +word +Aarhus +Aaron +Ababa +aback +abaft +abandon +abandoned +abandoning +abandonment +abandons +set password for root@"localhost" = password('foo'); +set password for root@"localhost" = password(''); +create table t3(n int); +insert into t3 values(1),(2); +use test; +select * from t3; +n +1 +2 +select sum(length(word)) from t1; +sum(length(word)) +71 +drop table t1,t3; +reset master; +slave stop; +reset slave; +create table t1(n int); +insert into t1 values (1),(2),(3); +create table t2(id int); +insert into t2 values(connection_id()); +create temporary table t1_temp(n int); +insert into t1_temp select get_lock('crash_lock%20C', 1) from t2; + update t1 set n = n + get_lock('crash_lock%20C', 2); +select (@id := id) - id from t2; +(@id := id) - id +0 +kill @id; +drop table t2; +Server shutdown in progress +slave start; +set sql_slave_skip_counter=1; +slave start; +select count(*) from t1; +count(*) +3 +drop table t1; +create table t1 (n int); +insert into t1 values(3456); +use mysql; +insert into user (Host, User, Password) +VALUES ("10.10.10.%", "blafasel2", password("blafasel2")); +select select_priv,user from mysql.user where user = 'blafasel2'; +select_priv user +N blafasel2 +update user set Select_priv = "Y" where User="blafasel2"; +select select_priv,user from mysql.user where user = 'blafasel2'; +select_priv user +Y blafasel2 +use test; +select n from t1; +n +3456 +select select_priv,user from mysql.user where user = 'blafasel2'; +select_priv user +Y blafasel2 +drop table t1; diff --git a/mysql-test/t/rpl_compat.test b/mysql-test/t/rpl_compat.test new file mode 100644 index 00000000000..c9455c1e2d2 --- /dev/null +++ b/mysql-test/t/rpl_compat.test @@ -0,0 +1,86 @@ +eval_result; +source include/master-slave.inc; +connection master; +require_version 3.23; +use test; +drop table if exists t1,t3; +create table t1 (word char(20) not null); +load data infile '../../std_data/words.dat' into table t1; +select * from t1; +set password for root@"localhost" = password('foo'); +set password for root@"localhost" = password(''); +create table t3(n int); +insert into t3 values(1),(2); +save_master_pos; +connection slave; +sync_with_master; +use test; +select * from t3; +select sum(length(word)) from t1; +connection master; +drop table t1,t3; +save_master_pos; +connection slave; +sync_with_master; + +#test handling of aborted connection in the middle of update +connection master; +reset master; +connection slave; +slave stop; +reset slave; + +connection master; +create table t1(n int); +insert into t1 values (1),(2),(3); +create table t2(id int); +insert into t2 values(connection_id()); +save_master_pos; + +connection master1; +#avoid generating result +create temporary table t1_temp(n int); +insert into t1_temp select get_lock('crash_lock%20C', 1) from t2; + +connection master; +send update t1 set n = n + get_lock('crash_lock%20C', 2); +connection master1; +sleep 2; +select (@id := id) - id from t2; +kill @id; +drop table t2; +connection master; +--error 1053; +reap; +connection slave; +slave start; +sync_with_master ; +#now slave will hit an error +wait_for_slave_to_stop; + +set sql_slave_skip_counter=1; +slave start; +select count(*) from t1; +connection master1; +drop table t1; +create table t1 (n int); +insert into t1 values(3456); +use mysql; +insert into user (Host, User, Password) + VALUES ("10.10.10.%", "blafasel2", password("blafasel2")); +select select_priv,user from mysql.user where user = 'blafasel2'; +update user set Select_priv = "Y" where User="blafasel2"; +select select_priv,user from mysql.user where user = 'blafasel2'; +use test; +save_master_pos; +connection slave; +sync_with_master; +select n from t1; +select select_priv,user from mysql.user where user = 'blafasel2'; +connection master1; +drop table t1; +save_master_pos; +connection slave; +sync_with_master; + + diff --git a/sql/slave.cc b/sql/slave.cc index 86db6efa34d..100e305530f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1538,10 +1538,6 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) if (ev->server_id == ::server_id || (rli->slave_skip_counter && type_code != ROTATE_EVENT)) { - /* - TODO: I/O thread must handle skipping file delivery for - old load data infile events - */ /* TODO: I/O thread should not even log events with the same server id */ rli->inc_pos(ev->get_event_len(), type_code != STOP_EVENT ? ev->log_pos : LL(0), @@ -1953,6 +1949,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev) DBUG_ASSERT(cev->inited_from_old); thd = mi->io_thd; thd->file_id = cev->file_id = mi->file_id++; + thd->server_id = cev->server_id; cev_not_written = 1; if (unlikely(net_request_file(net,cev->fname))) @@ -1980,7 +1977,8 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev) if (unlikely(!num_bytes)) /* eof */ { send_ok(net); /* 3.23 master wants it */ - Execute_load_log_event xev(mi->io_thd); + Execute_load_log_event xev(thd); + xev.log_pos = mi->master_log_pos; if (unlikely(mi->rli.relay_log.append(&xev))) { sql_print_error("Slave I/O: error writing Exec_load event to \ @@ -1993,6 +1991,7 @@ relay log"); { cev->block = (char*)net->read_pos; cev->block_len = num_bytes; + cev->log_pos = mi->master_log_pos; if (unlikely(mi->rli.relay_log.append(cev))) { sql_print_error("Slave I/O: error writing Create_file event to \ @@ -2005,6 +2004,7 @@ relay log"); { aev.block = (char*)net->read_pos; aev.block_len = num_bytes; + aev.log_pos = mi->master_log_pos; if (unlikely(mi->rli.relay_log.append(&aev))) { sql_print_error("Slave I/O: error writing Append_block event to \