From b6b47f8824f57d434a51358017725ebc05e47535 Mon Sep 17 00:00:00 2001 From: Tatjana Azundris Nuernberg Date: Fri, 17 Feb 2012 19:02:17 +0000 Subject: [PATCH 01/41] BUG#13431369 - MAIN.VARIABLES-NOTEMBEDDED CRASHES THE SERVER SPORADICALLY ON WINDOWS On shutdown(), Windows can drop traffic still queued for sending even if that wasn't specifically requested. As a result, fatal errors (those after signaling which the server will drop the connection) were sometimes only seen as "connection lost" on the client side, because the server-side shutdown() erraneously discarded the correct error message before sending it. If on Windows, we now use the Windows API to access the (non-broken) equivalent of shutdown(). Backport from trunk include/violite.h: export mysql_socket_shutdown(). It lives in vio in the backport. sql/mysqld.cc: Go through our own shutdown() rather than straight to the POSIX one. vio/viosocket.c: Define mysql_socket_shutdown(). On UNIXoid systems, it's just a wrapper for shutdown(), but on Window, it uses DisconnectEx, which is magic. --- include/violite.h | 3 +++ sql/mysqld.cc | 16 ++++++++-------- vio/viosocket.c | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/include/violite.h b/include/violite.h index 32354938e13..5facd0911b7 100644 --- a/include/violite.h +++ b/include/violite.h @@ -61,6 +61,9 @@ int vio_close_pipe(Vio * vio); #define HANDLE void * #endif /* __WIN__ */ +/* backport from 5.6 where it is part of PSI, not vio_*() */ +int mysql_socket_shutdown(my_socket mysql_socket, int how); + void vio_delete(Vio* vio); int vio_close(Vio* vio); void vio_reset(Vio* vio, enum enum_vio_type type, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c47d39721b9..a37479dc4b4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -932,7 +932,7 @@ static void close_connections(void) { if (ip_sock != INVALID_SOCKET) { - (void) shutdown(ip_sock, SHUT_RDWR); + (void) mysql_socket_shutdown(ip_sock, SHUT_RDWR); (void) closesocket(ip_sock); ip_sock= INVALID_SOCKET; } @@ -964,7 +964,7 @@ static void close_connections(void) #ifdef HAVE_SYS_UN_H if (unix_sock != INVALID_SOCKET) { - (void) shutdown(unix_sock, SHUT_RDWR); + (void) mysql_socket_shutdown(unix_sock, SHUT_RDWR); (void) closesocket(unix_sock); (void) unlink(mysqld_unix_port); unix_sock= INVALID_SOCKET; @@ -1069,7 +1069,7 @@ static void close_server_sock() { ip_sock=INVALID_SOCKET; DBUG_PRINT("info",("calling shutdown on TCP/IP socket")); - VOID(shutdown(tmp_sock, SHUT_RDWR)); + VOID(mysql_socket_shutdown(tmp_sock, SHUT_RDWR)); #if defined(__NETWARE__) /* The following code is disabled for normal systems as it causes MySQL @@ -1084,7 +1084,7 @@ static void close_server_sock() { unix_sock=INVALID_SOCKET; DBUG_PRINT("info",("calling shutdown on unix socket")); - VOID(shutdown(tmp_sock, SHUT_RDWR)); + VOID(mysql_socket_shutdown(tmp_sock, SHUT_RDWR)); #if defined(__NETWARE__) /* The following code is disabled for normal systems as it may cause MySQL @@ -5091,7 +5091,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) if (req.sink) ((void (*)(int))req.sink)(req.fd); - (void) shutdown(new_sock, SHUT_RDWR); + (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); continue; } @@ -5106,7 +5106,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) if (getsockname(new_sock,&dummy, &dummyLen) < 0) { sql_perror("Error on new connection socket"); - (void) shutdown(new_sock, SHUT_RDWR); + (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); continue; } @@ -5118,7 +5118,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) if (!(thd= new THD)) { - (void) shutdown(new_sock, SHUT_RDWR); + (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); VOID(closesocket(new_sock)); continue; } @@ -5137,7 +5137,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) vio_delete(vio_tmp); else { - (void) shutdown(new_sock, SHUT_RDWR); + (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); } delete thd; diff --git a/vio/viosocket.c b/vio/viosocket.c index 024aacc5db2..9633a01f689 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -23,8 +23,15 @@ the file descriptior. */ +#ifdef __WIN__ + #include + #include + #pragma comment(lib, "ws2_32.lib") +#endif #include "vio_priv.h" + + int vio_errno(Vio *vio __attribute__((unused))) { return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ @@ -260,6 +267,37 @@ vio_was_interrupted(Vio *vio __attribute__((unused))) } +int +mysql_socket_shutdown(my_socket mysql_socket, int how) +{ + int result; + +#ifdef __WIN__ + static LPFN_DISCONNECTEX DisconnectEx = NULL; + if (DisconnectEx == NULL) + { + DWORD dwBytesReturned; + GUID guidDisconnectEx = WSAID_DISCONNECTEX; + WSAIoctl(mysql_socket, SIO_GET_EXTENSION_FUNCTION_POINTER, + &guidDisconnectEx, sizeof(GUID), + &DisconnectEx, sizeof(DisconnectEx), + &dwBytesReturned, NULL, NULL); + } +#endif + + /* Non instrumented code */ +#ifdef __WIN__ + if (DisconnectEx) + result= (DisconnectEx(mysql_socket, (LPOVERLAPPED) NULL, + (DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1; + else +#endif + result= shutdown(mysql_socket, how); + + return result; +} + + int vio_close(Vio * vio) { int r=0; @@ -272,7 +310,7 @@ int vio_close(Vio * vio) vio->type == VIO_TYPE_SSL); DBUG_ASSERT(vio->sd >= 0); - if (shutdown(vio->sd, SHUT_RDWR)) + if (mysql_socket_shutdown(vio->sd, SHUT_RDWR)) r= -1; if (closesocket(vio->sd)) r= -1; From ede9f4fab18049e5f22e782337d7876fdcb7eb4a Mon Sep 17 00:00:00 2001 From: Tatjana Azundris Nuernberg Date: Sun, 19 Feb 2012 03:18:49 +0000 Subject: [PATCH 02/41] BUG 13454045 - 63524: BUG #35396 "ABNORMAL/IMPOSSIBLE/LARGE QUERY_TIME AND LOCK_TIME" HAPPENS A If a query's end time is before before its start time, the system clock has been turn back (daylight savings time etc.). When the system clock is changed, we can't tell for certain a given query was actually slow. We did not protect against logging such a query with a bogus execution time (resulting from end_time - start_time being negative), and possibly logging it even though it did not really take long to run. We now have a sanity check in place. sql/sql_parse.cc: Make sure end time is not before start time - otherwise, we can be SURE the system clock was changed in between, but not by how much. In other words, when the clock is changed, we don't know how long a query ran, and whether it was slow. --- sql/sql_parse.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 989c3e0f42f..0f190809ab9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1734,8 +1734,9 @@ void log_slow_statement(THD *thd) ulonglong end_utime_of_query= thd->current_utime(); thd_proc_info(thd, "logging slow query"); - if (((end_utime_of_query - thd->utime_after_lock) > - thd->variables.long_query_time || + if ((((end_utime_of_query > thd->utime_after_lock) && + ((end_utime_of_query - thd->utime_after_lock) > + thd->variables.long_query_time)) || ((thd->server_status & (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) && opt_log_queries_not_using_indexes && From bd560bb7b68b14f1d439a91e58d689cb6064e123 Mon Sep 17 00:00:00 2001 From: Sunanda Menon Date: Mon, 20 Feb 2012 06:19:12 +0100 Subject: [PATCH 03/41] Raise version number after cloning 5.0.96 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 908171ca857..0f1968747c0 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.96) +AM_INIT_AUTOMAKE(mysql, 5.0.97) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=96 +NDB_VERSION_BUILD=97 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 457af3df74be62b8e17be0bb8cfc33a0e2c990b7 Mon Sep 17 00:00:00 2001 From: Karen Langford Date: Mon, 20 Feb 2012 17:03:24 +0100 Subject: [PATCH 04/41] Raise version number after cloning 5.1.62 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index fb6155aa0be..ccc2ac26570 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ dnl dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MySQL Server], [5.1.62], [], [mysql]) +AC_INIT([MySQL Server], [5.1.63], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM From 74374933c8db3c7f1de07ced89ce72dd705576b3 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 20 Feb 2012 22:59:11 +0100 Subject: [PATCH 05/41] Bug#11761296: 53775: QUERY ON PARTITIONED TABLE RETURNS CACHED RESULT FROM PREVIOUS TRANSACTION The current Query Cache API is not fully compatible with the partitioning engine. There is no good way to implement support for QC due to: 1) a static callback for ha_partition would need to have access to all partition names and call the underlying callback for each [sub]partition with the correct name. 2) pruning would be impossible, even if one used the ulonglong engine_data due to if engine_data is changed, the table is invalidated by the QC. So the only viable solution to avoid incorrect data is to not allow caching of queries using partitioned tables. (There are some extra changes, due to removal of \r as line break) --- mysql-test/include/query_cache.inc | 38 +++-- mysql-test/r/cache_innodb.result | 7 +- mysql-test/r/partition_cache.result | 205 +++++++++++++++++++++++++++ mysql-test/t/cache_innodb-master.opt | 1 - mysql-test/t/partition_cache.test | 21 +++ sql/ha_partition.cc | 28 ++-- sql/ha_partition.h | 20 ++- 7 files changed, 286 insertions(+), 34 deletions(-) create mode 100644 mysql-test/r/partition_cache.result delete mode 100644 mysql-test/t/cache_innodb-master.opt create mode 100644 mysql-test/t/partition_cache.test diff --git a/mysql-test/include/query_cache.inc b/mysql-test/include/query_cache.inc index 7ce97b42158..ecc5014880c 100644 --- a/mysql-test/include/query_cache.inc +++ b/mysql-test/include/query_cache.inc @@ -4,6 +4,9 @@ # $engine_type -- storage engine to be tested # $test_foreign_keys -- 0, skip foreign key tests # -- 1, do not skip foreign key tests +# $partitions_a -- partition by column 'a' +# $partitions_id -- partition by column 'id' +# $partitions_s1 -- partition by column 's1' # have to be set before sourcing this script. # # Last update: @@ -19,47 +22,61 @@ eval SET SESSION STORAGE_ENGINE = $engine_type; drop table if exists t1,t2,t3; --enable_warnings +set @save_query_cache_size = @@global.query_cache_size; +set GLOBAL query_cache_size = 1355776; + # # Without auto_commit. # flush status; set autocommit=0; -create table t1 (a int not null); +eval create table t1 (a int not null)$partitions_a; insert into t1 values (1),(2),(3); +--sorted_result select * from t1; show status like "Qcache_queries_in_cache"; drop table t1; commit; set autocommit=1; begin; -create table t1 (a int not null); +eval create table t1 (a int not null)$partitions_a; insert into t1 values (1),(2),(3); +--sorted_result select * from t1; show status like "Qcache_queries_in_cache"; drop table t1; commit; -create table t1 (a int not null); -create table t2 (a int not null); -create table t3 (a int not null); +eval create table t1 (a int not null)$partitions_a; +eval create table t2 (a int not null)$partitions_a; +eval create table t3 (a int not null)$partitions_a; insert into t1 values (1),(2); insert into t2 values (1),(2); insert into t3 values (1),(2); +--sorted_result select * from t1; +--sorted_result select * from t2; +--sorted_result select * from t3; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; begin; +--sorted_result select * from t1; +--sorted_result select * from t2; +--sorted_result select * from t3; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; insert into t1 values (3); insert into t2 values (3); insert into t1 values (4); +--sorted_result select * from t1; +--sorted_result select * from t2; +--sorted_result select * from t3; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; @@ -67,7 +84,7 @@ commit; show status like "Qcache_queries_in_cache"; drop table t3,t2,t1; -CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)); +eval CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id))$partitions_id; select count(*) from t1; insert into t1 (id) values (0); select count(*) from t1; @@ -78,8 +95,6 @@ if ($test_foreign_keys) # # one statement roll back inside transation # -let $save_query_cache_size=`select @@global.query_cache_size`; -set GLOBAL query_cache_size=1355776; CREATE TABLE t1 ( id int(10) NOT NULL auto_increment, a varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY a (a)); CREATE TABLE t2 ( id int(10) NOT NULL auto_increment, b varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY b (b)); CREATE TABLE t3 ( id int(10) NOT NULL auto_increment, t1_id int(10) NOT NULL default '0', t2_id int(10) NOT NULL default '0', state int(11) default NULL, PRIMARY KEY (id), UNIQUE KEY t1_id (t1_id,t2_id), KEY t2_id (t2_id,t1_id), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`), CONSTRAINT `t3_ibfk_2` FOREIGN KEY (`t2_id`) REFERENCES `t2` (`id`)); @@ -95,9 +110,6 @@ insert into t3 VALUES ( NULL, 1, 1, 2 ); commit; select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id = t2.id and t1.id = 1 order by t1.a asc; drop table t3,t2,t1; ---disable_query_log -eval set GLOBAL query_cache_size=$save_query_cache_size; ---enable_query_log } # @@ -118,7 +130,7 @@ SET GLOBAL query_cache_size = 200000; flush status; SET @@autocommit=1; eval SET SESSION STORAGE_ENGINE = $engine_type; -CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1)); +eval CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1))$partitions_s1; INSERT INTO t2 VALUES (1,repeat('a',10)),(2,repeat('a',10)),(3,repeat('a',10)),(4,repeat('a',10)); COMMIT; START TRANSACTION; @@ -176,8 +188,8 @@ show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; # Final cleanup -eval set GLOBAL query_cache_size=$save_query_cache_size; disconnect connection1; --source include/wait_until_disconnected.inc connection default; +set @@global.query_cache_size = @save_query_cache_size; drop table t2; diff --git a/mysql-test/r/cache_innodb.result b/mysql-test/r/cache_innodb.result index b59298727c5..03989c80b9d 100644 --- a/mysql-test/r/cache_innodb.result +++ b/mysql-test/r/cache_innodb.result @@ -1,5 +1,7 @@ SET SESSION STORAGE_ENGINE = InnoDB; drop table if exists t1,t2,t3; +set @save_query_cache_size = @@global.query_cache_size; +set GLOBAL query_cache_size = 1355776; flush status; set autocommit=0; create table t1 (a int not null); @@ -100,7 +102,7 @@ show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 2 drop table t3,t2,t1; -CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)); +CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)); select count(*) from t1; count(*) 0 @@ -109,7 +111,6 @@ select count(*) from t1; count(*) 1 drop table t1; -set GLOBAL query_cache_size=1355776; CREATE TABLE t1 ( id int(10) NOT NULL auto_increment, a varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY a (a)); CREATE TABLE t2 ( id int(10) NOT NULL auto_increment, b varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY b (b)); CREATE TABLE t3 ( id int(10) NOT NULL auto_increment, t1_id int(10) NOT NULL default '0', t2_id int(10) NOT NULL default '0', state int(11) default NULL, PRIMARY KEY (id), UNIQUE KEY t1_id (t1_id,t2_id), KEY t2_id (t2_id,t1_id), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`), CONSTRAINT `t3_ibfk_2` FOREIGN KEY (`t2_id`) REFERENCES `t2` (`id`)); @@ -218,5 +219,5 @@ Qcache_queries_in_cache 1 show status like "Qcache_hits"; Variable_name Value Qcache_hits 1 -set GLOBAL query_cache_size=1048576; +set @@global.query_cache_size = @save_query_cache_size; drop table t2; diff --git a/mysql-test/r/partition_cache.result b/mysql-test/r/partition_cache.result new file mode 100644 index 00000000000..e4e7cc8a4ac --- /dev/null +++ b/mysql-test/r/partition_cache.result @@ -0,0 +1,205 @@ +SET SESSION STORAGE_ENGINE = InnoDB; +drop table if exists t1,t2,t3; +set @save_query_cache_size = @@global.query_cache_size; +set GLOBAL query_cache_size = 1355776; +flush status; +set autocommit=0; +create table t1 (a int not null) PARTITION BY KEY (a) PARTITIONS 3; +insert into t1 values (1),(2),(3); +select * from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +drop table t1; +commit; +set autocommit=1; +begin; +create table t1 (a int not null) PARTITION BY KEY (a) PARTITIONS 3; +insert into t1 values (1),(2),(3); +select * from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +drop table t1; +commit; +create table t1 (a int not null) PARTITION BY KEY (a) PARTITIONS 3; +create table t2 (a int not null) PARTITION BY KEY (a) PARTITIONS 3; +create table t3 (a int not null) PARTITION BY KEY (a) PARTITIONS 3; +insert into t1 values (1),(2); +insert into t2 values (1),(2); +insert into t3 values (1),(2); +select * from t1; +a +1 +2 +select * from t2; +a +1 +2 +select * from t3; +a +1 +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +begin; +select * from t1; +a +1 +2 +select * from t2; +a +1 +2 +select * from t3; +a +1 +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +insert into t1 values (3); +insert into t2 values (3); +insert into t1 values (4); +select * from t1; +a +1 +2 +3 +4 +select * from t2; +a +1 +2 +3 +select * from t3; +a +1 +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +commit; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +drop table t3,t2,t1; +CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) PARTITION BY HASH (id) PARTITIONS 3; +select count(*) from t1; +count(*) +0 +insert into t1 (id) values (0); +select count(*) from t1; +count(*) +1 +drop table t1; +SET SESSION STORAGE_ENGINE = InnoDB; +SET @@autocommit=1; +connection default +SHOW VARIABLES LIKE 'have_query_cache'; +Variable_name Value +have_query_cache YES +SET GLOBAL query_cache_size = 200000; +flush status; +SET @@autocommit=1; +SET SESSION STORAGE_ENGINE = InnoDB; +CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1)) PARTITION BY KEY (s1) PARTITIONS 3; +INSERT INTO t2 VALUES (1,repeat('a',10)),(2,repeat('a',10)),(3,repeat('a',10)),(4,repeat('a',10)); +COMMIT; +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +0 +UPDATE t2 SET s2 = 'w' WHERE s1 = 3; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +connection connection1 +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +0 +INSERT INTO t2 VALUES (5,'w'); +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +COMMIT; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +connection default +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +COMMIT; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +connection connection1 +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +INSERT INTO t2 VALUES (6,'w'); +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +3 +connection default +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +DELETE from t2 WHERE s1=3; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +COMMIT; +connection connection1 +COMMIT; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +set @@global.query_cache_size = @save_query_cache_size; +drop table t2; diff --git a/mysql-test/t/cache_innodb-master.opt b/mysql-test/t/cache_innodb-master.opt deleted file mode 100644 index 5f0ebff98f6..00000000000 --- a/mysql-test/t/cache_innodb-master.opt +++ /dev/null @@ -1 +0,0 @@ ---set-variable=query_cache_size=1M diff --git a/mysql-test/t/partition_cache.test b/mysql-test/t/partition_cache.test new file mode 100644 index 00000000000..b5d19796b7c --- /dev/null +++ b/mysql-test/t/partition_cache.test @@ -0,0 +1,21 @@ +# t/cache_innodb.test +# +# Last update: +# 2006-07-26 ML test refactored (MySQL 5.1) +# main code t/innodb_cache.test --> include/query_cache.inc +# new wrapper t/cache_innodb.test +# + +--source include/have_query_cache.inc + +--source include/have_innodb.inc +--source include/have_partition.inc +let $engine_type= InnoDB; +# Using SELECT to get a space as first character. +let $partitions_a= `SELECT ' PARTITION BY KEY (a) PARTITIONS 3'`; +let $partitions_id= `SELECT ' PARTITION BY HASH (id) PARTITIONS 3'`; +let $partitions_s1= `SELECT ' PARTITION BY KEY (s1) PARTITIONS 3'`; +# partitioning does not support FOREIGN KEYs +let $test_foreign_keys= 0; + +--source include/query_cache.inc diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 7c7cf5a4302..7e044b5260e 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -6494,20 +6494,20 @@ int ha_partition::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys) return ret; err: if (file > m_file) - { - uint *key_numbers= (uint*) ha_thd()->alloc(sizeof(uint) * num_of_keys); - KEY *old_key_info= table_arg->key_info; - uint i; - /* Use the newly added key_info as table->key_info to remove them. */ - for (i= 0; i < num_of_keys; i++) - key_numbers[i]= i; - table_arg->key_info= key_info; - while (--file >= m_file) - { - (void) (*file)->prepare_drop_index(table_arg, key_numbers, num_of_keys); - (void) (*file)->final_drop_index(table_arg); - } - table_arg->key_info= old_key_info; + { + uint *key_numbers= (uint*) ha_thd()->alloc(sizeof(uint) * num_of_keys); + KEY *old_key_info= table_arg->key_info; + uint i; + /* Use the newly added key_info as table->key_info to remove them. */ + for (i= 0; i < num_of_keys; i++) + key_numbers[i]= i; + table_arg->key_info= key_info; + while (--file >= m_file) + { + (void) (*file)->prepare_drop_index(table_arg, key_numbers, num_of_keys); + (void) (*file)->final_drop_index(table_arg); + } + table_arg->key_info= old_key_info; } return ret; } diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 46e2f447a47..813c0ae8960 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -219,9 +219,9 @@ public: */ ha_partition(handlerton *hton, TABLE_SHARE * table); ha_partition(handlerton *hton, partition_info * part_info); - ha_partition(handlerton *hton, TABLE_SHARE *share, - partition_info *part_info_arg, - ha_partition *clone_arg, + ha_partition(handlerton *hton, TABLE_SHARE *share, + partition_info *part_info_arg, + ha_partition *clone_arg, MEM_ROOT *clone_mem_root_arg); ~ha_partition(); /* @@ -553,6 +553,20 @@ public: virtual int extra(enum ha_extra_function operation); virtual int extra_opt(enum ha_extra_function operation, ulong cachesize); virtual int reset(void); + /* + Do not allow caching of partitioned tables, since we cannot return + a callback or engine_data that would work for a generic engine. + */ + virtual my_bool register_query_cache_table(THD *thd, char *table_key, + uint key_length, + qc_engine_callback + *engine_callback, + ulonglong *engine_data) + { + *engine_callback= NULL; + *engine_data= 0; + return FALSE; + } private: static const uint NO_CURRENT_PART_ID; From bdd1a2f17a9ce608da6b9896b5fbcaa950f1de09 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 21 Feb 2012 14:13:31 +0200 Subject: [PATCH 06/41] bumped up the version of the main tree to match the security tree --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 908171ca857..0f1968747c0 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.96) +AM_INIT_AUTOMAKE(mysql, 5.0.97) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=96 +NDB_VERSION_BUILD=97 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From c2d0fea84e25aca620e7e6922de234e38a24703a Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Tue, 21 Feb 2012 17:57:07 +0200 Subject: [PATCH 07/41] Fix Bug#13639142 64128: INNODB ERROR IN SERVER LOG OF INNODB_BUG34300 Suppress innodb_bug34300 from failing if InnoDB prints: 120221 11:05:03 InnoDB: ERROR: the age of the last checkpoint is 9439048, InnoDB: which exceeds the log group capacity 9433498. by default the log capacity is 2 log files, 5 MB each. --- mysql-test/suite/innodb/t/innodb_bug34300.test | 1 + mysql-test/suite/innodb_plugin/t/innodb_bug34300.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/suite/innodb/t/innodb_bug34300.test b/mysql-test/suite/innodb/t/innodb_bug34300.test index 6c516ccb73e..c49b69f29fc 100644 --- a/mysql-test/suite/innodb/t/innodb_bug34300.test +++ b/mysql-test/suite/innodb/t/innodb_bug34300.test @@ -8,6 +8,7 @@ -- disable_query_log -- disable_result_log call mtr.add_suppression("InnoDB: Warning: a long semaphore wait:"); +call mtr.add_suppression("the age of the last checkpoint is"); # set packet size and reconnect SET @@global.max_allowed_packet=16777216; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug34300.test b/mysql-test/suite/innodb_plugin/t/innodb_bug34300.test index 8be53f0db30..6684ba692c8 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug34300.test +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug34300.test @@ -8,6 +8,7 @@ -- disable_query_log -- disable_result_log call mtr.add_suppression("InnoDB: Warning: a long semaphore wait:"); +call mtr.add_suppression("the age of the last checkpoint is"); # set packet size and reconnect let $max_packet=`select @@global.max_allowed_packet`; From f3eb021d5e0c09215b28bf82c10b2e3085ad7a38 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Wed, 22 Feb 2012 11:17:50 +0100 Subject: [PATCH 08/41] Bug#13519724 63793: CRASH IN DTCOLLATION::SET(DTCOLLATION &SET) Backport of fix for: Bug#53236 Segfault in DTCollation::set(DTCollation&) --- mysql-test/r/cast.result | 9 +++++++++ mysql-test/t/cast.test | 12 ++++++++++++ sql/sql_select.cc | 4 ++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index 44d57055e7f..d7a7503707b 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -468,4 +468,13 @@ NULL Warnings: Warning 1301 Result of cast_as_char() was larger than max_allowed_packet (2048) - truncated SET @@GLOBAL.max_allowed_packet=default; +# +# Bug#13519724 63793: CRASH IN DTCOLLATION::SET(DTCOLLATION &SET) +# +CREATE TABLE t1 (a VARCHAR(50)); +SELECT a FROM t1 +WHERE CAST(a as BINARY)=x'62736D697468' +AND CAST(a AS BINARY)=x'65736D697468'; +a +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index 426d7c7fdf2..4474736200c 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -297,4 +297,16 @@ connection default; disconnect newconn; SET @@GLOBAL.max_allowed_packet=default; +--echo # +--echo # Bug#13519724 63793: CRASH IN DTCOLLATION::SET(DTCOLLATION &SET) +--echo # + +CREATE TABLE t1 (a VARCHAR(50)); + +SELECT a FROM t1 +WHERE CAST(a as BINARY)=x'62736D697468' + AND CAST(a AS BINARY)=x'65736D697468'; + +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5f1efabfc97..0d8dc740431 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8546,10 +8546,10 @@ change_cond_ref_to_const(THD *thd, I_List *save_list, left_item->collation.collation == value->collation.collation)) { Item *tmp=value->clone_item(); - tmp->collation.set(right_item->collation); if (tmp) { + tmp->collation.set(right_item->collation); thd->change_item_tree(args + 1, tmp); func->update_used_tables(); if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC) @@ -8570,10 +8570,10 @@ change_cond_ref_to_const(THD *thd, I_List *save_list, right_item->collation.collation == value->collation.collation)) { Item *tmp= value->clone_item(); - tmp->collation.set(left_item->collation); if (tmp) { + tmp->collation.set(left_item->collation); thd->change_item_tree(args, tmp); value= tmp; func->update_used_tables(); From 6a0d03fce76616dd10e8d6bd83c19af26f8c5874 Mon Sep 17 00:00:00 2001 From: Chaithra Gopalareddy Date: Fri, 24 Feb 2012 11:53:36 +0530 Subject: [PATCH 09/41] Bug#13012483:EXPLAIN EXTENDED, PREPARED STATEMENT, CRASH IN CHECK_SIMPLE_EQUALITY PROBLEM: Crash in "check_simple_equality" when using a subquery with "IN" and "ALL" in prepare. ANALYSIS: Crash can be reproduced using a simplified query like this one: prepare s from "select 1 from g1 where 1 < all ( select @:=(1 in (select 1 from g1)) from g1)"; This bug is currently present only on 5.5.and 5.1. Its fixed as part of work log(#1110) in 5.6. We are taking one change to fix this in 5.5 and 5.1. Problem seems to be present because we are trying to evaluate "is_null" on an argument which is part of a subquery (In Item_is_not_null_test::update_used_tables()). But the condition to evaluate is only when we do not have a sub query present, which means to say that "with_subselect" is not set. With respect to the above query, we create an object of type "Item_in_optimizer" which by definition is always associated with a subquery. While in 5.6 we set "with_subselect" to true for "Item_in_optimizer" object, we do not do the same in 5.5. This results in the evaluation for "is_null" resulting in a coredump. So, we are now setting "with_subselect" to true for "Item_in_optimizer" in 5.1 and 5.5. mysql-test/r/func_in.result: Result file changes for the test case added mysql-test/t/func_in.test: Test case added for Bug#13012483 sql/item_cmpfunc.h: Changed Item_in_optimizer::Item_in_optimizer( ) to set "with_subselect" to true --- mysql-test/r/func_in.result | 10 ++++++++++ mysql-test/t/func_in.test | 13 +++++++++++++ sql/item_cmpfunc.h | 2 +- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index 0b6117581f3..7f0e607e789 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -776,4 +776,14 @@ SELECT 1 IN (YEAR(FROM_UNIXTIME(NULL)) ,1); 1 IN (YEAR(FROM_UNIXTIME(NULL)) ,1) 1 # +# +# Bug#13012483: EXPLAIN EXTENDED, PREPARED STATEMENT, CRASH IN CHECK_SIMPLE_EQUALITY +# +CREATE TABLE t1 (a INT); +PREPARE s FROM "SELECT 1 FROM t1 WHERE 1 < ALL (SELECT @:= (1 IN (SELECT 1 FROM t1)) FROM t1)"; +EXECUTE s; +1 +DROP TABLE t1; +# End of test BUG#13012483 +# End of 5.1 tests diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 08469b37967..dd4194e2a4e 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -562,4 +562,17 @@ SELECT 1 IN (YEAR(FROM_UNIXTIME(NULL)) ,1); --echo # +--echo # +--echo # Bug#13012483: EXPLAIN EXTENDED, PREPARED STATEMENT, CRASH IN CHECK_SIMPLE_EQUALITY +--echo # + +CREATE TABLE t1 (a INT); +PREPARE s FROM "SELECT 1 FROM t1 WHERE 1 < ALL (SELECT @:= (1 IN (SELECT 1 FROM t1)) FROM t1)"; +EXECUTE s; + +DROP TABLE t1; + +--echo # End of test BUG#13012483 + +--echo # --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 4d8cadfcce9..b185bf02790 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -254,7 +254,7 @@ public: Item_in_optimizer(Item *a, Item_in_subselect *b): Item_bool_func(a, my_reinterpret_cast(Item *)(b)), cache(0), save_cache(0), result_for_null_param(UNKNOWN) - {} + { with_subselect= true; } bool fix_fields(THD *, Item **); bool fix_left(THD *thd, Item **ref); bool is_null(); From 5682272e1c28ad2197c3f06ccb0c2a55aa71d469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 27 Feb 2012 23:19:14 +0200 Subject: [PATCH 10/41] Remove a bogus BLOB debug assertion that was added in Bug#13721257 fix. --- storage/innodb_plugin/row/row0row.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/storage/innodb_plugin/row/row0row.c b/storage/innodb_plugin/row/row0row.c index 7ec05f01821..c1f39fb68cb 100644 --- a/storage/innodb_plugin/row/row0row.c +++ b/storage/innodb_plugin/row/row0row.c @@ -245,15 +245,11 @@ row_build( #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG if (rec_offs_any_null_extern(rec, offsets)) { /* This condition can occur during crash recovery - before trx_rollback_active() has completed execution. - - This condition is possible if the server crashed - during an insert or update-by-delete-and-insert before - btr_store_big_rec_extern_fields() did mtr_commit() all - BLOB pointers to the freshly inserted clustered index - record. */ - ut_a(trx_assert_recovered( - row_get_rec_trx_id(rec, index, offsets))); + before trx_rollback_active() has completed execution, + or when a concurrently executing + row_ins_index_entry_low() has committed the B-tree + mini-transaction but has not yet managed to restore + the cursor position for writing the big_rec. */ ut_a(trx_undo_roll_ptr_is_insert( row_get_rec_roll_ptr(rec, index, offsets))); } From 1bd0c9b531dba8e774761ae18f4df852b468040e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Feb 2012 14:00:00 +0200 Subject: [PATCH 11/41] Bug#12861864 RACE CONDITION IN BTR_GET_SIZE() AND DROP INDEX/TABLE/DATABASE also filed as Bug#13146269, Bug#13713178 btr_get_size(): Add mtr_t parameter. Require that the caller S-latches index->lock. If index->page==FIL_NULL or the index is to be dropped, return ULINT_UNDEFINED to indicate that the statistics are unavailable. dict_update_statistics(): If btr_get_size() returns ULINT_UNDEFINED, fake the index cardinality statistics. dict_index_set_page(): Unused function, remove. row_drop_table_for_mysql(): Before starting to drop the table, mark the indexes unavailable in the data dictionary cache while holding index->lock X-latch. ha_innobase::prepare_drop_index(), ha_innobase::final_drop_index(): When setting index->to_be_dropped, acquire the index->lock X-latch. rb:960 approved by Jimmy Yang --- storage/innodb_plugin/ChangeLog | 8 +++++ storage/innodb_plugin/btr/btr0btr.c | 26 +++++++++------- storage/innodb_plugin/dict/dict0dict.c | 22 ++++++++++---- .../innodb_plugin/handler/handler0alter.cc | 12 ++++++-- storage/innodb_plugin/include/btr0btr.h | 7 +++-- storage/innodb_plugin/include/dict0dict.h | 14 ++------- storage/innodb_plugin/include/dict0dict.ic | 21 ++----------- storage/innodb_plugin/include/dict0mem.h | 10 ++++--- storage/innodb_plugin/row/row0mysql.c | 30 +++++++++++++++++-- 9 files changed, 93 insertions(+), 57 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index d6115a28148..373335b6ff5 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,11 @@ +2012-02-28 The InnoDB Team + + * btr/btr0btr.c, dict/dict0dict.c, include/btr0btr.h, + include/dict0dict.h, include/dict0dict.ic, include/dict0mem.h, + handler/handler0alter.cc, row/row0mysql.c: + Fix Bug#12861864 RACE CONDITION IN BTR_GET_SIZE() AND + DROP INDEX/TABLE/DATABASE + 2012-02-15 The InnoDB Team * btr/btr0btr.c, btr/btr0cur.c, fsp/fsp0fsp.c, ibuf/ibuf0ibuf.c, diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c index 20eb30588fa..05723c26e2f 100644 --- a/storage/innodb_plugin/btr/btr0btr.c +++ b/storage/innodb_plugin/btr/btr0btr.c @@ -991,45 +991,49 @@ btr_page_alloc( /**************************************************************//** Gets the number of pages in a B-tree. -@return number of pages */ +@return number of pages, or ULINT_UNDEFINED if the index is unavailable */ UNIV_INTERN ulint btr_get_size( /*=========*/ dict_index_t* index, /*!< in: index */ - ulint flag) /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ + ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ + mtr_t* mtr) /*!< in/out: mini-transaction where index + is s-latched */ { fseg_header_t* seg_header; page_t* root; ulint n; ulint dummy; - mtr_t mtr; - mtr_start(&mtr); + ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index), + MTR_MEMO_S_LOCK)); - mtr_s_lock(dict_index_get_lock(index), &mtr); + if (index->page == FIL_NULL + || index->to_be_dropped + || *index->name == TEMP_INDEX_PREFIX) { + return(ULINT_UNDEFINED); + } - root = btr_root_get(index, &mtr); + root = btr_root_get(index, mtr); if (flag == BTR_N_LEAF_PAGES) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; - fseg_n_reserved_pages(seg_header, &n, &mtr); + fseg_n_reserved_pages(seg_header, &n, mtr); } else if (flag == BTR_TOTAL_SIZE) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP; - n = fseg_n_reserved_pages(seg_header, &dummy, &mtr); + n = fseg_n_reserved_pages(seg_header, &dummy, mtr); seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; - n += fseg_n_reserved_pages(seg_header, &dummy, &mtr); + n += fseg_n_reserved_pages(seg_header, &dummy, mtr); } else { ut_error; } - mtr_commit(&mtr); - return(n); } diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c index 2d2262acf87..ef3567c360d 100644 --- a/storage/innodb_plugin/dict/dict0dict.c +++ b/storage/innodb_plugin/dict/dict0dict.c @@ -4267,16 +4267,27 @@ dict_update_statistics( (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO && dict_index_is_clust(index)))) { + mtr_t mtr; ulint size; - size = btr_get_size(index, BTR_TOTAL_SIZE); - index->stat_index_size = size; + mtr_start(&mtr); + mtr_s_lock(dict_index_get_lock(index), &mtr); - sum_of_index_sizes += size; + size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr); - size = btr_get_size(index, BTR_N_LEAF_PAGES); + if (size != ULINT_UNDEFINED) { + sum_of_index_sizes += size; + index->stat_index_size = size; + size = btr_get_size( + index, BTR_N_LEAF_PAGES, &mtr); + } - if (size == 0) { + mtr_commit(&mtr); + + switch (size) { + case ULINT_UNDEFINED: + goto fake_statistics; + case 0: /* The root node of the tree is a leaf */ size = 1; } @@ -4293,6 +4304,7 @@ dict_update_statistics( various means, also via secondary indexes. */ ulint i; +fake_statistics: sum_of_index_sizes++; index->stat_index_size = index->stat_n_leaf_pages = 1; diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc index 485e03737e3..e2702b157af 100644 --- a/storage/innodb_plugin/handler/handler0alter.cc +++ b/storage/innodb_plugin/handler/handler0alter.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 2005, 2012, 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 @@ -11,8 +11,8 @@ 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., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -1010,7 +1010,9 @@ ha_innobase::prepare_drop_index( goto func_exit; } + rw_lock_x_lock(dict_index_get_lock(index)); index->to_be_dropped = TRUE; + rw_lock_x_unlock(dict_index_get_lock(index)); } /* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined @@ -1129,7 +1131,9 @@ func_exit: = dict_table_get_first_index(prebuilt->table); do { + rw_lock_x_lock(dict_index_get_lock(index)); index->to_be_dropped = FALSE; + rw_lock_x_unlock(dict_index_get_lock(index)); index = dict_table_get_next_index(index); } while (index); } @@ -1189,7 +1193,9 @@ ha_innobase::final_drop_index( for (index = dict_table_get_first_index(prebuilt->table); index; index = dict_table_get_next_index(index)) { + rw_lock_x_lock(dict_index_get_lock(index)); index->to_be_dropped = FALSE; + rw_lock_x_unlock(dict_index_get_lock(index)); } goto func_exit; diff --git a/storage/innodb_plugin/include/btr0btr.h b/storage/innodb_plugin/include/btr0btr.h index 6e7bb8fc61e..793fbc76f3e 100644 --- a/storage/innodb_plugin/include/btr0btr.h +++ b/storage/innodb_plugin/include/btr0btr.h @@ -536,13 +536,16 @@ btr_parse_page_reorganize( #ifndef UNIV_HOTBACKUP /**************************************************************//** Gets the number of pages in a B-tree. -@return number of pages */ +@return number of pages, or ULINT_UNDEFINED if the index is unavailable */ UNIV_INTERN ulint btr_get_size( /*=========*/ dict_index_t* index, /*!< in: index */ - ulint flag); /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ + ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ + mtr_t* mtr) /*!< in/out: mini-transaction where index + is s-latched */ + __attribute__((nonnull, warn_unused_result)); /**************************************************************//** Allocates a new file page to be used in an index tree. NOTE: we assume that the caller has made the reservation for free extents! diff --git a/storage/innodb_plugin/include/dict0dict.h b/storage/innodb_plugin/include/dict0dict.h index fdb3bd5d50c..e728c78b9c0 100644 --- a/storage/innodb_plugin/include/dict0dict.h +++ b/storage/innodb_plugin/include/dict0dict.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -1018,14 +1018,6 @@ dict_index_get_page( /*================*/ const dict_index_t* tree); /*!< in: index */ /*********************************************************************//** -Sets the page number of the root of index tree. */ -UNIV_INLINE -void -dict_index_set_page( -/*================*/ - dict_index_t* index, /*!< in/out: index */ - ulint page); /*!< in: page number */ -/*********************************************************************//** Gets the read-write lock of the index tree. @return read-write lock */ UNIV_INLINE diff --git a/storage/innodb_plugin/include/dict0dict.ic b/storage/innodb_plugin/include/dict0dict.ic index 1704e9c2d71..f3d73b09bdb 100644 --- a/storage/innodb_plugin/include/dict0dict.ic +++ b/storage/innodb_plugin/include/dict0dict.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -722,21 +722,6 @@ dict_index_get_page( return(index->page); } -/*********************************************************************//** -Sets the page number of the root of index tree. */ -UNIV_INLINE -void -dict_index_set_page( -/*================*/ - dict_index_t* index, /*!< in/out: index */ - ulint page) /*!< in: page number */ -{ - ut_ad(index); - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - index->page = page; -} - /*********************************************************************//** Gets the read-write lock of the index tree. @return read-write lock */ diff --git a/storage/innodb_plugin/include/dict0mem.h b/storage/innodb_plugin/include/dict0mem.h index bd32a239cfd..1b26aea38c9 100644 --- a/storage/innodb_plugin/include/dict0mem.h +++ b/storage/innodb_plugin/include/dict0mem.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -305,7 +305,9 @@ struct dict_index_struct{ unsigned to_be_dropped:1; /*!< TRUE if this index is marked to be dropped in ha_innobase::prepare_drop_index(), - otherwise FALSE */ + otherwise FALSE. Protected by + dict_sys->mutex, dict_operation_lock and + index->lock.*/ dict_field_t* fields; /*!< array of field descriptions */ #ifndef UNIV_HOTBACKUP UT_LIST_NODE_T(dict_index_t) diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index 36aad4f8ca2..5f8fc6a903b 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2012, 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 @@ -11,8 +11,8 @@ 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., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -3013,6 +3013,7 @@ row_drop_table_for_mysql( { dict_foreign_t* foreign; dict_table_t* table; + dict_index_t* index; ulint space_id; ulint err; const char* table_name; @@ -3305,6 +3306,18 @@ check_next_foreign: "END;\n" , FALSE, trx); + /* Mark all indexes unavailable in the data dictionary cache + before starting to drop the table. */ + + for (index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + rw_lock_x_lock(dict_index_get_lock(index)); + ut_ad(!index->to_be_dropped); + index->to_be_dropped = TRUE; + rw_lock_x_unlock(dict_index_get_lock(index)); + } + switch (err) { ibool is_temp; const char* name_or_path; @@ -3384,6 +3397,17 @@ check_next_foreign: the undo log. We can directly exit here and return the DB_TOO_MANY_CONCURRENT_TRXS error. */ + + /* Mark all indexes available in the data dictionary + cache again. */ + + for (index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + rw_lock_x_lock(dict_index_get_lock(index)); + index->to_be_dropped = FALSE; + rw_lock_x_unlock(dict_index_get_lock(index)); + } break; case DB_OUT_OF_FILE_SPACE: From e74c9b71ab80d6795e3d4028f23b64a9acba7c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Feb 2012 21:41:55 +0200 Subject: [PATCH 12/41] Fix a mistake in the Bug#12861864 fix. row_drop_table_for_mysql(): Really flag the indexes unavailable before starting to drop the table. --- storage/innodb_plugin/row/row0mysql.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index 5f8fc6a903b..d67a7b29e1c 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -3220,6 +3220,18 @@ check_next_foreign: trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); trx->table_id = table->id; + /* Mark all indexes unavailable in the data dictionary cache + before starting to drop the table. */ + + for (index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + rw_lock_x_lock(dict_index_get_lock(index)); + ut_ad(!index->to_be_dropped); + index->to_be_dropped = TRUE; + rw_lock_x_unlock(dict_index_get_lock(index)); + } + /* We use the private SQL parser of Innobase to generate the query graphs needed in deleting the dictionary data from system tables in Innobase. Deleting a row from SYS_INDEXES table also @@ -3306,18 +3318,6 @@ check_next_foreign: "END;\n" , FALSE, trx); - /* Mark all indexes unavailable in the data dictionary cache - before starting to drop the table. */ - - for (index = dict_table_get_first_index(table); - index != NULL; - index = dict_table_get_next_index(index)) { - rw_lock_x_lock(dict_index_get_lock(index)); - ut_ad(!index->to_be_dropped); - index->to_be_dropped = TRUE; - rw_lock_x_unlock(dict_index_get_lock(index)); - } - switch (err) { ibool is_temp; const char* name_or_path; From c22c9270fb40a8a2df988084968c0e04dd07a4b8 Mon Sep 17 00:00:00 2001 From: Praveenkumar Hulakund Date: Wed, 29 Feb 2012 12:23:15 +0530 Subject: [PATCH 13/41] Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES IGNORED AND BREAKS REPLICATION Analysis: ======================== sql_mode "NO_BACKSLASH_ESCAPES": When user want to use backslash as character input, instead of escape character in a string literal then sql_mode can be set to "NO_BACKSLASH_ESCAPES". With this mode enabled, backslash becomes an ordinary character like any other. SQL_MODE set applies to the current client session. And while creating the stored procedure, MySQL stores the current sql_mode and always executes the stored procedure in sql_mode stored with the Procedure, regardless of the server SQL mode in effect when the routine is invoked. In the scenario (for which bug is reported), the routine is created with sql_mode=NO_BACKSLASH_ESCAPES. And routine is executed with the invoker sql_mode is "" (NOT SET) by executing statement "call testp('Axel\'s')". Since invoker sql_mode is "" (NOT_SET), the '\' in 'Axel\'s'(argument to function) is considered as escape character and column "a" (of table "t1") values are updated with "Axel's". The binary log generated for above update operation is as below, set sql_mode=XXXXXX (for no_backslash_escapes) update test.t1 set a= NAME_CONST('var',_latin1'Axel\'s' COLLATE 'latin1_swedish_ci'); While logging stored procedure statements, the local variables (params) used in statements are replaced with the NAME_CONST(var_name, var_value) (Internal function) (http://dev.mysql.com/doc/refman/5.6/en/miscellaneous-functions.html#function_name-const) On slave, these logs are applied. NAME_CONST is parsed to get the variable and its value. Since, stored procedure is created with sql_mode="NO_BACKSLASH_ESCAPES", the sql_mode is also logged in. So that at slave this sql_mode is set before executing the statements of routine. So at slave, sql_mode is set to "NO_BACKSLASH_ESCAPES" and then while parsing NAME_CONST of string variable, '\' is considered as NON ESCAPE character and parsing reported error for "'" (as we have only one "'" no backslash). At slave, parsing was proper with sql_mode "NO_BACKSLASH_ESCAPES". But above error reported while writing bin log, "'" (of Axel's) is escaped with "\" character. Actually, all special characters (n, r, ', ", \, 0...) are escaped while writing NAME_CONST for string variable(param, local variable) in bin log Airrespective of "NO_BACKSLASH_ESCAPES" sql_mode. So, basically, the problem is that logging string parameter does not take into account sql_mode value. Fix: ======================== So when sql_mode is set to "NO_BACKSLASH_ESCAPES", escaping characters as (n, r, ', ", \, 0...) should be avoided. To do so, added a check to not to escape such characters while writing NAME_CONST for string variables in bin log. And when sql_mode is set to NO_BACKSLASH_ESCAPES, quote character "'" is represented as ''. http://dev.mysql.com/doc/refman/5.6/en/string-literals.html (There are several ways to include quote characters within a string: ) mysql-test/r/sql_mode.result: Added test case for Bug#12601974. mysql-test/suite/binlog/r/binlog_sql_mode.result: Appended result of test cases added for Bug#12601974. mysql-test/suite/binlog/t/binlog_sql_mode.test: Added test case for Bug#12601974. mysql-test/t/sql_mode.test: Appended result of test cases added for Bug#12601974. --- mysql-test/r/sql_mode.result | 204 ++++++++++++++++++ .../suite/binlog/r/binlog_sql_mode.result | 111 ++++++++++ .../suite/binlog/t/binlog_sql_mode.test | 96 +++++++++ mysql-test/t/sql_mode.test | 154 +++++++++++++ sql/item.cc | 7 +- sql/item.h | 2 +- sql/log_event.cc | 25 ++- sql/mysql_priv.h | 2 +- sql/sp_head.cc | 2 +- sql/sql_prepare.cc | 6 +- 10 files changed, 596 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index 0b0d5a38d0b..fb192c25087 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -527,3 +527,207 @@ SELECT * FROM mysql.columns_priv WHERE Host = 'localhost' AND User LIKE 'user_%P Host Db User Table_name Column_name Timestamp Column_priv DROP TABLE t1; DROP TABLE t2; + +# +# Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES +# IGNORED AND BREAKS REPLICATION +# +DROP TABLE IF EXISTS test_table; +DROP FUNCTION IF EXISTS test_function; +CREATE TABLE test_table (c1 CHAR(50)); +SET @org_mode=@@sql_mode; +SET @@sql_mode=''; +PREPARE insert_stmt FROM 'INSERT INTO test_table VALUES (?)'; +PREPARE update_stmt FROM 'UPDATE test_table SET c1= ? WHERE c1= ?'; +CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50) +BEGIN +DECLARE char_val CHAR(50); +SELECT c1 INTO char_val FROM test_table WHERE c1=var; +RETURN char_val; +END +$ +SET @var1='abcd\'ef'; +SET @var2='abcd\"ef'; +SET @var3='abcd\bef'; +SET @var4='abcd\nef'; +SET @var5='abcd\ref'; +SET @var6='abcd\tef'; +SET @var7='abcd\\ef'; +SET @var8='abcd\%ef'; +SET @var9='abcd\_ef'; +SET @to_var1='wxyz\'ef'; +SET @to_var2='wxyz\"ef'; +SET @to_var3='wxyz\bef'; +SET @to_var4='wxyz\nef'; +SET @to_var5='wxyz\ref'; +SET @to_var6='wxyz\tef'; +SET @to_var7='wxyz\\ef'; +SET @to_var8='wxyz\%ef'; +SET @to_var9='wxyz\_ef'; +# STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +EXECUTE insert_stmt USING @var1; +EXECUTE insert_stmt USING @var2; +EXECUTE insert_stmt USING @var3; +EXECUTE insert_stmt USING @var4; +EXECUTE insert_stmt USING @var5; +EXECUTE insert_stmt USING @var6; +EXECUTE insert_stmt USING @var7; +EXECUTE insert_stmt USING @var8; +EXECUTE insert_stmt USING @var9; +SELECT * FROM test_table; +c1 +abcd'ef +abcd"ef +abcdef +abcd +ef +abcd ef +abcd ef +abcd\ef +abcd\%ef +abcd\_ef +EXECUTE update_stmt USING @to_var1, @var1; +EXECUTE update_stmt USING @to_var2, @var2; +EXECUTE update_stmt USING @to_var3, @var3; +EXECUTE update_stmt USING @to_var4, @var4; +EXECUTE update_stmt USING @to_var5, @var5; +EXECUTE update_stmt USING @to_var6, @var6; +EXECUTE update_stmt USING @to_var7, @var7; +EXECUTE update_stmt USING @to_var8, @var8; +EXECUTE update_stmt USING @to_var9, @var9; +SELECT * FROM test_table; +c1 +wxyz'ef +wxyz"ef +wxyzef +wxyz +ef +wxyz ef +wxyz ef +wxyz\ef +wxyz\%ef +wxyz\_ef + +# END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +# STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +select test_function(@to_var1); +test_function(@to_var1) +wxyz'ef +SELECT test_function(@to_var2); +test_function(@to_var2) +wxyz"ef +SELECT test_function(@to_var3); +test_function(@to_var3) +wxyzef +SELECT test_function(@to_var4); +test_function(@to_var4) +wxyz +ef +SELECT test_function(@to_var5); +test_function(@to_var5) +wxyz ef +SELECT test_function(@to_var6); +test_function(@to_var6) +wxyz ef +SELECT test_function(@to_var7); +test_function(@to_var7) +wxyz\ef +SELECT test_function(@to_var8); +test_function(@to_var8) +wxyz\%ef +SELECT test_function(@to_var9); +test_function(@to_var9) +wxyz\_ef + +# END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +DELETE FROM test_table; +DROP FUNCTION test_function; +SET @@sql_mode='NO_BACKSLASH_ESCAPES'; +CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50) +BEGIN +DECLARE char_val CHAR(50); +SELECT c1 INTO char_val FROM test_table WHERE c1=var; +RETURN char_val; +END +$ +# STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +EXECUTE insert_stmt USING @var1; +EXECUTE insert_stmt USING @var2; +EXECUTE insert_stmt USING @var3; +EXECUTE insert_stmt USING @var4; +EXECUTE insert_stmt USING @var5; +EXECUTE insert_stmt USING @var6; +EXECUTE insert_stmt USING @var7; +EXECUTE insert_stmt USING @var8; +EXECUTE insert_stmt USING @var9; +SELECT * FROM test_table; +c1 +abcd'ef +abcd"ef +abcdef +abcd +ef +abcd ef +abcd ef +abcd\ef +abcd\%ef +abcd\_ef +EXECUTE update_stmt USING @to_var1, @var1; +EXECUTE update_stmt USING @to_var2, @var2; +EXECUTE update_stmt USING @to_var3, @var3; +EXECUTE update_stmt USING @to_var4, @var4; +EXECUTE update_stmt USING @to_var5, @var5; +EXECUTE update_stmt USING @to_var6, @var6; +EXECUTE update_stmt USING @to_var7, @var7; +EXECUTE update_stmt USING @to_var8, @var8; +EXECUTE update_stmt USING @to_var9, @var9; +SELECT * FROM test_table; +c1 +wxyz'ef +wxyz"ef +wxyzef +wxyz +ef +wxyz ef +wxyz ef +wxyz\ef +wxyz\%ef +wxyz\_ef + +# END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +# STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +select test_function(@to_var1); +test_function(@to_var1) +wxyz'ef +SELECT test_function(@to_var2); +test_function(@to_var2) +wxyz"ef +SELECT test_function(@to_var3); +test_function(@to_var3) +wxyzef +SELECT test_function(@to_var4); +test_function(@to_var4) +wxyz +ef +SELECT test_function(@to_var5); +test_function(@to_var5) +wxyz ef +SELECT test_function(@to_var6); +test_function(@to_var6) +wxyz ef +SELECT test_function(@to_var7); +test_function(@to_var7) +wxyz\ef +SELECT test_function(@to_var8); +test_function(@to_var8) +wxyz\%ef +SELECT test_function(@to_var9); +test_function(@to_var9) +wxyz\_ef + +# END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +DROP TABLE test_table; +DROP FUNCTION test_function; +SET @@sql_mode= @org_mode; + +#End of Test for Bug#12601974 diff --git a/mysql-test/suite/binlog/r/binlog_sql_mode.result b/mysql-test/suite/binlog/r/binlog_sql_mode.result index 4477c94a95e..1aea77c4a4b 100644 --- a/mysql-test/suite/binlog/r/binlog_sql_mode.result +++ b/mysql-test/suite/binlog/r/binlog_sql_mode.result @@ -38,3 +38,114 @@ DROP VIEW testView; DROP TABLE t1; SET @@global.sql_mode= @old_sql_mode; SET @@session.binlog_format=@old_binlog_format; + +# +# Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES +# IGNORED AND BREAKS REPLICATION +# +DROP DATABASE IF EXISTS mysqltest_db; +DROP TABLE IF EXISTS test_table; +CREATE DATABASE mysqltest_db; +USE mysqltest_db; +CREATE TABLE test_table (c1 CHAR(50)); +SET @org_mode=@@sql_mode; +SET @@sql_mode=''; +CREATE PROCEDURE proc_without_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50)) +BEGIN +DECLARE var1 CHAR(50) DEFAULT param1; +DECLARE var2 CHAR(50) DEFAULT param2; +DECLARE var3 CHAR(50) DEFAULT 'abcd\bef'; +DECLARE var4 CHAR(50) DEFAULT 'abcd\nef'; +DECLARE var5 CHAR(50) DEFAULT 'abcd\ref'; +DECLARE var6 CHAR(50) DEFAULT 'abcd\tef'; +DECLARE var7 CHAR(50) DEFAULT 'abcd\\ef'; +DECLARE var8 CHAR(50) DEFAULT 'abcd\%ef'; +DECLARE var9 CHAR(50) DEFAULT 'abcd\_ef'; +INSERT INTO test_table VALUES (var1); +INSERT INTO test_table VALUES (var2); +INSERT INTO test_table VALUES (var3); +INSERT INTO test_table VALUES (var4); +INSERT INTO test_table VALUES (var5); +INSERT INTO test_table VALUES (var6); +INSERT INTO test_table VALUES (var7); +INSERT INTO test_table VALUES (var8); +INSERT INTO test_table VALUES (var9); +END +$ +SET @@sql_mode='NO_BACKSLASH_ESCAPES'$ +CREATE PROCEDURE proc_with_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50)) +BEGIN +DECLARE var1 CHAR(50) DEFAULT param1; +DECLARE var2 CHAR(50) DEFAULT param2; +DECLARE var3 CHAR(50) DEFAULT 'wxyz\bef'; +DECLARE var4 CHAR(50) DEFAULT 'wxyz\nef'; +DECLARE var5 CHAR(50) DEFAULT 'wxyz\ref'; +DECLARE var6 CHAR(50) DEFAULT 'wxyz\tef'; +DECLARE var7 CHAR(50) DEFAULT 'wxyz\\ef'; +DECLARE var8 CHAR(50) DEFAULT 'wxyz\%ef'; +DECLARE var9 CHAR(50) DEFAULT 'wxyz\_ef'; +INSERT INTO test_table VALUES (var1); +INSERT INTO test_table VALUES (var2); +INSERT INTO test_table VALUES (var3); +INSERT INTO test_table VALUES (var4); +INSERT INTO test_table VALUES (var5); +INSERT INTO test_table VALUES (var6); +INSERT INTO test_table VALUES (var7); +INSERT INTO test_table VALUES (var8); +INSERT INTO test_table VALUES (var9); +END +$ +SET @@sql_mode=''; +CALL proc_without_sql_mode('abcd\'ef', 'abcd\"ef'); +CALL proc_with_sql_mode('wxyz\'ef', 'wxyz\"ef'); +SELECT * FROM test_table; +c1 +abcd'ef +abcd"ef +abcdef +abcd +ef +abcd ef +abcd ef +abcd\ef +abcd\%ef +abcd\_ef +wxyz'ef +wxyz"ef +wxyz\bef +wxyz\nef +wxyz\ref +wxyz\tef +wxyz\\ef +wxyz\%ef +wxyz\_ef +"Dropping table test_table" +DROP TABLE test_table; +#"test_table" content after replaying the binlog +SELECT * FROM test_table; +c1 +abcd'ef +abcd"ef +abcdef +abcd +ef +abcd ef +abcd ef +abcd\ef +abcd\%ef +abcd\_ef +wxyz'ef +wxyz"ef +wxyz\bef +wxyz\nef +wxyz\ref +wxyz\tef +wxyz\\ef +wxyz\%ef +wxyz\_ef +#Clean up +DROP DATABASE mysqltest_db; +SET @@sql_mode= @org_mode; +use test; + +#End of Test for Bug#12601974 diff --git a/mysql-test/suite/binlog/t/binlog_sql_mode.test b/mysql-test/suite/binlog/t/binlog_sql_mode.test index ab4f6450543..167c8f5a96d 100644 --- a/mysql-test/suite/binlog/t/binlog_sql_mode.test +++ b/mysql-test/suite/binlog/t/binlog_sql_mode.test @@ -73,3 +73,99 @@ DROP TABLE t1; SET @@global.sql_mode= @old_sql_mode; SET @@session.binlog_format=@old_binlog_format; + +--echo +--echo # +--echo # Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES +--echo # IGNORED AND BREAKS REPLICATION +--echo # + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest_db; +DROP TABLE IF EXISTS test_table; +--enable_warnings + +CREATE DATABASE mysqltest_db; +USE mysqltest_db; +CREATE TABLE test_table (c1 CHAR(50)); + +SET @org_mode=@@sql_mode; + +SET @@sql_mode=''; +DELIMITER $; +CREATE PROCEDURE proc_without_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50)) +BEGIN + DECLARE var1 CHAR(50) DEFAULT param1; + DECLARE var2 CHAR(50) DEFAULT param2; + DECLARE var3 CHAR(50) DEFAULT 'abcd\bef'; + DECLARE var4 CHAR(50) DEFAULT 'abcd\nef'; + DECLARE var5 CHAR(50) DEFAULT 'abcd\ref'; + DECLARE var6 CHAR(50) DEFAULT 'abcd\tef'; + DECLARE var7 CHAR(50) DEFAULT 'abcd\\ef'; + DECLARE var8 CHAR(50) DEFAULT 'abcd\%ef'; + DECLARE var9 CHAR(50) DEFAULT 'abcd\_ef'; + + INSERT INTO test_table VALUES (var1); + INSERT INTO test_table VALUES (var2); + INSERT INTO test_table VALUES (var3); + INSERT INTO test_table VALUES (var4); + INSERT INTO test_table VALUES (var5); + INSERT INTO test_table VALUES (var6); + INSERT INTO test_table VALUES (var7); + INSERT INTO test_table VALUES (var8); + INSERT INTO test_table VALUES (var9); +END +$ + +SET @@sql_mode='NO_BACKSLASH_ESCAPES'$ +CREATE PROCEDURE proc_with_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50)) +BEGIN + DECLARE var1 CHAR(50) DEFAULT param1; + DECLARE var2 CHAR(50) DEFAULT param2; + DECLARE var3 CHAR(50) DEFAULT 'wxyz\bef'; + DECLARE var4 CHAR(50) DEFAULT 'wxyz\nef'; + DECLARE var5 CHAR(50) DEFAULT 'wxyz\ref'; + DECLARE var6 CHAR(50) DEFAULT 'wxyz\tef'; + DECLARE var7 CHAR(50) DEFAULT 'wxyz\\ef'; + DECLARE var8 CHAR(50) DEFAULT 'wxyz\%ef'; + DECLARE var9 CHAR(50) DEFAULT 'wxyz\_ef'; + + INSERT INTO test_table VALUES (var1); + INSERT INTO test_table VALUES (var2); + INSERT INTO test_table VALUES (var3); + INSERT INTO test_table VALUES (var4); + INSERT INTO test_table VALUES (var5); + INSERT INTO test_table VALUES (var6); + INSERT INTO test_table VALUES (var7); + INSERT INTO test_table VALUES (var8); + INSERT INTO test_table VALUES (var9); +END +$ + +DELIMITER ;$ +SET @@sql_mode=''; +CALL proc_without_sql_mode('abcd\'ef', 'abcd\"ef'); +CALL proc_with_sql_mode('wxyz\'ef', 'wxyz\"ef'); +SELECT * FROM test_table; + +let $MYSQLD_DATADIR= `select @@datadir`; +--exec $MYSQL_BINLOG --force-if-open -d mysqltest_db $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog + +--echo "Dropping table test_table" +DROP TABLE test_table; + +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog" + +--echo #"test_table" content after replaying the binlog +SELECT * FROM test_table; + +--echo #Clean up +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog +DROP DATABASE mysqltest_db; +SET @@sql_mode= @org_mode; +use test; + +--echo +--echo #End of Test for Bug#12601974 + + diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test index 4a9f34443cb..526791d9a42 100644 --- a/mysql-test/t/sql_mode.test +++ b/mysql-test/t/sql_mode.test @@ -344,3 +344,157 @@ SELECT * FROM mysql.columns_priv WHERE Host = 'localhost' AND User LIKE 'user_%P # Cleanup DROP TABLE t1; DROP TABLE t2; + + +--echo +--echo # +--echo # Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES +--echo # IGNORED AND BREAKS REPLICATION +--echo # + +--disable_warnings +DROP TABLE IF EXISTS test_table; +DROP FUNCTION IF EXISTS test_function; +--enable_warnings + +CREATE TABLE test_table (c1 CHAR(50)); + +SET @org_mode=@@sql_mode; + +SET @@sql_mode=''; + +PREPARE insert_stmt FROM 'INSERT INTO test_table VALUES (?)'; +PREPARE update_stmt FROM 'UPDATE test_table SET c1= ? WHERE c1= ?'; +DELIMITER $; +CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50) +BEGIN + DECLARE char_val CHAR(50); + SELECT c1 INTO char_val FROM test_table WHERE c1=var; + RETURN char_val; +END +$ +DELIMITER ;$ + +SET @var1='abcd\'ef'; +SET @var2='abcd\"ef'; +SET @var3='abcd\bef'; +SET @var4='abcd\nef'; +SET @var5='abcd\ref'; +SET @var6='abcd\tef'; +SET @var7='abcd\\ef'; +SET @var8='abcd\%ef'; +SET @var9='abcd\_ef'; + +SET @to_var1='wxyz\'ef'; +SET @to_var2='wxyz\"ef'; +SET @to_var3='wxyz\bef'; +SET @to_var4='wxyz\nef'; +SET @to_var5='wxyz\ref'; +SET @to_var6='wxyz\tef'; +SET @to_var7='wxyz\\ef'; +SET @to_var8='wxyz\%ef'; +SET @to_var9='wxyz\_ef'; + +--echo # STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +EXECUTE insert_stmt USING @var1; +EXECUTE insert_stmt USING @var2; +EXECUTE insert_stmt USING @var3; +EXECUTE insert_stmt USING @var4; +EXECUTE insert_stmt USING @var5; +EXECUTE insert_stmt USING @var6; +EXECUTE insert_stmt USING @var7; +EXECUTE insert_stmt USING @var8; +EXECUTE insert_stmt USING @var9; + +SELECT * FROM test_table; + +EXECUTE update_stmt USING @to_var1, @var1; +EXECUTE update_stmt USING @to_var2, @var2; +EXECUTE update_stmt USING @to_var3, @var3; +EXECUTE update_stmt USING @to_var4, @var4; +EXECUTE update_stmt USING @to_var5, @var5; +EXECUTE update_stmt USING @to_var6, @var6; +EXECUTE update_stmt USING @to_var7, @var7; +EXECUTE update_stmt USING @to_var8, @var8; +EXECUTE update_stmt USING @to_var9, @var9; + +SELECT * FROM test_table; + +--echo +--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT + +--echo # STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +select test_function(@to_var1); +SELECT test_function(@to_var2); +SELECT test_function(@to_var3); +SELECT test_function(@to_var4); +SELECT test_function(@to_var5); +SELECT test_function(@to_var6); +SELECT test_function(@to_var7); +SELECT test_function(@to_var8); +SELECT test_function(@to_var9); + +--echo +--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +DELETE FROM test_table; +DROP FUNCTION test_function; + +SET @@sql_mode='NO_BACKSLASH_ESCAPES'; +DELIMITER $; +CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50) +BEGIN + DECLARE char_val CHAR(50); + SELECT c1 INTO char_val FROM test_table WHERE c1=var; + RETURN char_val; +END +$ +DELIMITER ;$ + +--echo # STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +EXECUTE insert_stmt USING @var1; +EXECUTE insert_stmt USING @var2; +EXECUTE insert_stmt USING @var3; +EXECUTE insert_stmt USING @var4; +EXECUTE insert_stmt USING @var5; +EXECUTE insert_stmt USING @var6; +EXECUTE insert_stmt USING @var7; +EXECUTE insert_stmt USING @var8; +EXECUTE insert_stmt USING @var9; + +SELECT * FROM test_table; + +EXECUTE update_stmt USING @to_var1, @var1; +EXECUTE update_stmt USING @to_var2, @var2; +EXECUTE update_stmt USING @to_var3, @var3; +EXECUTE update_stmt USING @to_var4, @var4; +EXECUTE update_stmt USING @to_var5, @var5; +EXECUTE update_stmt USING @to_var6, @var6; +EXECUTE update_stmt USING @to_var7, @var7; +EXECUTE update_stmt USING @to_var8, @var8; +EXECUTE update_stmt USING @to_var9, @var9; + +SELECT * FROM test_table; + +--echo +--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT + +--echo # STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +select test_function(@to_var1); +SELECT test_function(@to_var2); +SELECT test_function(@to_var3); +SELECT test_function(@to_var4); +SELECT test_function(@to_var5); +SELECT test_function(@to_var6); +SELECT test_function(@to_var7); +SELECT test_function(@to_var8); +SELECT test_function(@to_var9); + +--echo +--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING + +DROP TABLE test_table; +DROP FUNCTION test_function; +SET @@sql_mode= @org_mode; + +--echo +--echo #End of Test for Bug#12601974 diff --git a/sql/item.cc b/sql/item.cc index f80d862e856..2a7d2453889 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3085,7 +3085,7 @@ String *Item_param::val_str(String* str) that binary log contains wrong statement */ -const String *Item_param::query_val_str(String* str) const +const String *Item_param::query_val_str(THD *thd, String* str) const { switch (state) { case INT_VALUE: @@ -3123,7 +3123,8 @@ const String *Item_param::query_val_str(String* str) const case LONG_DATA_VALUE: { str->length(0); - append_query_string(value.cs_info.character_set_client, &str_value, str); + append_query_string(thd, value.cs_info.character_set_client, &str_value, + str); break; } case NULL_VALUE: @@ -3256,7 +3257,7 @@ void Item_param::print(String *str, enum_query_type query_type) char buffer[STRING_BUFFER_USUAL_SIZE]; String tmp(buffer, sizeof(buffer), &my_charset_bin); const String *res; - res= query_val_str(&tmp); + res= query_val_str(current_thd, &tmp); str->append(*res); } } diff --git a/sql/item.h b/sql/item.h index 8d7ad3c41d3..1934e005776 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1703,7 +1703,7 @@ public: */ void (*set_param_func)(Item_param *param, uchar **pos, ulong len); - const String *query_val_str(String *str) const; + const String *query_val_str(THD *thd, String *str) const; bool convert_str_value(THD *thd); diff --git a/sql/log_event.cc b/sql/log_event.cc index fac3e3f264b..427f27650dd 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -572,7 +572,7 @@ char *str_to_hex(char *to, const char *from, uint len) */ int -append_query_string(CHARSET_INFO *csinfo, +append_query_string(THD *thd, CHARSET_INFO *csinfo, String const *from, String *to) { char *beg, *ptr; @@ -587,9 +587,26 @@ append_query_string(CHARSET_INFO *csinfo, else { *ptr++= '\''; - ptr+= escape_string_for_mysql(csinfo, ptr, 0, - from->ptr(), from->length()); - *ptr++='\''; + if (!(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)) + { + ptr+= escape_string_for_mysql(csinfo, ptr, 0, + from->ptr(), from->length()); + } + else + { + const char *frm_str= from->ptr(); + + for (; frm_str < (from->ptr() + from->length()); frm_str++) + { + /* Using '' way to represent "'" */ + if (*frm_str == '\'') + *ptr++= *frm_str; + + *ptr++= *frm_str; + } + } + + *ptr++= '\''; } to->length(orig_len + ptr - beg); return 0; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4b89a7a7961..359e84a3370 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -799,7 +799,7 @@ bool delete_precheck(THD *thd, TABLE_LIST *tables); bool insert_precheck(THD *thd, TABLE_LIST *tables); bool create_table_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *create_table); -int append_query_string(CHARSET_INFO *csinfo, +int append_query_string(THD *thd, CHARSET_INFO *csinfo, String const *from, String *to); void get_default_definer(THD *thd, LEX_USER *definer); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 8bea0be0f56..db9142e47f5 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -157,7 +157,7 @@ sp_get_item_value(THD *thd, Item *item, String *str) buf.append(result->charset()->csname); if (cs->escape_with_backslash_is_dangerous) buf.append(' '); - append_query_string(cs, result, &buf); + append_query_string(thd, cs, result, &buf); buf.append(" COLLATE '"); buf.append(item->collation.collation->name); buf.append('\''); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index ec7a7fb73b8..98379dba9ba 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -795,7 +795,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, */ else if (! is_param_long_data_type(param)) DBUG_RETURN(1); - res= param->query_val_str(&str); + res= param->query_val_str(thd, &str); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ @@ -969,7 +969,7 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt, DBUG_RETURN(1); } } - res= param->query_val_str(&str); + res= param->query_val_str(thd, &str); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ @@ -1115,7 +1115,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, setup_one_conversion_function(thd, param, param->param_type); if (param->set_from_user_var(thd, entry)) DBUG_RETURN(1); - val= param->query_val_str(&buf); + val= param->query_val_str(thd, &buf); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ From 7e36c4bdb0364158b63b4939838204b4f140b63e Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Thu, 1 Mar 2012 11:05:51 +0530 Subject: [PATCH 14/41] Bug#13635833: MULTIPLE CRASHES IN FOREIGN KEY CODE WITH CONCURRENT DDL/DML There are two threads. In one thread, dml operation is going on involving cascaded update operation. In another thread, alter table add foreign key constraint is happening. Under these circumstances, it is possible for the dml thread to access a dict_foreign_t object that has been freed by the ddl thread. The debug sync test case provides the sequence of operations. Without fix, the test case will crash the server (because of newly added assert). With fix, the alter table stmt will return an error message. Backporting the fix from MySQL 5.5 to 5.1 rb:961 rb:947 --- include/my_base.h | 7 +- .../suite/innodb/r/innodb_bug13635833.result | 45 +++++++++++++ .../suite/innodb/t/innodb_bug13635833.test | 64 +++++++++++++++++++ .../innodb_plugin/r/innodb_bug13635833.result | 45 +++++++++++++ .../innodb_plugin/t/innodb_bug13635833.test | 64 +++++++++++++++++++ mysys/my_handler_errors.h | 6 +- sql/handler.cc | 2 + storage/innobase/dict/dict0dict.c | 4 ++ storage/innobase/handler/ha_innodb.cc | 4 ++ storage/innobase/include/db0err.h | 2 + storage/innobase/row/row0ins.c | 3 + storage/innobase/row/row0mysql.c | 24 +++++++ storage/innodb_plugin/dict/dict0dict.c | 4 ++ storage/innodb_plugin/handler/ha_innodb.cc | 3 + storage/innodb_plugin/include/db0err.h | 2 + storage/innodb_plugin/row/row0ins.c | 3 + storage/innodb_plugin/row/row0mysql.c | 24 +++++++ 17 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_bug13635833.result create mode 100644 mysql-test/suite/innodb/t/innodb_bug13635833.test create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug13635833.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug13635833.test diff --git a/include/my_base.h b/include/my_base.h index 80ba4bcd004..ffd68046029 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -445,7 +445,12 @@ enum ha_base_keytype { #define HA_ERR_FILE_TOO_SHORT 175 /* File too short */ #define HA_ERR_WRONG_CRC 176 /* Wrong CRC on page */ #define HA_ERR_TOO_MANY_CONCURRENT_TRXS 177 /*Too many active concurrent transactions */ -#define HA_ERR_LAST 177 /* Copy of last error nr */ + +/* The error codes from 178 to 180 is not used, because we need to +maintain forward compatibility with higher versions. */ + +#define HA_ERR_TABLE_IN_FK_CHECK 181 /* Table being used in foreign key check */ +#define HA_ERR_LAST 181 /* Copy of last error nr */ /* Number of different errors */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/mysql-test/suite/innodb/r/innodb_bug13635833.result b/mysql-test/suite/innodb/r/innodb_bug13635833.result new file mode 100644 index 00000000000..e9107d5c125 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug13635833.result @@ -0,0 +1,45 @@ +SET DEBUG_SYNC='reset'; +create table t1 (f1 integer, key k1 (f1)) engine=innodb; +create table t2 (f1 int, f2 int, key(f1), key(f2)) engine=innodb; +create table t3 (f2 int, key(f2)) engine=innodb; +insert into t1 values (10); +insert into t2 values (10, 20); +insert into t3 values (20); +alter table t2 add constraint c1 foreign key (f1) +references t1(f1) on update cascade; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + KEY `k1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + KEY `f1` (`f1`), + KEY `f2` (`f2`), + CONSTRAINT `c1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `f2` int(11) DEFAULT NULL, + KEY `f2` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET DEBUG_SYNC='alter_table_before_rename_result_table + SIGNAL update_can_proceed WAIT_FOR dict_unfreeze'; +alter table t2 add constraint z1 foreign key (f2) +references t3(f2) on update cascade; +SET DEBUG_SYNC='innodb_row_update_for_mysql_begin + WAIT_FOR update_can_proceed'; +SET DEBUG_SYNC='innodb_dml_cascade_dict_unfreeze SIGNAL dict_unfreeze + WAIT_FOR foreign_free_cache'; +update ignore t1 set f1 = 20; +ERROR HY000: Error on rename of './test/t2' to '#sql2-temporary' (errno: 181) +SET DEBUG_SYNC='now SIGNAL foreign_free_cache'; +drop table t2; +drop table t1; +drop table t3; +SET DEBUG_SYNC='reset'; diff --git a/mysql-test/suite/innodb/t/innodb_bug13635833.test b/mysql-test/suite/innodb/t/innodb_bug13635833.test new file mode 100644 index 00000000000..b66b99b7681 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug13635833.test @@ -0,0 +1,64 @@ +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/not_embedded.inc + +SET DEBUG_SYNC='reset'; + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +create table t1 (f1 integer, key k1 (f1)) engine=innodb; +create table t2 (f1 int, f2 int, key(f1), key(f2)) engine=innodb; +create table t3 (f2 int, key(f2)) engine=innodb; + +insert into t1 values (10); +insert into t2 values (10, 20); +insert into t3 values (20); + +alter table t2 add constraint c1 foreign key (f1) + references t1(f1) on update cascade; + +show create table t1; +show create table t2; +show create table t3; + +SET DEBUG_SYNC='alter_table_before_rename_result_table + SIGNAL update_can_proceed WAIT_FOR dict_unfreeze'; + +--send +alter table t2 add constraint z1 foreign key (f2) + references t3(f2) on update cascade; + +connect (thr2,localhost,root,,); +connection thr2; + +SET DEBUG_SYNC='innodb_row_update_for_mysql_begin + WAIT_FOR update_can_proceed'; +SET DEBUG_SYNC='innodb_dml_cascade_dict_unfreeze SIGNAL dict_unfreeze + WAIT_FOR foreign_free_cache'; + +--send +update ignore t1 set f1 = 20; + +connection default; +--replace_regex /'[^']*test\/#sql2-[0-9a-f-]*'/'#sql2-temporary'/ +--error ER_ERROR_ON_RENAME +reap; + +SET DEBUG_SYNC='now SIGNAL foreign_free_cache'; + +connection thr2; +reap; +disconnect thr2; +--source include/wait_until_disconnected.inc + +connection default; + +drop table t2; +drop table t1; +drop table t3; + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc + +SET DEBUG_SYNC='reset'; diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug13635833.result b/mysql-test/suite/innodb_plugin/r/innodb_bug13635833.result new file mode 100644 index 00000000000..e9107d5c125 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug13635833.result @@ -0,0 +1,45 @@ +SET DEBUG_SYNC='reset'; +create table t1 (f1 integer, key k1 (f1)) engine=innodb; +create table t2 (f1 int, f2 int, key(f1), key(f2)) engine=innodb; +create table t3 (f2 int, key(f2)) engine=innodb; +insert into t1 values (10); +insert into t2 values (10, 20); +insert into t3 values (20); +alter table t2 add constraint c1 foreign key (f1) +references t1(f1) on update cascade; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + KEY `k1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL, + KEY `f1` (`f1`), + KEY `f2` (`f2`), + CONSTRAINT `c1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `f2` int(11) DEFAULT NULL, + KEY `f2` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET DEBUG_SYNC='alter_table_before_rename_result_table + SIGNAL update_can_proceed WAIT_FOR dict_unfreeze'; +alter table t2 add constraint z1 foreign key (f2) +references t3(f2) on update cascade; +SET DEBUG_SYNC='innodb_row_update_for_mysql_begin + WAIT_FOR update_can_proceed'; +SET DEBUG_SYNC='innodb_dml_cascade_dict_unfreeze SIGNAL dict_unfreeze + WAIT_FOR foreign_free_cache'; +update ignore t1 set f1 = 20; +ERROR HY000: Error on rename of './test/t2' to '#sql2-temporary' (errno: 181) +SET DEBUG_SYNC='now SIGNAL foreign_free_cache'; +drop table t2; +drop table t1; +drop table t3; +SET DEBUG_SYNC='reset'; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug13635833.test b/mysql-test/suite/innodb_plugin/t/innodb_bug13635833.test new file mode 100644 index 00000000000..90df623e8a0 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug13635833.test @@ -0,0 +1,64 @@ +--source include/have_innodb_plugin.inc +--source include/have_debug_sync.inc +--source include/not_embedded.inc + +SET DEBUG_SYNC='reset'; + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +create table t1 (f1 integer, key k1 (f1)) engine=innodb; +create table t2 (f1 int, f2 int, key(f1), key(f2)) engine=innodb; +create table t3 (f2 int, key(f2)) engine=innodb; + +insert into t1 values (10); +insert into t2 values (10, 20); +insert into t3 values (20); + +alter table t2 add constraint c1 foreign key (f1) + references t1(f1) on update cascade; + +show create table t1; +show create table t2; +show create table t3; + +SET DEBUG_SYNC='alter_table_before_rename_result_table + SIGNAL update_can_proceed WAIT_FOR dict_unfreeze'; + +--send +alter table t2 add constraint z1 foreign key (f2) + references t3(f2) on update cascade; + +connect (thr2,localhost,root,,); +connection thr2; + +SET DEBUG_SYNC='innodb_row_update_for_mysql_begin + WAIT_FOR update_can_proceed'; +SET DEBUG_SYNC='innodb_dml_cascade_dict_unfreeze SIGNAL dict_unfreeze + WAIT_FOR foreign_free_cache'; + +--send +update ignore t1 set f1 = 20; + +connection default; +--replace_regex /'[^']*test\/#sql2-[0-9a-f-]*'/'#sql2-temporary'/ +--error ER_ERROR_ON_RENAME +reap; + +SET DEBUG_SYNC='now SIGNAL foreign_free_cache'; + +connection thr2; +reap; +disconnect thr2; +--source include/wait_until_disconnected.inc + +connection default; + +drop table t2; +drop table t1; +drop table t3; + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc + +SET DEBUG_SYNC='reset'; diff --git a/mysys/my_handler_errors.h b/mysys/my_handler_errors.h index 44c79466e84..1710ac81395 100644 --- a/mysys/my_handler_errors.h +++ b/mysys/my_handler_errors.h @@ -78,6 +78,10 @@ static const char *handler_error_messages[]= "Got a fatal error during initialzaction of handler", "File to short; Expected more data in file", "Read page with wrong checksum", - "Too many active concurrent transactions" + "Too many active concurrent transactions", + "", + "", + "", + "Table is being used in foreign key check" /* HA_ERR_TABLE_IN_FK_CHECK */ }; diff --git a/sql/handler.cc b/sql/handler.cc index 895e7cc4df0..d2eaab19ad8 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -345,6 +345,7 @@ int ha_init_errors(void) SETMSG(HA_ERR_AUTOINC_READ_FAILED, ER(ER_AUTOINC_READ_FAILED)); SETMSG(HA_ERR_AUTOINC_ERANGE, ER(ER_WARN_DATA_OUT_OF_RANGE)); SETMSG(HA_ERR_TOO_MANY_CONCURRENT_TRXS, ER(ER_TOO_MANY_CONCURRENT_TRXS)); + SETMSG(HA_ERR_TABLE_IN_FK_CHECK, "Table being used in foreign key check"); /* Register the error messages for use with my_error(). */ return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST); @@ -2820,6 +2821,7 @@ void handler::print_error(int error, myf errflag) case HA_ERR_TOO_MANY_CONCURRENT_TRXS: textno= ER_TOO_MANY_CONCURRENT_TRXS; break; + case HA_ERR_TABLE_IN_FK_CHECK: default: { /* The error was "unknown" to this function. diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index beea0a2f411..b2baa81b73f 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -26,6 +26,8 @@ Created 1/8/1996 Heikki Tuuri #include "pars0sym.h" #include "que0que.h" #include "rem0cmp.h" +#include "m_string.h" +#include "my_sys.h" #ifndef UNIV_HOTBACKUP # include "m_ctype.h" /* my_isspace() */ #endif /* !UNIV_HOTBACKUP */ @@ -1889,6 +1891,8 @@ dict_foreign_free( /*==============*/ dict_foreign_t* foreign) /* in, own: foreign key struct */ { + ut_a(foreign->foreign_table->n_foreign_key_checks_running == 0); + mem_heap_free(foreign->heap); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 20ab9c7a101..c59c02abe1b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -746,6 +746,10 @@ convert_error_code_to_mysql( return(HA_ERR_RECORD_FILE_FULL); + } else if (error == (int) DB_TABLE_IN_FK_CHECK) { + + return(HA_ERR_TABLE_IN_FK_CHECK); + } else if (error == (int) DB_TABLE_IS_BEING_USED) { return(HA_ERR_WRONG_COMMAND); diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index bab6fa46370..1514b19639c 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -82,6 +82,8 @@ Created 5/24/1996 Heikki Tuuri #define DB_REFERENCING_NO_INDEX 52 /* the parent (referencing) table does not have an index that contains the foreign keys as its prefix columns */ +#define DB_TABLE_IN_FK_CHECK 53 /* table is being used in foreign + key check */ /* The following are partial failure codes */ #define DB_FAIL 1000 diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index bb5c95a572b..785a0426195 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1074,6 +1074,9 @@ row_ins_foreign_check_on_constraint( release the latch. */ row_mysql_unfreeze_data_dictionary(thr_get_trx(thr)); + + DEBUG_SYNC_C("innodb_dml_cascade_dict_unfreeze"); + row_mysql_freeze_data_dictionary(thr_get_trx(thr)); mtr_start(mtr); diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 6148b01af9d..e8b3c485b0e 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -31,6 +31,8 @@ Created 9/17/2000 Heikki Tuuri #include "btr0sea.h" #include "fil0fil.h" #include "ibuf0ibuf.h" +#include "m_string.h" +#include "my_sys.h" /* A dummy variable used to fool the compiler */ ibool row_mysql_identically_false = FALSE; @@ -1373,6 +1375,8 @@ row_update_for_mysql( return(DB_ERROR); } + DEBUG_SYNC_C("innodb_row_update_for_mysql_begin"); + trx->op_info = "updating or deleting"; row_mysql_delay_if_needed(); @@ -3652,6 +3656,7 @@ row_rename_table_for_mysql( ulint n_constraints_to_drop = 0; ibool old_is_tmp, new_is_tmp; pars_info_t* info = NULL; + ulint retry = 0; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_a(old_name != NULL); @@ -3750,6 +3755,25 @@ row_rename_table_for_mysql( } } + /* Is a foreign key check running on this table? */ + for (retry = 0; retry < 100 + && table->n_foreign_key_checks_running > 0; ++retry) { + row_mysql_unlock_data_dictionary(trx); + os_thread_yield(); + row_mysql_lock_data_dictionary(trx); + } + + if (table->n_foreign_key_checks_running > 0) { + ut_print_timestamp(stderr); + fputs(" InnoDB: Error: in ALTER TABLE ", stderr); + ut_print_name(stderr, trx, TRUE, old_name); + fprintf(stderr, "\n" + "InnoDB: a FOREIGN KEY check is running.\n" + "InnoDB: Cannot rename table.\n"); + err = DB_TABLE_IN_FK_CHECK; + goto funct_exit; + } + /* We use the private SQL parser of Innobase to generate the query graphs needed in deleting the dictionary data from system tables in Innobase. Deleting a row from SYS_INDEXES table also frees the file diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c index 2d2262acf87..b70d5929f53 100644 --- a/storage/innodb_plugin/dict/dict0dict.c +++ b/storage/innodb_plugin/dict/dict0dict.c @@ -24,6 +24,8 @@ Created 1/8/1996 Heikki Tuuri ***********************************************************************/ #include "dict0dict.h" +#include "m_string.h" +#include "my_sys.h" #ifdef UNIV_NONINL #include "dict0dict.ic" @@ -2272,6 +2274,8 @@ dict_foreign_free( /*==============*/ dict_foreign_t* foreign) /*!< in, own: foreign key struct */ { + ut_a(foreign->foreign_table->n_foreign_key_checks_running == 0); + mem_heap_free(foreign->heap); } diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 09094c0146e..47d309f2360 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -868,6 +868,9 @@ convert_error_code_to_mysql( case DB_OUT_OF_FILE_SPACE: return(HA_ERR_RECORD_FILE_FULL); + case DB_TABLE_IN_FK_CHECK: + return(HA_ERR_TABLE_IN_FK_CHECK); + case DB_TABLE_IS_BEING_USED: return(HA_ERR_WRONG_COMMAND); diff --git a/storage/innodb_plugin/include/db0err.h b/storage/innodb_plugin/include/db0err.h index c7fa6d2a444..e4a3844cd22 100644 --- a/storage/innodb_plugin/include/db0err.h +++ b/storage/innodb_plugin/include/db0err.h @@ -97,6 +97,8 @@ enum db_err { DB_FOREIGN_EXCEED_MAX_CASCADE, /* Foreign key constraint related cascading delete/update exceeds maximum allowed depth */ + DB_TABLE_IN_FK_CHECK, /* table is being used in foreign + key check */ /* The following are partial failure codes */ DB_FAIL = 1000, diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c index 9a603d5690f..2d4afa6c5ed 100644 --- a/storage/innodb_plugin/row/row0ins.c +++ b/storage/innodb_plugin/row/row0ins.c @@ -1102,6 +1102,9 @@ row_ins_foreign_check_on_constraint( release the latch. */ row_mysql_unfreeze_data_dictionary(thr_get_trx(thr)); + + DEBUG_SYNC_C("innodb_dml_cascade_dict_unfreeze"); + row_mysql_freeze_data_dictionary(thr_get_trx(thr)); mtr_start(mtr); diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index 36aad4f8ca2..cd46244eb34 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -51,6 +51,8 @@ Created 9/17/2000 Heikki Tuuri #include "btr0sea.h" #include "fil0fil.h" #include "ibuf0ibuf.h" +#include "m_string.h" +#include "my_sys.h" /** Provide optional 4.x backwards compatibility for 5.0 and above */ UNIV_INTERN ibool row_rollback_on_timeout = FALSE; @@ -1350,6 +1352,8 @@ row_update_for_mysql( return(DB_ERROR); } + DEBUG_SYNC_C("innodb_row_update_for_mysql_begin"); + trx->op_info = "updating or deleting"; row_mysql_delay_if_needed(); @@ -3741,6 +3745,7 @@ row_rename_table_for_mysql( ulint n_constraints_to_drop = 0; ibool old_is_tmp, new_is_tmp; pars_info_t* info = NULL; + ulint retry = 0; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_a(old_name != NULL); @@ -3824,6 +3829,25 @@ row_rename_table_for_mysql( } } + /* Is a foreign key check running on this table? */ + for (retry = 0; retry < 100 + && table->n_foreign_key_checks_running > 0; ++retry) { + row_mysql_unlock_data_dictionary(trx); + os_thread_yield(); + row_mysql_lock_data_dictionary(trx); + } + + if (table->n_foreign_key_checks_running > 0) { + ut_print_timestamp(stderr); + fputs(" InnoDB: Error: in ALTER TABLE ", stderr); + ut_print_name(stderr, trx, TRUE, old_name); + fprintf(stderr, "\n" + "InnoDB: a FOREIGN KEY check is running.\n" + "InnoDB: Cannot rename table.\n"); + err = DB_TABLE_IN_FK_CHECK; + goto funct_exit; + } + /* We use the private SQL parser of Innobase to generate the query graphs needed in updating the dictionary data from system tables. */ From 621db3d42ef19d8ff28da9968fcc47d952345a28 Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Thu, 1 Mar 2012 15:44:23 +0530 Subject: [PATCH 15/41] The innodb plugin module cannot use DEBUG_SYNC_C facility on Windows. Taking care of it. --- .../suite/innodb_plugin/t/innodb_bug13635833.test | 2 ++ storage/innodb_plugin/row/row0mysql.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug13635833.test b/mysql-test/suite/innodb_plugin/t/innodb_bug13635833.test index 90df623e8a0..5db7a41e201 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug13635833.test +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug13635833.test @@ -1,6 +1,8 @@ --source include/have_innodb_plugin.inc --source include/have_debug_sync.inc --source include/not_embedded.inc +# InnoDB Plugin cannot use DEBUG_SYNC on Windows +--source include/not_windows.inc SET DEBUG_SYNC='reset'; diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index cd46244eb34..b7df3479a3c 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -51,8 +51,14 @@ Created 9/17/2000 Heikki Tuuri #include "btr0sea.h" #include "fil0fil.h" #include "ibuf0ibuf.h" -#include "m_string.h" -#include "my_sys.h" + +#ifdef __WIN__ +/* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */ +# define DEBUG_SYNC_C(dummy) ((void) 0) +#else +# include "m_string.h" /* for my_sys.h */ +# include "my_sys.h" /* DEBUG_SYNC_C */ +#endif /** Provide optional 4.x backwards compatibility for 5.0 and above */ UNIV_INTERN ibool row_rollback_on_timeout = FALSE; From 8aea62fa8a4ac6b065322814d2dcc2c2a9a7ec7e Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Mon, 5 Mar 2012 21:58:07 +0400 Subject: [PATCH 16/41] Fix for BUG#12414917 - ISCLOSED() CRASHES ON 64-BIT BUILDS Problem: lack of incoming geometry data validation may lead to a server crash when ISCLOSED() function called. Solution: necessary incoming data check added. mysql-test/r/gis.result: Fix for BUG#12414917 - ISCLOSED() CRASHES ON 64-BIT BUILDS test result. mysql-test/t/gis.test: Fix for BUG#12414917 - ISCLOSED() CRASHES ON 64-BIT BUILDS test case. sql/spatial.cc: Fix for BUG#12414917 - ISCLOSED() CRASHES ON 64-BIT BUILDS check if a LINESTRING has at least one point as we rely on that further. --- mysql-test/r/gis.result | 6 ++++++ mysql-test/t/gis.test | 7 +++++++ sql/spatial.cc | 3 ++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index acb55d225a7..9b901e0f93f 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1075,4 +1075,10 @@ SPATIAL INDEX i1 (col1, col2) ); ERROR HY000: Incorrect arguments to SPATIAL INDEX DROP TABLE t0, t1, t2; +# +# BUG#12414917 - ISCLOSED() CRASHES ON 64-BIT BUILDS +# +SELECT ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20))); +ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20))) +NULL End of 5.1 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index f8cec14d9ae..fbd4c87cb97 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -812,4 +812,11 @@ CREATE TABLE t3 ( # cleanup DROP TABLE t0, t1, t2; + +--echo # +--echo # BUG#12414917 - ISCLOSED() CRASHES ON 64-BIT BUILDS +--echo # +SELECT ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20))); + + --echo End of 5.1 tests diff --git a/sql/spatial.cc b/sql/spatial.cc index ed3d72b91ec..0d2dd81c71e 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -627,7 +627,8 @@ int Gis_line_string::is_closed(int *closed) const return 0; } data+= 4; - if (no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points)) + if (n_points == 0 || + no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points)) return 1; /* Get first point */ From 30d32207e724ebf9dca7c2ecdaec04b076cd902b Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Mon, 5 Mar 2012 22:15:23 +0400 Subject: [PATCH 17/41] BUG#12537203 - CRASH WHEN SUBSELECTING GLOBAL VARIABLES IN GEOMETRY FUNCTION ARGUMENTS A defect in the subquery substitution code may lead to a server crash: setting substitution's name should be followed by setting its length (to keep them in sync). mysql-test/r/gis.result: BUG#12537203 - CRASH WHEN SUBSELECTING GLOBAL VARIABLES IN GEOMETRY FUNCTION ARGUMENTS test result. mysql-test/t/gis.test: BUG#12537203 - CRASH WHEN SUBSELECTING GLOBAL VARIABLES IN GEOMETRY FUNCTION ARGUMENTS test case. sql/item_subselect.cc: BUG#12537203 - CRASH WHEN SUBSELECTING GLOBAL VARIABLES IN GEOMETRY FUNCTION ARGUMENTS set substitution's name length as well as the name itself (to keep them in sync). --- mysql-test/r/gis.result | 6 ++++++ mysql-test/t/gis.test | 7 +++++++ sql/item_subselect.cc | 1 + 3 files changed, 14 insertions(+) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 9b901e0f93f..9af100e479c 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1081,4 +1081,10 @@ DROP TABLE t0, t1, t2; SELECT ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20))); ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20))) NULL +# +# BUG#12537203 - CRASH WHEN SUBSELECTING GLOBAL VARIABLES IN +# GEOMETRY FUNCTION ARGUMENTS +# +SELECT GEOMETRYCOLLECTION((SELECT @@OLD)); +ERROR 22007: Illegal non geometric '' value found during parsing End of 5.1 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index fbd4c87cb97..c2a1416f9a1 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -818,5 +818,12 @@ DROP TABLE t0, t1, t2; --echo # SELECT ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20))); +--echo # +--echo # BUG#12537203 - CRASH WHEN SUBSELECTING GLOBAL VARIABLES IN +--echo # GEOMETRY FUNCTION ARGUMENTS +--echo # +--error ER_ILLEGAL_VALUE_FOR_TYPE +SELECT GEOMETRYCOLLECTION((SELECT @@OLD)); + --echo End of 5.1 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index e9e2e8bacf9..8335ae2ca8d 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -173,6 +173,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) (*ref)= substitution; substitution->name= name; + substitution->name_length= name_length; if (have_to_be_excluded) engine->exclude(); substitution= 0; From b15a8bf8a7ec9d1181cf813a2662a0777dbcea89 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 6 Mar 2012 15:13:56 +0400 Subject: [PATCH 18/41] BUG#12537203 - CRASH WHEN SUBSELECTING GLOBAL VARIABLES IN GEOMETRY FUNCTION ARGUMENTS Fixed --ps-protocol gis test failure. --- mysql-test/t/gis.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index c2a1416f9a1..abda3e997bd 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -822,6 +822,7 @@ SELECT ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20))); --echo # BUG#12537203 - CRASH WHEN SUBSELECTING GLOBAL VARIABLES IN --echo # GEOMETRY FUNCTION ARGUMENTS --echo # +--replace_regex /non geometric .* value/non geometric '' value/ --error ER_ILLEGAL_VALUE_FOR_TYPE SELECT GEOMETRYCOLLECTION((SELECT @@OLD)); From c657f00458a3c3fb8a35e974c453ed62b903ec9b Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Tue, 6 Mar 2012 13:30:30 +0100 Subject: [PATCH 19/41] Bug#11761576 54082: HANDLE_SEGFAULT MAKES USE OF UNSAFE FUNCTIONS Post-push fixes. mysys/stacktrace.c: Missing comma after "%s" format specifier. sql/mysqld.cc: Move #define to signal_handler.cc sql/signal_handler.cc: Missing #define UNSAFE_DEFAULT_LINUX_THREADS 200 --- mysys/stacktrace.c | 2 +- sql/mysqld.cc | 4 ---- sql/signal_handler.cc | 1 + 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index b2eae0fb4c6..8ef98f197b8 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -170,7 +170,7 @@ void my_print_stacktrace(uchar* stack_bottom __attribute__((unused)), my_safe_printf_stderr("%s", "Error when traversing the stack, stack appears corrupt.\n"); else - my_safe_printf_stderr("%s" + my_safe_printf_stderr("%s", "Please read " "http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n" "and follow instructions on how to resolve the stack trace.\n" diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c47d39721b9..b4dd3108707 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2468,10 +2468,6 @@ static void check_data_home(const char *path) #endif /*__WIN__ || __NETWARE */ -#ifdef HAVE_LINUXTHREADS -#define UNSAFE_DEFAULT_LINUX_THREADS 200 -#endif - #if BACKTRACE_DEMANGLE #include diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 54b456ec2c4..121338c31d2 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -131,6 +131,7 @@ extern "C" sig_handler handle_fatal_signal(int sig) "Hope that's ok; if not, decrease some variables in the equation.\n\n"); #if defined(HAVE_LINUXTHREADS) +#define UNSAFE_DEFAULT_LINUX_THREADS 200 if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS) { my_safe_printf_stderr( From c5511bdf0888974cc9a68474702e10163a2763c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 8 Mar 2012 14:56:22 +0200 Subject: [PATCH 20/41] Bug#13807811 BTR_PCUR_RESTORE_POSITION() CAN SKIP A RECORD This bug has been there at least since MySQL 4.0.9. (Before 4.0.9, the code probably was even more severely broken.) btr_pcur_restore_position(): When cursor restoration fails, before invoking btr_pcur_store_position() move to the previous or next record unless cursor->rel_pos==BTR_PCUR_ON or the record was not a user record. This bug can cause skipped records when btr_pcur_store_position() is called on the last record of a page. A symptom would be record count mismatch in CHECK TABLE, or failure to find a record to delete-mark or update or purge. The following operations should be affected by the bug: * row_search_for_mysql(): SELECT, UPDATE, REPLACE, CHECK TABLE, (almost anything else than INSERT) * foreign key CASCADE operations * row_merge_read_clustered_index(): index creation (since MySQL 5.1 InnoDB Plugin) * multi-threaded purge (after MySQL 5.5): not sure, but it might fail to purge some records Not all callers of btr_pcur_restore_position() should be affected. Anything that asserts or checks that restoration succeeds is unaffected. For example, cursor restoration on the change buffer tree should always succeed, because access is being protected by additional latches. Likewise, rollback, or any code accesses data dictionary tables while holding dict_sys->mutex should be safe. rb:967 approved by Jimmy Yang --- storage/innobase/btr/btr0pcur.c | 66 +++++++++++++++++++-------- storage/innodb_plugin/ChangeLog | 5 ++ storage/innodb_plugin/btr/btr0pcur.c | 68 ++++++++++++++++++++-------- 3 files changed, 99 insertions(+), 40 deletions(-) diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 8d473794243..439ab3093b2 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -291,13 +291,20 @@ btr_pcur_restore_position( /* Save the old search mode of the cursor */ old_mode = cursor->search_mode; - if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) { + switch (cursor->rel_pos) { + case BTR_PCUR_ON: mode = PAGE_CUR_LE; - } else if (cursor->rel_pos == BTR_PCUR_AFTER) { + break; + case BTR_PCUR_AFTER: mode = PAGE_CUR_G; - } else { - ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE); + break; + case BTR_PCUR_BEFORE: mode = PAGE_CUR_L; + break; +#ifdef UNIV_DEBUG + default: + ut_error; +#endif /* UNIV_DEBUG */ } btr_pcur_open_with_no_init(index, tuple, mode, latch_mode, @@ -306,26 +313,45 @@ btr_pcur_restore_position( /* Restore the old search mode */ cursor->search_mode = old_mode; - if (cursor->rel_pos == BTR_PCUR_ON - && btr_pcur_is_on_user_rec(cursor, mtr) - && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), - rec_get_offsets( - btr_pcur_get_rec(cursor), index, - NULL, ULINT_UNDEFINED, &heap))) { + if (btr_pcur_is_on_user_rec(cursor, mtr)) { + switch (cursor->rel_pos) { + case BTR_PCUR_ON: + if (!cmp_dtuple_rec( + tuple, btr_pcur_get_rec(cursor), + rec_get_offsets(btr_pcur_get_rec(cursor), + index, NULL, + ULINT_UNDEFINED, &heap))) { - /* We have to store the NEW value for the modify clock, since - the cursor can now be on a different page! But we can retain - the value of old_rec */ + /* We have to store the NEW value for + the modify clock, since the cursor can + now be on a different page! But we can + retain the value of old_rec */ - cursor->block_when_stored = buf_block_align( - btr_pcur_get_page(cursor)); - cursor->modify_clock = buf_block_get_modify_clock( - cursor->block_when_stored); - cursor->old_stored = BTR_PCUR_OLD_STORED; + cursor->block_when_stored = + buf_block_align( + btr_pcur_get_page(cursor)); + cursor->modify_clock = + buf_block_get_modify_clock( + cursor->block_when_stored); + cursor->old_stored = BTR_PCUR_OLD_STORED; - mem_heap_free(heap); + mem_heap_free(heap); - return(TRUE); + return(TRUE); + } + + break; + case BTR_PCUR_BEFORE: + page_cur_move_to_next(btr_pcur_get_page_cur(cursor)); + break; + case BTR_PCUR_AFTER: + page_cur_move_to_prev(btr_pcur_get_page_cur(cursor)); + break; +#ifdef UNIV_DEBUG + default: + ut_error; +#endif /* UNIV_DEBUG */ + } } mem_heap_free(heap); diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 373335b6ff5..b43aed5cc06 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,8 @@ +2012-03-08 The InnoDB Team + + * btr/btr0pcur.c: + Fix Bug#13807811 BTR_PCUR_RESTORE_POSITION() CAN SKIP A RECORD + 2012-02-28 The InnoDB Team * btr/btr0btr.c, dict/dict0dict.c, include/btr0btr.h, diff --git a/storage/innodb_plugin/btr/btr0pcur.c b/storage/innodb_plugin/btr/btr0pcur.c index 57d9752649f..6cbfd8a64b7 100644 --- a/storage/innodb_plugin/btr/btr0pcur.c +++ b/storage/innodb_plugin/btr/btr0pcur.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -121,6 +121,8 @@ btr_pcur_store_position( ut_a(btr_page_get_next(page, mtr) == FIL_NULL); ut_a(btr_page_get_prev(page, mtr) == FIL_NULL); + ut_ad(page_is_leaf(page)); + ut_ad(page_get_page_no(page) == index->page); cursor->old_stored = BTR_PCUR_OLD_STORED; @@ -313,13 +315,20 @@ btr_pcur_restore_position_func( /* Save the old search mode of the cursor */ old_mode = cursor->search_mode; - if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) { + switch (cursor->rel_pos) { + case BTR_PCUR_ON: mode = PAGE_CUR_LE; - } else if (cursor->rel_pos == BTR_PCUR_AFTER) { + break; + case BTR_PCUR_AFTER: mode = PAGE_CUR_G; - } else { - ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE); + break; + case BTR_PCUR_BEFORE: mode = PAGE_CUR_L; + break; +#ifdef UNIV_DEBUG + default: + ut_error; +#endif /* UNIV_DEBUG */ } btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode, @@ -328,25 +337,44 @@ btr_pcur_restore_position_func( /* Restore the old search mode */ cursor->search_mode = old_mode; - if (cursor->rel_pos == BTR_PCUR_ON - && btr_pcur_is_on_user_rec(cursor) - && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), - rec_get_offsets( - btr_pcur_get_rec(cursor), index, - NULL, ULINT_UNDEFINED, &heap))) { + if (btr_pcur_is_on_user_rec(cursor)) { + switch (cursor->rel_pos) { + case BTR_PCUR_ON: + if (!cmp_dtuple_rec( + tuple, btr_pcur_get_rec(cursor), + rec_get_offsets(btr_pcur_get_rec(cursor), + index, NULL, + ULINT_UNDEFINED, &heap))) { - /* We have to store the NEW value for the modify clock, since - the cursor can now be on a different page! But we can retain - the value of old_rec */ + /* We have to store the NEW value for + the modify clock, since the cursor can + now be on a different page! But we can + retain the value of old_rec */ - cursor->block_when_stored = btr_pcur_get_block(cursor); - cursor->modify_clock = buf_block_get_modify_clock( - cursor->block_when_stored); - cursor->old_stored = BTR_PCUR_OLD_STORED; + cursor->block_when_stored = + btr_pcur_get_block(cursor); + cursor->modify_clock = + buf_block_get_modify_clock( + cursor->block_when_stored); + cursor->old_stored = BTR_PCUR_OLD_STORED; - mem_heap_free(heap); + mem_heap_free(heap); - return(TRUE); + return(TRUE); + } + + break; + case BTR_PCUR_BEFORE: + page_cur_move_to_next(btr_pcur_get_page_cur(cursor)); + break; + case BTR_PCUR_AFTER: + page_cur_move_to_prev(btr_pcur_get_page_cur(cursor)); + break; +#ifdef UNIV_DEBUG + default: + ut_error; +#endif /* UNIV_DEBUG */ + } } mem_heap_free(heap); From 6e6ba8654b0e6e078f5f3d41d504ad446ef759ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 8 Mar 2012 17:10:10 +0200 Subject: [PATCH 21/41] Fix a compiler warning about possibly uninitiaizlied variable. --- storage/innobase/btr/btr0pcur.c | 3 +-- storage/innodb_plugin/btr/btr0pcur.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 439ab3093b2..50aef035f2e 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -301,10 +301,9 @@ btr_pcur_restore_position( case BTR_PCUR_BEFORE: mode = PAGE_CUR_L; break; -#ifdef UNIV_DEBUG default: ut_error; -#endif /* UNIV_DEBUG */ + mode = 0; /* silence a warning */ } btr_pcur_open_with_no_init(index, tuple, mode, latch_mode, diff --git a/storage/innodb_plugin/btr/btr0pcur.c b/storage/innodb_plugin/btr/btr0pcur.c index 6cbfd8a64b7..33700501bc5 100644 --- a/storage/innodb_plugin/btr/btr0pcur.c +++ b/storage/innodb_plugin/btr/btr0pcur.c @@ -325,10 +325,9 @@ btr_pcur_restore_position_func( case BTR_PCUR_BEFORE: mode = PAGE_CUR_L; break; -#ifdef UNIV_DEBUG default: ut_error; -#endif /* UNIV_DEBUG */ + mode = 0; } btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode, From 29aaa6588d1bc6d943c32eaa03e5ccd4c0a6a036 Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Fri, 9 Mar 2012 11:07:16 +0530 Subject: [PATCH 22/41] Bug #11766634 59783: InnoDB data grows unexpectedly when inserting, truncating, inserting the same set of rows. When a table is re-created with the same set of rows, the data file size must not grow. rb:968 Approved by Marko. --- .../suite/innodb/r/innodb_bug11766634.result | 6 +++ .../suite/innodb/t/innodb_bug11766634.test | 51 +++++++++++++++++++ .../innodb_plugin/r/innodb_bug11766634.result | 6 +++ .../innodb_plugin/t/innodb_bug11766634.test | 51 +++++++++++++++++++ storage/innobase/fsp/fsp0fsp.c | 32 +++--------- storage/innodb_plugin/fsp/fsp0fsp.c | 37 ++++---------- 6 files changed, 131 insertions(+), 52 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_bug11766634.result create mode 100644 mysql-test/suite/innodb/t/innodb_bug11766634.test create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug11766634.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test diff --git a/mysql-test/suite/innodb/r/innodb_bug11766634.result b/mysql-test/suite/innodb/r/innodb_bug11766634.result new file mode 100644 index 00000000000..90ce5315598 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug11766634.result @@ -0,0 +1,6 @@ +create table t1 (f1 char(255)) engine innodb; +ibdata1 size: 27262976 bytes +drop table t1; +create table t1 (f1 char(255)) engine innodb; +ibdata1 size: 27262976 bytes +drop table t1; diff --git a/mysql-test/suite/innodb/t/innodb_bug11766634.test b/mysql-test/suite/innodb/t/innodb_bug11766634.test new file mode 100644 index 00000000000..a830955c78a --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug11766634.test @@ -0,0 +1,51 @@ +# Bug 11766634 59783: InnoDB data grows unexpectedly when inserting, +# truncating, inserting the same set of rows. +# +# Scenario: +# create table t1. Insert $recs records. check size of ibdata1. +# drop table t1. create table t1. Insert the same set of $recs +# records. The size of ibdata1 must not increase. +# + +-- source include/not_embedded.inc +-- source include/have_innodb.inc + +create table t1 (f1 char(255)) engine innodb; +let $MYSQLD_DATADIR=`select @@datadir`; +let IBDATA1=$MYSQLD_DATADIR/ibdata1; + +let $recs = 36262; + +--disable_query_log +let $c = $recs; +while ($c) +{ + insert into t1 values ('Hello World'); + dec $c; +} +--enable_query_log + +perl; +my $filesize = -s $ENV{'IBDATA1'}; +print "ibdata1 size: $filesize bytes\n"; +EOF + +drop table t1; +create table t1 (f1 char(255)) engine innodb; + +--disable_query_log +let $c = $recs; +while ($c) +{ + insert into t1 values ('Hello World'); + dec $c; +} +--enable_query_log + +perl; +my $filesize = -s $ENV{'IBDATA1'}; +print "ibdata1 size: $filesize bytes\n"; +EOF + +drop table t1; + diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug11766634.result b/mysql-test/suite/innodb_plugin/r/innodb_bug11766634.result new file mode 100644 index 00000000000..90ce5315598 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug11766634.result @@ -0,0 +1,6 @@ +create table t1 (f1 char(255)) engine innodb; +ibdata1 size: 27262976 bytes +drop table t1; +create table t1 (f1 char(255)) engine innodb; +ibdata1 size: 27262976 bytes +drop table t1; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test b/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test new file mode 100644 index 00000000000..1780317675d --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test @@ -0,0 +1,51 @@ +# Bug 11766634 59783: InnoDB data grows unexpectedly when inserting, +# truncating, inserting the same set of rows. +# +# Scenario: +# create table t1. Insert $recs records. check size of ibdata1. +# drop table t1. create table t1. Insert the same set of $recs +# records. The size of ibdata1 must not increase. +# + +-- source include/not_embedded.inc +-- source include/have_innodb_plugin.inc + +create table t1 (f1 char(255)) engine innodb; +let $MYSQLD_DATADIR=`select @@datadir`; +let IBDATA1=$MYSQLD_DATADIR/ibdata1; + +let $recs = 36262; + +--disable_query_log +let $c = $recs; +while ($c) +{ + insert into t1 values ('Hello World'); + dec $c; +} +--enable_query_log + +perl; +my $filesize = -s $ENV{'IBDATA1'}; +print "ibdata1 size: $filesize bytes\n"; +EOF + +drop table t1; +create table t1 (f1 char(255)) engine innodb; + +--disable_query_log +let $c = $recs; +while ($c) +{ + insert into t1 values ('Hello World'); + dec $c; +} +--enable_query_log + +perl; +my $filesize = -s $ENV{'IBDATA1'}; +print "ibdata1 size: $filesize bytes\n"; +EOF + +drop table t1; + diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c index 90e6ad34a9a..b095d0a0275 100644 --- a/storage/innobase/fsp/fsp0fsp.c +++ b/storage/innobase/fsp/fsp0fsp.c @@ -245,13 +245,13 @@ fseg_n_reserved_pages_low( /************************************************************************ Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/* in: segment inode */ - ulint space, /* in: space id */ ulint page, /* in: page offset */ + xdes_t* descr, /* in: extent descriptor */ mtr_t* mtr); /* in: mtr */ /************************************************************************** Returns the first extent descriptor for a segment. We think of the extent @@ -635,10 +635,8 @@ xdes_calc_descriptor_index( /************************************************************************ Gets pointer to a the extent descriptor of a page. The page where the extent -descriptor resides is x-locked. If the page offset is equal to the free limit -of the space, adds new extents from above the free limit to the space free -list, if not free limit == space size. This adding is necessary to make the -descriptor defined, as they are uninitialized above the free limit. */ +descriptor resides is x-locked. This function no longer extends the data +file. */ UNIV_INLINE xdes_t* xdes_get_descriptor_with_space_hdr( @@ -666,19 +664,10 @@ xdes_get_descriptor_with_space_hdr( limit = mtr_read_ulint(sp_header + FSP_FREE_LIMIT, MLOG_4BYTES, mtr); size = mtr_read_ulint(sp_header + FSP_SIZE, MLOG_4BYTES, mtr); - /* If offset is >= size or > limit, return NULL */ - - if ((offset >= size) || (offset > limit)) { - + if ((offset >= size) || (offset >= limit)) { return(NULL); } - /* If offset is == limit, fill free list of the space. */ - - if (offset == limit) { - fsp_fill_free_list(FALSE, space, sp_header, mtr); - } - descr_page_no = xdes_calc_descriptor_page(offset); if (descr_page_no == 0) { @@ -2552,7 +2541,7 @@ fseg_alloc_free_page_low( ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT, ret_page % FSP_EXTENT_SIZE, mtr) == TRUE); - fseg_mark_page_used(seg_inode, space, ret_page, mtr); + fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr); } return(ret_page); @@ -2946,22 +2935,17 @@ fsp_get_available_space_in_free_extents( /************************************************************************ Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/* in: segment inode */ - ulint space, /* in: space id */ ulint page, /* in: page offset */ + xdes_t* descr, /* in: extent descriptor */ mtr_t* mtr) /* in: mtr */ { - xdes_t* descr; ulint not_full_n_used; - ut_ad(seg_inode && mtr); - - descr = xdes_get_descriptor(space, page, mtr); - ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr) == mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr)); diff --git a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c index c84cae302a6..e54629a7b67 100644 --- a/storage/innodb_plugin/fsp/fsp0fsp.c +++ b/storage/innodb_plugin/fsp/fsp0fsp.c @@ -273,15 +273,13 @@ fseg_n_reserved_pages_low( /********************************************************************//** Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/*!< in: segment inode */ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes - or 0 for uncompressed pages */ ulint page, /*!< in: page offset */ + xdes_t* descr, /* extent descriptor */ mtr_t* mtr); /*!< in: mtr */ /**********************************************************************//** Returns the first extent descriptor for a segment. We think of the extent @@ -705,12 +703,10 @@ xdes_calc_descriptor_index( /********************************************************************//** Gets pointer to a the extent descriptor of a page. The page where the extent -descriptor resides is x-locked. If the page offset is equal to the free limit -of the space, adds new extents from above the free limit to the space free -list, if not free limit == space size. This adding is necessary to make the -descriptor defined, as they are uninitialized above the free limit. +descriptor resides is x-locked. This function no longer extends the data +file. @return pointer to the extent descriptor, NULL if the page does not -exist in the space or if the offset exceeds the free limit */ +exist in the space or if the offset is >= the free limit */ UNIV_INLINE __attribute__((nonnull, warn_unused_result)) xdes_t* xdes_get_descriptor_with_space_hdr( @@ -740,19 +736,10 @@ xdes_get_descriptor_with_space_hdr( zip_size = dict_table_flags_to_zip_size( mach_read_from_4(sp_header + FSP_SPACE_FLAGS)); - /* If offset is >= size or > limit, return NULL */ - - if ((offset >= size) || (offset > limit)) { - + if ((offset >= size) || (offset >= limit)) { return(NULL); } - /* If offset is == limit, fill free list of the space. */ - - if (offset == limit) { - fsp_fill_free_list(FALSE, space, sp_header, mtr); - } - descr_page_no = xdes_calc_descriptor_page(zip_size, offset); if (descr_page_no == 0) { @@ -2877,7 +2864,7 @@ got_hinted_page: ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT, ret_page % FSP_EXTENT_SIZE, mtr) == TRUE); - fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr); + fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr); } return(fsp_page_create( @@ -3283,27 +3270,21 @@ fsp_get_available_space_in_free_extents( /********************************************************************//** Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/*!< in: segment inode */ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes - or 0 for uncompressed pages */ ulint page, /*!< in: page offset */ + xdes_t* descr, /* extent descriptor */ mtr_t* mtr) /*!< in: mtr */ { - xdes_t* descr; ulint not_full_n_used; - ut_ad(seg_inode && mtr); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); - descr = xdes_get_descriptor(space, zip_size, page, mtr); - ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr) == mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr)); From c48233c61e6ab3a45f554de4d975f5c91b914822 Mon Sep 17 00:00:00 2001 From: Dmitry Lenev Date: Sun, 11 Mar 2012 16:05:42 +0400 Subject: [PATCH 23/41] Fixed test case for bug #13105873 "valgrind warning:possible crash in foreign key handling on subsequent create table if not exists". Do not leave current database unassigned after the end of the test case. --- mysql-test/r/sp-bugs.result | 1 + mysql-test/t/sp-bugs.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/r/sp-bugs.result b/mysql-test/r/sp-bugs.result index 59588768d14..3b4e2855e46 100644 --- a/mysql-test/r/sp-bugs.result +++ b/mysql-test/r/sp-bugs.result @@ -128,4 +128,5 @@ CALL p1(); Warnings: Note 1050 Table 't2' already exists DROP DATABASE testdb; +USE test; End of 5.1 tests diff --git a/mysql-test/t/sp-bugs.test b/mysql-test/t/sp-bugs.test index a23ccea8189..2d143b6d86a 100644 --- a/mysql-test/t/sp-bugs.test +++ b/mysql-test/t/sp-bugs.test @@ -161,5 +161,6 @@ CALL p1(); --echo # below stmt should not return valgrind warnings CALL p1(); DROP DATABASE testdb; +USE test; --echo End of 5.1 tests From ad031d51100555dd1b77baaa075d2f7c8790571b Mon Sep 17 00:00:00 2001 From: "Norvald H. Ryeng" Date: Mon, 12 Mar 2012 08:56:56 +0100 Subject: [PATCH 24/41] Bug#13031606 VALUES() IN A SELECT STATEMENT CRASHES SERVER Problem: Grouping results by VALUES(alias for string literal) causes the server to crash. Item_insert_values is not constructed to handle other types of arguments than field and reference to field. In this case, the argument is an Item_string, and this causes Item_insert_values::fix_fields() to crash. Fix: Issue an error message when the argument to Item_insert_values is not a field or a reference to a field. This is slightly in breach with documentation, which states that VALUES should return NULL, but the error message is only issued in cases where the server otherwise would crash, so there is no change in behavior for queries that already work. Future versions will restrict syntax so that using VALUES in this way is illegal. mysql-test/r/errors.result: Add test case for bug #13031606. mysql-test/t/errors.test: Add test case for bug #13031606. sql/item.cc: Issue error message if argument is not field or reference to field. --- mysql-test/r/errors.result | 14 ++++++++++++++ mysql-test/t/errors.test | 18 ++++++++++++++++++ sql/item.cc | 16 ++++------------ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/errors.result b/mysql-test/r/errors.result index 022a32d9c9b..bcc92296945 100644 --- a/mysql-test/r/errors.result +++ b/mysql-test/r/errors.result @@ -55,3 +55,17 @@ Error 1054 Unknown column 'b' in 'field list' INSERT INTO t1 SELECT b FROM t1; ERROR 42S22: Unknown column 'b' in 'field list' DROP TABLE t1; +CREATE TABLE t1 (a INT); +CREATE TABLE t2(a INT PRIMARY KEY, b INT); +SELECT '' AS b FROM t1 GROUP BY VALUES(b); +ERROR 42S22: Unknown column '' in 'VALUES() function' +REPLACE t2(b) SELECT '' AS b FROM t1 GROUP BY VALUES(b); +ERROR 42S22: Unknown column '' in 'VALUES() function' +UPDATE t2 SET a=(SELECT '' AS b FROM t1 GROUP BY VALUES(b)); +ERROR 42S22: Unknown column '' in 'VALUES() function' +INSERT INTO t2 VALUES (1,0) ON DUPLICATE KEY UPDATE +b=(SELECT '' AS b FROM t1 GROUP BY VALUES(b)); +ERROR 42S22: Unknown column '' in 'VALUES() function' +INSERT INTO t2(a,b) VALUES (1,0) ON DUPLICATE KEY UPDATE +b=(SELECT VALUES(a)+2 FROM t1); +DROP TABLE t1, t2; diff --git a/mysql-test/t/errors.test b/mysql-test/t/errors.test index 89579ec1739..b426d9fd5b0 100644 --- a/mysql-test/t/errors.test +++ b/mysql-test/t/errors.test @@ -67,3 +67,21 @@ SHOW ERRORS; INSERT INTO t1 SELECT b FROM t1; DROP TABLE t1; # End of 5.0 tests + +# +# Bug #13031606 VALUES() IN A SELECT STATEMENT CRASHES SERVER +# +CREATE TABLE t1 (a INT); +CREATE TABLE t2(a INT PRIMARY KEY, b INT); +--error ER_BAD_FIELD_ERROR +SELECT '' AS b FROM t1 GROUP BY VALUES(b); +--error ER_BAD_FIELD_ERROR +REPLACE t2(b) SELECT '' AS b FROM t1 GROUP BY VALUES(b); +--error ER_BAD_FIELD_ERROR +UPDATE t2 SET a=(SELECT '' AS b FROM t1 GROUP BY VALUES(b)); +--error ER_BAD_FIELD_ERROR +INSERT INTO t2 VALUES (1,0) ON DUPLICATE KEY UPDATE + b=(SELECT '' AS b FROM t1 GROUP BY VALUES(b)); +INSERT INTO t2(a,b) VALUES (1,0) ON DUPLICATE KEY UPDATE + b=(SELECT VALUES(a)+2 FROM t1); +DROP TABLE t1, t2; diff --git a/sql/item.cc b/sql/item.cc index 2a7d2453889..90bfb0d2852 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6657,20 +6657,12 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items) } if (arg->type() == REF_ITEM) + arg= static_cast(arg)->ref[0]; + if (arg->type() != FIELD_ITEM) { - Item_ref *ref= (Item_ref *)arg; - if (ref->ref[0]->type() != FIELD_ITEM) - { - my_error(ER_BAD_FIELD_ERROR, MYF(0), "", "VALUES() function"); - return TRUE; - } - arg= ref->ref[0]; + my_error(ER_BAD_FIELD_ERROR, MYF(0), "", "VALUES() function"); + return TRUE; } - /* - According to our SQL grammar, VALUES() function can reference - only to a column. - */ - DBUG_ASSERT(arg->type() == FIELD_ITEM); Item_field *field_arg= (Item_field *)arg; From 4a6c4d8603024663727972cc6178b5173f2d59e6 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 12 Mar 2012 12:28:27 +0000 Subject: [PATCH 25/41] BUG#12400313 RELAY_LOG_SPACE_LIMIT IS NOT WORKING IN MANY CASES BUG#64503: mysql frequently ignores --relay-log-space-limit When the SQL thread goes to sleep, waiting for more events, it sets the flag ignore_log_space_limit to true. This gives the IO thread a chance to queue some more events and ultimately the SQL thread will be able to purge the log once it is rotated. By then the SQL thread resets the ignore_log_space_limit to false. However, between the time the SQL thread has set the ignore flag and the time it resets it, the IO thread will be queuing events in the relay log, possibly going way over the limit. This patch makes the IO and SQL thread to synchronize when they reach the space limit and only ask for one event at a time. Thus the SQL thread sets ignore_log_space_limit flag and the IO thread resets it to false everytime it processes one more event. In addition, everytime the SQL thread processes the next event, and the limit has been reached, it checks if the IO thread should rotate. If it should, it instructs the IO thread to rotate, giving the SQL thread a chance to purge the logs (freeing space). Finally, this patch removes the resetting of the ignore_log_space_limit flag from purge_first_log, because this is now reset by the IO thread every time it processes the next event when the limit has been reached. If the SQL thread is in a transaction, it cannot purge so, there is no point in asking the IO thread to rotate. The only thing it can do is to ask for more events until the transaction is over (then it can ask the IO to rotate and purge the log right away). Otherwise, there would be a deadlock (SQL would not be able to purge and IO thread would not be able to queue events so that the SQL would finish the transaction). --- .../rpl/r/rpl_stm_relay_ign_space.result | 4 + .../rpl/t/rpl_stm_relay_ign_space-slave.opt | 1 + .../suite/rpl/t/rpl_stm_relay_ign_space.test | 96 +++++++++++++++++++ sql/log.cc | 2 - sql/rpl_rli.h | 7 ++ sql/slave.cc | 92 ++++++++++++++++-- 6 files changed, 191 insertions(+), 11 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result create mode 100644 mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt create mode 100644 mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test diff --git a/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result b/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result new file mode 100644 index 00000000000..cbef4231798 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result @@ -0,0 +1,4 @@ +include/master-slave.inc +[connection master] +include/assert.inc [Assert that relay log space is close to the limit] +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt new file mode 100644 index 00000000000..f780540aba8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt @@ -0,0 +1 @@ +--relay-log-space-limit=8192 --relay-log-purge --max-relay-log-size=4096 diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test new file mode 100644 index 00000000000..afe9f8575d3 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test @@ -0,0 +1,96 @@ +# +# BUG#12400313 / BUG#64503 test case +# +# +# Description +# ----------- +# +# This test case starts the slave server with: +# --relay-log-space-limit=8192 --relay-log-purge --max-relay-log-size=4096 +# +# Then it issues some queries that will cause the slave to reach +# relay-log-space-limit. We lock the table so that the SQL thread is +# not able to purge the log and then we issue some more statements. +# +# The purpose is to show that the IO thread will honor the limits +# while the SQL thread is not able to purge the relay logs, which did +# not happen before this patch. In addition we assert that while +# ignoring the limit (SQL thread needs to rotate before purging), the +# IO thread does not do it in an uncontrolled manner. + +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc +--source include/have_innodb.inc + +--disable_query_log +CREATE TABLE t1 (c1 TEXT) engine=InnoDB; + +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); + +--sync_slave_with_master + +# wait for the SQL thread to sleep +--let $show_statement= SHOW PROCESSLIST +--let $field= State +--let $condition= = 'Has read all relay log; waiting for the slave I/O thread to update it' +--source include/wait_show_condition.inc + +# now the io thread has set rli->ignore_space_limit +# lets lock the table so that once the SQL thread awakes +# it blocks there and does not set rli->ignore_space_limit +# back to zero +LOCK TABLE t1 WRITE; + +# now issue more statements that will overflow the +# rli->log_space_limit (in this case ~10K) +--connection master + +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); + +--connection slave + +# ASSERT that the IO thread waits for the SQL thread to release some +# space before continuing +--let $show_statement= SHOW PROCESSLIST +--let $field= State +--let $condition= LIKE 'Waiting for %' +# before the patch (IO would have transfered everything) +#--let $condition= = 'Waiting for master to send event' +# after the patch (now it waits for space to be freed) +#--let $condition= = 'Waiting for the slave SQL thread to free enough relay log space' +--source include/wait_show_condition.inc + +# without the patch we can uncomment the following two lines and +# watch the IO thread synchronize with the master, thus writing +# relay logs way over the space limit +#--connection master +#--source include/sync_slave_io_with_master.inc + +## ASSERT that the IO thread has honored the limit+few bytes required to be able to purge +--let $relay_log_space_while_sql_is_executing = query_get_value(SHOW SLAVE STATUS, Relay_Log_Space, 1) +--let $relay_log_space_limit = query_get_value(SHOW VARIABLES LIKE "relay_log_space_limit", Value, 1) +--let $assert_text= Assert that relay log space is close to the limit +--let $assert_cond= $relay_log_space_while_sql_is_executing <= $relay_log_space_limit * 1.1 +--source include/assert.inc + +# unlock the table and let SQL thread continue applying events +UNLOCK TABLES; + +--connection master +DROP TABLE t1; +--enable_query_log +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/sql/log.cc b/sql/log.cc index cca403ca1be..3714f1190be 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3194,8 +3194,6 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) pthread_mutex_lock(&rli->log_space_lock); rli->relay_log.purge_logs(to_purge_if_included, included, 0, 0, &rli->log_space_total); - // Tell the I/O thread to take the relay_log_space_limit into account - rli->ignore_log_space_limit= 0; pthread_mutex_unlock(&rli->log_space_lock); /* diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index 113fb04ce00..f49be72db46 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -189,6 +189,13 @@ public: ulonglong log_space_limit,log_space_total; bool ignore_log_space_limit; + /* + Used by the SQL thread to instructs the IO thread to rotate + the logs when the SQL thread needs to purge to release some + disk space. + */ + bool sql_force_rotate_relay; + /* When it commits, InnoDB internally stores the master log position it has processed so far; the position to store is the one of the end of the diff --git a/sql/slave.cc b/sql/slave.cc index 02d8cc2c199..be109a385da 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1450,6 +1450,54 @@ Waiting for the slave SQL thread to free enough relay log space"); !(slave_killed=io_slave_killed(thd,mi)) && !rli->ignore_log_space_limit) pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock); + + /* + Makes the IO thread read only one event at a time + until the SQL thread is able to purge the relay + logs, freeing some space. + + Therefore, once the SQL thread processes this next + event, it goes to sleep (no more events in the queue), + sets ignore_log_space_limit=true and wakes the IO thread. + However, this event may have been enough already for + the SQL thread to purge some log files, freeing + rli->log_space_total . + + This guarantees that the SQL and IO thread move + forward only one event at a time (to avoid deadlocks), + when the relay space limit is reached. It also + guarantees that when the SQL thread is prepared to + rotate (to be able to purge some logs), the IO thread + will know about it and will rotate. + + NOTE: The ignore_log_space_limit is only set when the SQL + thread sleeps waiting for events. + + */ + if (rli->ignore_log_space_limit) + { +#ifndef DBUG_OFF + { + char llbuf1[22], llbuf2[22]; + DBUG_PRINT("info", ("log_space_limit=%s " + "log_space_total=%s " + "ignore_log_space_limit=%d " + "sql_force_rotate_relay=%d", + llstr(rli->log_space_limit,llbuf1), + llstr(rli->log_space_total,llbuf2), + (int) rli->ignore_log_space_limit, + (int) rli->sql_force_rotate_relay)); + } +#endif + if (rli->sql_force_rotate_relay) + { + rotate_relay_log(rli->mi); + rli->sql_force_rotate_relay= false; + } + + rli->ignore_log_space_limit= false; + } + thd->exit_cond(save_proc_info); DBUG_RETURN(slave_killed); } @@ -4260,19 +4308,45 @@ static Log_event* next_event(Relay_log_info* rli) constraint, because we do not want the I/O thread to block because of space (it's ok if it blocks for any other reason (e.g. because the master does not send anything). Then the I/O thread stops waiting - and reads more events. - The SQL thread decides when the I/O thread should take log_space_limit - into account again : ignore_log_space_limit is reset to 0 - in purge_first_log (when the SQL thread purges the just-read relay - log), and also when the SQL thread starts. We should also reset - ignore_log_space_limit to 0 when the user does RESET SLAVE, but in - fact, no need as RESET SLAVE requires that the slave + and reads one more event and starts honoring log_space_limit again. + + If the SQL thread needs more events to be able to rotate the log (it + might need to finish the current group first), then it can ask for one + more at a time. Thus we don't outgrow the relay log indefinitely, + but rather in a controlled manner, until the next rotate. + + When the SQL thread starts it sets ignore_log_space_limit to false. + We should also reset ignore_log_space_limit to 0 when the user does + RESET SLAVE, but in fact, no need as RESET SLAVE requires that the slave be stopped, and the SQL thread sets ignore_log_space_limit to 0 when it stops. */ pthread_mutex_lock(&rli->log_space_lock); - // prevent the I/O thread from blocking next times - rli->ignore_log_space_limit= 1; + + /* + If we have reached the limit of the relay space and we + are going to sleep, waiting for more events: + + 1. If outside a group, SQL thread asks the IO thread + to force a rotation so that the SQL thread purges + logs next time it processes an event (thus space is + freed). + + 2. If in a group, SQL thread asks the IO thread to + ignore the limit and queues yet one more event + so that the SQL thread finishes the group and + is are able to rotate and purge sometime soon. + */ + if (rli->log_space_limit && + rli->log_space_limit < rli->log_space_total) + { + /* force rotation if not in an unfinished group */ + rli->sql_force_rotate_relay= !rli->is_in_group(); + + /* ask for one more event */ + rli->ignore_log_space_limit= true; + } + /* If the I/O thread is blocked, unblock it. Ok to broadcast after unlock, because the mutex is only destroyed in From 9eedf9b4526b83ec6e310fae768273b4ea042e14 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 12 Mar 2012 23:15:01 +0000 Subject: [PATCH 26/41] BUG#12400313 Hardening the test case: - including a diff_tables at the end. - increasing the tolerance on the relay limit size. --- mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result | 1 + mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result b/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result index cbef4231798..7820f1ef97f 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result +++ b/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result @@ -1,4 +1,5 @@ include/master-slave.inc [connection master] include/assert.inc [Assert that relay log space is close to the limit] +include/diff_tables.inc [master:test.t1,slave:test.t1] include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test index afe9f8575d3..2b10da00f76 100644 --- a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test @@ -82,12 +82,16 @@ INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --let $relay_log_space_while_sql_is_executing = query_get_value(SHOW SLAVE STATUS, Relay_Log_Space, 1) --let $relay_log_space_limit = query_get_value(SHOW VARIABLES LIKE "relay_log_space_limit", Value, 1) --let $assert_text= Assert that relay log space is close to the limit ---let $assert_cond= $relay_log_space_while_sql_is_executing <= $relay_log_space_limit * 1.1 +--let $assert_cond= $relay_log_space_while_sql_is_executing <= $relay_log_space_limit * 1.15 --source include/assert.inc # unlock the table and let SQL thread continue applying events UNLOCK TABLES; +--connection master +--let $diff_tables=master:test.t1,slave:test.t1 +--source include/diff_tables.inc + --connection master DROP TABLE t1; --enable_query_log From 7f84e70b8689c535828af7f696775c4391f20a66 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 12 Mar 2012 23:23:40 +0000 Subject: [PATCH 27/41] BUG#12400313 Adding missing sync_slave_with_master to the test case. --- mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test index 2b10da00f76..c90bcfea1b7 100644 --- a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test @@ -89,6 +89,7 @@ INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx UNLOCK TABLES; --connection master +--sync_slave_with_master --let $diff_tables=master:test.t1,slave:test.t1 --source include/diff_tables.inc From a8217b7cd3e31c7ff5212b84b9736af689a5ad39 Mon Sep 17 00:00:00 2001 From: Inaam Rana Date: Thu, 15 Mar 2012 11:53:30 -0400 Subject: [PATCH 28/41] Bug#13537504 VALGRIND: COND. JUMP/MOVE DEPENDS ON UNINITIALISED VALUES IN OS_THREAD_EQ rb://977 approved by: Marko Makela rw_lock::writer_thread field contains the thread id of current x-holder or wait-x thread. This field is un-initialized at lock creation and is written to for the first time when an attempt is made to x-lock. Current code considers ::writer_thread as valid memory region only when the lock is held in x-mode (or there is an x-waiter). This is an overkill and it generates valgrind warnings. The fix is to consider ::writer_thread as valid memory region once it has been written to. Reasoning: ========== The ::writer_thread can be safely considered valid because: * We only ever do comparison with current calling threads id. * We only ever do comparison when ::recursive flag is set * We always unset ::recursive flag in x-unlock * Same thread cannot be unlocking and attempting to lock at the same time * thread_id recycling is not an issue because before an id is recycled the thread must leave innodb meaning it must release all locks meaning it must unset ::recursive flag. --- storage/innodb_plugin/ChangeLog | 6 ++++++ storage/innodb_plugin/include/sync0rw.ic | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index b43aed5cc06..416227c84c3 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2012-03-15 The InnoDB Team + + * include/sync0rw.ic: + Fix Bug#13537504 VALGRIND: COND. JUMP/MOVE DEPENDS ON + UNINITIALISED VALUES IN OS_THREAD_EQ + 2012-03-08 The InnoDB Team * btr/btr0pcur.c: diff --git a/storage/innodb_plugin/include/sync0rw.ic b/storage/innodb_plugin/include/sync0rw.ic index 5eb3d017eca..cd997febc30 100644 --- a/storage/innodb_plugin/include/sync0rw.ic +++ b/storage/innodb_plugin/include/sync0rw.ic @@ -564,8 +564,6 @@ rw_lock_x_unlock_func( if (lock->lock_word == 0) { /* Last caller in a possible recursive chain. */ lock->recursive = FALSE; - UNIV_MEM_INVALID(&lock->writer_thread, - sizeof lock->writer_thread); } #ifdef UNIV_SYNC_DEBUG @@ -606,8 +604,6 @@ rw_lock_x_unlock_direct( if (lock->lock_word == 0) { lock->recursive = FALSE; - UNIV_MEM_INVALID(&lock->writer_thread, - sizeof lock->writer_thread); } #ifdef UNIV_SYNC_DEBUG From 04c96834ccf8880529865d6d34c67410af8e33b9 Mon Sep 17 00:00:00 2001 From: Inaam Rana Date: Thu, 15 Mar 2012 12:38:40 -0400 Subject: [PATCH 29/41] Bug#13851171 STRING OVERFLOW IN INNODB CODE FOUND BY STATIC ANALYSIS rb://976 approved by: Marko Makela Add an assertion to ensure that string overflow is not happening. Pointed by Coverity analysis. --- storage/innodb_plugin/ChangeLog | 6 ++++++ storage/innodb_plugin/handler/ha_innodb.cc | 2 ++ 2 files changed, 8 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 416227c84c3..058128a2200 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2012-03-15 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#13851171STRING OVERFLOW IN INNODB CODE FOUND BY STATIC + ANALYSIS + 2012-03-15 The InnoDB Team * include/sync0rw.ic: diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 09094c0146e..f16b9fabd20 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -6718,6 +6718,8 @@ ha_innobase::create( DBUG_RETURN(HA_ERR_TO_BIG_ROW); } + ut_a(strlen(name) < sizeof(name2)); + strcpy(name2, name); normalize_table_name(norm_name, name2); From 0023147055f7222a1d454e71729b0013af68881c Mon Sep 17 00:00:00 2001 From: Inaam Rana Date: Thu, 15 Mar 2012 13:30:17 -0400 Subject: [PATCH 30/41] Bug#13825266 RACE IN LOCK_VALIDATE() WHEN ACCESSING PAGES DIRECTLY FROM BUFFER POOL rb://975 approved by: Marko Makela There is a race in lock_validate() where we try to access a page without ensuring that the tablespace stays valid during the operation i.e.: it is not deleted. This patch tries to fix that by using an existing flag (the flag is renamed to make it's name more generic in line with it's new use). --- storage/innodb_plugin/ChangeLog | 7 +++ storage/innodb_plugin/fil/fil0fil.c | 59 +++++++++++++------------ storage/innodb_plugin/ibuf/ibuf0ibuf.c | 6 +-- storage/innodb_plugin/include/fil0fil.h | 15 +++---- storage/innodb_plugin/lock/lock0lock.c | 14 ++++-- 5 files changed, 58 insertions(+), 43 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 058128a2200..8b767bc8141 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,10 @@ +2012-03-15 The InnoDB Team + + * fil/fil0fil.c, ibuf/ibuf0ibuf.c, include/fil0fil.h, + lock/lock0lock.c: + Fix Bug#13825266 RACE IN LOCK_VALIDATE() WHEN ACCESSING PAGES + DIRECTLY FROM BUFFER POOL + 2012-03-15 The InnoDB Team * handler/ha_innodb.cc: diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c index 01057c26d94..eebfbd9ccad 100644 --- a/storage/innodb_plugin/fil/fil0fil.c +++ b/storage/innodb_plugin/fil/fil0fil.c @@ -175,7 +175,7 @@ struct fil_space_struct { .ibd file of tablespace and want to stop temporarily posting of new i/o requests on the file */ - ibool stop_ibuf_merges; + ibool stop_new_ops; /*!< we set this TRUE when we start deleting a single-table tablespace */ ibool is_being_deleted; @@ -200,12 +200,13 @@ struct fil_space_struct { ulint n_pending_flushes; /*!< this is positive when flushing the tablespace to disk; dropping of the tablespace is forbidden if this is positive */ - ulint n_pending_ibuf_merges;/*!< this is positive - when merging insert buffer entries to - a page so that we may need to access - the ibuf bitmap page in the - tablespade: dropping of the tablespace - is forbidden if this is positive */ + ulint n_pending_ops;/*!< this is positive when we + have pending operations against this + tablespace. The pending operations can + be ibuf merges or lock validation code + trying to read a block. + Dropping of the tablespace is forbidden + if this is positive */ hash_node_t hash; /*!< hash chain node */ hash_node_t name_hash;/*!< hash chain the name_hash table */ #ifndef UNIV_HOTBACKUP @@ -1236,7 +1237,7 @@ try_again: } space->stop_ios = FALSE; - space->stop_ibuf_merges = FALSE; + space->stop_new_ops = FALSE; space->is_being_deleted = FALSE; space->purpose = purpose; space->size = 0; @@ -1245,7 +1246,7 @@ try_again: space->n_reserved_extents = 0; space->n_pending_flushes = 0; - space->n_pending_ibuf_merges = 0; + space->n_pending_ops = 0; UT_LIST_INIT(space->chain); space->magic_n = FIL_SPACE_MAGIC_N; @@ -1836,13 +1837,12 @@ fil_read_flushed_lsn_and_arch_log_no( #ifndef UNIV_HOTBACKUP /*******************************************************************//** -Increments the count of pending insert buffer page merges, if space is not -being deleted. -@return TRUE if being deleted, and ibuf merges should be skipped */ +Increments the count of pending operation, if space is not being deleted. +@return TRUE if being deleted, and operation should be skipped */ UNIV_INTERN ibool -fil_inc_pending_ibuf_merges( -/*========================*/ +fil_inc_pending_ops( +/*================*/ ulint id) /*!< in: space id */ { fil_space_t* space; @@ -1858,13 +1858,13 @@ fil_inc_pending_ibuf_merges( (ulong) id); } - if (space == NULL || space->stop_ibuf_merges) { + if (space == NULL || space->stop_new_ops) { mutex_exit(&fil_system->mutex); return(TRUE); } - space->n_pending_ibuf_merges++; + space->n_pending_ops++; mutex_exit(&fil_system->mutex); @@ -1872,11 +1872,11 @@ fil_inc_pending_ibuf_merges( } /*******************************************************************//** -Decrements the count of pending insert buffer page merges. */ +Decrements the count of pending operations. */ UNIV_INTERN void -fil_decr_pending_ibuf_merges( -/*=========================*/ +fil_decr_pending_ops( +/*=================*/ ulint id) /*!< in: space id */ { fil_space_t* space; @@ -1887,13 +1887,13 @@ fil_decr_pending_ibuf_merges( if (space == NULL) { fprintf(stderr, - "InnoDB: Error: decrementing ibuf merge of a" - " dropped tablespace %lu\n", + "InnoDB: Error: decrementing pending operation" + " of a dropped tablespace %lu\n", (ulong) id); } if (space != NULL) { - space->n_pending_ibuf_merges--; + space->n_pending_ops--; } mutex_exit(&fil_system->mutex); @@ -2183,15 +2183,15 @@ fil_delete_tablespace( char* path; ut_a(id != 0); -stop_ibuf_merges: +stop_new_ops: mutex_enter(&fil_system->mutex); space = fil_space_get_by_id(id); if (space != NULL) { - space->stop_ibuf_merges = TRUE; + space->stop_new_ops = TRUE; - if (space->n_pending_ibuf_merges == 0) { + if (space->n_pending_ops == 0) { mutex_exit(&fil_system->mutex); count = 0; @@ -2205,9 +2205,10 @@ stop_ibuf_merges: ut_print_filename(stderr, space->name); fprintf(stderr, ",\n" "InnoDB: but there are %lu pending" - " ibuf merges on it.\n" + " operations (most likely ibuf merges)" + " on it.\n" "InnoDB: Loop %lu.\n", - (ulong) space->n_pending_ibuf_merges, + (ulong) space->n_pending_ops, (ulong) count); } @@ -2216,7 +2217,7 @@ stop_ibuf_merges: os_thread_sleep(20000); count++; - goto stop_ibuf_merges; + goto stop_new_ops; } } @@ -2242,7 +2243,7 @@ try_again: } ut_a(space); - ut_a(space->n_pending_ibuf_merges == 0); + ut_a(space->n_pending_ops == 0); space->is_being_deleted = TRUE; diff --git a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c index f2b51c7ebed..f1da399167c 100644 --- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c +++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c @@ -3281,7 +3281,7 @@ ibuf_merge_or_delete_for_page( function. When the counter is > 0, that prevents tablespace from being dropped. */ - tablespace_being_deleted = fil_inc_pending_ibuf_merges(space); + tablespace_being_deleted = fil_inc_pending_ops(space); if (UNIV_UNLIKELY(tablespace_being_deleted)) { /* Do not try to read the bitmap page from space; @@ -3305,7 +3305,7 @@ ibuf_merge_or_delete_for_page( mtr_commit(&mtr); if (!tablespace_being_deleted) { - fil_decr_pending_ibuf_merges(space); + fil_decr_pending_ops(space); } return; @@ -3537,7 +3537,7 @@ reset_bit: if (update_ibuf_bitmap && !tablespace_being_deleted) { - fil_decr_pending_ibuf_merges(space); + fil_decr_pending_ops(space); } ibuf_exit(); diff --git a/storage/innodb_plugin/include/fil0fil.h b/storage/innodb_plugin/include/fil0fil.h index f6a19646292..c95038b9231 100644 --- a/storage/innodb_plugin/include/fil0fil.h +++ b/storage/innodb_plugin/include/fil0fil.h @@ -340,20 +340,19 @@ fil_read_flushed_lsn_and_arch_log_no( ib_uint64_t* min_flushed_lsn, /*!< in/out: */ ib_uint64_t* max_flushed_lsn); /*!< in/out: */ /*******************************************************************//** -Increments the count of pending insert buffer page merges, if space is not -being deleted. -@return TRUE if being deleted, and ibuf merges should be skipped */ +Increments the count of pending operation, if space is not being deleted. +@return TRUE if being deleted, and operation should be skipped */ UNIV_INTERN ibool -fil_inc_pending_ibuf_merges( -/*========================*/ +fil_inc_pending_ops( +/*================*/ ulint id); /*!< in: space id */ /*******************************************************************//** -Decrements the count of pending insert buffer page merges. */ +Decrements the count of pending operations. */ UNIV_INTERN void -fil_decr_pending_ibuf_merges( -/*=========================*/ +fil_decr_pending_ops( +/*=================*/ ulint id); /*!< in: space id */ #endif /* !UNIV_HOTBACKUP */ /*******************************************************************//** diff --git a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/lock0lock.c index c8bbc5c02bd..49f732da175 100644 --- a/storage/innodb_plugin/lock/lock0lock.c +++ b/storage/innodb_plugin/lock/lock0lock.c @@ -5040,9 +5040,17 @@ lock_validate(void) lock_mutex_exit_kernel(); - lock_rec_validate_page(space, - fil_space_get_zip_size(space), - page_no); + /* Make sure that the tablespace is not + deleted while we are trying to access + the page. */ + if (!fil_inc_pending_ops(space)) { + lock_rec_validate_page( + space, + fil_space_get_zip_size(space), + page_no); + + fil_decr_pending_ops(space); + } lock_mutex_enter_kernel(); From 08f051df04675833ff819be306a204c0c9813e29 Mon Sep 17 00:00:00 2001 From: Annamalai Gurusami Date: Fri, 16 Mar 2012 12:06:29 +0530 Subject: [PATCH 31/41] Bug #11766634 59783: INNODB DATA GROWS UNEXPECTEDLY WHEN INSERTING, TRUNCATING, INSERTING THE The test case must insert all the records using a single transaction. Otherwise the test case takes more than 15 minutes and will time out in pb2 and mtr. --- mysql-test/suite/innodb/t/innodb_bug11766634.test | 4 ++++ mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/mysql-test/suite/innodb/t/innodb_bug11766634.test b/mysql-test/suite/innodb/t/innodb_bug11766634.test index a830955c78a..91be4da0338 100644 --- a/mysql-test/suite/innodb/t/innodb_bug11766634.test +++ b/mysql-test/suite/innodb/t/innodb_bug11766634.test @@ -18,11 +18,13 @@ let $recs = 36262; --disable_query_log let $c = $recs; +start transaction; while ($c) { insert into t1 values ('Hello World'); dec $c; } +commit work; --enable_query_log perl; @@ -35,11 +37,13 @@ create table t1 (f1 char(255)) engine innodb; --disable_query_log let $c = $recs; +start transaction; while ($c) { insert into t1 values ('Hello World'); dec $c; } +commit work; --enable_query_log perl; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test b/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test index 1780317675d..cd46deb64fb 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug11766634.test @@ -18,11 +18,13 @@ let $recs = 36262; --disable_query_log let $c = $recs; +start transaction; while ($c) { insert into t1 values ('Hello World'); dec $c; } +commit work; --enable_query_log perl; @@ -35,11 +37,13 @@ create table t1 (f1 char(255)) engine innodb; --disable_query_log let $c = $recs; +start transaction; while ($c) { insert into t1 values ('Hello World'); dec $c; } +commit work; --enable_query_log perl; From 56d4eb21db828bbf1725b7523d8e3a4809e058c5 Mon Sep 17 00:00:00 2001 From: Praveenkumar Hulakund Date: Tue, 27 Mar 2012 12:42:11 +0530 Subject: [PATCH 32/41] Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE Analysis: ------------------------------- According to the Manual (http://dev.mysql.com/doc/refman/5.1/en/identifier-case-sensitivity.html): "Column, index, stored routine, and event names are not case sensitive on any platform, nor are column aliases." In other words, 'lower_case_table_names' does not affect the behaviour of those identifiers. On the other hand, trigger names are case sensitive on some platforms, and case insensitive on others. 'lower_case_table_names' does not affect the behaviour of trigger names either. The bug was that SHOW statements did case sensitive comparison for stored procedure / stored function / event names. Fix: Modified the code so that comparison in case insensitive for routines and events for "SHOW" operation. --- mysql-test/r/sp-bugs.result | 118 ++++++++++++++++++++++++++++++++++++ mysql-test/t/sp-bugs.test | 86 ++++++++++++++++++++++++++ sql/sql_show.cc | 5 +- 3 files changed, 207 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp-bugs.result b/mysql-test/r/sp-bugs.result index 59588768d14..d003fc9798a 100644 --- a/mysql-test/r/sp-bugs.result +++ b/mysql-test/r/sp-bugs.result @@ -109,6 +109,7 @@ DROP FUNCTION db1.f1; DROP TABLE db1.t1; DROP DATABASE db1; DROP DATABASE db2; +USE test; # # Bug#13105873:valgrind warning:possible crash in foreign # key handling on subsequent create table if not exists @@ -128,4 +129,121 @@ CALL p1(); Warnings: Note 1050 Table 't2' already exists DROP DATABASE testdb; +USE test; End of 5.1 tests +# +# Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +# +SET @@SQL_MODE = ''; +CREATE FUNCTION testf_bug11763507() RETURNS INT +BEGIN +RETURN 0; +END +$ +CREATE PROCEDURE testp_bug11763507() +BEGIN +SELECT "PROCEDURE testp_bug11763507"; +END +$ +CREATE EVENT teste_bug11763507 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT 1 $ +SELECT testf_bug11763507(); +testf_bug11763507() +0 +SELECT TESTF_bug11763507(); +TESTF_bug11763507() +0 +SHOW FUNCTION STATUS LIKE 'testf_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testf_bug11763507 FUNCTION root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW FUNCTION STATUS WHERE NAME='testf_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testf_bug11763507 FUNCTION root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW FUNCTION STATUS LIKE 'TESTF_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testf_bug11763507 FUNCTION root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW FUNCTION STATUS WHERE NAME='TESTF_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testf_bug11763507 FUNCTION root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE FUNCTION testf_bug11763507; +Function sql_mode Create Function character_set_client collation_connection Database Collation +testf_bug11763507 CREATE DEFINER=`root`@`localhost` FUNCTION `testf_bug11763507`() RETURNS int(11) +BEGIN +RETURN 0; +END latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE FUNCTION TESTF_bug11763507; +Function sql_mode Create Function character_set_client collation_connection Database Collation +testf_bug11763507 CREATE DEFINER=`root`@`localhost` FUNCTION `testf_bug11763507`() RETURNS int(11) +BEGIN +RETURN 0; +END latin1 latin1_swedish_ci latin1_swedish_ci +SHOW FUNCTION CODE testf_bug11763507; +Pos Instruction +0 freturn 3 0 +SHOW FUNCTION CODE TESTF_bug11763507; +Pos Instruction +0 freturn 3 0 +CALL testp_bug11763507(); +PROCEDURE testp_bug11763507 +PROCEDURE testp_bug11763507 +CALL TESTP_bug11763507(); +PROCEDURE testp_bug11763507 +PROCEDURE testp_bug11763507 +SHOW PROCEDURE STATUS LIKE 'testp_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testp_bug11763507 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW PROCEDURE STATUS WHERE NAME='testp_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testp_bug11763507 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW PROCEDURE STATUS LIKE 'TESTP_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testp_bug11763507 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW PROCEDURE STATUS WHERE NAME='TESTP_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testp_bug11763507 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE PROCEDURE testp_bug11763507; +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +testp_bug11763507 CREATE DEFINER=`root`@`localhost` PROCEDURE `testp_bug11763507`() +BEGIN +SELECT "PROCEDURE testp_bug11763507"; +END latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE PROCEDURE TESTP_bug11763507; +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +testp_bug11763507 CREATE DEFINER=`root`@`localhost` PROCEDURE `testp_bug11763507`() +BEGIN +SELECT "PROCEDURE testp_bug11763507"; +END latin1 latin1_swedish_ci latin1_swedish_ci +SHOW PROCEDURE CODE testp_bug11763507; +Pos Instruction +0 stmt 0 "SELECT "PROCEDURE testp_bug11763507"" +SHOW PROCEDURE CODE TESTP_bug11763507; +Pos Instruction +0 stmt 0 "SELECT "PROCEDURE testp_bug11763507"" +SHOW EVENTS LIKE 'teste_bug11763507'; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +test teste_bug11763507 root@localhost SYSTEM ONE TIME # # # # NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +SHOW EVENTS LIKE 'TESTE_bug11763507'; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +test teste_bug11763507 root@localhost SYSTEM ONE TIME # # # # NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE EVENT teste_bug11763507; +Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation +teste_bug11763507 SYSTEM # latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE EVENT TESTE_bug11763507; +Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation +teste_bug11763507 SYSTEM # latin1 latin1_swedish_ci latin1_swedish_ci +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'testf_bug11763507'; +specific_name +testf_bug11763507 +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'TESTF_bug11763507'; +specific_name +testf_bug11763507 +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='testf_bug11763507'; +specific_name +testf_bug11763507 +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='TESTF_bug11763507'; +specific_name +testf_bug11763507 +DROP EVENT teste_bug11763507; +DROP PROCEDURE testp_bug11763507; +DROP FUNCTION testf_bug11763507; +#END OF BUG#11763507 test. diff --git a/mysql-test/t/sp-bugs.test b/mysql-test/t/sp-bugs.test index a23ccea8189..88b12b0ec61 100644 --- a/mysql-test/t/sp-bugs.test +++ b/mysql-test/t/sp-bugs.test @@ -138,6 +138,7 @@ DROP FUNCTION db1.f1; DROP TABLE db1.t1; DROP DATABASE db1; DROP DATABASE db2; +USE test; --echo # --echo # Bug#13105873:valgrind warning:possible crash in foreign @@ -161,5 +162,90 @@ CALL p1(); --echo # below stmt should not return valgrind warnings CALL p1(); DROP DATABASE testdb; +USE test; --echo End of 5.1 tests + +--echo # +--echo # Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +--echo # +SET @@SQL_MODE = ''; +DELIMITER $; +CREATE FUNCTION testf_bug11763507() RETURNS INT +BEGIN + RETURN 0; +END +$ + +CREATE PROCEDURE testp_bug11763507() +BEGIN + SELECT "PROCEDURE testp_bug11763507"; +END +$ + +CREATE EVENT teste_bug11763507 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT 1 $ + +DELIMITER ;$ + +# STORED FUNCTIONS +SELECT testf_bug11763507(); +SELECT TESTF_bug11763507(); + +--replace_column 5 # 6 # +SHOW FUNCTION STATUS LIKE 'testf_bug11763507'; +--replace_column 5 # 6 # +SHOW FUNCTION STATUS WHERE NAME='testf_bug11763507'; +--replace_column 5 # 6 # +SHOW FUNCTION STATUS LIKE 'TESTF_bug11763507'; +--replace_column 5 # 6 # +SHOW FUNCTION STATUS WHERE NAME='TESTF_bug11763507'; + +SHOW CREATE FUNCTION testf_bug11763507; +SHOW CREATE FUNCTION TESTF_bug11763507; + +SHOW FUNCTION CODE testf_bug11763507; +SHOW FUNCTION CODE TESTF_bug11763507; + +# STORED PROCEDURE +CALL testp_bug11763507(); +CALL TESTP_bug11763507(); + +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS LIKE 'testp_bug11763507'; +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS WHERE NAME='testp_bug11763507'; +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS LIKE 'TESTP_bug11763507'; +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS WHERE NAME='TESTP_bug11763507'; + +SHOW CREATE PROCEDURE testp_bug11763507; +SHOW CREATE PROCEDURE TESTP_bug11763507; + +SHOW PROCEDURE CODE testp_bug11763507; +SHOW PROCEDURE CODE TESTP_bug11763507; + +# EVENTS +--replace_column 6 # 7 # 8 # 9 # +SHOW EVENTS LIKE 'teste_bug11763507'; +--replace_column 6 # 7 # 8 # 9 # +SHOW EVENTS LIKE 'TESTE_bug11763507'; + +--replace_column 4 # +SHOW CREATE EVENT teste_bug11763507; +--replace_column 4 # +SHOW CREATE EVENT TESTE_bug11763507; + +# INFORMATION SCHEMA +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'testf_bug11763507'; +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'TESTF_bug11763507'; + +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='testf_bug11763507'; +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='TESTF_bug11763507'; + +DROP EVENT teste_bug11763507; +DROP PROCEDURE testp_bug11763507; +DROP FUNCTION testf_bug11763507; + +--echo #END OF BUG#11763507 test. diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2c85e29f985..ab3217dbe48 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4323,7 +4323,8 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0) { restore_record(table, s->default_values); - if (!wild || !wild[0] || !wild_compare(sp_name.c_ptr_safe(), wild, 0)) + if (!wild || !wild[0] || !wild_case_compare(system_charset_info, + sp_name.c_ptr_safe(), wild)) { int enum_idx= (int) proc_table->field[5]->val_int(); table->field[3]->store(sp_name.ptr(), sp_name.length(), cs); @@ -5325,7 +5326,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) DBUG_RETURN(1); } - if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0))) + if (!(!wild || !wild[0] || !wild_case_compare(scs, et.name.str, wild))) DBUG_RETURN(0); /* From 10120d363dbde6f825d4b9ce3226b7e3bf374c7d Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Tue, 27 Mar 2012 14:39:27 +0200 Subject: [PATCH 33/41] Backport of fix for Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER --- mysql-test/r/subselect.result | 49 +++++++++++++++++++++++++++++++ mysql-test/t/subselect.test | 55 +++++++++++++++++++++++++++++++++++ sql/item_subselect.cc | 8 ++++- sql/table.cc | 1 + 4 files changed, 112 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 26e8e3ad0ef..26fe129feed 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4461,6 +4461,55 @@ ERROR 21000: Subquery returns more than 1 row SET SESSION sql_mode=@old_sql_mode; DEALLOCATE PREPARE stmt; DROP TABLE t1; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; End of 5.0 tests. CREATE TABLE t1 (a INT, b INT); INSERT INTO t1 VALUES (2,22),(1,11),(2,22); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 4c5ecbd9ee6..aec0db59843 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3427,6 +3427,61 @@ SET SESSION sql_mode=@old_sql_mode; DEALLOCATE PREPARE stmt; DROP TABLE t1; +--echo # +--echo # Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +--echo # + +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); + +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; + +## All these are subject to the transformation +## '1 < some (...)' => '1 < max(...)' +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); + +SET SESSION sql_mode=@old_sql_mode; + +DROP TABLE t1, t2; + +--echo # +--echo # Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +--echo # + +create table t2(i int); +insert into t2 values(0); + +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; + +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; + +CREATE TABLE t1 ( + pk int NOT NULL, + col_varchar_key varchar(1) DEFAULT NULL, + PRIMARY KEY (pk), + KEY col_varchar_key (col_varchar_key) +); + +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; + +SET SESSION sql_mode=@old_sql_mode; + +drop table t2, t1; +drop view v1; + --echo End of 5.0 tests. # diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index e9e2e8bacf9..bfd0e1c21c3 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1020,7 +1020,13 @@ Item_in_subselect::single_value_transformer(JOIN *join, print_where(item, "rewrite with MIN/MAX", QT_ORDINARY);); if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY) { - DBUG_ASSERT(select_lex->non_agg_field_used()); + /* + If the argument is a field, we assume that fix_fields() has + tagged the select_lex with non_agg_field_used. + We reverse that decision after this rewrite with MIN/MAX. + */ + if (item->get_arg(0)->type() == Item::FIELD_ITEM) + DBUG_ASSERT(select_lex->non_agg_field_used()); select_lex->set_non_agg_field_used(false); } diff --git a/sql/table.cc b/sql/table.cc index 9b7f3e66ea6..4577778285f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3979,6 +3979,7 @@ Item *Field_iterator_table::create_item(THD *thd) { select->non_agg_fields.push_back(item); item->marker= select->cur_pos_in_select_list; + select->set_non_agg_field_used(true); } return item; } From 65126ffa57554a7a6e76ad63c2938288ef4ca59c Mon Sep 17 00:00:00 2001 From: Sunny Bains Date: Wed, 28 Mar 2012 13:08:25 +1100 Subject: [PATCH 34/41] Bug# 13847885 - PURGING STALLS WHEN PURGE_SYS->N_PAGES_HANDLED OVERFLOWS Change the type of purge_sys_t::n_pages_handled and purge_sys_t::handle_limit to ulonglong from ulint. On a 32 bit system doing ~700 deletes per second the counters can overflow in ~3.5 months, if they are 32 bit. Approved by Jimmy Yang over IM. --- innobase/include/trx0purge.h | 4 ++-- innobase/trx/trx0purge.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/innobase/include/trx0purge.h b/innobase/include/trx0purge.h index 049c79aec9b..5b4e02a9b4d 100644 --- a/innobase/include/trx0purge.h +++ b/innobase/include/trx0purge.h @@ -120,9 +120,9 @@ struct trx_purge_struct{ read_view_t* view; /* The purge will not remove undo logs which are >= this view (purge view) */ mutex_t mutex; /* Mutex protecting the fields below */ - ulint n_pages_handled;/* Approximate number of undo log + ulonglong n_pages_handled;/* Approximate number of undo log pages processed in purge */ - ulint handle_limit; /* Target of how many pages to get + ulonglong handle_limit; /* Target of how many pages to get processed in the current purge */ /*------------------------------*/ /* The following two fields form the 'purge pointer' which advances diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c index 3df34111281..d5016f3fca4 100644 --- a/innobase/trx/trx0purge.c +++ b/innobase/trx/trx0purge.c @@ -1041,7 +1041,7 @@ trx_purge(void) { que_thr_t* thr; /* que_thr_t* thr2; */ - ulint old_pages_handled; + ulonglong old_pages_handled; mutex_enter(&(purge_sys->mutex)); @@ -1135,7 +1135,7 @@ trx_purge(void) (ulong) purge_sys->n_pages_handled); } - return(purge_sys->n_pages_handled - old_pages_handled); + return((ulint) (purge_sys->n_pages_handled - old_pages_handled)); } /********************************************************************** From f3d5127f4d1c9cccf9f1ab74ef2fa290b33f234d Mon Sep 17 00:00:00 2001 From: Praveenkumar Hulakund Date: Wed, 28 Mar 2012 12:05:31 +0530 Subject: [PATCH 35/41] Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE Analysis: ------------------------------- According to the Manual (http://dev.mysql.com/doc/refman/5.1/en/identifier-case-sensitivity.html): "Column, index, stored routine, and event names are not case sensitive on any platform, nor are column aliases." In other words, 'lower_case_table_names' does not affect the behaviour of those identifiers. On the other hand, trigger names are case sensitive on some platforms, and case insensitive on others. 'lower_case_table_names' does not affect the behaviour of trigger names either. The bug was that SHOW statements did case sensitive comparison for stored procedure / stored function / event names. Fix: Modified the code so that comparison in case insensitive for routines and events for "SHOW" operation. As part of this commit, only fixing the test failures due to the actual code fix. --- mysql-test/r/sp-bugs.result | 27 ------------------------- mysql-test/r/sp-code.result | 29 +++++++++++++++++++++++++++ mysql-test/r/sp_notembedded.result | 20 +++++++++++++++++++ mysql-test/t/sp-bugs.test | 21 -------------------- mysql-test/t/sp-code.test | 32 ++++++++++++++++++++++++++++++ mysql-test/t/sp_notembedded.test | 23 +++++++++++++++++++++ 6 files changed, 104 insertions(+), 48 deletions(-) diff --git a/mysql-test/r/sp-bugs.result b/mysql-test/r/sp-bugs.result index d003fc9798a..eef51385fb1 100644 --- a/mysql-test/r/sp-bugs.result +++ b/mysql-test/r/sp-bugs.result @@ -145,8 +145,6 @@ BEGIN SELECT "PROCEDURE testp_bug11763507"; END $ -CREATE EVENT teste_bug11763507 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR -DO SELECT 1 $ SELECT testf_bug11763507(); testf_bug11763507() 0 @@ -177,12 +175,6 @@ testf_bug11763507 CREATE DEFINER=`root`@`localhost` FUNCTION `testf_bug11763507 BEGIN RETURN 0; END latin1 latin1_swedish_ci latin1_swedish_ci -SHOW FUNCTION CODE testf_bug11763507; -Pos Instruction -0 freturn 3 0 -SHOW FUNCTION CODE TESTF_bug11763507; -Pos Instruction -0 freturn 3 0 CALL testp_bug11763507(); PROCEDURE testp_bug11763507 PROCEDURE testp_bug11763507 @@ -213,24 +205,6 @@ testp_bug11763507 CREATE DEFINER=`root`@`localhost` PROCEDURE `testp_bug1176350 BEGIN SELECT "PROCEDURE testp_bug11763507"; END latin1 latin1_swedish_ci latin1_swedish_ci -SHOW PROCEDURE CODE testp_bug11763507; -Pos Instruction -0 stmt 0 "SELECT "PROCEDURE testp_bug11763507"" -SHOW PROCEDURE CODE TESTP_bug11763507; -Pos Instruction -0 stmt 0 "SELECT "PROCEDURE testp_bug11763507"" -SHOW EVENTS LIKE 'teste_bug11763507'; -Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation -test teste_bug11763507 root@localhost SYSTEM ONE TIME # # # # NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci -SHOW EVENTS LIKE 'TESTE_bug11763507'; -Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation -test teste_bug11763507 root@localhost SYSTEM ONE TIME # # # # NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci -SHOW CREATE EVENT teste_bug11763507; -Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation -teste_bug11763507 SYSTEM # latin1 latin1_swedish_ci latin1_swedish_ci -SHOW CREATE EVENT TESTE_bug11763507; -Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation -teste_bug11763507 SYSTEM # latin1 latin1_swedish_ci latin1_swedish_ci SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'testf_bug11763507'; specific_name testf_bug11763507 @@ -243,7 +217,6 @@ testf_bug11763507 SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='TESTF_bug11763507'; specific_name testf_bug11763507 -DROP EVENT teste_bug11763507; DROP PROCEDURE testp_bug11763507; DROP FUNCTION testf_bug11763507; #END OF BUG#11763507 test. diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result index 39770dc4f2a..bb30cf5bb49 100644 --- a/mysql-test/r/sp-code.result +++ b/mysql-test/r/sp-code.result @@ -888,3 +888,32 @@ Pos Instruction 4 jump 6 5 error 1339 DROP PROCEDURE p1; +# +# Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +# +SET @@SQL_MODE = ''; +CREATE FUNCTION testf_bug11763507() RETURNS INT +BEGIN +RETURN 0; +END +$ +CREATE PROCEDURE testp_bug11763507() +BEGIN +SELECT "PROCEDURE testp_bug11763507"; +END +$ +SHOW FUNCTION CODE testf_bug11763507; +Pos Instruction +0 freturn 3 0 +SHOW FUNCTION CODE TESTF_bug11763507; +Pos Instruction +0 freturn 3 0 +SHOW PROCEDURE CODE testp_bug11763507; +Pos Instruction +0 stmt 0 "SELECT "PROCEDURE testp_bug11763507"" +SHOW PROCEDURE CODE TESTP_bug11763507; +Pos Instruction +0 stmt 0 "SELECT "PROCEDURE testp_bug11763507"" +DROP PROCEDURE testp_bug11763507; +DROP FUNCTION testf_bug11763507; +#END OF BUG#11763507 test. diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result index 7e9ccf01d23..0e74677db02 100644 --- a/mysql-test/r/sp_notembedded.result +++ b/mysql-test/r/sp_notembedded.result @@ -279,6 +279,26 @@ ERROR 70100: Query execution was interrupted DROP VIEW v1; DROP TABLE t1; DROP FUNCTION f1; +# +# Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +# +SET @@SQL_MODE = ''; +CREATE EVENT teste_bug11763507 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT 1 $ +SHOW EVENTS LIKE 'teste_bug11763507'; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +test teste_bug11763507 root@localhost SYSTEM ONE TIME # # # # NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +SHOW EVENTS LIKE 'TESTE_bug11763507'; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +test teste_bug11763507 root@localhost SYSTEM ONE TIME # # # # NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE EVENT teste_bug11763507; +Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation +teste_bug11763507 SYSTEM # latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE EVENT TESTE_bug11763507; +Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation +teste_bug11763507 SYSTEM # latin1 latin1_swedish_ci latin1_swedish_ci +DROP EVENT teste_bug11763507; +#END OF BUG#11763507 test. # ------------------------------------------------------------------ # -- End of 5.1 tests # ------------------------------------------------------------------ diff --git a/mysql-test/t/sp-bugs.test b/mysql-test/t/sp-bugs.test index 88b12b0ec61..3ab1689e8b2 100644 --- a/mysql-test/t/sp-bugs.test +++ b/mysql-test/t/sp-bugs.test @@ -183,9 +183,6 @@ BEGIN END $ -CREATE EVENT teste_bug11763507 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR -DO SELECT 1 $ - DELIMITER ;$ # STORED FUNCTIONS @@ -204,9 +201,6 @@ SHOW FUNCTION STATUS WHERE NAME='TESTF_bug11763507'; SHOW CREATE FUNCTION testf_bug11763507; SHOW CREATE FUNCTION TESTF_bug11763507; -SHOW FUNCTION CODE testf_bug11763507; -SHOW FUNCTION CODE TESTF_bug11763507; - # STORED PROCEDURE CALL testp_bug11763507(); CALL TESTP_bug11763507(); @@ -223,20 +217,6 @@ SHOW PROCEDURE STATUS WHERE NAME='TESTP_bug11763507'; SHOW CREATE PROCEDURE testp_bug11763507; SHOW CREATE PROCEDURE TESTP_bug11763507; -SHOW PROCEDURE CODE testp_bug11763507; -SHOW PROCEDURE CODE TESTP_bug11763507; - -# EVENTS ---replace_column 6 # 7 # 8 # 9 # -SHOW EVENTS LIKE 'teste_bug11763507'; ---replace_column 6 # 7 # 8 # 9 # -SHOW EVENTS LIKE 'TESTE_bug11763507'; - ---replace_column 4 # -SHOW CREATE EVENT teste_bug11763507; ---replace_column 4 # -SHOW CREATE EVENT TESTE_bug11763507; - # INFORMATION SCHEMA SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'testf_bug11763507'; SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'TESTF_bug11763507'; @@ -244,7 +224,6 @@ SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE ' SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='testf_bug11763507'; SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='TESTF_bug11763507'; -DROP EVENT teste_bug11763507; DROP PROCEDURE testp_bug11763507; DROP FUNCTION testf_bug11763507; diff --git a/mysql-test/t/sp-code.test b/mysql-test/t/sp-code.test index 247c84fda39..c7bca4865b7 100644 --- a/mysql-test/t/sp-code.test +++ b/mysql-test/t/sp-code.test @@ -649,3 +649,35 @@ END// DELIMITER ;// SHOW PROCEDURE CODE p1; DROP PROCEDURE p1; + +--echo # +--echo # Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +--echo # +SET @@SQL_MODE = ''; +DELIMITER $; +CREATE FUNCTION testf_bug11763507() RETURNS INT +BEGIN + RETURN 0; +END +$ + +CREATE PROCEDURE testp_bug11763507() +BEGIN + SELECT "PROCEDURE testp_bug11763507"; +END +$ + +DELIMITER ;$ + +# STORED FUNCTIONS +SHOW FUNCTION CODE testf_bug11763507; +SHOW FUNCTION CODE TESTF_bug11763507; + +# STORED PROCEDURE +SHOW PROCEDURE CODE testp_bug11763507; +SHOW PROCEDURE CODE TESTP_bug11763507; + +DROP PROCEDURE testp_bug11763507; +DROP FUNCTION testf_bug11763507; + +--echo #END OF BUG#11763507 test. diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test index 326cc22f1cd..396c9791c34 100644 --- a/mysql-test/t/sp_notembedded.test +++ b/mysql-test/t/sp_notembedded.test @@ -449,6 +449,29 @@ DROP FUNCTION f1; --disconnect con1 --disconnect con2 +--echo # +--echo # Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +--echo # +SET @@SQL_MODE = ''; +DELIMITER $; + +CREATE EVENT teste_bug11763507 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT 1 $ + +DELIMITER ;$ +# EVENTS +--replace_column 6 # 7 # 8 # 9 # +SHOW EVENTS LIKE 'teste_bug11763507'; +--replace_column 6 # 7 # 8 # 9 # +SHOW EVENTS LIKE 'TESTE_bug11763507'; + +--replace_column 4 # +SHOW CREATE EVENT teste_bug11763507; +--replace_column 4 # +SHOW CREATE EVENT TESTE_bug11763507; + +DROP EVENT teste_bug11763507; +--echo #END OF BUG#11763507 test. --echo # ------------------------------------------------------------------ --echo # -- End of 5.1 tests From b5c690aa548ce7796d25f9df3f8ae056dcda1703 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 4 Apr 2012 13:29:45 +0400 Subject: [PATCH 36/41] Bug#11766300 59387: FAILING ASSERTION: CURSOR->POS_STATE == 1997660512 (BTR_PCUR_IS_POSITIONE Bug#13639204 64111: CRASH ON SELECT SUBQUERY WITH NON UNIQUE INDEX The crash happened due to wrong calculation of key length during creation of reference for sort order index. The problem is that keyuse->used_tables can have OUTER_REF_TABLE_BIT enabled but used_tables parameter(create_ref_for_key() func) does not have it. So key parts which have OUTER_REF_TABLE_BIT are ommited and it could lead to incorrect key length calculation(zero key length). mysql-test/r/subselect_innodb.result: test result mysql-test/t/subselect_innodb.test: test case sql/sql_select.cc: added OUTER_REF_TABLE_BIT to the used_tables parameter for create_ref_for_key() function. storage/innobase/handler/ha_innodb.cc: added assertion, request from Inno team storage/innodb_plugin/handler/ha_innodb.cc: added assertion, request from Inno team --- mysql-test/r/subselect_innodb.result | 60 ++++++++++++++++++++++ mysql-test/t/subselect_innodb.test | 56 ++++++++++++++++++++ sql/sql_select.cc | 7 ++- storage/innobase/handler/ha_innodb.cc | 1 + storage/innodb_plugin/handler/ha_innodb.cc | 1 + 5 files changed, 124 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result index 6c6d563e284..4069958267a 100644 --- a/mysql-test/r/subselect_innodb.result +++ b/mysql-test/r/subselect_innodb.result @@ -245,3 +245,63 @@ x NULL drop procedure p1; drop tables t1,t2,t3; +# +# Bug #11766300 59387: FAILING ASSERTION: CURSOR->POS_STATE == 1997660512 (BTR_PCUR_IS_POSITIONE +# +CREATE TABLE t1 (a INT) ENGINE=INNODB; +INSERT INTO t1 VALUES (0); +CREATE TABLE t2 (d BINARY(2), PRIMARY KEY (d(1)), UNIQUE KEY (d)) ENGINE=INNODB; +SELECT 1 FROM t1 WHERE NOT EXISTS +(SELECT 1 FROM t2 WHERE d = (SELECT d FROM t2 WHERE a >= 1) ORDER BY d); +1 +1 +EXPLAIN SELECT 1 FROM t1 WHERE NOT EXISTS +(SELECT 1 FROM t2 WHERE d = (SELECT d FROM t2 WHERE a >= 1) ORDER BY d); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 1 Using where +2 DEPENDENT SUBQUERY t2 eq_ref PRIMARY,d d 2 func 1 Using where +3 DEPENDENT SUBQUERY t2 index NULL d 2 NULL 1 Using where; Using index +DROP TABLE t2; +CREATE TABLE t2 (b INT, c INT, UNIQUE KEY (b), UNIQUE KEY (b, c )) ENGINE=INNODB; +INSERT INTO t2 VALUES (1, 1); +SELECT 1 FROM t1 +WHERE a != (SELECT 1 FROM t2 WHERE a <=> b OR a > '' AND 6 = 7 ORDER BY b, c); +1 +DROP TABLE t1, t2; +# +# Bug #13639204 64111: CRASH ON SELECT SUBQUERY WITH NON UNIQUE +# INDEX +# +CREATE TABLE t1 ( +id int +) ENGINE=InnoDB; +INSERT INTO t1 (id) VALUES (11); +CREATE TABLE t2 ( +t1_id int, +position int, +KEY t1_id (t1_id), +KEY t1_id_position (t1_id,position) +) ENGINE=InnoDB; +EXPLAIN SELECT +(SELECT position FROM t2 +WHERE t2.t1_id = t1.id +ORDER BY t2.t1_id , t2.position +LIMIT 10,1 +) AS maxkey +FROM t1 +LIMIT 1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 1 +2 DEPENDENT SUBQUERY t2 ref t1_id,t1_id_position t1_id_position 5 test.t1.id 1 Using where +SELECT +(SELECT position FROM t2 +WHERE t2.t1_id = t1.id +ORDER BY t2.t1_id , t2.position +LIMIT 10,1 +) AS maxkey +FROM t1 +LIMIT 1; +maxkey +NULL +DROP TABLE t1,t2; +End of 5.1 tests diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test index 573fe0c1810..ce070b454c3 100644 --- a/mysql-test/t/subselect_innodb.test +++ b/mysql-test/t/subselect_innodb.test @@ -238,3 +238,59 @@ call p1(); call p1(); drop procedure p1; drop tables t1,t2,t3; + +--echo # +--echo # Bug #11766300 59387: FAILING ASSERTION: CURSOR->POS_STATE == 1997660512 (BTR_PCUR_IS_POSITIONE +--echo # + +CREATE TABLE t1 (a INT) ENGINE=INNODB; +INSERT INTO t1 VALUES (0); +CREATE TABLE t2 (d BINARY(2), PRIMARY KEY (d(1)), UNIQUE KEY (d)) ENGINE=INNODB; + +SELECT 1 FROM t1 WHERE NOT EXISTS +(SELECT 1 FROM t2 WHERE d = (SELECT d FROM t2 WHERE a >= 1) ORDER BY d); + +EXPLAIN SELECT 1 FROM t1 WHERE NOT EXISTS +(SELECT 1 FROM t2 WHERE d = (SELECT d FROM t2 WHERE a >= 1) ORDER BY d); + +DROP TABLE t2; + +CREATE TABLE t2 (b INT, c INT, UNIQUE KEY (b), UNIQUE KEY (b, c )) ENGINE=INNODB; +INSERT INTO t2 VALUES (1, 1); + +SELECT 1 FROM t1 +WHERE a != (SELECT 1 FROM t2 WHERE a <=> b OR a > '' AND 6 = 7 ORDER BY b, c); + +DROP TABLE t1, t2; + +--echo # +--echo # Bug #13639204 64111: CRASH ON SELECT SUBQUERY WITH NON UNIQUE +--echo # INDEX +--echo # +CREATE TABLE t1 ( +id int +) ENGINE=InnoDB; +INSERT INTO t1 (id) VALUES (11); + +CREATE TABLE t2 ( +t1_id int, +position int, +KEY t1_id (t1_id), +KEY t1_id_position (t1_id,position) +) ENGINE=InnoDB; + +let $query=SELECT +(SELECT position FROM t2 +WHERE t2.t1_id = t1.id +ORDER BY t2.t1_id , t2.position +LIMIT 10,1 +) AS maxkey +FROM t1 +LIMIT 1; + +eval EXPLAIN $query; +eval $query; + +DROP TABLE t1,t2; + +--echo End of 5.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0d8dc740431..a0390baffaa 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5793,6 +5793,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, } keyuse++; } while (keyuse->table == table && keyuse->key == key); + DBUG_ASSERT(length > 0 && keyparts != 0); } /* not ftkey */ /* set up fieldref */ @@ -13426,6 +13427,9 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, DBUG_ENTER("test_if_skip_sort_order"); LINT_INIT(ref_key_parts); + /* Check that we are always called with first non-const table */ + DBUG_ASSERT(tab == tab->join->join_tab + tab->join->const_tables); + /* Keys disabled by ALTER TABLE ... DISABLE KEYS should have already been taken into account. @@ -13507,7 +13511,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, while (keyuse->key != new_ref_key && keyuse->table == tab->table) keyuse++; if (create_ref_for_key(tab->join, tab, keyuse, - tab->join->const_table_map)) + (tab->join->const_table_map | + OUTER_REF_TABLE_BIT))) DBUG_RETURN(0); pick_table_access_method(tab); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c59c02abe1b..6576016501f 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4871,6 +4871,7 @@ ha_innobase::index_read( DBUG_ENTER("index_read"); ut_a(prebuilt->trx == thd_to_trx(user_thd)); + ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT); ha_statistic_increment(&SSV::ha_read_key_count); diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index d1e9649be07..b8e9ccc72ef 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -5575,6 +5575,7 @@ ha_innobase::index_read( DBUG_ENTER("index_read"); ut_a(prebuilt->trx == thd_to_trx(user_thd)); + ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT); ha_statistic_increment(&SSV::ha_read_key_count); From 7dcf0a66fdcd098fb6f8700712595bbaeb4e3cbf Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 6 Apr 2012 12:04:07 +0300 Subject: [PATCH 37/41] Bug #13934049: 64884: LOGINS WITH INCORRECT PASSWORD ARE ALLOWED Fixed an improper type conversion on return that can make the server accept logins with a wrong password. --- sql/password.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/password.c b/sql/password.c index e9e81fb7bf3..e029ba51fc4 100644 --- a/sql/password.c +++ b/sql/password.c @@ -531,7 +531,7 @@ check_scramble(const char *scramble_arg, const char *message, mysql_sha1_reset(&sha1_context); mysql_sha1_input(&sha1_context, buf, SHA1_HASH_SIZE); mysql_sha1_result(&sha1_context, hash_stage2_reassured); - return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE); + return test(memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE)); } From fe3f79933bb13023a41e626dc3b5fd5ad75508f6 Mon Sep 17 00:00:00 2001 From: Mayank Prasad Date: Fri, 6 Apr 2012 17:03:13 +0530 Subject: [PATCH 38/41] BUG#13738989 : 62136 : FAILED TO FETCH SELECT RESULT USING EMBEDDED MYSQLD Background : In mysql-5.1, in a fix for bug#47485, code has been changed for mysql client (libmysql/libmysql.c) but corresponding code was not changed for embedded mysql. In that code change, after execution of a statement, mysql_stmt_store_result() checks for mysql->state to be MYSQL_STATUS_STATEMENT_GET_RESULT, instead of MYSQL_STATUS_GET_RESULT (earlier). Reason: In embedded mysql code, after execution, mysql->state was not set to MYSQL_STATUS_STATEMENT_GET_RESULT, so it was throwing OUT_OF_SYNC error. Fix: Fixed the code in libmysqld/lib_sql.cc to have mysql->state to be set to MYSQL_STATUS_STATEMENT_GET_RESULT after execution. --- libmysqld/lib_sql.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index b6da6172039..4afe02efbdb 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -343,6 +343,8 @@ static int emb_stmt_execute(MYSQL_STMT *stmt) set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } + else if (stmt->mysql->status == MYSQL_STATUS_GET_RESULT) + stmt->mysql->status= MYSQL_STATUS_STATEMENT_GET_RESULT; DBUG_RETURN(0); } From af90fc04ffe1770cf1e2dc22abc8cad235b83d8d Mon Sep 17 00:00:00 2001 From: Venkata Sidagam Date: Mon, 9 Apr 2012 16:42:41 +0530 Subject: [PATCH 39/41] Bug #11766072 59107: MYSQLSLAP CRASHES IF STARTED WITH NO ARGUMENTS ON WINDOWS This bug is a duplicate of Bug #31173, which was pushed to the mysql-trunk 5.6 on 4th Aug, 2010. This is just a back-port of the fix mysql-test/r/mysqlslap.result: A test added as part of the fix for Bug #59107 mysql-test/t/mysqlslap.test: A test added as part of the fix for Bug #59107 --- client/mysqlslap.c | 3 ++- mysql-test/r/mysqlslap.result | 10 ++++++++++ mysql-test/t/mysqlslap.test | 9 +++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/client/mysqlslap.c b/client/mysqlslap.c index bce3566c6d4..35c36806769 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -143,7 +143,8 @@ static my_bool opt_compress= FALSE, tty_password= FALSE, const char *auto_generate_sql_type= "mixed"; static unsigned long connect_flags= CLIENT_MULTI_RESULTS | - CLIENT_MULTI_STATEMENTS; + CLIENT_MULTI_STATEMENTS | + CLIENT_REMEMBER_OPTIONS; static int verbose, delimiter_length; static uint commit_rate; diff --git a/mysql-test/r/mysqlslap.result b/mysql-test/r/mysqlslap.result index a94d9156462..7ac050c6357 100644 --- a/mysql-test/r/mysqlslap.result +++ b/mysql-test/r/mysqlslap.result @@ -245,3 +245,13 @@ mtr mysql test DROP DATABASE bug58090; +# +# Bug #11766072 - 59107: MYSQLSLAP CRASHES IF STARTED WITH NO ARGUMENTS ON WINDOWS +# +Benchmark + Average number of seconds to run all queries: TIME seconds + Minimum number of seconds to run all queries: TIME seconds + Maximum number of seconds to run all queries: TIME seconds + Number of clients running queries: 1 + Average number of queries per client: 0 + diff --git a/mysql-test/t/mysqlslap.test b/mysql-test/t/mysqlslap.test index 757d2813483..69eaae76409 100644 --- a/mysql-test/t/mysqlslap.test +++ b/mysql-test/t/mysqlslap.test @@ -1,6 +1,5 @@ # Can't run test of external client with embedded server --source include/not_embedded.inc ---source include/not_windows.inc --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql @@ -37,7 +36,7 @@ --exec $MYSQL_SLAP --only-print --delimiter=";" --query="select * from t1;select * from t2" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32)); INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')" --engine="heap,myisam" --post-query="SHOW TABLES" --pre-query="SHOW TABLES"; - --exec $MYSQL_SLAP --only-print --delimiter=";" --query="select * from t1;select * from t2" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32)); INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')" --engine="heap,myisam" --post-query="SHOW TABLES" --pre-query="SHOW TABLES" --number-of-queries=6 --commit=1; + --exec $MYSQL_SLAP --only-print --delimiter=";" --query="select * from t1;select * from t2" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32)); INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')" --engine="heap,myisam" --post-query="SHOW TABLES" --pre-query="SHOW TABLES" --number-of-queries=6 --commit=1 --exec $MYSQL_SLAP --silent --concurrency=5 --iterations=1 --number-int-cols=2 --number-char-cols=3 --auto-generate-sql --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=write --detach=2 @@ -68,3 +67,9 @@ SHOW DATABASES; SHOW DATABASES; DROP DATABASE bug58090; +--echo # +--echo # Bug #11766072 - 59107: MYSQLSLAP CRASHES IF STARTED WITH NO ARGUMENTS ON WINDOWS +--echo # + +--replace_regex /queries: [0-9]+.[0-9]+/queries: TIME/ +--exec $MYSQL_SLAP From 5a47413934a0ba0aeb91224f1010bb70bd9b1e8a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 May 2012 10:13:25 +0300 Subject: [PATCH 40/41] fix of LP bug#998321 The problem is that we can't check null_value field of non-basic constant without the item execution.: --- mysql-test/r/func_if.result | 17 +++++++++++++++++ mysql-test/t/func_if.test | 13 +++++++++++++ sql/item_cmpfunc.cc | 4 ++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index 955a784f04c..8d3507f6bed 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -186,3 +186,20 @@ MAX(IFNULL(CAST(c AS UNSIGNED), 0)) 12345678901234567890 DROP TABLE t1; End of 5.0 tests +# +# LP bug#998321 Simple query with IF expression causes an +# assertion abort (see also mysql Bug#12620084) +# +SELECT if(0, (SELECT min('hello')), NULL); +if(0, (SELECT min('hello')), NULL) +NULL +SELECT if(1, (SELECT min('hello')), NULL); +if(1, (SELECT min('hello')), NULL) +hello +SELECT if(0, NULL, (SELECT min('hello'))); +if(0, NULL, (SELECT min('hello'))) +hello +SELECT if(1, NULL, (SELECT min('hello'))); +if(1, NULL, (SELECT min('hello'))) +NULL +End of 5.2 tests diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 8142f57c0de..0d51b95ebe4 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -170,6 +170,19 @@ DROP TABLE t1; --echo End of 5.0 tests + +--echo # +--echo # LP bug#998321 Simple query with IF expression causes an +--echo # assertion abort (see also mysql Bug#12620084) +--echo # + +SELECT if(0, (SELECT min('hello')), NULL); +SELECT if(1, (SELECT min('hello')), NULL); +SELECT if(0, NULL, (SELECT min('hello'))); +SELECT if(1, NULL, (SELECT min('hello'))); + +--echo End of 5.2 tests + --disable_query_log # Restore timezone to default set time_zone= @@global.time_zone; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c4d56a93af6..ea216944dbb 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2659,8 +2659,8 @@ Item_func_if::fix_length_and_dec() enum Item_result arg1_type=args[1]->result_type(); enum Item_result arg2_type=args[2]->result_type(); - bool null1=args[1]->const_item() && args[1]->null_value; - bool null2=args[2]->const_item() && args[2]->null_value; + bool null1=args[1]->basic_const_item() && args[1]->null_value; + bool null2=args[2]->basic_const_item() && args[2]->null_value; if (null1) { From 57f824b0990b0a8708665a4a9ede245ce6064539 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 18 May 2012 12:42:06 +0200 Subject: [PATCH 41/41] post-merge fixes sql/slave.cc: add mutex protection, like in sql_parse.cc --- mysql-test/suite/innodb/t/disabled.def | 3 ++- mysql-test/suite/innodb_plugin/t/disabled.def | 3 +++ mysql-test/suite/innodb_plugin/t/innodb-blob.test | 1 - sql/slave.cc | 6 +++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/innodb/t/disabled.def b/mysql-test/suite/innodb/t/disabled.def index 6536c0221f8..46309c92bbe 100644 --- a/mysql-test/suite/innodb/t/disabled.def +++ b/mysql-test/suite/innodb/t/disabled.def @@ -10,6 +10,7 @@ # ############################################################################## -#innodb_bug53756 : Waiting for merge with Percona Server; bug fixed in innodb_plugin in MySQL 5.1.50 +innodb_bug13635833: Disabled until merging with XtraDB 5.1.63 + innodb-lock: Disabled until merging with XtraDB 5.1.60 innodb_replace: Disabled until merging with XtraDB 5.1.60 diff --git a/mysql-test/suite/innodb_plugin/t/disabled.def b/mysql-test/suite/innodb_plugin/t/disabled.def index 72fec47a09a..a8f74a04a53 100644 --- a/mysql-test/suite/innodb_plugin/t/disabled.def +++ b/mysql-test/suite/innodb_plugin/t/disabled.def @@ -10,7 +10,10 @@ # ############################################################################## +innodb_bug13635833: Disabled until merging with XtraDB 5.1.63 + innodb_bug52745: Disabled as this has valgrind failures (also in MySQL 5.1.50) innodb-index: Disabled until merging with XtraDB 5.1.60 innodb-lock: Disabled until merging with XtraDB 5.1.60 innodb_replace: Disabled until merging with XtraDB 5.1.60 +innodb-blob: Disabled until merging with XtraDB 5.1.63 diff --git a/mysql-test/suite/innodb_plugin/t/innodb-blob.test b/mysql-test/suite/innodb_plugin/t/innodb-blob.test index eb2bc13d609..7d2968c720d 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb-blob.test +++ b/mysql-test/suite/innodb_plugin/t/innodb-blob.test @@ -3,7 +3,6 @@ # columns are stored off-page. --source include/have_innodb_plugin.inc -skip Not fixed in XtraDB yet; # DEBUG_SYNC must be compiled in. --source include/have_debug_sync.inc diff --git a/sql/slave.cc b/sql/slave.cc index e793061b844..41068ffa211 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1451,7 +1451,9 @@ Waiting for the slave SQL thread to free enough relay log space"); #endif if (rli->sql_force_rotate_relay) { + pthread_mutex_lock(&active_mi->data_lock); rotate_relay_log(rli->mi); + pthread_mutex_unlock(&active_mi->data_lock); rli->sql_force_rotate_relay= false; } @@ -4531,7 +4533,6 @@ int rotate_relay_log(Master_info* mi) DBUG_ENTER("rotate_relay_log"); Relay_log_info* rli= &mi->rli; int error= 0; - safe_mutex_assert_owner(&mi->data_lock); /* We need to test inited because otherwise, new_file() will attempt to lock @@ -4559,7 +4560,10 @@ int rotate_relay_log(Master_info* mi) output in SHOW SLAVE STATUS meanwhile. So we harvest now. If the log is closed, then this will just harvest the last writes, probably 0 as they probably have been harvested. + + Note that it needs to be protected by mi->data_lock. */ + safe_mutex_assert_owner(&mi->data_lock); rli->relay_log.harvest_bytes_written(&rli->log_space_total); end: DBUG_RETURN(error);