diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index de040c9759b..b0895b4c0ee 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -583,6 +583,13 @@ MYSQL_THD thd_get_current_thd(); int thd_killed(const MYSQL_THD thd); +/** + Set the killed status of the current statement. + + @param thd user thread connection handle +*/ +void thd_set_kill_status(const MYSQL_THD thd); + /** Return the thread id of a user thread diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index d4b3afaeb87..d3d6580ac7c 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -189,6 +189,7 @@ int mysql_tmpfile(const char *prefix); void* thd_get_current_thd(); int thd_killed(const void* thd); +void thd_set_kill_status(const void* thd); unsigned long thd_get_thread_id(const void* thd); void thd_get_xid(const void* thd, MYSQL_XID *xid); void mysql_query_cache_invalidate4(void* thd, diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index f66be5ec00c..0b9d31ef7c5 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -189,6 +189,7 @@ int mysql_tmpfile(const char *prefix); void* thd_get_current_thd(); int thd_killed(const void* thd); +void thd_set_kill_status(const void* thd); unsigned long thd_get_thread_id(const void* thd); void thd_get_xid(const void* thd, MYSQL_XID *xid); void mysql_query_cache_invalidate4(void* thd, diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index d2e9451c938..97b6a519208 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -142,6 +142,7 @@ int mysql_tmpfile(const char *prefix); void* thd_get_current_thd(); int thd_killed(const void* thd); +void thd_set_kill_status(const void* thd); unsigned long thd_get_thread_id(const void* thd); void thd_get_xid(const void* thd, MYSQL_XID *xid); void mysql_query_cache_invalidate4(void* thd, diff --git a/mysql-test/r/max_statement_time.result b/mysql-test/r/max_statement_time.result index 86a4eb1e488..0e749afd051 100644 --- a/mysql-test/r/max_statement_time.result +++ b/mysql-test/r/max_statement_time.result @@ -110,3 +110,17 @@ WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED' AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_exceeded; STATUS 1 + +# Check that the appropriate error status is set. + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +START TRANSACTION; +SELECT * FROM t1 FOR UPDATE; +a +1 +SET @@SESSION.max_statement_time = 500; +UPDATE t1 SET a = 2; +ERROR 70100: Query execution was interrupted, max_statement_time exceeded +ROLLBACK; +DROP TABLE t1; diff --git a/mysql-test/t/max_statement_time.test b/mysql-test/t/max_statement_time.test index f0fe6a0a16a..91a70a62fcd 100644 --- a/mysql-test/t/max_statement_time.test +++ b/mysql-test/t/max_statement_time.test @@ -4,6 +4,7 @@ --source include/have_statement_timeout.inc --source include/not_embedded.inc +--source include/have_innodb.inc --echo --echo # Test MAX_STATEMENT_TIME option syntax. @@ -79,7 +80,6 @@ DROP TABLE t1; --echo # Test the MAX_STATEMENT_TIME option with SF. --echo - CREATE TABLE t1 (a INT, b VARCHAR(300)); INSERT INTO t1 VALUES (1, 'string'); @@ -159,3 +159,23 @@ SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED' AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_exceeded; + +--echo +--echo # Check that the appropriate error status is set. +--echo + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +START TRANSACTION; +SELECT * FROM t1 FOR UPDATE; + +connect (con1,localhost,root,,test,,); +SET @@SESSION.max_statement_time = 500; +--error ER_QUERY_TIMEOUT +UPDATE t1 SET a = 2; +disconnect con1; + +connection default; +ROLLBACK; +DROP TABLE t1; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 2de1058e290..1ddbe1c2c28 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -3490,6 +3490,16 @@ extern "C" int thd_killed(const MYSQL_THD thd) return(thd->killed); } +/** + Set the killed status of the current statement. + + @param thd user thread connection handle +*/ +extern "C" void thd_set_kill_status(const MYSQL_THD thd) +{ + thd->send_kill_message(); +} + /** Return the thread id of a user thread @param thd user thread diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 2a5dab9e7d6..a2e57f95322 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -950,7 +950,7 @@ convert_error_code_to_mysql( return(0); case DB_INTERRUPTED: - my_error(ER_QUERY_INTERRUPTED, MYF(0)); + thd_set_kill_status(thd ? thd : thd_get_current_thd()); /* fall through */ case DB_FOREIGN_EXCEED_MAX_CASCADE: @@ -8687,7 +8687,7 @@ ha_innobase::check( prebuilt->trx->op_info = ""; if (thd_killed(user_thd)) { - my_error(ER_QUERY_INTERRUPTED, MYF(0)); + thd_set_kill_status(user_thd); } DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);