List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:September 11 2009 12:07pm
Subject:bzr push into mysql-5.4 branch (alik:2814)
View as plain text  
 2814 Alexander Nozdrin	2009-09-11 [merge]
      Merge from mysql-next

    added:
      mysql-test/suite/backup/r/backup_slow_query_log.result
      mysql-test/suite/backup/t/backup_slow_query_log.opt
      mysql-test/suite/backup/t/backup_slow_query_log.test
    modified:
      .bzr-mysql/default.conf
      mysql-test/r/backup_disabled.result
      mysql-test/suite/backup/my.cnf
      mysql-test/suite/backup/r/backup_client.result
      mysql-test/suite/backup/r/backup_db_grants.result
      mysql-test/suite/backup/r/backup_db_grants_extra.result
      mysql-test/suite/backup/r/backup_logs.result
      mysql-test/suite/backup/r/backup_namecase.result
      mysql-test/suite/backup/r/backup_no_data.result
      mysql-test/suite/backup/r/backup_pipe.result
      mysql-test/suite/backup/r/backup_table_grants.result
      mysql-test/suite/backup/r/backup_xpfm_compat_backup_lctn0.result
      mysql-test/suite/backup/r/backup_xpfm_compat_backup_lctn1.result
      mysql-test/suite/backup/r/backup_xpfm_compat_backup_lctn2.result
      mysql-test/suite/backup/r/backup_xpfm_compat_restore_lctn2.result
      mysql-test/suite/backup/t/backup_db_grants.test
      mysql-test/suite/backup/t/backup_logs.test
      mysql-test/suite/backup/t/backup_namecase.test
      mysql-test/suite/backup/t/backup_no_data.test
      mysql-test/suite/backup/t/backup_pipe.test
      mysql-test/suite/backup/t/backup_xpfm_compat_restore_lctn2.test
      mysql-test/suite/backup/t/disabled.def
      mysql-test/suite/backup_engines/my.cnf
      mysql-test/suite/backup_extra/my.cnf
      mysql-test/suite/backup_ptr/my.cnf
      mysql-test/suite/ndb/t/backup_no_ndb.cnf
      mysql-test/suite/rpl/t/rpl_backup.cnf
      mysql-test/suite/rpl/t/rpl_backup_block.cnf
      mysql-test/suite/rpl/t/rpl_backup_extra.cnf
      mysql-test/suite/rpl/t/rpl_backup_multi.cnf
      mysql-test/suite/rpl/t/rpl_backup_ptr.cnf
      mysql-test/suite/rpl/t/rpl_backup_shutdown.cnf
      mysql-test/t/backup_disabled.test
      mysql-test/t/implicit_commit.cnf
      sql/backup/kernel.cc
      sql/backup/stream.cc
      sql/backup/stream.h
      sql/mysql_priv.h
      sql/mysqld.cc
      sql/set_var.cc
      sql/share/errmsg-utf8.txt
      sql/share/errmsg.txt
      sql/si_objects.cc
      sql/sql_parse.cc
=== modified file 'include/my_handler.h'
--- a/include/my_handler.h	2008-11-12 15:23:22 +0000
+++ b/include/my_handler.h	2009-07-30 15:15:27 +0000
@@ -123,8 +123,29 @@ extern void my_handler_error_unregister(
   this amount of bytes.
 */
 #define portable_sizeof_char_ptr 8
+
+/**
+  Return values of index_cond_func_xxx functions.
+
+  0=ICP_NO_MATCH  - index tuple doesn't satisfy the pushed index condition (the
+                engine should discard the tuple and go to the next one)
+  1=ICP_MATCH     - index tuple satisfies the pushed index condition (the engine
+                should fetch and return the record)
+  2=ICP_OUT_OF_RANGE - index tuple is out range that we're scanning, e.g. this
+                   if we're scanning "t.key BETWEEN 10 AND 20" and got a
+                   "t.key=21" tuple (the engine should stop scanning and return
+                   HA_ERR_END_OF_FILE right away).
+*/
+
+typedef enum icp_result {
+  ICP_NO_MATCH,
+  ICP_MATCH,
+  ICP_OUT_OF_RANGE
+} ICP_RESULT;
+
 #ifdef	__cplusplus
 }
 #endif
 
+
 #endif /* _my_handler_h */

=== modified file 'mysql-test/include/mix1.inc'
--- a/mysql-test/include/mix1.inc	2009-07-28 14:16:37 +0000
+++ b/mysql-test/include/mix1.inc	2009-09-02 12:51:07 +0000
@@ -1554,3 +1554,27 @@ SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
 DROP TABLE t1;
 
 --echo End of 5.1 tests
+
+--echo #
+--echo # Bug#43600: Incorrect type conversion caused wrong result.
+--echo #
+CREATE TABLE t1 (
+  a int NOT NULL
+) engine= innodb;
+
+CREATE TABLE t2 (
+  a int NOT NULL,
+  b int NOT NULL,
+  filler char(100) DEFAULT NULL,
+  KEY a (a,b)
+) engine= innodb;
+
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t2 select A.a + 10 *B.a, 1, 'filler' from t1 A, t1 B;
+
+explain select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+
+drop table t1,t2;
+--echo # End of test case for the bug#43600
+

=== modified file 'mysql-test/include/mtr_warnings.sql'
--- a/mysql-test/include/mtr_warnings.sql	2009-07-10 11:44:11 +0000
+++ b/mysql-test/include/mtr_warnings.sql	2009-09-09 13:01:25 +0000
@@ -172,6 +172,14 @@ INSERT INTO global_suppressions VALUES
   */
  ("Can't find file: '.\\\\test\\\\\\?{8}.frm'"),
 
+ /*
+   BUG#42147 - Concurrent DML and LOCK TABLE ... READ for InnoDB 
+   table cause warnings in errlog
+   Note: This is a temporary suppression until Bug#42147 can be 
+   fixed properly. See bug page for more information.
+  */
+ ("Found lock of type 6 that is write and read locked"),
+
  ("THE_LAST_SUPPRESSION")||
 
 

