Permalink
Browse files

Merge branch 'MYSQL-15' into twitter-dev

  • Loading branch information...
2 parents d47f9d1 + 7fc0322 commit 8efbad7c19e89b81a0f6b752d8088a27c6944c8e Davi Arnaut committed Mar 6, 2012
Showing with 2,356 additions and 40 deletions.
  1. +4 −0 config.h.cmake
  2. +17 −0 configure.cmake
  3. +14 −3 include/my_global.h
  4. +69 −0 include/my_timer.h
  5. +7 −0 include/mysql/plugin.h
  6. +1 −0 include/mysql/plugin_audit.h.pp
  7. +1 −0 include/mysql/plugin_auth.h.pp
  8. +1 −0 include/mysql/plugin_ftparser.h.pp
  9. +3 −0 libmysqld/CMakeLists.txt
  10. +4 −0 mysql-test/include/have_statement_timeout.inc
  11. +3 −0 mysql-test/r/grant.result
  12. +2 −0 mysql-test/r/have_statement_timeout.require
  13. +157 −0 mysql-test/r/max_statement_time.result
  14. +3 −3 mysql-test/r/ps.result
  15. +1 −0 mysql-test/r/system_mysql_db.result
  16. +2 −0 mysql-test/suite/funcs_1/r/is_columns_mysql.result
  17. +33 −0 mysql-test/suite/funcs_1/r/is_user_privileges.result
  18. 0 mysql-test/suite/randgen/r/max_statement_time.result
  19. +16 −0 mysql-test/suite/randgen/t/max_statement_time.test
  20. +53 −0 mysql-test/suite/sys_vars/r/have_statement_timeout_basic.result
  21. +91 −0 mysql-test/suite/sys_vars/r/max_statement_time_basic.result
  22. +66 −0 mysql-test/suite/sys_vars/r/max_statement_time_func.result
  23. +55 −0 mysql-test/suite/sys_vars/t/have_statement_timeout_basic.test
  24. +78 −0 mysql-test/suite/sys_vars/t/max_statement_time_basic.test
  25. +75 −0 mysql-test/suite/sys_vars/t/max_statement_time_func.test
  26. +220 −0 mysql-test/t/max_statement_time.test
  27. +8 −0 mysys/CMakeLists.txt
  28. +219 −0 mysys/kqueue_timers.c
  29. +256 −0 mysys/posix_timers.c
  30. +1 −1 scripts/mysql_system_tables.sql
  31. +4 −4 scripts/mysql_system_tables_data.sql
  32. +4 −0 scripts/mysql_system_tables_fix.sql
  33. +4 −0 sql/CMakeLists.txt
  34. +18 −0 sql/handler.cc
  35. +4 −0 sql/handler.h
  36. +1 −0 sql/lex.h
  37. +22 −0 sql/mysqld.cc
  38. +1 −0 sql/set_var.h
  39. +4 −1 sql/share/errmsg-utf8.txt
  40. +3 −0 sql/signal_handler.cc
  41. +40 −2 sql/sql_acl.cc
  42. +42 −16 sql/sql_class.cc
  43. +11 −0 sql/sql_class.h
  44. +3 −0 sql/sql_lex.cc
  45. +3 −0 sql/sql_lex.h
  46. +92 −1 sql/sql_parse.cc
  47. +233 −0 sql/sql_timer.cc
  48. +50 −0 sql/sql_timer.h
  49. +37 −5 sql/sql_yacc.yy
  50. +3 −1 sql/structs.h
  51. +10 −0 sql/sys_vars.cc
  52. +34 −3 storage/innobase/handler/ha_innodb.cc
  53. +4 −0 unittest/mysys/CMakeLists.txt
  54. +269 −0 unittest/mysys/my_timer-t.c
