From 87679ac97302915962f3c9c5f188f5b0c3d44b22 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Wed, 11 Feb 2009 11:56:25 +0000 Subject: [PATCH 01/28] BUG#38197 Errors in @@init_slave not visible in 'show slave status' Some errors that cause the slave SQL thread to stop are not shown in the Slave_SQL_Error column of "SHOW SLAVE STATUS". Instead, the error is only in the server's error log. That makes it difficult to analyze the error for the user. One example of an error that stops the slave but is not shown by "SHOW SLAVE STATUS" is when @@global.init_slave is set incorrectly (e.g., it contains something that is not valid SQL). Three failures were not correctly reported: 1 - Failures during slave thread initialization 2 - Failures while initializing the relay log position right after starting the slave thread. 3 - Failures while processing queries passed through the init_slave option. This patch fixes the issues by reporting the errors through relay-info->report. --- mysql-test/suite/rpl/r/rpl_bug33931.result | 10 +-- mysql-test/suite/rpl/r/rpl_bug38197.result | 18 +++++ mysql-test/suite/rpl/t/rpl_bug33931.test | 6 +- mysql-test/suite/rpl/t/rpl_bug38197.test | 86 ++++++++++++++++++++++ sql/slave.cc | 23 ++++-- 5 files changed, 129 insertions(+), 14 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_bug38197.result create mode 100644 mysql-test/suite/rpl/t/rpl_bug38197.test diff --git a/mysql-test/suite/rpl/r/rpl_bug33931.result b/mysql-test/suite/rpl/r/rpl_bug33931.result index 1b3f2cfc7dc..85c8fb0da9c 100644 --- a/mysql-test/suite/rpl/r/rpl_bug33931.result +++ b/mysql-test/suite/rpl/r/rpl_bug33931.result @@ -1,5 +1,5 @@ reset master; -call mtr.add_suppression("Failed during slave.*thread initialization"); +call mtr.add_suppression("Failed during slave thread initialization"); stop slave; reset slave; SET GLOBAL debug="d,simulate_io_slave_error_on_init,simulate_sql_slave_error_on_init"; @@ -23,8 +23,8 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 0 -Last_Error +Last_Errno # +Last_Error Failed during slave thread initialization Skip_Counter 0 Exec_Master_Log_Pos 0 Relay_Log_Space # @@ -41,6 +41,6 @@ Seconds_Behind_Master # Master_SSL_Verify_Server_Cert No Last_IO_Errno 0 Last_IO_Error -Last_SQL_Errno 0 -Last_SQL_Error +Last_SQL_Errno # +Last_SQL_Error Failed during slave thread initialization SET GLOBAL debug=""; diff --git a/mysql-test/suite/rpl/r/rpl_bug38197.result b/mysql-test/suite/rpl/r/rpl_bug38197.result new file mode 100644 index 00000000000..ab957e6d9bc --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_bug38197.result @@ -0,0 +1,18 @@ +stop slave; +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; +start slave; +stop slave; +reset slave; +SET GLOBAL debug= "d,simulate_io_slave_error_on_init,simulate_sql_slave_error_on_init"; +start slave; +Reporting the following error: Failed during slave thread initialization +SET GLOBAL debug= ""; +stop slave; +reset slave; +SET GLOBAL init_slave= "garbage"; +start slave; +Reporting the following error: Slave SQL thread aborted. Can't execute init_slave query +SET GLOBAL init_slave= ""; diff --git a/mysql-test/suite/rpl/t/rpl_bug33931.test b/mysql-test/suite/rpl/t/rpl_bug33931.test index a439b346538..13f781c644b 100644 --- a/mysql-test/suite/rpl/t/rpl_bug33931.test +++ b/mysql-test/suite/rpl/t/rpl_bug33931.test @@ -15,7 +15,7 @@ reset master; connection slave; # Add suppression for expected warnings in slaves error log -call mtr.add_suppression("Failed during slave.*thread initialization"); +call mtr.add_suppression("Failed during slave thread initialization"); --disable_warnings stop slave; @@ -37,8 +37,8 @@ connection slave; # source include/wait_for_slave_to_stop.inc; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # +--replace_result $MASTER_MYPORT MASTER_PORT +--replace_column 1 # 8 # 9 # 19 # 23 # 33 # 37 # query_vertical show slave status; # diff --git a/mysql-test/suite/rpl/t/rpl_bug38197.test b/mysql-test/suite/rpl/t/rpl_bug38197.test new file mode 100644 index 00000000000..4ca0de6ec66 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_bug38197.test @@ -0,0 +1,86 @@ +###################################################################### +# Some errors that cause the slave SQL thread to stop are not shown in +# the Slave_SQL_Error column of "SHOW SLAVE STATUS". Instead, the error +# is only in the server's error log. +# +# Two failures and their respective reporting are verified: +# +# 1 - Failures during slave thread initialization +# 2 - Failures while processing queries passed through the init_slave +# option. +# +# In order to check the first type of failure, we inject a fault in the +# SQL/IO Threads through SET GLOBAL debug. +# +# To check the second type, we set @@global.init_slave to an invalid +# command thus preventing the initialization of the SQL Thread. +# +# Obs: +# 1 - Note that testing failures while initializing the relay log position +# is hard as the same function is called before the code reaches the point +# that we want to test. +# +# 2 - This test does not target failures that are reported while applying +# events such as duplicate keys, errors while reading the relay-log.bin*, +# etc. Such errors are already checked on other tests. +###################################################################### + +###################################################################### +# Configuring the Environment +###################################################################### +source include/have_debug.inc; +source include/master-slave.inc; +source include/have_log_bin.inc; + +connection slave; + +--disable_warnings +stop slave; +--enable_warnings +reset slave; + +###################################################################### +# Injecting faults in the threads' initialization +###################################################################### +connection slave; + +# Set debug flags on slave to force errors to occur +SET GLOBAL debug= "d,simulate_io_slave_error_on_init,simulate_sql_slave_error_on_init"; + +start slave; + +# +# slave is going to stop because of emulated failures +# but there won't be any crashes nor asserts hit. +# +source include/wait_for_slave_to_stop.inc; + +let $error= query_get_value(SHOW SLAVE STATUS, Last_Error, 1); +echo Reporting the following error: $error; + +SET GLOBAL debug= ""; + +###################################################################### +# Injecting faults in the init_slave option +###################################################################### +connection slave; + +--disable_warnings +stop slave; +--enable_warnings +source include/wait_for_slave_to_stop.inc; + +reset slave; + +SET GLOBAL init_slave= "garbage"; + +start slave; +source include/wait_for_slave_sql_to_stop.inc; + +let $error= query_get_value(SHOW SLAVE STATUS, Last_Error, 1); +echo Reporting the following error: $error; + +###################################################################### +# Clean up +###################################################################### +SET GLOBAL init_slave= ""; diff --git a/sql/slave.cc b/sql/slave.cc index 22c61b3ec6c..71affbab6bf 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2678,7 +2678,8 @@ pthread_handler_t handle_slave_sql(void *arg) */ pthread_cond_broadcast(&rli->start_cond); pthread_mutex_unlock(&rli->run_lock); - sql_print_error("Failed during slave thread initialization"); + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + "Failed during slave thread initialization"); goto err; } thd->init_for_queries(); @@ -2722,9 +2723,9 @@ pthread_handler_t handle_slave_sql(void *arg) rli->group_relay_log_pos, 1 /*need data lock*/, &errmsg, 1 /*look for a description_event*/)) - { - sql_print_error("Error initializing relay log position: %s", - errmsg); + { + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + "Error initializing relay log position: %s", errmsg); goto err; } THD_CHECK_SENTRY(thd); @@ -2769,8 +2770,8 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, execute_init_command(thd, &sys_init_slave, &LOCK_sys_init_slave); if (thd->is_slave_error) { - sql_print_error("\ -Slave SQL thread aborted. Can't execute init_slave query"); + rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), + "Slave SQL thread aborted. Can't execute init_slave query"); goto err; } } @@ -2820,10 +2821,20 @@ Slave SQL thread aborted. Can't execute init_slave query"); thd->main_da.sql_errno(), last_errno)); if (last_errno == 0) { + /* + This function is reporting an error which was not reported + while executing exec_relay_log_event(). + */ rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), errmsg); } else if (last_errno != thd->main_da.sql_errno()) { + /* + * An error was reported while executing exec_relay_log_event() + * however the error code differs from what is in the thread. + * This function prints out more information to help finding + * what caused the problem. + */ sql_print_error("Slave (additional info): %s Error_code: %d", errmsg, thd->main_da.sql_errno()); } From 0e0843d8700a791e379e8c2d41bc85eff307026f Mon Sep 17 00:00:00 2001 From: Satya B Date: Fri, 20 Mar 2009 14:48:14 +0530 Subject: [PATCH 02/28] Fix for BUG#41330 -Myisam table open count set to zero before index blocks are written. When we have a myisam table with DELAY_KEY_WRITE option, index updates are not applied until the flush tables command is issued or until the server is shutdown. If server gets killed before the index updates are written to disk, the index file is corrupted as expected but the table is not marked as crashed. So when we start server with myisam-recover, table is not repaired leaving the table unusable. The problem is when we try to write the index updates to index file, we decrement the open_count even before the flushing the keys to index file. Fixed by moving the decrement operation after flushing the keys to the index file. So we always have non zero open count if the flush table operation is killed and when the server is started with mysiam-recover option, it marks the table as crashed and repairs it. Note: No testcase for added as we need to kill the server and start the server with different set of options and other non trivial operations involved. --- myisam/mi_close.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/myisam/mi_close.c b/myisam/mi_close.c index 81d32be468a..43eebed520b 100644 --- a/myisam/mi_close.c +++ b/myisam/mi_close.c @@ -35,8 +35,6 @@ int mi_close(register MI_INFO *info) if (info->lock_type == F_EXTRA_LCK) info->lock_type=F_UNLCK; /* HA_EXTRA_NO_USER_CHANGE */ - if (share->reopen == 1 && share->kfile >= 0) - _mi_decrement_open_count(info); if (info->lock_type != F_UNLCK) { @@ -78,6 +76,8 @@ int mi_close(register MI_INFO *info) */ if (share->mode != O_RDONLY && mi_is_crashed(info)) mi_state_info_write(share->kfile, &share->state, 1); + /* Decrement open count must be last I/O on this file. */ + _mi_decrement_open_count(info); if (my_close(share->kfile,MYF(0))) error = my_errno; } From 95301268221bfcf72baaa9f34f234ff6231235c8 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Fri, 27 Mar 2009 13:19:50 +0800 Subject: [PATCH 03/28] BUG#37145 Killing a statement doing DDL may log binlog event with error code 1053 When the thread executing a DDL was killed after finished its execution but before writing the binlog event, the error code in the binlog event could be set wrongly to ER_SERVER_SHUTDOWN or ER_QUERY_INTERRUPTED. This patch fixed the problem by ignoring the kill status when constructing the event for DDL statements. This patch also included the following changes in order to provide the test case. 1) modified mysqltest to support variable for connection command 2) modified mysql-test-run.pl, add new variable MYSQL_SLAVE to run mysql client against the slave mysqld. --- client/mysqltest.c | 21 +- mysql-test/include/diff_master_slave.inc | 21 ++ mysql-test/include/kill_query.inc | 68 +++++ .../kill_query_and_diff_master_slave.inc | 43 +++ mysql-test/mysql-test-run.pl | 14 +- mysql-test/r/rpl_killed_ddl.result | 146 ++++++++++ mysql-test/t/rpl_killed_ddl-master.opt | 1 + mysql-test/t/rpl_killed_ddl.test | 271 ++++++++++++++++++ sql/item_func.cc | 4 + sql/log.cc | 15 +- sql/log_event.cc | 3 + sql/log_event.h | 6 +- sql/mysql_priv.h | 7 + sql/sp.cc | 8 +- sql/sp_head.cc | 3 +- sql/sql_acl.cc | 24 +- sql/sql_base.cc | 16 +- sql/sql_db.cc | 8 +- sql/sql_delete.cc | 4 +- sql/sql_insert.cc | 5 +- sql/sql_parse.cc | 12 +- sql/sql_rename.cc | 3 +- sql/sql_table.cc | 24 +- sql/sql_trigger.cc | 2 +- sql/sql_update.cc | 2 +- sql/sql_view.cc | 6 +- 26 files changed, 674 insertions(+), 63 deletions(-) create mode 100644 mysql-test/include/diff_master_slave.inc create mode 100644 mysql-test/include/kill_query.inc create mode 100644 mysql-test/include/kill_query_and_diff_master_slave.inc create mode 100644 mysql-test/r/rpl_killed_ddl.result create mode 100644 mysql-test/t/rpl_killed_ddl-master.opt create mode 100644 mysql-test/t/rpl_killed_ddl.test diff --git a/client/mysqltest.c b/client/mysqltest.c index 312012d7b8d..865c1d9a717 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -4093,13 +4093,20 @@ int select_connection(struct st_command *command) if (!*p) die("Missing connection name in connect"); - name= p; - while (*p && !my_isspace(charset_info,*p)) - p++; - if (*p) - *p++= 0; - command->last_argument= p; - return select_connection_name(name); + + static DYNAMIC_STRING ds_connection; + const struct command_arg connection_args[] = { + { "connection_name", ARG_STRING, TRUE, &ds_connection, "Name of the connection that we switch to." } + }; + check_command_args(command, command->first_argument, connection_args, + sizeof(connection_args)/sizeof(struct command_arg), + ','); + + DBUG_PRINT("info", ("changing connection: %s", ds_connection.str)); + + int ret= select_connection_name(ds_connection.str); + dynstr_free(&ds_connection); + return ret; } diff --git a/mysql-test/include/diff_master_slave.inc b/mysql-test/include/diff_master_slave.inc new file mode 100644 index 00000000000..b6d79190671 --- /dev/null +++ b/mysql-test/include/diff_master_slave.inc @@ -0,0 +1,21 @@ +# ==== Purpose ==== +# +# Diff the output of a statement on master and slave +# +# ==== Usage ===== +# +# let $diff_statement= SELECT * FROM t1 WHERE a < 100; +# source include/diff_master_slave.inc; + +--echo source include/diff_master_slave.inc; +disable_query_log; +disable_result_log; + +exec $MYSQL test -e "$diff_statement" > $MYSQLTEST_VARDIR/tmp/diff_master.out; +sync_slave_with_master; +exec $MYSQL_SLAVE test -e "$diff_statement" > $MYSQLTEST_VARDIR/tmp/diff_slave.out; + +diff_files $MYSQLTEST_VARDIR/tmp/diff_master.out $MYSQLTEST_VARDIR/tmp/diff_slave.out; + +enable_result_log; +enable_query_log; diff --git a/mysql-test/include/kill_query.inc b/mysql-test/include/kill_query.inc new file mode 100644 index 00000000000..341c3b93535 --- /dev/null +++ b/mysql-test/include/kill_query.inc @@ -0,0 +1,68 @@ +# ==== Purpose ==== +# +# Kill a query in the master connection, and then try to reap the +# result of the killed query. +# +# ==== Usage ==== +# +# The following variables should be set before sourcing this file. +# +# $debug_lock: name of the debug user lock, if set, will release/lock +# the specified debug lock accordingly, and before +# sourcing this, connection 'master' should get the user +# lock and run a query in another thread, which will +# block before creating statement event. +# +# $connection_name: name of the connection that is waiting for the +# lock, this can not be 'master' +# +# $connection_id: id of the connection that is waiting for the lock +# +# Example: +# let $debug_lock=; +# connection master1; +# let $connection_name= master1; +# let $connection_id= `SELECT CONNECTION_ID()`; +# send CREATE TABLE t1; +# source kill_query.inc; +# +# let $debug_lock= "debug_lock.before_query_log_event"; +# connection master; +# eval SELECT GET_LOCK($debug_lock, 10); +# connection master1; +# let $connection_name= master1; +# let $connection_id= `SELECT CONNECTION_ID()`; +# send CREATE TABLE t1; +# source kill_query.inc; + + +--echo source include/kill_query.inc; +disable_query_log; +disable_result_log; +connection master; + +# kill the query that is waiting +eval kill query $connection_id; + +if (`SELECT '$debug_lock' != ''`) +{ + # release the lock to allow binlog continue + eval SELECT RELEASE_LOCK($debug_lock); +} + +# reap the result of the waiting query +connection $connection_name; +error 0, 1317, 1307, 1306, 1334, 1305; +reap; + +connection master; + +if (`SELECT '$debug_lock' != ''`) +{ + # get lock again to make the next query wait + eval SELECT GET_LOCK($debug_lock, 10); +} + +connection $connection_name; +enable_query_log; +enable_result_log; diff --git a/mysql-test/include/kill_query_and_diff_master_slave.inc b/mysql-test/include/kill_query_and_diff_master_slave.inc new file mode 100644 index 00000000000..611d6929c99 --- /dev/null +++ b/mysql-test/include/kill_query_and_diff_master_slave.inc @@ -0,0 +1,43 @@ +# ==== Purpose ==== +# +# Kill a query, sync master with slave, and diff the output of a +# statement on master and slave to check if statement is correctly +# replicated. +# +# ==== Usage ==== +# +# connection ; +# let $connection_name= +# let $connection_id=`SELECT CONNECTION_ID()`; +# let $diff_statement=; +# send ; +# source include/kill_query_and_diff_master_slave.inc; +# +# Note: must not be 'master'. +# +# See also kill_query.inc and diff_master_slave.inc for more +# information + +source include/kill_query.inc; + +# Release the debug lock if used, so that the statements in +# diff_master_slave.inc will not be blocked. +connection master; +disable_query_log; +disable_result_log; +if (`SELECT '$debug_lock' != ''`) +{ + eval SELECT RELEASE_LOCK($debug_lock); +} +enable_result_log; +enable_query_log; + +source include/diff_master_slave.inc; + +# Acquire the debug lock again if used +connection master; +disable_query_log; disable_result_log; if (`SELECT '$debug_lock' != +''`) { eval SELECT GET_LOCK($debug_lock, 10); } enable_result_log; +enable_query_log; + +connection $connection_name; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 0948c973e9b..ffa9b4cb1d3 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2063,7 +2063,7 @@ sub environment_setup () { $ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog; # ---------------------------------------------------- - # Setup env so childs can execute mysql + # Setup env so childs can execute mysql against master # ---------------------------------------------------- my $cmdline_mysql= mtr_native_path($exe_mysql) . @@ -2074,6 +2074,18 @@ sub environment_setup () { $ENV{'MYSQL'}= $cmdline_mysql; + # ---------------------------------------------------- + # Setup env so childs can execute mysql against slave + # ---------------------------------------------------- + my $cmdline_mysql_slave= + mtr_native_path($exe_mysql) . + " --no-defaults --host=localhost --user=root --password= " . + "--port=$slave->[0]->{'port'} " . + "--socket=$slave->[0]->{'path_sock'} ". + "--character-sets-dir=$path_charsetsdir"; + + $ENV{'MYSQL_SLAVE'}= $cmdline_mysql_slave; + # ---------------------------------------------------- # Setup env so childs can execute bug25714 # ---------------------------------------------------- diff --git a/mysql-test/r/rpl_killed_ddl.result b/mysql-test/r/rpl_killed_ddl.result new file mode 100644 index 00000000000..aa419a8556e --- /dev/null +++ b/mysql-test/r/rpl_killed_ddl.result @@ -0,0 +1,146 @@ +stop slave; +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; +start slave; +DROP DATABASE IF EXISTS d1; +DROP DATABASE IF EXISTS d2; +DROP DATABASE IF EXISTS d3; +DROP DATABASE IF EXISTS d4; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; +DROP FUNCTION IF EXISTS f4; +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +DROP TABLE IF EXISTS t4; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP PROCEDURE IF EXISTS p4; +DROP TRIGGER IF EXISTS tr1; +DROP TRIGGER IF EXISTS tr2; +DROP TRIGGER IF EXISTS tr3; +DROP TRIGGER IF EXISTS tr4; +CREATE DATABASE d1; +CREATE FUNCTION f1 () RETURNS INT DETERMINISTIC +RETURN 1; +CREATE PROCEDURE p1 (OUT rows INT) +BEGIN +SELECT COUNT(*) INTO rows FROM t1; +END; +// +CREATE TABLE t1 (a int); +CREATE TABLE t3 (a int); +CREATE TRIGGER tr1 BEFORE INSERT ON t1 +FOR EACH ROW BEGIN +DELETE FROM t4 WHERE a=NEW.a; +END; +// +CREATE INDEX i1 ON t1 (a); +CREATE VIEW v1 AS SELECT a FROM t1 WHERE a < 100; +[on master] +[on master1] +CREATE DATABASE d2; +source include/kill_query.inc; +source include/diff_master_slave.inc; +ALTER DATABASE d1 +DEFAULT CHARACTER SET = 'utf8'; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP DATABASE d1; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP DATABASE d2; +source include/kill_query.inc; +source include/diff_master_slave.inc; +CREATE FUNCTION f2 () RETURNS INT DETERMINISTIC +RETURN 1; +source include/kill_query.inc; +source include/diff_master_slave.inc; +ALTER FUNCTION f1 SQL SECURITY INVOKER; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP FUNCTION IF EXISTS f1; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP FUNCTION IF EXISTS f2; +source include/kill_query.inc; +source include/diff_master_slave.inc; +CREATE PROCEDURE p2 (OUT rows INT) +BEGIN +SELECT COUNT(*) INTO rows FROM t2; +END; +// +source include/kill_query.inc; +source include/diff_master_slave.inc; +ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows of table t1'; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP PROCEDURE IF EXISTS p1; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP PROCEDURE IF EXISTS p2; +source include/kill_query.inc; +source include/diff_master_slave.inc; +CREATE TABLE t2 (b int); +source include/kill_query.inc; +source include/diff_master_slave.inc; +ALTER TABLE t1 ADD (d int); +source include/kill_query.inc; +source include/diff_master_slave.inc; +RENAME TABLE t3 TO t4; +source include/kill_query.inc; +source include/diff_master_slave.inc; +CREATE INDEX i2 on t1 (a); +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP INDEX i1 on t1; +source include/kill_query.inc; +source include/diff_master_slave.inc; +CREATE TRIGGER tr2 BEFORE INSERT ON t4 +FOR EACH ROW BEGIN +DELETE FROM t1 WHERE a=NEW.a; +END; +// +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP TRIGGER tr1; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP TRIGGER IF EXISTS tr2; +source include/kill_query.inc; +source include/diff_master_slave.inc; +CREATE VIEW v2 AS SELECT a FROM t1 WHERE a > 100; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP VIEW v1; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP VIEW IF EXISTS v2; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP TABLE t1; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP TABLE IF EXISTS t2; +source include/kill_query.inc; +source include/diff_master_slave.inc; +DROP DATABASE IF EXISTS d1; +DROP DATABASE IF EXISTS d2; +DROP DATABASE IF EXISTS d3; +DROP DATABASE IF EXISTS d4; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; +DROP FUNCTION IF EXISTS f4; +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +DROP TABLE IF EXISTS t4; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP PROCEDURE IF EXISTS p4; diff --git a/mysql-test/t/rpl_killed_ddl-master.opt b/mysql-test/t/rpl_killed_ddl-master.opt new file mode 100644 index 00000000000..aaf2d8a4251 --- /dev/null +++ b/mysql-test/t/rpl_killed_ddl-master.opt @@ -0,0 +1 @@ +--debug=d,debug_lock_before_query_log_event diff --git a/mysql-test/t/rpl_killed_ddl.test b/mysql-test/t/rpl_killed_ddl.test new file mode 100644 index 00000000000..f4f2f6ac320 --- /dev/null +++ b/mysql-test/t/rpl_killed_ddl.test @@ -0,0 +1,271 @@ +# ==== Purpose ==== +# +# This test check if DDL statements are correctly binlogged when the +# thread is killed +# +# ==== Method ==== +# +# Start a DDL query and kill it, check if the error code of the binlog +# event is correct. +# +# DDL statements tested: +# CREATE/ALTER/RENAME/DROP DATABASE +# CREATE/ALTER/DROP FUNCTION +# CREATE/ALTER/DROP PROCEDURE +# CREATE/ALTER/RENAME/DROP TABLE +# CREATE/DROP TRIGGER +# CREATE/ALTER/DROP VIEW +# +# ==== Bugs ===== +# + +source include/have_debug.inc; +source include/master-slave.inc; + +# Use the DBUG_SYNC_POINT to make sure the thread running the DDL is +# waiting before creating the query log event + +let $debug_lock= "debug_lock.before_query_log_event"; + +######## INITIALIZATION ######## + +disable_warnings; +DROP DATABASE IF EXISTS d1; +DROP DATABASE IF EXISTS d2; +DROP DATABASE IF EXISTS d3; +DROP DATABASE IF EXISTS d4; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; +DROP FUNCTION IF EXISTS f4; +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +DROP TABLE IF EXISTS t4; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP PROCEDURE IF EXISTS p4; +DROP TRIGGER IF EXISTS tr1; +DROP TRIGGER IF EXISTS tr2; +DROP TRIGGER IF EXISTS tr3; +DROP TRIGGER IF EXISTS tr4; +enable_warnings; + +CREATE DATABASE d1; + +CREATE FUNCTION f1 () RETURNS INT DETERMINISTIC + RETURN 1; + +DELIMITER //; +CREATE PROCEDURE p1 (OUT rows INT) + BEGIN + SELECT COUNT(*) INTO rows FROM t1; + END; + // +DELIMITER ;// + +CREATE TABLE t1 (a int); +CREATE TABLE t3 (a int); + +DELIMITER //; +CREATE TRIGGER tr1 BEFORE INSERT ON t1 + FOR EACH ROW BEGIN + DELETE FROM t4 WHERE a=NEW.a; + END; + // +DELIMITER ;// + +CREATE INDEX i1 ON t1 (a); + +CREATE VIEW v1 AS SELECT a FROM t1 WHERE a < 100; + +sync_slave_with_master; + +connection master1; +let $connection_name= master1; +let $connection_id= `SELECT CONNECTION_ID()`; + +connection master; +echo [on master]; + +# This will block the execution of a statement at the DBUG_SYNC_POINT +# with given lock name +if (`SELECT '$debug_lock' != ''`) +{ + disable_query_log; + disable_result_log; + eval SELECT IS_FREE_LOCK($debug_lock); + eval SELECT GET_LOCK($debug_lock, 10); + eval SELECT IS_FREE_LOCK($debug_lock); + enable_query_log; + enable_result_log; +} + +######## START TEST ######## + +connection master1; +echo [on master1]; + +disable_warnings; + +######## DATABASE ######## + +let $diff_statement= SHOW DATABASES LIKE 'd%'; + +send CREATE DATABASE d2; +source include/kill_query_and_diff_master_slave.inc; + +send ALTER DATABASE d1 + DEFAULT CHARACTER SET = 'utf8'; +source include/kill_query_and_diff_master_slave.inc; + +send DROP DATABASE d1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP DATABASE d2; +source include/kill_query_and_diff_master_slave.inc; + +######## FUNCTION ######## + +let $diff_statement= SHOW FUNCTION STATUS LIKE 'f%'; + +send CREATE FUNCTION f2 () RETURNS INT DETERMINISTIC + RETURN 1; +source include/kill_query_and_diff_master_slave.inc; + +send ALTER FUNCTION f1 SQL SECURITY INVOKER; +source include/kill_query_and_diff_master_slave.inc; + +# function f1 probably does not exist because the ALTER query was +# killed +send DROP FUNCTION IF EXISTS f1; +source include/kill_query_and_diff_master_slave.inc; + +# function f2 probably does not exist because the CREATE query was +# killed +send DROP FUNCTION IF EXISTS f2; +source include/kill_query_and_diff_master_slave.inc; + +######## PROCEDURE ######## + +let $diff_statement= SHOW PROCEDURE STATUS LIKE 'p%'; + +DELIMITER //; +send CREATE PROCEDURE p2 (OUT rows INT) + BEGIN + SELECT COUNT(*) INTO rows FROM t2; + END; + // +DELIMITER ;// +source include/kill_query_and_diff_master_slave.inc; + +send ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows of table t1'; +source include/kill_query_and_diff_master_slave.inc; + +send DROP PROCEDURE IF EXISTS p1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP PROCEDURE IF EXISTS p2; +source include/kill_query_and_diff_master_slave.inc; + +######## TABLE ######## + +let $diff_statement= SHOW TABLES LIKE 't%'; + +send CREATE TABLE t2 (b int); +source include/kill_query_and_diff_master_slave.inc; + +send ALTER TABLE t1 ADD (d int); +source include/kill_query_and_diff_master_slave.inc; + +send RENAME TABLE t3 TO t4; +source include/kill_query_and_diff_master_slave.inc; + +######## INDEX ######## + +let $diff_statement= SHOW INDEX FROM t1; + +send CREATE INDEX i2 on t1 (a); +source include/kill_query_and_diff_master_slave.inc; + +send DROP INDEX i1 on t1; +source include/kill_query_and_diff_master_slave.inc; + +######## TRIGGER ######## + +let $diff_statement= SHOW TRIGGERS LIKE 'v%'; + +DELIMITER //; +send CREATE TRIGGER tr2 BEFORE INSERT ON t4 + FOR EACH ROW BEGIN + DELETE FROM t1 WHERE a=NEW.a; + END; + // +DELIMITER ;// +source include/kill_query_and_diff_master_slave.inc; + +send DROP TRIGGER tr1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP TRIGGER IF EXISTS tr2; +source include/kill_query_and_diff_master_slave.inc; + +######## VIEW ######## + +let $diff_statement= SHOW TABLES LIKE 'v%'; + +send CREATE VIEW v2 AS SELECT a FROM t1 WHERE a > 100; +source include/kill_query_and_diff_master_slave.inc; + +send DROP VIEW v1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP VIEW IF EXISTS v2; +source include/kill_query_and_diff_master_slave.inc; + +######## DROP TABLE ######## + +# Because of BUG#43529, we cannot use the DBUG_SYNC_POINT for DROP +# TABLE statements on 5.0 +connection master; +disable_query_log; +disable_result_log; +eval SELECT RELEASE_LOCK($debug_lock); +enable_result_log; +enable_query_log; +let $debug_lock=; + +connection master1; + +let $diff_statement= SHOW TABLES LIKE 't%'; + +send DROP TABLE t1; +source include/kill_query_and_diff_master_slave.inc; + +send DROP TABLE IF EXISTS t2; +source include/kill_query_and_diff_master_slave.inc; + +######## CLEAN UP ######## + +# The DROP statements above are killed during the process, so they +# does not make sure the objects are dropped. + +disable_warnings; +DROP DATABASE IF EXISTS d1; +DROP DATABASE IF EXISTS d2; +DROP DATABASE IF EXISTS d3; +DROP DATABASE IF EXISTS d4; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; +DROP FUNCTION IF EXISTS f4; +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +DROP TABLE IF EXISTS t4; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP PROCEDURE IF EXISTS p4; +enable_warnings; diff --git a/sql/item_func.cc b/sql/item_func.cc index 47e16a1bcc3..e7e75ecd020 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3377,6 +3377,10 @@ longlong Item_master_pos_wait::val_int() } #ifdef EXTRA_DEBUG +/** + This will release the user lock that the thread currently locked, + please see also the comment of DEBUG_SYNC_POINT. +*/ void debug_sync_point(const char* lock_name, uint lock_timeout) { THD* thd=current_thd; diff --git a/sql/log.cc b/sql/log.cc index d979dd101e0..b16303ee232 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -158,7 +158,8 @@ static int binlog_commit(THD *thd, bool all) */ if (all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { - Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE); + Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), + TRUE, FALSE, THD::KILLED_NO_VALUE); qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE) DBUG_RETURN(binlog_end_trans(thd, trans_log, &qev)); } @@ -202,7 +203,8 @@ static int binlog_rollback(THD *thd, bool all) */ if (unlikely(thd->transaction.all.modified_non_trans_table)) { - Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE); + Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), + TRUE, FALSE, THD::KILLED_NO_VALUE); qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE) error= binlog_end_trans(thd, trans_log, &qev); } @@ -240,7 +242,8 @@ static int binlog_savepoint_set(THD *thd, void *sv) *(my_off_t *)sv= my_b_tell(trans_log); /* Write it to the binary log */ - Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + TRUE, FALSE, THD::KILLED_NO_VALUE); DBUG_RETURN(mysql_bin_log.write(&qinfo)); } @@ -257,7 +260,8 @@ static int binlog_savepoint_rollback(THD *thd, void *sv) */ if (unlikely(thd->transaction.all.modified_non_trans_table)) { - Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + TRUE, FALSE, THD::KILLED_NO_VALUE); DBUG_RETURN(mysql_bin_log.write(&qinfo)); } reinit_io_cache(trans_log, WRITE_CACHE, *(my_off_t *)sv, 0, 0); @@ -2089,7 +2093,8 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event) transaction is either a BEGIN..COMMIT block or a single statement in autocommit mode. */ - Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE); + Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), + TRUE, FALSE, THD::KILLED_NO_VALUE); /* Imagine this is rollback due to net timeout, after all statements of the transaction succeeded. Then we want a diff --git a/sql/log_event.cc b/sql/log_event.cc index c4cdfc27fa0..7856e1458ef 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1358,6 +1358,9 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, { time_t end_time; + DBUG_EXECUTE_IF("debug_lock_before_query_log_event", + DBUG_SYNC_POINT("debug_lock.before_query_log_event", 10);); + if (killed_status_arg == THD::KILLED_NO_VALUE) killed_status_arg= thd_arg->killed; error_code= diff --git a/sql/log_event.h b/sql/log_event.h index 6ccbf8e4d5c..45e3d11b48c 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -813,9 +813,13 @@ public: #ifndef MYSQL_CLIENT + /* + for argument killed_err_arg, use ` THD::NOT_KILLED ' if the killed + status should be ignored, otherwise use `THD::KILLED_NO_VALUE' + */ Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans, bool suppress_use, - THD::killed_state killed_err_arg= THD::KILLED_NO_VALUE); + THD::killed_state killed_err_arg); const char* get_db() { return db; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index b855af9a8d3..37ba0611ee0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -451,6 +451,13 @@ MY_LOCALE *my_locale_by_number(uint number); The client tells the server to block with SELECT GET_LOCK() and unblocks it with SELECT RELEASE_LOCK(). Used for debugging difficult concurrency problems + + NOTE: This will release the user lock that the thread currently + locked, which can cause problem if users want to use user locks for + other purposes. In order to overcome this problem, it's adviced to + wrap the call to DBUG_SYNC_POINT() within the DBUG_EXECUTE_IF(), so + that it will only be activated if the given keyword is included in + the 'debug' option, and will not fiddle user locks otherwise. */ #define DBUG_SYNC_POINT(lock_name,lock_timeout) \ debug_sync_point(lock_name,lock_timeout) diff --git a/sql/sp.cc b/sql/sp.cc index 3af51b82521..2450e9564d0 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -646,7 +646,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) /* Such a statement can always go directly to binlog, no trans cache */ Query_log_event qinfo(thd, log_query.c_ptr(), log_query.length(), 0, - FALSE); + FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } @@ -680,7 +680,8 @@ db_drop_routine(THD *thd, int type, sp_name *name) if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } @@ -725,7 +726,8 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b51d97e66c5..7da52458f26 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1601,7 +1601,8 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, if (need_binlog_call && thd->binlog_evt_union.unioned_events) { Query_log_event qinfo(thd, binlog_buf.ptr(), binlog_buf.length(), - thd->binlog_evt_union.unioned_events_trans, FALSE); + thd->binlog_evt_union.unioned_events_trans, + FALSE, THD::KILLED_NO_VALUE); if (mysql_bin_log.write(&qinfo) && thd->binlog_evt_union.unioned_events_trans) { diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index b2d0304f007..f61304a1e26 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1506,7 +1506,8 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->host.hostname ? acl_user->host.hostname : "", new_password)); thd->clear_error(); - Query_log_event qinfo(thd, buff, query_length, 0, FALSE); + Query_log_event qinfo(thd, buff, query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } end: @@ -3014,7 +3015,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } @@ -3181,7 +3183,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } @@ -3294,7 +3297,8 @@ bool mysql_grant(THD *thd, const char *db, List &list, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } @@ -5404,7 +5408,8 @@ bool mysql_create_user(THD *thd, List &list) if (some_users_created && mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } @@ -5473,7 +5478,8 @@ bool mysql_drop_user(THD *thd, List &list) if (some_users_deleted && mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } @@ -5553,7 +5559,8 @@ bool mysql_rename_user(THD *thd, List &list) if (some_users_renamed && mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } @@ -5731,7 +5738,8 @@ bool mysql_revoke_all(THD *thd, List &list) if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0cf3e023be9..8f60c02a08c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -793,18 +793,9 @@ void close_temporary_tables(THD *thd) thd->variables.character_set_client= system_charset_info; Query_log_event qinfo(thd, s_query.ptr(), s_query.length() - 1 /* to remove trailing ',' */, - 0, FALSE); + 0, FALSE, THD::NOT_KILLED); thd->variables.character_set_client= cs_save; - /* - Imagine the thread had created a temp table, then was doing a SELECT, and - the SELECT was killed. Then it's not clever to mark the statement above as - "killed", because it's not really a statement updating data, and there - are 99.99% chances it will succeed on slave. - If a real update (one updating a persistent table) was killed on the - master, then this real update will be logged with error_code=killed, - rightfully causing the slave to stop. - */ - qinfo.error_code= 0; + DBUG_ASSERT(qinfo.error_code == 0); mysql_bin_log.write(&qinfo); } else @@ -2578,7 +2569,8 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, { end = strxmov(strmov(query, "DELETE FROM `"), db,"`.`",name,"`", NullS); - Query_log_event qinfo(thd, query, (ulong)(end-query), 0, FALSE); + Query_log_event qinfo(thd, query, (ulong)(end-query), + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); my_free(query, MYF(0)); } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 80fea3ef1b1..be538783458 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -70,7 +70,7 @@ static byte* dboptions_get_key(my_dbopt_t *opt, uint *length, static inline void write_to_binlog(THD *thd, char *query, uint q_len, char *db, uint db_len) { - Query_log_event qinfo(thd, query, q_len, 0, 0); + Query_log_event qinfo(thd, query, q_len, 0, 0, THD::NOT_KILLED); qinfo.error_code= 0; qinfo.db= db; qinfo.db_len= db_len; @@ -562,7 +562,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, query, query_length, 0, - /* suppress_use */ TRUE); + /* suppress_use */ TRUE, THD::NOT_KILLED); /* Write should use the database being created as the "current @@ -645,7 +645,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, 0, - /* suppress_use */ TRUE); + /* suppress_use */ TRUE, THD::NOT_KILLED); /* Write should use the database being created as the "current @@ -770,7 +770,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, query, query_length, 0, - /* suppress_use */ TRUE); + /* suppress_use */ TRUE, THD::NOT_KILLED); /* Write should use the database being created as the "current database" and not the threads current database, which is the diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 38f89683065..a757b7c28a5 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -730,7 +730,7 @@ void multi_delete::send_error(uint errcode,const char *err) if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_tables, FALSE); + transactional_tables, FALSE, THD::KILLED_NO_VALUE); mysql_bin_log.write(&qinfo); } thd->transaction.all.modified_non_trans_table= true; @@ -958,7 +958,7 @@ end: { thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - 0, FALSE); + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } send_ok(thd); // This should return record count diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b79f979df05..dcee47f6518 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2537,7 +2537,8 @@ bool Delayed_insert::handle_inserts(void) thd.variables.time_zone = row->time_zone; } - Query_log_event qinfo(&thd, row->query, row->query_length, 0, FALSE); + Query_log_event qinfo(&thd, row->query, row->query_length, + 0, FALSE, THD::KILLED_NO_VALUE); mysql_bin_log.write(&qinfo); thd.time_zone_used = backup_time_zone_used; @@ -3099,7 +3100,7 @@ void select_insert::abort() if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_table, FALSE); + transactional_table, FALSE, THD::KILLED_NO_VALUE); mysql_bin_log.write(&qinfo); } if (thd->transaction.stmt.modified_non_trans_table) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2297283c92d..a946a6afb35 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3551,7 +3551,8 @@ end_with_restore_list: if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } @@ -3586,7 +3587,8 @@ end_with_restore_list: if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } @@ -3612,7 +3614,8 @@ end_with_restore_list: if (mysql_bin_log.is_open()) { thd->clear_error(); // No binlog error generated - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } @@ -4394,7 +4397,8 @@ end_with_restore_list: { if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index f6766aec285..cec9e4c39de 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -84,7 +84,8 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list) if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } send_ok(thd); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 963a98cfb59..eec6ad626f0 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -333,7 +333,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, { if (!error) thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + FALSE, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } @@ -1814,7 +1815,8 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name, if (!internal_tmp_table && mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + FALSE, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } error= FALSE; @@ -2903,7 +2905,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST *src_table, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + FALSE, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } res= FALSE; @@ -3012,7 +3015,8 @@ mysql_discard_or_import_tablespace(THD *thd, goto err; if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + FALSE, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } err: @@ -3168,7 +3172,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } send_ok(thd); @@ -3360,7 +3365,8 @@ view_err: if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + FALSE, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } send_ok(thd); @@ -3872,7 +3878,8 @@ view_err: if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + FALSE, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } goto end_temporary; @@ -4007,7 +4014,8 @@ view_err: if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + FALSE, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } broadcast_refresh(); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 930e3601699..d2ae494d4eb 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -304,7 +304,7 @@ end: /* Such a statement can always go directly to binlog, no trans cache. */ Query_log_event qinfo(thd, stmt_query.ptr(), stmt_query.length(), 0, - FALSE); + FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 8a3f5bcdc26..0da0b6e6635 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1575,7 +1575,7 @@ void multi_update::send_error(uint errcode,const char *err) into repl event. */ Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_tables, FALSE); + transactional_tables, FALSE, THD::KILLED_NO_VALUE); mysql_bin_log.write(&qinfo); } thd->transaction.all.modified_non_trans_table= TRUE; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 9e0fa87d5f5..9e1e2a20dc6 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -655,7 +655,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, else if (views->with_check == VIEW_CHECK_CASCADED) buff.append(STRING_WITH_LEN(" WITH CASCADED CHECK OPTION")); - Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE); + Query_log_event qinfo(thd, buff.ptr(), buff.length(), + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } @@ -1544,7 +1545,8 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) { if (!something_wrong) thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE); + Query_log_event qinfo(thd, thd->query, thd->query_length, + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } From 668d988c71a7980b3f131feb51c24427cfd78082 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Thu, 2 Apr 2009 11:29:28 -0400 Subject: [PATCH 04/28] Bug#43876: mysqld_multi introduces --no-defaults which screws up my system Bug#32136: mysqld_multi --defaults-file not respected while using \ --mysqld=mysqld_safe Revert change that adds "--no-defaults" to mysqld_multi. This closes Bug#43508 and re-opens Bug#32136. --- scripts/mysqld_multi.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 631e1e38cc7..3cb4665eb1c 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -293,12 +293,7 @@ sub start_mysqlds() @groups = &find_groups($groupids); for ($i = 0; defined($groups[$i]); $i++) { - # Defaults are made explicit parameters to server execution... @options = defaults_for_group($groups[$i]); - # ...so server MUST NOT try to read again from some config file, especially - # as the "right" file may be unknown to the server if we are using - # --defaults-file=... params in here. - unshift(@options,"--no-defaults"); $mysqld_found= 1; # The default $mysqld_found= 0 if (!length($mysqld)); From 4fda8858b16ebb41262e8e4944e204ece83aaec9 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Thu, 2 Apr 2009 18:34:18 -0400 Subject: [PATCH 05/28] Bug#43716: Test mysqlbinlog_row_big is failing, needs to be updated Altered the test to accommodate the new behavior of max_allowed_packet. Had to disconnect / reconnect the default connection for the new value to register. Re-enabled certain parts of the test that were commented out and added some setup / cleanup code to ensure proper reset of max_allowed_packet at the end of the test. Re-recorded the .result file to account for changes to the test. --- mysql-test/r/mysqlbinlog_row_big.result | 48 ++++++++++++++++----- mysql-test/t/mysqlbinlog_row_big.test | 56 +++++++++++++++++-------- 2 files changed, 77 insertions(+), 27 deletions(-) diff --git a/mysql-test/r/mysqlbinlog_row_big.result b/mysql-test/r/mysqlbinlog_row_big.result index f2ca72f9936..46fa0dc79cd 100644 --- a/mysql-test/r/mysqlbinlog_row_big.result +++ b/mysql-test/r/mysqlbinlog_row_big.result @@ -9,7 +9,17 @@ SET timestamp=1000000000; # # We need big packets. # +# Capture initial value to reset at the end of the test +# Now adjust max_allowed_packet SET @@global.max_allowed_packet= 1024*1024*1024; +max_allowed_packet is a global variable. +In order for the preceding change in max_allowed_packets' value +to be seen and used, we must start a new connection. +The change does not take effect with the current one. +For simplicity, we just disconnect / reconnect connection default here. +Disconnecting default connection... +Reconnecting default connection... +default connection established, continuing with the test # # Delete all existing binary logs. # @@ -21,40 +31,56 @@ CREATE TABLE t1 ( c1 LONGTEXT ) ENGINE=MyISAM DEFAULT CHARSET latin1; # -# Show how much rows are affected by each statement. +# Show how many rows are affected by each statement. # # -# Insert a big row. +# Insert some big rows. # +256MB +INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 16777216)); +affected rows: 1 +32MB INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 2097152)); affected rows: 1 +4MB +INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 262144)); +affected rows: 1 +512KB +INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 32768)); +affected rows: 1 # # Show what we have in the table. # Do not display the column value itself, just its length. # SELECT LENGTH(c1) FROM t1; +LENGTH(c1) 268435456 LENGTH(c1) 33554432 -affected rows: 1 +LENGTH(c1) 4194304 +LENGTH(c1) 524288 +affected rows: 4 # -# Grow the row by updating. +# Grow the rows by updating. # UPDATE t1 SET c1 = CONCAT(c1, c1); -affected rows: 1 -info: Rows matched: 1 Changed: 1 Warnings: 0 +affected rows: 4 +info: Rows matched: 4 Changed: 4 Warnings: 0 # # Show what we have in the table. # Do not display the column value itself, just its length. # SELECT LENGTH(c1) FROM t1; +LENGTH(c1) 536870912 +LENGTH(c1) 1048576 LENGTH(c1) 67108864 -affected rows: 1 +LENGTH(c1) 8388608 +affected rows: 4 # -# Delete the row. +# Delete the rows. # DELETE FROM t1 WHERE c1 >= 'ManyMegaByteBlck'; -affected rows: 1 +affected rows: 4 # -# Hide how much rows are affected by each statement. +# Hide how many rows are affected by each statement. # # # Flush all log buffers to the log file. @@ -70,5 +96,7 @@ FLUSH LOGS; # # Cleanup. # +# reset variable value to pass testcase checks +SET @@global.max_allowed_packet = 1048576; DROP TABLE t1; remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_big_1.out diff --git a/mysql-test/t/mysqlbinlog_row_big.test b/mysql-test/t/mysqlbinlog_row_big.test index 14e818e7214..75f3b90269f 100644 --- a/mysql-test/t/mysqlbinlog_row_big.test +++ b/mysql-test/t/mysqlbinlog_row_big.test @@ -38,8 +38,26 @@ SET timestamp=1000000000; --echo # --echo # We need big packets. --echo # +--echo # Capture initial value to reset at the end of the test +# use let $ = query_get_value as FLUSH statements +# in the test will set @ values to NULL +let $orig_max_allowed_packet = +query_get_value(SELECT @@global.max_allowed_packet, @@global.max_allowed_packet, 1); + +--echo # Now adjust max_allowed_packet SET @@global.max_allowed_packet= 1024*1024*1024; +--echo max_allowed_packet is a global variable. +--echo In order for the preceding change in max_allowed_packets' value +--echo to be seen and used, we must start a new connection. +--echo The change does not take effect with the current one. +--echo For simplicity, we just disconnect / reconnect connection default here. +--echo Disconnecting default connection... +disconnect default; +--echo Reconnecting default connection... +connect (default, localhost,root,,); +--echo default connection established, continuing with the test + --echo # --echo # Delete all existing binary logs. --echo # @@ -53,34 +71,35 @@ eval CREATE TABLE t1 ( ) ENGINE=$engine_type DEFAULT CHARSET latin1; --echo # ---echo # Show how much rows are affected by each statement. +--echo # Show how many rows are affected by each statement. --echo # --enable_info --echo # ---echo # Insert a big row. +--echo # Insert some big rows. --echo # -# -# 256MB -#INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 16777216)); -# -# 32MB + +--echo 256MB +INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 16777216)); + +--echo 32MB INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 2097152)); -# -# 4MB -#INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 262144)); -# -# 512KB -#INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 32768)); + +--echo 4MB +INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 262144)); + +--echo 512KB +INSERT INTO t1 VALUES (REPEAT('ManyMegaByteBlck', 32768)); --echo # --echo # Show what we have in the table. --echo # Do not display the column value itself, just its length. --echo # +--sorted_result query_vertical SELECT LENGTH(c1) FROM t1; --echo # ---echo # Grow the row by updating. +--echo # Grow the rows by updating. --echo # UPDATE t1 SET c1 = CONCAT(c1, c1); @@ -88,15 +107,16 @@ UPDATE t1 SET c1 = CONCAT(c1, c1); --echo # Show what we have in the table. --echo # Do not display the column value itself, just its length. --echo # +--sorted_result query_vertical SELECT LENGTH(c1) FROM t1; --echo # ---echo # Delete the row. +--echo # Delete the rows. --echo # DELETE FROM t1 WHERE c1 >= 'ManyMegaByteBlck'; --echo # ---echo # Hide how much rows are affected by each statement. +--echo # Hide how many rows are affected by each statement. --echo # --disable_info @@ -113,13 +133,15 @@ FLUSH LOGS; --echo # at the bottom of the test script. --echo # let $MYSQLD_DATADIR= `select @@datadir`; ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_result $MYSQLTEST_VARDIR --replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ --exec $MYSQL_BINLOG -v -v $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/$mysqlbinlog_output --echo # --echo # Cleanup. --echo # +--echo # reset variable value to pass testcase checks +eval SET @@global.max_allowed_packet = $orig_max_allowed_packet; DROP TABLE t1; --echo remove_file \$MYSQLTEST_VARDIR/$mysqlbinlog_output From 33364242bb6f27b87af495ca14c5cd7a22952b00 Mon Sep 17 00:00:00 2001 From: Horst Hunger Date: Fri, 3 Apr 2009 11:37:48 +0200 Subject: [PATCH 06/28] Fix belonging to bug#42838: Though this bug is only for 6.0 I put in some updated result files for 6.0 and this are the corrsponding resul files for 5.1, so that sys_vars should then run successfully also in 5.1. --- .../r/binlog_cache_size_basic_64.result | 2 +- .../r/bulk_insert_buffer_size_basic_64.result | 4 +++ .../r/delayed_insert_limit_basic_64.result | 2 +- .../r/delayed_queue_size_basic_64.result | 2 +- .../r/join_buffer_size_basic_64.result | 4 +-- .../r/key_buffer_size_basic_64.result | 2 -- .../sys_vars/r/log_warnings_basic_64.result | 4 +++ .../r/max_binlog_cache_size_basic_64.result | 6 ++-- .../r/max_connect_errors_basic_64.result | 4 +-- .../r/max_heap_table_size_basic_64.result | 6 ++-- .../r/max_seeks_for_key_basic_64.result | 4 +-- .../sys_vars/r/max_tmp_tables_basic_64.result | 8 ++--- .../r/max_write_lock_count_basic_64.result | 4 +-- .../r/min_examined_row_limit_basic_64.result | 4 +++ .../r/multi_range_count_basic_64.result | 4 +-- .../myisam_max_sort_file_size_basic_64.result | 8 ++++- .../r/myisam_repair_threads_basic_64.result | 4 +-- .../r/myisam_sort_buffer_size_basic_64.result | 4 +-- .../r/net_retry_count_basic_64.result | 4 +-- .../r/query_alloc_block_size_basic_64.result | 4 +-- .../r/query_cache_limit_basic_64.result | 4 +++ .../query_cache_min_res_unit_basic_64.result | 4 +++ .../r/query_cache_size_basic_64.result | 4 +++ .../r/query_prealloc_size_basic_64.result | 34 +++---------------- .../r/range_alloc_block_size_basic_64.result | 4 +-- .../r/rpl_recovery_rank_basic_64.result | 6 ++++ .../slave_transaction_retries_basic_64.result | 2 ++ .../sys_vars/r/sync_binlog_basic_64.result | 4 +++ ...ansaction_alloc_block_size_basic_64.result | 2 +- .../transaction_prealloc_size_basic_64.result | 2 +- .../sys_vars/r/wait_timeout_basic_64.result | 2 +- 31 files changed, 84 insertions(+), 68 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/binlog_cache_size_basic_64.result b/mysql-test/suite/sys_vars/r/binlog_cache_size_basic_64.result index 45ed43589a3..3858df0f4d6 100644 --- a/mysql-test/suite/sys_vars/r/binlog_cache_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/binlog_cache_size_basic_64.result @@ -44,7 +44,7 @@ SET @@global.binlog_cache_size = 10000.01; ERROR 42000: Incorrect argument type to variable 'binlog_cache_size' SET @@global.binlog_cache_size = -1024; Warnings: -Warning 1292 Truncated incorrect binlog_cache_size value: '0' +Warning 1292 Truncated incorrect binlog_cache_size value: '-1024' SELECT @@global.binlog_cache_size; @@global.binlog_cache_size 4096 diff --git a/mysql-test/suite/sys_vars/r/bulk_insert_buffer_size_basic_64.result b/mysql-test/suite/sys_vars/r/bulk_insert_buffer_size_basic_64.result index 9e0e8e07470..320290fbca1 100644 --- a/mysql-test/suite/sys_vars/r/bulk_insert_buffer_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/bulk_insert_buffer_size_basic_64.result @@ -66,6 +66,8 @@ SELECT @@global.bulk_insert_buffer_size; @@global.bulk_insert_buffer_size 42949672950 SET @@global.bulk_insert_buffer_size = -1024; +Warnings: +Warning 1292 Truncated incorrect bulk_insert_buffer_size value: '-1024' SELECT @@global.bulk_insert_buffer_size; @@global.bulk_insert_buffer_size 0 @@ -80,6 +82,8 @@ SELECT @@session.bulk_insert_buffer_size; @@session.bulk_insert_buffer_size 42949672950 SET @@session.bulk_insert_buffer_size = -2; +Warnings: +Warning 1292 Truncated incorrect bulk_insert_buffer_size value: '-2' SELECT @@session.bulk_insert_buffer_size; @@session.bulk_insert_buffer_size 0 diff --git a/mysql-test/suite/sys_vars/r/delayed_insert_limit_basic_64.result b/mysql-test/suite/sys_vars/r/delayed_insert_limit_basic_64.result index 246bf0e8734..1f7d0a52e72 100644 --- a/mysql-test/suite/sys_vars/r/delayed_insert_limit_basic_64.result +++ b/mysql-test/suite/sys_vars/r/delayed_insert_limit_basic_64.result @@ -35,7 +35,7 @@ SELECT @@global.delayed_insert_limit; 1 SET @@global.delayed_insert_limit = -1024; Warnings: -Warning 1292 Truncated incorrect delayed_insert_limit value: '0' +Warning 1292 Truncated incorrect delayed_insert_limit value: '-1024' SELECT @@global.delayed_insert_limit; @@global.delayed_insert_limit 1 diff --git a/mysql-test/suite/sys_vars/r/delayed_queue_size_basic_64.result b/mysql-test/suite/sys_vars/r/delayed_queue_size_basic_64.result index d575626b0a1..ed866b7e0b4 100644 --- a/mysql-test/suite/sys_vars/r/delayed_queue_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/delayed_queue_size_basic_64.result @@ -35,7 +35,7 @@ SELECT @@global.delayed_queue_size; 1 SET @@global.delayed_queue_size = -1024; Warnings: -Warning 1292 Truncated incorrect delayed_queue_size value: '0' +Warning 1292 Truncated incorrect delayed_queue_size value: '-1024' SELECT @@global.delayed_queue_size; @@global.delayed_queue_size 1 diff --git a/mysql-test/suite/sys_vars/r/join_buffer_size_basic_64.result b/mysql-test/suite/sys_vars/r/join_buffer_size_basic_64.result index ed652af67d2..4811d4732df 100644 --- a/mysql-test/suite/sys_vars/r/join_buffer_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/join_buffer_size_basic_64.result @@ -71,7 +71,7 @@ SELECT @@global.join_buffer_size=8200 OR @@global.join_buffer_size= 8228; 1 SET @@global.join_buffer_size = -1024; Warnings: -Warning 1292 Truncated incorrect join_buffer_size value: '0' +Warning 1292 Truncated incorrect join_buffer_size value: '-1024' SELECT @@global.join_buffer_size=8200 OR @@global.join_buffer_size= 8228; @@global.join_buffer_size=8200 OR @@global.join_buffer_size= 8228 1 @@ -103,7 +103,7 @@ SELECT @@session.join_buffer_size=8200 OR @@session.join_buffer_size= 8228; 1 SET @@session.join_buffer_size = -2; Warnings: -Warning 1292 Truncated incorrect join_buffer_size value: '0' +Warning 1292 Truncated incorrect join_buffer_size value: '-2' SELECT @@session.join_buffer_size=8200 OR @@session.join_buffer_size= 8228; @@session.join_buffer_size=8200 OR @@session.join_buffer_size= 8228 1 diff --git a/mysql-test/suite/sys_vars/r/key_buffer_size_basic_64.result b/mysql-test/suite/sys_vars/r/key_buffer_size_basic_64.result index 9ce1ab20993..eea782701bb 100644 --- a/mysql-test/suite/sys_vars/r/key_buffer_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/key_buffer_size_basic_64.result @@ -17,8 +17,6 @@ SELECT @@global.key_buffer_size BETWEEN 8 AND 36; @@global.key_buffer_size BETWEEN 8 AND 36 1 SET @@global.key_buffer_size = 1800; -Warnings: -Warning 1292 Truncated incorrect key_buffer_size value: '1800' SELECT @@global.key_buffer_size BETWEEN 8 AND 36; @@global.key_buffer_size BETWEEN 8 AND 36 1 diff --git a/mysql-test/suite/sys_vars/r/log_warnings_basic_64.result b/mysql-test/suite/sys_vars/r/log_warnings_basic_64.result index ba6671c87a4..6a94881dad0 100644 --- a/mysql-test/suite/sys_vars/r/log_warnings_basic_64.result +++ b/mysql-test/suite/sys_vars/r/log_warnings_basic_64.result @@ -74,6 +74,8 @@ SELECT @@global.log_warnings; @@global.log_warnings 100000000000 SET @@global.log_warnings = -1024; +Warnings: +Warning 1292 Truncated incorrect log_warnings value: '-1024' SELECT @@global.log_warnings; @@global.log_warnings 0 @@ -92,6 +94,8 @@ SELECT @@session.log_warnings; @@session.log_warnings 100000000000 SET @@session.log_warnings = -2; +Warnings: +Warning 1292 Truncated incorrect log_warnings value: '-2' SELECT @@session.log_warnings; @@session.log_warnings 0 diff --git a/mysql-test/suite/sys_vars/r/max_binlog_cache_size_basic_64.result b/mysql-test/suite/sys_vars/r/max_binlog_cache_size_basic_64.result index 30db3f14dd4..10a42f6ab0e 100644 --- a/mysql-test/suite/sys_vars/r/max_binlog_cache_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/max_binlog_cache_size_basic_64.result @@ -1,7 +1,7 @@ SET @start_value = @@global.max_binlog_cache_size; SELECT @start_value; @start_value -18446744073709551615 +18446744073709547520 '#--------------------FN_DYNVARS_072_01------------------------#' SET @@global.max_binlog_cache_size = 5000; SET @@global.max_binlog_cache_size = DEFAULT; @@ -39,7 +39,7 @@ SELECT @@global.max_binlog_cache_size; '#--------------------FN_DYNVARS_072_04-------------------------#' SET @@global.max_binlog_cache_size = -1; Warnings: -Warning 1292 Truncated incorrect max_binlog_cache_size value: '0' +Warning 1292 Truncated incorrect max_binlog_cache_size value: '-1' SELECT @@global.max_binlog_cache_size; @@global.max_binlog_cache_size 4096 @@ -54,7 +54,7 @@ SELECT @@global.max_binlog_cache_size; 99999997952 SET @@global.max_binlog_cache_size = -1024; Warnings: -Warning 1292 Truncated incorrect max_binlog_cache_size value: '0' +Warning 1292 Truncated incorrect max_binlog_cache_size value: '-1024' SELECT @@global.max_binlog_cache_size; @@global.max_binlog_cache_size 4096 diff --git a/mysql-test/suite/sys_vars/r/max_connect_errors_basic_64.result b/mysql-test/suite/sys_vars/r/max_connect_errors_basic_64.result index 8117b650651..762cfd14a3a 100644 --- a/mysql-test/suite/sys_vars/r/max_connect_errors_basic_64.result +++ b/mysql-test/suite/sys_vars/r/max_connect_errors_basic_64.result @@ -39,7 +39,7 @@ SELECT @@global.max_connect_errors; '#--------------------FN_DYNVARS_073_04-------------------------#' SET @@global.max_connect_errors = -1; Warnings: -Warning 1292 Truncated incorrect max_connect_errors value: '0' +Warning 1292 Truncated incorrect max_connect_errors value: '-1' SELECT @@global.max_connect_errors; @@global.max_connect_errors 1 @@ -54,7 +54,7 @@ SELECT @@global.max_connect_errors; 100000000000 SET @@global.max_connect_errors = -1024; Warnings: -Warning 1292 Truncated incorrect max_connect_errors value: '0' +Warning 1292 Truncated incorrect max_connect_errors value: '-1024' SELECT @@global.max_connect_errors; @@global.max_connect_errors 1 diff --git a/mysql-test/suite/sys_vars/r/max_heap_table_size_basic_64.result b/mysql-test/suite/sys_vars/r/max_heap_table_size_basic_64.result index ebab80f376b..6642b6024b5 100644 --- a/mysql-test/suite/sys_vars/r/max_heap_table_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/max_heap_table_size_basic_64.result @@ -73,13 +73,13 @@ SELECT @@session.max_heap_table_size; '#------------------FN_DYNVARS_077_05-----------------------#' SET @@global.max_heap_table_size = -1; Warnings: -Warning 1292 Truncated incorrect max_heap_table_size value: '0' +Warning 1292 Truncated incorrect max_heap_table_size value: '-1' SELECT @@global.max_heap_table_size; @@global.max_heap_table_size 16384 SET @@global.max_heap_table_size = -1024; Warnings: -Warning 1292 Truncated incorrect max_heap_table_size value: '0' +Warning 1292 Truncated incorrect max_heap_table_size value: '-1024' SELECT @@global.max_heap_table_size; @@global.max_heap_table_size 16384 @@ -111,7 +111,7 @@ SELECT @@global.max_heap_table_size; 4294967296 SET @@session.max_heap_table_size = -1; Warnings: -Warning 1292 Truncated incorrect max_heap_table_size value: '0' +Warning 1292 Truncated incorrect max_heap_table_size value: '-1' SELECT @@session.max_heap_table_size; @@session.max_heap_table_size 16384 diff --git a/mysql-test/suite/sys_vars/r/max_seeks_for_key_basic_64.result b/mysql-test/suite/sys_vars/r/max_seeks_for_key_basic_64.result index eefb829cdae..5b1e076c188 100644 --- a/mysql-test/suite/sys_vars/r/max_seeks_for_key_basic_64.result +++ b/mysql-test/suite/sys_vars/r/max_seeks_for_key_basic_64.result @@ -77,7 +77,7 @@ SELECT @@global.max_seeks_for_key; 1 SET @@global.max_seeks_for_key = -1024; Warnings: -Warning 1292 Truncated incorrect max_seeks_for_key value: '0' +Warning 1292 Truncated incorrect max_seeks_for_key value: '-1024' SELECT @@global.max_seeks_for_key; @@global.max_seeks_for_key 1 @@ -103,7 +103,7 @@ SELECT @@session.max_seeks_for_key; 1 SET @@session.max_seeks_for_key = -2; Warnings: -Warning 1292 Truncated incorrect max_seeks_for_key value: '0' +Warning 1292 Truncated incorrect max_seeks_for_key value: '-2' SELECT @@session.max_seeks_for_key; @@session.max_seeks_for_key 1 diff --git a/mysql-test/suite/sys_vars/r/max_tmp_tables_basic_64.result b/mysql-test/suite/sys_vars/r/max_tmp_tables_basic_64.result index 4b9f68c509e..808e99b739d 100644 --- a/mysql-test/suite/sys_vars/r/max_tmp_tables_basic_64.result +++ b/mysql-test/suite/sys_vars/r/max_tmp_tables_basic_64.result @@ -71,7 +71,7 @@ SELECT @@session.max_tmp_tables; '#------------------FN_DYNVARS_086_05-----------------------#' SET @@global.max_tmp_tables = -1024; Warnings: -Warning 1292 Truncated incorrect max_tmp_tables value: '0' +Warning 1292 Truncated incorrect max_tmp_tables value: '-1024' SELECT @@global.max_tmp_tables; @@global.max_tmp_tables 1 @@ -81,7 +81,7 @@ SELECT @@global.max_tmp_tables; 4294967296 SET @@global.max_tmp_tables = -1; Warnings: -Warning 1292 Truncated incorrect max_tmp_tables value: '0' +Warning 1292 Truncated incorrect max_tmp_tables value: '-1' SELECT @@global.max_tmp_tables; @@global.max_tmp_tables 1 @@ -105,7 +105,7 @@ SELECT @@session.max_tmp_tables; 4294967296 SET @@session.max_tmp_tables = -1; Warnings: -Warning 1292 Truncated incorrect max_tmp_tables value: '0' +Warning 1292 Truncated incorrect max_tmp_tables value: '-1' SELECT @@session.max_tmp_tables; @@session.max_tmp_tables 1 @@ -115,7 +115,7 @@ SELECT @@session.max_tmp_tables; 429496729500 SET @@session.max_tmp_tables = -001; Warnings: -Warning 1292 Truncated incorrect max_tmp_tables value: '0' +Warning 1292 Truncated incorrect max_tmp_tables value: '-1' SELECT @@session.max_tmp_tables; @@session.max_tmp_tables 1 diff --git a/mysql-test/suite/sys_vars/r/max_write_lock_count_basic_64.result b/mysql-test/suite/sys_vars/r/max_write_lock_count_basic_64.result index d74586841dd..934777e38d3 100644 --- a/mysql-test/suite/sys_vars/r/max_write_lock_count_basic_64.result +++ b/mysql-test/suite/sys_vars/r/max_write_lock_count_basic_64.result @@ -37,7 +37,7 @@ SELECT @@global.max_write_lock_count; '#------------------FN_DYNVARS_088_04-----------------------#' SET @@global.max_write_lock_count = -1024; Warnings: -Warning 1292 Truncated incorrect max_write_lock_count value: '0' +Warning 1292 Truncated incorrect max_write_lock_count value: '-1024' SELECT @@global.max_write_lock_count; @@global.max_write_lock_count 1 @@ -47,7 +47,7 @@ SELECT @@global.max_write_lock_count; 4294967296 SET @@global.max_write_lock_count = -1; Warnings: -Warning 1292 Truncated incorrect max_write_lock_count value: '0' +Warning 1292 Truncated incorrect max_write_lock_count value: '-1' SELECT @@global.max_write_lock_count; @@global.max_write_lock_count 1 diff --git a/mysql-test/suite/sys_vars/r/min_examined_row_limit_basic_64.result b/mysql-test/suite/sys_vars/r/min_examined_row_limit_basic_64.result index fa11659c6c5..5cf77ed6dc8 100644 --- a/mysql-test/suite/sys_vars/r/min_examined_row_limit_basic_64.result +++ b/mysql-test/suite/sys_vars/r/min_examined_row_limit_basic_64.result @@ -82,6 +82,8 @@ SELECT @@global.min_examined_row_limit; @@global.min_examined_row_limit 429496726 SET @@global.min_examined_row_limit = -1024; +Warnings: +Warning 1292 Truncated incorrect min_examined_row_limit value: '-1024' SELECT @@global.min_examined_row_limit; @@global.min_examined_row_limit 0 @@ -104,6 +106,8 @@ SELECT @@session.min_examined_row_limit; @@session.min_examined_row_limit 4294967296 SET @@session.min_examined_row_limit = -1; +Warnings: +Warning 1292 Truncated incorrect min_examined_row_limit value: '-1' SELECT @@session.min_examined_row_limit; @@session.min_examined_row_limit 0 diff --git a/mysql-test/suite/sys_vars/r/multi_range_count_basic_64.result b/mysql-test/suite/sys_vars/r/multi_range_count_basic_64.result index f2115aec2e2..29019ca5971 100644 --- a/mysql-test/suite/sys_vars/r/multi_range_count_basic_64.result +++ b/mysql-test/suite/sys_vars/r/multi_range_count_basic_64.result @@ -81,7 +81,7 @@ SELECT @@global.multi_range_count; 4294967296 SET @@global.multi_range_count = -1024; Warnings: -Warning 1292 Truncated incorrect multi_range_count value: '0' +Warning 1292 Truncated incorrect multi_range_count value: '-1024' SELECT @@global.multi_range_count; @@global.multi_range_count 1 @@ -111,7 +111,7 @@ SELECT @@session.multi_range_count; 4294967296 SET @@session.multi_range_count = -1; Warnings: -Warning 1292 Truncated incorrect multi_range_count value: '0' +Warning 1292 Truncated incorrect multi_range_count value: '-1' SELECT @@session.multi_range_count; @@session.multi_range_count 1 diff --git a/mysql-test/suite/sys_vars/r/myisam_max_sort_file_size_basic_64.result b/mysql-test/suite/sys_vars/r/myisam_max_sort_file_size_basic_64.result index 00ff1dfc1ab..df2a49e4dd5 100644 --- a/mysql-test/suite/sys_vars/r/myisam_max_sort_file_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/myisam_max_sort_file_size_basic_64.result @@ -1,7 +1,7 @@ SET @start_global_value = @@global.myisam_max_sort_file_size; SELECT @start_global_value; @start_global_value -9223372036854775807 +9223372036853727232 '#--------------------FN_DYNVARS_094_01-------------------------#' SET @@global.myisam_max_sort_file_size = 500000; SET @@global.myisam_max_sort_file_size = DEFAULT; @@ -48,14 +48,20 @@ SET @@local.myisam_max_sort_file_size = 4; ERROR HY000: Variable 'myisam_max_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL '#------------------FN_DYNVARS_094_05-----------------------#' SET @@global.myisam_max_sort_file_size = -1; +Warnings: +Warning 1292 Truncated incorrect myisam_max_sort_file_size value: '-1' SELECT @@global.myisam_max_sort_file_size; @@global.myisam_max_sort_file_size 0 SET @@global.myisam_max_sort_file_size = -2147483648; +Warnings: +Warning 1292 Truncated incorrect myisam_max_sort_file_size value: '-2147483648' SELECT @@global.myisam_max_sort_file_size; @@global.myisam_max_sort_file_size 0 SET @@global.myisam_max_sort_file_size = -2147483649; +Warnings: +Warning 1292 Truncated incorrect myisam_max_sort_file_size value: '-2147483649' SELECT @@global.myisam_max_sort_file_size; @@global.myisam_max_sort_file_size 0 diff --git a/mysql-test/suite/sys_vars/r/myisam_repair_threads_basic_64.result b/mysql-test/suite/sys_vars/r/myisam_repair_threads_basic_64.result index 8271451cc9e..0a317d28b11 100644 --- a/mysql-test/suite/sys_vars/r/myisam_repair_threads_basic_64.result +++ b/mysql-test/suite/sys_vars/r/myisam_repair_threads_basic_64.result @@ -61,7 +61,7 @@ SELECT @@global.myisam_repair_threads ; 1 SET @@global.myisam_repair_threads = -1024; Warnings: -Warning 1292 Truncated incorrect myisam_repair_threads value: '0' +Warning 1292 Truncated incorrect myisam_repair_threads value: '-1024' SELECT @@global.myisam_repair_threads ; @@global.myisam_repair_threads 1 @@ -102,7 +102,7 @@ SELECT @@session.myisam_repair_threads ; 1 SET @@session.myisam_repair_threads = -2; Warnings: -Warning 1292 Truncated incorrect myisam_repair_threads value: '0' +Warning 1292 Truncated incorrect myisam_repair_threads value: '-2' SELECT @@session.myisam_repair_threads ; @@session.myisam_repair_threads 1 diff --git a/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic_64.result b/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic_64.result index bfcada76a46..be9e415d830 100644 --- a/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic_64.result @@ -61,7 +61,7 @@ SELECT @@global.myisam_sort_buffer_size ; 4 SET @@global.myisam_sort_buffer_size = -1024; Warnings: -Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0' +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '-1024' SELECT @@global.myisam_sort_buffer_size ; @@global.myisam_sort_buffer_size 4 @@ -102,7 +102,7 @@ SELECT @@session.myisam_sort_buffer_size ; 4 SET @@session.myisam_sort_buffer_size = -2; Warnings: -Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0' +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '-2' SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size 4 diff --git a/mysql-test/suite/sys_vars/r/net_retry_count_basic_64.result b/mysql-test/suite/sys_vars/r/net_retry_count_basic_64.result index db133d23f79..67dae3d1291 100644 --- a/mysql-test/suite/sys_vars/r/net_retry_count_basic_64.result +++ b/mysql-test/suite/sys_vars/r/net_retry_count_basic_64.result @@ -77,7 +77,7 @@ SELECT @@global.net_retry_count; 1 SET @@global.net_retry_count = -1024; Warnings: -Warning 1292 Truncated incorrect net_retry_count value: '0' +Warning 1292 Truncated incorrect net_retry_count value: '-1024' SELECT @@global.net_retry_count; @@global.net_retry_count 1 @@ -107,7 +107,7 @@ SELECT @@session.net_retry_count; 1 SET @@session.net_retry_count = -2; Warnings: -Warning 1292 Truncated incorrect net_retry_count value: '0' +Warning 1292 Truncated incorrect net_retry_count value: '-2' SELECT @@session.net_retry_count; @@session.net_retry_count 1 diff --git a/mysql-test/suite/sys_vars/r/query_alloc_block_size_basic_64.result b/mysql-test/suite/sys_vars/r/query_alloc_block_size_basic_64.result index 57c96a8168a..7c573bdb7cb 100644 --- a/mysql-test/suite/sys_vars/r/query_alloc_block_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/query_alloc_block_size_basic_64.result @@ -78,7 +78,7 @@ SELECT @@global.query_alloc_block_size; 1024 SET @@global.query_alloc_block_size = -1; Warnings: -Warning 1292 Truncated incorrect query_alloc_block_size value: '0' +Warning 1292 Truncated incorrect query_alloc_block_size value: '-1' SELECT @@global.query_alloc_block_size; @@global.query_alloc_block_size 1024 @@ -110,7 +110,7 @@ SELECT @@session.query_alloc_block_size; 1024 SET @@session.query_alloc_block_size = -2; Warnings: -Warning 1292 Truncated incorrect query_alloc_block_size value: '0' +Warning 1292 Truncated incorrect query_alloc_block_size value: '-2' SELECT @@session.query_alloc_block_size; @@session.query_alloc_block_size 1024 diff --git a/mysql-test/suite/sys_vars/r/query_cache_limit_basic_64.result b/mysql-test/suite/sys_vars/r/query_cache_limit_basic_64.result index a592883ef91..7b3e759deb4 100644 --- a/mysql-test/suite/sys_vars/r/query_cache_limit_basic_64.result +++ b/mysql-test/suite/sys_vars/r/query_cache_limit_basic_64.result @@ -32,6 +32,8 @@ SELECT @@global.query_cache_limit; 1048575 '#--------------------FN_DYNVARS_131_04-------------------------#' SET @@global.query_cache_limit = -1; +Warnings: +Warning 1292 Truncated incorrect query_cache_limit value: '-1' SELECT @@global.query_cache_limit; @@global.query_cache_limit 0 @@ -49,6 +51,8 @@ SELECT @@global.query_cache_limit; @@global.query_cache_limit 10240022115 SET @@global.query_cache_limit = -1024; +Warnings: +Warning 1292 Truncated incorrect query_cache_limit value: '-1024' SELECT @@global.query_cache_limit; @@global.query_cache_limit 0 diff --git a/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic_64.result b/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic_64.result index e1c74d2bbc1..fdbbc71f108 100644 --- a/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic_64.result +++ b/mysql-test/suite/sys_vars/r/query_cache_min_res_unit_basic_64.result @@ -42,6 +42,8 @@ SELECT @@global.query_cache_min_res_unit; 1048576 '#--------------------FN_DYNVARS_132_04-------------------------#' SET @@global.query_cache_min_res_unit = -1; +Warnings: +Warning 1292 Truncated incorrect query_cache_min_res_unit value: '-1' SELECT @@global.query_cache_min_res_unit; @@global.query_cache_min_res_unit 512 @@ -59,6 +61,8 @@ SELECT @@global.query_cache_min_res_unit; @@global.query_cache_min_res_unit 512 SET @@global.query_cache_min_res_unit = -1024; +Warnings: +Warning 1292 Truncated incorrect query_cache_min_res_unit value: '-1024' SELECT @@global.query_cache_min_res_unit; @@global.query_cache_min_res_unit 512 diff --git a/mysql-test/suite/sys_vars/r/query_cache_size_basic_64.result b/mysql-test/suite/sys_vars/r/query_cache_size_basic_64.result index 0cc508b169e..c6d7999677f 100644 --- a/mysql-test/suite/sys_vars/r/query_cache_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/query_cache_size_basic_64.result @@ -41,6 +41,8 @@ SELECT @@global.query_cache_size; 1047552 '#--------------------FN_DYNVARS_133_04-------------------------#' SET @@global.query_cache_size = -1; +Warnings: +Warning 1292 Truncated incorrect query_cache_size value: '-1' SELECT @@global.query_cache_size; @@global.query_cache_size 0 @@ -58,6 +60,8 @@ SELECT @@global.query_cache_size; @@global.query_cache_size 0 SET @@global.query_cache_size = -1024; +Warnings: +Warning 1292 Truncated incorrect query_cache_size value: '-1024' SELECT @@global.query_cache_size; @@global.query_cache_size 0 diff --git a/mysql-test/suite/sys_vars/r/query_prealloc_size_basic_64.result b/mysql-test/suite/sys_vars/r/query_prealloc_size_basic_64.result index 0e61fbcd4b5..a16c56f95c5 100644 --- a/mysql-test/suite/sys_vars/r/query_prealloc_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/query_prealloc_size_basic_64.result @@ -35,10 +35,6 @@ SET @@global.query_prealloc_size = 8192; SELECT @@global.query_prealloc_size ; @@global.query_prealloc_size 8192 -SET @@global.query_prealloc_size = 4294967295; -SELECT @@global.query_prealloc_size ; -@@global.query_prealloc_size -4294966272 SET @@global.query_prealloc_size = 655354; SELECT @@global.query_prealloc_size ; @@global.query_prealloc_size @@ -48,10 +44,6 @@ SET @@session.query_prealloc_size = 8192; SELECT @@session.query_prealloc_size ; @@session.query_prealloc_size 8192 -SET @@session.query_prealloc_size = 4294967295; -SELECT @@session.query_prealloc_size ; -@@session.query_prealloc_size -4294966272 SET @@session.query_prealloc_size = 655345; SELECT @@session.query_prealloc_size ; @@session.query_prealloc_size @@ -63,48 +55,32 @@ Warning 1292 Truncated incorrect query_prealloc_size value: '0' SELECT @@global.query_prealloc_size ; @@global.query_prealloc_size 8192 -SET @@global.query_prealloc_size = -1024; -Warnings: -Warning 1292 Truncated incorrect query_prealloc_size value: '0' -SELECT @@global.query_prealloc_size ; -@@global.query_prealloc_size -8192 -SET @@global.query_prealloc_size = 429496729533; -SELECT @@global.query_prealloc_size ; -@@global.query_prealloc_size -429496728576 SET @@global.query_prealloc_size = 65530.34.; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.' at line 1 SELECT @@global.query_prealloc_size ; @@global.query_prealloc_size -429496728576 +8192 SET @@global.query_prealloc_size = test; ERROR 42000: Incorrect argument type to variable 'query_prealloc_size' SELECT @@global.query_prealloc_size ; @@global.query_prealloc_size -429496728576 +8192 SET @@global.query_prealloc_size = "test"; ERROR 42000: Incorrect argument type to variable 'query_prealloc_size' SELECT @@global.query_prealloc_size ; @@global.query_prealloc_size -429496728576 +8192 SET @@global.query_prealloc_size = 'test'; ERROR 42000: Incorrect argument type to variable 'query_prealloc_size' SELECT @@global.query_prealloc_size ; @@global.query_prealloc_size -429496728576 +8192 SET @@global.query_prealloc_size = ON; ERROR 42000: Incorrect argument type to variable 'query_prealloc_size' SELECT @@global.query_prealloc_size ; @@global.query_prealloc_size -429496728576 -SET @@session.query_prealloc_size = 0; -Warnings: -Warning 1292 Truncated incorrect query_prealloc_size value: '0' -SELECT @@session.query_prealloc_size ; -@@session.query_prealloc_size 8192 -SET @@session.query_prealloc_size = -2; +SET @@session.query_prealloc_size = 0; Warnings: Warning 1292 Truncated incorrect query_prealloc_size value: '0' SELECT @@session.query_prealloc_size ; diff --git a/mysql-test/suite/sys_vars/r/range_alloc_block_size_basic_64.result b/mysql-test/suite/sys_vars/r/range_alloc_block_size_basic_64.result index 26ddfdd2bae..29bf939edac 100644 --- a/mysql-test/suite/sys_vars/r/range_alloc_block_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/range_alloc_block_size_basic_64.result @@ -71,7 +71,7 @@ SELECT @@global.range_alloc_block_size; 4096 SET @@global.range_alloc_block_size = -1024; Warnings: -Warning 1292 Truncated incorrect range_alloc_block_size value: '0' +Warning 1292 Truncated incorrect range_alloc_block_size value: '-1024' SELECT @@global.range_alloc_block_size; @@global.range_alloc_block_size 4096 @@ -97,7 +97,7 @@ SELECT @@session.range_alloc_block_size; 4096 SET @@session.range_alloc_block_size = -2; Warnings: -Warning 1292 Truncated incorrect range_alloc_block_size value: '0' +Warning 1292 Truncated incorrect range_alloc_block_size value: '-2' SELECT @@session.range_alloc_block_size; @@session.range_alloc_block_size 4096 diff --git a/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_64.result b/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_64.result index 74a47fa0f08..9ec34c677e1 100644 --- a/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_64.result +++ b/mysql-test/suite/sys_vars/r/rpl_recovery_rank_basic_64.result @@ -45,14 +45,20 @@ SET @@local.rpl_recovery_rank = 4; ERROR HY000: Variable 'rpl_recovery_rank' is a GLOBAL variable and should be set with SET GLOBAL '#------------------FN_DYNVARS_142_04-----------------------#' SET @@global.rpl_recovery_rank = -1; +Warnings: +Warning 1292 Truncated incorrect rpl_recovery_rank value: '-1' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 SET @@global.rpl_recovery_rank = -2147483648; +Warnings: +Warning 1292 Truncated incorrect rpl_recovery_rank value: '-2147483648' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 SET @@global.rpl_recovery_rank = -2147483649; +Warnings: +Warning 1292 Truncated incorrect rpl_recovery_rank value: '-2147483649' SELECT @@global.rpl_recovery_rank; @@global.rpl_recovery_rank 0 diff --git a/mysql-test/suite/sys_vars/r/slave_transaction_retries_basic_64.result b/mysql-test/suite/sys_vars/r/slave_transaction_retries_basic_64.result index 9434b14b238..6e0bc659f9e 100644 --- a/mysql-test/suite/sys_vars/r/slave_transaction_retries_basic_64.result +++ b/mysql-test/suite/sys_vars/r/slave_transaction_retries_basic_64.result @@ -55,6 +55,8 @@ SET @@local.slave_transaction_retries = 4; ERROR HY000: Variable 'slave_transaction_retries' is a GLOBAL variable and should be set with SET GLOBAL '#------------------FN_DYNVARS_149_05-----------------------#' SET @@global.slave_transaction_retries = -1; +Warnings: +Warning 1292 Truncated incorrect slave_transaction_retries value: '-1' SELECT @@global.slave_transaction_retries; @@global.slave_transaction_retries 0 diff --git a/mysql-test/suite/sys_vars/r/sync_binlog_basic_64.result b/mysql-test/suite/sys_vars/r/sync_binlog_basic_64.result index ffd1b3fc4f1..d3cc4e2a9c2 100644 --- a/mysql-test/suite/sys_vars/r/sync_binlog_basic_64.result +++ b/mysql-test/suite/sys_vars/r/sync_binlog_basic_64.result @@ -36,6 +36,8 @@ SELECT @@global.sync_binlog; 65536 '#--------------------FN_DYNVARS_168_04-------------------------#' SET @@global.sync_binlog = -1; +Warnings: +Warning 1292 Truncated incorrect sync_binlog value: '-1' SELECT @@global.sync_binlog; @@global.sync_binlog 0 @@ -53,6 +55,8 @@ SELECT @@global.sync_binlog; @@global.sync_binlog 10240022115 SET @@global.sync_binlog = -1024; +Warnings: +Warning 1292 Truncated incorrect sync_binlog value: '-1024' SELECT @@global.sync_binlog; @@global.sync_binlog 0 diff --git a/mysql-test/suite/sys_vars/r/transaction_alloc_block_size_basic_64.result b/mysql-test/suite/sys_vars/r/transaction_alloc_block_size_basic_64.result index c968d6f108c..749df56c60b 100644 --- a/mysql-test/suite/sys_vars/r/transaction_alloc_block_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/transaction_alloc_block_size_basic_64.result @@ -67,7 +67,7 @@ SELECT @@global.transaction_alloc_block_size; 1024 SET @@global.transaction_alloc_block_size = -1024; Warnings: -Warning 1292 Truncated incorrect transaction_alloc_block_size value: '0' +Warning 1292 Truncated incorrect transaction_alloc_block_size value: '-1024' SELECT @@global.transaction_alloc_block_size; @@global.transaction_alloc_block_size 1024 diff --git a/mysql-test/suite/sys_vars/r/transaction_prealloc_size_basic_64.result b/mysql-test/suite/sys_vars/r/transaction_prealloc_size_basic_64.result index 2fb6451372f..3455b9479c0 100644 --- a/mysql-test/suite/sys_vars/r/transaction_prealloc_size_basic_64.result +++ b/mysql-test/suite/sys_vars/r/transaction_prealloc_size_basic_64.result @@ -66,7 +66,7 @@ SELECT @@global.transaction_prealloc_size; 1024 SET @@global.transaction_prealloc_size = -1024; Warnings: -Warning 1292 Truncated incorrect transaction_prealloc_size value: '0' +Warning 1292 Truncated incorrect transaction_prealloc_size value: '-1024' SELECT @@global.transaction_prealloc_size; @@global.transaction_prealloc_size 1024 diff --git a/mysql-test/suite/sys_vars/r/wait_timeout_basic_64.result b/mysql-test/suite/sys_vars/r/wait_timeout_basic_64.result index ae03e677e56..c9bffc61b6f 100644 --- a/mysql-test/suite/sys_vars/r/wait_timeout_basic_64.result +++ b/mysql-test/suite/sys_vars/r/wait_timeout_basic_64.result @@ -44,7 +44,7 @@ Warnings: Warning 1292 Truncated incorrect wait_timeout value: '0' SET @@global.wait_timeout = -1024; Warnings: -Warning 1292 Truncated incorrect wait_timeout value: '0' +Warning 1292 Truncated incorrect wait_timeout value: '-1024' 'Bug # 34837: Errors are not coming on assigning invalid values to variable'; SET @@global.wait_timeout = ON; ERROR 42000: Incorrect argument type to variable 'wait_timeout' From 61ce70924c56b2f4b597338344575a8236cf7189 Mon Sep 17 00:00:00 2001 From: Guangbao Ni Date: Fri, 3 Apr 2009 18:21:57 +0000 Subject: [PATCH 07/28] BUG#42640 mysqld crashes when unsafe statements are executed (STRICT_TRANS_TABLESmode) Mysql server crashes because unsafe statements warning is wrongly elevated to error, which is set the error status of Diagnostics_area of the thread in THD::binlog_query(). Yet the caller believes that binary logging shouldn't touch the status, so it will set the status also later by my_ok(), my_error() or my_message() seperately according to the execution result of the statement or transaction. But the status of Diagnostics_area of the thread is allowed to set only once. Fixed to clear the error wrongly set by binary logging, but keep the warning message. --- .../suite/binlog/r/binlog_stm_ps.result | 2 +- .../suite/binlog/r/binlog_unsafe.result | 128 ++++++++++-------- mysql-test/suite/binlog/t/binlog_unsafe.test | 19 +++ mysql-test/suite/rpl/r/rpl_skip_error.result | 2 +- .../suite/rpl/r/rpl_stm_loadfile.result | 4 +- mysql-test/suite/rpl/r/rpl_udf.result | 8 +- sql/sql_class.cc | 6 +- 7 files changed, 105 insertions(+), 64 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_stm_ps.result b/mysql-test/suite/binlog/r/binlog_stm_ps.result index 1cf7429987e..ea7cc6f16df 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_ps.result +++ b/mysql-test/suite/binlog/r/binlog_stm_ps.result @@ -11,7 +11,7 @@ prepare s from "insert into t1 select 100 limit ?"; set @a=100; execute s using @a; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; create table t1 (a int) diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result index a0809c79fa2..675c327e9e7 100644 --- a/mysql-test/suite/binlog/r/binlog_unsafe.result +++ b/mysql-test/suite/binlog/r/binlog_unsafe.result @@ -10,25 +10,25 @@ INSERT DELAYED INTO t1 VALUES (5); ---- Insert directly ---- INSERT INTO t1 VALUES (@@global.sync_binlog); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. INSERT INTO t1 VALUES (@@session.insert_id); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. INSERT INTO t1 VALUES (@@global.auto_increment_increment); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. INSERT INTO t2 SELECT UUID(); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. INSERT INTO t2 VALUES (@@session.sql_mode); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. INSERT INTO t2 VALUES (@@global.init_slave); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. INSERT INTO t2 VALUES (@@hostname); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. ---- Insert from stored procedure ---- CREATE PROCEDURE proc() BEGIN @@ -42,13 +42,13 @@ INSERT INTO t2 VALUES (@@hostname); END| CALL proc(); Warnings: -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. ---- Insert from stored function ---- CREATE FUNCTION func() RETURNS INT @@ -66,13 +66,13 @@ SELECT func(); func() 0 Warnings: -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. ---- Insert from trigger ---- CREATE TRIGGER trig BEFORE INSERT ON trigger_table @@ -88,14 +88,14 @@ INSERT INTO t2 VALUES (@@hostname); END| INSERT INTO trigger_table VALUES ('bye.'); Warnings: -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. ---- Insert from prepared statement ---- PREPARE p1 FROM 'INSERT INTO t1 VALUES (@@global.sync_binlog)'; PREPARE p2 FROM 'INSERT INTO t1 VALUES (@@session.insert_id)'; @@ -106,25 +106,25 @@ PREPARE p6 FROM 'INSERT INTO t2 VALUES (@@global.init_slave)'; PREPARE p7 FROM 'INSERT INTO t2 VALUES (@@hostname)'; EXECUTE p1; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. EXECUTE p2; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. EXECUTE p3; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. EXECUTE p4; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. EXECUTE p5; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. EXECUTE p6; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. EXECUTE p7; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. ---- Insert from nested call of triggers / functions / procedures ---- CREATE PROCEDURE proc1() INSERT INTO trigger_table VALUES ('ha!')| @@ -154,13 +154,13 @@ EXECUTE prep6; func5() 0 Warnings: -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. ==== Variables that should *not* be unsafe ==== INSERT INTO t1 VALUES (@@session.pseudo_thread_id); INSERT INTO t1 VALUES (@@session.pseudo_thread_id); @@ -195,16 +195,16 @@ DROP TABLE t1, t2, t3, trigger_table, trigger_table2; CREATE TABLE t1(a INT, b INT, KEY(a), PRIMARY KEY(b)); INSERT INTO t1 SELECT * FROM t1 LIMIT 1; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. REPLACE INTO t1 SELECT * FROM t1 LIMIT 1; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. UPDATE t1 SET a=1 LIMIT 1; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. DELETE FROM t1 LIMIT 1; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. CREATE PROCEDURE p1() BEGIN INSERT INTO t1 SELECT * FROM t1 LIMIT 1; @@ -214,10 +214,10 @@ DELETE FROM t1 LIMIT 1; END| CALL p1(); Warnings: -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. DROP PROCEDURE p1; DROP TABLE t1; DROP TABLE IF EXISTS t1; @@ -225,7 +225,7 @@ CREATE TABLE t1 (a VARCHAR(100), b VARCHAR(100)); INSERT INTO t1 VALUES ('a','b'); UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. DROP TABLE t1; DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1(i INT PRIMARY KEY); @@ -234,7 +234,7 @@ CREATE TABLE t3(i INT, ch CHAR(50)); "Should issue message Statement is not safe to log in statement format." INSERT INTO t1 SELECT * FROM t2 LIMIT 1; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. CREATE FUNCTION func6() RETURNS INT BEGIN @@ -246,7 +246,7 @@ END| "Should issue message Statement is not safe to log in statement format only once" INSERT INTO t3 VALUES(func6(), UUID()); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. "Check whether SET @@SQL_LOG_BIN = 0/1 doesn't work in substatements" CREATE FUNCTION fun_check_log_bin() RETURNS INT BEGIN @@ -259,7 +259,7 @@ SELECT fun_check_log_bin(); fun_check_log_bin() 100 Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. "SQL_LOG_BIN should be ON still" SHOW VARIABLES LIKE "SQL_LOG_BIN"; Variable_name Value @@ -309,4 +309,22 @@ DROP FUNCTION func7; DROP TRIGGER trig; DROP TABLE t1, t2, t3, trigger_table; set @@SESSION.SQL_LOG_BIN = @save_log_bin; +SET @save_sql_mode = @@SESSION.SQL_MODE; +SET @@SESSION.SQL_MODE = STRICT_ALL_TABLES; +CREATE TABLE t1(i INT PRIMARY KEY); +CREATE TABLE t2(i INT PRIMARY KEY); +INSERT INTO t1 SELECT * FROM t2 LIMIT 1; +Warnings: +Note 1592 Statement is not safe to log in statement format. +INSERT INTO t1 VALUES(@@global.sync_binlog); +Warnings: +Note 1592 Statement is not safe to log in statement format. +UPDATE t1 SET i = 999 LIMIT 1; +Warnings: +Note 1592 Statement is not safe to log in statement format. +DELETE FROM t1 LIMIT 1; +Warnings: +Note 1592 Statement is not safe to log in statement format. +DROP TABLE t1, t2; +SET @@SESSION.SQL_MODE = @save_sql_mode; "End of tests" diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test index 642dc3a46f7..1b0f0a6c30a 100644 --- a/mysql-test/suite/binlog/t/binlog_unsafe.test +++ b/mysql-test/suite/binlog/t/binlog_unsafe.test @@ -46,6 +46,7 @@ # BUG#34732: mysqlbinlog does not print default values for auto_increment variables # BUG#34768: nondeterministic INSERT using LIMIT logged in stmt mode if binlog_format=mixed # BUG#41980, SBL, INSERT .. SELECT .. LIMIT = ERROR, even when @@SQL_LOG_BIN is 0 +# BUG#42640: mysqld crashes when unsafe statements are executed (STRICT_TRANS_TABLES mode) # # ==== Related test cases ==== # @@ -369,4 +370,22 @@ DROP FUNCTION func7; DROP TRIGGER trig; DROP TABLE t1, t2, t3, trigger_table; set @@SESSION.SQL_LOG_BIN = @save_log_bin; + +# +# For BUG#42640: mysqld crashes when unsafe statements are executed (STRICT_TRANS_TABLES mode) +# +SET @save_sql_mode = @@SESSION.SQL_MODE; +SET @@SESSION.SQL_MODE = STRICT_ALL_TABLES; + +CREATE TABLE t1(i INT PRIMARY KEY); +CREATE TABLE t2(i INT PRIMARY KEY); + +INSERT INTO t1 SELECT * FROM t2 LIMIT 1; +INSERT INTO t1 VALUES(@@global.sync_binlog); + +UPDATE t1 SET i = 999 LIMIT 1; +DELETE FROM t1 LIMIT 1; + +DROP TABLE t1, t2; +SET @@SESSION.SQL_MODE = @save_sql_mode; --echo "End of tests" diff --git a/mysql-test/suite/rpl/r/rpl_skip_error.result b/mysql-test/suite/rpl/r/rpl_skip_error.result index b90d8113e8e..205c7785349 100644 --- a/mysql-test/suite/rpl/r/rpl_skip_error.result +++ b/mysql-test/suite/rpl/r/rpl_skip_error.result @@ -76,7 +76,7 @@ create table t1(a int primary key); insert into t1 values (1),(2); delete from t1 where @@server_id=1; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. set sql_mode=strict_trans_tables; insert into t1 values (7), (8), (9); [on slave] diff --git a/mysql-test/suite/rpl/r/rpl_stm_loadfile.result b/mysql-test/suite/rpl/r/rpl_stm_loadfile.result index d18befe6e4c..72f58268d5f 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_loadfile.result +++ b/mysql-test/suite/rpl/r/rpl_stm_loadfile.result @@ -10,7 +10,7 @@ CREATE TABLE test.t1 (a INT, blob_column LONGBLOB, PRIMARY KEY(a)); INSERT INTO test.t1 VALUES(1,'test'); UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=1; Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. create procedure test.p1() begin INSERT INTO test.t1 VALUES(2,'test'); @@ -18,7 +18,7 @@ UPDATE test.t1 SET blob_column=LOAD_FILE('../../std_data/words2.dat') WHERE a=2; end| CALL test.p1(); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. SELECT * FROM test.t1 ORDER BY blob_column; a blob_column 1 abase diff --git a/mysql-test/suite/rpl/r/rpl_udf.result b/mysql-test/suite/rpl/r/rpl_udf.result index 79a82b5fbc7..56df5b30d93 100644 --- a/mysql-test/suite/rpl/r/rpl_udf.result +++ b/mysql-test/suite/rpl/r/rpl_udf.result @@ -182,19 +182,19 @@ CREATE TABLE t1(sum INT, price FLOAT(24)) ENGINE=MyISAM; affected rows: 0 INSERT INTO t1 VALUES(myfunc_int(100), myfunc_double(50.00)); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. affected rows: 1 INSERT INTO t1 VALUES(myfunc_int(10), myfunc_double(5.00)); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. affected rows: 1 INSERT INTO t1 VALUES(myfunc_int(200), myfunc_double(25.00)); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. affected rows: 1 INSERT INTO t1 VALUES(myfunc_int(1), myfunc_double(500.00)); Warnings: -Warning 1592 Statement is not safe to log in statement format. +Note 1592 Statement is not safe to log in statement format. affected rows: 1 SELECT * FROM t1 ORDER BY sum; sum price diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 7f15508caa1..b73822f5a48 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -3676,7 +3676,11 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, if (sql_log_bin_toplevel && lex->is_stmt_unsafe() && variables.binlog_format == BINLOG_FORMAT_STMT) { - push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN, + /* + A warning can be elevated a error when STRICT sql mode. + But we don't want to elevate binlog warning to error here. + */ + push_warning(this, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_BINLOG_UNSAFE_STATEMENT, ER(ER_BINLOG_UNSAFE_STATEMENT)); if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED)) From aebaf079d1611532767dd0c9b183ca73a07b6ac9 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 3 Apr 2009 16:11:54 -0300 Subject: [PATCH 08/28] Bug#43230: SELECT ... FOR UPDATE can hang with FLUSH TABLES WITH READ LOCK indefinitely The problem is that a SELECT .. FOR UPDATE statement might open a table and later wait for a impeding global read lock without noticing whether it is holding a table that is being waited upon the the flush phase of the process that took the global read lock. The same problem also affected the following statements: LOCK TABLES .. WRITE UPDATE .. SET (update and multi-table update) TRUNCATE TABLE .. LOAD DATA .. The solution is to make the above statements wait for a impending global read lock before opening the tables. If there is no impending global read lock, the statement raises a temporary protection against global read locks and progresses smoothly towards completion. Important notice: the patch does not try to address all possible cases, only those which are common and can be fixed unintrusively enough for 5.0. --- mysql-test/r/lock_multi.result | 55 ++++++++++++++ mysql-test/t/lock_multi.test | 128 +++++++++++++++++++++++++++++++++ sql/sql_lex.cc | 1 + sql/sql_lex.h | 16 +++++ sql/sql_parse.cc | 26 ++++++- sql/sql_yacc.yy | 7 +- 6 files changed, 231 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index d1b50a0080c..037b375fe0b 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -133,3 +133,58 @@ ALTER TABLE t1 ADD COLUMN a INT; # 2.2.1. normal mode # 2.2.2. PS mode DROP TABLE t1; +create table t1 (a int); +create table t2 like t1; +# con1 +lock tables t1 write; +# con2 +flush tables with read lock; +# con5 +# global read lock is taken +# con3 +select * from t2 for update; +# waiting for release of read lock +# con4 +# would hang and later cause a deadlock +flush tables t2; +# clean up +unlock tables; +unlock tables; +a +drop table t1,t2; +# +# Lightweight version: +# Ensure that the wait for a GRL is done before opening tables. +# +create table t1 (a int); +create table t2 like t1; +# +# UPDATE +# +# default +flush tables with read lock; +# con1 +update t2 set a = 1; +# default +# statement is waiting for release of read lock +# con2 +flush table t2; +# default +unlock tables; +# con1 +# +# LOCK TABLES .. WRITE +# +# default +flush tables with read lock; +# con1 +lock tables t2 write; +# default +# statement is waiting for release of read lock +# con2 +flush table t2; +# default +unlock tables; +# con1 +unlock tables; +drop table t1,t2; diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 6c3c942b046..fa6af85f29c 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -683,6 +683,134 @@ DROP TABLE t1; --disconnect locker --disconnect writer +# +# Bug#43230: SELECT ... FOR UPDATE can hang with FLUSH TABLES WITH READ LOCK indefinitely +# + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); +connect (con3,localhost,root,,); +connect (con4,localhost,root,,); +connect (con5,localhost,root,,); + +create table t1 (a int); +create table t2 like t1; + +connection con1; +--echo # con1 +lock tables t1 write; +connection con2; +--echo # con2 +send flush tables with read lock; +connection con5; +--echo # con5 +let $show_statement= SHOW PROCESSLIST; +let $field= State; +let $condition= = 'Flushing tables'; +--source include/wait_show_condition.inc +--echo # global read lock is taken +connection con3; +--echo # con3 +send select * from t2 for update; +connection con5; +let $show_statement= SHOW PROCESSLIST; +let $field= State; +let $condition= = 'Waiting for release of readlock'; +--source include/wait_show_condition.inc +--echo # waiting for release of read lock +connection con4; +--echo # con4 +--echo # would hang and later cause a deadlock +flush tables t2; +connection con1; +--echo # clean up +unlock tables; +connection con2; +--reap +unlock tables; +connection con3; +--reap +connection default; +disconnect con5; +disconnect con4; +disconnect con3; +disconnect con2; +disconnect con1; + +drop table t1,t2; + +--echo # +--echo # Lightweight version: +--echo # Ensure that the wait for a GRL is done before opening tables. +--echo # + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); + +create table t1 (a int); +create table t2 like t1; + +--echo # +--echo # UPDATE +--echo # + +connection default; +--echo # default +flush tables with read lock; +connection con1; +--echo # con1 +send update t2 set a = 1; +connection default; +--echo # default +let $show_statement= SHOW PROCESSLIST; +let $field= State; +let $condition= = 'Waiting for release of readlock'; +--source include/wait_show_condition.inc +--echo # statement is waiting for release of read lock +connection con2; +--echo # con2 +flush table t2; +connection default; +--echo # default +unlock tables; +connection con1; +--echo # con1 +--reap + +--echo # +--echo # LOCK TABLES .. WRITE +--echo # + +connection default; +--echo # default +flush tables with read lock; +connection con1; +--echo # con1 +send lock tables t2 write; +connection default; +--echo # default +let $show_statement= SHOW PROCESSLIST; +let $field= State; +let $condition= = 'Waiting for release of readlock'; +--source include/wait_show_condition.inc +--echo # statement is waiting for release of read lock +connection con2; +--echo # con2 +flush table t2; +connection default; +--echo # default +unlock tables; +connection con1; +--echo # con1 +--reap +unlock tables; + +connection default; +disconnect con2; +disconnect con1; + +drop table t1,t2; + # End of 5.0 tests # Wait till all disconnects are completed diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 4c53772bc25..da31106648a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -204,6 +204,7 @@ void lex_start(THD *thd) lex->nest_level=0 ; lex->allow_sum_func= 0; lex->in_sum_func= NULL; + lex->protect_against_global_read_lock= FALSE; DBUG_VOID_RETURN; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 9f020f4adc5..3e762581e04 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1176,6 +1176,22 @@ typedef struct st_lex : public Query_tables_list bool escape_used; + /* + Special case for SELECT .. FOR UPDATE and LOCK TABLES .. WRITE. + + Protect from a impending GRL as otherwise the thread might deadlock + if it starts waiting for the GRL in mysql_lock_tables. + + The protection is needed because there is a race between setting + the global read lock and waiting for all open tables to be closed. + The problem is a circular wait where a thread holding "old" open + tables will wait for the global read lock to be released while the + thread holding the global read lock will wait for all "old" open + tables to be closed -- the flush part of flush tables with read + lock. + */ + bool protect_against_global_read_lock; + st_lex(); virtual ~st_lex() diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ba887486aa1..02030ac2e19 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2800,6 +2800,10 @@ mysql_execute_command(THD *thd) if (res) goto error; + if (!thd->locked_tables && lex->protect_against_global_read_lock && + !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) + goto error; + if (!(res= open_and_lock_tables(thd, all_tables))) { if (lex->describe) @@ -3660,6 +3664,9 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if (update_precheck(thd, all_tables)) break; + if (!thd->locked_tables && + !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) + goto error; DBUG_ASSERT(select_lex->offset_limit == 0); unit->set_limit(select_lex); res= (up_result= mysql_update(thd, all_tables, @@ -3686,6 +3693,15 @@ end_with_restore_list: else res= 0; + /* + Protection might have already been risen if its a fall through + from the SQLCOM_UPDATE case above. + */ + if (!thd->locked_tables && + lex->sql_command == SQLCOM_UPDATE_MULTI && + !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) + goto error; + res= mysql_multi_update_prepare(thd); #ifdef HAVE_REPLICATION @@ -3853,7 +3869,8 @@ end_with_restore_list: ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); goto error; } - + if (!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) + goto error; res= mysql_truncate(thd, first_table, 0); break; case SQLCOM_DELETE: @@ -4027,6 +4044,10 @@ end_with_restore_list: if (check_one_table_access(thd, privilege, all_tables)) goto error; + if (!thd->locked_tables && + !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) + goto error; + res= mysql_load(thd, lex->exchange, first_table, lex->field_list, lex->update_list, lex->value_list, lex->duplicates, lex->ignore, (bool) lex->local_file); @@ -4082,6 +4103,9 @@ end_with_restore_list: goto error; if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, 0)) goto error; + if (lex->protect_against_global_read_lock && + !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) + goto error; thd->in_lock_tables=1; thd->options|= OPTION_TABLE_LOCK; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 51fb5dbdfe4..b36c65854d7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4522,6 +4522,7 @@ select_lock_type: LEX *lex=Lex; lex->current_select->set_lock_for_tables(TL_WRITE); lex->safe_to_cache_query=0; + lex->protect_against_global_read_lock= TRUE; } | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM { @@ -10058,8 +10059,12 @@ table_lock_list: table_lock: table_ident opt_table_alias lock_option { - if (!Select->add_table_to_list(YYTHD, $1, $2, 0, (thr_lock_type) $3)) + thr_lock_type lock_type= (thr_lock_type) $3; + if (!Select->add_table_to_list(YYTHD, $1, $2, 0, lock_type)) MYSQL_YYABORT; + /* If table is to be write locked, protect from a impending GRL. */ + if (lock_type >= TL_WRITE_ALLOW_WRITE) + Lex->protect_against_global_read_lock= TRUE; } ; From 2ee7a7cff1a18b68d895a9aaf29993ea81d5a48e Mon Sep 17 00:00:00 2001 From: Serge Kozlov Date: Sat, 4 Apr 2009 01:33:13 +0400 Subject: [PATCH 09/28] Bug#37716. 1. Test case was rewritten completely. 2. Test covers 3 cases: a) do deadlock on slave, wait retries of transaction, unlock slave before lock timeout; b) do deadlock on slave and wait error 'lock timeout exceed' on slave; c) same as b) but if of max relay log size = 0; 3. Added comments inline. 4. Updated result file. --- mysql-test/extra/rpl_tests/rpl_deadlock.test | 199 +++++++-------- mysql-test/include/wait_for_status_var.inc | 68 ++++++ .../suite/rpl/r/rpl_deadlock_innodb.result | 230 ++++++++++-------- 3 files changed, 290 insertions(+), 207 deletions(-) create mode 100644 mysql-test/include/wait_for_status_var.inc diff --git a/mysql-test/extra/rpl_tests/rpl_deadlock.test b/mysql-test/extra/rpl_tests/rpl_deadlock.test index 62fe9b2223a..1b331cc948b 100644 --- a/mysql-test/extra/rpl_tests/rpl_deadlock.test +++ b/mysql-test/extra/rpl_tests/rpl_deadlock.test @@ -7,125 +7,126 @@ # (Guilhem) have seen the test manage to provoke lock wait timeout # error but not deadlock error; that is ok as code deals with the two # errors in exactly the same way. -# We don't 'show status like 'slave_retried_transactions'' because this -# is not repeatable (depends on sleeps). --- source include/master-slave.inc +--source include/master-slave.inc + +# 0) Prepare tables and data +--echo *** Prepare tables and data *** connection master; eval CREATE TABLE t1 (a INT NOT NULL, KEY(a)) ENGINE=$engine_type; -eval CREATE TABLE t2 (a INT NOT NULL, KEY(a)) ENGINE=$engine_type; -# requiring 'unique' for the timeout part of the test -eval CREATE TABLE t3 (a INT UNIQUE) ENGINE=$engine_type; -eval CREATE TABLE t4 (a INT) ENGINE=$engine_type; -show variables like 'slave_transaction_retries'; +eval CREATE TABLE t2 (a INT) ENGINE=$engine_type; +eval CREATE TABLE t3 (a INT NOT NULL, KEY(a)) ENGINE=$engine_type; sync_slave_with_master; -show create table t1; -show create table t2; -show variables like 'slave_transaction_retries'; -stop slave; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SHOW CREATE TABLE t3; +SHOW VARIABLES LIKE 'slave_transaction_retries'; +--source include/stop_slave.inc + +connection master; +BEGIN; +INSERT INTO t1 VALUES (1); +# We make a long transaction here +INSERT INTO t2 VALUES (2), (2), (2), (2), (2), (2), (2), (2), (2), (2); +INSERT INTO t3 VALUES (3); +COMMIT; +save_master_pos; +# Save BEGIN event into variable +let $master_pos_begin= query_get_value(SHOW BINLOG EVENTS, Pos, 5); +--echo # 1) Test deadlock - -connection master; -begin; -# Let's keep BEGIN and the locked statement in two different relay logs. -insert into t2 values (0); # t2,t1 actors of deadlock in repl-ed ta -#insert into t3 select * from t2 for update; -let $1=10; -disable_query_log; -while ($1) -{ - eval insert into t3 values( $1 ); - dec $1; -} -enable_query_log; -insert into t1 values(1); -commit; -save_master_pos; +# Block slave SQL thread, wait retries of transaction, unlock slave before lock timeout +--echo *** Test deadlock *** connection slave; -begin; -# Let's make our transaction large so that it's repl-ed msta that's victim -let $1=100; -disable_query_log; -while ($1) -{ - eval insert into t4 values( $1 ); - dec $1; -} -enable_query_log; -select * from t1 for update; # t1,t2 on local slave's -start slave; - -# bad option, todo: replicate a non-transactional t_sync with the transaction -# and use wait_until_rows_count macro below ---real_sleep 3 # hope that slave is blocked now -#let $count=11; -#let $table=t_sync; -#--include wait_until_rows_count.inc - -select * from t2 for update /* dl */; # provoke deadlock, repl-ed should be victim -commit; +BEGIN; +SELECT * FROM t1 FOR UPDATE; +# Save variable 'Slave_retried_transactions' before deadlock +let $slave_retried_transactions= query_get_value(SHOW GLOBAL STATUS LIKE 'Slave_retried_transactions', Value, 1); +START SLAVE; +# Wait until SQL thread blocked: variable 'Slave_retried_transactions' will incremented +let $status_var= Slave_retried_transactions; +let $status_var_value= $slave_retried_transactions; +let $status_type= GLOBAL; +let $status_var_comparsion= >; +--source include/wait_for_status_var.inc +SELECT COUNT(*) FROM t2; +COMMIT; sync_with_master; -select * from t1; # check that repl-ed succeeded finally -select * from t2 /* must be 1 */; -# check that no error is reported ---replace_column 1 # 7 # 8 # 9 # 16 # 22 # 23 # 33 # 35 # 36 # ---replace_result $MASTER_MYPORT MASTER_MYPORT ---vertical_results -show slave status; ---horizontal_results + +# Check the data +SELECT * FROM t1; +SELECT * FROM t3; +# Check that no error is reported +--source include/show_slave_status2.inc +--echo # 2) Test lock wait timeout +# Block slave and wait lock timeout error +--echo *** Test lock wait timeout *** -stop slave; -delete from t3; -change master to master_log_pos=548; # the BEGIN log event -begin; -select * from t2 for update; # hold lock -start slave; ---real_sleep 10 # repl-ed should have blocked, and be retrying -select count(*) from t3 /* must be zero */; # replaying begins after rollback -commit; +connection slave; +--source include/stop_slave.inc +DELETE FROM t2; +# Set slave position to the BEGIN log event +--replace_result $master_pos_begin MASTER_POS_BEGIN +eval CHANGE MASTER TO MASTER_LOG_POS=$master_pos_begin; +BEGIN; +# Hold lock +SELECT * FROM t1 FOR UPDATE; +# Wait until slave stopped with error 'Lock wait timeout exceeded' +START SLAVE; +let $slave_sql_errno= 1205; +--source include/wait_for_slave_sql_error.inc +SELECT COUNT(*) FROM t2; +COMMIT; +--source include/start_slave.inc sync_with_master; -select * from t1; # check that repl-ed succeeded finally -select * from t2; -# check that no error is reported ---replace_column 1 # 7 # 8 # 9 # 11 # 16 # 22 # 23 # 33 # ---replace_result $MASTER_MYPORT MASTER_MYPORT ---vertical_results -show slave status; ---horizontal_results +# Check data from tables +SELECT * FROM t1; +SELECT * FROM t3; +# Check that no error is reported +--source include/show_slave_status2.inc +--echo -# Now we repeat 2), but with BEGIN in the same relay log as -# COMMIT (to see if seeking into hot log is ok). -set @my_max_relay_log_size= @@global.max_relay_log_size; -set global max_relay_log_size=0; +# 3) Test lock wait timeout and purged relay log +# Set max_relay_log_size=0, block slave and wait lock timeout error. +# Restart slave and check that no erros appear +--echo *** Test lock wait timeout and purged relay logs *** -# This is really copy-paste of 2) of above -stop slave; -delete from t3; -change master to master_log_pos=548; -begin; -select * from t2 for update; -start slave; ---real_sleep 10 -select count(*) from t3 /* must be zero */; # replaying begins after rollback -commit; +connection slave; +SET @my_max_relay_log_size= @@global.max_relay_log_size; +SET global max_relay_log_size=0; +--source include/stop_slave.inc +DELETE FROM t2; +# Set slave position to the BEGIN log event +eval CHANGE MASTER TO MASTER_LOG_POS=$master_pos_begin; +BEGIN; +# Hold lock +SELECT * FROM t1 FOR UPDATE; +# Wait until slave stopped with error 'Lock wait timeout exceeded' +START SLAVE; +let $slave_sql_errno= 1205; +--source include/wait_for_slave_sql_error.inc +SELECT COUNT(*) FROM t2; +COMMIT; +--source include/start_slave.inc sync_with_master; -select * from t1; -select * from t2; ---replace_column 1 # 7 # 8 # 9 # 11 # 16 # 22 # 23 # 33 # 35 # 36 # ---replace_result $MASTER_MYPORT MASTER_MYPORT ---vertical_results -show slave status; ---horizontal_results +# Check data from tables +SELECT * FROM t1; +SELECT * FROM t3; +# Check that no error is reported +--source include/show_slave_status2.inc +--echo +# Clean up +--echo *** Clean up *** connection master; -drop table t1,t2,t3,t4; +DROP TABLE t1,t2,t3; sync_slave_with_master; -set global max_relay_log_size= @my_max_relay_log_size; +SET global max_relay_log_size= @my_max_relay_log_size; --echo End of 5.1 tests diff --git a/mysql-test/include/wait_for_status_var.inc b/mysql-test/include/wait_for_status_var.inc new file mode 100644 index 00000000000..4c168da7f1a --- /dev/null +++ b/mysql-test/include/wait_for_status_var.inc @@ -0,0 +1,68 @@ +# ==== Purpose ==== +# +# Waits until a variable from SHOW STATUS has returned a specified +# value, or until a timeout is reached. +# +# ==== Usage ==== +# +# let $status_var= Threads_connected; +# let $status_var_value= 1; +# --source include/wait_for_status_var.inc +# +# Parameters: +# +# $status_var, $status_var_value +# This macro will wait until the variable of SHOW STATUS +# named $status_var gets the value $status_var_value. See +# the example above. +# +# $status_type= GLOBAL|SESSION +# To specify the type (attribute) of status variable and +# run either SHOW GLOBAL STATUS or SHOW SESSION STATUS. +# +# $status_var_comparsion +# By default, this file waits until $status_var becomes equal to +# $status_var_value. If you want to wait until $status_var +# becomes *unequal* to $status_var_value, set this parameter to the +# string '!=', like this: +# let $status_var_comparsion= !=; +# +# $status_timeout +# The default timeout is 1 minute. You can change the timeout by +# setting $status_timeout. The unit is tenths of seconds. +# + +if (`SELECT STRCMP('$status_type', '') * STRCMP(UPPER('$status_type'), 'SESSION') * STRCMP(UPPER('$status_type'), 'GLOBAL')`) +{ + --echo **** ERROR: Unknown type of variable status_type: allowed values are: SESSION or GLOBAL **** + exit; +} + +let $_status_timeout_counter= $status_timeout; +if (!$_status_timeout_counter) +{ + let $_status_timeout_counter= 600; +} + +let $_status_var_comparsion= $status_var_comparsion; +if (`SELECT '$_status_var_comparsion' = ''`) +{ + let $_status_var_comparsion= =; +} + +let $_show_status_value= query_get_value("SHOW $status_type STATUS LIKE '$status_var'", Value, 1); +while (`SELECT NOT('$_show_status_value' $_status_var_comparsion '$status_var_value')`) +{ + if (!$_status_timeout_counter) + { + --echo **** ERROR: failed while waiting for $status_type $status_var $_status_var_comparison $status_var_value **** + --echo Note: the following output may have changed since the failure was detected + --echo **** Showing STATUS, PROCESSLIST **** + eval SHOW $status_type STATUS LIKE '$status_var'; + SHOW PROCESSLIST; + exit; + } + dec $_status_timeout_counter; + sleep 0.1; + let $_show_status_value= query_get_value("SHOW $status_type STATUS LIKE '$status_var'", Value, 1); +} diff --git a/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result b/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result index 1753fc0cb2d..6c8d35619e5 100644 --- a/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result +++ b/mysql-test/suite/rpl/r/rpl_deadlock_innodb.result @@ -4,51 +4,57 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +*** Prepare tables and data *** CREATE TABLE t1 (a INT NOT NULL, KEY(a)) ENGINE=innodb; -CREATE TABLE t2 (a INT NOT NULL, KEY(a)) ENGINE=innodb; -CREATE TABLE t3 (a INT UNIQUE) ENGINE=innodb; -CREATE TABLE t4 (a INT) ENGINE=innodb; -show variables like 'slave_transaction_retries'; -Variable_name Value -slave_transaction_retries 10 -show create table t1; +CREATE TABLE t2 (a INT) ENGINE=innodb; +CREATE TABLE t3 (a INT NOT NULL, KEY(a)) ENGINE=innodb; +SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, KEY `a` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 -show create table t2; +SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( `a` int(11) NOT NULL, KEY `a` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 -show variables like 'slave_transaction_retries'; +SHOW VARIABLES LIKE 'slave_transaction_retries'; Variable_name Value slave_transaction_retries 2 -stop slave; -begin; -insert into t2 values (0); -insert into t1 values(1); -commit; -begin; -select * from t1 for update; +include/stop_slave.inc +BEGIN; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (2), (2), (2), (2), (2), (2), (2), (2), (2), (2); +INSERT INTO t3 VALUES (3); +COMMIT; + +*** Test deadlock *** +BEGIN; +SELECT * FROM t1 FOR UPDATE; a -start slave; -select * from t2 for update /* dl */; -a -commit; -select * from t1; +START SLAVE; +SELECT COUNT(*) FROM t2; +COUNT(*) +0 +COMMIT; +SELECT * FROM t1; a 1 -select * from t2 /* must be 1 */; +SELECT * FROM t3; a -0 -show slave status; +3 +SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port MASTER_MYPORT +Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 Read_Master_Log_Pos # @@ -83,102 +89,41 @@ Last_IO_Errno # Last_IO_Error # Last_SQL_Errno 0 Last_SQL_Error -stop slave; -delete from t3; -change master to master_log_pos=548; -begin; -select * from t2 for update; + +*** Test lock wait timeout *** +include/stop_slave.inc +DELETE FROM t2; +CHANGE MASTER TO MASTER_LOG_POS=MASTER_POS_BEGIN; +BEGIN; +SELECT * FROM t1 FOR UPDATE; a +1 +START SLAVE; +SELECT COUNT(*) FROM t2; +COUNT(*) 0 -start slave; -select count(*) from t3 /* must be zero */; -count(*) -0 -commit; -select * from t1; +COMMIT; +include/start_slave.inc +SELECT * FROM t1; a 1 1 -select * from t2; +SELECT * FROM t3; a -0 -0 -show slave status; +3 +3 +SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port MASTER_MYPORT +Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 -Slave_IO_Running # -Slave_SQL_Running Yes -Replicate_Do_DB -Replicate_Ignore_DB -Replicate_Do_Table -Replicate_Ignore_Table # -Replicate_Wild_Do_Table -Replicate_Wild_Ignore_Table -Last_Errno 0 -Last_Error -Skip_Counter 0 -Exec_Master_Log_Pos # -Relay_Log_Space # -Until_Condition None -Until_Log_File -Until_Log_Pos 0 -Master_SSL_Allowed No -Master_SSL_CA_File -Master_SSL_CA_Path -Master_SSL_Cert -Master_SSL_Cipher -Master_SSL_Key -Seconds_Behind_Master # -Master_SSL_Verify_Server_Cert No -Last_IO_Errno 0 -Last_IO_Error -Last_SQL_Errno 0 -Last_SQL_Error -set @my_max_relay_log_size= @@global.max_relay_log_size; -set global max_relay_log_size=0; -stop slave; -delete from t3; -change master to master_log_pos=548; -begin; -select * from t2 for update; -a -0 -0 -start slave; -select count(*) from t3 /* must be zero */; -count(*) -0 -commit; -select * from t1; -a -1 -1 -1 -select * from t2; -a -0 -0 -0 -show slave status; -Slave_IO_State # -Master_Host 127.0.0.1 -Master_User root -Master_Port MASTER_MYPORT -Connect_Retry 1 -Master_Log_File master-bin.000001 -Read_Master_Log_Pos # -Relay_Log_File # -Relay_Log_Pos # -Relay_Master_Log_File master-bin.000001 -Slave_IO_Running # +Slave_IO_Running Yes Slave_SQL_Running Yes Replicate_Do_DB Replicate_Ignore_DB @@ -206,6 +151,75 @@ Last_IO_Errno # Last_IO_Error # Last_SQL_Errno 0 Last_SQL_Error -drop table t1,t2,t3,t4; -set global max_relay_log_size= @my_max_relay_log_size; + +*** Test lock wait timeout and purged relay logs *** +SET @my_max_relay_log_size= @@global.max_relay_log_size; +SET global max_relay_log_size=0; +include/stop_slave.inc +DELETE FROM t2; +CHANGE MASTER TO MASTER_LOG_POS=440; +BEGIN; +SELECT * FROM t1 FOR UPDATE; +a +1 +1 +START SLAVE; +SELECT COUNT(*) FROM t2; +COUNT(*) +0 +COMMIT; +include/start_slave.inc +SELECT * FROM t1; +a +1 +1 +1 +SELECT * FROM t3; +a +3 +3 +3 +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table # +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +Master_SSL_Verify_Server_Cert No +Last_IO_Errno # +Last_IO_Error # +Last_SQL_Errno 0 +Last_SQL_Error + +*** Clean up *** +DROP TABLE t1,t2,t3; +SET global max_relay_log_size= @my_max_relay_log_size; End of 5.1 tests From 1287d8c53a71c583508802a0fb98e92983fea9ed Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Sun, 5 Apr 2009 13:03:04 +0100 Subject: [PATCH 10/28] BUG#39393 slave-skip-errors does not work when using ROW based replication RBR was not considering the option --slave-skip-errors. To fix the problem, we are reporting the ignored ERROR(s) as warnings thus avoiding stopping the SQL Thread. Besides, it fixes the output of "SHOW VARIABLES LIKE 'slave_skip_errors'" which was showing nothing when the value "all" was assigned to --slave-skip-errors. @sql/log_event.cc skipped rbr errors when the option skip-slave-errors is set. @sql/slave.cc fixed the output of for SHOW VARIABLES LIKE 'slave_skip_errors'" @test-cases fixed the output of rpl.rpl_idempotency updated the test case rpl_skip_error --- mysql-test/suite/rpl/r/rpl_idempotency.result | 20 +-- mysql-test/suite/rpl/r/rpl_skip_error.result | 92 +++++++++- mysql-test/suite/rpl/t/rpl_idempotency.test | 16 +- mysql-test/suite/rpl/t/rpl_skip_error.test | 115 +++++++++++- sql/log_event.cc | 165 +++++++++++------- sql/slave.cc | 1 + 6 files changed, 315 insertions(+), 94 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_idempotency.result b/mysql-test/suite/rpl/r/rpl_idempotency.result index f39d0f1f37f..3341c03db0f 100644 --- a/mysql-test/suite/rpl/r/rpl_idempotency.result +++ b/mysql-test/suite/rpl/r/rpl_idempotency.result @@ -141,9 +141,9 @@ select * from ti1 order by b /* must be (2),(3) */; b 2 3 -*** slave must stop +*** slave must stop (Trying to delete a referenced foreing key) Last_SQL_Error -0 +1451 select * from ti1 order by b /* must be (1),(2),(3) - not deleted */; b 1 @@ -159,7 +159,7 @@ set global slave_exec_mode='STRICT'; *** conspire future problem delete from ti1 where b=3; insert into ti2 set a=3, b=3 /* offending write event */; -*** slave must stop +*** slave must stop (Trying to insert an invalid foreign key) Last_SQL_Error 1452 select * from ti2 order by b /* must be (2,2) */; @@ -179,7 +179,7 @@ a b *** conspiring query insert into ti1 set b=1; insert into ti1 set b=1 /* offending write event */; -*** slave must stop +*** slave must stop (Trying to insert a dupliacte key) Last_SQL_Error 1062 set foreign_key_checks= 0; @@ -195,32 +195,32 @@ INSERT INTO t2 VALUES (-1),(-2),(-3); DELETE FROM t1 WHERE a = -2; DELETE FROM t2 WHERE a = -2; DELETE FROM t1 WHERE a = -2; -*** slave must stop +*** slave must stop (Key was not found) Last_SQL_Error 1032 set global slave_exec_mode='IDEMPOTENT'; start slave sql_thread; set global slave_exec_mode='STRICT'; DELETE FROM t2 WHERE a = -2; -*** slave must stop +*** slave must stop (Key was not found) Last_SQL_Error -0 +1032 set global slave_exec_mode='IDEMPOTENT'; start slave sql_thread; set global slave_exec_mode='STRICT'; UPDATE t1 SET a = 1 WHERE a = -1; UPDATE t2 SET a = 1 WHERE a = -1; UPDATE t1 SET a = 1 WHERE a = -1; -*** slave must stop +*** slave must stop (Key was not found) Last_SQL_Error 1032 set global slave_exec_mode='IDEMPOTENT'; start slave sql_thread; set global slave_exec_mode='STRICT'; UPDATE t2 SET a = 1 WHERE a = -1; -*** slave must stop +*** slave must stop (Key was not found) Last_SQL_Error -0 +1032 set global slave_exec_mode='IDEMPOTENT'; start slave sql_thread; SET @@global.slave_exec_mode= @old_slave_exec_mode; diff --git a/mysql-test/suite/rpl/r/rpl_skip_error.result b/mysql-test/suite/rpl/r/rpl_skip_error.result index b90d8113e8e..dc02bb783ae 100644 --- a/mysql-test/suite/rpl/r/rpl_skip_error.result +++ b/mysql-test/suite/rpl/r/rpl_skip_error.result @@ -74,19 +74,16 @@ Last_SQL_Error drop table t1; create table t1(a int primary key); insert into t1 values (1),(2); -delete from t1 where @@server_id=1; -Warnings: -Warning 1592 Statement is not safe to log in statement format. +SET SQL_LOG_BIN=0; +delete from t1; +SET SQL_LOG_BIN=1; set sql_mode=strict_trans_tables; -insert into t1 values (7), (8), (9); +insert into t1 values (1), (2), (3); [on slave] select * from t1; a 1 2 -7 -8 -9 SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 @@ -128,3 +125,84 @@ Last_SQL_Errno 0 Last_SQL_Error ==== Clean Up ==== drop table t1; +==== Using Innodb ==== +SET SQL_LOG_BIN=0; +CREATE TABLE t1(id INT NOT NULL PRIMARY KEY, data INT) Engine=InnoDB; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL, + `data` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET SQL_LOG_BIN=1; +CREATE TABLE t1(id INT NOT NULL PRIMARY KEY, data INT) Engine=InnoDB; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL, + `data` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES(1, 1); +INSERT INTO t1 VALUES(2, 1); +INSERT INTO t1 VALUES(3, 1); +INSERT INTO t1 VALUES(4, 1); +SET SQL_LOG_BIN=0; +DELETE FROM t1 WHERE id = 4; +SET SQL_LOG_BIN=1; +UPDATE t1 SET id= id + 3, data = 2; + +SELECT *, "INNODB SET SLAVE DATA" FROM t1 ORDER BY id; +id data INNODB SET SLAVE DATA +1 1 INNODB SET SLAVE DATA +2 1 INNODB SET SLAVE DATA +3 1 INNODB SET SLAVE DATA +4 1 INNODB SET SLAVE DATA +SELECT *, "INNODB SET MASTER DATA" FROM t1 ORDER BY id; +id data INNODB SET MASTER DATA +4 2 INNODB SET MASTER DATA +5 2 INNODB SET MASTER DATA +6 2 INNODB SET MASTER DATA +==== Using MyIsam ==== +SET SQL_LOG_BIN=0; +CREATE TABLE t2(id INT NOT NULL PRIMARY KEY, data INT) Engine=MyIsam; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `id` int(11) NOT NULL, + `data` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SET SQL_LOG_BIN=1; +CREATE TABLE t2(id INT NOT NULL PRIMARY KEY, data INT) Engine=MyIsam; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `id` int(11) NOT NULL, + `data` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t2 VALUES(1, 1); +INSERT INTO t2 VALUES(2, 1); +INSERT INTO t2 VALUES(3, 1); +INSERT INTO t2 VALUES(5, 1); +SET SQL_LOG_BIN=0; +DELETE FROM t2 WHERE id = 5; +SET SQL_LOG_BIN=1; +UPDATE t2 SET id= id + 3, data = 2; + +SELECT *, "MYISAM SET SLAVE DATA" FROM t2 ORDER BY id; +id data MYISAM SET SLAVE DATA +2 1 MYISAM SET SLAVE DATA +3 1 MYISAM SET SLAVE DATA +4 2 MYISAM SET SLAVE DATA +5 1 MYISAM SET SLAVE DATA +SELECT *, "MYISAM SET MASTER DATA" FROM t2 ORDER BY id; +id data MYISAM SET MASTER DATA +4 2 MYISAM SET MASTER DATA +5 2 MYISAM SET MASTER DATA +6 2 MYISAM SET MASTER DATA +==== Clean Up ==== +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/rpl/t/rpl_idempotency.test b/mysql-test/suite/rpl/t/rpl_idempotency.test index 1946aa100ab..bfd1860759e 100644 --- a/mysql-test/suite/rpl/t/rpl_idempotency.test +++ b/mysql-test/suite/rpl/t/rpl_idempotency.test @@ -208,7 +208,7 @@ select * from ti1 order by b /* must be (2),(3) */; # foreign key: row is referenced ---echo *** slave must stop +--echo *** slave must stop (Trying to delete a referenced foreing key) connection slave; source include/wait_for_slave_sql_to_stop.inc; @@ -242,7 +242,7 @@ delete from ti1 where b=3; connection master; insert into ti2 set a=3, b=3 /* offending write event */; ---echo *** slave must stop +--echo *** slave must stop (Trying to insert an invalid foreign key) connection slave; source include/wait_for_slave_sql_to_stop.inc; @@ -281,7 +281,7 @@ insert into ti1 set b=1; connection master; insert into ti1 set b=1 /* offending write event */; ---echo *** slave must stop +--echo *** slave must stop (Trying to insert a dupliacte key) connection slave; source include/wait_for_slave_sql_to_stop.inc; @@ -316,7 +316,7 @@ DELETE FROM t2 WHERE a = -2; connection master; DELETE FROM t1 WHERE a = -2; ---echo *** slave must stop +--echo *** slave must stop (Key was not found) connection slave; source include/wait_for_slave_sql_to_stop.inc; @@ -333,8 +333,8 @@ sync_slave_with_master; set global slave_exec_mode='STRICT'; connection master; -DELETE FROM t2 WHERE a = -2; ---echo *** slave must stop +DELETE FROM t2 WHERE a = -2; +--echo *** slave must stop (Key was not found) connection slave; source include/wait_for_slave_sql_to_stop.inc; @@ -356,7 +356,7 @@ UPDATE t2 SET a = 1 WHERE a = -1; connection master; UPDATE t1 SET a = 1 WHERE a = -1; ---echo *** slave must stop +--echo *** slave must stop (Key was not found) connection slave; source include/wait_for_slave_sql_to_stop.inc; @@ -376,7 +376,7 @@ set global slave_exec_mode='STRICT'; connection master; UPDATE t2 SET a = 1 WHERE a = -1; ---echo *** slave must stop +--echo *** slave must stop (Key was not found) connection slave; source include/wait_for_slave_sql_to_stop.inc; diff --git a/mysql-test/suite/rpl/t/rpl_skip_error.test b/mysql-test/suite/rpl/t/rpl_skip_error.test index cac797d3797..c15d24be9e5 100644 --- a/mysql-test/suite/rpl/t/rpl_skip_error.test +++ b/mysql-test/suite/rpl/t/rpl_skip_error.test @@ -8,18 +8,23 @@ # ==== Method ==== # # We run the slave with --slave-skip-errors=1062 (the code for -# duplicate key). On slave, we insert value 1 in a table, and then, -# on master, we insert value 1 in the table. The error should be -# ignored on slave. -# +# duplicate key). Then we have two set of tests. In the first +# set, we insert value 1 in a table on the slave, and then, on +# master, we insert value 1 in the table. In the second set, we +# insert several values on the master, disable the binlog and +# delete one of the values and re-enable the binlog. Right after, +# we perform an update on the set of values in order to generate +# a duplicate key on the slave. The errors should be ignored on +# the slave. +# # ==== Related bugs ==== # # BUG#28839: Errors in strict mode silently stop SQL thread if --slave-skip-errors exists -# bug in this test: BUG#30594: rpl.rpl_skip_error is nondeterministic +# bug in this test: BUG#30594: rpl.rpl_skip_error is nondeterministic: +# BUG#39393: slave-skip-errors does not work when using ROW based replication source include/master-slave.inc; -source include/have_binlog_format_statement.inc; - +source include/have_innodb.inc; --echo ==== Test Without sql_mode=strict_trans_tables ==== @@ -64,9 +69,11 @@ sync_slave_with_master; connection master; create table t1(a int primary key); insert into t1 values (1),(2); -delete from t1 where @@server_id=1; +SET SQL_LOG_BIN=0; +delete from t1; +SET SQL_LOG_BIN=1; set sql_mode=strict_trans_tables; -insert into t1 values (7), (8), (9); +insert into t1 values (1), (2), (3); --echo [on slave] sync_slave_with_master; @@ -80,3 +87,93 @@ connection master; drop table t1; sync_slave_with_master; # End of 5.0 tests + +# +# BUG#39393: slave-skip-errors does not work when using ROW based replication +# +--echo ==== Using Innodb ==== + +connection master; + +SET SQL_LOG_BIN=0; +CREATE TABLE t1(id INT NOT NULL PRIMARY KEY, data INT) Engine=InnoDB; +SHOW CREATE TABLE t1; +SET SQL_LOG_BIN=1; + +connection slave; + +CREATE TABLE t1(id INT NOT NULL PRIMARY KEY, data INT) Engine=InnoDB; +SHOW CREATE TABLE t1; + +connection master; + +INSERT INTO t1 VALUES(1, 1); +INSERT INTO t1 VALUES(2, 1); +INSERT INTO t1 VALUES(3, 1); +INSERT INTO t1 VALUES(4, 1); + +SET SQL_LOG_BIN=0; +DELETE FROM t1 WHERE id = 4; +SET SQL_LOG_BIN=1; +UPDATE t1 SET id= id + 3, data = 2; + +sync_slave_with_master; + +let $error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1); +echo $error; + +connection slave; + +SELECT *, "INNODB SET SLAVE DATA" FROM t1 ORDER BY id; + +connection master; + +SELECT *, "INNODB SET MASTER DATA" FROM t1 ORDER BY id; + +--echo ==== Using MyIsam ==== + +connection master; + +SET SQL_LOG_BIN=0; +CREATE TABLE t2(id INT NOT NULL PRIMARY KEY, data INT) Engine=MyIsam; +SHOW CREATE TABLE t2; +SET SQL_LOG_BIN=1; + +connection slave; + +CREATE TABLE t2(id INT NOT NULL PRIMARY KEY, data INT) Engine=MyIsam; +SHOW CREATE TABLE t2; + +connection master; + +INSERT INTO t2 VALUES(1, 1); +INSERT INTO t2 VALUES(2, 1); +INSERT INTO t2 VALUES(3, 1); +INSERT INTO t2 VALUES(5, 1); + +SET SQL_LOG_BIN=0; +DELETE FROM t2 WHERE id = 5; +SET SQL_LOG_BIN=1; +UPDATE t2 SET id= id + 3, data = 2; + +sync_slave_with_master; + +let $error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1); +echo $error; + +connection slave; + +SELECT *, "MYISAM SET SLAVE DATA" FROM t2 ORDER BY id; + +connection master; + +SELECT *, "MYISAM SET MASTER DATA" FROM t2 ORDER BY id; + +--echo ==== Clean Up ==== + +connection master; + +DROP TABLE t1; +DROP TABLE t2; + +sync_slave_with_master; diff --git a/sql/log_event.cc b/sql/log_event.cc index aa7e8c84a0f..423174f77d5 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -277,6 +277,47 @@ static void clear_all_errors(THD *thd, Relay_log_info *rli) rli->clear_error(); } +inline int idempotent_error_code(int err_code) +{ + int ret= 0; + + switch (err_code) + { + case 0: + ret= 1; + break; + /* + The following list of "idempotent" errors + means that an error from the list might happen + because of idempotent (more than once) + applying of a binlog file. + Notice, that binlog has a ddl operation its + second applying may cause + + case HA_ERR_TABLE_DEF_CHANGED: + case HA_ERR_CANNOT_ADD_FOREIGN: + + which are not included into to the list. + + Note that HA_ERR_RECORD_DELETED is not in the list since + do_exec_row() should not return that error code. + */ + case HA_ERR_RECORD_CHANGED: + case HA_ERR_KEY_NOT_FOUND: + case HA_ERR_END_OF_FILE: + case HA_ERR_FOUND_DUPP_KEY: + case HA_ERR_FOUND_DUPP_UNIQUE: + case HA_ERR_FOREIGN_DUPLICATE_KEY: + case HA_ERR_NO_REFERENCED_ROW: + case HA_ERR_ROW_IS_REFERENCED: + ret= 1; + break; + default: + ret= 0; + break; + } + return (ret); +} /** Ignore error code specified on command line. @@ -301,14 +342,37 @@ inline int ignored_error_code(int err_code) return ((err_code == ER_SLAVE_IGNORED_TABLE) || (use_slave_mask && bitmap_is_set(&slave_error_mask, err_code))); } -#endif +/* + This function converts an engine's error to a server error. + + If the thread does not have an error already reported, it tries to + define it by calling the engine's method print_error. However, if a + mapping is not found, it uses the ER_UNKNOWN_ERROR and prints out a + warning message. +*/ +int convert_handler_error(int error, THD* thd, TABLE *table) +{ + uint actual_error= (thd->is_error() ? thd->main_da.sql_errno() : + 0); + + if (actual_error == 0) + { + table->file->print_error(error, MYF(0)); + actual_error= (thd->is_error() ? thd->main_da.sql_errno() : + ER_UNKNOWN_ERROR); + if (actual_error == ER_UNKNOWN_ERROR) + if (global_system_variables.log_warnings) + sql_print_warning("Unknown error detected %d in handler", error); + } + + return (actual_error); +} /* pretty_print_str() */ -#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) static char *pretty_print_str(char *packet, const char *str, int len) { const char *end= str + len; @@ -7158,7 +7222,9 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) { /* Error reporting borrowed from Query_log_event with many excessive - simplifications (we don't honour --slave-skip-errors) + simplifications. + We should not honour --slave-skip-errors at this point as we are + having severe errors which should not be skiped. */ rli->report(ERROR_LEVEL, actual_error, "Error '%s' on opening tables", @@ -7184,6 +7250,10 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) { if (ptr->m_tabledef.compatible_with(rli, ptr->table)) { + /* + We should not honour --slave-skip-errors at this point as we are + having severe errors which should not be skiped. + */ mysql_unlock_tables(thd, thd->lock); thd->lock= 0; thd->is_slave_error= 1; @@ -7275,7 +7345,6 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) // Do event specific preparations error= do_before_row_operations(rli); - // row processing loop while (error == 0 && m_curr_row < m_rows_end) @@ -7291,48 +7360,27 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) DBUG_ASSERT(error != HA_ERR_RECORD_DELETED); table->in_use = old_thd; - switch (error) + + if (error) { - case 0: - break; - /* - The following list of "idempotent" errors - means that an error from the list might happen - because of idempotent (more than once) - applying of a binlog file. - Notice, that binlog has a ddl operation its - second applying may cause + int actual_error= convert_handler_error(error, thd, table); + bool idempotent_error= (idempotent_error_code(error) && + ((bit_is_set(slave_exec_mode, + SLAVE_EXEC_MODE_IDEMPOTENT)) == 1)); + bool ignored_error= (idempotent_error == 0 ? + ignored_error_code(actual_error) : 0); - case HA_ERR_TABLE_DEF_CHANGED: - case HA_ERR_CANNOT_ADD_FOREIGN: - - which are not included into to the list. - - Note that HA_ERR_RECORD_DELETED is not in the list since - do_exec_row() should not return that error code. - */ - case HA_ERR_RECORD_CHANGED: - case HA_ERR_KEY_NOT_FOUND: - case HA_ERR_END_OF_FILE: - case HA_ERR_FOUND_DUPP_KEY: - case HA_ERR_FOUND_DUPP_UNIQUE: - case HA_ERR_FOREIGN_DUPLICATE_KEY: - case HA_ERR_NO_REFERENCED_ROW: - case HA_ERR_ROW_IS_REFERENCED: - - if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1) + if (idempotent_error || ignored_error) { if (global_system_variables.log_warnings) slave_rows_error_report(WARNING_LEVEL, error, rli, thd, table, get_type_str(), RPL_LOG_NAME, (ulong) log_pos); + clear_all_errors(thd, const_cast(rli)); error= 0; + if (idempotent_error == 0) + break; } - break; - - default: - thd->is_slave_error= 1; - break; } /* @@ -7346,7 +7394,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) (ulong) m_curr_row, (ulong) m_curr_row_end, (ulong) m_rows_end)); if (!m_curr_row_end && !error) - unpack_current_row(rli); + error= unpack_current_row(rli); // at this moment m_curr_row_end should be set DBUG_ASSERT(error || m_curr_row_end != NULL); @@ -7359,7 +7407,19 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) DBUG_EXECUTE_IF("STOP_SLAVE_after_first_Rows_event", const_cast(rli)->abort_slave= 1;); - error= do_after_row_operations(rli, error); + + if ((error= do_after_row_operations(rli, error)) && + ignored_error_code(convert_handler_error(error, thd, table))) + { + + if (global_system_variables.log_warnings) + slave_rows_error_report(WARNING_LEVEL, error, rli, thd, table, + get_type_str(), + RPL_LOG_NAME, (ulong) log_pos); + clear_all_errors(thd, const_cast(rli)); + error= 0; + } + if (!cache_stmt) { DBUG_PRINT("info", ("Marked that we need to keep log")); @@ -7374,37 +7434,22 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) if (rli->tables_to_lock && get_flags(STMT_END_F)) const_cast(rli)->clear_tables_to_lock(); - if (error) - { /* error has occured during the transaction */ - slave_rows_error_report(ERROR_LEVEL, error, rli, thd, table, - get_type_str(), RPL_LOG_NAME, (ulong) log_pos); - } if (error) { - /* - If one day we honour --skip-slave-errors in row-based replication, and - the error should be skipped, then we would clear mappings, rollback, - close tables, but the slave SQL thread would not stop and then may - assume the mapping is still available, the tables are still open... - So then we should clear mappings/rollback/close here only if this is a - STMT_END_F. - For now we code, knowing that error is not skippable and so slave SQL - thread is certainly going to stop. - rollback at the caller along with sbr. - */ + slave_rows_error_report(ERROR_LEVEL, error, rli, thd, table, + get_type_str(), + RPL_LOG_NAME, (ulong) log_pos); thd->reset_current_stmt_binlog_row_based(); const_cast(rli)->cleanup_context(thd, error); thd->is_slave_error= 1; - DBUG_RETURN(error); } - /* This code would ideally be placed in do_update_pos() instead, but since we have no access to table there, we do the setting of last_event_start_time here instead. */ - if (table && (table->s->primary_key == MAX_KEY) && - !cache_stmt && get_flags(STMT_END_F) == RLE_NO_FLAGS) + else if (table && (table->s->primary_key == MAX_KEY) && + !cache_stmt && get_flags(STMT_END_F) == RLE_NO_FLAGS) { /* ------------ Temporary fix until WL#2975 is implemented --------- @@ -7425,7 +7470,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) const_cast(rli)->last_event_start_time= my_time(0); } - DBUG_RETURN(0); + DBUG_RETURN(error); } Log_event::enum_skip_reason diff --git a/sql/slave.cc b/sql/slave.cc index 8c29cb8a72f..fed53cf605e 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -361,6 +361,7 @@ void init_slave_skip_errors(const char* arg) if (!my_strnncoll(system_charset_info,(uchar*)arg,4,(const uchar*)"all",4)) { bitmap_set_all(&slave_error_mask); + print_slave_skip_errors(); DBUG_VOID_RETURN; } for (p= arg ; *p; ) From 83a78142641e243b39dba198e06de749f0d2db09 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 7 Apr 2009 11:48:38 +0500 Subject: [PATCH 11/28] Bug#42649 THR_LOCK_charset global mutex abused by InnoDB The patch was originally proposed by Mikael and reviewed by Bar. --- mysys/charset.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/mysys/charset.c b/mysys/charset.c index e61995de1d8..7a7ef0ad3ea 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -494,29 +494,40 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) { char buf[FN_REFLEN]; CHARSET_INFO *cs; - /* - To make things thread safe we are not allowing other threads to interfere - while we may changing the cs_info_table - */ - pthread_mutex_lock(&THR_LOCK_charset); + if ((cs= all_charsets[cs_number])) { - if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED)) + if (cs->state & MY_CS_READY) /* if CS is already initialized */ + return cs; + + /* + To make things thread safe we are not allowing other threads to interfere + while we may changing the cs_info_table + */ + pthread_mutex_lock(&THR_LOCK_charset); + + if (!(cs->state & (MY_CS_COMPILED|MY_CS_LOADED))) /* if CS is not in memory */ { strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS); my_read_charset_file(buf,flags); } - cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; - } - if (cs && !(cs->state & MY_CS_READY)) - { - if ((cs->cset->init && cs->cset->init(cs, cs_alloc)) || - (cs->coll->init && cs->coll->init(cs, cs_alloc))) - cs= NULL; + + if (cs->state & MY_CS_AVAILABLE) + { + if (!(cs->state & MY_CS_READY)) + { + if ((cs->cset->init && cs->cset->init(cs, cs_alloc)) || + (cs->coll->init && cs->coll->init(cs, cs_alloc))) + cs= NULL; + else + cs->state|= MY_CS_READY; + } + } else - cs->state|= MY_CS_READY; + cs= NULL; + + pthread_mutex_unlock(&THR_LOCK_charset); } - pthread_mutex_unlock(&THR_LOCK_charset); return cs; } From c045d1dcea0b2582b38ee5476b090097182c7144 Mon Sep 17 00:00:00 2001 From: Satya B Date: Tue, 7 Apr 2009 16:54:32 +0530 Subject: [PATCH 12/28] Fix for Bug #43973 - backup_myisam.test fails on 6.0-bugteam The test started failing following the push for BUG#41541. Some of the algorithms access bytes beyond the input data and this can affect up to one byte less than "word size" which is BITS_SAVED / 8. Fixed by adding (BITS_SAVED / 8) -1 bytes to buffer size (i.e. Memory Segment #2) to avoid accessing un-allocated data. --- myisam/mi_packrec.c | 36 +++++++++------------------------- mysql-test/r/myisampack.result | 22 +++++++++++++++++++++ mysql-test/t/myisampack.test | 25 +++++++++++++++++++++++ 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index df9a4d18a6c..68911d7f129 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -208,10 +208,17 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) This segment will be reallocated after construction of the tables. */ length=(uint) (elements*2+trees*(1 << myisam_quick_table_bits)); + /* + To keep some algorithms simpler, we accept that they access + bytes beyond the end of the input data. This can affect up to + one byte less than the "word size" size used in this file, + which is BITS_SAVED / 8. To avoid accessing non-allocated + data, we add (BITS_SAVED / 8) - 1 bytes to the buffer size. + */ if (!(share->decode_tables=(uint16*) my_malloc((length + OFFSET_TABLE_SIZE) * sizeof(uint16) + - (uint) (share->pack.header_length - sizeof(header)), - MYF(MY_WME | MY_ZEROFILL)))) + (uint) (share->pack.header_length - sizeof(header) + + (BITS_SAVED / 8) - 1), MYF(MY_WME | MY_ZEROFILL)))) goto err1; tmp_buff=share->decode_tables+length; disk_cache=(byte*) (tmp_buff+OFFSET_TABLE_SIZE); @@ -1430,31 +1437,6 @@ static void fill_buffer(MI_BIT_BUFF *bit_buff) bit_buff->current_byte=0; return; } - else - { - uint len= 0; - uint i= 0; - /* - Check if the remaining buffer/record to read is less than the word size. - If so read byte by byte - - Note: if this branch becomes a bottleneck it can be removed, assuming - that the second memory segment allocates 7 extra bytes (see - _mi_read_pack_info()). - */ - len= bit_buff->end - bit_buff->pos; - if (len < (BITS_SAVED / 8)) - { - bit_buff->current_byte= 0; - for (i=0 ; i < len ; i++) - { - bit_buff->current_byte+= (((uint) ((uchar) bit_buff->pos[len - i - 1])) - << (8 * i)); - } - bit_buff->pos= bit_buff->end; - return; - } - } #if BITS_SAVED == 64 bit_buff->current_byte= ((((uint) ((uchar) bit_buff->pos[7]))) + diff --git a/mysql-test/r/myisampack.result b/mysql-test/r/myisampack.result index b4b200549a5..736a550e32b 100644 --- a/mysql-test/r/myisampack.result +++ b/mysql-test/r/myisampack.result @@ -38,3 +38,25 @@ SELECT COUNT(*) FROM t1; COUNT(*) 1024 DROP TABLE t1; +# +# Bug #43973 - backup_myisam.test fails on 6.0-bugteam +# +CREATE DATABASE mysql_db1; +CREATE TABLE mysql_db1.t1 (c1 VARCHAR(5), c2 int); +CREATE INDEX i1 ON mysql_db1.t1 (c1, c2); +INSERT INTO mysql_db1.t1 VALUES ('A',1); +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +FLUSH TABLE mysql_db1.t1; +# Compress the table using MYISAMPACK tool +# Run MYISAMCHK tool on the compressed table +SELECT COUNT(*) FROM mysql_db1.t1 WHERE c2 < 5; +COUNT(*) +128 +DROP TABLE mysql_db1.t1; +DROP DATABASE mysql_db1; diff --git a/mysql-test/t/myisampack.test b/mysql-test/t/myisampack.test index ace7afce88a..ce27071bcf8 100644 --- a/mysql-test/t/myisampack.test +++ b/mysql-test/t/myisampack.test @@ -50,3 +50,28 @@ FLUSH TABLE t1; --exec $MYISAMPACK $MYSQLTEST_VARDIR/master-data/test/t1 SELECT COUNT(*) FROM t1; DROP TABLE t1; + +--echo # +--echo # Bug #43973 - backup_myisam.test fails on 6.0-bugteam +--echo # +CREATE DATABASE mysql_db1; +CREATE TABLE mysql_db1.t1 (c1 VARCHAR(5), c2 int); +CREATE INDEX i1 ON mysql_db1.t1 (c1, c2); +INSERT INTO mysql_db1.t1 VALUES ('A',1); +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +INSERT INTO mysql_db1.t1 SELECT * FROM mysql_db1.t1; +FLUSH TABLE mysql_db1.t1; +# +--echo # Compress the table using MYISAMPACK tool +--exec $MYISAMPACK -s $MYSQLTEST_VARDIR/master-data/mysql_db1/t1 +--echo # Run MYISAMCHK tool on the compressed table +--exec $MYISAMCHK -srq $MYSQLTEST_VARDIR/master-data/mysql_db1/t1 +SELECT COUNT(*) FROM mysql_db1.t1 WHERE c2 < 5; +# +DROP TABLE mysql_db1.t1; +DROP DATABASE mysql_db1; From 998697fd4cb1594b39b969a67992e5197408e9e5 Mon Sep 17 00:00:00 2001 From: Narayanan V Date: Wed, 8 Apr 2009 12:25:19 +0530 Subject: [PATCH 13/28] Bug#37631 Incorrect key file for table after upgrading from 5.0 to 5.1 The conformance checker was not taking into account, and, making concessions for acceptable incompatibilites in tables created by versions earlier than 4.1. The current patch relaxes the conformance checker to ignore differences in key_alg and language for tables created by versions earlier than 4.1. --- storage/myisam/ha_myisam.cc | 21 +++++++++++++++------ storage/myisammrg/ha_myisammrg.cc | 5 +++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 72e202e6132..dd66c255475 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -315,6 +315,7 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, t2_keys in Number of keys in second table t2_recs in Number of records in second table strict in Strict check switch + table in handle to the table object DESCRIPTION This function compares two MyISAM definitions. By intention it was done @@ -330,6 +331,10 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, Otherwise 'strict' flag must be set to 1 and it is not required to pass converted dot-frm definition as t1_*. + For compatibility reasons we relax some checks, specifically: + - 4.0 (and earlier versions) always set key_alg to 0. + - 4.0 (and earlier versions) have the same language for all keysegs. + RETURN VALUE 0 - Equal definitions. 1 - Different definitions. @@ -344,10 +349,11 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo, uint t1_keys, uint t1_recs, MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo, - uint t2_keys, uint t2_recs, bool strict) + uint t2_keys, uint t2_recs, bool strict, TABLE *table_arg) { uint i, j; DBUG_ENTER("check_definition"); + my_bool mysql_40_compat= table_arg && table_arg->s->frm_version < FRM_VER_TRUE_VARCHAR; if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys)) { DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u", @@ -386,8 +392,9 @@ int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo, test(t2_keyinfo[i].flag & HA_SPATIAL))); DBUG_RETURN(1); } - if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs || - t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg) + if ((mysql_40_compat && + t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg) || + t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs) { DBUG_PRINT("error", ("Key %d has different definition", i)); DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d", @@ -417,8 +424,9 @@ int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo, t1_keysegs_j__type= HA_KEYTYPE_VARBINARY1; /* purecov: inspected */ } - if (t1_keysegs_j__type != t2_keysegs[j].type || - t1_keysegs[j].language != t2_keysegs[j].language || + if ((mysql_40_compat && + t1_keysegs[j].language != t2_keysegs[j].language) || + t1_keysegs_j__type != t2_keysegs[j].type || t1_keysegs[j].null_bit != t2_keysegs[j].null_bit || t1_keysegs[j].length != t2_keysegs[j].length) { @@ -671,7 +679,8 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked) } if (check_definition(keyinfo, recinfo, table->s->keys, recs, file->s->keyinfo, file->s->rec, - file->s->base.keys, file->s->base.fields, true)) + file->s->base.keys, file->s->base.fields, + true, table)) { /* purecov: begin inspected */ my_errno= HA_ERR_CRASHED; diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 061af97d0fb..7e25309ae70 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -137,7 +137,8 @@ extern int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, extern int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo, uint t1_keys, uint t1_recs, MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo, - uint t2_keys, uint t2_recs, bool strict); + uint t2_keys, uint t2_recs, bool strict, + TABLE *table_arg); static void split_file_name(const char *file_name, LEX_STRING *db, LEX_STRING *name); @@ -595,7 +596,7 @@ int ha_myisammrg::attach_children(void) if (check_definition(keyinfo, recinfo, keys, recs, u_table->table->s->keyinfo, u_table->table->s->rec, u_table->table->s->base.keys, - u_table->table->s->base.fields, false)) + u_table->table->s->base.fields, false, NULL)) { DBUG_PRINT("error", ("table definition mismatch: '%s'", u_table->table->filename)); From 40b00f174ce67b895e6defbfb8f9efd67454eed1 Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Wed, 8 Apr 2009 16:45:43 +0530 Subject: [PATCH 14/28] Bug #43950 myisamchk shows negative value for 'Max keyfile length' While printing the Max keyfile length 'llstr' call was used which was treating the max_key_file_length as negative. Changing this to ullstr fixes the problem. myisamchk output will differ in 32 bit and 64 bit Operating systems so its not possible to have test case for this bug. --- myisam/myisamchk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index 29fb2ea1a60..b1a61f2f373 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -1311,7 +1311,7 @@ static void descript(MI_CHECK *param, register MI_INFO *info, my_string name) share->base.max_key_file_length != HA_OFFSET_ERROR) printf("Max datafile length: %13s Max keyfile length: %13s\n", llstr(share->base.max_data_file_length-1,llbuff), - llstr(share->base.max_key_file_length-1,llbuff2)); + ullstr(share->base.max_key_file_length - 1, llbuff2)); } } From 65ff9e1b0b70d81c1d404fd388c3cd8090c07589 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Wed, 8 Apr 2009 22:02:19 +0100 Subject: [PATCH 15/28] BUG#39393. Post-fix for test rpl_skip_error. The result set for multi-row statements is not the same between STMT and RBR and among different versions. Thus to avoid test failures, we are not printing out such result sets. Note, however, that this does not have impact on coverage and accuracy since the execution is able to continue without further issues when an error is found on the master and such error is set to be skipped. --- mysql-test/suite/rpl/r/rpl_skip_error.result | 26 +++----------------- mysql-test/suite/rpl/t/rpl_skip_error.test | 18 +++----------- 2 files changed, 8 insertions(+), 36 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_skip_error.result b/mysql-test/suite/rpl/r/rpl_skip_error.result index dc02bb783ae..d955859f030 100644 --- a/mysql-test/suite/rpl/r/rpl_skip_error.result +++ b/mysql-test/suite/rpl/r/rpl_skip_error.result @@ -153,17 +153,8 @@ DELETE FROM t1 WHERE id = 4; SET SQL_LOG_BIN=1; UPDATE t1 SET id= id + 3, data = 2; -SELECT *, "INNODB SET SLAVE DATA" FROM t1 ORDER BY id; -id data INNODB SET SLAVE DATA -1 1 INNODB SET SLAVE DATA -2 1 INNODB SET SLAVE DATA -3 1 INNODB SET SLAVE DATA -4 1 INNODB SET SLAVE DATA -SELECT *, "INNODB SET MASTER DATA" FROM t1 ORDER BY id; -id data INNODB SET MASTER DATA -4 2 INNODB SET MASTER DATA -5 2 INNODB SET MASTER DATA -6 2 INNODB SET MASTER DATA +**** We cannot execute a select as there are differences in the +**** behavior between STMT and RBR. ==== Using MyIsam ==== SET SQL_LOG_BIN=0; CREATE TABLE t2(id INT NOT NULL PRIMARY KEY, data INT) Engine=MyIsam; @@ -192,17 +183,8 @@ DELETE FROM t2 WHERE id = 5; SET SQL_LOG_BIN=1; UPDATE t2 SET id= id + 3, data = 2; -SELECT *, "MYISAM SET SLAVE DATA" FROM t2 ORDER BY id; -id data MYISAM SET SLAVE DATA -2 1 MYISAM SET SLAVE DATA -3 1 MYISAM SET SLAVE DATA -4 2 MYISAM SET SLAVE DATA -5 1 MYISAM SET SLAVE DATA -SELECT *, "MYISAM SET MASTER DATA" FROM t2 ORDER BY id; -id data MYISAM SET MASTER DATA -4 2 MYISAM SET MASTER DATA -5 2 MYISAM SET MASTER DATA -6 2 MYISAM SET MASTER DATA +**** We cannot execute a select as there are differences in the +**** behavior between STMT and RBR. ==== Clean Up ==== DROP TABLE t1; DROP TABLE t2; diff --git a/mysql-test/suite/rpl/t/rpl_skip_error.test b/mysql-test/suite/rpl/t/rpl_skip_error.test index c15d24be9e5..9c6aa3dcb57 100644 --- a/mysql-test/suite/rpl/t/rpl_skip_error.test +++ b/mysql-test/suite/rpl/t/rpl_skip_error.test @@ -122,13 +122,8 @@ sync_slave_with_master; let $error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1); echo $error; -connection slave; - -SELECT *, "INNODB SET SLAVE DATA" FROM t1 ORDER BY id; - -connection master; - -SELECT *, "INNODB SET MASTER DATA" FROM t1 ORDER BY id; +--echo **** We cannot execute a select as there are differences in the +--echo **** behavior between STMT and RBR. --echo ==== Using MyIsam ==== @@ -161,13 +156,8 @@ sync_slave_with_master; let $error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1); echo $error; -connection slave; - -SELECT *, "MYISAM SET SLAVE DATA" FROM t2 ORDER BY id; - -connection master; - -SELECT *, "MYISAM SET MASTER DATA" FROM t2 ORDER BY id; +--echo **** We cannot execute a select as there are differences in the +--echo **** behavior between STMT and RBR. --echo ==== Clean Up ==== From 41361d89467cc59fa1fee8f3eb66c356b4826fe8 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Thu, 9 Apr 2009 14:22:06 +0800 Subject: [PATCH 16/28] Post fix of BUG#37145 Binlog the CREATE EVENT unless the created event been successfully dropped Modified Query_log_event constructor to make sure that error_code is not set to ER_SERVER_SHUTDOWN or ER_QUERY_INTERRUPTED errors when NOT_KILLED --- sql/events.cc | 12 ++++++++++-- sql/log_event.cc | 11 ++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/sql/events.cc b/sql/events.cc index 4203ca06d7f..ea935e67bd3 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -412,6 +412,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists))) { Event_queue_element *new_element; + bool dropped= 0; if (!(new_element= new Event_queue_element())) ret= TRUE; // OOM @@ -419,8 +420,9 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, parse_data->name, new_element))) { - db_repository->drop_event(thd, parse_data->dbname, parse_data->name, - TRUE); + if (!db_repository->drop_event(thd, parse_data->dbname, parse_data->name, + TRUE)) + dropped= 1; delete new_element; } else @@ -429,6 +431,12 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool created; if (event_queue) event_queue->create_event(thd, new_element, &created); + } + /* + binlog the create event unless it's been successfully dropped + */ + if (!dropped) + { /* Binlog the create event. */ DBUG_ASSERT(thd->query && thd->query_length); write_bin_log(thd, TRUE, thd->query, thd->query_length); diff --git a/sql/log_event.cc b/sql/log_event.cc index 89094da3e94..10ff6555e9b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2292,7 +2292,16 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, (thd_arg->is_error() ? thd_arg->main_da.sql_errno() : 0) : ((thd_arg->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ? 0 : thd_arg->killed_errno()); - + + /* thd_arg->main_da.sql_errno() might be ER_SERVER_SHUTDOWN or + ER_QUERY_INTERRUPTED, So here we need to make sure that + error_code is not set to these errors when specified NOT_KILLED + by the caller + */ + if ((killed_status_arg == THD::NOT_KILLED) && + (error_code == ER_SERVER_SHUTDOWN || error_code == ER_QUERY_INTERRUPTED)) + error_code= 0; + time(&end_time); exec_time = (ulong) (end_time - thd_arg->start_time); /** From 74a332d50468456a303920597a8031dda10d5baf Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Thu, 9 Apr 2009 15:42:59 +0800 Subject: [PATCH 17/28] post fix compiling problem after push BUG#37145 to 5.0-bugteam --- client/mysqltest.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 865c1d9a717..799609a7d27 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -4087,17 +4087,16 @@ int select_connection_name(const char *name) int select_connection(struct st_command *command) { - char *name; char *p= command->first_argument; + static DYNAMIC_STRING ds_connection; + const struct command_arg connection_args[] = { + { "connection_name", ARG_STRING, TRUE, &ds_connection, "Name of the connection that we switch to." } + }; DBUG_ENTER("select_connection"); if (!*p) die("Missing connection name in connect"); - static DYNAMIC_STRING ds_connection; - const struct command_arg connection_args[] = { - { "connection_name", ARG_STRING, TRUE, &ds_connection, "Name of the connection that we switch to." } - }; check_command_args(command, command->first_argument, connection_args, sizeof(connection_args)/sizeof(struct command_arg), ','); From 9b1076b4717e470c6b9391441a1016b402053541 Mon Sep 17 00:00:00 2001 From: Narayanan V Date: Thu, 9 Apr 2009 13:48:23 +0530 Subject: [PATCH 18/28] Bug#38848 myisam_use_mmap causes widespread myisam corruption on windows Currently the memory map is being created with a size that is greater than the size of the underlying datafile. This can cause varying behaviour, e.g. In windows the size of the datafile is increased, while on linux it remains the same. This fix removes the increment margin to the size that is used while creating the memory map. --- storage/myisam/mi_dynrec.c | 6 +++--- storage/myisam/mi_packrec.c | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c index 3433c26f98b..d1cbd6955dd 100644 --- a/storage/myisam/mi_dynrec.c +++ b/storage/myisam/mi_dynrec.c @@ -66,7 +66,7 @@ static int _mi_cmp_buffer(File file, const uchar *buff, my_off_t filepos, my_bool mi_dynmap_file(MI_INFO *info, my_off_t size) { DBUG_ENTER("mi_dynmap_file"); - if (size > (my_off_t) (~((size_t) 0)) - MEMMAP_EXTRA_MARGIN) + if (size > (my_off_t) (~((size_t) 0))) { DBUG_PRINT("warning", ("File is too large for mmap")); DBUG_RETURN(1); @@ -80,7 +80,7 @@ my_bool mi_dynmap_file(MI_INFO *info, my_off_t size) upon a write if no physical memory is available. */ info->s->file_map= (uchar*) - my_mmap(0, (size_t)(size + MEMMAP_EXTRA_MARGIN), + my_mmap(0, (size_t) size, info->s->mode==O_RDONLY ? PROT_READ : PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, @@ -113,7 +113,7 @@ void mi_remap_file(MI_INFO *info, my_off_t size) if (info->s->file_map) { VOID(my_munmap((char*) info->s->file_map, - (size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN)); + (size_t) info->s->mmaped_length)); mi_dynmap_file(info, size); } } diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c index be9ce9a0c24..d9abcbce050 100644 --- a/storage/myisam/mi_packrec.c +++ b/storage/myisam/mi_packrec.c @@ -1502,7 +1502,9 @@ my_bool _mi_memmap_file(MI_INFO *info) DBUG_PRINT("warning",("File isn't extended for memmap")); DBUG_RETURN(0); } - if (mi_dynmap_file(info, share->state.state.data_file_length)) + if (mi_dynmap_file(info, + share->state.state.data_file_length + + MEMMAP_EXTRA_MARGIN)) DBUG_RETURN(0); } info->opt_flag|= MEMMAP_USED; From b6e8991cd1984927649b89fa70650de6111a69ad Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Thu, 9 Apr 2009 16:58:18 +0800 Subject: [PATCH 19/28] Fix compile error on windows for BUG#37145 on 5.0-bugteam --- client/mysqltest.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 799609a7d27..2f19fad9ea9 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -4087,6 +4087,7 @@ int select_connection_name(const char *name) int select_connection(struct st_command *command) { + int ret; char *p= command->first_argument; static DYNAMIC_STRING ds_connection; const struct command_arg connection_args[] = { @@ -4103,7 +4104,7 @@ int select_connection(struct st_command *command) DBUG_PRINT("info", ("changing connection: %s", ds_connection.str)); - int ret= select_connection_name(ds_connection.str); + ret= select_connection_name(ds_connection.str); dynstr_free(&ds_connection); return ret; } From db992986fe94ff7c5224786e0cccd1d4b846239d Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 9 Apr 2009 14:19:31 +0500 Subject: [PATCH 20/28] Bug#43833 Simple INSERT crashes the server The crash happens due to wrong 'digits' variable value(0), 'digits' can not be 0, so the fix is use 1 as min allowed value. --- mysql-test/r/insert.result | 5 +++++ mysql-test/t/insert.test | 9 +++++++++ sql/field.cc | 6 +++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index 2e49bd373d6..c98ed104a69 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -595,4 +595,9 @@ SELECT * FROM t2; c1 15449237462 DROP TABLE t1, t2; +CREATE TABLE t1(f1 FLOAT); +INSERT INTO t1 VALUES (1.23); +CREATE TABLE t2(f1 CHAR(1)); +INSERT INTO t2 SELECT f1 FROM t1; +DROP TABLE t1, t2; End of 5.0 tests. diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 0b5a12fa523..a1735c1a91f 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -454,5 +454,14 @@ SELECT * FROM t2; DROP TABLE t1, t2; +# +# Bug#43833 Simple INSERT crashes the server +# +CREATE TABLE t1(f1 FLOAT); +INSERT INTO t1 VALUES (1.23); +CREATE TABLE t2(f1 CHAR(1)); +INSERT INTO t2 SELECT f1 FROM t1; +DROP TABLE t1, t2; + --echo End of 5.0 tests. diff --git a/sql/field.cc b/sql/field.cc index 36cc4681dec..99e9d7803e1 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5987,13 +5987,13 @@ int Field_str::store(double nr) calculate the maximum number of significant digits if the 'f'-format would be used (+1 for decimal point if the number has a fractional part). */ - digits= max(0, (int) max_length - fractional); + digits= max(1, (int) max_length - fractional); /* If the exponent is negative, decrease digits by the number of leading zeros after the decimal point that do not count as significant digits. */ if (exp < 0) - digits= max(0, (int) digits + exp); + digits= max(1, (int) digits + exp); /* 'e'-format is used only if the exponent is less than -4 or greater than or equal to the precision. In this case we need to adjust the number of @@ -6001,7 +6001,7 @@ int Field_str::store(double nr) We also have to reserve one additional character if abs(exp) >= 100. */ if (exp >= (int) digits || exp < -4) - digits= max(0, (int) (max_length - 5 - (exp >= 100 || exp <= -100))); + digits= max(1, (int) (max_length - 5 - (exp >= 100 || exp <= -100))); /* Limit precision to DBL_DIG to avoid garbage past significant digits */ set_if_smaller(digits, DBL_DIG); From dc3fad94b478813e17f03cb43a3b837f3aafdc81 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Thu, 9 Apr 2009 11:40:22 +0100 Subject: [PATCH 21/28] BUG#13684: SP: DROP PROCEDURE|FUNCTION IF EXISTS not binlogged if routine does not exist There is an inconsistency with DROP DATABASE IF EXISTS, DROP TABLE IF EXISTS and DROP VIEW IF EXISTS: those are binlogged even if the DB or TABLE does not exist, whereas DROP PROCEDURE IF EXISTS does not. It would be nice or at least consistent if DROP PROCEDURE/STATEMENT worked the same too. Fixed DROP PROCEDURE|FUNCTION IF EXISTS by adding a call to mysql_bin_log.write in mysql_execute_command. Checked also if all documented "DROP (...) IF EXISTS" get binlogged. NOTE: This is a 5.0 backport patch as requested by support. --- mysql-test/r/rpl_drop_if_exists.result | 80 ++++++++++++++++++++++++++ mysql-test/r/rpl_sp.result | 16 ++++++ mysql-test/t/rpl_drop_if_exists.test | 77 +++++++++++++++++++++++++ sql/sql_parse.cc | 8 +++ 4 files changed, 181 insertions(+) create mode 100644 mysql-test/r/rpl_drop_if_exists.result create mode 100644 mysql-test/t/rpl_drop_if_exists.test diff --git a/mysql-test/r/rpl_drop_if_exists.result b/mysql-test/r/rpl_drop_if_exists.result new file mode 100644 index 00000000000..f711a873122 --- /dev/null +++ b/mysql-test/r/rpl_drop_if_exists.result @@ -0,0 +1,80 @@ +RESET MASTER; +DROP PROCEDURE IF EXISTS db_bug_13684.p; +DROP FUNCTION IF EXISTS db_bug_13684.f; +DROP TRIGGER IF EXISTS db_bug_13684.tr; +DROP VIEW IF EXISTS db_bug_13684.v; +DROP TABLE IF EXISTS db_bug_13684.t; +DROP DATABASE IF EXISTS db_bug_13684; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; DROP PROCEDURE IF EXISTS db_bug_13684.p +master-bin.000001 # Query # # use `test`; DROP FUNCTION IF EXISTS db_bug_13684.f +master-bin.000001 # Query # # use `test`; DROP TRIGGER IF EXISTS db_bug_13684.tr +master-bin.000001 # Query # # use `test`; DROP VIEW IF EXISTS db_bug_13684.v +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS db_bug_13684.t +master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684 +CREATE DATABASE db_bug_13684; +CREATE TABLE db_bug_13684.t (a int); +CREATE VIEW db_bug_13684.v +AS SELECT * FROM db_bug_13684.t; +CREATE TRIGGER db_bug_13684.tr BEFORE INSERT ON db_bug_13684.t +FOR EACH ROW BEGIN +END; +CREATE PROCEDURE db_bug_13684.p (OUT p1 INT) +BEGIN +END; +CREATE FUNCTION db_bug_13684.f (s CHAR(20)) +RETURNS CHAR(50) DETERMINISTIC +RETURN s; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; DROP PROCEDURE IF EXISTS db_bug_13684.p +master-bin.000001 # Query # # use `test`; DROP FUNCTION IF EXISTS db_bug_13684.f +master-bin.000001 # Query # # use `test`; DROP TRIGGER IF EXISTS db_bug_13684.tr +master-bin.000001 # Query # # use `test`; DROP VIEW IF EXISTS db_bug_13684.v +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS db_bug_13684.t +master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684 +master-bin.000001 # Query # # CREATE DATABASE db_bug_13684 +master-bin.000001 # Query # # use `test`; CREATE TABLE db_bug_13684.t (a int) +master-bin.000001 # Query # # use `test`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `db_bug_13684`.`v` AS select `db_bug_13684`.`t`.`a` AS `a` from `db_bug_13684`.`t` +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` TRIGGER db_bug_13684.tr BEFORE INSERT ON db_bug_13684.t +FOR EACH ROW BEGIN +END +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `db_bug_13684`.`p`(OUT p1 INT) +BEGIN +END +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION `db_bug_13684`.`f`(s CHAR(20)) RETURNS char(50) CHARSET latin1 + DETERMINISTIC +RETURN s +DROP PROCEDURE IF EXISTS db_bug_13684.p; +DROP FUNCTION IF EXISTS db_bug_13684.f; +DROP TRIGGER IF EXISTS db_bug_13684.tr; +DROP VIEW IF EXISTS db_bug_13684.v; +DROP TABLE IF EXISTS db_bug_13684.t; +DROP DATABASE IF EXISTS db_bug_13684; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; DROP PROCEDURE IF EXISTS db_bug_13684.p +master-bin.000001 # Query # # use `test`; DROP FUNCTION IF EXISTS db_bug_13684.f +master-bin.000001 # Query # # use `test`; DROP TRIGGER IF EXISTS db_bug_13684.tr +master-bin.000001 # Query # # use `test`; DROP VIEW IF EXISTS db_bug_13684.v +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS db_bug_13684.t +master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684 +master-bin.000001 # Query # # CREATE DATABASE db_bug_13684 +master-bin.000001 # Query # # use `test`; CREATE TABLE db_bug_13684.t (a int) +master-bin.000001 # Query # # use `test`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `db_bug_13684`.`v` AS select `db_bug_13684`.`t`.`a` AS `a` from `db_bug_13684`.`t` +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` TRIGGER db_bug_13684.tr BEFORE INSERT ON db_bug_13684.t +FOR EACH ROW BEGIN +END +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `db_bug_13684`.`p`(OUT p1 INT) +BEGIN +END +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION `db_bug_13684`.`f`(s CHAR(20)) RETURNS char(50) CHARSET latin1 + DETERMINISTIC +RETURN s +master-bin.000001 # Query # # use `test`; DROP PROCEDURE IF EXISTS db_bug_13684.p +master-bin.000001 # Query # # use `test`; DROP FUNCTION IF EXISTS db_bug_13684.f +master-bin.000001 # Query # # use `test`; DROP TRIGGER IF EXISTS db_bug_13684.tr +master-bin.000001 # Query # # use `test`; DROP VIEW IF EXISTS db_bug_13684.v +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS db_bug_13684.t +master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684 diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result index ebe5f8b0be9..0f4d0fa8dad 100644 --- a/mysql-test/r/rpl_sp.result +++ b/mysql-test/r/rpl_sp.result @@ -483,6 +483,7 @@ master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo master-bin.000001 # Query 1 # use `mysqltest1`; drop function fn1 master-bin.000001 # Query 1 # drop database mysqltest1 master-bin.000001 # Query 1 # drop user "zedjzlcsjhd"@127.0.0.1 +master-bin.000001 # Query 1 # use `test`; drop function if exists f1 master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) READS SQL DATA begin @@ -498,12 +499,15 @@ master-bin.000001 # Query 1 # use `test`; create table t1 (a int) master-bin.000001 # Query 1 # use `test`; insert into t1 (a) values (f1()) master-bin.000001 # Query 1 # use `test`; drop view v1 master-bin.000001 # Query 1 # use `test`; drop function f1 +master-bin.000001 # Query 1 # use `test`; DROP PROCEDURE IF EXISTS p1 master-bin.000001 # Query 1 # use `test`; DROP TABLE IF EXISTS t1 master-bin.000001 # Query 1 # use `test`; CREATE TABLE t1(col VARCHAR(10)) master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`(arg VARCHAR(10)) INSERT INTO t1 VALUES(arg) master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES( NAME_CONST('arg',_latin1'test' COLLATE 'latin1_swedish_ci')) master-bin.000001 # Query 1 # use `test`; DROP PROCEDURE p1 +master-bin.000001 # Query 1 # use `test`; DROP PROCEDURE IF EXISTS p1 +master-bin.000001 # Query 1 # use `test`; DROP FUNCTION IF EXISTS f1 master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() SET @a = 1 master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) @@ -804,6 +808,9 @@ drop user "zedjzlcsjhd"@127.0.0.1 /*!*/; use test/*!*/; SET TIMESTAMP=t/*!*/; +drop function if exists f1 +/*!*/; +SET TIMESTAMP=t/*!*/; CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) READS SQL DATA begin @@ -831,6 +838,9 @@ SET TIMESTAMP=t/*!*/; drop function f1 /*!*/; SET TIMESTAMP=t/*!*/; +DROP PROCEDURE IF EXISTS p1 +/*!*/; +SET TIMESTAMP=t/*!*/; DROP TABLE IF EXISTS t1 /*!*/; SET TIMESTAMP=t/*!*/; @@ -847,6 +857,12 @@ SET TIMESTAMP=t/*!*/; DROP PROCEDURE p1 /*!*/; SET TIMESTAMP=t/*!*/; +DROP PROCEDURE IF EXISTS p1 +/*!*/; +SET TIMESTAMP=t/*!*/; +DROP FUNCTION IF EXISTS f1 +/*!*/; +SET TIMESTAMP=t/*!*/; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() SET @a = 1 /*!*/; diff --git a/mysql-test/t/rpl_drop_if_exists.test b/mysql-test/t/rpl_drop_if_exists.test new file mode 100644 index 00000000000..a042fa8caff --- /dev/null +++ b/mysql-test/t/rpl_drop_if_exists.test @@ -0,0 +1,77 @@ +# BUG#13684: +# SP: DROP PROCEDURE|FUNCTION IF EXISTS not binlogged if routine +# does not exist +# +# There is an inconsistency with DROP DATABASE IF EXISTS, DROP +# TABLE IF EXISTS and DROP VIEW IF EXISTS: those are binlogged even +# if the DB or TABLE does not exist, whereas DROP PROCEDURE IF +# EXISTS does not. It would be nice or at least consistent if DROP +# PROCEDURE/STATEMENT worked the same too. +# +# Description: +# DROP PROCEDURE|FUNCTION IF EXISTS does not get binlogged whereas DROP +# DATABASE|TABLE|TRIGGER|... IF EXISTS do. +# +# Fixed DROP PROCEDURE|FUNCTION IF EXISTS by adding a call to +# mysql_bin_log.write in mysql_execute_command. Checked also if all +# documented "DROP (...) IF EXISTS" get binlogged. +# +# Test is implemented as follows: +# +# i) test each "drop if exists" (DDL) +# ii) show binlog events; +# iii) create an object for each drop if exists statement; +# iv) issue "drop if exists" in existent objects. +# v) show binlog events; +# + +--source include/have_log_bin.inc +RESET MASTER; + +disable_warnings; + +# test all "drop if exists" in manual with inexistent objects +DROP PROCEDURE IF EXISTS db_bug_13684.p; +DROP FUNCTION IF EXISTS db_bug_13684.f; +DROP TRIGGER IF EXISTS db_bug_13684.tr; +DROP VIEW IF EXISTS db_bug_13684.v; +DROP TABLE IF EXISTS db_bug_13684.t; +DROP DATABASE IF EXISTS db_bug_13684; + +--source include/show_binlog_events.inc + +# test drop with existing values + +# create +CREATE DATABASE db_bug_13684; + +CREATE TABLE db_bug_13684.t (a int); + +CREATE VIEW db_bug_13684.v + AS SELECT * FROM db_bug_13684.t; + +CREATE TRIGGER db_bug_13684.tr BEFORE INSERT ON db_bug_13684.t + FOR EACH ROW BEGIN + END; + +CREATE PROCEDURE db_bug_13684.p (OUT p1 INT) + BEGIN + END; + +CREATE FUNCTION db_bug_13684.f (s CHAR(20)) + RETURNS CHAR(50) DETERMINISTIC + RETURN s; + +--source include/show_binlog_events.inc + +# drop existing +DROP PROCEDURE IF EXISTS db_bug_13684.p; +DROP FUNCTION IF EXISTS db_bug_13684.f; +DROP TRIGGER IF EXISTS db_bug_13684.tr; +DROP VIEW IF EXISTS db_bug_13684.v; +DROP TABLE IF EXISTS db_bug_13684.t; +DROP DATABASE IF EXISTS db_bug_13684; + +--source include/show_binlog_events.inc + +enable_warnings; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e4618874fb9..7fbe6b86fbd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5067,6 +5067,14 @@ create_sp_error: case SP_KEY_NOT_FOUND: if (lex->drop_if_exists) { + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, + /* using_trans */ 0, + /* suppress use */ FALSE, + THD::NOT_KILLED); + mysql_bin_log.write(&qinfo); + } push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), SP_COM_STRING(lex), lex->spname->m_name.str); From 064c1b2cac3ee742d0384edcc4b1988a8c8eba60 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 9 Apr 2009 12:25:25 -0300 Subject: [PATCH 22/28] Bug#43706: libmysqld segfaults when re-intialised Bug#44091: libmysqld gets stuck waiting on mutex on initialization The problem was that libmysqld wasn't enforcing a certain initialization and deinitialization order for the mysys library. Another problem was that the global object used for management of log event handlers (aka LOGGER) wasn't being prepared for a possible reutilization. What leads to the hang/crash reported is that a failure to load the language file triggers a double call of the cleanup functions, causing an already destroyed mutex to be used. The solution is enforce a order on the initialization and deinitialization of the mysys library within the libmysqld library and to ensure that the global LOGGER object reset it's internal state during cleanup. --- mysys/my_init.c | 4 ++++ sql/log.cc | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/mysys/my_init.c b/mysys/my_init.c index b330ffac65a..a60927be693 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -136,6 +136,10 @@ void my_end(int infoflag) */ FILE *info_file= DBUG_FILE; my_bool print_info= (info_file != stderr); + + if (!my_init_done) + return; + /* We do not use DBUG_ENTER here, as after cleanup DBUG is no longer operational, so we cannot use DBUG_RETURN. diff --git a/sql/log.cc b/sql/log.cc index 44296daa939..ed2eff6625d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -845,6 +845,7 @@ void LOGGER::cleanup_base() { table_log_handler->cleanup(); delete table_log_handler; + table_log_handler= NULL; } if (file_log_handler) file_log_handler->cleanup(); @@ -855,7 +856,11 @@ void LOGGER::cleanup_end() { DBUG_ASSERT(inited == 1); if (file_log_handler) + { delete file_log_handler; + file_log_handler=NULL; + } + inited= 0; } From aa449c10535df749e263f15d144d23b51e1c8cb0 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Thu, 9 Apr 2009 22:18:18 -0400 Subject: [PATCH 23/28] Bug#39559: dump of stored procedures / functions with C-style \ comment can't be read back A change to the lexer in 5.1 caused slash-asterisk-bang-version sections to be terminated early if there exists a slash-asterisk- style comment inside it. Nesting comments is usually illegal, but we rely on versioned comment blocks in mysqldump, and the contents of those sections must be allowed to have comments. The problem was that when encountering open-comment tokens and consuming -or- passing through the contents, the "in_comment" state at the end was clobbered with the not-in-a-comment value, regardless of whether we were in a comment before this or not. So, """/*!VER one /* two */ three */""" would lose its in-comment state between "two" and "three". Save the echo and in-comment state, and restore it at the end of the comment if we consume a comment. --- mysql-test/r/parser.result | 52 ++++++++++++++++++++++ mysql-test/t/parser.test | 28 ++++++++++++ sql/sql_lex.cc | 91 +++++++++++++++++++++++++++++--------- sql/sql_lex.h | 14 ++++++ 4 files changed, 163 insertions(+), 22 deletions(-) diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index 002fbd02c2a..097f6dc69ff 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -615,3 +615,55 @@ UPDATE t3 SET a4={d '1789-07-14'} WHERE a1=0; SELECT a1, a4 FROM t2 WHERE a4 LIKE {fn UCASE('1789-07-14')}; a1 a4 DROP TABLE t1, t2, t3; +# +# Bug#39559: dump of stored procedures / functions with C-style +# comment can't be read back +# ++----------+--------+ +| expected | result | ++----------+--------+ +| 2 | 2 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 1 | 1 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 3 | 3 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 2 | 2 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 7 | 7 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 8 | 8 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 7 | 7 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 4 | 4 | ++----------+--------+ ++----------+--------+ +| expected | result | ++----------+--------+ +| 4 | 4 | ++----------+--------+ +# +# End of 5.1 tests +# diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index 7efc519e441..e44fc85bc5e 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -724,3 +724,31 @@ SELECT {fn CONCAT(a1,a2)} FROM t1; UPDATE t3 SET a4={d '1789-07-14'} WHERE a1=0; SELECT a1, a4 FROM t2 WHERE a4 LIKE {fn UCASE('1789-07-14')}; DROP TABLE t1, t2, t3; + +########################################################################### +--echo # +--echo # Bug#39559: dump of stored procedures / functions with C-style +--echo # comment can't be read back +--echo # + +--write_file $MYSQLTEST_VARDIR/tmp/bug39559.sql +select 2 as expected, /*!01000/**/*/ 2 as result; +select 1 as expected, /*!99998/**/*/ 1 as result; +select 3 as expected, /*!01000 1 + */ 2 as result; +select 2 as expected, /*!99990 1 + */ 2 as result; +select 7 as expected, /*!01000 1 + /* 8 + */ 2 + */ 4 as result; +select 8 as expected, /*!99998 1 + /* 2 + */ 4 + */ 8 as result; +select 7 as expected, /*!01000 1 + /*!01000 8 + */ 2 + */ 4 as result; +select 7 as expected, /*!01000 1 + /*!99998 8 + */ 2 + */ 4 as result; +select 4 as expected, /*!99998 1 + /*!99998 8 + */ 2 + */ 4 as result; +select 4 as expected, /*!99998 1 + /*!01000 8 + */ 2 + */ 4 as result; +select 7 as expected, /*!01000 1 + /*!01000 8 + /*!01000 error */ 16 + */ 2 + */ 4 as result; +select 4 as expected, /* 1 + /*!01000 8 + */ 2 + */ 4; +EOF + +--exec $MYSQL --comment --force --table test <$MYSQLTEST_VARDIR/tmp/bug39559.sql +--remove_file $MYSQLTEST_VARDIR/tmp/bug39559.sql + +--echo # +--echo # End of 5.1 tests +--echo # diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 19a19f2b6fb..5e24a18bea3 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -712,6 +712,53 @@ static inline uint int_token(const char *str,uint length) return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger; } + +/** + Given a stream that is advanced to the first contained character in + an open comment, consume the comment. Optionally, if we are allowed, + recurse so that we understand comments within this current comment. + + At this level, we do not support version-condition comments. We might + have been called with having just passed one in the stream, though. In + that case, we probably want to tolerate mundane comments inside. Thus, + the case for recursion. + + @retval Whether EOF reached before comment is closed. +*/ +bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted) +{ + reg1 uchar c; + while (! lip->eof()) + { + c= lip->yyGet(); + + if (remaining_recursions_permitted > 0) + { + if ((c == '/') && (lip->yyPeek() == '*')) + { + lip->yySkip(); /* Eat asterisk */ + consume_comment(lip, remaining_recursions_permitted-1); + continue; + } + } + + if (c == '*') + { + if (lip->yyPeek() == '/') + { + lip->yySkip(); /* Eat slash */ + return FALSE; + } + } + + if (c == '\n') + lip->yylineno++; + } + + return TRUE; +} + + /* MYSQLlex remember the following states from the following MYSQLlex() @@ -1204,6 +1251,8 @@ int MYSQLlex(void *arg, void *yythd) /* Reject '/' '*', since we might need to turn off the echo */ lip->yyUnget(); + lip->save_in_comment_state(); + if (lip->yyPeekn(2) == '!') { lip->in_comment= DISCARD_COMMENT; @@ -1246,11 +1295,17 @@ int MYSQLlex(void *arg, void *yythd) /* Expand the content of the special comment as real code */ lip->set_echo(TRUE); state=MY_LEX_START; - break; + break; /* Do not treat contents as a comment. */ + } + else + { + comment_closed= ! consume_comment(lip, 1); + /* version allowed to have one level of comment inside. */ } } else { + /* Not a version comment. */ state=MY_LEX_START; lip->set_echo(TRUE); break; @@ -1261,38 +1316,30 @@ int MYSQLlex(void *arg, void *yythd) lip->in_comment= PRESERVE_COMMENT; lip->yySkip(); // Accept / lip->yySkip(); // Accept * + comment_closed= ! consume_comment(lip, 0); + /* regular comments can have zero comments inside. */ } /* Discard: - regular '/' '*' comments, - special comments '/' '*' '!' for a future version, by scanning until we find a closing '*' '/' marker. - Note: There is no such thing as nesting comments, - the first '*' '/' sequence seen will mark the end. + + Nesting regular comments isn't allowed. The first + '*' '/' returns the parser to the previous state. + + /#!VERSI oned containing /# regular #/ is allowed #/ + + Inside one versioned comment, another versioned comment + is treated as a regular discardable comment. It gets + no special parsing. */ - comment_closed= FALSE; - while (! lip->eof()) - { - c= lip->yyGet(); - if (c == '*') - { - if (lip->yyPeek() == '/') - { - lip->yySkip(); - comment_closed= TRUE; - state = MY_LEX_START; - break; - } - } - else if (c == '\n') - lip->yylineno++; - } + /* Unbalanced comments with a missing '*' '/' are a syntax error */ if (! comment_closed) return (ABORT_SYM); state = MY_LEX_START; // Try again - lip->in_comment= NO_COMMENT; - lip->set_echo(TRUE); + lip->restore_in_comment_state(); break; case MY_LEX_END_LONG_COMMENT: if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/') diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a48b99d07c7..cf825a57fd5 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1160,6 +1160,18 @@ public: m_echo= echo; } + void save_in_comment_state() + { + m_echo_saved= m_echo; + in_comment_saved= in_comment; + } + + void restore_in_comment_state() + { + m_echo= m_echo_saved; + in_comment= in_comment_saved; + } + /** Skip binary from the input stream. @param n number of bytes to accept. @@ -1417,6 +1429,7 @@ private: /** Echo the parsed stream to the pre-processed buffer. */ bool m_echo; + bool m_echo_saved; /** Pre-processed buffer. */ char *m_cpp_buf; @@ -1479,6 +1492,7 @@ public: /** State of the lexical analyser for comments. */ enum_comment_state in_comment; + enum_comment_state in_comment_saved; /** Starting position of the TEXT_STRING or IDENT in the pre-processed From 39d9d106bf7ba62b0e33bfe3bd2028dbd54c55a7 Mon Sep 17 00:00:00 2001 From: Narayanan V Date: Fri, 10 Apr 2009 11:56:54 +0530 Subject: [PATCH 24/28] Bug#44020 Unicode Swedish collations not working with IBMDB2I The utf8_swedish_ci and ucs2_swedish_ci collations do not work with indexes on IBMDB2I tables. The current patch adds the mapping for ucs2_swedish collation and removes the ucs2_spanish2 mapping which is not supported by any version of the operating system. --- storage/ibmdb2i/db2i_collationSupport.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/ibmdb2i/db2i_collationSupport.cc b/storage/ibmdb2i/db2i_collationSupport.cc index 26ad0c9dee6..a41f211a689 100644 --- a/storage/ibmdb2i/db2i_collationSupport.cc +++ b/storage/ibmdb2i/db2i_collationSupport.cc @@ -111,7 +111,7 @@ static const char* mySQLCollation[MAX_COLLATION] = {"ucs2_slovak"}, {"ucs2_slovenian"}, {"ucs2_spanish"}, - {"ucs2_spanish2"}, + {"ucs2_swedish"}, {"ucs2_turkish"}, {"ucs2_unicode"}, {"ucs2"}, @@ -132,7 +132,7 @@ static const char* mySQLCollation[MAX_COLLATION] = {"utf8_slovak"}, {"utf8_slovenian"}, {"utf8_spanish"}, - {"utf8_spanish2"}, + {"utf8_swedish"}, {"utf8_turkish"}, {"utf8_unicode"}, {"utf8"} @@ -205,7 +205,7 @@ static const char* mySqlSortSequence[MAX_COLLATION] = {"ASK"}, {"ASL"}, {"AES"}, - {"AES__TRADIT"}, + {"ASW"}, {"ATR"}, {"AEN"}, {"*HEX"}, @@ -226,7 +226,7 @@ static const char* mySqlSortSequence[MAX_COLLATION] = {"ASK"}, {"ASL"}, {"AES"}, - {"AES__TRADIT"}, + {"ASW"}, {"ATR"}, {"AEN"}, {"*HEX"} From 9887dd7a669ad15fdada650f276dfb5d699faa5f Mon Sep 17 00:00:00 2001 From: Narayanan V Date: Fri, 10 Apr 2009 13:01:15 +0530 Subject: [PATCH 25/28] Bug#44022 CREATE TABLE sometimes fails silently for IBMDB2I engine In some circumstances, when a table is created with the IBMDB2I engine, the CREATE TABLE statement will return successfully but the table will not exist. The current patch addresses the above issue and causes CREATE to fail and report and error to the user. --- storage/ibmdb2i/ha_ibmdb2i.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc index 6c7ce12ded1..11eceb68cb7 100644 --- a/storage/ibmdb2i/ha_ibmdb2i.cc +++ b/storage/ibmdb2i/ha_ibmdb2i.cc @@ -2323,7 +2323,7 @@ int ha_ibmdb2i::create(const char *name, TABLE *table_arg, if (!rc && !isTemporary) { db2i_table* temp = new db2i_table(table_arg->s, name); - int32 rc = temp->fastInitForCreate(name); + rc = temp->fastInitForCreate(name); delete temp; if (rc) delete_table(name); From 4a12ecf7d9b6476d4062dd54ad6d6d30b4f43f56 Mon Sep 17 00:00:00 2001 From: Narayanan V Date: Fri, 10 Apr 2009 13:18:07 +0530 Subject: [PATCH 26/28] Bug#44025 Some schema names longer than 8 characters not supported by IBMDB2I On IBM i 5.4, schemas with names that are longer than 8 characters and contain digits or an underscore cannot contain IBMDB2I tables, even though this should theoritically be possible if all alpha characters are uppercase. THe current patch fixes the IBMDB2I engine to allow digits and the underscore(_) to be used in schema names longer than 8 characters on IBM i 5.4. --- storage/ibmdb2i/db2i_misc.h | 10 ++++++++-- storage/ibmdb2i/ha_ibmdb2i.cc | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/storage/ibmdb2i/db2i_misc.h b/storage/ibmdb2i/db2i_misc.h index 1cc3f962cfc..9e20f01208b 100644 --- a/storage/ibmdb2i/db2i_misc.h +++ b/storage/ibmdb2i/db2i_misc.h @@ -92,11 +92,17 @@ bool convertMySQLNameToDB2Name(const char* input, return (o <= outlen-1); } -bool isUpperOrQuote(const CHARSET_INFO* cs, const char* s) +bool isOrdinaryIdentifier(const char* s) { while (*s) { - if (my_isupper(cs, *s) || (*s == '"')) + if (my_isupper(system_charset_info, *s) || + my_isdigit(system_charset_info, *s) || + (*s == '_') || + (*s == '@') || + (*s == '$') || + (*s == '#') || + (*s == '"')) ++s; else return false; diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc index 6c7ce12ded1..fee4a993b00 100644 --- a/storage/ibmdb2i/ha_ibmdb2i.cc +++ b/storage/ibmdb2i/ha_ibmdb2i.cc @@ -2122,7 +2122,7 @@ int ha_ibmdb2i::create(const char *name, TABLE *table_arg, if (osVersion.v < 6) { if (strlen(libName) > - MAX_DB2_V5R4_LIBNAME_LENGTH + (isUpperOrQuote(system_charset_info, libName) ? 2 : 0)) + MAX_DB2_V5R4_LIBNAME_LENGTH + (isOrdinaryIdentifier(libName) ? 2 : 0)) { getErrTxt(DB2I_ERR_TOO_LONG_SCHEMA,libName, MAX_DB2_V5R4_LIBNAME_LENGTH); DBUG_RETURN(DB2I_ERR_TOO_LONG_SCHEMA); From 5c5691e8ec0a4c7ffe7990b03008838ae7571d19 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 10 Apr 2009 14:25:48 +0500 Subject: [PATCH 27/28] Bug#43385 Cannot ALTER DATABASE ... UPGRADE DATA DIRECTORY NAME when Views exist allow 'rename view' for ALTER ...UPGRADE DATA DIRECTORY NAME command. it's safe because a view has valid internal db&table names in this case. --- mysql-test/r/upgrade.result | 20 ++++++++++++++++++++ mysql-test/t/upgrade.test | 30 ++++++++++++++++++++++++++++++ sql/sql_rename.cc | 9 +++++++-- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/upgrade.result b/mysql-test/r/upgrade.result index adf81efe8e3..711e69094f7 100644 --- a/mysql-test/r/upgrade.result +++ b/mysql-test/r/upgrade.result @@ -84,3 +84,23 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin2 drop database `a-b-c`; drop database `tabc`; +use `#mysql50#a-b-c`; +create table t1(f1 char(10)); +show databases like '%a-b-c%'; +Database (%a-b-c%) +#mysql50#a-b-c +ALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME; +show databases like '%a-b-c%'; +Database (%a-b-c%) +a-b-c +show create view `a-b-c`.v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `a`.`f1` AS `f1` from (`a-b-c`.`t1` `a` join `information_schema`.`tables` `b`) where (convert(`a`.`f1` using utf8) = `b`.`TABLE_NAME`) utf8 utf8_general_ci +Warnings: +Note 1600 Creation context of view `a-b-c`.`v1' is invalid +select * from `a-b-c`.v1; +f1 +Warnings: +Note 1600 Creation context of view `a-b-c`.`v1' is invalid +drop database `a-b-c`; +use test; diff --git a/mysql-test/t/upgrade.test b/mysql-test/t/upgrade.test index 437b0f47cc0..5c4abc7559d 100644 --- a/mysql-test/t/upgrade.test +++ b/mysql-test/t/upgrade.test @@ -89,3 +89,33 @@ show create table `a-b-c`.`t1`; drop database `a-b-c`; drop database `tabc`; +# +# Bug#43385 Cannot ALTER DATABASE ... UPGRADE DATA DIRECTORY NAME when Views exist +# +let $MYSQLD_DATADIR= `select @@datadir`; +--mkdir $MYSQLD_DATADIR/a-b-c +use `#mysql50#a-b-c`; +create table t1(f1 char(10)); + +--write_file $MYSQLD_DATADIR/a-b-c/v1.frm +TYPE=VIEW +query=select `a`.`f1` AS `f1` from `a-b-c`.`t1` `a` join `information_schema`.`tables` `b` where (convert(`a`.`f1` using utf8) = `b`.`TABLE_NAME`) +md5=068271f1c657fe115e497856ca0fa493 +updatable=0 +algorithm=0 +definer_user=root +definer_host=localhost +suid=2 +with_check_option=0 +timestamp=2009-04-10 11:53:37 +create-version=1 +source=select f1 from `a-b-c`.t1 a, information_schema.tables b\nwhere a.f1 = b.table_name +EOF + +show databases like '%a-b-c%'; +ALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME; +show databases like '%a-b-c%'; +show create view `a-b-c`.v1; +select * from `a-b-c`.v1; +drop database `a-b-c`; +use test; diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index fc87356e452..ced69388009 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -301,8 +301,13 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, } break; case FRMTYPE_VIEW: - /* change of schema is not allowed */ - if (strcmp(ren_table->db, new_db)) + /* + change of schema is not allowed + except of ALTER ...UPGRADE DATA DIRECTORY NAME command + because a view has valid internal db&table names in this case. + */ + if (thd->lex->sql_command != SQLCOM_ALTER_DB_UPGRADE && + strcmp(ren_table->db, new_db)) my_error(ER_FORBID_SCHEMA_CHANGE, MYF(0), ren_table->db, new_db); else From 7ff5b7a9369e97a66d5773df5092553f5e976888 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Mon, 13 Apr 2009 18:09:10 +0500 Subject: [PATCH 28/28] Bug#43385 Cannot ALTER DATABASE ... UPGRADE DATA DIRECTORY NAME when Views exist(addon) mysql_rename_view can not rename view if database is not the same. The fix is to add new argument 'new_db' to mysql_rename_view() and allow rename with different databases (only for ALTER DATABASE ... UPGRADE DATA DIRECTORY NAME). --- mysql-test/t/upgrade.test | 2 ++ sql/parse_file.cc | 5 +++-- sql/parse_file.h | 2 +- sql/sql_rename.cc | 2 +- sql/sql_view.cc | 10 ++++++---- sql/sql_view.h | 3 ++- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/mysql-test/t/upgrade.test b/mysql-test/t/upgrade.test index 5c4abc7559d..e096b6520a1 100644 --- a/mysql-test/t/upgrade.test +++ b/mysql-test/t/upgrade.test @@ -116,6 +116,8 @@ show databases like '%a-b-c%'; ALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME; show databases like '%a-b-c%'; show create view `a-b-c`.v1; +--disable_ps_protocol select * from `a-b-c`.v1; +--enable_ps_protocol drop database `a-b-c`; use test; diff --git a/sql/parse_file.cc b/sql/parse_file.cc index 07ea434e8e0..f2dbeba1bbf 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -302,6 +302,7 @@ err_w_file: @thd thread handler @param schema name of given schema @param old_name original file name + @param new_db new schema @param new_name new file name @retval @@ -311,14 +312,14 @@ err_w_file: */ my_bool rename_in_schema_file(THD *thd, const char *schema, const char *old_name, - const char *new_name) + const char *new_db, const char *new_name) { char old_path[FN_REFLEN], new_path[FN_REFLEN], arc_path[FN_REFLEN]; build_table_filename(old_path, sizeof(old_path) - 1, schema, old_name, reg_ext, 0); build_table_filename(new_path, sizeof(new_path) - 1, - schema, new_name, reg_ext, 0); + new_db, new_name, reg_ext, 0); if (my_rename(old_path, new_path, MYF(MY_WME))) return 1; diff --git a/sql/parse_file.h b/sql/parse_file.h index cfac69cc471..84647e45927 100644 --- a/sql/parse_file.h +++ b/sql/parse_file.h @@ -83,7 +83,7 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, uchar* base, File_option *parameters); my_bool rename_in_schema_file(THD *thd, const char *schema, const char *old_name, - const char *new_name); + const char *new_db, const char *new_name); class File_parser: public Sql_alloc { diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index ced69388009..d4331b12cd4 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -311,7 +311,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, my_error(ER_FORBID_SCHEMA_CHANGE, MYF(0), ren_table->db, new_db); else - rc= mysql_rename_view(thd, new_alias, ren_table); + rc= mysql_rename_view(thd, new_db, new_alias, ren_table); break; default: DBUG_ASSERT(0); // should never happen diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 4d523ddf9ac..4f207f78688 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1912,6 +1912,7 @@ int view_checksum(THD *thd, TABLE_LIST *view) Parameters: thd thread handler + new_db new name of database new_name new name of view view view @@ -1921,6 +1922,7 @@ int view_checksum(THD *thd, TABLE_LIST *view) */ bool mysql_rename_view(THD *thd, + const char *new_db, const char *new_name, TABLE_LIST *view) { @@ -1959,16 +1961,16 @@ mysql_rename_view(THD *thd, goto err; /* rename view and it's backups */ - if (rename_in_schema_file(thd, view->db, view->table_name, new_name)) + if (rename_in_schema_file(thd, view->db, view->table_name, new_db, new_name)) goto err; dir.str= dir_buff; dir.length= build_table_filename(dir_buff, sizeof(dir_buff) - 1, - view->db, "", "", 0); + new_db, "", "", 0); pathstr.str= path_buff; pathstr.length= build_table_filename(path_buff, sizeof(path_buff) - 1, - view->db, new_name, reg_ext, 0); + new_db, new_name, reg_ext, 0); file.str= pathstr.str + dir.length; file.length= pathstr.length - dir.length; @@ -1977,7 +1979,7 @@ mysql_rename_view(THD *thd, (uchar*)&view_def, view_parameters)) { /* restore renamed view in case of error */ - rename_in_schema_file(thd, view->db, new_name, view->table_name); + rename_in_schema_file(thd, new_db, new_name, view->db, view->table_name); goto err; } } else diff --git a/sql/sql_view.h b/sql/sql_view.h index b8138663489..e08c2168e14 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -37,7 +37,8 @@ int view_checksum(THD *thd, TABLE_LIST *view); extern TYPELIB updatable_views_with_limit_typelib; bool check_duplicate_names(List& item_list, bool gen_unique_view_names); -bool mysql_rename_view(THD *thd, const char *new_name, TABLE_LIST *view); +bool mysql_rename_view(THD *thd, const char *new_db, const char *new_name, + TABLE_LIST *view); #define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL)