summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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/md5.c.THIS329
-rw-r--r--mysys/my_aes.c.THIS228
-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/events.cc7
-rw-r--r--sql/lex.h1
-rw-r--r--sql/log.cc10
-rw-r--r--sql/log_event.cc1
-rw-r--r--sql/mysqld.cc16
-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_base.cc4
-rw-r--r--sql/sql_class.cc65
-rw-r--r--sql/sql_class.h71
-rw-r--r--sql/sql_connect.cc7
-rw-r--r--sql/sql_parse.cc11
-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_thd.cc2
-rw-r--r--storage/innobase/fil/fil0pagecompress.cc6
-rw-r--r--storage/oqgraph/mysql-test/oqgraph/regression_mdev5996.result1
-rw-r--r--storage/oqgraph/mysql-test/oqgraph/regression_mdev5996.test2
-rw-r--r--storage/xtradb/fil/fil0pagecompress.cc7
-rw-r--r--storage/xtradb/os/os0file.cc2
66 files changed, 1821 insertions, 817 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/md5.c.THIS b/mysys/md5.c.THIS
deleted file mode 100644
index 829eea50d22..00000000000
--- a/mysys/md5.c.THIS
+++ /dev/null
@@ -1,329 +0,0 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
-
- 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 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 Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
- not require an integer type which is exactly 32 bits. This work
- draws on the changes for the same purpose by Tatu Ylonen
- <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
- that code, there is no copyright issue. I hereby disclaim
- copyright in any changes I have made; this code remains in the
- public domain. */
-
-/*
- Skip entirely if built with OpenSSL/YaSSL support.
-*/
-#if !defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
-
-#include <my_global.h>
-#include <m_string.h>
-#include "my_md5.h"
-
-static void
-my_MD5Transform (cvs_uint32 buf[4], const unsigned char in[64]);
-
-/* Little-endian byte-swapping routines. Note that these do not
- depend on the size of datatypes such as uint32, nor do they require
- us to detect the endianness of the machine we are running on. It
- is possible they should be macros for speed, but I would be
- surprised if they were a performance bottleneck for MD5. */
-
-static uint32 getu32 (const unsigned char *addr)
-{
- return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
- | addr[1]) << 8 | addr[0];
-}
-
-static void
-putu32 (uint32 data, unsigned char *addr)
-{
- addr[0] = (unsigned char)data;
- addr[1] = (unsigned char)(data >> 8);
- addr[2] = (unsigned char)(data >> 16);
- addr[3] = (unsigned char)(data >> 24);
-}
-
-/*
- Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- initialization constants.
-*/
-void
-my_MD5Init (my_MD5Context *ctx)
-{
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
-
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
-}
-
-/*
- Update context to reflect the concatenation of another buffer full
- of bytes.
-*/
-void
-my_MD5Update (my_MD5Context *ctx, unsigned char const *buf, unsigned len)
-{
- uint32 t;
-
- /* Update bitcount */
-
- t = ctx->bits[0];
- if ((ctx->bits[0] = (t + ((uint32)len << 3)) & 0xffffffff) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
-
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
-
- /* Handle any leading odd-sized chunks */
-
- if ( t ) {
- unsigned char *p = ctx->in + t;
-
- t = 64-t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- my_MD5Transform (ctx->buf, ctx->in);
- buf += t;
- len -= t;
- }
-
- /* Process data in 64-byte chunks */
-
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- my_MD5Transform (ctx->buf, ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
-
- memcpy(ctx->in, buf, len);
-}
-
-/*
- Final wrapup - pad to 64-byte boundary with the bit pattern
- 1 0* (64-bit count of bits processed, MSB-first)
-*/
-void
-my_MD5Final (unsigned char digest[16], my_MD5Context *ctx)
-{
- unsigned count;
- unsigned char *p;
-
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- my_MD5Transform (ctx->buf, ctx->in);
-
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count-8);
- }
-
- /* Append length in bits and transform */
- putu32(ctx->bits[0], ctx->in + 56);
- putu32(ctx->bits[1], ctx->in + 60);
-
- my_MD5Transform (ctx->buf, ctx->in);
- putu32(ctx->buf[0], digest);
- putu32(ctx->buf[1], digest + 4);
- putu32(ctx->buf[2], digest + 8);
- putu32(ctx->buf[3], digest + 12);
- memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
-}
-
-#ifndef ASM_MD5
-
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void
-my_MD5Transform (uint32 buf[4], const unsigned char inraw[64])
-{
- register uint32 a, b, c, d;
- uint32 in[16];
- int i;
-
- for (i = 0; i < 16; ++i)
- in[i] = getu32 (inraw + 4 * i);
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-#endif
-
-#ifdef TEST
-/*
- Simple test program. Can use it to manually run the tests from
- RFC1321 for example.
-*/
-#include <stdio.h>
-
-int
-main (int argc, char **argv)
-{
- my_MD5Context context;
- unsigned char checksum[16];
- int i;
- int j;
-
- if (argc < 2)
- {
- fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
- exit (1);
- }
- for (j = 1; j < argc; ++j)
- {
- printf ("MD5 (\"%s\") = ", argv[j]);
- my_MD5Init (&context);
- my_MD5Update (&context, argv[j], strlen (argv[j]));
- my_MD5Final (checksum, &context);
- for (i = 0; i < 16; i++)
- {
- printf ("%02x", (unsigned int) checksum[i]);
- }
- printf ("\n");
- }
- return 0;
-}
-#endif /* TEST */
-
-#endif /* !defined(HAVE_OPENSSL) && !defined(HAVE_YASSL) */
diff --git a/mysys/my_aes.c.THIS b/mysys/my_aes.c.THIS
deleted file mode 100644
index 7074f700413..00000000000
--- a/mysys/my_aes.c.THIS
+++ /dev/null
@@ -1,228 +0,0 @@
-/* Copyright (c) 2002, 2006 MySQL AB
- Use is subject to license terms
-
- 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 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 Street, Fifth Floor, Boston, MA 02110-1301, USA */
-
-
-/*
- Implementation of AES Encryption for MySQL
- Initial version by Peter Zaitsev June 2002
-*/
-
-
-#include <my_global.h>
-#include <m_string.h>
-#include "my_aes.h"
-
-enum encrypt_dir { AES_ENCRYPT, AES_DECRYPT };
-
-#define AES_BLOCK_SIZE 16 /* Block size in bytes */
-
-#define AES_BAD_DATA -1 /* If bad data discovered during decoding */
-
-
-/* The structure for key information */
-typedef struct {
- int nr; /* Number of rounds */
- uint32 rk[4*(AES_MAXNR + 1)]; /* key schedule */
-} KEYINSTANCE;
-
-
-/*
- This is internal function just keeps joint code of Key generation
-
- SYNOPSIS
- my_aes_create_key()
- aes_key Address of Key Instance to be created
- direction Direction (are we encoding or decoding)
- key Key to use for real key creation
- key_length Length of the key
-
- DESCRIPTION
-
- RESULT
- 0 ok
- -1 Error Note: The current impementation never returns this
-*/
-
-static int my_aes_create_key(KEYINSTANCE *aes_key,
- enum encrypt_dir direction, const char *key,
- int key_length)
-{
- uint8 rkey[AES_KEY_LENGTH/8]; /* The real key to be used for encryption */
- uint8 *rkey_end=rkey+AES_KEY_LENGTH/8; /* Real key boundary */
- uint8 *ptr; /* Start of the real key*/
- const char *sptr; /* Start of the working key */
- const char *key_end=key+key_length; /* Working key boundary*/
-
- bzero((char*) rkey,AES_KEY_LENGTH/8); /* Set initial key */
-
- for (ptr= rkey, sptr= key; sptr < key_end; ptr++,sptr++)
- {
- if (ptr == rkey_end)
- ptr= rkey; /* Just loop over tmp_key until we used all key */
- *ptr^= (uint8) *sptr;
- }
-#ifdef AES_USE_KEY_BITS
- /*
- This block is intended to allow more weak encryption if application
- build with libmysqld needs to correspond to export regulations
- It should be never used in normal distribution as does not give
- any speed improvement.
- To get worse security define AES_USE_KEY_BITS to number of bits
- you want key to be. It should be divisible by 8
-
- WARNING: Changing this value results in changing of enryption for
- all key lengths so altering this value will result in impossibility
- to decrypt data encrypted with previous value
- */
-#define AES_USE_KEY_BYTES (AES_USE_KEY_BITS/8)
- /*
- To get weaker key we use first AES_USE_KEY_BYTES bytes of created key
- and cyclically copy them until we created all required key length
- */
- for (ptr= rkey+AES_USE_KEY_BYTES, sptr=rkey ; ptr < rkey_end;
- ptr++,sptr++)
- {
- if (sptr == rkey+AES_USE_KEY_BYTES)
- sptr=rkey;
- *ptr=*sptr;
- }
-#endif
- if (direction == AES_DECRYPT)
- aes_key->nr = rijndaelKeySetupDec(aes_key->rk, rkey, AES_KEY_LENGTH);
- else
- aes_key->nr = rijndaelKeySetupEnc(aes_key->rk, rkey, AES_KEY_LENGTH);
- return 0;
-}
-
-
-/*
- Crypt buffer with AES encryption algorithm.
-
- SYNOPSIS
- my_aes_encrypt()
- source Pointer to data for encryption
- source_length Size of encryption data
- dest Buffer to place encrypted data (must be large enough)
- key Key to be used for encryption
- key_length Length of the key. Will handle keys of any length
-
- RETURN
- >= 0 Size of encrypted data
- < 0 Error
-*/
-
-int my_aes_encrypt(const char* source, int source_length, char* dest,
- const char* key, int key_length)
-{
- KEYINSTANCE aes_key;
- uint8 block[AES_BLOCK_SIZE]; /* 128 bit block used for padding */
- int rc; /* result codes */
- int num_blocks; /* number of complete blocks */
- char pad_len; /* pad size for the last block */
- int i;
-
- if ((rc= my_aes_create_key(&aes_key,AES_ENCRYPT,key,key_length)))
- return rc;
-
- num_blocks = source_length/AES_BLOCK_SIZE;
-
- for (i = num_blocks; i > 0; i--) /* Encode complete blocks */
- {
- rijndaelEncrypt(aes_key.rk, aes_key.nr, (const uint8*) source,
- (uint8*) dest);
- source+= AES_BLOCK_SIZE;
- dest+= AES_BLOCK_SIZE;
- }
-
- /* Encode the rest. We always have incomplete block */
- pad_len = AES_BLOCK_SIZE - (source_length - AES_BLOCK_SIZE*num_blocks);
- memcpy(block, source, 16 - pad_len);
- bfill(block + AES_BLOCK_SIZE - pad_len, pad_len, pad_len);
- rijndaelEncrypt(aes_key.rk, aes_key.nr, block, (uint8*) dest);
- return AES_BLOCK_SIZE*(num_blocks + 1);
-}
-
-
-/*
- DeCrypt buffer with AES encryption algorithm.
-
- SYNOPSIS
- my_aes_decrypt()
- source Pointer to data for decryption
- source_length Size of encrypted data
- dest Buffer to place decrypted data (must be large enough)
- key Key to be used for decryption
- key_length Length of the key. Will handle keys of any length
-
- RETURN
- >= 0 Size of encrypted data
- < 0 Error
-*/
-
-int my_aes_decrypt(const char *source, int source_length, char *dest,
- const char *key, int key_length)
-{
- KEYINSTANCE aes_key;
- uint8 block[AES_BLOCK_SIZE]; /* 128 bit block used for padding */
- int rc; /* Result codes */
- int num_blocks; /* Number of complete blocks */
- uint pad_len; /* Pad size for the last block */
- int i;
-
- if ((rc=my_aes_create_key(&aes_key,AES_DECRYPT,key,key_length)))
- return rc;
-
- num_blocks = source_length/AES_BLOCK_SIZE;
-
- if ((source_length != num_blocks*AES_BLOCK_SIZE) || num_blocks ==0 )
- return AES_BAD_DATA; /* Input size has to be even and at least one block */
-
- for (i = num_blocks-1; i > 0; i--) /* Decode all but last blocks */
- {
- rijndaelDecrypt(aes_key.rk, aes_key.nr, (const uint8*) source,
- (uint8*) dest);
- source+= AES_BLOCK_SIZE;
- dest+= AES_BLOCK_SIZE;
- }
-
- rijndaelDecrypt(aes_key.rk, aes_key.nr, (const uint8*) source, block);
- /* Use last char in the block as size */
- pad_len = (uint) (uchar) block[AES_BLOCK_SIZE-1];
-
- if (pad_len > AES_BLOCK_SIZE)
- return AES_BAD_DATA;
- /* We could also check whole padding but we do not really need this */
-
- memcpy(dest, block, AES_BLOCK_SIZE - pad_len);
- return AES_BLOCK_SIZE*num_blocks - pad_len;
-}
-
-
-/*
- Get size of buffer which will be large enough for encrypted data
-
- SYNOPSIS
- my_aes_get_size()
- source_length Length of data to be encrypted
-
- RETURN
- Size of buffer required to store encrypted data
-*/
-
-int my_aes_get_size(int source_length)
-{
- return AES_BLOCK_SIZE*(source_length/AES_BLOCK_SIZE)+AES_BLOCK_SIZE;
-}
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/events.cc b/sql/events.cc
index fa40086c1f7..d42a5d7b0a0 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -1131,8 +1131,11 @@ Events::load_events_from_db(THD *thd)
goto end;
}
#ifdef WITH_WSREP
- // when SST from master node who initials event, the event status is ENABLED
- // this is problematic because there are two nodes with same events and both enabled.
+ /*
+ When SST from master node who initials event, the event status is ENABLED
+ this is problematic because there are two nodes with same events and
+ both enabled.
+ */
if (WSREP(thd) && et->originator != thd->variables.server_id)
{
store_record(table, record[1]);
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.cc b/sql/log.cc
index 9c6de086a13..8ad6556e7c4 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1910,12 +1910,12 @@ static bool trans_cannot_safely_rollback(THD *thd, bool all)
return ((thd->variables.option_bits & OPTION_KEEP_LOG) ||
(trans_has_updated_non_trans_table(thd) &&
- WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT) ||
+ WSREP_FORMAT((enum enum_binlog_format) thd->variables.binlog_format) == BINLOG_FORMAT_STMT) ||
(cache_mngr->trx_cache.changes_to_non_trans_temp_table() &&
- WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_MIXED) ||
+ WSREP_FORMAT((enum enum_binlog_format) thd->variables.binlog_format) == BINLOG_FORMAT_MIXED) ||
(trans_has_updated_non_trans_table(thd) &&
ending_single_stmt_trans(thd,all) &&
- WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_MIXED));
+ WSREP_FORMAT((enum enum_binlog_format) thd->variables.binlog_format) == BINLOG_FORMAT_MIXED));
}
@@ -2064,9 +2064,9 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
else if (ending_trans(thd, all) ||
(!(thd->variables.option_bits & OPTION_KEEP_LOG) &&
(!stmt_has_updated_non_trans_table(thd) ||
- WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_STMT) &&
+ WSREP_FORMAT((enum enum_binlog_format) thd->variables.binlog_format) != BINLOG_FORMAT_STMT) &&
(!cache_mngr->trx_cache.changes_to_non_trans_temp_table() ||
- WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_MIXED)))
+ WSREP_FORMAT((enum enum_binlog_format) thd->variables.binlog_format) != BINLOG_FORMAT_MIXED)))
error= binlog_truncate_trx_cache(thd, cache_mngr, all);
}
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 d252c33ac53..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();
@@ -8077,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},
@@ -9145,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_base.cc b/sql/sql_base.cc
index 356f672657e..a23c71dfc1c 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3558,7 +3558,7 @@ thr_lock_type read_lock_type_for_table(THD *thd,
*/
bool log_on= mysql_bin_log.is_open() && thd->variables.sql_log_bin;
ulong binlog_format= thd->variables.binlog_format;
- if ((log_on == FALSE) || (WSREP_FORMAT(binlog_format) == BINLOG_FORMAT_ROW) ||
+ if ((log_on == FALSE) || (WSREP_FORMAT((enum enum_binlog_format) binlog_format) == BINLOG_FORMAT_ROW) ||
(table_list->table->s->table_category == TABLE_CATEGORY_LOG) ||
(table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) ||
!(is_update_query(prelocking_ctx->sql_command) ||
@@ -5327,7 +5327,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
We can solve these problems in mixed mode by switching to binlogging
if at least one updated table is used by sub-statement
*/
- if (WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_ROW && tables &&
+ if (WSREP_FORMAT((enum enum_binlog_format) thd->variables.binlog_format) != BINLOG_FORMAT_ROW && tables &&
has_write_table_with_auto_increment(thd->lex->first_not_own_table()))
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS);
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index dde0a9a2f7a..c8c03da0471 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -861,9 +861,26 @@ 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),
+ :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
+ /* statement id */ 0),
rli_fake(0), rgi_fake(0), rgi_slave(NULL),
in_sub_stmt(0), log_all_errors(0),
binlog_unsafe_warning_flags(0),
@@ -896,16 +913,17 @@ THD::THD(bool is_wsrep_applier)
debug_sync_control(0),
#endif /* defined(ENABLED_DEBUG_SYNC) */
wait_for_commit_ptr(0),
- main_da(0, false, false),
+ main_da(0, false, false),
m_stmt_da(&main_da)
#ifdef WITH_WSREP
- ,wsrep_applier(is_wsrep_applier)
- ,wsrep_applier_closing(false)
- ,wsrep_client_thread(false)
- ,wsrep_apply_toi(false)
- ,wsrep_po_handle(WSREP_PO_INITIALIZER)
- ,wsrep_po_cnt(0)
- ,wsrep_apply_format(0)
+ ,
+ wsrep_applier(is_wsrep_applier),
+ wsrep_applier_closing(false),
+ wsrep_client_thread(false),
+ wsrep_apply_toi(false),
+ wsrep_po_handle(WSREP_PO_INITIALIZER),
+ wsrep_po_cnt(0),
+ wsrep_apply_format(0)
#endif
{
ulong tmp;
@@ -1058,6 +1076,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 +1393,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 +1800,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 +1812,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 +1850,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 +2019,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);
@@ -4317,7 +4350,7 @@ extern "C" int thd_binlog_format(const MYSQL_THD thd)
{
if (((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()) &&
thd->variables.option_bits & OPTION_BIN_LOG)
- return (int) WSREP_FORMAT(thd->variables.binlog_format);
+ return (int) WSREP_FORMAT((enum enum_binlog_format) thd->variables.binlog_format);
else
return BINLOG_FORMAT_UNSPEC;
}
@@ -5047,7 +5080,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
binlog by filtering rules.
*/
if (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG) &&
- !(WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_STMT &&
+ !(WSREP_FORMAT((enum enum_binlog_format) variables.binlog_format) == BINLOG_FORMAT_STMT &&
!binlog_filter->db_ok(db)))
{
/*
@@ -5257,7 +5290,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
*/
my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE), MYF(0));
}
- else if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_ROW &&
+ else if (WSREP_FORMAT((enum enum_binlog_format) variables.binlog_format) == BINLOG_FORMAT_ROW &&
sqlcom_can_generate_row_events(this))
{
/*
@@ -5286,7 +5319,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
else
{
/* binlog_format = STATEMENT */
- if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_STMT)
+ if (WSREP_FORMAT((enum enum_binlog_format) variables.binlog_format) == BINLOG_FORMAT_STMT)
{
if (lex->is_stmt_row_injection())
{
@@ -5414,11 +5447,11 @@ int THD::decide_logging_format(TABLE_LIST *tables)
DBUG_PRINT("info", ("decision: no logging since "
"mysql_bin_log.is_open() = %d "
"and (options & OPTION_BIN_LOG) = 0x%llx "
- "and binlog_format = %lu "
+ "and binlog_format = %u "
"and binlog_filter->db_ok(db) = %d",
mysql_bin_log.is_open(),
(variables.option_bits & OPTION_BIN_LOG),
- WSREP_FORMAT(variables.binlog_format),
+ (uint) WSREP_FORMAT((enum enum_binlog_format) variables.binlog_format),
binlog_filter->db_ok(db)));
#endif
diff --git a/sql/sql_class.h b/sql/sql_class.h
index cab2968a62b..0860b868cd2 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
*/
@@ -3282,8 +3286,8 @@ public:
tests fail and so force them to propagate the
lex->binlog_row_based_if_mixed upwards to the caller.
*/
- if ((WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_MIXED) &&
- (in_sub_stmt == 0))
+ if ((WSREP_FORMAT((enum enum_binlog_format) variables.binlog_format) ==
+ BINLOG_FORMAT_MIXED) && (in_sub_stmt == 0))
set_current_stmt_binlog_format_row();
DBUG_VOID_RETURN;
@@ -3334,7 +3338,8 @@ public:
show_system_thread(system_thread)));
if (in_sub_stmt == 0)
{
- if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_ROW)
+ if (WSREP_FORMAT((enum enum_binlog_format) variables.binlog_format) ==
+ BINLOG_FORMAT_ROW)
set_current_stmt_binlog_format_row();
else if (temporary_tables == NULL)
set_current_stmt_binlog_format_stmt();
@@ -3722,8 +3727,8 @@ public:
mysql_mutex_t LOCK_wakeup_ready;
mysql_cond_t COND_wakeup_ready;
/*
- The GTID assigned to the last commit. If no GTID was assigned to any commit
- so far, this is indicated by last_commit_gtid.seq_no == 0.
+ The GTID assigned to the last commit. If no GTID was assigned to any commit
+ so far, this is indicated by last_commit_gtid.seq_no == 0.
*/
rpl_gtid last_commit_gtid;
@@ -3758,27 +3763,55 @@ public:
mysql_cond_t COND_wsrep_thd;
wsrep_trx_meta_t wsrep_trx_meta;
uint32 wsrep_rand;
- Relay_log_info* wsrep_rli;
- rpl_group_info* wsrep_rgi;
+ Relay_log_info *wsrep_rli;
+ rpl_group_info *wsrep_rgi;
wsrep_ws_handle_t wsrep_ws_handle;
ulong wsrep_retry_counter; // of autocommit
- char* wsrep_retry_query;
+ char *wsrep_retry_query;
size_t wsrep_retry_query_len;
enum enum_server_command wsrep_retry_command;
enum wsrep_consistency_check_mode
wsrep_consistency_check;
int wsrep_mysql_replicated;
- const char* wsrep_TOI_pre_query; /* a query to apply before
- the actual TOI query */
+ const char *wsrep_TOI_pre_query; /* a query to apply before
+ the actual TOI query */
size_t wsrep_TOI_pre_query_len;
wsrep_po_handle_t wsrep_po_handle;
size_t wsrep_po_cnt;
#ifdef GTID_SUPPORT
rpl_sid wsrep_po_sid;
#endif /* GTID_SUPPORT */
- void* wsrep_apply_format;
+ 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..0788c233508 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:
@@ -2778,10 +2781,9 @@ mysql_execute_command(THD *thd)
else
res= check_access(thd, privileges_requested, any_db, NULL, NULL, 0, 0);
- if (res)
- break;
+ if (!res)
+ res= execute_sqlcom_select(thd, all_tables);
- res= execute_sqlcom_select(thd, all_tables);
break;
}
case SQLCOM_PREPARE:
@@ -3132,7 +3134,7 @@ mysql_execute_command(THD *thd)
*/
if (thd->query_name_consts &&
mysql_bin_log.is_open() &&
- WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT &&
+ WSREP_FORMAT((enum enum_binlog_format) thd->variables.binlog_format) == BINLOG_FORMAT_STMT &&
!mysql_bin_log.is_query_in_union(thd, thd->query_id))
{
List_iterator_fast<Item> it(select_lex->item_list);
@@ -5492,6 +5494,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_thd.cc b/sql/wsrep_thd.cc
index b9ff0ecf8a8..b65eead817d 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -90,7 +90,7 @@ void wsrep_client_rollback(THD *thd)
#define NUMBER_OF_FIELDS_TO_IDENTIFY_WORKER 2
//#include "rpl_info_factory.h"
-#if 0
+#ifdef NOT_USED
static Relay_log_info* wsrep_relay_log_init(const char* log_fname)
{
diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc
index b6eb2e73b30..77efd250fa0 100644
--- a/storage/innobase/fil/fil0pagecompress.cc
+++ b/storage/innobase/fil/fil0pagecompress.cc
@@ -99,7 +99,6 @@ fil_decompress_page_2(
return;
}
- ulint olen = 0;
byte* ptr = buf + FIL_PAGE_DATA;
ulint version = mach_read_from_1(buf + FIL_PAGE_VERSION);
int err = 0;
@@ -206,6 +205,7 @@ fil_decompress_page_2(
#ifdef HAVE_LZO
case PAGE_LZO_ALGORITHM: {
+ ulint olen = 0;
fprintf(stderr, "InnoDB: [Note]: lzo \n");
err = lzo1x_decompress((const unsigned char *)ptr,
original_len,(unsigned char *)(page_buf), &olen, NULL);
@@ -493,7 +493,6 @@ fil_decompress_page(
ulint actual_size = 0;
ulint compression_alg = 0;
byte *in_buf;
- ulint olen=0;
ulint ptype;
ut_ad(buf);
@@ -607,6 +606,8 @@ fil_decompress_page(
#endif /* HAVE_LZ4 */
#ifdef HAVE_LZO
case PAGE_LZO_ALGORITHM:
+ {
+ ulint olen=0;
err = lzo1x_decompress((const unsigned char *)buf+FIL_PAGE_DATA+FIL_PAGE_COMPRESSED_SIZE,
actual_size,(unsigned char *)in_buf, &olen, NULL);
@@ -621,6 +622,7 @@ fil_decompress_page(
ut_error;
}
break;
+ }
#endif /* HAVE_LZO */
#ifdef HAVE_LZMA
case PAGE_LZMA_ALGORITHM: {
diff --git a/storage/oqgraph/mysql-test/oqgraph/regression_mdev5996.result b/storage/oqgraph/mysql-test/oqgraph/regression_mdev5996.result
index a639a185ec2..39e476b2403 100644
--- a/storage/oqgraph/mysql-test/oqgraph/regression_mdev5996.result
+++ b/storage/oqgraph/mysql-test/oqgraph/regression_mdev5996.result
@@ -1,3 +1,4 @@
+call mtr.add_suppression("99999999 is open on delete");
Performing OQGraph regression test mdev5996 - using db=``, table=`999999999`
use test;
drop table if exists `999999999` ;
diff --git a/storage/oqgraph/mysql-test/oqgraph/regression_mdev5996.test b/storage/oqgraph/mysql-test/oqgraph/regression_mdev5996.test
index e5d04ef357d..cb4563a5759 100644
--- a/storage/oqgraph/mysql-test/oqgraph/regression_mdev5996.test
+++ b/storage/oqgraph/mysql-test/oqgraph/regression_mdev5996.test
@@ -2,6 +2,8 @@
# MidSchipDB_unstable
--let $oqgraph_table_name= 999999999
+call mtr.add_suppression("99999999 is open on delete");
+
--let $oqgraph_database_name=
--source regression_mdev5996.inc
diff --git a/storage/xtradb/fil/fil0pagecompress.cc b/storage/xtradb/fil/fil0pagecompress.cc
index e92f3587236..d7bc0ff62e7 100644
--- a/storage/xtradb/fil/fil0pagecompress.cc
+++ b/storage/xtradb/fil/fil0pagecompress.cc
@@ -99,7 +99,6 @@ fil_decompress_page_2(
return;
}
- ulint olen = 0;
byte* ptr = buf + FIL_PAGE_DATA;
ulint version = mach_read_from_1(buf + FIL_PAGE_VERSION);
int err = 0;
@@ -206,6 +205,7 @@ fil_decompress_page_2(
#ifdef HAVE_LZO
case PAGE_LZO_ALGORITHM: {
+ ulint olen = 0;
fprintf(stderr, "InnoDB: [Note]: lzo \n");
err = lzo1x_decompress((const unsigned char *)ptr,
original_len,(unsigned char *)(page_buf), &olen, NULL);
@@ -490,7 +490,6 @@ fil_decompress_page(
ulint actual_size = 0;
ulint compression_alg = 0;
byte *in_buf;
- ulint olen=0;
ulint ptype;
ut_ad(buf);
@@ -603,7 +602,8 @@ fil_decompress_page(
break;
#endif /* HAVE_LZ4 */
#ifdef HAVE_LZO
- case PAGE_LZO_ALGORITHM:
+ case PAGE_LZO_ALGORITHM: {
+ ulint olen=0;
err = lzo1x_decompress((const unsigned char *)buf+FIL_PAGE_DATA+FIL_PAGE_COMPRESSED_SIZE,
actual_size,(unsigned char *)in_buf, &olen, NULL);
@@ -618,6 +618,7 @@ fil_decompress_page(
ut_error;
}
break;
+ }
#endif /* HAVE_LZO */
#ifdef HAVE_LZMA
case PAGE_LZMA_ALGORITHM: {
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index d67573d14aa..a7a5d5f32c0 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -6404,7 +6404,7 @@ os_file_trim(
#define SECT_SIZE 512
size_t trim_len = UNIV_PAGE_SIZE - len;
- os_offset_t off = slot->offset + len;
+ os_offset_t off __attribute__((unused)) = slot->offset + len;
// len here should be alligned to sector size
ut_a((trim_len % SECT_SIZE) == 0);
ut_a((len % SECT_SIZE) == 0);