View
@@ -308,6 +308,10 @@
#cmakedefine STRUCT_DIRENT_HAS_D_NAMLEN 1
#cmakedefine SPRINTF_RETURNS_INT 1
+#cmakedefine HAVE_POSIX_TIMERS 1
+#cmakedefine HAVE_KQUEUE_TIMERS 1
+#cmakedefine HAVE_MY_TIMER 1
+
#define USE_MB 1
#define USE_MB_IDENT 1
View
@@ -147,6 +147,7 @@ IF(UNIX)
IF(NOT LIBRT)
MY_SEARCH_LIBS(clock_gettime rt LIBRT)
ENDIF()
+ MY_SEARCH_LIBS(timer_create rt LIBRT)
FIND_PACKAGE(Threads)
SET(CMAKE_REQUIRED_LIBRARIES
@@ -454,6 +455,9 @@ CHECK_FUNCTION_EXISTS (valloc HAVE_VALLOC)
CHECK_FUNCTION_EXISTS (memalign HAVE_MEMALIGN)
CHECK_FUNCTION_EXISTS (chown HAVE_CHOWN)
CHECK_FUNCTION_EXISTS (nl_langinfo HAVE_NL_LANGINFO)
+CHECK_FUNCTION_EXISTS (timer_create HAVE_TIMER_CREATE)
+CHECK_FUNCTION_EXISTS (timer_settime HAVE_TIMER_SETTIME)
+CHECK_FUNCTION_EXISTS (kqueue HAVE_KQUEUE)
#--------------------------------------------------------------------
# Support for WL#2373 (Use cycle counter for timing)
@@ -495,6 +499,8 @@ CHECK_SYMBOL_EXISTS(FIONREAD "sys/ioctl.h" FIONREAD_IN_SYS_IOCTL)
CHECK_SYMBOL_EXISTS(TIOCSTAT "sys/ioctl.h" TIOCSTAT_IN_SYS_IOCTL)
CHECK_SYMBOL_EXISTS(FIONREAD "sys/filio.h" FIONREAD_IN_SYS_FILIO)
CHECK_SYMBOL_EXISTS(gettimeofday "sys/time.h" HAVE_GETTIMEOFDAY)
+CHECK_SYMBOL_EXISTS(SIGEV_THREAD_ID "signal.h;time.h" HAVE_SIGEV_THREAD_ID)
+CHECK_SYMBOL_EXISTS(EVFILT_TIMER "sys/types.h;sys/event.h;sys/time.h" HAVE_EVFILT_TIMER)
CHECK_SYMBOL_EXISTS(finite "math.h" HAVE_FINITE_IN_MATH_H)
IF(HAVE_FINITE_IN_MATH_H)
@@ -514,7 +520,18 @@ int main() {
return 0;
}" HAVE_ISINF)
+# Check for the Linux-specific POSIX timers API.
+IF(HAVE_TIMER_CREATE AND HAVE_TIMER_SETTIME AND HAVE_SIGEV_THREAD_ID)
+ SET(HAVE_POSIX_TIMERS 1 CACHE INTERNAL "Have POSIX timer-related functions")
+ENDIF()
+
+IF(HAVE_KQUEUE AND HAVE_EVFILT_TIMER)
+ SET(HAVE_KQUEUE_TIMERS 1 CACHE INTERNAL "Have kqueue timer-related filter")
+ENDIF()
+IF(HAVE_POSIX_TIMERS OR HAVE_KQUEUE_TIMERS)
+ SET(HAVE_MY_TIMER 1 CACHE INTERNAL "Have mysys timer-related functions")
+ENDIF()
#
# Test for endianess
View
@@ -377,6 +377,19 @@ C_MODE_END
#include <crypt.h>
#endif
+/**
+ Cast a member of a structure to the structure that contains it.
+
+ @param ptr Pointer to the member.
+ @param type Type of the structure that contains the member.
+ @param member Name of the member within the structure.
+*/
+#define my_container_of(ptr, type, member) \
+ ({ \
+ const typeof(((type *)0)->member) *__mptr= (ptr); \
+ (type *)((char *)__mptr - offsetof(type, member)); \
+ })
+
/*
A lot of our programs uses asserts, so better to always include it
This also fixes a problem when people uses DBUG_ASSERT without including
@@ -1418,9 +1431,7 @@ do { doubleget_union _tmp; \
#define NEED_EXPLICIT_SYNC_DIR 1
#endif
-#if !defined(__cplusplus) && !defined(bool)
-#define bool In_C_you_should_use_my_bool_instead()
-#endif
+#include <stdbool.h>
/* Provide __func__ macro definition for platforms that miss it. */
#if __STDC_VERSION__ < 199901L
View
@@ -0,0 +1,69 @@
+/* Copyright (c) 2012, Twitter, Inc. 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. */
+
+#ifndef MY_TIMER_H
+#define MY_TIMER_H
+
+#include "my_global.h" /* C_MODE_START, C_MODE_END */
+#include "my_config.h" /* HAVE_*_TIMERS */
+
+/* POSIX timers API. */
+#ifdef HAVE_POSIX_TIMERS
+# include <time.h> /* timer_t */
+ typedef timer_t os_timer_t;
+#elif HAVE_KQUEUE_TIMERS
+# include <sys/types.h> /* uintptr_t */
+ typedef uintptr_t os_timer_t;
+#endif
+
+/* Whether timer API is implemented. */
+#ifdef HAVE_MY_TIMER
+
+C_MODE_START
+
+typedef struct st_my_timer my_timer_t;
+
+/** Non-copyable timer object. */
+struct st_my_timer
+{
+ /** Timer ID used to identify the timer in timer requests. */
+ os_timer_t id;
+
+ /** Timer expiration notification function. */
+ void (*notify_function)(my_timer_t *);
+};
+
+/* Initialize internal components. */
+int my_timer_init_ext(void);
+
+/* Release any resources acquired. */
+void my_timer_deinit(void);
+
+/* Create a timer object. */
+int my_timer_create(my_timer_t *timer);
+
+/* Set the time (in milliseconds) until the next expiration of the timer. */
+int my_timer_set(my_timer_t *timer, unsigned long time);
+
+/* Reset the time until the next expiration of the timer. */
+int my_timer_reset(my_timer_t *timer, bool *state);
+
+/* Delete a timer object. */
+void my_timer_delete(my_timer_t *timer);
+
+C_MODE_END
+
+#endif /* HAVE_MY_TIMER */
+#endif /* MY_TIMER_H */
View
@@ -583,6 +583,13 @@ MYSQL_THD thd_get_current_thd();
int thd_killed(const MYSQL_THD thd);
+/**
+ Set the killed status of the current statement.
+
+ @param thd user thread connection handle
+*/
+void thd_set_kill_status(const MYSQL_THD thd);
+
/**
Return the thread id of a user thread
@@ -189,6 +189,7 @@
int mysql_tmpfile(const char *prefix);
void* thd_get_current_thd();
int thd_killed(const void* thd);
+void thd_set_kill_status(const void* thd);
unsigned long thd_get_thread_id(const void* thd);
void thd_get_xid(const void* thd, MYSQL_XID *xid);
void mysql_query_cache_invalidate4(void* thd,
@@ -189,6 +189,7 @@
int mysql_tmpfile(const char *prefix);
void* thd_get_current_thd();
int thd_killed(const void* thd);
+void thd_set_kill_status(const void* thd);
unsigned long thd_get_thread_id(const void* thd);
void thd_get_xid(const void* thd, MYSQL_XID *xid);
void mysql_query_cache_invalidate4(void* thd,
@@ -142,6 +142,7 @@
int mysql_tmpfile(const char *prefix);
void* thd_get_current_thd();
int thd_killed(const void* thd);
+void thd_set_kill_status(const void* thd);
unsigned long thd_get_thread_id(const void* thd);
void thd_get_xid(const void* thd, MYSQL_XID *xid);
void mysql_query_cache_invalidate4(void* thd,
View
@@ -92,6 +92,9 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
${MYSYS_LIBWRAP_SOURCE}
)
+IF(HAVE_MY_TIMER)
+ SET(SQL_EMBEDDED_SOURCES ${SQL_EMBEDDED_SOURCES} ../sql/sql_timer.cc)
+ENDIF()
ADD_CONVENIENCE_LIBRARY(sql_embedded ${SQL_EMBEDDED_SOURCES})
DTRACE_INSTRUMENT(sql_embedded)
@@ -0,0 +1,4 @@
+-- require r/have_statement_timeout.require
+disable_query_log;
+show variables like 'have_statement_timeout';
+enable_query_log;
@@ -55,6 +55,7 @@ max_connections 0
max_user_connections 0
plugin
authentication_string NULL
+max_statement_time 0
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'
@@ -126,6 +127,7 @@ max_connections 0
max_user_connections 0
plugin
authentication_string NULL
+max_statement_time 0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10
@@ -173,6 +175,7 @@ max_connections 30
max_user_connections 0
plugin
authentication_string NULL
+max_statement_time 0
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
@@ -0,0 +1,2 @@
+Variable_name Value
+have_statement_timeout YES
@@ -0,0 +1,157 @@
+
+# Test MAX_STATEMENT_TIME option syntax.
+
+CREATE TABLE t1 (a INT);
+SET @var = (SELECT MAX_STATEMENT_TIME=0 1);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1)' at line 1
+SELECT 1 FROM t1 WHERE a IN (SELECT MAX_STATEMENT_TIME=0 1);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1)' at line 1
+SELECT (SELECT MAX_STATEMENT_TIME=0 a FROM t1);
+ERROR 42S22: Unknown column 'MAX_STATEMENT_TIME' in 'field list'
+SELECT a FROM t1 WHERE a IN (SELECT MAX_STATEMENT_TIME=0 a FROM t1);
+ERROR 42S22: Unknown column 'MAX_STATEMENT_TIME' in 'field list'
+SELECT * FROM t1 WHERE a IN (SELECT MAX_STATEMENT_TIME=0 a FROM t1);
+ERROR 42S22: Unknown column 'MAX_STATEMENT_TIME' in 'field list'
+SELECT MAX_STATEMENT_TIME=0 * FROM t1
+WHERE a IN (SELECT MAX_STATEMENT_TIME=0 a FROM t1);
+ERROR 42S22: Unknown column 'MAX_STATEMENT_TIME' in 'field list'
+SELECT * FROM t1
+WHERE a IN (SELECT a FROM t1 UNION SELECT MAX_STATEMENT_TIME=0 a FROM t1);
+ERROR 42S22: Unknown column 'MAX_STATEMENT_TIME' in 'field list'
+SELECT MAX_STATEMENT_TIME=0 * FROM t1
+WHERE a IN (SELECT a FROM t1 UNION SELECT MAX_STATEMENT_TIME=0 a FROM t1);
+ERROR 42S22: Unknown column 'MAX_STATEMENT_TIME' in 'field list'
+SELECT * FROM t1 UNION SELECT MAX_STATEMENT_TIME=0 * FROM t1;
+ERROR 42000: Incorrect usage/placement of 'MAX_STATEMENT_TIME'
+SELECT MAX_STATEMENT_TIME=0 * FROM t1
+UNION SELECT MAX_STATEMENT_TIME=0 * FROM t1;
+ERROR 42000: Incorrect usage/placement of 'MAX_STATEMENT_TIME'
+INSERT INTO t1 SELECT MAX_STATEMENT_TIME=0 * FROM t1;
+ERROR 42000: Incorrect usage/placement of 'MAX_STATEMENT_TIME'
+CREATE TABLE t1 AS SELECT MAX_STATEMENT_TIME=0 * FROM t1;
+ERROR 42000: Incorrect usage/placement of 'MAX_STATEMENT_TIME'
+CREATE TABLE t1 AS SELECT 1 A UNION SELECT 2 UNION SELECT MAX_STATEMENT_TIME=0 3;
+ERROR 42000: Incorrect usage/placement of 'MAX_STATEMENT_TIME'
+SELECT MAX_STATEMENT_TIME=0 * FROM t1;
+a
+DROP TABLE t1;
+
+# Test the MAX_STATEMENT_TIME option.
+
+SELECT MAX_STATEMENT_TIME=1 SLEEP(1);
+SLEEP(1)
+1
+CREATE TABLE t1 (a INT, b VARCHAR(300));
+INSERT INTO t1 VALUES (1, 'string');
+SELECT 996;
+996
+996
+DROP TABLE t1;
+
+# Test the MAX_STATEMENT_TIME option with SF.
+
+CREATE TABLE t1 (a INT, b VARCHAR(300));
+INSERT INTO t1 VALUES (1, 'string');
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+WHILE true DO
+INSERT INTO t1 SELECT * FROM t1;
+END WHILE;
+RETURN 1;
+END|
+SELECT MAX_STATEMENT_TIME=500 f1();
+ERROR 70100: Query execution was interrupted, max_statement_time exceeded
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+# MAX_STATEMENT_TIME option takes precedence over @@max_statement_time.
+
+SET @@SESSION.max_statement_time = 100;
+SELECT MAX_STATEMENT_TIME=2000 SLEEP(1);
+SLEEP(1)
+0
+SET @@SESSION.max_statement_time = DEFAULT;
+
+# MAX_STATEMENT_TIME account resource
+
+GRANT USAGE ON *.* TO user1@localhost WITH MAX_STATEMENT_TIME 5000;
+# con1
+SELECT @@max_statement_time;
+@@max_statement_time
+5000
+# restart and reconnect
+SELECT @@max_statement_time;
+@@max_statement_time
+5000
+DROP USER user1@localhost;
+
+# MAX_STATEMENT_TIME status variables.
+
+SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_set
+FROM INFORMATION_SCHEMA.GLOBAL_STATUS
+WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_SET';
+SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_exceeded
+FROM INFORMATION_SCHEMA.GLOBAL_STATUS
+WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_EXCEEDED';
+SELECT MAX_STATEMENT_TIME=10 SLEEP(1);
+SLEEP(1)
+1
+# Ensure that the counters for:
+# - statements that are time limited; and
+# - statements that exceeded their maximum execution time
+# are incremented.
+SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS
+WHERE VARIABLE_NAME = 'MAX_STATEMENT_TIME_SET'
+ AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_set;
+STATUS
+1
+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 = 500;
+UPDATE t1 SET a = 2;
+ERROR 70100: Query execution was interrupted, max_statement_time exceeded
+SHOW WARNINGS;
+Level Code Message
+Error 996 Query execution was interrupted, max_statement_time exceeded
+Error 996 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 = 500;
+LOCK TABLES t1 WRITE;
+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;
Oops, something went wrong.

0 comments on commit 8efbad7

Please sign in to comment.