=== modified file 'mysql-test/lib/v1/mtr_report.pl'
--- a/mysql-test/lib/v1/mtr_report.pl	2009-02-05 08:59:29 +0000
+++ b/mysql-test/lib/v1/mtr_report.pl	2009-09-09 13:01:25 +0000
@@ -377,6 +377,9 @@ sub mtr_report_stats ($) {
 		/Slave: Can't DROP 'c7'.* 1091/ or
 		/Slave: Key column 'c6'.* 1072/ or
 
+    # Warnings generated until bug#42147 is properly resolved
+    /Found lock of type 6 that is write and read locked/ or
+
 		# rpl_idempotency.test produces warnings for the slave.
 		($testname eq 'rpl.rpl_idempotency' and
 		 (/Slave: Can\'t find record in \'t1\' Error_code: 1032/ or

=== modified file 'mysql-test/r/flush_block_commit.result'
--- a/mysql-test/r/flush_block_commit.result	2009-03-27 22:06:26 +0000
+++ b/mysql-test/r/flush_block_commit.result	2009-09-01 15:57:05 +0000
@@ -10,13 +10,17 @@ INSERT INTO t1 VALUES(1);
 # Switch to connection con2
 FLUSH TABLES WITH READ LOCK;
 # Switch to connection con1
+# Sending:
 COMMIT;
 # Switch to connection con2
+# Wait until COMMIT gets blocked.
+# Verify that 'con1' was blocked and data did not move.
 SELECT * FROM t1;
 a
-1
 UNLOCK TABLES;
 # Switch to connection con1
+# Reaping COMMIT
+# Switch to connection con1
 BEGIN;
 SELECT * FROM t1 FOR UPDATE;
 a

=== modified file 'mysql-test/r/innodb_mysql.result'
--- a/mysql-test/r/innodb_mysql.result	2009-07-31 19:46:24 +0000
+++ b/mysql-test/r/innodb_mysql.result	2009-09-02 12:51:07 +0000
@@ -1764,6 +1764,33 @@ id	select_type	table	type	possible_keys	
 2	DERIVED	t1	index	c3,c2	c2	14	NULL	5	
 DROP TABLE t1;
 End of 5.1 tests
+#
+# Bug#43600: Incorrect type conversion caused wrong result.
+#
+CREATE TABLE t1 (
+a int NOT NULL
+) engine= innodb;
+CREATE TABLE t2 (
+a int NOT NULL,
+b int NOT NULL,
+filler char(100) DEFAULT NULL,
+KEY a (a,b)
+) engine= innodb;
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t2 select A.a + 10 *B.a, 1, 'filler' from t1 A, t1 B;
+explain select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	
+1	SIMPLE	t2	ref	a	a	4	test.t1.a	1	Using where
+select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+a	a	b	filler
+0	0	1	filler
+1	1	1	filler
+2	2	1	filler
+3	3	1	filler
+4	4	1	filler
+drop table t1,t2;
+# End of test case for the bug#43600
 drop table if exists t1, t2, t3;
 create table t1(a int);
 insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

=== modified file 'mysql-test/r/innodb_mysql_lock.result'
--- a/mysql-test/r/innodb_mysql_lock.result	2009-07-08 12:09:38 +0000
+++ b/mysql-test/r/innodb_mysql_lock.result	2009-09-09 13:01:25 +0000
@@ -21,4 +21,36 @@ INSERT INTO t1 VALUES (2);
 ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
 # Cleanup
 commit;
+set @@autocommit=1;
 commit;
+set @@autocommit=1;
+set @@autocommit=1;
+#
+# Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB 
+#            table cause warnings in errlog
+#
+#
+# Note that this test for now relies on a global suppression of 
+# the warning "Found lock of type 6 that is write and read locked"
+# This suppression rule can be removed once Bug#42147 is properly
+# fixed. See bug page for more info.
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i INT) engine= innodb;
+# Connection 2
+# Get user-level lock
+SELECT get_lock('bug42147_lock', 60);
+get_lock('bug42147_lock', 60)
+1
+# Connection 1
+INSERT INTO t1 SELECT get_lock('bug42147_lock', 60);
+# Connection 2
+LOCK TABLES t1 READ;
+SELECT release_lock('bug42147_lock');
+release_lock('bug42147_lock')
+1
+# Connection 1
+# Connection 2
+UNLOCK TABLES;
+# Connection 1
+DROP TABLE t1;

=== modified file 'mysql-test/r/join_cache.result'
--- a/mysql-test/r/join_cache.result	2009-04-16 02:25:27 +0000
+++ b/mysql-test/r/join_cache.result	2009-09-04 06:58:24 +0000
@@ -3966,3 +3966,30 @@ id1	num3	text1	id4	id3	dummy
 set join_buffer_size=default;
 set join_cache_level=default;
 DROP TABLE t1,t2,t3,t4,t5;
+#
+# Bug#45267: Incomplete check caused wrong result.
+#
+CREATE TABLE t1 (
+`pk` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
+);
+CREATE TABLE t3 (
+`pk` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
+);
+INSERT INTO t3 VALUES
+(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),
+(16),(17),(18),(19),(20);
+CREATE TABLE t2 (
+`pk` int(11) NOT NULL AUTO_INCREMENT,
+`int_nokey` int(11) NOT NULL,
+`time_key` time NOT NULL,
+PRIMARY KEY (`pk`),
+KEY `time_key` (`time_key`)
+);
+INSERT INTO t2 VALUES (10,9,'22:36:46'),(11,0,'08:46:46');
+SELECT DISTINCT t1.`pk`
+FROM t1 RIGHT JOIN t2 STRAIGHT_JOIN t3 ON t2.`int_nokey`  ON t2.`time_key`
+GROUP BY 1;
+pk
+NULL
+DROP TABLE IF EXISTS t1, t2, t3;
+#

=== modified file 'mysql-test/r/lock.result'
--- a/mysql-test/r/lock.result	2009-08-03 15:26:04 +0000
+++ b/mysql-test/r/lock.result	2009-08-31 14:03:25 +0000
@@ -341,5 +341,20 @@ alter table t1 add column j int;
 unlock tables;
 drop table t1;
 #
+# Bug #43272 HANDLER SQL command does not work under LOCK TABLES
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT);
+LOCK TABLE t1 WRITE;
+# HANDLER commands are not allowed in LOCK TABLES mode
+HANDLER t1 OPEN;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+HANDLER t1 READ FIRST;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+HANDLER t1 CLOSE;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+UNLOCK TABLES;
+DROP TABLE t1;
+#
 # End of 6.0 tests.
 #

=== modified file 'mysql-test/r/mdl_sync.result'
--- a/mysql-test/r/mdl_sync.result	2009-08-27 06:22:17 +0000
+++ b/mysql-test/r/mdl_sync.result	2009-09-01 15:57:05 +0000
@@ -233,3 +233,24 @@ drop table t2;
 # Switching to connection 'default'.
 # Clean-up.
 drop table t1;
+#
+# Test for bug #46673 "Deadlock between FLUSH TABLES WITH READ LOCK
+#                      and DML".
+#
+drop tables if exists t1;
+create table t1 (i int);
+# Switching to connection 'con46673'.
+begin;
+insert into t1 values (1);
+# Switching to connection 'default'.
+# Statement below should not get blocked. And if after some
+# changes to code it is there should not be a deadlock between
+# it and transaction from connection 'con46673'.
+flush tables with read lock;
+unlock tables;
+# Switching to connection 'con46673'.
+delete from t1 where i = 1;
+commit;
+# Switching to connection 'default'.
+# Clean-up
+drop table t1;

=== modified file 'mysql-test/r/myisam.result'
--- a/mysql-test/r/myisam.result	2009-08-04 19:50:51 +0000
+++ b/mysql-test/r/myisam.result	2009-09-02 12:51:07 +0000
@@ -2285,3 +2285,30 @@ h+0	d + 0	e	g + 0
 1	1	4	0
 DROP TABLE t1;
 End of 5.1 tests
+#
+# Bug#43600: Incorrect type conversion caused wrong result.
+#
+CREATE TABLE t1 (
+a int NOT NULL
+) engine= myisam;
+CREATE TABLE t2 (
+a int NOT NULL,
+b int NOT NULL,
+filler char(100) DEFAULT NULL,
+KEY a (a,b)
+) engine= myisam;
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t2 select A.a + 10 *B.a, 1, 'filler' from t1 A, t1 B;
+explain select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	5	
+1	SIMPLE	t2	ref	a	a	4	test.t1.a	1	Using index condition
+select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+a	a	b	filler
+0	0	1	filler
+1	1	1	filler
+2	2	1	filler
+3	3	1	filler
+4	4	1	filler
+drop table t1,t2;
+# End of test case for the bug#43600

=== modified file 'mysql-test/r/read_only_innodb.result'
--- a/mysql-test/r/read_only_innodb.result	2009-03-06 22:17:00 +0000
+++ b/mysql-test/r/read_only_innodb.result	2009-09-01 15:57:05 +0000
@@ -7,10 +7,12 @@ insert into table_11733 values(11733);
 set global read_only=1;
 select @@global.read_only;
 @@global.read_only
-0
+1
 select * from table_11733 ;
-ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+a
+11733
 COMMIT;
+ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement
 set global read_only=0;
 drop table table_11733 ;
 drop user test@localhost;

=== modified file 'mysql-test/suite/rpl/r/rpl_backup_block.result'
--- a/mysql-test/suite/rpl/r/rpl_backup_block.result	2009-05-27 20:11:45 +0000
+++ b/mysql-test/suite/rpl/r/rpl_backup_block.result	2009-09-05 09:19:47 +0000
@@ -111,6 +111,67 @@ Master_Server_Id	1
 Last_SQL_Error
 The incident RESTORE_ON_MASTER occured on the master. Message: A restore operation was initiated on the master.
 #
+# Case 2 - Verify a new slave cannot connect
+#
+# Connecting to slave 2...
+CHANGE MASTER TO master_host='127.0.0.1',master_port=MASTER_A_PORT,master_user='root',MASTER_LOG_FILE='MASTER_A_LOG_FILE';
+# Capture slave 2's backupdir.
+SET @@global.backupdir= @@global.datadir;
+# Now verify slave cannot start.
+START SLAVE IO_THREAD;
+SHOW SLAVE STATUS;
+Slave_IO_State	#
+Master_Host	127.0.0.1
+Master_User	root
+Master_Port	MASTER_PORT
+Connect_Retry	60
+Master_Log_File	#
+Read_Master_Log_Pos	#
+Relay_Log_File	#
+Relay_Log_Pos	#
+Relay_Master_Log_File	#
+Slave_IO_Running	No
+Slave_SQL_Running	No
+Replicate_Do_DB	
+Replicate_Ignore_DB	
+Replicate_Do_Table	
+Replicate_Ignore_Table	#
+Replicate_Wild_Do_Table	
+Replicate_Wild_Ignore_Table	
+Last_Errno	0
+Last_Error	
+Skip_Counter	#
+Exec_Master_Log_Pos	#
+Relay_Log_Space	#
+Until_Condition	None
+Until_Log_File	
+Until_Log_Pos	0
+Master_SSL_Allowed	No
+Master_SSL_CA_File	
+Master_SSL_CA_Path	
+Master_SSL_Cert	
+Master_SSL_Cipher	
+Master_SSL_Key	
+Seconds_Behind_Master	#
+Master_SSL_Verify_Server_Cert	No
+Last_IO_Errno	1765
+Last_IO_Error	The master is not allowing slave connections.
+Last_SQL_Errno	#
+Last_SQL_Error	#
+Replicate_Ignore_Server_Ids	
+Master_Server_Id	1
+# Show the slave stopped with an error.
+Last_IO_Error
+The master is not allowing slave connections.
+#
+# Case 3 - Verify connected slave cannot reestablish replication
+#
+# Connecting to slave 1...
+START SLAVE SQL_THREAD;
+# Show the slave stopped with an error.
+Last_SQL_Error
+The incident RESTORE_ON_MASTER occured on the master. Message: A restore operation was initiated on the master.
+#
 # Now resume restore on master
 #
 SET DEBUG_SYNC = 'now SIGNAL finish';
@@ -132,19 +193,139 @@ a
 3
 4
 5
-# Get master's binlog position before restore.
 #
 # Case 4 - Verify slaves can connect after restore
 #
 # Connecting to slave 1...
 SET global sql_slave_skip_counter=1;
 START SLAVE;
+SHOW SLAVE STATUS;
+Slave_IO_State	#
+Master_Host	127.0.0.1
+Master_User	root
+Master_Port	MASTER_PORT
+Connect_Retry	1
+Master_Log_File	#
+Read_Master_Log_Pos	#
+Relay_Log_File	#
+Relay_Log_Pos	#
+Relay_Master_Log_File	#
+Slave_IO_Running	Yes
+Slave_SQL_Running	Yes
+Replicate_Do_DB	
+Replicate_Ignore_DB	
+Replicate_Do_Table	
+Replicate_Ignore_Table	#
+Replicate_Wild_Do_Table	
+Replicate_Wild_Ignore_Table	
+Last_Errno	0
+Last_Error	
+Skip_Counter	#
+Exec_Master_Log_Pos	#
+Relay_Log_Space	#
+Until_Condition	None
+Until_Log_File	
+Until_Log_Pos	0
+Master_SSL_Allowed	No
+Master_SSL_CA_File	
+Master_SSL_CA_Path	
+Master_SSL_Cert	
+Master_SSL_Cipher	
+Master_SSL_Key	
+Seconds_Behind_Master	#
+Master_SSL_Verify_Server_Cert	No
+Last_IO_Errno	0
+Last_IO_Error	
+Last_SQL_Errno	0
+Last_SQL_Error	
+Replicate_Ignore_Server_Ids	
+Master_Server_Id	1
+# Show the slave started without an error.
+Last_SQL_Error
+
+# Showing tables on slave.
+SHOW FULL TABLES FROM rpl_backup_block;
+Tables_in_rpl_backup_block	Table_type
+t1	BASE TABLE
+SELECT * FROM rpl_backup_block.t1;
+a
+1
+2
+3
+4
+5
+90125
+# Connecting to slave 2...
+START SLAVE;
+SET global sql_slave_skip_counter=1;
+START SLAVE SQL_THREAD;
+SHOW SLAVE STATUS;
+Slave_IO_State	#
+Master_Host	127.0.0.1
+Master_User	root
+Master_Port	MASTER_PORT
+Connect_Retry	60
+Master_Log_File	#
+Read_Master_Log_Pos	#
+Relay_Log_File	#
+Relay_Log_Pos	#
+Relay_Master_Log_File	#
+Slave_IO_Running	Yes
+Slave_SQL_Running	Yes
+Replicate_Do_DB	
+Replicate_Ignore_DB	
+Replicate_Do_Table	
+Replicate_Ignore_Table	#
+Replicate_Wild_Do_Table	
+Replicate_Wild_Ignore_Table	
+Last_Errno	0
+Last_Error	
+Skip_Counter	#
+Exec_Master_Log_Pos	#
+Relay_Log_Space	#
+Until_Condition	None
+Until_Log_File	
+Until_Log_Pos	0
+Master_SSL_Allowed	No
+Master_SSL_CA_File	
+Master_SSL_CA_Path	
+Master_SSL_Cert	
+Master_SSL_Cipher	
+Master_SSL_Key	
+Seconds_Behind_Master	#
+Master_SSL_Verify_Server_Cert	No
+Last_IO_Errno	0
+Last_IO_Error	
+Last_SQL_Errno	#
+Last_SQL_Error	#
+Replicate_Ignore_Server_Ids	
+Master_Server_Id	1
+# Show the slave started without an error.
+Last_IO_Error
+
+# Showing databases on slave.
+SHOW FULL TABLES FROM rpl_backup_block;
+Tables_in_rpl_backup_block	Table_type
+t1	BASE TABLE
+SELECT * FROM rpl_backup_block.t1;
+a
+1
+2
+3
+4
+5
+90125
 #
 # Cleanup
 #
 # Connecting to slave 1...
 # Now stop the slave.
 SLAVE STOP;
+# Connecting to slave 2...
+# Now stop the slave.
+SLAVE STOP;
+# Reset slave 2's backupdir.
+SET @@global.backupdir = DEFAULT;
 # Connecting to master...
 DROP DATABASE rpl_backup_block;
 # Reset master's backupdir.
@@ -153,4 +334,8 @@ SET @@global.backupdir = DEFAULT;
 DROP DATABASE rpl_backup_block;
 # Reset slave 1's backupdir.
 SET @@global.backupdir = DEFAULT;
+# Connecting to slave 2...
+DROP DATABASE rpl_backup_block;
+# Reset slave 2's backupdir.
+SET @@global.backupdir = DEFAULT;
 SET DEBUG_SYNC = 'reset';

=== modified file 'mysql-test/suite/rpl/r/rpl_killed_ddl.result'
--- a/mysql-test/suite/rpl/r/rpl_killed_ddl.result	2009-04-08 23:42:51 +0000
+++ b/mysql-test/suite/rpl/r/rpl_killed_ddl.result	2009-09-02 06:18:28 +0000
@@ -24,6 +24,7 @@ DROP TABLE IF EXISTS t1;
 DROP TABLE IF EXISTS t2;
 DROP TABLE IF EXISTS t3;
 DROP TABLE IF EXISTS t4;
+DROP VIEW IF EXISTS v1;
 DROP PROCEDURE IF EXISTS p1;
 DROP PROCEDURE IF EXISTS p2;
 DROP PROCEDURE IF EXISTS p3;
@@ -163,6 +164,7 @@ DROP TABLE IF EXISTS t1;
 DROP TABLE IF EXISTS t2;
 DROP TABLE IF EXISTS t3;
 DROP TABLE IF EXISTS t4;
+DROP VIEW IF EXISTS v1;
 DROP PROCEDURE IF EXISTS p1;
 DROP PROCEDURE IF EXISTS p2;
 DROP PROCEDURE IF EXISTS p3;

=== modified file 'mysql-test/suite/rpl/t/disabled.def'
--- a/mysql-test/suite/rpl/t/disabled.def	2009-07-31 19:46:24 +0000
+++ b/mysql-test/suite/rpl/t/disabled.def	2009-09-08 10:12:56 +0000
@@ -15,6 +15,4 @@ rpl_extraColmaster_myisam  : BUG#40796 2
 rpl_cross_version          : BUG#42311 2009-03-27 joro rpl_cross_version fails on macosx
 rpl_heartbeat_basic        : Bug#43828 Sporadic failures (Serge.Kozlov@stripped)
 rpl_heartbeat_2slaves      : Bug#43828 Sporadic failures (Serge.Kozlov@stripped)
-rpl_failed_optimize        : WL#4284: Can't optimize table used by a pending transaction (there is metadata lock on the table).
-rpl_read_only              : WL#4284: Setting Read only won't succeed until all metadata locks are released.
 rpl_init_slave             : Bug#43005

=== modified file 'mysql-test/suite/rpl/t/rpl_backup_block.test'
--- a/mysql-test/suite/rpl/t/rpl_backup_block.test	2009-05-28 13:49:35 +0000
+++ b/mysql-test/suite/rpl/t/rpl_backup_block.test	2009-09-05 09:19:47 +0000
@@ -14,6 +14,8 @@
 --source include/have_debug.inc
 --source include/have_debug_sync.inc
 
+connect (slave2,127.0.0.1,root,,test,$SLAVE_MYPORT2,);
+
 SET DEBUG_SYNC = 'reset';
 
 --echo #
@@ -71,7 +73,7 @@ SELECT * FROM rpl_backup_block.t1;
 --echo #
 
 --echo # Get master's binlog position before restore.
-let $master_before_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
+let $master_before_pos= query_get_value("SHOW MASTER STATUS", Position, 1);
 
 --echo # Set debug sync point for restore.
 SET DEBUG_SYNC= 'after_backup_start_restore SIGNAL running WAIT_FOR finish';
@@ -96,50 +98,54 @@ source include/wait_for_slave_sql_to_sto
 --query_vertical SHOW SLAVE STATUS
 
 --echo # Show the slave stopped with an error.
-LET $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+LET $last_error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+--disable_query_log
+eval SELECT "$last_error" AS Last_SQL_Error;
+--enable_query_log
+
+--echo #
+--echo # Case 2 - Verify a new slave cannot connect
+--echo #
+
+--echo # Connecting to slave 2...
+connection slave2;
+--replace_result $MASTER_MYPORT MASTER_A_PORT $_binlog_file MASTER_A_LOG_FILE
+--eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$MASTER_MYPORT,master_user='root',MASTER_LOG_FILE='$_binlog_file'
+
+--echo # Capture slave 2's backupdir.
+let $MYSQLD_S2_BACKUPDIR= `select @@datadir`;
+SET @@global.backupdir= @@global.datadir;
+
+--echo # Now verify slave cannot start.
+START SLAVE IO_THREAD;
+source include/wait_for_slave_io_to_stop.inc;
+
+--replace_result $MASTER_MYPORT MASTER_PORT
+--replace_column 1 # 6 # 7 # 8 # 9 # 10 # 16 # 21 # 22 # 23 # 33 # 37 # 38 #
+--query_vertical SHOW SLAVE STATUS
+
+--echo # Show the slave stopped with an error.
+LET $last_error= query_get_value("SHOW SLAVE STATUS", Last_IO_Error, 1);
+--disable_query_log
+eval SELECT "$last_error" AS Last_IO_Error;
+--enable_query_log
+
+--echo #
+--echo # Case 3 - Verify connected slave cannot reestablish replication
+--echo #
+
+--echo # Connecting to slave 1...
+connection slave;
+
+START SLAVE SQL_THREAD;
+source include/wait_for_slave_sql_to_stop.inc;
+
+--echo # Show the slave stopped with an error.
+LET $last_error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
 --disable_query_log
 eval SELECT "$last_error" AS Last_SQL_Error;
 --enable_query_log
 
-#
-# BUG#44830 : SLAVE START no longer results in error if RESTORE is running on master
-#
-#--echo #
-#--echo # Case 2 - Verify a new slave cannot connect
-#--echo #
-#
-#connect (slave2,localhost,root,,test,$SLAVE_MYPORT2,$SLAVE_MYSOCK2);
-#
-#--echo # Connecting to slave 2...
-#connection slave2;
-#
-#--echo # Capture slave 2's backupdir.
-#let $MYSQLD_S2_BACKUPDIR= `select @@datadir`;
-#SET @@global.backupdir = @@global.datadir;
-#
-#--replace_result $MASTER_MYPORT MASTER_A_PORT $_binlog_file MASTER_A_LOG_FILE $master_before_pos MASTER_A_LOG_POS
-#--eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$MASTER_MYPORT,master_user='root',master_log_file='$_binlog_file',master_log_pos=$master_before_pos
-#
-#--echo # Now verify slave cannot start.
-#--error ER_RESTORE_CANNOT_START_SLAVE
-#START SLAVE;
-#
-#--echo #
-#--echo # Case 3 - Verify connected slave cannot reestablish replication
-#--echo #
-#
-#--echo # Connecting to slave 1...
-#connection slave;
-#
-#START SLAVE SQL_THREAD;
-#source include/wait_for_slave_sql_to_start.inc;
-#
-#--echo # Show the slave stopped with an error.
-#LET $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
-#--disable_query_log
-#eval SELECT "$last_error" AS Last_SQL_Error;
-#--enable_query_log
-#
 --echo #
 --echo # Now resume restore on master
 --echo #
@@ -162,12 +168,8 @@ eval SHOW BINLOG EVENTS FROM $master_bef
 
 --echo # Showing tables on master.
 SHOW FULL TABLES FROM rpl_backup_block;
-
 SELECT * FROM rpl_backup_block.t1;
 
---echo # Get master's binlog position before restore.
-let $master_after_pos = query_get_value("SHOW MASTER STATUS", Position, 1);
-
 --echo #
 --echo # Case 4 - Verify slaves can connect after restore
 --echo #
@@ -185,46 +187,45 @@ START SLAVE;
 # Sync with master to ensure nothing is replicated after incident event.
 sync_with_master;
 
-#--echo # Showing tables on slave.
-#SHOW FULL TABLES FROM rpl_backup_block;
-#
-#--replace_result $MASTER_MYPORT MASTER_PORT
-#--replace_column 1 # 6 # 7 # 8 # 9 # 10 # 16 # 21 # 22 # 23 # 33 # 35 # 36 #
-#--query_vertical SHOW SLAVE STATUS
-#
-#--echo # Show the slave started without an error.
-#LET $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
-#--disable_query_log
-#eval SELECT "$last_error" AS Last_SQL_Error;
-#--enable_query_log
-#
-#SELECT * FROM rpl_backup_block.t1;
-
-#
-# BUG#44830 : SLAVE START no longer results in error if RESTORE is running on master
-#
-#--echo # Connecting to slave 2...
-#connection slave2;
-#
-#--source include/wait_for_slave_to_stop.inc
-#
-#SET global sql_slave_skip_counter=1;
-#
-#START SLAVE;
-#--source include/wait_for_slave_to_start.inc
-#
-## Sync with master to ensure nothing is replicated after incident event.
-#sync_with_master;
-#
-#--replace_result $MASTER_MYPORT MASTER_PORT
-#--replace_column 1 # 6 # 7 # 8 # 9 # 10 # 16 # 21 # 22 # 23 # 33 # 35 # 36 #
-#--query_vertical SHOW SLAVE STATUS
-#
-#--echo # Show the slave started without an error.
-#LET $last_error = query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
-#--disable_query_log
-#eval SELECT "$last_error" AS Last_SQL_Error;
-#--enable_query_log
+--replace_result $MASTER_MYPORT MASTER_PORT
+--replace_column 1 # 6 # 7 # 8 # 9 # 10 # 16 # 21 # 22 # 23 # 33 #
+--query_vertical SHOW SLAVE STATUS
+
+--echo # Show the slave started without an error.
+LET $last_error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
+--disable_query_log
+eval SELECT "$last_error" AS Last_SQL_Error;
+--enable_query_log
+
+--echo # Showing tables on slave.
+SHOW FULL TABLES FROM rpl_backup_block;
+SELECT * FROM rpl_backup_block.t1;
+
+--echo # Connecting to slave 2...
+connection slave2;
+
+START SLAVE;
+--source include/wait_for_slave_sql_to_stop.inc
+
+SET global sql_slave_skip_counter=1;
+START SLAVE SQL_THREAD;
+--source include/wait_for_slave_to_start.inc
+
+# Sync with master to ensure nothing is replicated after incident event.
+sync_with_master;
+--replace_result $MASTER_MYPORT MASTER_PORT
+--replace_column 1 # 6 # 7 # 8 # 9 # 10 # 16 # 21 # 22 # 23 # 33 # 37 # 38 #
+--query_vertical SHOW SLAVE STATUS
+
+--echo # Show the slave started without an error.
+LET $last_error= query_get_value("SHOW SLAVE STATUS", Last_IO_Error, 1);
+--disable_query_log
+eval SELECT "$last_error" AS Last_IO_Error;
+--enable_query_log
+
+--echo # Showing databases on slave.
+SHOW FULL TABLES FROM rpl_backup_block;
+SELECT * FROM rpl_backup_block.t1;
 
 --echo #
 --echo # Cleanup
@@ -237,18 +238,15 @@ connection slave;
 SLAVE STOP;
 --source include/wait_for_slave_to_stop.inc
 
-#
-# BUG#44830 : SLAVE START no longer results in error if RESTORE is running on master
-#
-#--echo # Connecting to slave 2...
-#connection slave2;
-#
-#--echo # Now stop the slave.
-#SLAVE STOP;
-#--source include/wait_for_slave_to_stop.inc
-#
-#--echo # Reset slave 2's backupdir.
-#SET @@global.backupdir = DEFAULT;
+--echo # Connecting to slave 2...
+connection slave2;
+
+--echo # Now stop the slave.
+SLAVE STOP;
+--source include/wait_for_slave_to_stop.inc
+
+--echo # Reset slave 2's backupdir.
+SET @@global.backupdir = DEFAULT;
 
 --echo # Connecting to master...
 connection master;
@@ -267,5 +265,14 @@ DROP DATABASE rpl_backup_block;
 --echo # Reset slave 1's backupdir.
 SET @@global.backupdir = DEFAULT;
 
+--echo # Connecting to slave 2...
+connection slave2;
+
+DROP DATABASE rpl_backup_block;
+
+--echo # Reset slave 2's backupdir.
+SET @@global.backupdir = DEFAULT;
+
+
 connection default;
 SET DEBUG_SYNC = 'reset';

=== modified file 'mysql-test/suite/rpl/t/rpl_killed_ddl.test'
--- a/mysql-test/suite/rpl/t/rpl_killed_ddl.test	2009-06-24 19:39:33 +0000
+++ b/mysql-test/suite/rpl/t/rpl_killed_ddl.test	2009-09-02 06:18:28 +0000
@@ -62,6 +62,7 @@ DROP TABLE IF EXISTS t1;
 DROP TABLE IF EXISTS t2;
 DROP TABLE IF EXISTS t3;
 DROP TABLE IF EXISTS t4;
+DROP VIEW IF EXISTS v1;
 DROP PROCEDURE IF EXISTS p1;
 DROP PROCEDURE IF EXISTS p2;
 DROP PROCEDURE IF EXISTS p3;
@@ -349,6 +350,7 @@ DROP TABLE IF EXISTS t1;
 DROP TABLE IF EXISTS t2;
 DROP TABLE IF EXISTS t3;
 DROP TABLE IF EXISTS t4;
+DROP VIEW IF EXISTS v1;
 DROP PROCEDURE IF EXISTS p1;
 DROP PROCEDURE IF EXISTS p2;
 DROP PROCEDURE IF EXISTS p3;

=== modified file 'mysql-test/t/flush_block_commit.test'
--- a/mysql-test/t/flush_block_commit.test	2009-03-27 22:06:26 +0000
+++ b/mysql-test/t/flush_block_commit.test	2009-09-01 15:57:05 +0000
@@ -29,15 +29,25 @@ BEGIN;
 INSERT INTO t1 VALUES(1);
 --echo # Switch to connection con2
 connection con2;
---send FLUSH TABLES WITH READ LOCK
+FLUSH TABLES WITH READ LOCK;
 --echo # Switch to connection con1
 connection con1;
-COMMIT;
+--echo # Sending:
+--send COMMIT
 --echo # Switch to connection con2
 connection con2;
---reap
+--echo # Wait until COMMIT gets blocked.
+let $wait_condition=
+  select count(*) = 1 from information_schema.processlist
+  where state = "Waiting for release of readlock" and info = "COMMIT";
+--source include/wait_condition.inc
+--echo # Verify that 'con1' was blocked and data did not move.
 SELECT * FROM t1;
 UNLOCK TABLES;
+--echo # Switch to connection con1
+connection con1;
+--echo # Reaping COMMIT
+--reap
 
 # No deadlock ?
 

=== modified file 'mysql-test/t/innodb_mysql_lock.test'
--- a/mysql-test/t/innodb_mysql_lock.test	2009-07-08 12:09:38 +0000
+++ b/mysql-test/t/innodb_mysql_lock.test	2009-09-09 13:01:25 +0000
@@ -1,5 +1,8 @@
 -- source include/have_innodb.inc
 
+# Save the initial number of concurrent sessions.
+--source include/count_sessions.inc
+
 --echo #
 --echo # Bug #22876 Four-way deadlock
 --echo #
@@ -51,8 +54,68 @@ INSERT INTO t1 VALUES (2);
 connection con2;
 --reap
 commit;
+set @@autocommit=1;
 connection con1;
 commit;
+set @@autocommit=1;
 connection con3;
 --reap
+set @@autocommit=1;
 connection default;
+
+disconnect con1;
+disconnect con3;
+
+--echo #
+--echo # Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB 
+--echo #            table cause warnings in errlog
+--echo #
+
+--echo #
+--echo # Note that this test for now relies on a global suppression of 
+--echo # the warning "Found lock of type 6 that is write and read locked"
+--echo # This suppression rule can be removed once Bug#42147 is properly
+--echo # fixed. See bug page for more info.
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (i INT) engine= innodb;
+
+--echo # Connection 2
+--echo # Get user-level lock
+connection con2;
+SELECT get_lock('bug42147_lock', 60);
+
+--echo # Connection 1
+connection default;
+--send INSERT INTO t1 SELECT get_lock('bug42147_lock', 60)
+
+--echo # Connection 2
+connection con2;
+let $wait_condition=
+  SELECT COUNT(*) > 0 FROM information_schema.processlist
+  WHERE state = 'User lock' 
+  AND info = 'INSERT INTO t1 SELECT get_lock(\'bug42147_lock\', 60)';
+--source include/wait_condition.inc
+LOCK TABLES t1 READ;
+SELECT release_lock('bug42147_lock');
+
+--echo # Connection 1
+connection default;
+--reap
+
+--echo # Connection 2
+connection con2;
+UNLOCK TABLES;
+
+--echo # Connection 1
+connection default;
+disconnect con2;
+DROP TABLE t1;
+
+# Check that all connections opened by test cases in this file are really
+# gone so execution of other tests won't be affected by their presence.
+--source include/wait_until_count_sessions.inc

=== modified file 'mysql-test/t/join_cache.test'
--- a/mysql-test/t/join_cache.test	2009-04-16 02:25:27 +0000
+++ b/mysql-test/t/join_cache.test	2009-09-04 06:58:24 +0000
@@ -1617,3 +1617,34 @@ set join_buffer_size=default;
 set join_cache_level=default;
 
 DROP TABLE t1,t2,t3,t4,t5;
+
+--echo #
+--echo # Bug#45267: Incomplete check caused wrong result.
+--echo #
+CREATE TABLE t1 (
+  `pk` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
+);
+CREATE TABLE t3 (
+  `pk` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
+);
+INSERT INTO t3 VALUES
+(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),
+(16),(17),(18),(19),(20);
+CREATE TABLE t2 (
+  `pk` int(11) NOT NULL AUTO_INCREMENT,
+  `int_nokey` int(11) NOT NULL,
+  `time_key` time NOT NULL,
+  PRIMARY KEY (`pk`),
+  KEY `time_key` (`time_key`)
+);
+INSERT INTO t2 VALUES (10,9,'22:36:46'),(11,0,'08:46:46');
+
+SELECT DISTINCT t1.`pk`
+FROM t1 RIGHT JOIN t2 STRAIGHT_JOIN t3 ON t2.`int_nokey`  ON t2.`time_key`
+GROUP BY 1;
+
+DROP TABLE IF EXISTS t1, t2, t3;
+
+
+--echo #
+

=== modified file 'mysql-test/t/lock.test'
--- a/mysql-test/t/lock.test	2009-08-03 15:26:04 +0000
+++ b/mysql-test/t/lock.test	2009-08-31 14:03:25 +0000
@@ -416,6 +416,30 @@ alter table t1 add column j int;
 unlock tables;
 drop table t1;
 
+
+--echo #
+--echo # Bug #43272 HANDLER SQL command does not work under LOCK TABLES
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT);
+LOCK TABLE t1 WRITE;
+
+--echo # HANDLER commands are not allowed in LOCK TABLES mode
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+HANDLER t1 OPEN;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+HANDLER t1 READ FIRST;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+HANDLER t1 CLOSE;
+
+UNLOCK TABLES;
+DROP TABLE t1;
+
+
 --echo #
 --echo # End of 6.0 tests.
 --echo #

