summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2014-10-07 11:37:36 +0300
committerMonty <monty@mariadb.org>2014-10-07 11:37:36 +0300
commitcc8aed3eb7a671d353c453a255b53e8d91d7fa73 (patch)
tree27989f6009e4fd08c1c9dde9df1d77c56a4f1fa3
parent1a7d17311c8325a072e5c912a2eb3fffb95aa97d (diff)
downloadmariadb-git-cc8aed3eb7a671d353c453a255b53e8d91d7fa73.tar.gz
MDEV 4427: query timeouts
Added MAX_STATEMENT_TIME user variable to automaticly kill queries after a given time limit has expired. - Added timer functions based on pthread_cond_timedwait - Added kill_handlerton() to signal storage engines about kill/timeout - Added support for GRANT ... MAX_STATEMENT_TIME=# - Copy max_statement_time to current user, if stored in mysql.user - Added status variable max_statement_time_exceeded - Added KILL_TIMEOUT - Removed digest hash from performance schema tests as they change all the time. - Updated test results that changed because of the new user variables or new fields in mysql.user This functionallity is inspired by work done by Davi Arnaut at twitter. Test case is copied from Davi's work. Documentation can be found at https://kb.askmonty.org/en/how-to-limittimeout-queries/ mysql-test/r/mysqld--help.result: Updated for new help message mysql-test/suite/perfschema/r/all_instances.result: Added new mutex mysql-test/suite/sys_vars/r/max_statement_time_basic.result: Added testing of max_statement_time mysql-test/suite/sys_vars/t/max_statement_time_basic.test: Added testing of max_statement_time mysql-test/t/max_statement_time.test: Added testing of max_statement_time mysys/CMakeLists.txt: Added thr_timer mysys/my_init.c: mysys/mysys_priv.h: Added new mutex and condition variables Added new mutex and condition variables mysys/thr_timer.c: Added timer functions based on pthread_cond_timedwait() This can be compiled with HAVE_TIMER_CREATE to benchmark agains timer_create()/timer_settime() sql/lex.h: Added MAX_STATEMENT_TIME sql/log_event.cc: Safety fix (timeout should be threated as an interrupted query) sql/mysqld.cc: Added support for timers Added status variable max_statement_time_exceeded sql/share/errmsg-utf8.txt: Added ER_QUERY_TIMEOUT sql/signal_handler.cc: Added support for KILL_TIMEOUT sql/sql_acl.cc: Added support for GRANT ... MAX_STATEMENT_TIME=# Copy max_statement_time to current user sql/sql_class.cc: Added timer functionality to THD. Added thd_kill_timeout() sql/sql_class.h: Added timer functionality to THD. Added KILL_TIMEOUT Added max_statement_time variable in similar manner as long_query_time was done. sql/sql_connect.cc: Added handling of max_statement_time_exceeded sql/sql_parse.cc: Added starting and stopping timers for queries. sql/sql_show.cc: Added max_statement_time_exceeded for user/connects status in MariaDB 10.0 sql/sql_yacc.yy: Added support for GRANT ... MAX_STATEMENT_TIME=# syntax, to be enabled in 10.0 sql/structs.h: Added max_statement_time user resource sql/sys_vars.cc: Added max_statement_time variables mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test Removed test as we require all fields in mysql.user table. scripts/mysql_system_tables.sql scripts/mysql_system_tables_data.sql scripts/mysql_system_tables_fix.sql Updated mysql.user with new max_statement_time field
-rw-r--r--.gitignore1
-rw-r--r--include/thr_timer.h45
-rw-r--r--mysql-test/r/grant.result9
-rw-r--r--mysql-test/r/max_statement_time.result147
-rw-r--r--mysql-test/r/mysqld--help.result6
-rw-r--r--mysql-test/r/ps.result6
-rw-r--r--mysql-test/r/status_user.result2
-rw-r--r--mysql-test/r/system_mysql_db.result1
-rw-r--r--mysql-test/r/system_mysql_db_fix40123.result1
-rw-r--r--mysql-test/r/system_mysql_db_fix50030.result1
-rw-r--r--mysql-test/r/system_mysql_db_fix50117.result1
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_is.result4
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_mysql.result2
-rw-r--r--mysql-test/suite/funcs_1/r/is_user_privileges.result33
-rw-r--r--mysql-test/suite/perfschema/r/digest_table_full.result8
-rw-r--r--mysql-test/suite/perfschema/r/rpl_gtid_func.result12
-rw-r--r--mysql-test/suite/perfschema/r/start_server_no_digests.result4
-rw-r--r--mysql-test/suite/perfschema/r/statement_digest.result78
-rw-r--r--mysql-test/suite/perfschema/r/statement_digest_consumers.result82
-rw-r--r--mysql-test/suite/perfschema/r/statement_digest_long_query.result8
-rw-r--r--mysql-test/suite/perfschema/t/digest_table_full.test2
-rw-r--r--mysql-test/suite/perfschema/t/rpl_gtid_func.test4
-rw-r--r--mysql-test/suite/perfschema/t/start_server_no_digests.test2
-rw-r--r--mysql-test/suite/perfschema/t/statement_digest.test2
-rw-r--r--mysql-test/suite/perfschema/t/statement_digest_consumers.test4
-rw-r--r--mysql-test/suite/perfschema/t/statement_digest_long_query.test2
-rw-r--r--mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result25
-rw-r--r--mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test38
-rw-r--r--mysql-test/suite/roles/set_role-recursive.result8
-rw-r--r--mysql-test/suite/roles/set_role-simple.result4
-rw-r--r--mysql-test/suite/sys_vars/r/max_statement_time_basic.result172
-rw-r--r--mysql-test/suite/sys_vars/t/max_statement_time_basic.test217
-rw-r--r--mysql-test/t/grant.test4
-rw-r--r--mysql-test/t/max_statement_time.test189
-rw-r--r--mysys/CMakeLists.txt8
-rw-r--r--mysys/my_init.c18
-rw-r--r--mysys/mysys_priv.h6
-rw-r--r--mysys/thr_timer.c589
-rw-r--r--scripts/mysql_system_tables.sql4
-rw-r--r--scripts/mysql_system_tables_data.sql8
-rw-r--r--scripts/mysql_system_tables_fix.sql1
-rw-r--r--sql/lex.h1
-rw-r--r--sql/log_event.cc1
-rw-r--r--sql/mysqld.cc26
-rw-r--r--sql/share/errmsg-utf8.txt2
-rw-r--r--sql/signal_handler.cc4
-rw-r--r--sql/sql_acl.cc59
-rw-r--r--sql/sql_class.cc32
-rw-r--r--sql/sql_class.h48
-rw-r--r--sql/sql_connect.cc7
-rw-r--r--sql/sql_parse.cc4
-rw-r--r--sql/sql_show.cc5
-rw-r--r--sql/sql_yacc.yy8
-rw-r--r--sql/structs.h9
-rw-r--r--sql/sys_vars.cc23
-rw-r--r--sql/wsrep_mysqld.cc41
-rw-r--r--sql/wsrep_mysqld.h7
57 files changed, 1780 insertions, 255 deletions
diff --git a/.gitignore b/.gitignore
index 2ed53e5365d..2c7e5c890ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ mysql-test/mtr
mysql-test/mysql-test-run
mysql-test/var/
mysys/thr_lock
+mysys/thr_timer
packaging/rpm-oel/mysql.spec
packaging/rpm-uln/mysql.10.0.11.spec
packaging/solaris/postinstall-solaris
diff --git a/include/thr_timer.h b/include/thr_timer.h
new file mode 100644
index 00000000000..892bbc1a01f
--- /dev/null
+++ b/include/thr_timer.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2012 Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 or later of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/* Prototypes when using thr_timer functions */
+
+#ifndef _thr_timer_h
+#define _thr_timer_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct st_timer {
+ struct timespec expire_time;
+ my_bool expired;
+ uint index_in_queue;
+ void (*func)(void*);
+ void *func_arg;
+} thr_timer_t;
+
+/* Main functions for library */
+my_bool init_thr_timer(uint init_size_for_timer_queue);
+void end_thr_timer();
+
+/* Functions for handling one timer */
+void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*),
+ void *arg);
+my_bool thr_timer_settime(thr_timer_t *timer_data, ulonglong microseconds);
+void thr_timer_end(thr_timer_t *timer_data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _thr_timer_h */
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index 25fe976b7ed..6c769e60780 100644
--- a/mysql-test/r/grant.result
+++ b/mysql-test/r/grant.result
@@ -58,6 +58,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
@@ -85,7 +86,7 @@ delete from mysql.user where user='mysqltest_1';
flush privileges;
delete from mysql.user where user='mysqltest_1';
flush privileges;
-grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10;
+grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10 max_statement_time 60;
select * from mysql.user where user="mysqltest_1";
Host localhost
User mysqltest_1
@@ -132,10 +133,11 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 60.000000
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
-GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10
-grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30;
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_STATEMENT_TIME 60.000000
+grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30 max_statement_time 0;
select * from mysql.user where user="mysqltest_1";
Host localhost
User mysqltest_1
@@ -182,6 +184,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30
diff --git a/mysql-test/r/max_statement_time.result b/mysql-test/r/max_statement_time.result
new file mode 100644
index 00000000000..2681575daea
--- /dev/null
+++ b/mysql-test/r/max_statement_time.result
@@ -0,0 +1,147 @@
+
+# Test the MAX_STATEMENT_TIME option.
+
+SET @@MAX_STATEMENT_TIME=2;
+select @@max_statement_time;
+@@max_statement_time
+2.000000
+SELECT SLEEP(1);
+SLEEP(1)
+0
+SELECT SLEEP(3);
+SLEEP(3)
+1
+SET @@MAX_STATEMENT_TIME=0;
+SELECT SLEEP(1);
+SLEEP(1)
+0
+SHOW STATUS LIKE "max_statement_time_exceeded";
+Variable_name Value
+Max_statement_time_exceeded 1
+CREATE TABLE t1 (a INT, b VARCHAR(300)) engine=myisam;
+INSERT INTO t1 VALUES (1, 'string');
+SELECT 0;
+0
+0
+
+# Test the MAX_STATEMENT_TIME option with SF (should have no effect).
+
+CREATE PROCEDURE p1()
+BEGIN
+declare tmp int;
+SET @@MAX_STATEMENT_TIME=0.0001;
+SELECT COUNT(*) INTO tmp FROM t1 WHERE b LIKE '%z%';
+SET @@MAX_STATEMENT_TIME=0;
+END|
+CREATE PROCEDURE p2()
+BEGIN
+SET @@MAX_STATEMENT_TIME=5;
+END|
+SELECT @@MAX_STATEMENT_TIME;
+@@MAX_STATEMENT_TIME
+0.000000
+CALL p1();
+CALL p2();
+SELECT @@MAX_STATEMENT_TIME;
+@@MAX_STATEMENT_TIME
+5.000000
+SET @@MAX_STATEMENT_TIME=0;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP TABLE t1;
+
+# MAX_STATEMENT_TIME account resource
+
+GRANT USAGE ON *.* TO user1@localhost WITH MAX_STATEMENT_TIME 1.005;
+# con1
+SELECT @@max_statement_time;
+@@max_statement_time
+1.005000
+# restart and reconnect
+set @global.userstat=1;
+SELECT @@global.max_statement_time,@@session.max_statement_time;
+@@global.max_statement_time @@session.max_statement_time
+0.000000 1.005000
+select sleep(100);
+sleep(100)
+1
+SHOW STATUS LIKE "max_statement_time_exceeded";
+Variable_name Value
+Max_statement_time_exceeded 1
+show grants for user1@localhost;
+Grants for user1@localhost
+GRANT USAGE ON *.* TO 'user1'@'localhost' WITH MAX_STATEMENT_TIME 1.005000
+set @global.userstat=0;
+DROP USER user1@localhost;
+
+# MAX_STATEMENT_TIME status variables.
+
+flush status;
+SET @@max_statement_time=0;
+SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_exceeded
+FROM INFORMATION_SCHEMA.GLOBAL_STATUS
+WHERE VARIABLE_NAME = 'max_statement_time_exceeded';
+SET @@max_statement_time=0.5;
+SELECT SLEEP(2);
+SLEEP(2)
+1
+SHOW STATUS LIKE '%timeout%';
+Variable_name Value
+Ssl_default_timeout 0
+Ssl_session_cache_timeouts 0
+SET @@max_statement_time=0;
+# Ensure that the counters for:
+# - statements that exceeded their maximum execution time
+# are incremented.
+SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS
+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 = 0.5;
+UPDATE t1 SET a = 2;
+ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+SHOW WARNINGS;
+Level Code Message
+Error 1967 Query execution was interrupted (max_statement_time exceeded)
+ROLLBACK;
+DROP TABLE t1;
+
+# Test interaction with lock waits.
+
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+SET @@SESSION.max_statement_time= 0.5;
+LOCK TABLES t1 WRITE;
+SELECT @@SESSION.max_statement_time;
+@@SESSION.max_statement_time
+0.500000
+LOCK TABLES t1 READ;
+ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+UNLOCK TABLES;
+BEGIN;
+SELECT * FROM t1;
+a
+1
+ALTER TABLE t1 ADD COLUMN b INT;
+ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
+ROLLBACK;
+SELECT GET_LOCK('lock', 1);
+GET_LOCK('lock', 1)
+1
+SELECT GET_LOCK('lock', 1);
+GET_LOCK('lock', 1)
+NULL
+SELECT RELEASE_LOCK('lock');
+RELEASE_LOCK('lock')
+1
+DROP TABLE t1;
diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index 5a2142c402c..80ba45be72a 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -422,6 +422,11 @@ The following options may be given as the first argument:
value are used; the rest are ignored)
--max-sp-recursion-depth[=#]
Maximum stored procedure recursion depth
+ --max-statement-time=#
+ A SELECT query that have taken more than
+ max_statement_time seconds will be aborted. The argument
+ will be treated as a decimal value with microsecond
+ precision. A value of 0 (default) means no timeout
--max-tmp-tables=# Maximum number of temporary tables a client can keep open
at a time
--max-user-connections=#
@@ -1196,6 +1201,7 @@ max-relay-log-size 1073741824
max-seeks-for-key 18446744073709551615
max-sort-length 1024
max-sp-recursion-depth 0
+max-statement-time 0
max-tmp-tables 32
max-user-connections 0
max-write-lock-count 18446744073709551615
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 7db51eadbe6..e30fa9a1966 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -1202,13 +1202,13 @@ SET @aux= "SELECT COUNT(*)
prepare my_stmt from @aux;
execute my_stmt;
COUNT(*)
-45
+46
execute my_stmt;
COUNT(*)
-45
+46
execute my_stmt;
COUNT(*)
-45
+46
deallocate prepare my_stmt;
drop procedure if exists p1|
drop table if exists t1|
diff --git a/mysql-test/r/status_user.result b/mysql-test/r/status_user.result
index 829c8abb634..766a00f6f78 100644
--- a/mysql-test/r/status_user.result
+++ b/mysql-test/r/status_user.result
@@ -25,6 +25,7 @@ DENIED_CONNECTIONS bigint(21) NO 0
LOST_CONNECTIONS bigint(21) NO 0
ACCESS_DENIED bigint(21) NO 0
EMPTY_QUERIES bigint(21) NO 0
+MAX_STATEMENT_TIME_EXCEEDED bigint(21) NO 0
show columns from information_schema.user_statistics;
Field Type Null Key Default Extra
USER varchar(128) NO
@@ -50,6 +51,7 @@ DENIED_CONNECTIONS bigint(21) NO 0
LOST_CONNECTIONS bigint(21) NO 0
ACCESS_DENIED bigint(21) NO 0
EMPTY_QUERIES bigint(21) NO 0
+MAX_STATEMENT_TIME_EXCEEDED bigint(21) NO 0
show columns from information_schema.index_statistics;
Field Type Null Key Default Extra
TABLE_SCHEMA varchar(192) NO
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
index 0204354d9e3..f195b0a607e 100644
--- a/mysql-test/r/system_mysql_db.result
+++ b/mysql-test/r/system_mysql_db.result
@@ -131,6 +131,7 @@ user CREATE TABLE `user` (
`password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '',
+ `max_statement_time` decimal(12,6) NOT NULL DEFAULT '0.000000',
PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
show create table func;
diff --git a/mysql-test/r/system_mysql_db_fix40123.result b/mysql-test/r/system_mysql_db_fix40123.result
index 0204354d9e3..f195b0a607e 100644
--- a/mysql-test/r/system_mysql_db_fix40123.result
+++ b/mysql-test/r/system_mysql_db_fix40123.result
@@ -131,6 +131,7 @@ user CREATE TABLE `user` (
`password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '',
+ `max_statement_time` decimal(12,6) NOT NULL DEFAULT '0.000000',
PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
show create table func;
diff --git a/mysql-test/r/system_mysql_db_fix50030.result b/mysql-test/r/system_mysql_db_fix50030.result
index 0204354d9e3..f195b0a607e 100644
--- a/mysql-test/r/system_mysql_db_fix50030.result
+++ b/mysql-test/r/system_mysql_db_fix50030.result
@@ -131,6 +131,7 @@ user CREATE TABLE `user` (
`password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '',
+ `max_statement_time` decimal(12,6) NOT NULL DEFAULT '0.000000',
PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
show create table func;
diff --git a/mysql-test/r/system_mysql_db_fix50117.result b/mysql-test/r/system_mysql_db_fix50117.result
index 0204354d9e3..f195b0a607e 100644
--- a/mysql-test/r/system_mysql_db_fix50117.result
+++ b/mysql-test/r/system_mysql_db_fix50117.result
@@ -131,6 +131,7 @@ user CREATE TABLE `user` (
`password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N',
`default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '',
+ `max_statement_time` decimal(12,6) NOT NULL DEFAULT '0.000000',
PRIMARY KEY (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
show create table func;
diff --git a/mysql-test/suite/funcs_1/r/is_columns_is.result b/mysql-test/suite/funcs_1/r/is_columns_is.result
index 8f2f81a4616..c73eaa874c7 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_is.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_is.result
@@ -36,6 +36,7 @@ def information_schema CLIENT_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NUL
def information_schema CLIENT_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
def information_schema CLIENT_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
def information_schema CLIENT_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
+def information_schema CLIENT_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 24 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
def information_schema CLIENT_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
def information_schema CLIENT_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
def information_schema CLIENT_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
@@ -408,6 +409,7 @@ def information_schema USER_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL
def information_schema USER_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
def information_schema USER_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
def information_schema USER_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
+def information_schema USER_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 24 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
def information_schema USER_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
def information_schema USER_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
def information_schema USER_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select
@@ -533,6 +535,7 @@ NULL information_schema CLIENT_STATISTICS DENIED_CONNECTIONS bigint NULL NULL NU
NULL information_schema CLIENT_STATISTICS LOST_CONNECTIONS bigint NULL NULL NULL NULL bigint(21)
NULL information_schema CLIENT_STATISTICS ACCESS_DENIED bigint NULL NULL NULL NULL bigint(21)
NULL information_schema CLIENT_STATISTICS EMPTY_QUERIES bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema CLIENT_STATISTICS MAX_STATEMENT_TIME_EXCEEDED bigint NULL NULL NULL NULL bigint(21)
3.0000 information_schema COLLATIONS COLLATION_NAME varchar 32 96 utf8 utf8_general_ci varchar(32)
3.0000 information_schema COLLATIONS CHARACTER_SET_NAME varchar 32 96 utf8 utf8_general_ci varchar(32)
NULL information_schema COLLATIONS ID bigint NULL NULL NULL NULL bigint(11)
@@ -906,6 +909,7 @@ NULL information_schema USER_STATISTICS DENIED_CONNECTIONS bigint NULL NULL NULL
NULL information_schema USER_STATISTICS LOST_CONNECTIONS bigint NULL NULL NULL NULL bigint(21)
NULL information_schema USER_STATISTICS ACCESS_DENIED bigint NULL NULL NULL NULL bigint(21)
NULL information_schema USER_STATISTICS EMPTY_QUERIES bigint NULL NULL NULL NULL bigint(21)
+NULL information_schema USER_STATISTICS MAX_STATEMENT_TIME_EXCEEDED bigint NULL NULL NULL NULL bigint(21)
3.0000 information_schema VIEWS TABLE_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema VIEWS TABLE_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema VIEWS TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result
index d05c120bfa8..09adebfab1c 100644
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result
@@ -227,6 +227,7 @@ def mysql user is_role 44 N NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum
def mysql user Lock_tables_priv 21 N NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references
def mysql user max_connections 39 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned select,insert,update,references
def mysql user max_questions 37 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned select,insert,update,references
+def mysql user max_statement_time 46 0.000000 NO decimal NULL NULL 12 6 NULL NULL NULL decimal(12,6) select,insert,update,references
def mysql user max_updates 38 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned select,insert,update,references
def mysql user max_user_connections 40 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references
def mysql user Password 3 NO char 41 41 NULL NULL NULL latin1 latin1_bin char(41) select,insert,update,references
@@ -568,3 +569,4 @@ NULL mysql user max_user_connections int NULL NULL NULL NULL int(11)
3.0000 mysql user password_expired enum 1 3 utf8 utf8_general_ci enum('N','Y')
3.0000 mysql user is_role enum 1 3 utf8 utf8_general_ci enum('N','Y')
3.0000 mysql user default_role char 80 240 utf8 utf8_bin char(80)
+NULL mysql user max_statement_time decimal NULL NULL NULL NULL decimal(12,6)
diff --git a/mysql-test/suite/funcs_1/r/is_user_privileges.result b/mysql-test/suite/funcs_1/r/is_user_privileges.result
index 5296a37c98d..dfbe50ad862 100644
--- a/mysql-test/suite/funcs_1/r/is_user_privileges.result
+++ b/mysql-test/suite/funcs_1/r/is_user_privileges.result
@@ -132,6 +132,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -177,6 +178,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -222,6 +224,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
#
# Add GRANT OPTION db_datadict.* to testuser1;
GRANT UPDATE ON db_datadict.* TO 'testuser1'@'localhost' WITH GRANT OPTION;
@@ -291,6 +294,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -336,6 +340,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -381,6 +386,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
# Establish connection testuser1 (user=testuser1)
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -436,6 +442,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -481,6 +488,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -526,6 +534,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -603,6 +612,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -648,6 +658,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -693,6 +704,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION;
#
# Here <SELECT YES> is shown correctly for testuser1;
@@ -762,6 +774,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -807,6 +820,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -852,6 +866,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -907,6 +922,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -952,6 +968,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -997,6 +1014,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
SHOW GRANTS;
Grants for testuser1@localhost
GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION
@@ -1104,6 +1122,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -1149,6 +1168,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -1194,6 +1214,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -1296,6 +1317,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -1341,6 +1363,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -1386,6 +1409,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
@@ -1441,6 +1465,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -1486,6 +1511,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -1531,6 +1557,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -1593,6 +1620,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -1638,6 +1666,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -1683,6 +1712,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
SHOW GRANTS;
Grants for testuser1@localhost
GRANT USAGE ON *.* TO 'testuser1'@'localhost'
@@ -1760,6 +1790,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser2
Password
@@ -1805,6 +1836,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
Host localhost
User testuser3
Password
@@ -1850,6 +1882,7 @@ authentication_string
password_expired N
is_role N
default_role
+max_statement_time 0.000000
# Switch to connection testuser1
SELECT * FROM information_schema.user_privileges
WHERE grantee LIKE '''testuser%'''
diff --git a/mysql-test/suite/perfschema/r/digest_table_full.result b/mysql-test/suite/perfschema/r/digest_table_full.result
index 9c0efb7b1ca..4c7de82abc2 100644
--- a/mysql-test/suite/perfschema/r/digest_table_full.result
+++ b/mysql-test/suite/perfschema/r/digest_table_full.result
@@ -109,11 +109,11 @@ DROP TRIGGER trg;
####################################
# QUERYING PS STATEMENT DIGEST
####################################
-SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
+SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest;
-SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS
-NULL NULL NULL 55 32 1 2
-statements_digest 0e98ee6a98e296530ec59c12dbc08dfe TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1 0 0 0
+SCHEMA_NAME DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS
+NULL NULL 55 32 1 2
+statements_digest TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1 0 0 0
SHOW VARIABLES LIKE "performance_schema_digests_size";
Variable_name Value
performance_schema_digests_size 2
diff --git a/mysql-test/suite/perfschema/r/rpl_gtid_func.result b/mysql-test/suite/perfschema/r/rpl_gtid_func.result
index 98342bc4869..86c8347addd 100644
--- a/mysql-test/suite/perfschema/r/rpl_gtid_func.result
+++ b/mysql-test/suite/perfschema/r/rpl_gtid_func.result
@@ -33,11 +33,11 @@ TABLE information_schema % NO NO
TABLE master foo YES YES
TABLE mysql % NO NO
TABLE performance_schema % NO NO
-select digest, digest_text, count_star
+select digest_text, count_star
from performance_schema.events_statements_summary_by_digest
where digest_text like "%in_%_digest%";
-digest digest_text count_star
-e315485f9cbc06befb4e59970905a034 SELECT ? AS in_master_digest 1
+digest_text count_star
+SELECT ? AS in_master_digest 1
insert into test.marker values (2);
**** On Slave ****
select * from test.marker;
@@ -60,11 +60,11 @@ TABLE information_schema % NO NO
TABLE mysql % NO NO
TABLE performance_schema % NO NO
TABLE slave foo YES YES
-select digest, digest_text, count_star
+select digest_text, count_star
from performance_schema.events_statements_summary_by_digest
where digest_text like "%in_%_digest%";
-digest digest_text count_star
-bd2f53b41efcd037df41a3dd8bf3312a SELECT ? AS in_slave_digest 1
+digest_text count_star
+SELECT ? AS in_slave_digest 1
**** On Master ****
delete from performance_schema.setup_objects
where object_schema='master';
diff --git a/mysql-test/suite/perfschema/r/start_server_no_digests.result b/mysql-test/suite/perfschema/r/start_server_no_digests.result
index 4f6fa9bc5da..e4b389716a9 100644
--- a/mysql-test/suite/perfschema/r/start_server_no_digests.result
+++ b/mysql-test/suite/perfschema/r/start_server_no_digests.result
@@ -109,9 +109,9 @@ DROP TRIGGER trg;
####################################
# QUERYING PS STATEMENT DIGEST
####################################
-SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
+SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest;
-SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS
+SCHEMA_NAME DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS
SHOW VARIABLES LIKE "performance_schema_digests_size";
Variable_name Value
performance_schema_digests_size 0
diff --git a/mysql-test/suite/perfschema/r/statement_digest.result b/mysql-test/suite/perfschema/r/statement_digest.result
index 41cba435cb6..a7983e5baaa 100644
--- a/mysql-test/suite/perfschema/r/statement_digest.result
+++ b/mysql-test/suite/perfschema/r/statement_digest.result
@@ -109,46 +109,46 @@ DROP TRIGGER trg;
####################################
# QUERYING PS STATEMENT DIGEST
####################################
-SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
+SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest;
-SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS
-statements_digest 0e98ee6a98e296530ec59c12dbc08dfe TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1 0 0 0
-statements_digest 954f43425c3234acc8e194afd97e8a0a SELECT ? FROM t1 1 0 0 0
-statements_digest fc365a54bc19d746bd24c27aba46b990 SELECT ? FROM `t1` 1 0 0 0
-statements_digest 27ba28f6252e4ae0e9b14b36da536fbe SELECT ?, ... FROM t1 2 0 0 0
-statements_digest 81d03922612900032ec4b81934ab4841 SELECT ? FROM t2 1 0 0 0
-statements_digest adce8aec12b6b5046cd4bf55951014c7 SELECT ?, ... FROM t2 2 0 0 0
-statements_digest 59a1bd93c424b10802fe66bb6dcd94d2 INSERT INTO t1 VALUES (?) 1 1 0 0
-statements_digest 91b2da58b0eb49c35a38fbc49f5e491d INSERT INTO t2 VALUES (?) 1 1 0 0
-statements_digest 967114adbf91d8a4a99ec5e49e909ff4 INSERT INTO t3 VALUES (...) 4 4 0 0
-statements_digest 8f25e7a48487e0aa7377e816816bb658 INSERT INTO t4 VALUES (...) 1 1 0 0
-statements_digest 4e51253af793867fba66166de1f314f7 INSERT INTO t5 VALUES (...) 1 1 0 0
-statements_digest fa47b3109e117216cd10209690d28596 INSERT INTO t1 VALUES (?) /* , ... */ 2 7 0 0
-statements_digest 72409f84bc236e6fe9f2f7b4d727f2d3 INSERT INTO t3 VALUES (...) /* , ... */ 1 3 0 0
-statements_digest d40aaddb41ed794d65dd8273f0c75700 INSERT INTO t5 VALUES (...) /* , ... */ 1 3 0 0
-statements_digest 57a82b28388e52e99fc64339dd30edde INSERT INTO t1 VALUES ( NULL ) 1 1 0 0
-statements_digest 6a56b694106442474cb0e5fb7575c8b9 INSERT INTO t6 VALUES (...) 5 5 0 0
-statements_digest c9abf55e296c4317dbaf2d14ef907ad7 SELECT ? + ? 3 0 0 0
-statements_digest 156304a0851a3e3626b39fb3da841a82 SELECT ? 1 0 0 0
-statements_digest 3b085ab0d2063dfca1a39212e3ea1831 CREATE SCHEMA statements_digest_temp 2 2 0 0
-statements_digest 09f9fabef2feb9a54ba01455e5ae83b9 DROP SCHEMA statements_digest_temp 2 0 0 0
-statements_digest 7910a63ffd31cbcb742e15270c8958c8 SELECT ? FROM no_such_table 1 0 0 1
-statements_digest fa34540a438bc672478b1162505ee28c CREATE TABLE dup_table ( c CHARACTER (?) ) 2 0 0 1
-statements_digest 2c720f176bb7c8510ff8aca8921b9945 DROP TABLE dup_table 1 0 0 0
-statements_digest 0c7d9fd8c27ab067511da41ca3bcdff3 INSERT INTO t11 VALUES (?) 1 1 1 0
-statements_digest 81681ff345065ed72bcd1e9407ab85e4 SHOW WARNINGS 1 0 0 0
-statements_digest d766f5823ae5d8e4cf4602b8e7a3fb80 PREPARE stmt FROM ? 1 0 0 0
-statements_digest 3ab1e87eabd9688edf919754cce6348b EXECUTE stmt 2 0 0 0
-statements_digest 470094469d250b9f45cab45bf610efe8 DEALLOCATE PREPARE stmt 1 0 0 0
-statements_digest 1b4d25358e08b35ad54e49dfe5eaf3e4 CREATE PROCEDURE p1 ( ) BEGIN SELECT * FROM t12 ; END 1 0 0 0
-statements_digest 84554971243e91106214dcb8f4eaa89b CALL p1 ( ) 2 0 0 0
-statements_digest 77206e4bf30979c56752a7ed9150213a DROP PROCEDURE p1 1 0 0 0
-statements_digest 03b91dcdba6b0e29f7fb240ae4bcd97f CREATE FUNCTION `func` ( a INTEGER , b INTEGER ) RETURNS INTEGER (?) RETURN a + b 1 0 0 0
-statements_digest 72bc532f308f2dca62f5291df8c50e6f SELECT func (...) 2 0 0 0
-statements_digest 0b5a5297689c5036def6af8e8a8ce113 DROP FUNCTION func 1 0 0 0
-statements_digest d08331e42c67555ece50e46eef0f2b47 CREATE TRIGGER trg BEFORE INSERT ON t12 FOR EACH ROW SET @ ? := ? 1 0 0 0
-statements_digest 754a49a4de995c5a729e9ab52f135f59 INSERT INTO t12 VALUES (?) 2 2 0 0
-statements_digest 68df17752bca7c2c8ee2a6a19a0674e7 DROP TRIGGER trg 1 0 0 0
+SCHEMA_NAME DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS
+statements_digest TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1 0 0 0
+statements_digest SELECT ? FROM t1 1 0 0 0
+statements_digest SELECT ? FROM `t1` 1 0 0 0
+statements_digest SELECT ?, ... FROM t1 2 0 0 0
+statements_digest SELECT ? FROM t2 1 0 0 0
+statements_digest SELECT ?, ... FROM t2 2 0 0 0
+statements_digest INSERT INTO t1 VALUES (?) 1 1 0 0
+statements_digest INSERT INTO t2 VALUES (?) 1 1 0 0
+statements_digest INSERT INTO t3 VALUES (...) 4 4 0 0
+statements_digest INSERT INTO t4 VALUES (...) 1 1 0 0
+statements_digest INSERT INTO t5 VALUES (...) 1 1 0 0
+statements_digest INSERT INTO t1 VALUES (?) /* , ... */ 2 7 0 0
+statements_digest INSERT INTO t3 VALUES (...) /* , ... */ 1 3 0 0
+statements_digest INSERT INTO t5 VALUES (...) /* , ... */ 1 3 0 0
+statements_digest INSERT INTO t1 VALUES ( NULL ) 1 1 0 0
+statements_digest INSERT INTO t6 VALUES (...) 5 5 0 0
+statements_digest SELECT ? + ? 3 0 0 0
+statements_digest SELECT ? 1 0 0 0
+statements_digest CREATE SCHEMA statements_digest_temp 2 2 0 0
+statements_digest DROP SCHEMA statements_digest_temp 2 0 0 0
+statements_digest SELECT ? FROM no_such_table 1 0 0 1
+statements_digest CREATE TABLE dup_table ( c CHARACTER (?) ) 2 0 0 1
+statements_digest DROP TABLE dup_table 1 0 0 0
+statements_digest INSERT INTO t11 VALUES (?) 1 1 1 0
+statements_digest SHOW WARNINGS 1 0 0 0
+statements_digest PREPARE stmt FROM ? 1 0 0 0
+statements_digest EXECUTE stmt 2 0 0 0
+statements_digest DEALLOCATE PREPARE stmt 1 0 0 0
+statements_digest CREATE PROCEDURE p1 ( ) BEGIN SELECT * FROM t12 ; END 1 0 0 0
+statements_digest CALL p1 ( ) 2 0 0 0
+statements_digest DROP PROCEDURE p1 1 0 0 0
+statements_digest CREATE FUNCTION `func` ( a INTEGER , b INTEGER ) RETURNS INTEGER (?) RETURN a + b 1 0 0 0
+statements_digest SELECT func (...) 2 0 0 0
+statements_digest DROP FUNCTION func 1 0 0 0
+statements_digest CREATE TRIGGER trg BEFORE INSERT ON t12 FOR EACH ROW SET @ ? := ? 1 0 0 0
+statements_digest INSERT INTO t12 VALUES (?) 2 2 0 0
+statements_digest DROP TRIGGER trg 1 0 0 0
####################################
# CLEANUP
####################################
diff --git a/mysql-test/suite/perfschema/r/statement_digest_consumers.result b/mysql-test/suite/perfschema/r/statement_digest_consumers.result
index 21e62e13b19..8c5696bb139 100644
--- a/mysql-test/suite/perfschema/r/statement_digest_consumers.result
+++ b/mysql-test/suite/perfschema/r/statement_digest_consumers.result
@@ -123,47 +123,47 @@ DROP TRIGGER trg;
####################################
# QUERYING PS STATEMENT DIGEST
####################################
-SELECT schema_name, digest, digest_text, count_star FROM performance_schema.events_statements_summary_by_digest;
-schema_name digest digest_text count_star
-statements_digest 0e98ee6a98e296530ec59c12dbc08dfe TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1
-statements_digest 954f43425c3234acc8e194afd97e8a0a SELECT ? FROM t1 1
-statements_digest fc365a54bc19d746bd24c27aba46b990 SELECT ? FROM `t1` 1
-statements_digest 27ba28f6252e4ae0e9b14b36da536fbe SELECT ?, ... FROM t1 2
-statements_digest 81d03922612900032ec4b81934ab4841 SELECT ? FROM t2 1
-statements_digest adce8aec12b6b5046cd4bf55951014c7 SELECT ?, ... FROM t2 2
-statements_digest 59a1bd93c424b10802fe66bb6dcd94d2 INSERT INTO t1 VALUES (?) 1
-statements_digest 91b2da58b0eb49c35a38fbc49f5e491d INSERT INTO t2 VALUES (?) 1
-statements_digest 967114adbf91d8a4a99ec5e49e909ff4 INSERT INTO t3 VALUES (...) 4
-statements_digest 8f25e7a48487e0aa7377e816816bb658 INSERT INTO t4 VALUES (...) 1
-statements_digest 4e51253af793867fba66166de1f314f7 INSERT INTO t5 VALUES (...) 1
-statements_digest fa47b3109e117216cd10209690d28596 INSERT INTO t1 VALUES (?) /* , ... */ 2
-statements_digest 72409f84bc236e6fe9f2f7b4d727f2d3 INSERT INTO t3 VALUES (...) /* , ... */ 1
-statements_digest d40aaddb41ed794d65dd8273f0c75700 INSERT INTO t5 VALUES (...) /* , ... */ 1
-statements_digest 57a82b28388e52e99fc64339dd30edde INSERT INTO t1 VALUES ( NULL ) 1
-statements_digest 6a56b694106442474cb0e5fb7575c8b9 INSERT INTO t6 VALUES (...) 5
-statements_digest c9abf55e296c4317dbaf2d14ef907ad7 SELECT ? + ? 3
-statements_digest 156304a0851a3e3626b39fb3da841a82 SELECT ? 1
-statements_digest 3b085ab0d2063dfca1a39212e3ea1831 CREATE SCHEMA statements_digest_temp 2
-statements_digest 09f9fabef2feb9a54ba01455e5ae83b9 DROP SCHEMA statements_digest_temp 2
-statements_digest 7910a63ffd31cbcb742e15270c8958c8 SELECT ? FROM no_such_table 1
-statements_digest fa34540a438bc672478b1162505ee28c CREATE TABLE dup_table ( c CHARACTER (?) ) 2
-statements_digest 2c720f176bb7c8510ff8aca8921b9945 DROP TABLE dup_table 1
-statements_digest 0c7d9fd8c27ab067511da41ca3bcdff3 INSERT INTO t11 VALUES (?) 1
-statements_digest 81681ff345065ed72bcd1e9407ab85e4 SHOW WARNINGS 1
-statements_digest d766f5823ae5d8e4cf4602b8e7a3fb80 PREPARE stmt FROM ? 1
-statements_digest 3ab1e87eabd9688edf919754cce6348b EXECUTE stmt 2
-statements_digest 470094469d250b9f45cab45bf610efe8 DEALLOCATE PREPARE stmt 1
-statements_digest 1b4d25358e08b35ad54e49dfe5eaf3e4 CREATE PROCEDURE p1 ( ) BEGIN SELECT * FROM t12 ; END 1
-statements_digest 84554971243e91106214dcb8f4eaa89b CALL p1 ( ) 2
-statements_digest 77206e4bf30979c56752a7ed9150213a DROP PROCEDURE p1 1
-statements_digest 03b91dcdba6b0e29f7fb240ae4bcd97f CREATE FUNCTION `func` ( a INTEGER , b INTEGER ) RETURNS INTEGER (?) RETURN a + b 1
-statements_digest 72bc532f308f2dca62f5291df8c50e6f SELECT func (...) 2
-statements_digest 0b5a5297689c5036def6af8e8a8ce113 DROP FUNCTION func 1
-statements_digest d08331e42c67555ece50e46eef0f2b47 CREATE TRIGGER trg BEFORE INSERT ON t12 FOR EACH ROW SET @ ? := ? 1
-statements_digest 754a49a4de995c5a729e9ab52f135f59 INSERT INTO t12 VALUES (?) 2
-statements_digest 68df17752bca7c2c8ee2a6a19a0674e7 DROP TRIGGER trg 1
-SELECT digest, digest_text FROM performance_schema.events_statements_current;
-digest digest_text
+SELECT schema_name,digest_text, count_star FROM performance_schema.events_statements_summary_by_digest;
+schema_name digest_text count_star
+statements_digest TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1
+statements_digest SELECT ? FROM t1 1
+statements_digest SELECT ? FROM `t1` 1
+statements_digest SELECT ?, ... FROM t1 2
+statements_digest SELECT ? FROM t2 1
+statements_digest SELECT ?, ... FROM t2 2
+statements_digest INSERT INTO t1 VALUES (?) 1
+statements_digest INSERT INTO t2 VALUES (?) 1
+statements_digest INSERT INTO t3 VALUES (...) 4
+statements_digest INSERT INTO t4 VALUES (...) 1
+statements_digest INSERT INTO t5 VALUES (...) 1
+statements_digest INSERT INTO t1 VALUES (?) /* , ... */ 2
+statements_digest INSERT INTO t3 VALUES (...) /* , ... */ 1
+statements_digest INSERT INTO t5 VALUES (...) /* , ... */ 1
+statements_digest INSERT INTO t1 VALUES ( NULL ) 1
+statements_digest INSERT INTO t6 VALUES (...) 5
+statements_digest SELECT ? + ? 3
+statements_digest SELECT ? 1
+statements_digest CREATE SCHEMA statements_digest_temp 2
+statements_digest DROP SCHEMA statements_digest_temp 2
+statements_digest SELECT ? FROM no_such_table 1
+statements_digest CREATE TABLE dup_table ( c CHARACTER (?) ) 2
+statements_digest DROP TABLE dup_table 1
+statements_digest INSERT INTO t11 VALUES (?) 1
+statements_digest SHOW WARNINGS 1
+statements_digest PREPARE stmt FROM ? 1
+statements_digest EXECUTE stmt 2
+statements_digest DEALLOCATE PREPARE stmt 1
+statements_digest CREATE PROCEDURE p1 ( ) BEGIN SELECT * FROM t12 ; END 1
+statements_digest CALL p1 ( ) 2
+statements_digest DROP PROCEDURE p1 1
+statements_digest CREATE FUNCTION `func` ( a INTEGER , b INTEGER ) RETURNS INTEGER (?) RETURN a + b 1
+statements_digest SELECT func (...) 2
+statements_digest DROP FUNCTION func 1
+statements_digest CREATE TRIGGER trg BEFORE INSERT ON t12 FOR EACH ROW SET @ ? := ? 1
+statements_digest INSERT INTO t12 VALUES (?) 2
+statements_digest DROP TRIGGER trg 1
+SELECT digest_text FROM performance_schema.events_statements_current;
+digest_text
####################################
# CLEANUP
####################################
diff --git a/mysql-test/suite/perfschema/r/statement_digest_long_query.result b/mysql-test/suite/perfschema/r/statement_digest_long_query.result
index bb355304537..8bc7a877bda 100644
--- a/mysql-test/suite/perfschema/r/statement_digest_long_query.result
+++ b/mysql-test/suite/perfschema/r/statement_digest_long_query.result
@@ -6,7 +6,7 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1
####################################
# QUERYING PS STATEMENT DIGEST
####################################
-SELECT schema_name, digest, digest_text, count_star FROM events_statements_summary_by_digest;
-schema_name digest digest_text count_star
-performance_schema 9d35ff74210c6b30efa4559d627ed0f7 TRUNCATE TABLE events_statements_summary_by_digest 1
-performance_schema d78a04c1c42765b8552e0483c50ae9ff SELECT ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ... 1
+SELECT schema_name, digest_text, count_star FROM events_statements_summary_by_digest;
+schema_name digest_text count_star
+performance_schema TRUNCATE TABLE events_statements_summary_by_digest 1
+performance_schema SELECT ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ... 1
diff --git a/mysql-test/suite/perfschema/t/digest_table_full.test b/mysql-test/suite/perfschema/t/digest_table_full.test
index cb9d7ea4ea8..dbbce662256 100644
--- a/mysql-test/suite/perfschema/t/digest_table_full.test
+++ b/mysql-test/suite/perfschema/t/digest_table_full.test
@@ -19,7 +19,7 @@ TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;
--echo ####################################
--echo # QUERYING PS STATEMENT DIGEST
--echo ####################################
-SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
+SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest;
diff --git a/mysql-test/suite/perfschema/t/rpl_gtid_func.test b/mysql-test/suite/perfschema/t/rpl_gtid_func.test
index 27837572bff..f337f95bf84 100644
--- a/mysql-test/suite/perfschema/t/rpl_gtid_func.test
+++ b/mysql-test/suite/perfschema/t/rpl_gtid_func.test
@@ -45,7 +45,7 @@ insert into performance_schema.setup_objects
select * from performance_schema.setup_objects
order by object_type, object_schema, object_name;
-select digest, digest_text, count_star
+select digest_text, count_star
from performance_schema.events_statements_summary_by_digest
where digest_text like "%in_%_digest%";
@@ -67,7 +67,7 @@ insert into performance_schema.setup_objects
select * from performance_schema.setup_objects
order by object_type, object_schema, object_name;
-select digest, digest_text, count_star
+select digest_text, count_star
from performance_schema.events_statements_summary_by_digest
where digest_text like "%in_%_digest%";
diff --git a/mysql-test/suite/perfschema/t/start_server_no_digests.test b/mysql-test/suite/perfschema/t/start_server_no_digests.test
index cb9d7ea4ea8..dbbce662256 100644
--- a/mysql-test/suite/perfschema/t/start_server_no_digests.test
+++ b/mysql-test/suite/perfschema/t/start_server_no_digests.test
@@ -19,7 +19,7 @@ TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;
--echo ####################################
--echo # QUERYING PS STATEMENT DIGEST
--echo ####################################
-SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
+SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest;
diff --git a/mysql-test/suite/perfschema/t/statement_digest.test b/mysql-test/suite/perfschema/t/statement_digest.test
index ed1f99e4318..59486ad61d8 100644
--- a/mysql-test/suite/perfschema/t/statement_digest.test
+++ b/mysql-test/suite/perfschema/t/statement_digest.test
@@ -16,7 +16,7 @@ TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;
--echo ####################################
--echo # QUERYING PS STATEMENT DIGEST
--echo ####################################
-SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
+SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS,
SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest;
# Cleanup for Digest
diff --git a/mysql-test/suite/perfschema/t/statement_digest_consumers.test b/mysql-test/suite/perfschema/t/statement_digest_consumers.test
index e7510e32049..16fa300b975 100644
--- a/mysql-test/suite/perfschema/t/statement_digest_consumers.test
+++ b/mysql-test/suite/perfschema/t/statement_digest_consumers.test
@@ -28,8 +28,8 @@ TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;
--echo ####################################
--echo # QUERYING PS STATEMENT DIGEST
--echo ####################################
-SELECT schema_name, digest, digest_text, count_star FROM performance_schema.events_statements_summary_by_digest;
-SELECT digest, digest_text FROM performance_schema.events_statements_current;
+SELECT schema_name,digest_text, count_star FROM performance_schema.events_statements_summary_by_digest;
+SELECT digest_text FROM performance_schema.events_statements_current;
# Cleanup for Digest
--source ../include/digest_cleanup.inc
diff --git a/mysql-test/suite/perfschema/t/statement_digest_long_query.test b/mysql-test/suite/perfschema/t/statement_digest_long_query.test
index 3969383a6fb..be80917c9af 100644
--- a/mysql-test/suite/perfschema/t/statement_digest_long_query.test
+++ b/mysql-test/suite/perfschema/t/statement_digest_long_query.test
@@ -20,4 +20,4 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1
--echo ####################################
--echo # QUERYING PS STATEMENT DIGEST
--echo ####################################
-SELECT schema_name, digest, digest_text, count_star FROM events_statements_summary_by_digest;
+SELECT schema_name, digest_text, count_star FROM events_statements_summary_by_digest;
diff --git a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result
deleted file mode 100644
index df4bc6ce5f6..00000000000
--- a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result
+++ /dev/null
@@ -1,25 +0,0 @@
-use mysql;
-alter table user drop column is_role;
-alter table user drop column default_role;
-flush privileges;
-create role test_role;
-ERROR HY000: Column count of mysql.user is wrong. Expected 44, found 43. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error.
-drop role test_role;
-ERROR HY000: Operation DROP ROLE failed for 'test_role'
-alter table user add column is_role enum('N', 'Y') default 'N' not null
-COLLATE utf8_general_ci
-after password_expired;
-create role test_role;
-create user test_user@localhost;
-grant test_role to test_user@localhost;
-set default role test_role for root@localhost;
-ERROR HY000: Column count of mysql.user is wrong. Expected 45, found 44. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error.
-drop role test_role;
-drop user test_user@localhost;
-alter table user add column default_role char(80) binary default '' not null
-COLLATE utf8_general_ci
-after is_role;
-update user set is_role='N';
-flush privileges;
-create role test_role;
-drop role test_role;
diff --git a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test
deleted file mode 100644
index 5122a2fed9a..00000000000
--- a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test
+++ /dev/null
@@ -1,38 +0,0 @@
-source include/not_embedded.inc;
-
-connect (mysql, localhost, root,,);
-use mysql;
-
-alter table user drop column is_role;
-alter table user drop column default_role;
-
-flush privileges;
-
---replace_regex /10\d\d\d\d/MYSQL_VERSION_ID/
---error ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE
-create role test_role;
---error ER_CANNOT_USER
-drop role test_role;
-alter table user add column is_role enum('N', 'Y') default 'N' not null
- COLLATE utf8_general_ci
-after password_expired;
-
-# Test default role column
-create role test_role;
-create user test_user@localhost;
-grant test_role to test_user@localhost;
---replace_regex /10\d\d\d\d/MYSQL_VERSION_ID/
---error ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE
-set default role test_role for root@localhost;
-drop role test_role;
-drop user test_user@localhost;
-
-alter table user add column default_role char(80) binary default '' not null
- COLLATE utf8_general_ci
-after is_role;
-
-update user set is_role='N';
-
-flush privileges;
-create role test_role;
-drop role test_role;
diff --git a/mysql-test/suite/roles/set_role-recursive.result b/mysql-test/suite/roles/set_role-recursive.result
index 008de2c3265..9e62558fc14 100644
--- a/mysql-test/suite/roles/set_role-recursive.result
+++ b/mysql-test/suite/roles/set_role-recursive.result
@@ -16,11 +16,11 @@ Host User Role Admin_option
test_role1 test_role2 N
grant select on *.* to test_role2;
select * from mysql.user where user like 'test_role1';
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role
- test_role1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time
+ test_role1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000
select * from mysql.user where user like 'test_role2';
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role
- test_role2 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time
+ test_role2 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
show grants;
diff --git a/mysql-test/suite/roles/set_role-simple.result b/mysql-test/suite/roles/set_role-simple.result
index f870bf8eb30..3ce6d5c054b 100644
--- a/mysql-test/suite/roles/set_role-simple.result
+++ b/mysql-test/suite/roles/set_role-simple.result
@@ -11,8 +11,8 @@ localhost root test_role1 Y
localhost test_user test_role1 N
grant select on *.* to test_role1;
select * from mysql.user where user='test_role1';
-Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role
- test_role1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time
+ test_role1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
show grants;
diff --git a/mysql-test/suite/sys_vars/r/max_statement_time_basic.result b/mysql-test/suite/sys_vars/r/max_statement_time_basic.result
new file mode 100644
index 00000000000..8b384ac6765
--- /dev/null
+++ b/mysql-test/suite/sys_vars/r/max_statement_time_basic.result
@@ -0,0 +1,172 @@
+SET @start_global_value = @@global.max_statement_time;
+SELECT @start_global_value;
+@start_global_value
+0
+SET @start_session_value = @@session.max_statement_time;
+SELECT @start_session_value;
+@start_session_value
+0
+'#--------------------FN_DYNVARS_068_01-------------------------#'
+SET @@global.max_statement_time = 100;
+SET @@global.max_statement_time = DEFAULT;
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+0.000000
+SET @@session.max_statement_time = 200;
+SET @@session.max_statement_time = DEFAULT;
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+0.000000
+'#--------------------FN_DYNVARS_068_02-------------------------#'
+SET @@global.max_statement_time = DEFAULT;
+SELECT @@global.max_statement_time = 0;
+@@global.max_statement_time = 0
+1
+SET @@session.max_statement_time = DEFAULT;
+SELECT @@session.max_statement_time = 0;
+@@session.max_statement_time = 0
+1
+'#--------------------FN_DYNVARS_068_03-------------------------#'
+SET @@global.max_statement_time = 0;
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+0.000000
+SET @@global.max_statement_time = 0.123456;
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+0.123456
+SET @@global.max_statement_time = 60020;
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+60020.000000
+SET @@global.max_statement_time = 31536000;
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+31536000.000000
+SET @@global.max_statement_time = 65536;
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+65536.000000
+'#--------------------FN_DYNVARS_068_04-------------------------#'
+SET @@session.max_statement_time = 0;
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+0.000000
+SET @@session.max_statement_time = 1;
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+1.000000
+SET @@session.max_statement_time = 50050;
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+50050.000000
+SET @@session.max_statement_time = 31536000;
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+31536000.000000
+SET @@session.max_statement_time = 65550;
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+65550.000000
+'#------------------FN_DYNVARS_068_05-----------------------#'
+SET @@global.max_statement_time = 100000000000;
+Warnings:
+Warning 1292 Truncated incorrect max_statement_time value: '100000000000'
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+31536000.000000
+SET @@global.max_statement_time = -1;
+Warnings:
+Warning 1292 Truncated incorrect max_statement_time value: '-1'
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+0.000000
+SET @@global.max_statement_time = 65530.34;
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+65530.340000
+SET @@global.max_statement_time = test;
+ERROR 42000: Incorrect argument type to variable 'max_statement_time'
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+65530.340000
+SET @@session.max_statement_time = 100000000000;
+Warnings:
+Warning 1292 Truncated incorrect max_statement_time value: '100000000000'
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+31536000.000000
+SET @@session.max_statement_time = -2;
+Warnings:
+Warning 1292 Truncated incorrect max_statement_time value: '-2'
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+0.000000
+SET @@session.max_statement_time = 65530.34;
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+65530.340000
+SET @@session.max_statement_time = test;
+ERROR 42000: Incorrect argument type to variable 'max_statement_time'
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+65530.340000
+'#------------------FN_DYNVARS_068_06-----------------------#'
+SELECT @@global.max_statement_time = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='max_statement_time';
+@@global.max_statement_time = VARIABLE_VALUE
+1
+'#------------------FN_DYNVARS_068_07-----------------------#'
+SELECT @@session.max_statement_time = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.SESSION_VARIABLES
+WHERE VARIABLE_NAME='max_statement_time';
+@@session.max_statement_time = VARIABLE_VALUE
+1
+'#------------------FN_DYNVARS_068_08-----------------------#'
+SET @@global.max_statement_time = TRUE;
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+1.000000
+SET @@global.max_statement_time = FALSE;
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+0.000000
+'#---------------------FN_DYNVARS_001_09----------------------#'
+SET @@global.max_statement_time = 10;
+SELECT @@max_statement_time = @@global.max_statement_time;
+@@max_statement_time = @@global.max_statement_time
+0
+'#---------------------FN_DYNVARS_001_10----------------------#'
+SET @@max_statement_time = 100;
+SELECT @@max_statement_time = @@local.max_statement_time;
+@@max_statement_time = @@local.max_statement_time
+1
+SELECT @@local.max_statement_time = @@session.max_statement_time;
+@@local.max_statement_time = @@session.max_statement_time
+1
+'#---------------------FN_DYNVARS_001_11----------------------#'
+SET max_statement_time = 1;
+SELECT @@max_statement_time;
+@@max_statement_time
+1.000000
+SELECT local.max_statement_time;
+ERROR 42S02: Unknown table 'local' in field list
+SELECT session.max_statement_time;
+ERROR 42S02: Unknown table 'session' in field list
+SELECT max_statement_time = @@session.max_statement_time;
+ERROR 42S22: Unknown column 'max_statement_time' in 'field list'
+#
+# Check that one can use max_statement_time as a field
+#
+drop table if exists t1;
+create table t1 (a int, max_statement_time int);
+drop table t1;
+SET @@global.max_statement_time = @start_global_value;
+SELECT @@global.max_statement_time;
+@@global.max_statement_time
+0.000000
+SET @@session.max_statement_time = @start_session_value;
+SELECT @@session.max_statement_time;
+@@session.max_statement_time
+0.000000
diff --git a/mysql-test/suite/sys_vars/t/max_statement_time_basic.test b/mysql-test/suite/sys_vars/t/max_statement_time_basic.test
new file mode 100644
index 00000000000..186589dcee2
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/max_statement_time_basic.test
@@ -0,0 +1,217 @@
+####################### mysql-test\t\max_statement_time_basic.test ###############
+# #
+# Variable Name: max_statement_time #
+# Scope: GLOBAL | SESSION #
+# Access Type: Dynamic #
+# Data Type: numeric #
+# Default Value:10 #
+# Min Value: 1 #
+# #
+# #
+# Creation Date: 2012-12-30 #
+# Author: Monty #
+# #
+# Description: Test Cases of Dynamic System Variable max_statement_time #
+# that checks the behavior of this variable in the following ways#
+# * Default Value #
+# * Valid & Invalid values #
+# * Scope & Access method #
+# * Data Integrity #
+# #
+# Reference: https://kb.askmonty.org/en/how-to-limittimeout-queries/ #
+# server-system-variables.html #
+# #
+###############################################################################
+
+--source include/load_sysvars.inc
+
+############################################################
+# START OF max_statement_time TESTS #
+############################################################
+
+
+#############################################################
+# Save initial value #
+#############################################################
+
+SET @start_global_value = @@global.max_statement_time;
+SELECT @start_global_value;
+SET @start_session_value = @@session.max_statement_time;
+SELECT @start_session_value;
+
+
+--echo '#--------------------FN_DYNVARS_068_01-------------------------#'
+###############################################################
+# Display the DEFAULT value of max_statement_time #
+###############################################################
+
+SET @@global.max_statement_time = 100;
+SET @@global.max_statement_time = DEFAULT;
+SELECT @@global.max_statement_time;
+
+SET @@session.max_statement_time = 200;
+SET @@session.max_statement_time = DEFAULT;
+SELECT @@session.max_statement_time;
+
+
+--echo '#--------------------FN_DYNVARS_068_02-------------------------#'
+###############################################################
+# Check the DEFAULT value of max_statement_time #
+###############################################################
+
+SET @@global.max_statement_time = DEFAULT;
+SELECT @@global.max_statement_time = 0;
+
+SET @@session.max_statement_time = DEFAULT;
+SELECT @@session.max_statement_time = 0;
+
+
+--echo '#--------------------FN_DYNVARS_068_03-------------------------#'
+#########################################################################
+# Change the value of max_statement_time to a valid value for GLOBAL Scope #
+#########################################################################
+
+SET @@global.max_statement_time = 0;
+SELECT @@global.max_statement_time;
+SET @@global.max_statement_time = 0.123456;
+SELECT @@global.max_statement_time;
+SET @@global.max_statement_time = 60020;
+SELECT @@global.max_statement_time;
+SET @@global.max_statement_time = 31536000;
+SELECT @@global.max_statement_time;
+SET @@global.max_statement_time = 65536;
+SELECT @@global.max_statement_time;
+
+
+--echo '#--------------------FN_DYNVARS_068_04-------------------------#'
+##########################################################################
+# Change the value of max_statement_time to a valid value for SESSION Scope #
+##########################################################################
+
+SET @@session.max_statement_time = 0;
+SELECT @@session.max_statement_time;
+SET @@session.max_statement_time = 1;
+SELECT @@session.max_statement_time;
+SET @@session.max_statement_time = 50050;
+SELECT @@session.max_statement_time;
+SET @@session.max_statement_time = 31536000;
+SELECT @@session.max_statement_time;
+SET @@session.max_statement_time = 65550;
+SELECT @@session.max_statement_time;
+
+
+--echo '#------------------FN_DYNVARS_068_05-----------------------#'
+########################################################
+# Change the value of max_statement_time to an invalid value #
+########################################################
+
+SET @@global.max_statement_time = 100000000000;
+SELECT @@global.max_statement_time;
+SET @@global.max_statement_time = -1;
+SELECT @@global.max_statement_time;
+SET @@global.max_statement_time = 65530.34;
+SELECT @@global.max_statement_time;
+--Error ER_WRONG_TYPE_FOR_VAR
+SET @@global.max_statement_time = test;
+SELECT @@global.max_statement_time;
+
+SET @@session.max_statement_time = 100000000000;
+SELECT @@session.max_statement_time;
+SET @@session.max_statement_time = -2;
+SELECT @@session.max_statement_time;
+SET @@session.max_statement_time = 65530.34;
+SELECT @@session.max_statement_time;
+
+--Error ER_WRONG_TYPE_FOR_VAR
+SET @@session.max_statement_time = test;
+SELECT @@session.max_statement_time;
+
+
+--echo '#------------------FN_DYNVARS_068_06-----------------------#'
+####################################################################
+# Check if the value in GLOBAL Table matches value in variable #
+####################################################################
+
+
+SELECT @@global.max_statement_time = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='max_statement_time';
+
+--echo '#------------------FN_DYNVARS_068_07-----------------------#'
+####################################################################
+# Check if the value in SESSION Table matches value in variable #
+####################################################################
+
+SELECT @@session.max_statement_time = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.SESSION_VARIABLES
+WHERE VARIABLE_NAME='max_statement_time';
+
+
+--echo '#------------------FN_DYNVARS_068_08-----------------------#'
+####################################################################
+# Check if TRUE and FALSE values can be used on variable #
+####################################################################
+
+SET @@global.max_statement_time = TRUE;
+SELECT @@global.max_statement_time;
+SET @@global.max_statement_time = FALSE;
+SELECT @@global.max_statement_time;
+
+
+--echo '#---------------------FN_DYNVARS_001_09----------------------#'
+#################################################################################
+# Check if accessing variable with and without GLOBAL point to same variable #
+#################################################################################
+
+SET @@global.max_statement_time = 10;
+SELECT @@max_statement_time = @@global.max_statement_time;
+
+
+--echo '#---------------------FN_DYNVARS_001_10----------------------#'
+########################################################################################################
+# Check if accessing variable with SESSION,LOCAL and without SCOPE points to same session variable #
+########################################################################################################
+
+SET @@max_statement_time = 100;
+SELECT @@max_statement_time = @@local.max_statement_time;
+SELECT @@local.max_statement_time = @@session.max_statement_time;
+
+
+--echo '#---------------------FN_DYNVARS_001_11----------------------#'
+##########################################################################
+# Check if max_statement_time can be accessed with and without @@ sign #
+##########################################################################
+
+SET max_statement_time = 1;
+SELECT @@max_statement_time;
+--Error ER_UNKNOWN_TABLE
+SELECT local.max_statement_time;
+--Error ER_UNKNOWN_TABLE
+SELECT session.max_statement_time;
+--Error ER_BAD_FIELD_ERROR
+SELECT max_statement_time = @@session.max_statement_time;
+
+--echo #
+--echo # Check that one can use max_statement_time as a field
+--echo #
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int, max_statement_time int);
+drop table t1;
+
+####################################
+# Restore initial value #
+####################################
+
+SET @@global.max_statement_time = @start_global_value;
+SELECT @@global.max_statement_time;
+SET @@session.max_statement_time = @start_session_value;
+SELECT @@session.max_statement_time;
+
+
+####################################################
+# END OF max_statement_time TESTS #
+####################################################
+
diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test
index ed7271521c8..20632038273 100644
--- a/mysql-test/t/grant.test
+++ b/mysql-test/t/grant.test
@@ -47,10 +47,10 @@ flush privileges;
#
delete from mysql.user where user='mysqltest_1';
flush privileges;
-grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10;
+grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10 max_statement_time 60;
query_vertical select * from mysql.user where user="mysqltest_1";
show grants for mysqltest_1@localhost;
-grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30;
+grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30 max_statement_time 0;
query_vertical select * from mysql.user where user="mysqltest_1";
show grants for mysqltest_1@localhost;
# This is just to double check that one won't ignore results of selects
diff --git a/mysql-test/t/max_statement_time.test b/mysql-test/t/max_statement_time.test
new file mode 100644
index 00000000000..0356d3caa49
--- /dev/null
+++ b/mysql-test/t/max_statement_time.test
@@ -0,0 +1,189 @@
+#
+# Test behavior of MAX_STATEMENT_TIME.
+#
+
+--source include/not_embedded.inc
+--source include/have_innodb.inc
+
+--echo
+--echo # Test the MAX_STATEMENT_TIME option.
+--echo
+
+SET @@MAX_STATEMENT_TIME=2;
+select @@max_statement_time;
+SELECT SLEEP(1);
+SELECT SLEEP(3);
+SET @@MAX_STATEMENT_TIME=0;
+SELECT SLEEP(1);
+SHOW STATUS LIKE "max_statement_time_exceeded";
+
+CREATE TABLE t1 (a INT, b VARCHAR(300)) engine=myisam;
+
+INSERT INTO t1 VALUES (1, 'string');
+
+--disable_result_log
+--disable_query_log
+
+SET @@MAX_STATEMENT_TIME=2;
+
+SET @@MAX_STATEMENT_TIME=0.1;
+WHILE (! $mysql_errno)
+{
+ SET @@MAX_STATEMENT_TIME=0;
+ INSERT INTO t1 SELECT * FROM t1;
+ SET @@MAX_STATEMENT_TIME=0.1;
+ --error 0,ER_STATEMENT_TIMEOUT
+ SELECT COUNT(*) FROM t1 WHERE b LIKE '%z%';
+}
+SET @@MAX_STATEMENT_TIME=0;
+
+--enable_query_log
+--enable_result_log
+
+eval SELECT $mysql_errno;
+
+--echo
+--echo # Test the MAX_STATEMENT_TIME option with SF (should have no effect).
+--echo
+
+DELIMITER |;
+
+CREATE PROCEDURE p1()
+BEGIN
+ declare tmp int;
+ SET @@MAX_STATEMENT_TIME=0.0001;
+ SELECT COUNT(*) INTO tmp FROM t1 WHERE b LIKE '%z%';
+ SET @@MAX_STATEMENT_TIME=0;
+END|
+
+CREATE PROCEDURE p2()
+BEGIN
+ SET @@MAX_STATEMENT_TIME=5;
+END|
+
+DELIMITER ;|
+
+SELECT @@MAX_STATEMENT_TIME;
+CALL p1();
+CALL p2();
+SELECT @@MAX_STATEMENT_TIME;
+SET @@MAX_STATEMENT_TIME=0;
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP TABLE t1;
+
+--echo
+--echo # MAX_STATEMENT_TIME account resource
+--echo
+
+GRANT USAGE ON *.* TO user1@localhost WITH MAX_STATEMENT_TIME 1.005;
+
+--echo # con1
+connect(con1,localhost,user1,,test,,);
+SELECT @@max_statement_time;
+disconnect con1;
+
+--echo # restart and reconnect
+connection default;
+source include/restart_mysqld.inc;
+
+set @global.userstat=1;
+connect(con1,localhost,user1,,test,,);
+SELECT @@global.max_statement_time,@@session.max_statement_time;
+select sleep(100);
+SHOW STATUS LIKE "max_statement_time_exceeded";
+disconnect con1;
+
+connection default;
+show grants for user1@localhost;
+--disable_parsing
+select max_user_timeouts from information_schema.user_statistics where user="user1";
+--enable_parsing
+
+set @global.userstat=0;
+DROP USER user1@localhost;
+
+--echo
+--echo # MAX_STATEMENT_TIME status variables.
+--echo
+
+flush status;
+
+SET @@max_statement_time=0;
+SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_exceeded
+ FROM INFORMATION_SCHEMA.GLOBAL_STATUS
+ WHERE VARIABLE_NAME = 'max_statement_time_exceeded';
+
+SET @@max_statement_time=0.5;
+SELECT SLEEP(2);
+SHOW STATUS LIKE '%timeout%';
+SET @@max_statement_time=0;
+
+--echo # Ensure that the counters for:
+--echo # - statements that exceeded their maximum execution time
+--echo # are incremented.
+
+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 = 0.5;
+--error ER_STATEMENT_TIMEOUT
+UPDATE t1 SET a = 2;
+SHOW WARNINGS;
+disconnect con1;
+
+connection default;
+ROLLBACK;
+DROP TABLE t1;
+
+--echo
+--echo # Test interaction with lock waits.
+--echo
+
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1);
+
+connect (con1,localhost,root,,test,,);
+SET @@SESSION.max_statement_time= 0.5;
+
+connection default;
+LOCK TABLES t1 WRITE;
+
+connection con1;
+SELECT @@SESSION.max_statement_time;
+--error ER_STATEMENT_TIMEOUT
+LOCK TABLES t1 READ;
+
+connection default;
+UNLOCK TABLES;
+BEGIN;
+SELECT * FROM t1;
+
+connection con1;
+--error ER_STATEMENT_TIMEOUT
+ALTER TABLE t1 ADD COLUMN b INT;
+
+connection default;
+ROLLBACK;
+SELECT GET_LOCK('lock', 1);
+
+connection con1;
+SELECT GET_LOCK('lock', 1);
+
+disconnect con1;
+connection default;
+SELECT RELEASE_LOCK('lock');
+DROP TABLE t1;
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index f0d25dae6b9..7f076b10e78 100644
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -33,7 +33,9 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c my_default.c
my_basename.c
my_write.c ptr_cmp.c queues.c stacktrace.c
string.c thr_alarm.c thr_lock.c thr_mutex.c
- thr_rwlock.c tree.c typelib.c base64.c my_memmem.c my_getpagesize.c
+ thr_rwlock.c thr_timer.c
+ tree.c typelib.c base64.c my_memmem.c
+ my_getpagesize.c
lf_alloc-pin.c lf_dynarray.c lf_hash.c
safemalloc.c my_new.cc
my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c
@@ -89,6 +91,10 @@ ADD_EXECUTABLE(thr_lock thr_lock.c)
TARGET_LINK_LIBRARIES(thr_lock mysys)
SET_TARGET_PROPERTIES(thr_lock PROPERTIES COMPILE_FLAGS "-DMAIN")
+ADD_EXECUTABLE(thr_timer thr_timer.c)
+TARGET_LINK_LIBRARIES(thr_timer mysys)
+SET_TARGET_PROPERTIES(thr_timer PROPERTIES COMPILE_FLAGS "-DMAIN")
+
INSTALL_DEBUG_SYMBOLS(mysys)
IF(MSVC)
INSTALL_DEBUG_TARGET(mysys DESTINATION ${INSTALL_LIBDIR}/debug)
diff --git a/mysys/my_init.c b/mysys/my_init.c
index 2c06425f6fb..32289dbed7a 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -454,7 +454,8 @@ PSI_mutex_key key_LOCK_localtime_r;
#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */
PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock,
- key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_LOCK_alarm,
+ key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock,
+ key_LOCK_alarm, key_LOCK_timer,
key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap,
key_THR_LOCK_lock, key_THR_LOCK_malloc,
key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net,
@@ -474,6 +475,7 @@ static PSI_mutex_info all_mysys_mutexes[]=
{ &key_IO_CACHE_SHARE_mutex, "IO_CACHE::SHARE_mutex", 0},
{ &key_KEY_CACHE_cache_lock, "KEY_CACHE::cache_lock", 0},
{ &key_LOCK_alarm, "LOCK_alarm", PSI_FLAG_GLOBAL},
+ { &key_LOCK_timer, "LOCK_timer", PSI_FLAG_GLOBAL},
{ &key_my_thread_var_mutex, "my_thread_var::mutex", 0},
{ &key_THR_LOCK_charset, "THR_LOCK_charset", PSI_FLAG_GLOBAL},
{ &key_THR_LOCK_heap, "THR_LOCK_heap", PSI_FLAG_GLOBAL},
@@ -489,13 +491,14 @@ static PSI_mutex_info all_mysys_mutexes[]=
{ &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL }
};
-PSI_cond_key key_COND_alarm, key_IO_CACHE_SHARE_cond,
+PSI_cond_key key_COND_alarm, key_COND_timer, key_IO_CACHE_SHARE_cond,
key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend,
key_THR_COND_threads, key_WT_RESOURCE_cond;
static PSI_cond_info all_mysys_conds[]=
{
{ &key_COND_alarm, "COND_alarm", PSI_FLAG_GLOBAL},
+ { &key_COND_timer, "COND_timer", PSI_FLAG_GLOBAL},
{ &key_IO_CACHE_SHARE_cond, "IO_CACHE_SHARE::cond", 0},
{ &key_IO_CACHE_SHARE_cond_writer, "IO_CACHE_SHARE::cond_writer", 0},
{ &key_my_thread_var_suspend, "my_thread_var::suspend", 0},
@@ -512,12 +515,17 @@ static PSI_rwlock_info all_mysys_rwlocks[]=
#ifdef USE_ALARM_THREAD
PSI_thread_key key_thread_alarm;
+#endif
+PSI_thread_key key_thread_timer;
static PSI_thread_info all_mysys_threads[]=
{
- { &key_thread_alarm, "alarm", PSI_FLAG_GLOBAL}
+#ifdef USE_ALARM_THREAD
+ { &key_thread_alarm, "alarm", PSI_FLAG_GLOBAL},
+#endif
+ { &key_thread_timer, "statement_timer", PSI_FLAG_GLOBAL}
};
-#endif /* USE_ALARM_THREAD */
+
#ifdef HUGETLB_USE_PROC_MEMINFO
PSI_file_key key_file_proc_meminfo;
@@ -552,10 +560,8 @@ void my_init_mysys_psi_keys()
count= sizeof(all_mysys_rwlocks)/sizeof(all_mysys_rwlocks[0]);
mysql_rwlock_register(category, all_mysys_rwlocks, count);
-#ifdef USE_ALARM_THREAD
count= sizeof(all_mysys_threads)/sizeof(all_mysys_threads[0]);
mysql_thread_register(category, all_mysys_threads, count);
-#endif /* USE_ALARM_THREAD */
count= sizeof(all_mysys_files)/sizeof(all_mysys_files[0]);
mysql_file_register(category, all_mysys_files, count);
diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h
index 80c6a981db2..9b94a5a18ce 100644
--- a/mysys/mysys_priv.h
+++ b/mysys/mysys_priv.h
@@ -42,16 +42,16 @@ extern PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock,
key_THR_LOCK_lock, key_THR_LOCK_malloc,
key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net,
key_THR_LOCK_open, key_THR_LOCK_threads, key_LOCK_uuid_generator,
- key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap;
+ key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap, key_LOCK_timer;
-extern PSI_cond_key key_COND_alarm, key_IO_CACHE_SHARE_cond,
+extern PSI_cond_key key_COND_alarm, key_COND_timer, key_IO_CACHE_SHARE_cond,
key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend,
key_THR_COND_threads;
#ifdef USE_ALARM_THREAD
extern PSI_thread_key key_thread_alarm;
#endif /* USE_ALARM_THREAD */
-
+extern PSI_thread_key key_thread_timer;
extern PSI_rwlock_key key_SAFEHASH_mutex;
#endif /* HAVE_PSI_INTERFACE */
diff --git a/mysys/thr_timer.c b/mysys/thr_timer.c
new file mode 100644
index 00000000000..6414ee6f246
--- /dev/null
+++ b/mysys/thr_timer.c
@@ -0,0 +1,589 @@
+/*
+ Copyright (c) 2012 Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 or later of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+/*
+ Implementation if OS independent timers.
+ This is done based on pthread primitives, especially pthread_cond_timedwait()
+*/
+
+#include "mysys_priv.h"
+#include "thr_timer.h"
+#include <m_string.h>
+#include <queues.h>
+#ifdef HAVE_TIMER_CREATE
+#include <sys/syscall.h>
+#endif
+
+enum thread_state
+{
+ NOT_RUNNING= -1, RUNNING= 0, ABORTING=1
+};
+
+static enum thread_state timer_thread_state= NOT_RUNNING;
+
+volatile my_bool timer_thread_running= 0;
+struct timespec next_timer_expire_time;
+
+static my_bool thr_timer_inited= 0;
+static mysql_mutex_t LOCK_timer;
+static mysql_cond_t COND_timer;
+static QUEUE timer_queue;
+pthread_t timer_thread;
+
+#define set_max_time(abs_time) \
+ { (abs_time)->MY_tv_sec= INT_MAX32; (abs_time)->MY_tv_nsec= 0; }
+
+
+static void *timer_handler(void *arg __attribute__((unused)));
+
+/*
+ Compare two timespecs
+*/
+
+static int compare_timespec(void *not_used __attribute__((unused)),
+ uchar *a_ptr, uchar *b_ptr)
+{
+ return cmp_timespec((*(struct timespec*) a_ptr),
+ (*(struct timespec*) b_ptr));
+}
+
+
+/**
+ Initialize timer variables and create timer thread
+
+ @param alloc_timers Init allocation of timers. Will be autoextended
+ if needed
+ @return 0 ok
+ @return 1 error; Can't create thread
+*/
+
+static thr_timer_t max_timer_data;
+
+my_bool init_thr_timer(uint alloc_timers)
+{
+ pthread_attr_t thr_attr;
+ my_bool res;
+ DBUG_ENTER("init_thr_timer");
+
+ init_queue(&timer_queue, alloc_timers+2, offsetof(thr_timer_t,expire_time),
+ 0, compare_timespec, NullS,
+ offsetof(thr_timer_t, index_in_queue)+1, 1);
+ mysql_mutex_init(key_LOCK_timer, &LOCK_timer, MY_MUTEX_INIT_FAST);
+ mysql_cond_init(key_COND_timer, &COND_timer, NULL);
+
+ /* Set dummy element with max time into the queue to simplify usage */
+ bzero(&max_timer_data, sizeof(max_timer_data));
+ set_max_time(&max_timer_data.expire_time);
+ queue_insert(&timer_queue, (uchar*) &max_timer_data);
+ next_timer_expire_time= max_timer_data.expire_time;
+
+ /* Create a thread to handle timers */
+ pthread_attr_init(&thr_attr);
+ pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
+ pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
+ pthread_attr_setstacksize(&thr_attr,8196);
+ res= mysql_thread_create(key_thread_timer,
+ &timer_thread, &thr_attr, timer_handler, NULL) != 0;
+ pthread_attr_destroy(&thr_attr);
+
+ thr_timer_inited= 1;
+ DBUG_RETURN(res);
+}
+
+
+void end_thr_timer(void)
+{
+ struct timespec abstime;
+ DBUG_ENTER("end_thr_timer");
+
+ if (!thr_timer_inited)
+ DBUG_VOID_RETURN;
+
+ mysql_mutex_lock(&LOCK_timer);
+ timer_thread_state= ABORTING; /* Signal abort */
+ mysql_cond_signal(&COND_timer);
+
+ /* Wait until timer thread dies */
+ set_timespec(abstime, 10*1000); /* Wait up to 10 seconds */
+ while (timer_thread_state == ABORTING)
+ {
+ int error= mysql_cond_timedwait(&COND_timer, &LOCK_timer, &abstime);
+ if (error == ETIME || error == ETIMEDOUT)
+ break; /* Don't wait forever */
+ }
+ mysql_mutex_unlock(&LOCK_timer);
+ if (timer_thread_state == NOT_RUNNING)
+ {
+ mysql_mutex_destroy(&LOCK_timer);
+ mysql_cond_destroy(&COND_timer);
+ delete_queue(&timer_queue);
+ thr_timer_inited= 0;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Initialize a timer object
+
+ @param timer_data Timer structure
+ @param function Function to be called when getting timeout
+ @param argument Argument for function
+*/
+
+void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*),
+ void *arg)
+{
+ DBUG_ENTER("thr_timer_init");
+ bzero(timer_data, sizeof(*timer_data));
+ timer_data->func= function;
+ timer_data->func_arg= arg;
+ timer_data->expired= 1; /* Not active */
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Request timer after X milliseconds
+
+ SYNOPSIS
+ thr_timer()
+ timer_data Pointer to timer structure
+ micro_seconds; Number of microseconds until timer
+
+ RETURN VALUES
+ 0 ok
+ 1 If no more timers are allowed (aborted by process)
+
+ Stores in first argument a pointer to a non-zero int which is set to 0
+ when the timer has been given
+*/
+
+my_bool thr_timer_settime(thr_timer_t *timer_data, ulonglong micro_seconds)
+{
+ int reschedule;
+ DBUG_ENTER("thr_timer_settime");
+ DBUG_PRINT("enter",("thread: %s micro_seconds: %llu",my_thread_name(),
+ micro_seconds));
+
+ DBUG_ASSERT(timer_data->expired == 1);
+
+ set_timespec_nsec(timer_data->expire_time, micro_seconds*1000);
+ timer_data->expired= 0;
+
+ mysql_mutex_lock(&LOCK_timer); /* Lock from threads & timers */
+ if (queue_insert_safe(&timer_queue,(uchar*) timer_data))
+ {
+ DBUG_PRINT("info", ("timer queue full"));
+ fprintf(stderr,"Warning: thr_timer queue is full\n");
+ timer_data->expired= 1;
+ mysql_mutex_unlock(&LOCK_timer);
+ DBUG_RETURN(1);
+ }
+
+ /* Reschedule timer if the current one has more time left than new one */
+ reschedule= cmp_timespec(next_timer_expire_time, timer_data->expire_time);
+ mysql_mutex_unlock(&LOCK_timer);
+ if (reschedule > 0)
+ {
+#if defined(MAIN)
+ printf("reschedule\n"); fflush(stdout);
+#endif
+ DBUG_PRINT("info", ("reschedule"));
+ mysql_cond_signal(&COND_timer);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Remove timer from list of timers
+
+ notes: Timer will be marked as expired
+*/
+
+void thr_timer_end(thr_timer_t *timer_data)
+{
+ DBUG_ENTER("thr_timer_end");
+
+ mysql_mutex_lock(&LOCK_timer);
+ if (!timer_data->expired)
+ {
+ DBUG_ASSERT(timer_data->index_in_queue != 0);
+ DBUG_ASSERT(queue_element(&timer_queue, timer_data->index_in_queue) ==
+ (uchar*) timer_data);
+ queue_remove(&timer_queue, timer_data->index_in_queue);
+ /* Mark as expired for asserts to work */
+ timer_data->expired= 1;
+ }
+ mysql_mutex_unlock(&LOCK_timer);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Come here when some timer in queue is due.
+*/
+
+static sig_handler process_timers(struct timespec *now)
+{
+ thr_timer_t *timer_data;
+ DBUG_ENTER("process_timers");
+ DBUG_PRINT("info",("active timers: %d", timer_queue.elements - 1));
+
+#if defined(MAIN)
+ printf("process_timer\n"); fflush(stdout);
+#endif
+
+ /* We can safely remove the first one as it has already expired */
+ for (;;)
+ {
+ void (*function)(void*);
+ void *func_arg;
+
+ timer_data= (thr_timer_t*) queue_top(&timer_queue);
+ function= timer_data->func;
+ func_arg= timer_data->func_arg;
+ timer_data->expired= 1; /* Mark expired */
+ /*
+ We remove timer before calling timer function to allow thread to
+ delete it's timer data any time.
+ */
+ queue_remove_top(&timer_queue); /* Remove timer */
+ (*function)(func_arg); /* Inform thread of timeout */
+
+ /* Check if next one has also expired */
+ timer_data= (thr_timer_t*) queue_top(&timer_queue);
+ if (cmp_timespec(timer_data->expire_time, (*now)) > 0)
+ break; /* All data processed */
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ set up a timer thread to handle timeouts
+ This will be killed when timer_thread_state is set to ABORTING.
+ At end timer_aborted will be set to NOT_RUNNING
+*/
+
+static void *timer_handler(void *arg __attribute__((unused)))
+{
+ my_thread_init();
+
+ timer_thread_state= RUNNING;
+
+ mysql_mutex_lock(&LOCK_timer);
+ while (likely(timer_thread_state == RUNNING))
+ {
+ int error;
+ struct timespec *top_time;
+ struct timespec now, abstime;
+
+ set_timespec(now, 0);
+
+ top_time= &(((thr_timer_t*) queue_top(&timer_queue))->expire_time);
+
+ if (cmp_timespec((*top_time), now) <= 0)
+ {
+ process_timers(&now);
+ top_time= &(((thr_timer_t*) queue_top(&timer_queue))->expire_time);
+ }
+
+ abstime= *top_time;
+ next_timer_expire_time= *top_time;
+ if ((error= mysql_cond_timedwait(&COND_timer, &LOCK_timer, &abstime)) &&
+ error != ETIME && error != ETIMEDOUT)
+ {
+#ifdef MAIN
+ printf("Got error: %d from ptread_cond_timedwait (errno: %d)\n",
+ error,errno);
+#endif
+ }
+ }
+ timer_thread_state= NOT_RUNNING; /* Mark thread ended */
+ mysql_cond_signal(&COND_timer); /* signal end_thr_timer() */
+ mysql_mutex_unlock(&LOCK_timer);
+ my_thread_end();
+ pthread_exit(0);
+ return 0; /* Impossible */
+}
+
+
+/****************************************************************************
+ Testing of thr_timer (when compiled with -DMAIN)
+***************************************************************************/
+
+#ifdef MAIN
+
+static mysql_cond_t COND_thread_count;
+static mysql_mutex_t LOCK_thread_count;
+static uint thread_count, benchmark_runs, test_to_run= 1;
+
+static void send_signal(void *arg)
+{
+ struct st_my_thread_var *current_my_thread_var= arg;
+#if defined(MAIN)
+ printf("sending signal\n"); fflush(stdout);
+#endif
+ mysql_mutex_lock(&current_my_thread_var->mutex);
+ mysql_cond_signal(&current_my_thread_var->suspend);
+ mysql_mutex_unlock(&current_my_thread_var->mutex);
+}
+
+
+static void run_thread_test(int param)
+{
+ int i,wait_time,retry;
+ my_hrtime_t start_time;
+ thr_timer_t timer_data;
+ struct st_my_thread_var *current_my_thread_var;
+ DBUG_ENTER("run_thread_test");
+
+ current_my_thread_var= my_thread_var;
+ thr_timer_init(&timer_data, send_signal, current_my_thread_var);
+
+ for (i=1 ; i <= 10 ; i++)
+ {
+ wait_time=param ? 11-i : i;
+ start_time= my_hrtime();
+
+ mysql_mutex_lock(&current_my_thread_var->mutex);
+ if (thr_timer_settime(&timer_data, wait_time * 1000000))
+ {
+ printf("Thread: %s timers aborted\n",my_thread_name());
+ break;
+ }
+ if (wait_time == 3)
+ {
+ printf("Thread: %s Simulation of no timer needed\n",my_thread_name());
+ fflush(stdout);
+ }
+ else
+ {
+ for (retry=0 ; !timer_data.expired && retry < 10 ; retry++)
+ {
+ printf("Thread: %s Waiting %d sec\n",my_thread_name(),wait_time);
+ mysql_cond_wait(&current_my_thread_var->suspend,
+ &current_my_thread_var->mutex);
+
+ }
+ if (!timer_data.expired)
+ {
+ printf("Thread: %s didn't get an timer. Aborting!\n",
+ my_thread_name());
+ break;
+ }
+ }
+ mysql_mutex_unlock(&current_my_thread_var->mutex);
+ printf("Thread: %s Slept for %g (%d) sec\n",my_thread_name(),
+ (int) (my_hrtime().val-start_time.val)/1000000.0, wait_time);
+ fflush(stdout);
+ thr_timer_end(&timer_data);
+ fflush(stdout);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+static void run_thread_benchmark(int param)
+{
+ int i;
+ struct st_my_thread_var *current_my_thread_var;
+ thr_timer_t timer_data;
+ DBUG_ENTER("run_thread_benchmark");
+
+ current_my_thread_var= my_thread_var;
+ thr_timer_init(&timer_data, send_signal, current_my_thread_var);
+
+ for (i=1 ; i <= param ; i++)
+ {
+ if (thr_timer_settime(&timer_data, 1000000))
+ {
+ printf("Thread: %s timers aborted\n",my_thread_name());
+ break;
+ }
+ thr_timer_end(&timer_data);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+#ifdef HAVE_TIMER_CREATE
+
+/* Test for benchmarking posix timers against thr_timer */
+
+#ifndef sigev_notify_thread_id
+#define sigev_notify_thread_id _sigev_un._tid
+#endif
+
+static void run_timer_benchmark(int param)
+{
+ int i;
+ timer_t timerid;
+ struct sigevent sigev;
+ pid_t thread_id= (pid_t) syscall(SYS_gettid);
+ DBUG_ENTER("run_timer_benchmark");
+
+ /* Setup a signal that will never be signaled */
+ sigev.sigev_value.sival_ptr= 0;
+ sigev.sigev_signo= SIGRTMIN; /* First free signal */
+ sigev.sigev_notify= SIGEV_SIGNAL | SIGEV_THREAD_ID;
+ sigev.sigev_notify_thread_id= thread_id;
+
+ if (timer_create(CLOCK_MONOTONIC, &sigev, &timerid))
+ {
+ printf("Could not create timer\n");
+ exit(1);
+ }
+
+ for (i=1 ; i <= param ; i++)
+ {
+ struct itimerspec abstime;
+ abstime.it_interval.tv_sec= 0;
+ abstime.it_interval.tv_nsec= 0;
+ abstime.it_value.tv_sec= 1;
+ abstime.it_value.tv_nsec= 0;
+
+ if (timer_settime(timerid, 0, &abstime, NULL))
+ {
+ printf("Thread: %s timers aborted\n",my_thread_name());
+ break;
+ }
+ abstime.it_interval.tv_sec= 0;
+ abstime.it_interval.tv_nsec= 0;
+ abstime.it_value.tv_sec= 0;
+ abstime.it_value.tv_nsec= 0;
+ timer_settime(timerid, 0, &abstime, NULL);
+ }
+ timer_delete(timerid);
+ DBUG_VOID_RETURN;
+}
+#endif /* HAVE_TIMER_CREATE */
+
+
+static void *start_thread(void *arg)
+{
+ my_thread_init();
+ printf("Thread %d (%s) started\n",*((int*) arg),my_thread_name());
+ fflush(stdout);
+
+ switch (test_to_run) {
+ case 1:
+ run_thread_test(*((int*) arg));
+ break;
+ case 2:
+ run_thread_benchmark(benchmark_runs);
+ break;
+ case 3:
+#ifdef HAVE_TIMER_CREATE
+ run_timer_benchmark(benchmark_runs);
+#endif
+ break;
+ }
+ free((uchar*) arg);
+ mysql_mutex_lock(&LOCK_thread_count);
+ thread_count--;
+ mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */
+ mysql_mutex_unlock(&LOCK_thread_count);
+ my_thread_end();
+ return 0;
+}
+
+
+/* Start a lot of threads that will run with timers */
+
+static void run_test()
+{
+ pthread_t tid;
+ pthread_attr_t thr_attr;
+ int i,*param,error;
+ DBUG_ENTER("run_test");
+
+ if (init_thr_timer(5))
+ {
+ printf("Can't initialize timers\n");
+ exit(1);
+ }
+
+ mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
+ mysql_cond_init(0, &COND_thread_count, NULL);
+
+ thr_setconcurrency(3);
+ pthread_attr_init(&thr_attr);
+ pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
+ printf("Main thread: %s\n",my_thread_name());
+ for (i=0 ; i < 2 ; i++)
+ {
+ param=(int*) malloc(sizeof(int));
+ *param= i;
+ mysql_mutex_lock(&LOCK_thread_count);
+ if ((error= mysql_thread_create(0,
+ &tid, &thr_attr, start_thread,
+ (void*) param)))
+ {
+ printf("Can't create thread %d, error: %d\n",i,error);
+ exit(1);
+ }
+ thread_count++;
+ mysql_mutex_unlock(&LOCK_thread_count);
+ }
+
+ pthread_attr_destroy(&thr_attr);
+ mysql_mutex_lock(&LOCK_thread_count);
+ while (thread_count)
+ {
+ mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
+ }
+ mysql_mutex_unlock(&LOCK_thread_count);
+ DBUG_ASSERT(timer_queue.elements == 1);
+ end_thr_timer();
+ printf("Test succeeded\n");
+ DBUG_VOID_RETURN;
+}
+
+
+int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
+{
+ MY_INIT(argv[0]);
+
+ if (argc > 1 && argv[1][0] == '-')
+ {
+ switch (argv[1][1]) {
+ case '#':
+ test_to_run= 1;
+ DBUG_PUSH(argv[1]+2);
+ break;
+ case 'b':
+ test_to_run= 2;
+ benchmark_runs= atoi(argv[1]+2);
+ break;
+ case 't':
+ test_to_run= 3;
+ benchmark_runs= atoi(argv[1]+2);
+ break;
+ }
+ }
+ if (!benchmark_runs)
+ benchmark_runs= 1000000;
+
+ run_test();
+ my_end(1);
+ return 0;
+}
+
+#endif /* MAIN */
diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql
index a148e191204..faad08ab6d9 100644
--- a/scripts/mysql_system_tables.sql
+++ b/scripts/mysql_system_tables.sql
@@ -33,7 +33,7 @@ set @had_db_table= @@warning_count != 0;
CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges';
-CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) DEFAULT 0 NOT NULL, plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, authentication_string TEXT NOT NULL, password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, default_role char(80) binary DEFAULT '' NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
+CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) DEFAULT 0 NOT NULL, plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, authentication_string TEXT NOT NULL, password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, default_role char(80) binary DEFAULT '' NOT NULL, max_statement_time decimal(12,6) DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
-- Remember for later if user table already existed
set @had_user_table= @@warning_count != 0;
@@ -80,7 +80,7 @@ CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsign
CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
-CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
+CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob NOT NULL, body longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures';
CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql
index 46c96ef4bb1..075aafd5e3b 100644
--- a/scripts/mysql_system_tables_data.sql
+++ b/scripts/mysql_system_tables_data.sql
@@ -39,10 +39,10 @@ DROP TABLE tmp_db;
-- Fill "user" table with default users allowing root access
-- from local machine if "user" table didn't exist before
CREATE TEMPORARY TABLE tmp_user LIKE user;
-INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N', 'N','');
-REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','' FROM dual WHERE @current_hostname != 'localhost';
-REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N', '');
-REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N', '');
+INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N', 'N','', 0);
+REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0 FROM dual WHERE @current_hostname != 'localhost';
+REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0);
+REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N', '', 0);
INSERT INTO tmp_user (host,user) VALUES ('localhost','');
INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE @current_hostname != 'localhost';
INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0;
diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql
index 3ec2d94673a..96e4103b5bd 100644
--- a/scripts/mysql_system_tables_fix.sql
+++ b/scripts/mysql_system_tables_fix.sql
@@ -632,6 +632,7 @@ ALTER TABLE user ADD plugin char(64) DEFAULT '', ADD authentication_string TEXT
ALTER TABLE user ADD password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL;
ALTER TABLE user ADD is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL;
ALTER TABLE user ADD default_role char(80) binary DEFAULT '' NOT NULL;
+ALTER TABLE user ADD max_statement_time decimal(12,6) DEFAULT 0 NOT NULL;
ALTER TABLE user MODIFY plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, MODIFY authentication_string TEXT NOT NULL;
-- Somewhere above, we ran ALTER TABLE user .... CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin.
-- we want password_expired column to have collation utf8_general_ci.
diff --git a/sql/lex.h b/sql/lex.h
index 10a52160cf0..affb8032193 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -363,6 +363,7 @@ static SYMBOL symbols[] = {
{ "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR)},
{ "MAX_ROWS", SYM(MAX_ROWS)},
{ "MAX_SIZE", SYM(MAX_SIZE_SYM)},
+ { "MAX_STATEMENT_TIME", SYM(MAX_STATEMENT_TIME_SYM)},
{ "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR)},
{ "MAX_USER_CONNECTIONS", SYM(MAX_USER_CONNECTIONS_SYM)},
{ "MAXVALUE", SYM(MAX_VALUE_SYM)},
diff --git a/sql/log_event.cc b/sql/log_event.cc
index ee35acadd9b..e5183b208b2 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -473,6 +473,7 @@ inline bool unexpected_error_code(int unexpected_error)
case ER_NET_READ_ERROR:
case ER_NET_ERROR_ON_WRITE:
case ER_QUERY_INTERRUPTED:
+ case ER_STATEMENT_TIMEOUT:
case ER_CONNECTION_KILLED:
case ER_SERVER_SHUTDOWN:
case ER_NEW_ABORTING_CONNECTION:
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 899140f7d71..ec5f66cac45 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -2106,6 +2106,9 @@ void clean_up(bool print_message)
sp_cache_end();
free_status_vars();
end_thr_alarm(1); /* Free allocated memory */
+#ifndef EMBEDDED_LIBRARY
+ end_thr_timer();
+#endif
my_free_open_file_info();
if (defaults_argv)
free_defaults(defaults_argv);
@@ -4746,6 +4749,14 @@ static int init_server_components()
my_rnd_init(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
setup_fpu();
init_thr_lock();
+#ifndef EMBEDDED_LIBRARY
+ if (init_thr_timer(thread_scheduler->max_threads + extra_max_connections))
+ {
+ fprintf(stderr, "Can't initialize timers\n");
+ unireg_abort(1);
+ }
+#endif
+
my_uuid_init((ulong) (my_rnd(&sql_rand))*12345,12345);
#ifdef HAVE_REPLICATION
init_slave_list();
@@ -5361,9 +5372,6 @@ int mysqld_main(int argc, char **argv)
}
#endif
- if (WSREP_ON)
- wsrep_filter_new_cluster (&argc, argv);
-
orig_argc= argc;
orig_argv= argv;
my_getopt_use_args_separator= TRUE;
@@ -7341,6 +7349,13 @@ struct my_option my_long_options[]=
{"table_cache", 0, "Deprecated; use --table-open-cache instead.",
&tc_size, &tc_size, 0, GET_ULONG,
REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
+#ifdef WITH_WSREP
+ {"wsrep-new-cluster", 0, "Bootstrap a cluster. It works by overriding the "
+ "current value of wsrep_cluster_address. It is recommended not to add this "
+ "option to the config file as this will trigger bootstrap on every server "
+ "start.", &wsrep_new_cluster, &wsrep_new_cluster, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
+#endif
/* The following options exist in 5.6 but not in 10.0 */
MYSQL_TO_BE_IMPLEMENTED_OPTION("default-tmp-storage-engine"),
@@ -8073,6 +8088,7 @@ SHOW_VAR status_vars[]= {
{"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
{"Key", (char*) &show_default_keycache, SHOW_FUNC},
{"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
+ {"max_statement_time_exceeded", (char*) offsetof(STATUS_VAR, max_statement_time_exceeded), SHOW_LONG_STATUS},
{"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
{"Memory_used", (char*) offsetof(STATUS_VAR, memory_used), SHOW_LONGLONG_STATUS},
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH},
@@ -9141,7 +9157,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr)
debug_assert_if_crashed_table= 1;
global_system_variables.long_query_time= (ulonglong)
- (global_system_variables.long_query_time_double * 1e6);
+ (global_system_variables.long_query_time_double * 1e6 + 0.1);
+ global_system_variables.max_statement_time= (ulonglong)
+ (global_system_variables.max_statement_time_double * 1e6 + 0.1);
if (opt_short_log_format)
opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 32cdbe138b2..7042669a363 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7110,3 +7110,5 @@ ER_IT_IS_A_VIEW 42S02
eng "'%-.192s' is a view"
ER_SLAVE_SKIP_NOT_IN_GTID
eng "When using GTID, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position."
+ER_STATEMENT_TIMEOUT 70100
+ eng "Query execution was interrupted (max_statement_time exceeded)"
diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc
index 3fadbcd088f..61e2830e82e 100644
--- a/sql/signal_handler.cc
+++ b/sql/signal_handler.cc
@@ -172,6 +172,10 @@ extern "C" sig_handler handle_fatal_signal(int sig)
case KILL_QUERY_HARD:
kreason= "KILL_QUERY";
break;
+ case KILL_TIMEOUT:
+ case KILL_TIMEOUT_HARD:
+ kreason= "KILL_TIMEOUT";
+ break;
case KILL_SYSTEM_THREAD:
case KILL_SYSTEM_THREAD_HARD:
kreason= "KILL_SYSTEM_THREAD";
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 5e30b148ad7..8e976f0f579 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -211,8 +211,10 @@ static char *safe_str(char *str)
static const char *safe_str(const char *str)
{ return str ? str : ""; }
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
static size_t safe_strlen(const char *str)
{ return str ? strlen(str) : 0; }
+#endif
/* Classes */
@@ -709,6 +711,8 @@ bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, char *username,
#define ROLE_ASSIGN_COLUMN_IDX 43
#define DEFAULT_ROLE_COLUMN_IDX 44
+#define MAX_STATEMENT_TIME_COLUMN_IDX 45
+
/* various flags valid for ACL_USER */
#define IS_ROLE (1L << 0)
/* Flag to mark that a ROLE is on the recursive DEPTH_FIRST_SEARCH stack */
@@ -1272,6 +1276,8 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
user.sort= get_sort(2, user.host.hostname, user.user.str);
user.hostname_length= safe_strlen(user.host.hostname);
+ user.user_resource.user_conn= 0;
+ user.user_resource.max_statement_time= 0.0;
/* Starting from 4.0.2 we have more fields */
if (table->s->fields >= 31)
@@ -1331,6 +1337,14 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
fix_user_plugin_ptr(&user);
}
}
+
+ if (table->s->fields > MAX_STATEMENT_TIME_COLUMN_IDX)
+ {
+ /* Starting from 10.1.1 we can have max_statement_time */
+ ptr= get_field(thd->mem_root,
+ table->field[MAX_STATEMENT_TIME_COLUMN_IDX]);
+ user.user_resource.max_statement_time= ptr ? atof(ptr) : 0.0;
+ }
}
else
{
@@ -2041,6 +2055,8 @@ static void acl_update_user(const char *user, const char *host,
acl_user->user_resource.conn_per_hour= mqh->conn_per_hour;
if (mqh->specified_limits & USER_RESOURCES::USER_CONNECTIONS)
acl_user->user_resource.user_conn= mqh->user_conn;
+ if (mqh->specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME)
+ acl_user->user_resource.max_statement_time= mqh->max_statement_time;
if (ssl_type != SSL_TYPE_NOT_SPECIFIED)
{
acl_user->ssl_type= ssl_type;
@@ -3393,8 +3409,6 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo,
if (table->s->fields >= 36 &&
(mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS))
table->field[next_field+3]->store((longlong) mqh.user_conn, FALSE);
- mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour;
-
next_field+= 4;
if (table->s->fields >= 41)
{
@@ -3415,7 +3429,16 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo,
table->field[next_field]->reset();
table->field[next_field + 1]->reset();
}
+
+ if (table->s->fields > MAX_STATEMENT_TIME_COLUMN_IDX)
+ {
+ if (mqh.specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME)
+ table->field[MAX_STATEMENT_TIME_COLUMN_IDX]->
+ store(mqh.max_statement_time);
+ }
}
+ mqh_used= (mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour ||
+ mqh.user_conn || mqh.max_statement_time != 0.0);
/* table format checked earlier */
if (handle_as_role)
@@ -7508,6 +7531,21 @@ static void add_user_option(String *grant, long value, const char *name,
}
}
+
+static void add_user_option(String *grant, double value, const char *name)
+{
+ if (value != 0.0 )
+ {
+ char buff[FLOATING_POINT_BUFFER];
+ size_t len;
+ grant->append(' ');
+ grant->append(name, strlen(name));
+ grant->append(' ');
+ len= my_fcvt(value, 6, buff, NULL);
+ grant->append(buff, len);
+ }
+}
+
static const char *command_array[]=
{
"SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "RELOAD",
@@ -7890,7 +7928,8 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry,
(acl_user->user_resource.questions ||
acl_user->user_resource.updates ||
acl_user->user_resource.conn_per_hour ||
- acl_user->user_resource.user_conn))
+ acl_user->user_resource.user_conn ||
+ acl_user->user_resource.max_statement_time != 0.0))
{
global.append(STRING_WITH_LEN(" WITH"));
if (want_access & GRANT_ACL)
@@ -7903,6 +7942,8 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry,
"MAX_CONNECTIONS_PER_HOUR", false);
add_user_option(&global, acl_user->user_resource.user_conn,
"MAX_USER_CONNECTIONS", true);
+ add_user_option(&global, acl_user->user_resource.max_statement_time,
+ "MAX_STATEMENT_TIME");
}
}
@@ -12232,12 +12273,22 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
if ((acl_user->user_resource.questions ||
acl_user->user_resource.updates ||
acl_user->user_resource.conn_per_hour ||
- acl_user->user_resource.user_conn || max_user_connections_checking) &&
+ acl_user->user_resource.user_conn ||
+ acl_user->user_resource.max_statement_time != 0.0 ||
+ max_user_connections_checking) &&
get_or_create_user_conn(thd,
(opt_old_style_user_limits ? sctx->user : sctx->priv_user),
(opt_old_style_user_limits ? sctx->host_or_ip : sctx->priv_host),
&acl_user->user_resource))
DBUG_RETURN(1); // The error is set by get_or_create_user_conn()
+
+ if (acl_user->user_resource.max_statement_time != 0.0)
+ {
+ thd->variables.max_statement_time_double=
+ acl_user->user_resource.max_statement_time;
+ thd->variables.max_statement_time=
+ (thd->variables.max_statement_time_double * 1e6 + 0.1);
+ }
}
else
sctx->skip_grants();
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index dde0a9a2f7a..9b899464c4b 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -861,6 +861,23 @@ bool Drop_table_error_handler::handle_condition(THD *thd,
}
+/**
+ Send timeout to thread.
+
+ Note that this is always safe as the thread will always remove it's
+ timeouts at end of query (and thus before THD is destroyed)
+*/
+
+extern "C" void thd_kill_timeout(THD* thd)
+{
+ thd->status_var.max_statement_time_exceeded++;
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ /* Kill queries that can't cause data corruptions */
+ thd->awake(KILL_TIMEOUT);
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+}
+
+
THD::THD(bool is_wsrep_applier)
:Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
/* statement id */ 0),
@@ -1058,6 +1075,8 @@ THD::THD(bool is_wsrep_applier)
protocol_text.init(this);
protocol_binary.init(this);
+ thr_timer_init(&query_timer, (void (*)(void*)) thd_kill_timeout, this);
+
tablespace_op=FALSE;
/*
@@ -1373,6 +1392,7 @@ extern "C" THD *_current_thd_noinline(void)
return my_pthread_getspecific_ptr(THD*,THR_THD);
}
#endif
+
/*
Init common variables that has to be reset on start and on change_user
*/
@@ -1779,6 +1799,7 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
This is normally called from another thread's THD object.
@note Do always call this while holding LOCK_thd_data.
+ NOT_KILLED is used to awake a thread for a slave
*/
void THD::awake(killed_state state_to_set)
@@ -1790,6 +1811,13 @@ void THD::awake(killed_state state_to_set)
print_aborted_warning(3, "KILLED");
+ /*
+ Don't degrade killed state, for example from a KILL_CONNECTION to
+ STATEMENT TIMEOUT
+ */
+ if (killed >= KILL_CONNECTION)
+ state_to_set= killed;
+
/* Set the 'killed' flag of 'this', which is the target THD object. */
killed= state_to_set;
@@ -1821,6 +1849,7 @@ void THD::awake(killed_state state_to_set)
mysql_mutex_lock(&mysys_var->mutex);
if (!system_thread) // Don't abort locks
mysys_var->abort=1;
+
/*
This broadcast could be up in the air if the victim thread
exits the cond in the time between read and broadcast, but that is
@@ -1989,6 +2018,9 @@ int killed_errno(killed_state killed)
case KILL_QUERY:
case KILL_QUERY_HARD:
DBUG_RETURN(ER_QUERY_INTERRUPTED);
+ case KILL_TIMEOUT:
+ case KILL_TIMEOUT_HARD:
+ DBUG_RETURN(ER_STATEMENT_TIMEOUT);
case KILL_SERVER:
case KILL_SERVER_HARD:
DBUG_RETURN(ER_SERVER_SHUTDOWN);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index cab2968a62b..4ba2901d0cc 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -37,6 +37,7 @@
#include "violite.h" /* vio_is_connected */
#include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA,
THR_LOCK_INFO */
+#include "thr_timer.h"
#include <mysql/psi/mysql_stage.h>
#include <mysql/psi/mysql_statement.h>
#include <mysql/psi/mysql_idle.h>
@@ -449,17 +450,19 @@ enum killed_state
*/
ABORT_QUERY= 6,
ABORT_QUERY_HARD= 7,
+ KILL_TIMEOUT= 8,
+ KILL_TIMEOUT_HARD= 9,
/*
All of the following killed states will kill the connection
KILL_CONNECTION must be the first of these and it must start with
an even number (becasue of HARD bit)!
*/
- KILL_CONNECTION= 8,
- KILL_CONNECTION_HARD= 9,
- KILL_SYSTEM_THREAD= 10,
- KILL_SYSTEM_THREAD_HARD= 11,
- KILL_SERVER= 12,
- KILL_SERVER_HARD= 13
+ KILL_CONNECTION= 10,
+ KILL_CONNECTION_HARD= 11,
+ KILL_SYSTEM_THREAD= 12,
+ KILL_SYSTEM_THREAD_HARD= 13,
+ KILL_SERVER= 14,
+ KILL_SERVER_HARD= 15
};
extern int killed_errno(killed_state killed);
@@ -508,6 +511,7 @@ typedef struct system_variables
ulonglong max_heap_table_size;
ulonglong tmp_table_size;
ulonglong long_query_time;
+ ulonglong max_statement_time;
ulonglong optimizer_switch;
sql_mode_t sql_mode; ///< which non-standard SQL behaviour should be enabled
sql_mode_t old_behavior; ///< which old SQL behaviour should be enabled
@@ -644,8 +648,7 @@ typedef struct system_variables
my_bool wsrep_causal_reads;
uint wsrep_sync_wait;
ulong wsrep_retry_autocommit;
-
- double long_query_time_double;
+ double long_query_time_double, max_statement_time_double;
my_bool pseudo_slave_mode;
@@ -734,6 +737,7 @@ typedef struct system_status_var
ulong empty_queries;
ulong access_denied_errors;
ulong lost_connections;
+ ulong max_statement_time_exceeded;
/*
Number of statements sent from the client
*/
@@ -3779,6 +3783,34 @@ public:
void* wsrep_apply_format;
char wsrep_info[128]; /* string for dynamic proc info */
#endif /* WITH_WSREP */
+
+ /* Handling of timeouts for commands */
+ thr_timer_t query_timer;
+public:
+ void set_query_timer()
+ {
+#ifndef EMBEDDED_LIBRARY
+ /*
+ Don't start a query timer if
+ - If timeouts are not set
+ - if we are in a stored procedure or sub statement
+ - If this is a slave thread
+ - If we already have set a timeout (happens when running prepared
+ statements that calls mysql_execute_command())
+ */
+ if (!variables.max_statement_time || spcont || in_sub_stmt ||
+ slave_thread || query_timer.expired == 0)
+ return;
+ thr_timer_settime(&query_timer, variables.max_statement_time);
+#endif
+ }
+ void reset_query_timer()
+ {
+#ifndef EMBEDDED_LIBRARY
+ if (!query_timer.expired)
+ thr_timer_end(&query_timer);
+#endif
+ }
};
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 0065edcc14d..89a90f41697 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -101,7 +101,6 @@ int get_or_create_user_conn(THD *thd, const char *user,
end:
mysql_mutex_unlock(&LOCK_user_conn);
return return_val;
-
}
@@ -437,6 +436,7 @@ void init_user_stats(USER_STATS *user_stats,
ulonglong rollback_trans,
ulonglong denied_connections,
ulonglong lost_connections,
+ ulonglong max_statement_time_exceeded,
ulonglong access_denied_errors,
ulonglong empty_queries)
{
@@ -467,6 +467,7 @@ void init_user_stats(USER_STATS *user_stats,
user_stats->rollback_trans= rollback_trans;
user_stats->denied_connections= denied_connections;
user_stats->lost_connections= lost_connections;
+ user_stats->max_statement_time_exceeded= max_statement_time_exceeded;
user_stats->access_denied_errors= access_denied_errors;
user_stats->empty_queries= empty_queries;
DBUG_VOID_RETURN;
@@ -496,6 +497,7 @@ void add_user_stats(USER_STATS *user_stats,
ulonglong rollback_trans,
ulonglong denied_connections,
ulonglong lost_connections,
+ ulonglong max_statement_time_exceeded,
ulonglong access_denied_errors,
ulonglong empty_queries)
{
@@ -519,6 +521,7 @@ void add_user_stats(USER_STATS *user_stats,
user_stats->rollback_trans+= rollback_trans;
user_stats->denied_connections+= denied_connections;
user_stats->lost_connections+= lost_connections;
+ user_stats->max_statement_time_exceeded+= max_statement_time_exceeded;
user_stats->access_denied_errors+= access_denied_errors;
user_stats->empty_queries+= empty_queries;
}
@@ -644,6 +647,7 @@ static bool increment_count_by_name(const char *name, size_t name_length,
0, 0, // commit and rollback trans
thd->status_var.access_denied_errors,
0, // lost connections
+ 0, // max query timeouts
0, // access denied errors
0); // empty queries
@@ -756,6 +760,7 @@ static void update_global_user_stats_with_user(THD *thd,
/* The following can only contain 0 or 1 and then connection ends */
user_stats->denied_connections+= thd->status_var.access_denied_errors;
user_stats->lost_connections+= thd->status_var.lost_connections;
+ user_stats->max_statement_time_exceeded+= thd->status_var.max_statement_time_exceeded;
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6aa76ebf9c7..e8e02197a1b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2697,6 +2697,9 @@ mysql_execute_command(THD *thd)
goto error;
}
+ /* Start timeouts */
+ thd->set_query_timer();
+
switch (lex->sql_command) {
case SQLCOM_SHOW_EVENTS:
@@ -5492,6 +5495,7 @@ error:
finish:
+ thd->reset_query_timer();
DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() ||
thd->in_multi_stmt_transaction_mode());
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index ec7d4979a4e..a5c305f9448 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -3198,6 +3198,7 @@ static int aggregate_user_stats(HASH *all_user_stats, HASH *agg_user_stats)
user->other_commands,
user->commit_trans, user->rollback_trans,
user->denied_connections, user->lost_connections,
+ user->max_statement_time_exceeded,
user->access_denied_errors, user->empty_queries);
if (my_hash_insert(agg_user_stats, (uchar*) agg_user))
@@ -3223,6 +3224,7 @@ static int aggregate_user_stats(HASH *all_user_stats, HASH *agg_user_stats)
user->other_commands,
user->commit_trans, user->rollback_trans,
user->denied_connections, user->lost_connections,
+ user->max_statement_time_exceeded,
user->access_denied_errors, user->empty_queries);
}
}
@@ -3278,6 +3280,7 @@ int send_user_stats(THD* thd, HASH *all_user_stats, TABLE *table)
table->field[j++]->store((longlong)user_stats->lost_connections, TRUE);
table->field[j++]->store((longlong)user_stats->access_denied_errors, TRUE);
table->field[j++]->store((longlong)user_stats->empty_queries, TRUE);
+ table->field[j++]->store((longlong)user_stats->max_statement_time_exceeded, TRUE);
if (schema_table_store_record(thd, table))
{
DBUG_PRINT("error", ("store record error"));
@@ -7410,6 +7413,7 @@ ST_FIELD_INFO user_stats_fields_info[]=
{"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Lost_connections",SKIP_OPEN_TABLE},
{"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Access_denied",SKIP_OPEN_TABLE},
{"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Empty_queries",SKIP_OPEN_TABLE},
+ {"MAX_STATEMENT_TIME_EXCEEDED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Max_statement_time_exceeded",SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
};
@@ -7438,6 +7442,7 @@ ST_FIELD_INFO client_stats_fields_info[]=
{"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Lost_connections",SKIP_OPEN_TABLE},
{"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Access_denied",SKIP_OPEN_TABLE},
{"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Empty_queries",SKIP_OPEN_TABLE},
+ {"MAX_STATEMENT_TIME_EXCEEDED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Max_statement_time_exceeded",SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0}
};
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 78a0eff935a..df9c59e5deb 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1304,6 +1304,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MAX_SIZE_SYM
%token MAX_SYM /* SQL-2003-N */
%token MAX_UPDATES_PER_HOUR
+%token MAX_STATEMENT_TIME_SYM
%token MAX_USER_CONNECTIONS_SYM
%token MAX_VALUE_SYM /* SQL-2003-N */
%token MEDIUMBLOB
@@ -14266,6 +14267,7 @@ keyword_sp:
| MAX_CONNECTIONS_PER_HOUR {}
| MAX_QUERIES_PER_HOUR {}
| MAX_SIZE_SYM {}
+ | MAX_STATEMENT_TIME_SYM {}
| MAX_UPDATES_PER_HOUR {}
| MAX_USER_CONNECTIONS_SYM {}
| MEDIUM_SYM {}
@@ -15620,6 +15622,12 @@ grant_option:
lex->mqh.user_conn= $2;
lex->mqh.specified_limits|= USER_RESOURCES::USER_CONNECTIONS;
}
+ | MAX_STATEMENT_TIME_SYM NUM_literal
+ {
+ LEX *lex=Lex;
+ lex->mqh.max_statement_time= $2->val_real();
+ lex->mqh.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME;
+ }
;
begin:
diff --git a/sql/structs.h b/sql/structs.h
index da8d4beb754..d02301e4350 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -232,12 +232,15 @@ typedef struct user_resources {
connections allowed
*/
int user_conn;
+ /* Max query timeout */
+ double max_statement_time;
+
/*
Values of this enum and specified_limits member are used by the
parser to store which user limits were specified in GRANT statement.
*/
enum {QUERIES_PER_HOUR= 1, UPDATES_PER_HOUR= 2, CONNECTIONS_PER_HOUR= 4,
- USER_CONNECTIONS= 8};
+ USER_CONNECTIONS= 8, MAX_STATEMENT_TIME= 16};
uint specified_limits;
} USER_RESOURCES;
@@ -293,7 +296,7 @@ typedef struct st_user_stats
ha_rows rows_updated, rows_deleted, rows_inserted;
ulonglong select_commands, update_commands, other_commands;
ulonglong commit_trans, rollback_trans;
- ulonglong denied_connections, lost_connections;
+ ulonglong denied_connections, lost_connections, max_statement_time_exceeded;
ulonglong access_denied_errors;
ulonglong empty_queries;
} USER_STATS;
@@ -331,6 +334,7 @@ init_user_stats(USER_STATS *user_stats,
ulonglong rollback_trans,
ulonglong denied_connections,
ulonglong lost_connections,
+ ulonglong max_statement_time_exceeded,
ulonglong access_denied_errors,
ulonglong empty_queries);
@@ -357,6 +361,7 @@ add_user_stats(USER_STATS *user_stats,
ulonglong rollback_trans,
ulonglong denied_connections,
ulonglong lost_connections,
+ ulonglong max_statement_time_exceeded,
ulonglong access_denied_errors,
ulonglong empty_queries);
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 0fab83be90d..b9304403ee5 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1176,6 +1176,29 @@ static Sys_var_double Sys_long_query_time(
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(update_cached_long_query_time));
+
+static bool update_cached_max_statement_time(sys_var *self, THD *thd,
+ enum_var_type type)
+{
+ if (type == OPT_SESSION)
+ thd->variables.max_statement_time=
+ double2ulonglong(thd->variables.max_statement_time_double * 1e6);
+ else
+ global_system_variables.max_statement_time=
+ double2ulonglong(global_system_variables.max_statement_time_double * 1e6);
+ return false;
+}
+
+static Sys_var_double Sys_max_statement_time(
+ "max_statement_time",
+ "A SELECT query that have taken more than max_statement_time seconds "
+ "will be aborted. The argument will be treated as a decimal value "
+ "with microsecond precision. A value of 0 (default) means no timeout",
+ SESSION_VAR(max_statement_time_double),
+ CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, LONG_TIMEOUT), DEFAULT(0),
+ NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
+ ON_UPDATE(update_cached_max_statement_time));
+
static bool fix_low_prio_updates(sys_var *self, THD *thd, enum_var_type type)
{
if (type == OPT_SESSION)
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 2897bb3fb69..938ec243f61 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -82,6 +82,7 @@ my_bool wsrep_restart_slave_activated = 0; // node has dropped, and slave
// restart will be needed
my_bool wsrep_slave_UK_checks = 0; // slave thread does UK checks
my_bool wsrep_slave_FK_checks = 0; // slave thread does FK checks
+bool wsrep_new_cluster = false; // Bootstrap the cluster ?
/*
* End configuration options
*/
@@ -886,37 +887,6 @@ void wsrep_stop_replication(THD *thd)
return;
}
-/* This one is set to true when --wsrep-new-cluster is found in the command
- * line arguments */
-static my_bool wsrep_new_cluster= FALSE;
-#define WSREP_NEW_CLUSTER "--wsrep-new-cluster"
-/* Finds and hides --wsrep-new-cluster from the arguments list
- * by moving it to the end of the list and decrementing argument count */
-void wsrep_filter_new_cluster (int* argc, char* argv[])
-{
- int i;
- for (i= *argc - 1; i > 0; i--)
- {
- /* make a copy of the argument to convert possible underscores to hyphens.
- * the copy need not to be longer than WSREP_NEW_CLUSTER option */
- char arg[sizeof(WSREP_NEW_CLUSTER) + 1]= { 0, };
- strncpy(arg, argv[i], sizeof(arg) - 1);
- char* underscore(arg);
- while (NULL != (underscore= strchr(underscore, '_'))) *underscore= '-';
-
- if (!strcmp(arg, WSREP_NEW_CLUSTER))
- {
- wsrep_new_cluster= TRUE;
- *argc -= 1;
- /* preserve the order of remaining arguments AND
- * preserve the original argument pointers - just in case */
- char* wnc= argv[i];
- memmove(&argv[i], &argv[i + 1], (*argc - i)*sizeof(argv[i]));
- argv[*argc]= wnc; /* this will be invisible to the rest of the program */
- }
- }
-}
-
bool wsrep_start_replication()
{
wsrep_status_t rcode;
@@ -939,11 +909,16 @@ bool wsrep_start_replication()
return true;
}
- bool const bootstrap(TRUE == wsrep_new_cluster);
- wsrep_new_cluster= FALSE;
+ bool const bootstrap= wsrep_new_cluster;
WSREP_INFO("Start replication");
+ if (wsrep_new_cluster)
+ {
+ WSREP_INFO("'wsrep-new-cluster' option used, bootstrapping the cluster");
+ wsrep_new_cluster= false;
+ }
+
if ((rcode = wsrep->connect(wsrep,
wsrep_cluster_name,
wsrep_cluster_address,
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index bc78d2beecf..67f26548043 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -87,6 +87,7 @@ extern my_bool wsrep_restart_slave_activated;
extern my_bool wsrep_slave_FK_checks;
extern my_bool wsrep_slave_UK_checks;
extern ulong wsrep_running_threads;
+extern bool wsrep_new_cluster;
enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU };
enum enum_wsrep_sync_wait {
@@ -112,11 +113,6 @@ extern const char* wsrep_provider_version;
extern const char* wsrep_provider_vendor;
int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff);
-
-/* Filters out --wsrep-new-cluster oprtion from argv[]
- * should be called in the very beginning of main() */
-void wsrep_filter_new_cluster (int* argc, char* argv[]);
-
int wsrep_init();
void wsrep_deinit(bool free_options);
void wsrep_recover();
@@ -328,7 +324,6 @@ int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len);
#define wsrep_stop_replication(X) do { } while(0)
#define wsrep_inited (0)
#define wsrep_deinit(X) do { } while(0)
-#define wsrep_filter_new_cluster(X,Y) do { } while(0)
#define wsrep_recover() do { } while(0)
#define wsrep_slave_threads (1)