=== modified file 'mysql-test/t/mdl_sync.test'
--- a/mysql-test/t/mdl_sync.test	2009-08-27 06:22:17 +0000
+++ b/mysql-test/t/mdl_sync.test	2009-09-01 15:57:05 +0000
@@ -439,6 +439,42 @@ disconnect con46044_2;
 drop table t1;
 
 
+--echo #
+--echo # Test for bug #46673 "Deadlock between FLUSH TABLES WITH READ LOCK
+--echo #                      and DML".
+--echo #
+--disable_warnings
+drop tables if exists t1;
+--enable_warnings
+connect (con46673, localhost, root,,);
+connection default;
+create table t1 (i int);
+
+--echo # Switching to connection 'con46673'.
+connection con46673;
+begin;
+insert into t1 values (1);
+
+--echo # Switching to connection 'default'.
+connection default;
+--echo # Statement below should not get blocked. And if after some
+--echo # changes to code it is there should not be a deadlock between
+--echo # it and transaction from connection 'con46673'.
+flush tables with read lock;
+unlock tables;
+
+--echo # Switching to connection 'con46673'.
+connection con46673;
+delete from t1 where i = 1;
+commit;
+
+--echo # Switching to connection 'default'.
+connection default;
+--echo # Clean-up
+disconnect con46673;
+drop table t1;
+
+
 # Check that all connections opened by test cases in this file are really
 # gone so execution of other tests won't be affected by their presence.
 --source include/wait_until_count_sessions.inc

=== modified file 'mysql-test/t/myisam.test'
--- a/mysql-test/t/myisam.test	2009-07-29 10:25:07 +0000
+++ b/mysql-test/t/myisam.test	2009-09-02 12:51:07 +0000
@@ -1536,3 +1536,27 @@ SELECT h+0, d + 0, e, g + 0 FROM t1;
 DROP TABLE t1;
 
 --echo End of 5.1 tests
+
+--echo #
+--echo # Bug#43600: Incorrect type conversion caused wrong result.
+--echo #
+CREATE TABLE t1 (
+  a int NOT NULL
+) engine= myisam;
+
+CREATE TABLE t2 (
+  a int NOT NULL,
+  b int NOT NULL,
+  filler char(100) DEFAULT NULL,
+  KEY a (a,b)
+) engine= myisam;
+
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t2 select A.a + 10 *B.a, 1, 'filler' from t1 A, t1 B;
+
+explain select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+select * from t1, t2 where t2.a=t1.a and t2.b + 1;
+
+drop table t1,t2;
+--echo # End of test case for the bug#43600
+

=== modified file 'mysql-test/t/read_only_innodb.test'
--- a/mysql-test/t/read_only_innodb.test	2009-03-30 13:01:09 +0000
+++ b/mysql-test/t/read_only_innodb.test	2009-09-01 15:57:05 +0000
@@ -16,7 +16,6 @@ DROP TABLE IF EXISTS table_11733 ;
 grant CREATE, SELECT, DROP on *.* to test@localhost;
 
 connect (con1,localhost,test,,test);
-connect (con2,localhost,root,,);
 
 connection default;
 set global read_only=0;
@@ -29,28 +28,20 @@ BEGIN;
 insert into table_11733 values(11733);
 
 connection default;
-send set global read_only=1;
-
-connection con2;
-let $wait_condition=
-  select count(*) = 1 from information_schema.processlist
-  where state = "Flushing tables" and info = "set global read_only=1";
---source include/wait_condition.inc
+set global read_only=1;
 
 connection con1;
 select @@global.read_only;
--- error ER_LOCK_DEADLOCK
 select * from table_11733 ;
+--error ER_OPTION_PREVENTS_STATEMENT
 COMMIT;
 
 connection default;
-reap;
 set global read_only=0;
 drop table table_11733 ;
 drop user test@localhost;
 
 disconnect con1;
-disconnect con2;
 
 #
 # Bug #35732: read-only blocks SELECT statements in InnoDB

=== modified file 'mysys/thr_lock.c'
--- a/mysys/thr_lock.c	2009-03-11 17:17:00 +0000
+++ b/mysys/thr_lock.c	2009-09-09 13:01:25 +0000
@@ -564,13 +564,30 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_O
     if (lock->write.data)
     {
       /*
-        We can allow a read lock even if there is already a write lock
-	 on the table in one the following cases:
-	 - This thread alread have a write lock on the table
-	 - The write lock is TL_WRITE_ALLOW_READ or TL_WRITE_DELAYED
-           and the read lock is TL_READ_HIGH_PRIORITY or TL_READ
-         - The write lock is TL_WRITE_CONCURRENT_INSERT or TL_WRITE_ALLOW_WRITE
-	   and the read lock is not TL_READ_NO_INSERT
+        We can allow a read lock even if there is already a
+        write lock on the table if they are owned by the same
+        thread or if they satisfy the following lock
+        compatibility matrix:
+
+           Request
+          /-------
+         H|++++  WRITE_ALLOW_WRITE
+         e|+++-  WRITE_ALLOW_READ
+         l|+++-  WRITE_CONCURRENT_INSERT
+         d|++++  WRITE_DELAYED
+           ||||
+           |||\= READ_NO_INSERT
+           ||\ = READ_HIGH_PRIORITY
+           |\  = READ_WITH_SHARED_LOCKS
+           \   = READ
+
+        + = Request can be satisified.
+        - = Request cannot be satisified.
+
+        READ_NO_INSERT and WRITE_ALLOW_WRITE should in principle
+        be incompatible. However this will cause starvation of
+        LOCK TABLE READ in InnoDB under high write load.
+        See Bug#42147 for more information.
       */
 
       DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx",

=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am	2009-07-31 20:21:25 +0000
+++ b/sql/Makefile.am	2009-09-03 09:09:27 +0000
@@ -103,7 +103,7 @@ noinst_HEADERS =	item.h item_func.h item
 			probes.h sql_audit.h transaction.h \
 			contributors.h sql_servers.h bml.h \
 			si_objects.h si_logs.h sql_plist.h mdl.h records.h \
-			sql_signal.h \
+			sql_cmd.h sql_signal.h \
 			rpl_handler.h replication.h sql_prepare.h debug_sync.h
 
 mysqld_SOURCES =	sql_lex.cc sql_handler.cc sql_partition.cc \

=== modified file 'sql/lock.cc'
--- a/sql/lock.cc	2009-08-25 07:22:47 +0000
+++ b/sql/lock.cc	2009-09-03 07:11:55 +0000
@@ -1109,6 +1109,19 @@ static volatile uint waiting_for_read_lo
 #define GOT_GLOBAL_READ_LOCK               1
 #define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
 
+/**
+  Take global read lock, wait if there is protection against lock.
+
+  If the global read lock is already taken by this thread, then nothing is done.
+
+  See also "Handling of global read locks" above.
+
+  @param thd     Reference to thread.
+
+  @retval False  Success, global read lock set, commits are NOT blocked.
+  @retval True   Failure, thread was killed.
+*/
+
 bool lock_global_read_lock(THD *thd)
 {
   DBUG_ENTER("lock_global_read_lock");
@@ -1199,6 +1212,16 @@ bool lock_global_read_lock(THD *thd)
 }
 
 
+/**
+  Unlock global read lock.
+
+  Commits may or may not be blocked when this function is called.
+
+  See also "Handling of global read locks" above.
+
+  @param thd    Reference to thread.
+*/
+
 void unlock_global_read_lock(THD *thd)
 {
   uint tmp;
@@ -1225,6 +1248,25 @@ void unlock_global_read_lock(THD *thd)
   DBUG_VOID_RETURN;
 }
 
+/**
+  Wait if the global read lock is set, and optionally seek protection against
+  global read lock.
+
+  See also "Handling of global read locks" above.
+
+  @param thd              Reference to thread.
+  @param abort_on_refresh If True, abort waiting if a refresh occurs,
+                          do NOT seek protection against GRL.
+                          If False, wait until the GRL is released and seek
+                          protection against GRL.
+  @param is_not_commit    If False, called from a commit operation,
+                          wait only if commit blocking is also enabled.
+
+  @retval False  Success, protection against global read lock is set
+                          (if !abort_on_refresh)
+  @retval True   Failure, wait was aborted or thread was killed.
+*/
+
 #define must_wait (global_read_lock &&                             \
                    (is_not_commit ||                               \
                     global_read_lock_blocks_commit))
@@ -1241,6 +1283,16 @@ bool wait_if_global_read_lock(THD *thd, 
 
   LINT_INIT(old_message);
   /*
+    If we already have protection against global read lock,
+    just increment the counter.
+  */
+  if (unlikely(thd->global_read_lock_protection > 0))
+  {
+    if (!abort_on_refresh)
+      thd->global_read_lock_protection++;
+    DBUG_RETURN(FALSE);
+  }
+  /*
     Assert that we do not own LOCK_open. If we would own it, other
     threads could not close their tables. This would make a pretty
     deadlock.
@@ -1303,6 +1355,7 @@ bool wait_if_global_read_lock(THD *thd, 
   }
   if (!abort_on_refresh && !result)
   {
+    thd->global_read_lock_protection++;
     protect_against_global_read_lock++;
     DBUG_PRINT("sql_lock", ("protect_against_global_read_lock incr: %u",
                             protect_against_global_read_lock));
@@ -1323,10 +1376,31 @@ bool wait_if_global_read_lock(THD *thd, 
 }
 
 
+/**
+  Release protection against global read lock and restart
+  global read lock waiters.
+
+  Should only be called if we have protection against global read lock.
+
+  See also "Handling of global read locks" above.
+
+  @param thd     Reference to thread.
+*/
+
 void start_waiting_global_read_lock(THD *thd)
 {
   bool tmp;
   DBUG_ENTER("start_waiting_global_read_lock");
+  /*
+    Ignore request if we do not have protection against global read lock.
+    (Note that this is a violation of the interface contract, hence the assert).
+  */
+  DBUG_ASSERT(thd->global_read_lock_protection > 0);
+  if (unlikely(thd->global_read_lock_protection == 0))
+    DBUG_VOID_RETURN;
+  /* Decrement local read lock protection counter, return if we still have it */
+  if (unlikely(--thd->global_read_lock_protection > 0))
+    DBUG_VOID_RETURN;
   if (unlikely(thd->global_read_lock))
     DBUG_VOID_RETURN;
   (void) pthread_mutex_lock(&LOCK_global_read_lock);
@@ -1342,6 +1416,21 @@ void start_waiting_global_read_lock(THD 
 }
 
 
+/**
+  Make global read lock also block commits.
+
+  The scenario is:
+   - This thread has the global read lock.
+   - Global read lock blocking of commits is not set.
+
+  See also "Handling of global read locks" above.
+
+  @param thd     Reference to thread.
+
+  @retval False  Success, global read lock set, commits are blocked.
+  @retval True   Failure, thread was killed.
+*/
+
 bool make_global_read_lock_block_commit(THD *thd)
 {
   bool error;

=== modified file 'sql/slave.cc'
--- a/sql/slave.cc	2009-07-28 14:16:37 +0000
+++ b/sql/slave.cc	2009-09-05 09:19:47 +0000
@@ -2916,6 +2916,19 @@ max_allowed_packet",
         sql_print_error("\
 Stopping slave I/O thread due to out-of-memory error from master");
         goto err;
+
+      /* WL#4612 When a slave requests binlog dump from a master, it will send
+       * an ER_MASTER_BLOCKING_SLAVES error to the slave and then stop the
+       * connection if RESTORE command is running on it. The slave must report
+       * an error and then stop the I/O thread after it recieves the error
+       * from the master.
+       */
+      case ER_MASTER_BLOCKING_SLAVES:
+        sql_print_error("\
+Stopping slave I/O thread due to Restore are running on the master");
+        mi->report(ERROR_LEVEL, ER_MASTER_BLOCKING_SLAVES,
+                  ER(ER_MASTER_BLOCKING_SLAVES));
+        goto err;
       }
       if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings,
                            reconnect_messages[SLAVE_RECON_ACT_EVENT]))

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2009-08-27 06:22:17 +0000
+++ b/sql/sql_base.cc	2009-09-01 15:57:05 +0000
@@ -2641,7 +2641,9 @@ bool open_table(THD *thd, TABLE_LIST *ta
     DBUG_RETURN(FALSE);
   }
 
+#ifdef DISABLED_UNTIL_GRL_IS_MADE_PART_OF_MDL
   if (!(share= (TABLE_SHARE *) mdl_ticket->get_cached_object()))
+#endif
   {
     if (!(share= get_table_share_with_create(thd, table_list, key,
                                              key_length, OPEN_VIEW,
@@ -2707,13 +2709,16 @@ bool open_table(THD *thd, TABLE_LIST *ta
     if (table_list->i_s_requested_object &  OPEN_VIEW_ONLY)
       goto err_unlock;
 
+#ifdef DISABLED_UNTIL_GRL_IS_MADE_PART_OF_MDL
     /*
       We are going to to store extra reference to the share in MDL-subsystem
       so we need to increase reference counter;
     */
     reference_table_share(share);
     mdl_ticket->set_cached_object(share, table_share_release_hook);
+#endif
   }
+#ifdef DISABLED_UNTIL_GRL_IS_MADE_PART_OF_MDL
   else
   {
     if (table_list->view)
@@ -2734,6 +2739,7 @@ bool open_table(THD *thd, TABLE_LIST *ta
     */
     reference_table_share(share);
   }
+#endif
 
   if (share->version != refresh_version)
   {

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2009-08-13 14:29:55 +0000
+++ b/sql/sql_class.cc	2009-09-03 07:11:55 +0000
@@ -453,6 +453,7 @@ THD::THD()
    examined_row_count(0),
    warning_info(&main_warning_info),
    stmt_da(&main_da),
+   global_read_lock_protection(0),
    global_read_lock(0),
    is_fatal_error(0),
    transaction_rollback_request(0),

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2009-08-26 09:14:05 +0000
+++ b/sql/sql_class.h	2009-09-03 09:09:27 +0000
@@ -1914,6 +1914,7 @@ public:
   ulong	     rand_saved_seed1, rand_saved_seed2;
   pthread_t  real_id;                           /* For debugging */
   my_thread_id  thread_id;
+  uint       global_read_lock_protection;// GRL protection count
   uint	     tmp_table, global_read_lock;
   uint	     server_status,open_options;
   enum enum_thread_type system_thread;
@@ -2560,9 +2561,9 @@ private:
     To raise a SQL condition, the code should use the public
     raise_error() or raise_warning() methods provided by class THD.
   */
-  friend class Signal_common;
-  friend class Signal_statement;
-  friend class Resignal_statement;
+  friend class Sql_cmd_common_signal;
+  friend class Sql_cmd_signal;
+  friend class Sql_cmd_resignal;
   friend void push_warning(THD*, MYSQL_ERROR::enum_warning_level, uint, const char*);
   friend void my_message_sql(uint, const char *, myf);
 

=== added file 'sql/sql_cmd.h'
--- a/sql/sql_cmd.h	1970-01-01 00:00:00 +0000
+++ b/sql/sql_cmd.h	2009-09-03 09:09:27 +0000
@@ -0,0 +1,166 @@
+/* Copyright 2009 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/**
+  @file Representation of an SQL command.
+*/
+
+#ifndef SQL_CMD_INCLUDED
+#define SQL_CMD_INCLUDED
+
+/*
+  When a command is added here, be sure it's also added in mysqld.cc
+  in "struct show_var_st status_vars[]= {" ...
+
+  If the command returns a result set or is not allowed in stored
+  functions or triggers, please also make sure that
+  sp_get_flags_for_command (sp_head.cc) returns proper flags for the
+  added SQLCOM_.
+*/
+
+enum enum_sql_command {
+  SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE,
+  SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT,
+  SQLCOM_DELETE, SQLCOM_TRUNCATE, SQLCOM_DROP_TABLE, SQLCOM_DROP_INDEX,
+
+  SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
+  SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_STATUS,
+  SQLCOM_SHOW_ENGINE_LOGS, SQLCOM_SHOW_ENGINE_STATUS, SQLCOM_SHOW_ENGINE_MUTEX,
+  SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
+  SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
+  SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
+  SQLCOM_SHOW_TRIGGERS,
+
+  SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
+  SQLCOM_GRANT,
+  SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
+  SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
+  SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
+  SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
+  SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS,
+  SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
+  SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT,
+  SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT,
+  SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
+  SQLCOM_BEGIN, SQLCOM_CHANGE_MASTER,
+  SQLCOM_RENAME_TABLE,  
+  SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS,
+  SQLCOM_SHOW_OPEN_TABLES,
+  SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
+  SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI,
+  SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
+  SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
+  SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES,
+  SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER,
+  SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
+  SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL,
+  SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION,
+  SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC,
+  SQLCOM_SHOW_STATUS_PROC, SQLCOM_SHOW_STATUS_FUNC,
+  SQLCOM_PREPARE, SQLCOM_EXECUTE, SQLCOM_DEALLOCATE_PREPARE,
+  SQLCOM_CREATE_VIEW, SQLCOM_DROP_VIEW,
+  SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER,
+  SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
+  SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
+  SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
+  SQLCOM_ALTER_TABLESPACE,
+  SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN,
+  SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT,
+  SQLCOM_SHOW_PLUGINS,
+  SQLCOM_SHOW_CONTRIBUTORS,
+  SQLCOM_CREATE_SERVER, SQLCOM_DROP_SERVER, SQLCOM_ALTER_SERVER,
+  SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
+  SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
+  SQLCOM_SHOW_CREATE_TRIGGER,
+  SQLCOM_ALTER_DB_UPGRADE,
+  SQLCOM_BACKUP, SQLCOM_RESTORE, SQLCOM_PURGE_BACKUP_LOGS, 
+  SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
+  SQLCOM_SIGNAL, SQLCOM_RESIGNAL,
+  SQLCOM_SHOW_RELAYLOG_EVENTS, 
+
+  /*
+    When a command is added here, be sure it's also added in mysqld.cc
+    in "struct show_var_st status_vars[]= {" ...
+  */
+  /*
+    Conditional SQL command codes are not recommended, but if you need to
+    define them, make sure that they are defined immediately before SQLCOM_END.
+  */
+#ifdef BACKUP_TEST
+  SQLCOM_BACKUP_TEST,
+#endif
+  /* This should be the last !!! */
+  SQLCOM_END
+};
+
+/**
+  @class Sql_cmd - Representation of an SQL command.
+
+  This class is an interface between the parser and the runtime.
+  The parser builds the appropriate derived classes of Sql_cmd
+  to represent a SQL statement in the parsed tree.
+  The execute() method in the derived classes of Sql_cmd contain the runtime
+  implementation.
+  Note that this interface is used for SQL statements recently implemented,
+  the code for older statements tend to load the LEX structure with more
+  attributes instead.
+  Implement new statements by sub-classing Sql_cmd, as this improves
+  code modularity (see the 'big switch' in dispatch_command()), and decreases
+  the total size of the LEX structure (therefore saving memory in stored
+  programs).
+  The recommended name of a derived class of Sql_cmd is Sql_cmd_<derived>.
+
+  Notice that the Sql_cmd class should not be confused with the Statement class.
+  Statement is a class that is used to manage an SQL command or a set 
+  of SQL commands. When the SQL statement text is analyzed, the parser will
+  create one or more Sql_cmd objects to represent the actual SQL commands.
+*/
+class Sql_cmd : public Sql_alloc
+{
+private:
+  Sql_cmd(const Sql_cmd &);         // No copy constructor wanted
+  void operator=(Sql_cmd &);        // No assignment operator wanted
+
+public:
+  /**
+    @brief Return the command code for this statement
+  */
+  virtual enum_sql_command sql_command_code() const = 0;
+
+  /**
+    Execute this SQL statement.
+    @param thd the current thread.
+    @retval false on success.
+    @retval true on error
+  */
+  virtual bool execute(THD *thd) = 0;
+
+protected:
+  Sql_cmd()
+  {}
+
+  virtual ~Sql_cmd()
+  {
+    /*
+      Sql_cmd objects are allocated in thd->mem_root.
+      In MySQL, the C++ destructor is never called, the underlying MEM_ROOT is
+      simply destroyed instead.
+      Do not rely on the destructor for any cleanup.
+    */
+    DBUG_ASSERT(FALSE);
+  }
+};
+
+#endif // SQL_CMD_INCLUDED

=== modified file 'sql/sql_error.cc'
--- a/sql/sql_error.cc	2009-07-30 09:41:30 +0000
+++ b/sql/sql_error.cc	2009-09-03 09:09:27 +0000
@@ -153,7 +153,7 @@ This file contains the implementation of
   This is implemented by using 'String MYSQL_ERROR::m_message_text'.
 
   The UTF8 -> error_message_charset_info conversion is implemented in
-  Signal_common::eval_signal_informations() (for path #B and #C).
+  Sql_cmd_common_signal::eval_signal_informations() (for path #B and #C).
 
   Future work
   -----------

=== modified file 'sql/sql_error.h'
--- a/sql/sql_error.h	2009-07-30 09:41:30 +0000
+++ b/sql/sql_error.h	2009-09-03 09:09:27 +0000
@@ -213,9 +213,9 @@ private:
   */
   friend class THD;
   friend class Warning_info;
-  friend class Signal_common;
-  friend class Signal_statement;
-  friend class Resignal_statement;
+  friend class Sql_cmd_common_signal;
+  friend class Sql_cmd_signal;
+  friend class Sql_cmd_resignal;
   friend class sp_rcontext;
 
   /**
@@ -512,7 +512,7 @@ private:
   /** Read only status. */
   bool m_read_only;
 
-  friend class Resignal_statement;
+  friend class Sql_cmd_resignal;
 };
 
 ///////////////////////////////////////////////////////////////////////////

=== modified file 'sql/sql_handler.cc'
--- a/sql/sql_handler.cc	2009-08-25 07:22:47 +0000
+++ b/sql/sql_handler.cc	2009-08-31 14:03:25 +0000
@@ -201,6 +201,11 @@ bool mysql_ha_open(THD *thd, TABLE_LIST 
                       tables->db, tables->table_name, tables->alias,
                       (int) reopen));
 
+  if (thd->locked_tables_mode)
+  {
+    my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
   if (tables->schema_table)
   {
     my_error(ER_WRONG_USAGE, MYF(0), "HANDLER OPEN",
@@ -387,6 +392,11 @@ bool mysql_ha_close(THD *thd, TABLE_LIST
   DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
                       tables->db, tables->table_name, tables->alias));
 
+  if (thd->locked_tables_mode)
+  {
+    my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
   if ((hash_tables= (TABLE_LIST*) my_hash_search(&thd->handler_tables_hash,
                                               (uchar*) tables->alias,
                                               strlen(tables->alias) + 1)))
@@ -449,6 +459,12 @@ bool mysql_ha_read(THD *thd, TABLE_LIST 
   DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
                       tables->db, tables->table_name, tables->alias));
 
+  if (thd->locked_tables_mode)
+  {
+    my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
   LINT_INIT(key);
   LINT_INIT(key_len);
 

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2009-07-28 14:16:37 +0000
+++ b/sql/sql_lex.cc	2009-09-03 09:09:27 +0000
@@ -341,6 +341,7 @@ void lex_start(THD *thd)
   lex->select_lex.group_list.empty();
   lex->select_lex.order_list.empty();
   lex->sql_command= SQLCOM_END;
+  lex->m_sql_cmd= NULL;
   lex->duplicates= DUP_ERROR;
   lex->ignore= 0;
   lex->spname= NULL;

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2009-08-26 09:14:05 +0000
+++ b/sql/sql_lex.h	2009-09-03 09:09:27 +0000
@@ -55,86 +55,7 @@ class Event_parse_data;
 #endif
 #endif
 
-/*
-  When a command is added here, be sure it's also added in mysqld.cc
-  in "struct show_var_st status_vars[]= {" ...
-
-  If the command returns a result set or is not allowed in stored
-  functions or triggers, please also make sure that
-  sp_get_flags_for_command (sp_head.cc) returns proper flags for the
-  added SQLCOM_.
-*/
-
-enum enum_sql_command {
-  SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE,
-  SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT,
-  SQLCOM_DELETE, SQLCOM_TRUNCATE, SQLCOM_DROP_TABLE, SQLCOM_DROP_INDEX,
-
-  SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
-  SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_STATUS,
-  SQLCOM_SHOW_ENGINE_LOGS, SQLCOM_SHOW_ENGINE_STATUS, SQLCOM_SHOW_ENGINE_MUTEX,
-  SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
-  SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
-  SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
-  SQLCOM_SHOW_TRIGGERS,
-
-  SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
-  SQLCOM_GRANT,
-  SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
-  SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
-  SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
-  SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
-  SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS,
-  SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
-  SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT,
-  SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT,
-  SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
-  SQLCOM_BEGIN, SQLCOM_CHANGE_MASTER,
-  SQLCOM_RENAME_TABLE,  
-  SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS,
-  SQLCOM_SHOW_OPEN_TABLES,
-  SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
-  SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI,
-  SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
-  SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
-  SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES,
-  SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER,
-  SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
-  SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL,
-  SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION,
-  SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC,
-  SQLCOM_SHOW_STATUS_PROC, SQLCOM_SHOW_STATUS_FUNC,
-  SQLCOM_PREPARE, SQLCOM_EXECUTE, SQLCOM_DEALLOCATE_PREPARE,
-  SQLCOM_CREATE_VIEW, SQLCOM_DROP_VIEW,
-  SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER,
-  SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
-  SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
-  SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
-  SQLCOM_ALTER_TABLESPACE,
-  SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN,
-  SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT,
-  SQLCOM_SHOW_PLUGINS,
-  SQLCOM_SHOW_CONTRIBUTORS,
-  SQLCOM_CREATE_SERVER, SQLCOM_DROP_SERVER, SQLCOM_ALTER_SERVER,
-  SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
-  SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
-  SQLCOM_SHOW_CREATE_TRIGGER,
-  SQLCOM_ALTER_DB_UPGRADE,
-  SQLCOM_BACKUP, SQLCOM_RESTORE, SQLCOM_PURGE_BACKUP_LOGS, 
-#ifdef BACKUP_TEST
-  SQLCOM_BACKUP_TEST,
-#endif
-  SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
-  SQLCOM_SIGNAL, SQLCOM_RESIGNAL,
-  SQLCOM_SHOW_RELAYLOG_EVENTS, 
-
-  /*
-    When a command is added here, be sure it's also added in mysqld.cc
-    in "struct show_var_st status_vars[]= {" ...
-  */
-  /* This should be the last !!! */
-  SQLCOM_END
-};
+#include "sql_cmd.h"
 
 // describe/explain types
 #define DESCRIBE_NORMAL		1
@@ -1560,62 +1481,6 @@ public:
   CHARSET_INFO *m_underscore_cs;
 };
 
-/**
-  Abstract representation of a statement.
-  This class is an interface between the parser and the runtime.
-  The parser builds the appropriate sub classes of Sql_statement
-  to represent a SQL statement in the parsed tree.
-  The execute() method in the sub classes contain the runtime implementation.
-  Note that this interface is used for SQL statement recently implemented,
-  the code for older statements tend to load the LEX structure with more
-  attributes instead.
-  The recommended way to implement new statements is to sub-class
-  Sql_statement, as this improves code modularity (see the 'big switch' in
-  dispatch_command()), and decrease the total size of the LEX structure
-  (therefore saving memory in stored programs).
-*/
-class Sql_statement : public Sql_alloc
-{
-public:
-  /**
-    Execute this SQL statement.
-    @param thd the current thread.
-    @return 0 on success.
-  */
-  virtual bool execute(THD *thd) = 0;
-
-protected:
-  /**
-    Constructor.
-    @param lex the LEX structure that represents parts of this statement.
-  */
-  Sql_statement(struct LEX *lex)
-    : m_lex(lex)
-  {}
-
-  /** Destructor. */
-  virtual ~Sql_statement()
-  {
-    /*
-      Sql_statement objects are allocated in thd->mem_root.
-      In MySQL, the C++ destructor is never called, the underlying MEM_ROOT is
-      simply destroyed instead.
-      Do not rely on the destructor for any cleanup.
-    */
-    DBUG_ASSERT(FALSE);
-  }
-
-protected:
-  /**
-    The legacy LEX structure for this statement.
-    The LEX structure contains the existing properties of the parsed tree.
-    TODO: with time, attributes from LEX should move to sub classes of
-    Sql_statement, so that the parser only builds Sql_statement objects
-    with the minimum set of attributes, instead of a LEX structure that
-    contains the collection of every possible attribute.
-  */
-  struct LEX *m_lex;
-};
 
 /* The state of the lex parsing. This is saved in the THD struct */
 
@@ -1721,7 +1586,7 @@ struct LEX: public Query_tables_list
   nesting_map allow_sum_func;
   enum_sql_command sql_command;
 
-  Sql_statement *m_stmt;
+  Sql_cmd *m_sql_cmd;
 
   /*
     Usually `expr` rule of yacc is quite reused but some commands better

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2009-08-27 18:34:09 +0000
+++ b/sql/sql_parse.cc	2009-09-11 12:06:42 +0000
@@ -1797,7 +1797,6 @@ int
 mysql_execute_command(THD *thd)
 {
   int res= FALSE;
-  bool need_start_waiting= FALSE; // have protection against global read lock
   int  up_result= 0;
   LEX  *lex= thd->lex;
   /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
@@ -2106,7 +2105,7 @@ mysql_execute_command(THD *thd)
       break;
 
     if (!thd->locked_tables_mode && lex->protect_against_global_read_lock &&
-        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+        wait_if_global_read_lock(thd, 0, 1))
       break;
 
     res= execute_sqlcom_select(thd, all_tables);
@@ -2583,10 +2582,9 @@ mysql_execute_command(THD *thd)
       read lock when it succeeds. This needs to be released by
       start_waiting_global_read_lock(). We protect the normal CREATE
       TABLE in the same way. That way we avoid that a new table is
-      created during a gobal read lock.
+      created during a global read lock.
     */
-    if (!thd->locked_tables_mode &&
-        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+    if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
     {
       res= 1;
       goto end_with_restore_list;
@@ -2859,8 +2857,7 @@ end_with_restore_list:
                             "INDEX DIRECTORY");
       create_info.data_file_name= create_info.index_file_name= NULL;
 
-      if (!thd->locked_tables_mode &&
-          !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+      if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
       {
         res= 1;
         break;
@@ -3088,8 +3085,7 @@ end_with_restore_list:
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
     if (update_precheck(thd, all_tables))
       break;
-    if (!thd->locked_tables_mode &&
-        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+    if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
       goto error;
     DBUG_ASSERT(select_lex->offset_limit == 0);
     unit->set_limit(select_lex);
@@ -3127,7 +3123,7 @@ end_with_restore_list:
     */
     if (!thd->locked_tables_mode &&
         lex->sql_command == SQLCOM_UPDATE_MULTI &&
-        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+        wait_if_global_read_lock(thd, 0, 1))
       goto error;
 
     res= mysql_multi_update_prepare(thd);
@@ -3212,8 +3208,7 @@ end_with_restore_list:
     if ((res= insert_precheck(thd, all_tables)))
       break;
 
-    if (!thd->locked_tables_mode &&
-        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+    if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
     {
       res= 1;
       break;
@@ -3254,8 +3249,7 @@ end_with_restore_list:
 
     unit->set_limit(select_lex);
 
-    if (! thd->locked_tables_mode &&
-        ! (need_start_waiting= ! wait_if_global_read_lock(thd, 0, 1)))
+    if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
     {
       res= 1;
       break;
@@ -3327,7 +3321,7 @@ end_with_restore_list:
                  ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
       goto error;
     }
-    if (!(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+    if (wait_if_global_read_lock(thd, 0, 1))
       goto error;
     res= mysql_truncate(thd, first_table, 0);
 
@@ -3340,8 +3334,7 @@ end_with_restore_list:
     DBUG_ASSERT(select_lex->offset_limit == 0);
     unit->set_limit(select_lex);
 
-    if (!thd->locked_tables_mode &&
-        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+    if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
     {
       res= 1;
       break;
@@ -3361,8 +3354,7 @@ end_with_restore_list:
       (TABLE_LIST *)thd->lex->auxiliary_table_list.first;
     multi_delete *del_result;
 
-    if (!thd->locked_tables_mode &&
-        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+    if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
     {
       res= 1;
       break;
@@ -3499,8 +3491,7 @@ end_with_restore_list:
     if (check_one_table_access(thd, privilege, all_tables))
       goto error;
 
-    if (!thd->locked_tables_mode &&
-        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+    if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
       goto error;
 
     res= mysql_load(thd, lex->exchange, first_table, lex->field_list,
@@ -3615,7 +3606,7 @@ end_with_restore_list:
     /* release transactional metadata locks. */
     thd->mdl_context.release_all_locks();
     if (lex->protect_against_global_read_lock &&
-        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+        wait_if_global_read_lock(thd, 0, 1))
       goto error;
 
     init_mdl_requests(all_tables);
@@ -4809,8 +4800,8 @@ create_sp_error:
   }
   case SQLCOM_SIGNAL:
   case SQLCOM_RESIGNAL:
-    DBUG_ASSERT(lex->m_stmt != NULL);
-    res= lex->m_stmt->execute(thd);
+    DBUG_ASSERT(lex->m_sql_cmd != NULL);
+    res= lex->m_sql_cmd->execute(thd);
     break;
   default:
 #ifndef EMBEDDED_LIBRARY
@@ -4851,7 +4842,7 @@ finish:
   if (bml_registered)
     BML_instance->bml_leave();
 
-  if (need_start_waiting)
+  if (thd->global_read_lock_protection > 0)
   {
     /*
       Release the protection against the global read lock and wake

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2009-08-26 09:14:05 +0000
+++ b/sql/sql_select.h	2009-09-08 08:00:55 +0000
@@ -1743,7 +1743,8 @@ public:
   */
   JOIN_TAB *get_sort_by_join_tab()
   {
-    return (need_tmp || !sort_by_table || skip_sort_order) ?
+    return (need_tmp || !sort_by_table || skip_sort_order ||
+            (group && !group_list)) ?
               NULL : join_tab+const_tables;
   }
 private:

=== modified file 'sql/sql_signal.cc'
--- a/sql/sql_signal.cc	2009-07-30 09:41:30 +0000
+++ b/sql/sql_signal.cc	2009-09-03 09:09:27 +0000
@@ -91,7 +91,8 @@ void Set_signal_information::clear()
   memset(m_item, 0, sizeof(m_item));
 }
 
-void Signal_common::assign_defaults(MYSQL_ERROR *cond,
+void Sql_cmd_common_signal::assign_defaults(
+                                    MYSQL_ERROR *cond,
                                     bool set_level_code,
                                     MYSQL_ERROR::enum_warning_level level,
                                     int sqlcode)
@@ -105,7 +106,7 @@ void Signal_common::assign_defaults(MYSQ
     cond->set_builtin_message_text(ER(sqlcode));
 }
 
-void Signal_common::eval_defaults(THD *thd, MYSQL_ERROR *cond)
+void Sql_cmd_common_signal::eval_defaults(THD *thd, MYSQL_ERROR *cond)
 {
   DBUG_ASSERT(cond);
 
@@ -260,7 +261,7 @@ static int assign_condition_item(MEM_ROO
 }
 
 
-int Signal_common::eval_signal_informations(THD *thd, MYSQL_ERROR *cond)
+int Sql_cmd_common_signal::eval_signal_informations(THD *thd, MYSQL_ERROR *cond)
 {
   struct cond_item_map
   {
@@ -292,7 +293,7 @@ int Signal_common::eval_signal_informati
   String *member;
   const LEX_STRING *name;
 
-  DBUG_ENTER("Signal_common::eval_signal_informations");
+  DBUG_ENTER("Sql_cmd_common_signal::eval_signal_informations");
 
   for (i= FIRST_DIAG_SET_PROPERTY;
        i <= LAST_DIAG_SET_PROPERTY;
@@ -418,13 +419,13 @@ end:
   DBUG_RETURN(result);
 }
 
-bool Signal_common::raise_condition(THD *thd, MYSQL_ERROR *cond)
+bool Sql_cmd_common_signal::raise_condition(THD *thd, MYSQL_ERROR *cond)
 {
   bool result= TRUE;
 
-  DBUG_ENTER("Signal_common::raise_condition");
+  DBUG_ENTER("Sql_cmd_common_signal::raise_condition");
 
-  DBUG_ASSERT(m_lex->query_tables == NULL);
+  DBUG_ASSERT(thd->lex->query_tables == NULL);
 
   eval_defaults(thd, cond);
   if (eval_signal_informations(thd, cond))
@@ -451,12 +452,12 @@ bool Signal_common::raise_condition(THD 
   DBUG_RETURN(result);
 }
 
-bool Signal_statement::execute(THD *thd)
+bool Sql_cmd_signal::execute(THD *thd)
 {
   bool result= TRUE;
   MYSQL_ERROR cond(thd->mem_root);
 
-  DBUG_ENTER("Signal_statement::execute");
+  DBUG_ENTER("Sql_cmd_signal::execute");
 
   thd->stmt_da->reset_diagnostics_area();
   thd->row_count_func= 0;
@@ -468,12 +469,12 @@ bool Signal_statement::execute(THD *thd)
 }
 
 
-bool Resignal_statement::execute(THD *thd)
+bool Sql_cmd_resignal::execute(THD *thd)
 {
   MYSQL_ERROR *signaled;
   int result= TRUE;
 
-  DBUG_ENTER("Resignal_statement::execute");
+  DBUG_ENTER("Sql_cmd_resignal::execute");
 
   thd->warning_info->m_warn_id= thd->query_id;
 
@@ -507,4 +508,3 @@ bool Resignal_statement::execute(THD *th
 
   DBUG_RETURN(result);
 }
-

=== modified file 'sql/sql_signal.h'
--- a/sql/sql_signal.h	2009-07-30 09:41:30 +0000
+++ b/sql/sql_signal.h	2009-09-03 09:09:27 +0000
@@ -17,27 +17,25 @@
 #define SQL_SIGNAL_H
 
 /**
-  Signal_common represents the common properties of the SIGNAL and RESIGNAL
-  statements.
+  Sql_cmd_common_signal represents the common properties of the
+  SIGNAL and RESIGNAL statements.
 */
-class Signal_common : public Sql_statement
+class Sql_cmd_common_signal : public Sql_cmd
 {
 protected:
   /**
     Constructor.
-    @param lex the LEX structure for this statement.
     @param cond the condition signaled if any, or NULL.
     @param set collection of signal condition item assignments.
   */
-  Signal_common(LEX *lex,
-                const sp_cond_type_t *cond,
-                const Set_signal_information& set)
-    : Sql_statement(lex),
+  Sql_cmd_common_signal(const sp_cond_type_t *cond,
+                        const Set_signal_information& set)
+    : Sql_cmd(),
       m_cond(cond),
       m_set_signal_information(set)
   {}
 
-  virtual ~Signal_common()
+  virtual ~Sql_cmd_common_signal()
   {}
 
   /**
@@ -91,60 +89,56 @@ protected:
 };
 
 /**
-  Signal_statement represents a SIGNAL statement.
+  Sql_cmd_signal represents a SIGNAL statement.
 */
-class Signal_statement : public Signal_common
+class Sql_cmd_signal : public Sql_cmd_common_signal
 {
 public:
   /**
     Constructor, used to represent a SIGNAL statement.
-    @param lex the LEX structure for this statement.
     @param cond the SQL condition to signal (required).
     @param set the collection of signal informations to signal.
   */
-  Signal_statement(LEX *lex,
-                const sp_cond_type_t *cond,
-                const Set_signal_information& set)
-    : Signal_common(lex, cond, set)
+  Sql_cmd_signal(const sp_cond_type_t *cond,
+                 const Set_signal_information& set)
+    : Sql_cmd_common_signal(cond, set)
   {}
 
-  virtual ~Signal_statement()
+  virtual ~Sql_cmd_signal()
   {}
 
-  /**
-    Execute a SIGNAL statement at runtime.
-    @param thd the current thread.
-    @return false on success.
-  */
+  virtual enum_sql_command sql_command_code() const
+  {
+    return SQLCOM_SIGNAL;
+  }
+
   virtual bool execute(THD *thd);
 };
 
 /**
-  Resignal_statement represents a RESIGNAL statement.
+  Sql_cmd_resignal represents a RESIGNAL statement.
 */
-class Resignal_statement : public Signal_common
+class Sql_cmd_resignal : public Sql_cmd_common_signal
 {
 public:
   /**
     Constructor, used to represent a RESIGNAL statement.
-    @param lex the LEX structure for this statement.
     @param cond the SQL condition to resignal (optional, may be NULL).
     @param set the collection of signal informations to resignal.
   */
-  Resignal_statement(LEX *lex,
-                     const sp_cond_type_t *cond,
-                     const Set_signal_information& set)
-    : Signal_common(lex, cond, set)
+  Sql_cmd_resignal(const sp_cond_type_t *cond,
+                   const Set_signal_information& set)
+    : Sql_cmd_common_signal(cond, set)
   {}
 
-  virtual ~Resignal_statement()
+  virtual ~Sql_cmd_resignal()
   {}
 
-  /**
-    Execute a RESIGNAL statement at runtime.
-    @param thd the current thread.
-    @return 0 on success.
-  */
+  virtual enum_sql_command sql_command_code() const
+  {
+    return SQLCOM_RESIGNAL;
+  }
+
   virtual bool execute(THD *thd);
 };
 

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2009-08-25 07:22:47 +0000
+++ b/sql/sql_table.cc	2009-09-03 07:11:55 +0000
@@ -1728,7 +1728,7 @@ void write_bin_log(THD *thd, bool clear_
 bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
                     my_bool drop_temporary)
 {
-  bool error, need_start_waiting= FALSE;
+  bool error;
   Drop_table_error_handler err_handler(thd->get_internal_handler());
 
   DBUG_ENTER("mysql_rm_table");
@@ -1737,8 +1737,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST 
 
   if (!drop_temporary)
   {
-    if (!thd->locked_tables_mode &&
-        !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+    if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
       DBUG_RETURN(TRUE);
   }
 
@@ -1746,7 +1745,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST 
   error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
   thd->pop_internal_handler();
 
-  if (need_start_waiting)
+  if (thd->global_read_lock_protection > 0)
     start_waiting_global_read_lock(thd);
 
   if (error)

=== modified file 'sql/sql_trigger.cc'
--- a/sql/sql_trigger.cc	2009-08-25 07:22:47 +0000
+++ b/sql/sql_trigger.cc	2009-09-03 07:11:55 +0000
@@ -328,7 +328,6 @@ bool mysql_create_or_drop_trigger(THD *t
   TABLE *table;
   bool result= TRUE;
   String stmt_query;
-  bool need_start_waiting= FALSE;
   bool lock_upgrade_done= FALSE;
   MDL_ticket *mdl_ticket= NULL;
 
@@ -386,8 +385,7 @@ bool mysql_create_or_drop_trigger(THD *t
     LOCK_open is not enough because global read lock is held without holding
     LOCK_open).
   */
-  if (!thd->locked_tables_mode &&
-      !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+  if (!thd->locked_tables_mode && wait_if_global_read_lock(thd, 0, 1))
     DBUG_RETURN(TRUE);
 
   if (!create)
@@ -521,7 +519,7 @@ end:
   if (thd->locked_tables_mode && tables && lock_upgrade_done)
     mdl_ticket->downgrade_exclusive_lock();
 
-  if (need_start_waiting)
+  if (thd->global_read_lock_protection > 0)
     start_waiting_global_read_lock(thd);
 
   if (!result)

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2009-08-24 09:56:29 +0000
+++ b/sql/sql_yacc.yy	2009-09-03 09:09:27 +0000
@@ -2773,9 +2773,9 @@ signal_stmt:
             Yacc_state *state= & thd->m_parser_state->m_yacc;
 
             lex->sql_command= SQLCOM_SIGNAL;
-            lex->m_stmt= new (thd->mem_root) Signal_statement(lex, $2,
-                                                      state->m_set_signal_info);
-            if (lex->m_stmt == NULL)
+            lex->m_sql_cmd=
+              new (thd->mem_root) Sql_cmd_signal($2, state->m_set_signal_info);
+            if (lex->m_sql_cmd == NULL)
               MYSQL_YYABORT;
           }
         ;
@@ -2912,9 +2912,10 @@ resignal_stmt:
             Yacc_state *state= & thd->m_parser_state->m_yacc;
 
             lex->sql_command= SQLCOM_RESIGNAL;
-            lex->m_stmt= new (thd->mem_root) Resignal_statement(lex, $2,
-                                                      state->m_set_signal_info);
-            if (lex->m_stmt == NULL)
+            lex->m_sql_cmd=
+              new (thd->mem_root) Sql_cmd_resignal($2,
+                                                   state->m_set_signal_info);
+            if (lex->m_sql_cmd == NULL)
               MYSQL_YYABORT;
           }
         ;

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2009-07-24 12:37:26 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2009-09-02 12:51:07 +0000
@@ -63,7 +63,7 @@ static bool innodb_inited = 0;
 static handlerton *innodb_hton_ptr;
 
 C_MODE_START
-static my_bool index_cond_func_innodb(void *arg);
+static uint index_cond_func_innodb(void *arg);
 C_MODE_END
 
 
@@ -8563,9 +8563,12 @@ ha_rows ha_innobase::multi_range_read_in
 
 C_MODE_START
 
-/* Index condition check function to be called from within Innobase */
+/*
+  Index condition check function to be called from within Innobase.
+  See note on ICP_RESULT for return values description.
+*/
 
-static my_bool index_cond_func_innodb(void *arg)
+static uint index_cond_func_innodb(void *arg)
 {
   ha_innobase *h= (ha_innobase*)arg;
   if (h->end_range)
@@ -8573,7 +8576,7 @@ static my_bool index_cond_func_innodb(vo
     if (h->compare_key2(h->end_range) > 0)
       return 2; /* caller should return HA_ERR_END_OF_FILE already */
   }
-  return (my_bool)h->pushed_idx_cond->val_int();
+  return test(h->pushed_idx_cond->val_int());
 }
 
 C_MODE_END

=== modified file 'storage/innobase/include/row0mysql.h'
--- a/storage/innobase/include/row0mysql.h	2009-07-28 14:16:37 +0000
+++ b/storage/innobase/include/row0mysql.h	2009-09-02 12:51:07 +0000
@@ -524,7 +524,7 @@ struct mysql_row_templ_struct {
 #define ROW_PREBUILT_ALLOCATED	78540783
 #define ROW_PREBUILT_FREED	26423527
 
-typedef my_bool (*index_cond_func_t)(void *param);
+typedef uint (*index_cond_func_t)(void *param);
 
 /* A struct for (sometimes lazily) prebuilt structures in an Innobase table
 handle used within MySQL; these are used to save CPU time. */

=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc	2009-08-04 19:50:51 +0000
+++ b/storage/myisam/ha_myisam.cc	2009-09-02 12:51:07 +0000
@@ -1504,15 +1504,15 @@ int ha_myisam::delete_row(const uchar *b
 
 C_MODE_START
 
-my_bool index_cond_func_myisam(void *arg)
+ICP_RESULT index_cond_func_myisam(void *arg)
 {
   ha_myisam *h= (ha_myisam*)arg;
   if (h->end_range)
   {
     if (h->compare_key2(h->end_range) > 0)
-      return 2; /* caller should return HA_ERR_END_OF_FILE already */
+      return ICP_OUT_OF_RANGE; /* caller should return HA_ERR_END_OF_FILE already */
   }
-  return (my_bool)h->pushed_idx_cond->val_int();
+  return (ICP_RESULT) test(h->pushed_idx_cond->val_int());
 }
 
 C_MODE_END

=== modified file 'storage/myisam/ha_myisam.h'
--- a/storage/myisam/ha_myisam.h	2009-08-03 17:47:05 +0000
+++ b/storage/myisam/ha_myisam.h	2009-09-02 12:51:07 +0000
@@ -35,7 +35,7 @@ extern TYPELIB myisam_recover_typelib;
 extern ulong myisam_recover_options;
 
 C_MODE_START
-my_bool index_cond_func_myisam(void *arg);
+ICP_RESULT index_cond_func_myisam(void *arg);
 C_MODE_END
 
 class ha_myisam: public handler
@@ -167,7 +167,7 @@ public:
   Item *idx_cond_push(uint keyno, Item* idx_cond);
 private:
   DsMrr_impl ds_mrr;
-  friend my_bool index_cond_func_myisam(void *arg);
+  friend ICP_RESULT index_cond_func_myisam(void *arg);
 };
 
 #if !defined(EMBEDDED_LIBRARY) && defined(HAVE_MYISAM_PHYSICAL_LOGGING)

=== modified file 'storage/myisam/myisamdef.h'
--- a/storage/myisam/myisamdef.h	2009-08-03 17:47:05 +0000
+++ b/storage/myisam/myisamdef.h	2009-09-02 12:51:07 +0000
@@ -253,8 +253,7 @@ typedef struct st_mi_isam_share
   my_bool MI_LOG_OPEN_stored_in_physical_log;
 } MYISAM_SHARE;
 
-
-typedef my_bool (*index_cond_func_t)(void *param);
+typedef ICP_RESULT (*index_cond_func_t)(void *param);
 
 /** Information local to the table's instance */
 struct st_myisam_info


Attachment: [text/bzr-bundle] bzr/alik@sun.com-20090911120642-3mpeoeaiimux0zgd.bundle
Thread
bzr push into mysql-5.4 branch (alik:2814)Alexander Nozdrin11 Sep