List:Commits« Previous MessageNext Message »
From:Jon Olav Hauglid Date:October 1 2010 10:23am
Subject:bzr commit into mysql-trunk-merge branch (jon.hauglid:3204)
View as plain text  
#At file:///export/home/x/mysql-trunk-merge-test/ based on revid:bernt.johnsen@stripped

 3204 Jon Olav Hauglid	2010-10-01 [merge]
      Merge from mysql-5.5-bugteam to mysql-trunk-merge.

    modified:
      config.h.cmake
      configure.cmake
      configure.in
      dbug/dbug.c
      include/my_pthread.h
      include/mysql/psi/mysql_thread.h
      mysql-test/include/handler.inc
      mysql-test/r/check.result
      mysql-test/r/delayed.result
      mysql-test/r/flush.result
      mysql-test/r/handler_innodb.result
      mysql-test/r/handler_myisam.result
      mysql-test/r/log_tables_upgrade.result
      mysql-test/r/lowercase_fs_off.result
      mysql-test/r/mdl_sync.result
      mysql-test/r/merge.result
      mysql-test/r/myisampack.result
      mysql-test/r/mysql_upgrade.result
      mysql-test/r/mysql_upgrade_ssl.result
      mysql-test/r/variables_debug.result
      mysql-test/r/xa.result
      mysql-test/suite/parts/r/partition_special_innodb.result
      mysql-test/suite/perfschema/r/dml_setup_instruments.result
      mysql-test/t/check.test
      mysql-test/t/delayed.test
      mysql-test/t/flush.test
      mysql-test/t/lowercase_fs_off.test
      mysql-test/t/mdl_sync.test
      mysql-test/t/merge.test
      mysql-test/t/variables_debug.test
      mysql-test/t/xa.test
      mysys/thr_rwlock.c
      sql/events.cc
      sql/events.h
      sql/mdl.cc
      sql/mdl.h
      sql/sql_acl.cc
      sql/sql_admin.cc
      sql/sql_alter.cc
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_insert.cc
      sql/sql_lex.h
      sql/sql_parse.cc
      sql/sql_parse.h
      sql/sql_reload.cc
      sql/sql_rename.cc
      sql/sql_table.cc
      sql/sql_trigger.cc
      sql/sql_trigger.h
      sql/sql_truncate.cc
      sql/sql_yacc.yy
      sql/table.cc
      sql/table.h
      sql/transaction.cc
      storage/myisammrg/ha_myisammrg.cc
=== modified file 'config.h.cmake'
--- a/config.h.cmake	2010-07-29 10:44:35 +0000
+++ b/config.h.cmake	2010-10-01 10:23:16 +0000
@@ -220,7 +220,6 @@
 #cmakedefine HAVE_PTHREAD_KEY_DELETE 1
 #cmakedefine HAVE_PTHREAD_KILL 1
 #cmakedefine HAVE_PTHREAD_RWLOCK_RDLOCK 1
-#cmakedefine HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP 1
 #cmakedefine HAVE_PTHREAD_SETPRIO_NP 1
 #cmakedefine HAVE_PTHREAD_SETSCHEDPARAM 1
 #cmakedefine HAVE_PTHREAD_SIGMASK 1

=== modified file 'configure.cmake'
--- a/configure.cmake	2010-07-29 10:44:35 +0000
+++ b/configure.cmake	2010-10-01 10:23:16 +0000
@@ -346,7 +346,6 @@ CHECK_FUNCTION_EXISTS (pthread_condattr_
 CHECK_FUNCTION_EXISTS (pthread_init HAVE_PTHREAD_INIT)
 CHECK_FUNCTION_EXISTS (pthread_key_delete HAVE_PTHREAD_KEY_DELETE)
 CHECK_FUNCTION_EXISTS (pthread_rwlock_rdlock HAVE_PTHREAD_RWLOCK_RDLOCK)
-CHECK_FUNCTION_EXISTS (pthread_rwlockattr_setkind_np HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP)
 CHECK_FUNCTION_EXISTS (pthread_sigmask HAVE_PTHREAD_SIGMASK)
 CHECK_FUNCTION_EXISTS (pthread_threadmask HAVE_PTHREAD_THREADMASK)
 CHECK_FUNCTION_EXISTS (pthread_yield_np HAVE_PTHREAD_YIELD_NP)

=== modified file 'configure.in'
--- a/configure.in	2010-09-29 14:41:24 +0000
+++ b/configure.in	2010-10-01 10:23:16 +0000
@@ -2171,7 +2171,7 @@ AC_CHECK_FUNCS(alarm bfill bmove bsearch
   mkstemp mlockall perror poll pread pthread_attr_create mmap mmap64 getpagesize \
   pthread_attr_getstacksize pthread_attr_setstacksize pthread_condattr_create \
   pthread_getsequence_np pthread_key_delete pthread_rwlock_rdlock \
-  pthread_rwlockattr_setkind_np pthread_sigmask \
+  pthread_sigmask \
   readlink realpath rename rint rwlock_init setupterm \
   shmget shmat shmdt shmctl sigaction sigemptyset sigaddset \
   sighold sigset sigthreadmask port_create sleep thr_yield \

=== modified file 'dbug/dbug.c'
--- a/dbug/dbug.c	2010-09-15 11:51:29 +0000
+++ b/dbug/dbug.c	2010-10-01 10:23:16 +0000
@@ -515,11 +515,16 @@ int DbugParse(CODE_STATE *cs, const char
     stack->maxdepth= stack->next->maxdepth;
     stack->sub_level= stack->next->sub_level;
     strcpy(stack->name, stack->next->name);
-    stack->out_file= stack->next->out_file;
     stack->prof_file= stack->next->prof_file;
     if (stack->next == &init_settings)
     {
-      /* never share with the global parent - it can change under your feet */
+      /*
+        Never share with the global parent - it can change under your feet.
+
+        Reset out_file to stderr to prevent sharing of trace files between
+        global and session settings.
+      */
+      stack->out_file= stderr;
       stack->functions= ListCopy(init_settings.functions);
       stack->p_functions= ListCopy(init_settings.p_functions);
       stack->keywords= ListCopy(init_settings.keywords);
@@ -527,6 +532,7 @@ int DbugParse(CODE_STATE *cs, const char
     }
     else
     {
+      stack->out_file= stack->next->out_file;
       stack->functions= stack->next->functions;
       stack->p_functions= stack->next->p_functions;
       stack->keywords= stack->next->keywords;

=== modified file 'include/my_pthread.h'
--- a/include/my_pthread.h	2010-08-20 08:48:59 +0000
+++ b/include/my_pthread.h	2010-10-01 10:23:16 +0000
@@ -583,7 +583,7 @@ int my_pthread_fastmutex_lock(my_pthread
 /* Use our own version of read/write locks */
 #define NEED_MY_RW_LOCK 1
 #define rw_lock_t my_rw_lock_t
-#define my_rwlock_init(A,B) my_rw_init((A), 0)
+#define my_rwlock_init(A,B) my_rw_init((A))
 #define rw_rdlock(A) my_rw_rdlock((A))
 #define rw_wrlock(A) my_rw_wrlock((A))
 #define rw_tryrdlock(A) my_rw_tryrdlock((A))
@@ -595,49 +595,82 @@ int my_pthread_fastmutex_lock(my_pthread
 #endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */
 
 
-/*
-  Portable read-write locks which prefer readers.
+/**
+  Portable implementation of special type of read-write locks.
 
-  Required by some algorithms in order to provide correctness.
-*/
+  These locks have two properties which are unusual for rwlocks:
+  1) They "prefer readers" in the sense that they do not allow
+     situations in which rwlock is rd-locked and there is a
+     pending rd-lock which is blocked (e.g. due to pending
+     request for wr-lock).
+     This is a stronger guarantee than one which is provided for
+     PTHREAD_RWLOCK_PREFER_READER_NP rwlocks in Linux.
+     MDL subsystem deadlock detector relies on this property for
+     its correctness.
+  2) They are optimized for uncontended wr-lock/unlock case.
+     This is scenario in which they are most oftenly used
+     within MDL subsystem. Optimizing for it gives significant
+     performance improvements in some of tests involving many
+     connections.
+
+  Another important requirement imposed on this type of rwlock
+  by the MDL subsystem is that it should be OK to destroy rwlock
+  object which is in unlocked state even though some threads might
+  have not yet fully left unlock operation for it (of course there
+  is an external guarantee that no thread will try to lock rwlock
+  which is destroyed).
+  Putting it another way the unlock operation should not access
+  rwlock data after changing its state to unlocked.
 
-#if defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP)
-/*
-  On systems which have a way to specify that readers should
-  be preferred through attribute mechanism (e.g. Linux) we use
-  system implementation of read/write locks.
+  TODO/FIXME: We should consider alleviating this requirement as
+  it blocks us from doing certain performance optimizations.
 */
-#define rw_pr_lock_t pthread_rwlock_t
+
+typedef struct st_rw_pr_lock_t {
+  /**
+    Lock which protects the structure.
+    Also held for the duration of wr-lock.
+  */
+  pthread_mutex_t lock;
+  /**
+    Condition variable which is used to wake-up
+    writers waiting for readers to go away.
+  */
+  pthread_cond_t no_active_readers;
+  /** Number of active readers. */
+  uint active_readers;
+  /** Number of writers waiting for readers to go away. */
+  uint writers_waiting_readers;
+  /** Indicates whether there is an active writer. */
+  my_bool active_writer;
+#ifdef SAFE_MUTEX
+  /** Thread holding wr-lock (for debug purposes only). */
+  pthread_t writer_thread;
+#endif
+} rw_pr_lock_t;
+
 extern int rw_pr_init(rw_pr_lock_t *);
-#define rw_pr_rdlock(A) pthread_rwlock_rdlock(A)
-#define rw_pr_wrlock(A) pthread_rwlock_wrlock(A)
-#define rw_pr_tryrdlock(A) pthread_rwlock_tryrdlock(A)
-#define rw_pr_trywrlock(A) pthread_rwlock_trywrlock(A)
-#define rw_pr_unlock(A) pthread_rwlock_unlock(A)
-#define rw_pr_destroy(A) pthread_rwlock_destroy(A)
+extern int rw_pr_rdlock(rw_pr_lock_t *);
+extern int rw_pr_wrlock(rw_pr_lock_t *);
+extern int rw_pr_unlock(rw_pr_lock_t *);
+extern int rw_pr_destroy(rw_pr_lock_t *);
+#ifdef SAFE_MUTEX
+#define rw_pr_lock_assert_write_owner(A) \
+  DBUG_ASSERT((A)->active_writer && pthread_equal(pthread_self(), \
+                                                  (A)->writer_thread))
+#define rw_pr_lock_assert_not_write_owner(A) \
+  DBUG_ASSERT(! (A)->active_writer || ! pthread_equal(pthread_self(), \
+                                                      (A)->writer_thread))
+#else
 #define rw_pr_lock_assert_write_owner(A)
 #define rw_pr_lock_assert_not_write_owner(A)
-#else
-/* Otherwise we have to use our own implementation of read/write locks. */
-#define NEED_MY_RW_LOCK 1
-struct st_my_rw_lock_t;
-#define rw_pr_lock_t my_rw_lock_t
-extern int rw_pr_init(struct st_my_rw_lock_t *);
-#define rw_pr_rdlock(A) my_rw_rdlock((A))
-#define rw_pr_wrlock(A) my_rw_wrlock((A))
-#define rw_pr_tryrdlock(A) my_rw_tryrdlock((A))
-#define rw_pr_trywrlock(A) my_rw_trywrlock((A))
-#define rw_pr_unlock(A) my_rw_unlock((A))
-#define rw_pr_destroy(A) my_rw_destroy((A))
-#define rw_pr_lock_assert_write_owner(A) my_rw_lock_assert_write_owner((A))
-#define rw_pr_lock_assert_not_write_owner(A) my_rw_lock_assert_not_write_owner((A))
-#endif /* defined(HAVE_PTHREAD_RWLOCK_RDLOCK) && defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) */
+#endif /* SAFE_MUTEX */
 
 
 #ifdef NEED_MY_RW_LOCK
 /*
-  On systems which don't support native read/write locks, or don't support
-  read/write locks which prefer readers we have to use own implementation.
+  On systems which don't support native read/write locks we have
+  to use own implementation.
 */
 typedef struct st_my_rw_lock_t {
 	pthread_mutex_t lock;		/* lock for structure		*/
@@ -645,13 +678,12 @@ typedef struct st_my_rw_lock_t {
 	pthread_cond_t	writers;	/* waiting writers		*/
 	int		state;		/* -1:writer,0:free,>0:readers	*/
 	int             waiters;        /* number of waiting writers	*/
-	my_bool         prefer_readers;
 #ifdef SAFE_MUTEX
         pthread_t       write_thread;
 #endif
 } my_rw_lock_t;
 
-extern int my_rw_init(my_rw_lock_t *, my_bool *);
+extern int my_rw_init(my_rw_lock_t *);
 extern int my_rw_destroy(my_rw_lock_t *);
 extern int my_rw_rdlock(my_rw_lock_t *);
 extern int my_rw_wrlock(my_rw_lock_t *);

=== modified file 'include/mysql/psi/mysql_thread.h'
--- a/include/mysql/psi/mysql_thread.h	2010-08-20 08:48:59 +0000
+++ b/include/mysql/psi/mysql_thread.h	2010-10-01 10:23:16 +0000
@@ -141,9 +141,7 @@ typedef struct st_mysql_rwlock mysql_rwl
   @c mysql_prlock_t is a drop-in replacement for @c rw_pr_lock_t.
   @sa mysql_prlock_init
   @sa mysql_prlock_rdlock
-  @sa mysql_prlock_tryrdlock
   @sa mysql_prlock_wrlock
-  @sa mysql_prlock_trywrlock
   @sa mysql_prlock_unlock
   @sa mysql_prlock_destroy
 */
@@ -421,20 +419,6 @@ typedef struct st_mysql_cond mysql_cond_
 #endif
 
 /**
-  @def mysql_prlock_tryrdlock(RW)
-  Instrumented rw_pr_tryrdlock.
-  @c mysql_prlock_tryrdlock is a drop-in replacement
-  for @c rw_pr_tryrdlock.
-*/
-#ifdef HAVE_PSI_INTERFACE
-  #define mysql_prlock_tryrdlock(RW) \
-    inline_mysql_prlock_tryrdlock(RW, __FILE__, __LINE__)
-#else
-  #define mysql_prlock_tryrdlock(RW) \
-    inline_mysql_prlock_tryrdlock(RW)
-#endif
-
-/**
   @def mysql_rwlock_trywrlock(RW)
   Instrumented rwlock_trywrlock.
   @c mysql_rwlock_trywrlock is a drop-in replacement
@@ -449,20 +433,6 @@ typedef struct st_mysql_cond mysql_cond_
 #endif
 
 /**
-  @def mysql_prlock_trywrlock(RW)
-  Instrumented rw_pr_trywrlock.
-  @c mysql_prlock_trywrlock is a drop-in replacement
-  for @c rw_pr_trywrlock.
-*/
-#ifdef HAVE_PSI_INTERFACE
-  #define mysql_prlock_trywrlock(RW) \
-    inline_mysql_prlock_trywrlock(RW, __FILE__, __LINE__)
-#else
-  #define mysql_prlock_trywrlock(RW) \
-    inline_mysql_prlock_trywrlock(RW)
-#endif
-
-/**
   @def mysql_rwlock_unlock(RW)
   Instrumented rwlock_unlock.
   @c mysql_rwlock_unlock is a drop-in replacement
@@ -905,35 +875,6 @@ static inline int inline_mysql_rwlock_tr
   return result;
 }
 
-#ifndef DISABLE_MYSQL_PRLOCK_H
-static inline int inline_mysql_prlock_tryrdlock(
-  mysql_prlock_t *that
-#ifdef HAVE_PSI_INTERFACE
-  , const char *src_file, uint src_line
-#endif
-  )
-{
-  int result;
-#ifdef HAVE_PSI_INTERFACE
-  struct PSI_rwlock_locker *locker= NULL;
-  PSI_rwlock_locker_state state;
-  if (likely(PSI_server && that->m_psi))
-  {
-    locker= PSI_server->get_thread_rwlock_locker(&state, that->m_psi,
-                                                 PSI_RWLOCK_TRYREADLOCK);
-    if (likely(locker != NULL))
-      PSI_server->start_rwlock_rdwait(locker, src_file, src_line);
-  }
-#endif
-  result= rw_pr_tryrdlock(&that->m_prlock);
-#ifdef HAVE_PSI_INTERFACE
-  if (likely(locker != NULL))
-    PSI_server->end_rwlock_rdwait(locker, result);
-#endif
-  return result;
-}
-#endif
-
 static inline int inline_mysql_rwlock_trywrlock(
   mysql_rwlock_t *that
 #ifdef HAVE_PSI_INTERFACE
@@ -961,35 +902,6 @@ static inline int inline_mysql_rwlock_tr
   return result;
 }
 
-#ifndef DISABLE_MYSQL_PRLOCK_H
-static inline int inline_mysql_prlock_trywrlock(
-  mysql_prlock_t *that
-#ifdef HAVE_PSI_INTERFACE
-  , const char *src_file, uint src_line
-#endif
-  )
-{
-  int result;
-#ifdef HAVE_PSI_INTERFACE
-  struct PSI_rwlock_locker *locker= NULL;
-  PSI_rwlock_locker_state state;
-  if (likely(PSI_server && that->m_psi))
-  {
-    locker= PSI_server->get_thread_rwlock_locker(&state, that->m_psi,
-                                                 PSI_RWLOCK_TRYWRITELOCK);
-    if (likely(locker != NULL))
-      PSI_server->start_rwlock_wrwait(locker, src_file, src_line);
-  }
-#endif
-  result= rw_pr_trywrlock(&that->m_prlock);
-#ifdef HAVE_PSI_INTERFACE
-  if (likely(locker != NULL))
-    PSI_server->end_rwlock_wrwait(locker, result);
-#endif
-  return result;
-}
-#endif
-
 static inline int inline_mysql_rwlock_unlock(
   mysql_rwlock_t *that)
 {

=== modified file 'mysql-test/include/handler.inc'
--- a/mysql-test/include/handler.inc	2010-08-12 13:50:23 +0000
+++ b/mysql-test/include/handler.inc	2010-09-24 07:18:16 +0000
@@ -1809,9 +1809,32 @@ CREATE TABLE t1(a INT);
 INSERT INTO t1 VALUES (1);
 HANDLER t1 OPEN;
 # This used to cause the assert
---error ER_NO_SUCH_TABLE
+--error ER_NOT_SUPPORTED_YET
 HANDLER t1 READ FIRST WHERE f1() = 1;
 HANDLER t1 CLOSE;
 
 DROP FUNCTION f1;
 DROP TABLE t1;
+
+
+--echo #
+--echo # Bug#54920 Stored functions are allowed in HANDLER statements,
+--echo #           but broken.
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS f1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+HANDLER t1 OPEN;
+
+--error ER_NOT_SUPPORTED_YET
+HANDLER t1 READ FIRST WHERE f1() = 1;
+
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;

=== modified file 'mysql-test/r/check.result'
--- a/mysql-test/r/check.result	2009-02-09 21:00:15 +0000
+++ b/mysql-test/r/check.result	2010-09-22 08:15:41 +0000
@@ -23,3 +23,19 @@ REPAIR TABLE t1;
 Table	Op	Msg_type	Msg_text
 test.t1	repair	status	OK
 DROP TABLE t1;
+#
+# Bug#56422 CHECK TABLE run when the table is locked reports corruption
+#           along with timeout
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(a INT);
+LOCK TABLE t1 WRITE;
+# Connection con1
+SET lock_wait_timeout= 1;
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	Error	Lock wait timeout exceeded; try restarting transaction
+test.t1	check	status	Operation failed
+# Connection default
+UNLOCK TABLES;
+DROP TABLE t1;

=== modified file 'mysql-test/r/delayed.result'
--- a/mysql-test/r/delayed.result	2010-08-24 16:20:00 +0000
+++ b/mysql-test/r/delayed.result	2010-09-16 14:06:46 +0000
@@ -422,3 +422,31 @@ UNLOCK TABLES;
 # Connection con1
 # Connection default
 DROP TABLE t1, t2, t3;
+#
+# Test for bug #56251 "Deadlock with INSERT DELAYED and MERGE tables".
+#
+drop table if exists t1, t2, tm;
+create table t1(a int);
+create table t2(a int);
+create table tm(a int) engine=merge union=(t1, t2);
+begin;
+select * from t1;
+a
+# Connection 'con1'.
+# Sending:
+alter table t1 comment 'test';
+# Connection 'default'.
+# Wait until ALTER TABLE blocks and starts waiting
+# for connection 'default'. It should wait with a
+# pending SNW lock on 't1'.
+# Attempt to perform delayed insert into 'tm' should not lead
+# to a deadlock. Instead error ER_DELAYED_NOT_SUPPORTED should
+# be emitted.
+insert delayed into tm values (1);
+ERROR HY000: DELAYED option not supported for table 'tm'
+# Unblock ALTER TABLE.
+commit;
+# Connection 'con1'.
+# Reaping ALTER TABLE:
+# Connection 'default'.
+drop tables tm, t1, t2;

=== modified file 'mysql-test/r/flush.result'
--- a/mysql-test/r/flush.result	2010-08-13 14:14:36 +0000
+++ b/mysql-test/r/flush.result	2010-09-09 14:29:14 +0000
@@ -373,3 +373,53 @@ commit;
 # --> connection con2
 # --> connection default
 drop table t1;
+#
+# Test for bug #55273 "FLUSH TABLE tm WITH READ LOCK for Merge table
+#                      causes assert failure".
+#
+drop table if exists t1, t2, tm;
+create table t1 (i int);
+create table t2 (i int);
+create table tm (i int) engine=merge union=(t1, t2);
+insert into t1 values (1), (2);
+insert into t2 values (3), (4);
+# The below statement should succeed and lock merge
+# table for read. Only merge table gets flushed and
+# not underlying tables.
+flush tables tm with read lock;
+select * from tm;
+i
+1
+2
+3
+4
+# Check that underlying tables are locked.
+select * from t1;
+i
+1
+2
+select * from t2;
+i
+3
+4
+unlock tables;
+# This statement should succeed as well and flush
+# all tables in the list.
+flush tables tm, t1, t2 with read lock;
+select * from tm;
+i
+1
+2
+3
+4
+# Naturally, underlying tables should be locked in this case too.
+select * from t1;
+i
+1
+2
+select * from t2;
+i
+3
+4
+unlock tables;
+drop tables tm, t1, t2;

=== modified file 'mysql-test/r/handler_innodb.result'
--- a/mysql-test/r/handler_innodb.result	2010-07-05 11:59:34 +0000
+++ b/mysql-test/r/handler_innodb.result	2010-09-24 07:18:16 +0000
@@ -1726,7 +1726,22 @@ CREATE TABLE t1(a INT);
 INSERT INTO t1 VALUES (1);
 HANDLER t1 OPEN;
 HANDLER t1 READ FIRST WHERE f1() = 1;
-ERROR 42S02: Table 'test.t2' doesn't exist
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Bug#54920 Stored functions are allowed in HANDLER statements,
+#           but broken.
+#
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS f1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f1() = 1;
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
 HANDLER t1 CLOSE;
 DROP FUNCTION f1;
 DROP TABLE t1;

=== modified file 'mysql-test/r/handler_myisam.result'
--- a/mysql-test/r/handler_myisam.result	2010-07-05 11:59:34 +0000
+++ b/mysql-test/r/handler_myisam.result	2010-09-24 07:18:16 +0000
@@ -1722,7 +1722,22 @@ CREATE TABLE t1(a INT);
 INSERT INTO t1 VALUES (1);
 HANDLER t1 OPEN;
 HANDLER t1 READ FIRST WHERE f1() = 1;
-ERROR 42S02: Table 'test.t2' doesn't exist
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Bug#54920 Stored functions are allowed in HANDLER statements,
+#           but broken.
+#
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS f1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f1() = 1;
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
 HANDLER t1 CLOSE;
 DROP FUNCTION f1;
 DROP TABLE t1;

=== modified file 'mysql-test/r/log_tables_upgrade.result'
--- a/mysql-test/r/log_tables_upgrade.result	2010-02-26 12:22:48 +0000
+++ b/mysql-test/r/log_tables_upgrade.result	2010-09-22 08:15:41 +0000
@@ -17,9 +17,7 @@ mysql.columns_priv                      
 mysql.db                                           OK
 mysql.event                                        OK
 mysql.func                                         OK
-mysql.general_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.general_log                                  OK
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -31,9 +29,7 @@ mysql.proc                              
 mysql.procs_priv                                   OK
 mysql.renamed_general_log                          OK
 mysql.servers                                      OK
-mysql.slow_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.slow_log                                     OK
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK

=== modified file 'mysql-test/r/lowercase_fs_off.result'
--- a/mysql-test/r/lowercase_fs_off.result	2009-11-06 14:20:27 +0000
+++ b/mysql-test/r/lowercase_fs_off.result	2010-09-16 09:11:13 +0000
@@ -55,3 +55,11 @@ DROP USER user_1@localhost;
 DROP USER USER_1@localhost;
 DROP DATABASE db1;
 use test;
+#
+# Extra test coverage for Bug#56595 RENAME TABLE causes assert on OS X
+#
+CREATE TABLE t1(a INT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET new.a= 1;
+RENAME TABLE t1 TO T1;
+ALTER TABLE T1 RENAME t1;
+DROP TABLE t1;

=== modified file 'mysql-test/r/mdl_sync.result'
--- a/mysql-test/r/mdl_sync.result	2010-08-12 13:50:23 +0000
+++ b/mysql-test/r/mdl_sync.result	2010-09-08 08:25:37 +0000
@@ -2913,3 +2913,41 @@ UNLOCK TABLES;
 # Connection default
 UNLOCK TABLES;
 DROP DATABASE db1;
+#
+# Bug#56292 Deadlock with ALTER TABLE and MERGE tables
+#
+DROP TABLE IF EXISTS t1, t2, m1;
+CREATE TABLE t1(a INT) engine=MyISAM;
+CREATE TABLE t2(a INT) engine=MyISAM;
+CREATE TABLE m1(a INT) engine=MERGE UNION=(t1, t2);
+INSERT INTO t1 VALUES (1), (2);
+INSERT INTO t2 VALUES (3), (4);
+# Connection con1
+SET DEBUG_SYNC= 'mdl_upgrade_shared_lock_to_exclusive SIGNAL upgrade WAIT_FOR continue';
+# Sending:
+ALTER TABLE m1 engine=MERGE UNION=(t2, t1);
+# Connection con2
+# Waiting for ALTER TABLE to try lock upgrade
+SET DEBUG_SYNC= 'now WAIT_FOR upgrade';
+# Sending:
+DELETE FROM t2 WHERE a = 3;
+# Connection default
+# Check that DELETE is waiting on a metadata lock and not a table lock.
+# Now that DELETE blocks on a metadata lock, we should be able to do
+# SELECT * FROM m1 here. SELECT used to be blocked by a DELETE table
+# lock request.
+SELECT * FROM m1;
+a
+1
+2
+3
+4
+# Resuming ALTER TABLE
+SET DEBUG_SYNC= 'now SIGNAL continue';
+# Connection con1
+# Reaping: ALTER TABLE m1 engine=MERGE UNION=(t2, t1)
+# Connection con2
+# Reaping: DELETE FROM t2 WHERE a = 3
+# Connection default
+DROP TABLE m1, t1, t2;
+SET DEBUG_SYNC= 'RESET';

=== modified file 'mysql-test/r/merge.result'
--- a/mysql-test/r/merge.result	2010-09-21 14:47:41 +0000
+++ b/mysql-test/r/merge.result	2010-09-30 10:43:43 +0000
@@ -2358,6 +2358,48 @@ t2 WHERE b SOUNDS LIKE e AND d = 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
 DROP TABLE t2, t1;
+#
+# Bug#46339 - crash on REPAIR TABLE merge table USE_FRM
+#
+DROP TABLE IF EXISTS m1, t1;
+CREATE TABLE t1 (c1 INT) ENGINE=MYISAM;
+CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1) INSERT_METHOD=LAST;
+LOCK TABLE m1 READ;
+REPAIR TABLE m1 USE_FRM;
+Table	Op	Msg_type	Msg_text
+test.m1	repair	Error	Table 'm1' was locked with a READ lock and can't be updated
+test.m1	repair	status	Operation failed
+UNLOCK TABLES;
+REPAIR TABLE m1 USE_FRM;
+Table	Op	Msg_type	Msg_text
+test.m1	repair	note	The storage engine for the table doesn't support repair
+DROP TABLE m1,t1;
+CREATE TABLE m1 (f1 BIGINT) ENGINE=MRG_MyISAM UNION(t1);
+REPAIR TABLE m1 USE_FRM;
+Table	Op	Msg_type	Msg_text
+test.m1	repair	Warning	Can't open table
+test.m1	repair	error	Corrupt
+CREATE TABLE t1 (f1 BIGINT) ENGINE = MyISAM;
+REPAIR TABLE m1 USE_FRM;
+Table	Op	Msg_type	Msg_text
+test.m1	repair	note	The storage engine for the table doesn't support repair
+REPAIR TABLE m1;
+Table	Op	Msg_type	Msg_text
+test.m1	repair	note	The storage engine for the table doesn't support repair
+DROP TABLE m1, t1;
+CREATE TEMPORARY TABLE m1 (f1 BIGINT) ENGINE=MRG_MyISAM UNION(t1);
+REPAIR TABLE m1 USE_FRM;
+Table	Op	Msg_type	Msg_text
+test.m1	repair	Error	Table 'test.m1' doesn't exist
+test.m1	repair	error	Corrupt
+CREATE TEMPORARY TABLE t1 (f1 BIGINT) ENGINE=MyISAM;
+REPAIR TABLE m1 USE_FRM;
+Table	Op	Msg_type	Msg_text
+m1	repair	error	Cannot repair temporary table from .frm file
+REPAIR TABLE m1;
+Table	Op	Msg_type	Msg_text
+test.m1	repair	note	The storage engine for the table doesn't support repair
+DROP TABLE m1, t1;
 End of 5.1 tests
 #
 # An additional test case for Bug#27430 Crash in subquery code
@@ -2677,7 +2719,7 @@ OPTIMIZE TABLE t1;
 Table	Op	Msg_type	Msg_text
 test.t1	optimize	Error	Table 'test.t_not_exists' doesn't exist
 test.t1	optimize	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
-test.t1	optimize	note	The storage engine for the table doesn't support optimize
+test.t1	optimize	error	Corrupt
 DROP TABLE t1;
 #
 # Bug#36171 - CREATE TEMPORARY TABLE and MERGE engine
@@ -3444,13 +3486,12 @@ ALTER TABLE m1 ADD INDEX (c1);
 UNLOCK TABLES;
 DROP TABLE m1, t1;
 #
-# If children are to be altered, they need an explicit lock.
+# Locking the merge table will implicitly lock children.
 #
 CREATE TABLE t1 (c1 INT);
 CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1);
 LOCK TABLE m1 WRITE;
 ALTER TABLE t1 ADD INDEX (c1);
-ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
 LOCK TABLE m1 WRITE, t1 WRITE;
 ALTER TABLE t1 ADD INDEX (c1);
 UNLOCK TABLES;
@@ -3576,4 +3617,48 @@ ERROR HY000: The definition of table 'v1
 drop view v1;
 drop temporary table tmp;
 drop table t1, t2, t3, m1, m2;
+#
+# Bug#56494 Segfault in upgrade_shared_lock_to_exclusive() for
+#           REPAIR of merge table
+#
+DROP TABLE IF EXISTS t1, t2, t_not_exists;
+CREATE TABLE t1(a INT);
+ALTER TABLE t1 engine= MERGE UNION (t_not_exists);
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	Error	Table 'test.t_not_exists' doesn't exist
+test.t1	analyze	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1	analyze	error	Corrupt
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	Error	Table 'test.t_not_exists' doesn't exist
+test.t1	check	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1	check	error	Corrupt
+CHECKSUM TABLE t1;
+Table	Checksum
+test.t1	NULL
+Warnings:
+Error	1146	Table 'test.t_not_exists' doesn't exist
+Error	1168	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+OPTIMIZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	optimize	Error	Table 'test.t_not_exists' doesn't exist
+test.t1	optimize	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1	optimize	error	Corrupt
+REPAIR TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	Error	Table 'test.t_not_exists' doesn't exist
+test.t1	repair	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1	repair	error	Corrupt
+REPAIR TABLE t1 USE_FRM;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	Warning	Can't open table
+test.t1	repair	error	Corrupt
+DROP TABLE t1;
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(a INT) engine= MERGE UNION (t1);
+REPAIR TABLE t2 USE_FRM;
+Table	Op	Msg_type	Msg_text
+test.t2	repair	note	The storage engine for the table doesn't support repair
+DROP TABLE t1, t2;
 End of 6.0 tests

=== modified file 'mysql-test/r/myisampack.result'
--- a/mysql-test/r/myisampack.result	2009-11-26 12:47:55 +0000
+++ b/mysql-test/r/myisampack.result	2010-09-22 08:15:41 +0000
@@ -46,14 +46,12 @@ insert into t1 select * from t1;
 flush tables;
 optimize table t1;
 Table	Op	Msg_type	Msg_text
-test.t1	optimize	error	Table 'test.t1' is read only
-Warnings:
-Error	1036	Table 't1' is read only
+test.t1	optimize	Error	Table 't1' is read only
+test.t1	optimize	status	Operation failed
 repair table t1;
 Table	Op	Msg_type	Msg_text
-test.t1	repair	error	Table 'test.t1' is read only
-Warnings:
-Error	1036	Table 't1' is read only
+test.t1	repair	Error	Table 't1' is read only
+test.t1	repair	status	Operation failed
 drop table t1;
 #
 # BUG#41541 - Valgrind warnings on packed MyISAM table

=== modified file 'mysql-test/r/mysql_upgrade.result'
--- a/mysql-test/r/mysql_upgrade.result	2010-07-05 10:22:13 +0000
+++ b/mysql-test/r/mysql_upgrade.result	2010-09-22 08:15:41 +0000
@@ -5,9 +5,7 @@ mysql.columns_priv                      
 mysql.db                                           OK
 mysql.event                                        OK
 mysql.func                                         OK
-mysql.general_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.general_log                                  OK
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -18,9 +16,7 @@ mysql.plugin                            
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
 mysql.servers                                      OK
-mysql.slow_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.slow_log                                     OK
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -37,9 +33,7 @@ mysql.columns_priv                      
 mysql.db                                           OK
 mysql.event                                        OK
 mysql.func                                         OK
-mysql.general_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.general_log                                  OK
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -50,9 +44,7 @@ mysql.plugin                            
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
 mysql.servers                                      OK
-mysql.slow_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.slow_log                                     OK
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -69,9 +61,7 @@ mysql.columns_priv                      
 mysql.db                                           OK
 mysql.event                                        OK
 mysql.func                                         OK
-mysql.general_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.general_log                                  OK
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -82,9 +72,7 @@ mysql.plugin                            
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
 mysql.servers                                      OK
-mysql.slow_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.slow_log                                     OK
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -103,9 +91,7 @@ mysql.columns_priv                      
 mysql.db                                           OK
 mysql.event                                        OK
 mysql.func                                         OK
-mysql.general_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.general_log                                  OK
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -116,9 +102,7 @@ mysql.plugin                            
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
 mysql.servers                                      OK
-mysql.slow_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.slow_log                                     OK
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -141,9 +125,7 @@ mysql.columns_priv                      
 mysql.db                                           OK
 mysql.event                                        OK
 mysql.func                                         OK
-mysql.general_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.general_log                                  OK
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -154,9 +136,7 @@ mysql.plugin                            
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
 mysql.servers                                      OK
-mysql.slow_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.slow_log                                     OK
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -182,9 +162,7 @@ mysql.columns_priv                      
 mysql.db                                           OK
 mysql.event                                        OK
 mysql.func                                         OK
-mysql.general_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.general_log                                  OK
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -195,9 +173,7 @@ mysql.plugin                            
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
 mysql.servers                                      OK
-mysql.slow_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.slow_log                                     OK
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK

=== modified file 'mysql-test/r/mysql_upgrade_ssl.result'
--- a/mysql-test/r/mysql_upgrade_ssl.result	2010-08-11 17:56:56 +0000
+++ b/mysql-test/r/mysql_upgrade_ssl.result	2010-09-22 08:15:41 +0000
@@ -7,9 +7,7 @@ mysql.columns_priv                      
 mysql.db                                           OK
 mysql.event                                        OK
 mysql.func                                         OK
-mysql.general_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.general_log                                  OK
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -20,9 +18,7 @@ mysql.plugin                            
 mysql.proc                                         OK
 mysql.procs_priv                                   OK
 mysql.servers                                      OK
-mysql.slow_log
-Error    : You can't use locks with log tables.
-status   : OK
+mysql.slow_log                                     OK
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK

=== modified file 'mysql-test/r/variables_debug.result'
--- a/mysql-test/r/variables_debug.result	2010-05-24 19:01:36 +0000
+++ b/mysql-test/r/variables_debug.result	2010-10-01 10:23:16 +0000
@@ -32,3 +32,47 @@ SELECT @@global.debug;
 
 SET GLOBAL debug=@old_debug;
 End of 5.1 tests
+#
+# Bug#46165 server crash in dbug
+#
+SET @old_globaldebug = @@global.debug;
+SET @old_sessiondebug= @@session.debug;
+# Test 1 - Bug test case, single connection
+SET GLOBAL  debug= '+O,../../log/bug46165.1.trace';
+SET SESSION debug= '-d:-t:-i';
+SET GLOBAL  debug= '';
+SET SESSION debug= '';
+# Test 2 - Bug test case, two connections
+# Connection default
+SET GLOBAL  debug= '+O,../../log/bug46165.2.trace';
+SET SESSION debug= '-d:-t:-i';
+# Connection con1
+SET GLOBAL  debug= '';
+# Connection default
+SET SESSION debug= '';
+# Connection con1
+# Connection default
+SET GLOBAL  debug= '';
+# Test 3 - Active session trace file on disconnect
+# Connection con1
+SET GLOBAL  debug= '+O,../../log/bug46165.3.trace';
+SET SESSION debug= '-d:-t:-i';
+SET GLOBAL  debug= '';
+# Test 4 - Active session trace file on two connections
+# Connection default
+SET GLOBAL  debug= '+O,../../log/bug46165.4.trace';
+SET SESSION debug= '-d:-t:-i';
+# Connection con1
+SET SESSION debug= '-d:-t:-i';
+SET GLOBAL  debug= '';
+SET SESSION debug= '';
+# Connection default
+SET SESSION debug= '';
+# Connection con1
+# Connection default
+# Test 5 - Different trace files
+SET SESSION debug= '+O,../../log/bug46165.5.trace';
+SET SESSION debug= '+O,../../log/bug46165.6.trace';
+SET SESSION debug= '-O';
+SET GLOBAL  debug= @old_globaldebug;
+SET SESSION debug= @old_sessiondebug;

=== modified file 'mysql-test/r/xa.result'
--- a/mysql-test/r/xa.result	2010-03-10 15:31:22 +0000
+++ b/mysql-test/r/xa.result	2010-09-13 11:31:22 +0000
@@ -131,3 +131,14 @@ XA START 'xid1';
 XA END 'xid1';
 XA ROLLBACK 'xid1';
 DROP TABLE t1;
+#
+# Bug#56448 Assertion failed: ! is_set() with second xa end
+#
+XA START 'x';
+XA END 'x';
+XA END 'x';
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  IDLE state
+XA PREPARE 'x';
+XA PREPARE 'x';
+ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  PREPARED state
+XA ROLLBACK 'x';

=== modified file 'mysql-test/suite/parts/r/partition_special_innodb.result'
--- a/mysql-test/suite/parts/r/partition_special_innodb.result	2010-08-13 07:50:25 +0000
+++ b/mysql-test/suite/parts/r/partition_special_innodb.result	2010-09-23 09:13:21 +0000
@@ -242,7 +242,7 @@ ERROR HY000: Lock wait timeout exceeded;
 CHECK TABLE t1;
 Table	Op	Msg_type	Msg_text
 test.t1	check	Error	Lock wait timeout exceeded; try restarting transaction
-test.t1	check	error	Corrupt
+test.t1	check	status	Operation failed
 UNLOCK TABLES;
 DROP TABLE t1;
 CREATE TABLE t2 ( i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, f INT )

=== modified file 'mysql-test/suite/perfschema/r/dml_setup_instruments.result'
--- a/mysql-test/suite/perfschema/r/dml_setup_instruments.result	2010-09-27 11:37:21 +0000
+++ b/mysql-test/suite/perfschema/r/dml_setup_instruments.result	2010-10-01 10:23:16 +0000
@@ -13,7 +13,7 @@ wait/synch/mutex/sql/LOCK_active_mi	YES	
 wait/synch/mutex/sql/LOCK_audit_mask	YES	YES
 wait/synch/mutex/sql/LOCK_connection_count	YES	YES
 wait/synch/mutex/sql/LOCK_crypt	YES	YES
-wait/synch/mutex/sql/LOCK_dd_owns_lock_open	YES	YES
+wait/synch/mutex/sql/LOCK_delayed_create	YES	YES
 select * from performance_schema.SETUP_INSTRUMENTS
 where name like 'Wait/Synch/Rwlock/sql/%'
   and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock')

=== modified file 'mysql-test/t/check.test'
--- a/mysql-test/t/check.test	2009-02-09 21:00:15 +0000
+++ b/mysql-test/t/check.test	2010-09-22 08:15:41 +0000
@@ -53,5 +53,29 @@ REPAIR TABLE t1;
 DROP TABLE t1;
 
 
+--echo #
+--echo # Bug#56422 CHECK TABLE run when the table is locked reports corruption
+--echo #           along with timeout
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1(a INT);
+LOCK TABLE t1 WRITE;
+
+--echo # Connection con1
+connect(con1, localhost, root);
+SET lock_wait_timeout= 1;
+CHECK TABLE t1;
+
+--echo # Connection default
+connection default;
+UNLOCK TABLES;
+DROP TABLE t1;
+disconnect con1;
+
+
 # Wait till we reached the initial number of concurrent sessions
 --source include/wait_until_count_sessions.inc

=== modified file 'mysql-test/t/delayed.test'
--- a/mysql-test/t/delayed.test	2010-08-24 16:20:00 +0000
+++ b/mysql-test/t/delayed.test	2010-09-16 14:06:46 +0000
@@ -552,3 +552,52 @@ disconnect con1;
 connection default;
 DROP TABLE t1, t2, t3;
 --enable_ps_protocol
+
+
+--echo #
+--echo # Test for bug #56251 "Deadlock with INSERT DELAYED and MERGE tables".
+--echo #
+connect (con1,localhost,root,,);
+connection default;
+--disable_warnings
+drop table if exists t1, t2, tm;
+--enable_warnings
+create table t1(a int);
+create table t2(a int);
+create table tm(a int) engine=merge union=(t1, t2);
+begin;
+select * from t1;
+
+--echo # Connection 'con1'.
+connection con1;
+--echo # Sending:
+--send alter table t1 comment 'test'
+
+--echo # Connection 'default'.
+connection default;
+--echo # Wait until ALTER TABLE blocks and starts waiting
+--echo # for connection 'default'. It should wait with a
+--echo # pending SNW lock on 't1'.
+let $wait_condition=
+  select count(*) = 1 from information_schema.processlist
+  where state = "Waiting for table metadata lock" and
+        info = "alter table t1 comment 'test'";
+--source include/wait_condition.inc
+--echo # Attempt to perform delayed insert into 'tm' should not lead
+--echo # to a deadlock. Instead error ER_DELAYED_NOT_SUPPORTED should
+--echo # be emitted.
+--error ER_DELAYED_NOT_SUPPORTED
+insert delayed into tm values (1);
+--echo # Unblock ALTER TABLE.
+commit;
+
+--echo # Connection 'con1'.
+connection con1;
+--echo # Reaping ALTER TABLE:
+--reap
+
+disconnect con1;
+--source include/wait_until_disconnected.inc
+--echo # Connection 'default'.
+connection default;
+drop tables tm, t1, t2;

=== modified file 'mysql-test/t/flush.test'
--- a/mysql-test/t/flush.test	2010-08-13 14:14:36 +0000
+++ b/mysql-test/t/flush.test	2010-09-09 14:29:14 +0000
@@ -546,3 +546,34 @@ disconnect con2;
 connection default;
 drop table t1;
 
+
+--echo #
+--echo # Test for bug #55273 "FLUSH TABLE tm WITH READ LOCK for Merge table
+--echo #                      causes assert failure".
+--echo #
+--disable_warnings
+drop table if exists t1, t2, tm;
+--enable_warnings
+create table t1 (i int);
+create table t2 (i int);
+create table tm (i int) engine=merge union=(t1, t2);
+insert into t1 values (1), (2);
+insert into t2 values (3), (4);
+--echo # The below statement should succeed and lock merge
+--echo # table for read. Only merge table gets flushed and
+--echo # not underlying tables.
+flush tables tm with read lock;
+select * from tm;
+--echo # Check that underlying tables are locked.
+select * from t1;
+select * from t2;
+unlock tables;
+--echo # This statement should succeed as well and flush
+--echo # all tables in the list.
+flush tables tm, t1, t2 with read lock;
+select * from tm;
+--echo # Naturally, underlying tables should be locked in this case too.
+select * from t1;
+select * from t2;
+unlock tables;
+drop tables tm, t1, t2;

=== modified file 'mysql-test/t/lowercase_fs_off.test'
--- a/mysql-test/t/lowercase_fs_off.test	2009-10-27 10:09:36 +0000
+++ b/mysql-test/t/lowercase_fs_off.test	2010-09-16 09:11:13 +0000
@@ -91,3 +91,14 @@ DROP DATABASE db1;
 use test;
 
 # End of 5.0 tests
+
+
+--echo #
+--echo # Extra test coverage for Bug#56595 RENAME TABLE causes assert on OS X
+--echo #
+
+CREATE TABLE t1(a INT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET new.a= 1;
+RENAME TABLE t1 TO T1;
+ALTER TABLE T1 RENAME t1;
+DROP TABLE t1;

=== modified file 'mysql-test/t/mdl_sync.test'
--- a/mysql-test/t/mdl_sync.test	2010-08-12 13:50:23 +0000
+++ b/mysql-test/t/mdl_sync.test	2010-09-08 08:25:37 +0000
@@ -4532,6 +4532,68 @@ disconnect con2;
 disconnect con3;
 
 
+--echo #
+--echo # Bug#56292 Deadlock with ALTER TABLE and MERGE tables
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2, m1;
+--enable_warnings
+
+CREATE TABLE t1(a INT) engine=MyISAM;
+CREATE TABLE t2(a INT) engine=MyISAM;
+CREATE TABLE m1(a INT) engine=MERGE UNION=(t1, t2);
+
+INSERT INTO t1 VALUES (1), (2);
+INSERT INTO t2 VALUES (3), (4);
+
+connect(con1, localhost, root);
+connect(con2, localhost, root);
+
+--echo # Connection con1
+connection con1;
+SET DEBUG_SYNC= 'mdl_upgrade_shared_lock_to_exclusive SIGNAL upgrade WAIT_FOR continue';
+--echo # Sending:
+--send ALTER TABLE m1 engine=MERGE UNION=(t2, t1)
+
+--echo # Connection con2
+connection con2;
+--echo # Waiting for ALTER TABLE to try lock upgrade
+SET DEBUG_SYNC= 'now WAIT_FOR upgrade';
+--echo # Sending:
+--send DELETE FROM t2 WHERE a = 3
+
+--echo # Connection default
+connection default;
+--echo # Check that DELETE is waiting on a metadata lock and not a table lock.
+let $wait_condition=
+  SELECT COUNT(*) = 1 FROM information_schema.processlist
+  WHERE state = "Waiting for table metadata lock" AND
+        info = "DELETE FROM t2 WHERE a = 3";
+--source include/wait_condition.inc
+--echo # Now that DELETE blocks on a metadata lock, we should be able to do
+--echo # SELECT * FROM m1 here. SELECT used to be blocked by a DELETE table
+--echo # lock request.
+SELECT * FROM m1;
+--echo # Resuming ALTER TABLE
+SET DEBUG_SYNC= 'now SIGNAL continue';
+
+--echo # Connection con1
+connection con1;
+--echo # Reaping: ALTER TABLE m1 engine=MERGE UNION=(t2, t1)
+--reap
+--echo # Connection con2
+connection con2;
+--echo # Reaping: DELETE FROM t2 WHERE a = 3
+--reap
+--echo # Connection default
+connection default;
+DROP TABLE m1, t1, t2;
+SET DEBUG_SYNC= 'RESET';
+disconnect con1;
+disconnect con2;
+
+
 # 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/merge.test'
--- a/mysql-test/t/merge.test	2010-09-21 14:47:41 +0000
+++ b/mysql-test/t/merge.test	2010-09-30 10:43:43 +0000
@@ -2,6 +2,9 @@
 # Test of MERGE TABLES
 #
 
+# Save the initial number of concurrent sessions.
+--source include/count_sessions.inc
+
 # MERGE tables require MyISAM tables
 let $default=`select @@global.storage_engine`;
 set global storage_engine=myisam;
@@ -1731,6 +1734,84 @@ t2 WHERE b SOUNDS LIKE e AND d = 1;
 
 DROP TABLE t2, t1;
 
+--echo #
+--echo # Bug#46339 - crash on REPAIR TABLE merge table USE_FRM
+--echo #
+--disable_warnings
+DROP TABLE IF EXISTS m1, t1;
+--enable_warnings
+#
+# Test derived from a proposal of Shane Bester.
+#
+CREATE TABLE t1 (c1 INT) ENGINE=MYISAM;
+CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1) INSERT_METHOD=LAST;
+#
+# REPAIR ... USE_FRM with LOCK TABLES.
+#
+LOCK TABLE m1 READ;
+REPAIR TABLE m1 USE_FRM;
+UNLOCK TABLES;
+#
+# REPAIR ... USE_FRM without LOCK TABLES.
+#
+# This statement crashed the server (Bug#46339).
+#
+REPAIR TABLE m1 USE_FRM;
+#
+DROP TABLE m1,t1;
+#
+# Test derived from a proposal of Matthias Leich.
+#
+# Base table is missing.
+#
+CREATE TABLE m1 (f1 BIGINT) ENGINE=MRG_MyISAM UNION(t1);
+#
+# This statement crashed the server (Bug#46339).
+#
+REPAIR TABLE m1 USE_FRM;
+#
+# Create base table.
+#
+CREATE TABLE t1 (f1 BIGINT) ENGINE = MyISAM;
+#
+# This statement crashed the server (Bug#46339).
+#
+REPAIR TABLE m1 USE_FRM;
+#
+# Normal repair as reference.
+#
+REPAIR TABLE m1;
+#
+# Cleanup.
+#
+DROP TABLE m1, t1;
+#
+# Same with temporary tables.
+#
+# Base table is missing.
+#
+CREATE TEMPORARY TABLE m1 (f1 BIGINT) ENGINE=MRG_MyISAM UNION(t1);
+#
+# This statement crashed the server (Bug#46339).
+#
+REPAIR TABLE m1 USE_FRM;
+#
+# Create base table.
+#
+CREATE TEMPORARY TABLE t1 (f1 BIGINT) ENGINE=MyISAM;
+#
+# This statement crashed the server (Bug#46339).
+#
+REPAIR TABLE m1 USE_FRM;
+#
+# Normal repair as reference.
+#
+REPAIR TABLE m1;
+#
+# Cleanup.
+#
+DROP TABLE m1, t1;
+
 --echo End of 5.1 tests
 
 --echo #
@@ -2519,12 +2600,11 @@ UNLOCK TABLES;
 DROP TABLE m1, t1;
 
 --echo #
---echo # If children are to be altered, they need an explicit lock.
+--echo # Locking the merge table will implicitly lock children.
 --echo #
 CREATE TABLE t1 (c1 INT);
 CREATE TABLE m1 (c1 INT) ENGINE=MRG_MyISAM UNION=(t1);
 LOCK TABLE m1 WRITE;
---error ER_TABLE_NOT_LOCKED_FOR_WRITE
 ALTER TABLE t1 ADD INDEX (c1);
 LOCK TABLE m1 WRITE, t1 WRITE;
 ALTER TABLE t1 ADD INDEX (c1);
@@ -2665,6 +2745,37 @@ drop view v1;
 drop temporary table tmp;
 drop table t1, t2, t3, m1, m2;
 
+
+--echo #
+--echo # Bug#56494 Segfault in upgrade_shared_lock_to_exclusive() for
+--echo #           REPAIR of merge table
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2, t_not_exists;
+--enable_warnings
+
+CREATE TABLE t1(a INT);
+ALTER TABLE t1 engine= MERGE UNION (t_not_exists);
+# This caused the segfault
+ANALYZE TABLE t1;
+CHECK TABLE t1;
+CHECKSUM TABLE t1;
+OPTIMIZE TABLE t1;
+REPAIR TABLE t1;
+
+# This caused an assert
+REPAIR TABLE t1 USE_FRM;
+
+DROP TABLE t1;
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(a INT) engine= MERGE UNION (t1);
+# This caused an assert
+REPAIR TABLE t2 USE_FRM;
+
+DROP TABLE t1, t2;
+
+
 --echo End of 6.0 tests
 
 --disable_result_log
@@ -2672,3 +2783,7 @@ drop table t1, t2, t3, m1, m2;
 eval set global storage_engine=$default;
 --enable_result_log
 --enable_query_log
+
+# 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/variables_debug.test'
--- a/mysql-test/t/variables_debug.test	2010-05-24 19:01:36 +0000
+++ b/mysql-test/t/variables_debug.test	2010-10-01 10:23:16 +0000
@@ -36,3 +36,78 @@ SELECT @@global.debug;
 SET GLOBAL debug=@old_debug;
 
 --echo End of 5.1 tests
+
+
+--echo #
+--echo # Bug#46165 server crash in dbug
+--echo #
+
+SET @old_globaldebug = @@global.debug;
+SET @old_sessiondebug= @@session.debug;
+
+--echo # Test 1 - Bug test case, single connection
+SET GLOBAL  debug= '+O,../../log/bug46165.1.trace';
+SET SESSION debug= '-d:-t:-i';
+
+SET GLOBAL  debug= '';
+SET SESSION debug= '';
+
+--echo # Test 2 - Bug test case, two connections
+--echo # Connection default
+connection default;
+SET GLOBAL  debug= '+O,../../log/bug46165.2.trace';
+SET SESSION debug= '-d:-t:-i';
+
+--echo # Connection con1
+connect (con1, localhost, root);
+SET GLOBAL  debug= '';
+
+--echo # Connection default
+connection default;
+SET SESSION debug= '';
+--echo # Connection con1
+connection con1;
+disconnect con1;
+--source include/wait_until_disconnected.inc
+--echo # Connection default
+connection default;
+SET GLOBAL  debug= '';
+
+--echo # Test 3 - Active session trace file on disconnect
+--echo # Connection con1
+connect (con1, localhost, root);
+SET GLOBAL  debug= '+O,../../log/bug46165.3.trace';
+SET SESSION debug= '-d:-t:-i';
+SET GLOBAL  debug= '';
+disconnect con1;
+--source include/wait_until_disconnected.inc
+
+--echo # Test 4 - Active session trace file on two connections
+--echo # Connection default
+connection default;
+SET GLOBAL  debug= '+O,../../log/bug46165.4.trace';
+SET SESSION debug= '-d:-t:-i';
+
+--echo # Connection con1
+connect (con1, localhost, root);
+SET SESSION debug= '-d:-t:-i';
+SET GLOBAL  debug= '';
+SET SESSION debug= '';
+
+--echo # Connection default
+connection default;
+SET SESSION debug= '';
+--echo # Connection con1
+connection con1;
+disconnect con1;
+--source include/wait_until_disconnected.inc
+--echo # Connection default
+connection default;
+
+--echo # Test 5 - Different trace files
+SET SESSION debug= '+O,../../log/bug46165.5.trace';
+SET SESSION debug= '+O,../../log/bug46165.6.trace';
+SET SESSION debug= '-O';
+
+SET GLOBAL  debug= @old_globaldebug;
+SET SESSION debug= @old_sessiondebug;

=== modified file 'mysql-test/t/xa.test'
--- a/mysql-test/t/xa.test	2010-03-24 15:03:44 +0000
+++ b/mysql-test/t/xa.test	2010-09-13 11:31:22 +0000
@@ -228,6 +228,23 @@ XA ROLLBACK 'xid1';
 disconnect con1;
 DROP TABLE t1;
 
+
+--echo #
+--echo # Bug#56448 Assertion failed: ! is_set() with second xa end
+--echo #
+
+XA START 'x';
+XA END 'x';
+# Second XA END caused an assertion.
+--error ER_XAER_RMFAIL
+XA END 'x';
+XA PREPARE 'x';
+# Second XA PREPARE also caused an assertion.
+--error ER_XAER_RMFAIL
+XA PREPARE 'x';
+XA ROLLBACK 'x';
+
+
 # Wait till all disconnects are completed
 --source include/wait_until_count_sessions.inc
 

=== modified file 'mysys/thr_rwlock.c'
--- a/mysys/thr_rwlock.c	2010-08-12 13:50:23 +0000
+++ b/mysys/thr_rwlock.c	2010-09-29 12:09:07 +0000
@@ -59,7 +59,7 @@
 *  Mountain View, California  94043
 */
 
-int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr)
+int my_rw_init(my_rw_lock_t *rwp)
 {
   pthread_condattr_t	cond_attr;
 
@@ -74,8 +74,6 @@ int my_rw_init(my_rw_lock_t *rwp, my_boo
 #ifdef SAFE_MUTEX
   rwp->write_thread   = 0;
 #endif
-  /* If attribute argument is NULL use default value - prefer writers. */
-  rwp->prefer_readers= prefer_readers_attr ? *prefer_readers_attr : FALSE;
 
   return(0);
 }
@@ -96,8 +94,7 @@ int my_rw_rdlock(my_rw_lock_t *rwp)
   pthread_mutex_lock(&rwp->lock);
 
   /* active or queued writers */
-  while (( rwp->state < 0 ) ||
-         (rwp->waiters && ! rwp->prefer_readers))
+  while (( rwp->state < 0 ) || rwp->waiters)
     pthread_cond_wait( &rwp->readers, &rwp->lock);
 
   rwp->state++;
@@ -109,8 +106,7 @@ int my_rw_tryrdlock(my_rw_lock_t *rwp)
 {
   int res;
   pthread_mutex_lock(&rwp->lock);
-  if ((rwp->state < 0 ) ||
-      (rwp->waiters && ! rwp->prefer_readers))
+  if ((rwp->state < 0 ) || rwp->waiters)
     res= EBUSY;					/* Can't get lock */
   else
   {
@@ -192,30 +188,127 @@ int my_rw_unlock(my_rw_lock_t *rwp)
   return(0);
 }
 
+#endif /* defined(NEED_MY_RW_LOCK) */
+
 
-int rw_pr_init(struct st_my_rw_lock_t *rwlock)
+int rw_pr_init(rw_pr_lock_t *rwlock)
 {
-  my_bool prefer_readers_attr= TRUE;
-  return my_rw_init(rwlock, &prefer_readers_attr);
+  pthread_mutex_init(&rwlock->lock, NULL);
+  pthread_cond_init(&rwlock->no_active_readers, NULL);
+  rwlock->active_readers= 0;
+  rwlock->writers_waiting_readers= 0;
+  rwlock->active_writer= FALSE;
+#ifdef SAFE_MUTEX
+  rwlock->writer_thread= 0;
+#endif
+  return 0;
 }
 
-#else
 
-/*
-  We are on system which has native read/write locks which support
-  preferring of readers.
-*/
+int rw_pr_destroy(rw_pr_lock_t *rwlock)
+{
+  pthread_cond_destroy(&rwlock->no_active_readers);
+  pthread_mutex_destroy(&rwlock->lock);
+  return 0;
+}
 
-int rw_pr_init(rw_pr_lock_t *rwlock)
+
+int rw_pr_rdlock(rw_pr_lock_t *rwlock)
 {
-  pthread_rwlockattr_t rwlock_attr;
+  pthread_mutex_lock(&rwlock->lock);
+  /*
+    The fact that we were able to acquire 'lock' mutex means
+    that there are no active writers and we can acquire rd-lock.
+    Increment active readers counter to prevent requests for
+    wr-lock from succeeding and unlock mutex.
+  */
+  rwlock->active_readers++;
+  pthread_mutex_unlock(&rwlock->lock);
+  return 0;
+}
+
+
+int rw_pr_wrlock(rw_pr_lock_t *rwlock)
+{
+  pthread_mutex_lock(&rwlock->lock);
+
+  if (rwlock->active_readers != 0)
+  {
+    /* There are active readers. We have to wait until they are gone. */
+    rwlock->writers_waiting_readers++;
 
-  pthread_rwlockattr_init(&rwlock_attr);
-  pthread_rwlockattr_setkind_np(&rwlock_attr, PTHREAD_RWLOCK_PREFER_READER_NP);
-  pthread_rwlock_init(rwlock, NULL);
-  pthread_rwlockattr_destroy(&rwlock_attr);
+    while (rwlock->active_readers != 0)
+      pthread_cond_wait(&rwlock->no_active_readers, &rwlock->lock);
+
+    rwlock->writers_waiting_readers--;
+  }
+
+  /*
+    We own 'lock' mutex so there is no active writers.
+    Also there are no active readers.
+    This means that we can grant wr-lock.
+    Not releasing 'lock' mutex until unlock will block
+    both requests for rd and wr-locks.
+    Set 'active_writer' flag to simplify unlock.
+
+    Thanks to the fact wr-lock/unlock in the absence of
+    contention from readers is essentially mutex lock/unlock
+    with a few simple checks make this rwlock implementation
+    wr-lock optimized.
+  */
+  rwlock->active_writer= TRUE;
+#ifdef SAFE_MUTEX
+  rwlock->writer_thread= pthread_self();
+#endif
   return 0;
 }
 
-#endif /* defined(NEED_MY_RW_LOCK) */
+
+int rw_pr_unlock(rw_pr_lock_t *rwlock)
+{
+  if (rwlock->active_writer)
+  {
+    /* We are unlocking wr-lock. */
+#ifdef SAFE_MUTEX
+    rwlock->writer_thread= 0;
+#endif
+    rwlock->active_writer= FALSE;
+    if (rwlock->writers_waiting_readers)
+    {
+      /*
+        Avoid expensive cond signal in case when there is no contention
+        or it is wr-only.
+
+        Note that from view point of performance it would be better to
+        signal on the condition variable after unlocking mutex (as it
+        reduces number of contex switches).
+
+        Unfortunately this would mean that such rwlock can't be safely
+        used by MDL subsystem, which relies on the fact that it is OK
+        to destroy rwlock once it is in unlocked state.
+      */
+      pthread_cond_signal(&rwlock->no_active_readers);
+    }
+    pthread_mutex_unlock(&rwlock->lock);
+  }
+  else
+  {
+    /* We are unlocking rd-lock. */
+    pthread_mutex_lock(&rwlock->lock);
+    rwlock->active_readers--;
+    if (rwlock->active_readers == 0 &&
+        rwlock->writers_waiting_readers)
+    {
+      /*
+        If we are last reader and there are waiting
+        writers wake them up.
+      */
+      pthread_cond_signal(&rwlock->no_active_readers);
+    }
+    pthread_mutex_unlock(&rwlock->lock);
+  }
+  return 0;
+}
+
+
 #endif /* defined(THREAD) */

=== modified file 'sql/events.cc'
--- a/sql/events.cc	2010-08-20 08:48:59 +0000
+++ b/sql/events.cc	2010-10-01 10:23:16 +0000
@@ -485,10 +485,7 @@ Events::update_event(THD *thd, Event_par
       ret= TRUE;                                // OOM
     else if ((ret= db_repository->load_named_event(thd, dbname, name,
                                                    new_element)))
-    {
-      DBUG_ASSERT(ret == OP_LOAD_ERROR);
       delete new_element;
-    }
     else
     {
       /*

=== modified file 'sql/events.h'
--- a/sql/events.h	2010-08-05 12:34:19 +0000
+++ b/sql/events.h	2010-08-26 10:01:43 +0000
@@ -44,19 +44,6 @@ class THD;
 typedef class Item COND;
 typedef struct charset_info_st CHARSET_INFO;
 
-/* Return codes */
-enum enum_events_error_code
-{
-  OP_OK= 0,
-  OP_NOT_RUNNING,
-  OP_CANT_KILL,
-  OP_CANT_INIT,
-  OP_DISABLED_EVENT,
-  OP_LOAD_ERROR,
-  OP_ALREADY_EXISTS
-};
-
-
 int
 sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
 

=== modified file 'sql/mdl.cc'
--- a/sql/mdl.cc	2010-09-13 10:26:57 +0000
+++ b/sql/mdl.cc	2010-10-01 10:23:16 +0000
@@ -124,6 +124,7 @@ public:
   Deadlock_detection_visitor(MDL_context *start_node_arg)
     : m_start_node(start_node_arg),
       m_victim(NULL),
+      m_current_search_depth(0),
       m_found_deadlock(FALSE)
   {}
   virtual bool enter_node(MDL_context *node);
@@ -132,8 +133,6 @@ public:
   virtual bool inspect_edge(MDL_context *dest);
 
   MDL_context *get_victim() const { return m_victim; }
-
-  void abort_traversal(MDL_context *node);
 private:
   /**
     Change the deadlock victim to a new one if it has lower deadlock
@@ -148,6 +147,13 @@ private:
   MDL_context *m_start_node;
   /** If a deadlock is found, the context that identifies the victim. */
   MDL_context *m_victim;
+  /** Set to the 0 at start. Increased whenever
+    we descend into another MDL context (aka traverse to the next
+    wait-for graph node). When MAX_SEARCH_DEPTH is reached, we
+    assume that a deadlock is found, even if we have not found a
+    loop.
+  */
+  uint m_current_search_depth;
   /** TRUE if we found a deadlock. */
   bool m_found_deadlock;
   /**
@@ -181,7 +187,7 @@ private:
 
 bool Deadlock_detection_visitor::enter_node(MDL_context *node)
 {
-  m_found_deadlock= m_current_search_depth >= MAX_SEARCH_DEPTH;
+  m_found_deadlock= ++m_current_search_depth >= MAX_SEARCH_DEPTH;
   if (m_found_deadlock)
   {
     DBUG_ASSERT(! m_victim);
@@ -201,6 +207,7 @@ bool Deadlock_detection_visitor::enter_n
 
 void Deadlock_detection_visitor::leave_node(MDL_context *node)
 {
+  --m_current_search_depth;
   if (m_found_deadlock)
     opt_change_victim_to(node);
 }
@@ -245,21 +252,6 @@ Deadlock_detection_visitor::opt_change_v
 
 
 /**
-  Abort traversal of a wait-for graph and report a deadlock.
-
-  @param node Node which we were about to visit when abort
-              was initiated.
-*/
-
-void Deadlock_detection_visitor::abort_traversal(MDL_context *node)
-{
-  DBUG_ASSERT(! m_victim);
-  m_found_deadlock= TRUE;
-  opt_change_victim_to(node);
-}
-
-
-/**
   Get a bit corresponding to enum_mdl_type value in a granted/waiting bitmaps
   and compatibility matrices.
 */
@@ -2064,13 +2056,8 @@ bool MDL_lock::visit_subgraph(MDL_ticket
     are visiting it but this is OK: in the worst case we might do some
     extra work and one more context might be chosen as a victim.
   */
-  ++gvisitor->m_current_search_depth;
-
   if (gvisitor->enter_node(src_ctx))
-  {
-    --gvisitor->m_current_search_depth;
     goto end;
-  }
 
   /*
     We do a breadth-first search first -- that is, inspect all
@@ -2127,7 +2114,6 @@ bool MDL_lock::visit_subgraph(MDL_ticket
 
 end_leave_node:
   gvisitor->leave_node(src_ctx);
-  --gvisitor->m_current_search_depth;
 
 end:
   mysql_prlock_unlock(&m_rwlock);

=== modified file 'sql/mdl.h'
--- a/sql/mdl.h	2010-09-13 10:26:57 +0000
+++ b/sql/mdl.h	2010-10-01 10:23:16 +0000
@@ -385,10 +385,7 @@ public:
 
   virtual bool inspect_edge(MDL_context *dest) = 0;
   virtual ~MDL_wait_for_graph_visitor();
-  MDL_wait_for_graph_visitor() :m_lock_open_count(0),
-                                m_current_search_depth(0)
-  { }
-  virtual void abort_traversal(MDL_context *node) = 0;
+  MDL_wait_for_graph_visitor() :m_lock_open_count(0) {}
 public:
   /**
    XXX, hack: During deadlock search, we may need to
@@ -399,17 +396,6 @@ public:
    LOCK_open since it has significant performance impacts.
   */
   uint m_lock_open_count;
-  /**
-    Set to the 0 at start. Increased whenever
-    we descend into another MDL context (aka traverse to the next
-    wait-for graph node). When MAX_SEARCH_DEPTH is reached, we
-    assume that a deadlock is found, even if we have not found a
-    loop.
-
-    XXX: This member belongs to this class only temporarily until
-         bug #56405 is fixed.
-  */
-  uint m_current_search_depth;
 };
 
 /**

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2010-07-29 13:37:49 +0000
+++ b/sql/sql_acl.cc	2010-10-01 10:23:16 +0000
@@ -4054,7 +4054,8 @@ end:
 bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
                  bool any_combination_will_do, uint number, bool no_errors)
 {
-  TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table();
+  TABLE_LIST *tl;
+  TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
   Security_context *sctx= thd->security_ctx;
   uint i;
   ulong orig_want_access= want_access;
@@ -4071,34 +4072,32 @@ bool check_grant(THD *thd, ulong want_ac
     the given table list refers to the list for prelocking (contains tables
     of other queries). For simple queries first_not_own_table is 0.
   */
-  for (i= 0, table= tables;
-       i < number  && table != first_not_own_table;
-       table= table->next_global, i++)
+  for (i= 0, tl= tables;
+       i < number  && tl != first_not_own_table;
+       tl= tl->next_global, i++)
   {
     /*
       Save a copy of the privileges without the SHOW_VIEW_ACL attribute.
       It will be checked during making view.
     */
-    table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
+    tl->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
   }
 
   mysql_rwlock_rdlock(&LOCK_grant);
-  for (table= tables;
-       table && number-- && table != first_not_own_table;
-       table= table->next_global)
-  {
-    GRANT_TABLE *grant_table;
-    sctx = test(table->security_ctx) ?
-      table->security_ctx : thd->security_ctx;
-
-    const ACL_internal_table_access *access;
-    access= get_cached_table_access(&table->grant.m_internal,
-                                    table->get_db_name(),
-                                    table->get_table_name());
+  for (tl= tables;
+       tl && number-- && tl != first_not_own_table;
+       tl= tl->next_global)
+  {
+    sctx = test(tl->security_ctx) ? tl->security_ctx : thd->security_ctx;
+
+    const ACL_internal_table_access *access=
+      get_cached_table_access(&tl->grant.m_internal,
+                              tl->get_db_name(),
+                              tl->get_table_name());
 
     if (access)
     {
-      switch(access->check(orig_want_access, &table->grant.privilege))
+      switch(access->check(orig_want_access, &tl->grant.privilege))
       {
       case ACL_INTERNAL_ACCESS_GRANTED:
         /*
@@ -4122,29 +4121,33 @@ bool check_grant(THD *thd, ulong want_ac
     if (!want_access)
       continue;                                 // ok
 
-    if (!(~table->grant.privilege & want_access) ||
-        table->is_anonymous_derived_table() || table->schema_table)
+    if (!(~tl->grant.privilege & want_access) ||
+        tl->is_anonymous_derived_table() || tl->schema_table)
     {
       /*
-        It is subquery in the FROM clause. VIEW set table->derived after
+        It is subquery in the FROM clause. VIEW set tl->derived after
         table opening, but this function always called before table opening.
       */
-      if (!table->referencing_view)
+      if (!tl->referencing_view)
       {
         /*
           If it's a temporary table created for a subquery in the FROM
           clause, or an INFORMATION_SCHEMA table, drop the request for
           a privilege.
         */
-        table->grant.want_privilege= 0;
+        tl->grant.want_privilege= 0;
       }
       continue;
     }
-    if (!(grant_table= table_hash_search(sctx->host, sctx->ip,
-                                         table->get_db_name(), sctx->priv_user,
-                                         table->get_table_name(), FALSE)))
+    GRANT_TABLE *grant_table= table_hash_search(sctx->host, sctx->ip,
+                                                tl->get_db_name(),
+                                                sctx->priv_user,
+                                                tl->get_table_name(),
+                                                FALSE);
+
+    if (!grant_table)
     {
-      want_access &= ~table->grant.privilege;
+      want_access &= ~tl->grant.privilege;
       goto err;					// No grants
     }
 
@@ -4155,18 +4158,17 @@ bool check_grant(THD *thd, ulong want_ac
     if (any_combination_will_do)
       continue;
 
-    table->grant.grant_table=grant_table;	// Remember for column test
-    table->grant.version=grant_version;
-    table->grant.privilege|= grant_table->privs;
-    table->grant.want_privilege= ((want_access & COL_ACLS)
-				  & ~table->grant.privilege);
+    tl->grant.grant_table= grant_table; // Remember for column test
+    tl->grant.version= grant_version;
+    tl->grant.privilege|= grant_table->privs;
+    tl->grant.want_privilege= ((want_access & COL_ACLS) & ~tl->grant.privilege);
 
-    if (!(~table->grant.privilege & want_access))
+    if (!(~tl->grant.privilege & want_access))
       continue;
 
-    if (want_access & ~(grant_table->cols | table->grant.privilege))
+    if (want_access & ~(grant_table->cols | tl->grant.privilege))
     {
-      want_access &= ~(grant_table->cols | table->grant.privilege);
+      want_access &= ~(grant_table->cols | tl->grant.privilege);
       goto err;					// impossible
     }
   }
@@ -4183,7 +4185,7 @@ err:
              command,
              sctx->priv_user,
              sctx->host_or_ip,
-             table ? table->get_table_name() : "unknown");
+             tl ? tl->get_table_name() : "unknown");
   }
   DBUG_RETURN(TRUE);
 }

=== modified file 'sql/sql_admin.cc'
--- a/sql/sql_admin.cc	2010-08-18 11:29:04 +0000
+++ b/sql/sql_admin.cc	2010-09-22 08:15:41 +0000
@@ -111,9 +111,6 @@ static int prepare_for_repair(THD *thd, 
     table= &tmp_table;
   }
 
-  /* A MERGE table must not come here. */
-  DBUG_ASSERT(table->file->ht->db_type != DB_TYPE_MRG_MYISAM);
-
   /*
     REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
   */
@@ -151,6 +148,9 @@ static int prepare_for_repair(THD *thd, 
   if (!ext[0] || !ext[1])
     goto end;					// No data file
 
+  /* A MERGE table must not come here. */
+  DBUG_ASSERT(table->file->ht->db_type != DB_TYPE_MRG_MYISAM);
+
   // Name of data file
   strxmov(from, table->s->normalized_path.str, ext[1], NullS);
   if (!mysql_file_stat(key_file_misc, from, &stat_info, MYF(0)))
@@ -231,6 +231,26 @@ end:
 }
 
 
+/**
+  Check if a given error is something that could occur during
+  open_and_lock_tables() that does not indicate table corruption.
+
+  @param  sql_errno  Error number to check.
+
+  @retval TRUE       Error does not indicate table corruption.
+  @retval FALSE      Error could indicate table corruption.
+*/
+
+static inline bool table_not_corrupt_error(uint sql_errno)
+{
+  return (sql_errno == ER_NO_SUCH_TABLE ||
+          sql_errno == ER_FILE_NOT_FOUND ||
+          sql_errno == ER_LOCK_WAIT_TIMEOUT ||
+          sql_errno == ER_LOCK_DEADLOCK ||
+          sql_errno == ER_CANT_LOCK_LOG_TABLE ||
+          sql_errno == ER_OPEN_AS_READONLY);
+}
+
 
 /*
   RETURN VALUES
@@ -311,7 +331,13 @@ static bool mysql_admin_table(THD* thd, 
       lex->query_tables= table;
       lex->query_tables_last= &table->next_global;
       lex->query_tables_own_last= 0;
-      thd->no_warnings_for_error= no_warnings_for_error;
+      /*
+        Under locked tables, we know that the table can be opened,
+        so any errors opening the table are logical errors.
+        In these cases it makes sense to report them.
+      */
+      if (!thd->locked_tables_mode)
+        thd->no_warnings_for_error= no_warnings_for_error;
       if (view_operator_func == NULL)
         table->required_type=FRMTYPE_TABLE;
 
@@ -320,6 +346,14 @@ static bool mysql_admin_table(THD* thd, 
       table->next_global= save_next_global;
       table->next_local= save_next_local;
       thd->open_options&= ~extra_open_options;
+
+      /*
+        If open_and_lock_tables() failed, close_thread_tables() will close
+        the table and table->table can therefore be invalid.
+      */
+      if (open_error)
+        table->table= NULL;
+
       /*
         Under locked tables, we know that the table can be opened,
         so any errors opening the table are logical errors.
@@ -418,9 +452,7 @@ static bool mysql_admin_table(THD* thd, 
         push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                      ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
       if (thd->stmt_da->is_error() &&
-          (thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE ||
-           thd->stmt_da->sql_errno() == ER_FILE_NOT_FOUND))
-        /* A missing table is just issued as a failed command */
+          table_not_corrupt_error(thd->stmt_da->sql_errno()))
         result_code= HA_ADMIN_FAILED;
       else
         /* Default failure code is corrupt table */

=== modified file 'sql/sql_alter.cc'
--- a/sql/sql_alter.cc	2010-08-16 15:07:53 +0000
+++ b/sql/sql_alter.cc	2010-10-01 10:23:16 +0000
@@ -13,8 +13,7 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
-#include "sql_parse.h"                       // check_access,
-                                             // check_merge_table_access
+#include "sql_parse.h"                       // check_access
 #include "sql_table.h"                       // mysql_alter_table,
                                              // mysql_exchange_partition
 #include "sql_alter.h"
@@ -61,11 +60,15 @@ bool Alter_table_statement::execute(THD 
       check_access(thd, INSERT_ACL | CREATE_ACL, select_lex->db,
                    &priv,
                    NULL, /* Don't use first_tab->grant with sel_lex->db */
-                   0, 0) ||
-      check_merge_table_access(thd, first_table->db,
-                               create_info.merge_list.first))
+                   0, 0))
     DBUG_RETURN(TRUE);                  /* purecov: inspected */
 
+  /* If it is a merge table, check privileges for merge children. */
+  if (create_info.merge_list.first &&
+      check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
+                         create_info.merge_list.first, FALSE, UINT_MAX, FALSE))
+    DBUG_RETURN(TRUE);
+
   if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
     DBUG_RETURN(TRUE);                  /* purecov: inspected */
 

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2010-09-27 11:37:21 +0000
+++ b/sql/sql_base.cc	2010-10-01 10:23:16 +0000
@@ -100,14 +100,11 @@ bool No_such_table_error_handler::safely
   TABLE_SHAREs, refresh_version and the table id counter.
 */
 mysql_mutex_t LOCK_open;
-mysql_mutex_t LOCK_dd_owns_lock_open;
-uint dd_owns_lock_open= 0;
 
 #ifdef HAVE_PSI_INTERFACE
-static PSI_mutex_key key_LOCK_open, key_LOCK_dd_owns_lock_open;
+static PSI_mutex_key key_LOCK_open;
 static PSI_mutex_info all_tdc_mutexes[]= {
-  { &key_LOCK_open, "LOCK_open", PSI_FLAG_GLOBAL },
-  { &key_LOCK_dd_owns_lock_open, "LOCK_dd_owns_lock_open", PSI_FLAG_GLOBAL }
+  { &key_LOCK_open, "LOCK_open", PSI_FLAG_GLOBAL }
 };
 
 /**
@@ -250,7 +247,8 @@ static void check_unused(void)
     Length of key
 */
 
-uint create_table_def_key(THD *thd, char *key, TABLE_LIST *table_list,
+uint create_table_def_key(THD *thd, char *key,
+                          const TABLE_LIST *table_list,
                           bool tmp_table)
 {
   uint key_length= (uint) (strmov(strmov(key, table_list->db)+1,
@@ -301,8 +299,6 @@ bool table_def_init(void)
   init_tdc_psi_keys();
 #endif
   mysql_mutex_init(key_LOCK_open, &LOCK_open, MY_MUTEX_INIT_FAST);
-  mysql_mutex_init(key_LOCK_dd_owns_lock_open, &LOCK_dd_owns_lock_open,
-                   MY_MUTEX_INIT_FAST);
   oldest_unused_share= &end_of_unused_share;
   end_of_unused_share.prev= &oldest_unused_share;
 
@@ -346,7 +342,6 @@ void table_def_free(void)
     table_def_inited= 0;
     /* Free table definitions. */
     my_hash_free(&table_def_cache);
-    mysql_mutex_destroy(&LOCK_dd_owns_lock_open);
     mysql_mutex_destroy(&LOCK_open);
   }
   DBUG_VOID_RETURN;
@@ -1999,39 +1994,60 @@ void update_non_unique_table_error(TABLE
 }
 
 
+/**
+  Find temporary table specified by database and table names in the
+  THD::temporary_tables list.
+
+  @return TABLE instance if a temporary table has been found; NULL otherwise.
+*/
+
 TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name)
 {
-  TABLE_LIST table_list;
+  TABLE_LIST tl;
 
-  table_list.db= (char*) db;
-  table_list.table_name= (char*) table_name;
-  return find_temporary_table(thd, &table_list);
+  tl.db= (char*) db;
+  tl.table_name= (char*) table_name;
+
+  return find_temporary_table(thd, &tl);
 }
 
 
-TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list)
+/**
+  Find a temporary table specified by TABLE_LIST instance in the
+  THD::temporary_tables list.
+
+  @return TABLE instance if a temporary table has been found; NULL otherwise.
+*/
+
+TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl)
 {
-  char	key[MAX_DBKEY_LENGTH];
-  uint	key_length;
-  TABLE *table;
-  DBUG_ENTER("find_temporary_table");
-  DBUG_PRINT("enter", ("table: '%s'.'%s'",
-                       table_list->db, table_list->table_name));
+  char key[MAX_DBKEY_LENGTH];
+  uint key_length= create_table_def_key(thd, key, tl, 1);
+
+  return find_temporary_table(thd, key, key_length);
+}
+
+
+/**
+  Find a temporary table specified by a key in the THD::temporary_tables list.
 
-  key_length= create_table_def_key(thd, key, table_list, 1);
-  for (table=thd->temporary_tables ; table ; table= table->next)
+  @return TABLE instance if a temporary table has been found; NULL otherwise.
+*/
+
+TABLE *find_temporary_table(THD *thd,
+                            const char *table_key,
+                            uint table_key_length)
+{
+  for (TABLE *table= thd->temporary_tables; table; table= table->next)
   {
-    if (table->s->table_cache_key.length == key_length &&
-	!memcmp(table->s->table_cache_key.str, key, key_length))
+    if (table->s->table_cache_key.length == table_key_length &&
+        !memcmp(table->s->table_cache_key.str, table_key, table_key_length))
     {
-      DBUG_PRINT("info",
-                 ("Found table. server_id: %u  pseudo_thread_id: %lu",
-                  (uint) thd->server_id,
-                  (ulong) thd->variables.pseudo_thread_id));
-      DBUG_RETURN(table);
+      return table;
     }
   }
-  DBUG_RETURN(0);                               // Not a temporary table
+
+  return NULL;
 }
 
 
@@ -3035,41 +3051,11 @@ retry_share:
   table->reginfo.lock_type=TL_READ;		/* Assume read */
 
  reset:
-  DBUG_ASSERT(table->s->ref_count > 0 || table->s->tmp_table != NO_TMP_TABLE);
-
-  if (thd->lex->need_correct_ident())
-    table->alias_name_used= my_strcasecmp(table_alias_charset,
-                                          table->s->table_name.str, alias);
-  /* Fix alias if table name changes */
-  if (strcmp(table->alias, alias))
-  {
-    uint length=(uint) strlen(alias)+1;
-    table->alias= (char*) my_realloc((char*) table->alias, length,
-                                     MYF(MY_WME));
-    memcpy((char*) table->alias, alias, length);
-  }
-  table->tablenr=thd->current_tablenr++;
-  table->used_fields=0;
-  table->const_table=0;
-  table->null_row= table->maybe_null= 0;
-  table->force_index= table->force_index_order= table->force_index_group= 0;
-  table->status=STATUS_NO_RECORD;
-  table->insert_values= 0;
-  table->fulltext_searched= 0;
-  table->file->ft_handler= 0;
-  table->reginfo.impossible_range= 0;
-  /* Catch wrong handling of the auto_increment_field_not_null. */
-  DBUG_ASSERT(!table->auto_increment_field_not_null);
-  table->auto_increment_field_not_null= FALSE;
-  if (table->timestamp_field)
-    table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
-  table->pos_in_table_list= table_list;
   table_list->updatable= 1; // It is not derived table nor non-updatable VIEW
-  table->clear_column_bitmaps();
   table_list->table= table;
-  DBUG_ASSERT(table->key_read == 0);
-  /* Tables may be reused in a sub statement. */
-  DBUG_ASSERT(! table->file->extra(HA_EXTRA_IS_ATTACHED_CHILDREN));
+
+  table->init(thd, table_list);
+
   DBUG_RETURN(FALSE);
 
 err_lock:
@@ -4542,13 +4528,15 @@ lock_table_names(THD *thd,
            ! (flags & MYSQL_OPEN_SKIP_TEMPORARY) &&
            find_temporary_table(thd, table))))
     {
-      if (schema_set.insert(table))
+      if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) &&
+          schema_set.insert(table))
         return TRUE;
       mdl_requests.push_front(&table->mdl_request);
     }
   }
 
-  if (! mdl_requests.is_empty())
+  if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) &&
+      ! mdl_requests.is_empty())
   {
     /*
       Scoped locks: Take intention exclusive locks on all involved
@@ -5183,6 +5171,8 @@ static bool check_lock_and_start_stmt(TH
   @param[in]    lock_type       lock to use for table
   @param[in]    flags           options to be used while opening and locking
                                 table (see open_table(), mysql_lock_tables())
+  @param[in]    prelocking_strategy  Strategy which specifies how prelocking
+                                     algorithm should work for this statement.
 
   @return       table
     @retval     != NULL         OK, opened table returned
@@ -5208,7 +5198,8 @@ static bool check_lock_and_start_stmt(TH
 */
 
 TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
-                                thr_lock_type lock_type, uint flags)
+                                thr_lock_type lock_type, uint flags,
+                                Prelocking_strategy *prelocking_strategy)
 {
   TABLE_LIST *save_next_global;
   DBUG_ENTER("open_n_lock_single_table");
@@ -5224,7 +5215,8 @@ TABLE *open_n_lock_single_table(THD *thd
   table_l->required_type= FRMTYPE_TABLE;
 
   /* Open the table. */
-  if (open_and_lock_tables(thd, table_l, FALSE, flags))
+  if (open_and_lock_tables(thd, table_l, FALSE, flags,
+                           prelocking_strategy))
     table_l->table= NULL; /* Just to be sure. */
 
   /* Restore list. */
@@ -5716,35 +5708,37 @@ void close_tables_for_reopen(THD *thd, T
 }
 
 
-/*
-  Open a single table without table caching and don't set it in open_list
-
-  SYNPOSIS
-    open_temporary_table()
-    thd		  Thread object
-    path	  Path (without .frm)
-    db		  database
-    table_name	  Table name
-    link_in_list  1 if table should be linked into thd->temporary_tables
-
- NOTES:
-    Used by alter_table to open a temporary table and when creating
-    a temporary table with CREATE TEMPORARY ...
-
- RETURN
-   0  Error
-   #  TABLE object
-*/
-
-TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
-			    const char *table_name, bool link_in_list)
+/**
+  Open a single table without table caching and don't add it to
+  THD::open_tables. Depending on the 'add_to_temporary_tables_list' value,
+  the opened TABLE instance will be addded to THD::temporary_tables list.
+
+  @param thd                          Thread context.
+  @param path                         Path (without .frm)
+  @param db                           Database name.
+  @param table_name                   Table name.
+  @param add_to_temporary_tables_list Specifies if the opened TABLE
+                                      instance should be linked into
+                                      THD::temporary_tables list.
+
+  @note This function is used:
+    - by alter_table() to open a temporary table;
+    - when creating a temporary table with CREATE TEMPORARY TABLE.
+
+  @return TABLE instance for opened table.
+  @retval NULL on error.
+*/
+
+TABLE *open_table_uncached(THD *thd, const char *path, const char *db,
+                           const char *table_name,
+                           bool add_to_temporary_tables_list)
 {
   TABLE *tmp_table;
   TABLE_SHARE *share;
   char cache_key[MAX_DBKEY_LENGTH], *saved_cache_key, *tmp_path;
   uint key_length;
   TABLE_LIST table_list;
-  DBUG_ENTER("open_temporary_table");
+  DBUG_ENTER("open_table_uncached");
   DBUG_PRINT("enter",
              ("table: '%s'.'%s'  path: '%s'  server_id: %u  "
               "pseudo_thread_id: %lu",
@@ -5799,7 +5793,7 @@ TABLE *open_temporary_table(THD *thd, co
   share->tmp_table= (tmp_table->file->has_transactions() ? 
                      TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE);
 
-  if (link_in_list)
+  if (add_to_temporary_tables_list)
   {
     /* growing temp list at the head */
     tmp_table->next= thd->temporary_tables;

=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h	2010-09-13 10:26:57 +0000
+++ b/sql/sql_base.h	2010-10-01 10:23:16 +0000
@@ -17,7 +17,6 @@
 #define SQL_BASE_INCLUDED
 
 #include "unireg.h"                    // REQUIRED: for other includes
-#include "table.h"                              /* open_table_mode */
 #include "sql_trigger.h"                        /* trg_event_type */
 #include "sql_class.h"                          /* enum_mark_columns */
 #include "mysqld.h"                             /* key_map */
@@ -71,8 +70,6 @@ enum enum_tdc_remove_table_type {TDC_RT_
 
 bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
 extern mysql_mutex_t LOCK_open;
-extern mysql_mutex_t LOCK_dd_owns_lock_open;
-extern uint dd_owns_lock_open;
 bool table_cache_init(void);
 void table_cache_free(void);
 bool table_def_init(void);
@@ -81,7 +78,8 @@ void table_def_start_shutdown(void);
 void assign_new_table_id(TABLE_SHARE *share);
 uint cached_open_tables(void);
 uint cached_table_definitions(void);
-uint create_table_def_key(THD *thd, char *key, TABLE_LIST *table_list,
+uint create_table_def_key(THD *thd, char *key,
+                          const TABLE_LIST *table_list,
                           bool tmp_table);
 TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key,
                              uint key_length, uint db_flags, int *error,
@@ -124,6 +122,11 @@ TABLE *open_ltable(THD *thd, TABLE_LIST 
   (LONG_TIMEOUT = 1 year) rather than the user-supplied timeout value.
 */
 #define MYSQL_LOCK_IGNORE_TIMEOUT               0x0800
+/**
+  When acquiring "strong" (SNW, SNRW, X) metadata locks on tables to
+  be open do not acquire global and schema-scope IX locks.
+*/
+#define MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK         0x1000
 
 /** Please refer to the internals manual. */
 #define MYSQL_OPEN_REOPEN  (MYSQL_OPEN_IGNORE_FLUSH |\
@@ -143,8 +146,9 @@ bool open_new_frm(THD *thd, TABLE_SHARE 
 
 bool get_key_map_from_key_list(key_map *map, TABLE *table,
                                List<String> *index_list);
-TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
-			    const char *table_name, bool link_in_list);
+TABLE *open_table_uncached(THD *thd, const char *path, const char *db,
+			   const char *table_name,
+                           bool add_to_temporary_tables_list);
 TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name);
 TABLE *find_write_locked_table(TABLE *list, const char *db,
                                const char *table_name);
@@ -161,7 +165,9 @@ TABLE_LIST *find_table_in_list(TABLE_LIS
                                const char *db_name,
                                const char *table_name);
 TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name);
-TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list);
+TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl);
+TABLE *find_temporary_table(THD *thd, const char *table_key,
+                            uint table_key_length);
 void close_thread_tables(THD *thd);
 bool fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
                                           List<Item> &values,
@@ -240,7 +246,8 @@ bool open_and_lock_tables(THD *thd, TABL
 int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived);
 /* simple open_and_lock_tables without derived handling for single table */
 TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
-                                thr_lock_type lock_type, uint flags);
+                                thr_lock_type lock_type, uint flags,
+                                Prelocking_strategy *prelocking_strategy);
 bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags);
 bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
 int decide_logging_format(THD *thd, TABLE_LIST *tables);
@@ -449,6 +456,16 @@ open_tables(THD *thd, TABLE_LIST **table
 }
 
 
+inline TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
+                                       thr_lock_type lock_type, uint flags)
+{
+  DML_prelocking_strategy prelocking_strategy;
+
+  return open_n_lock_single_table(thd, table_l, lock_type, flags,
+                                  &prelocking_strategy);
+}
+
+
 /* open_and_lock_tables with derived handling */
 inline bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
                                  bool derived, uint flags)

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2010-09-29 14:41:24 +0000
+++ b/sql/sql_insert.cc	2010-10-01 10:23:16 +0000
@@ -634,14 +634,12 @@ bool open_and_lock_for_insert_delayed(TH
 static int
 create_insert_stmt_from_insert_delayed(THD *thd, String *buf)
 {
-  /* Append the part of thd->query before "DELAYED" keyword */
-  if (buf->append(thd->query(),
-                  thd->lex->keyword_delayed_begin - thd->query()))
+  /* Make a copy of thd->query() and then remove the "DELAYED" keyword */
+  if (buf->append(thd->query()) ||
+      buf->replace(thd->lex->keyword_delayed_begin_offset,
+                   thd->lex->keyword_delayed_end_offset -
+                   thd->lex->keyword_delayed_begin_offset, 0))
     return 1;
-  /* Append the part of thd->query after "DELAYED" keyword */
-  if (buf->append(thd->lex->keyword_delayed_begin + 7))
-    return 1;
-
   return 0;
 }
 
@@ -2496,6 +2494,65 @@ void kill_delayed_threads(void)
 
 
 /**
+  A strategy for the prelocking algorithm which prevents the
+  delayed insert thread from opening tables with engines which
+  do not support delayed inserts.
+
+  Particularly it allows to abort open_tables() as soon as we
+  discover that we have opened a MERGE table, without acquiring
+  metadata locks on underlying tables.
+*/
+
+class Delayed_prelocking_strategy : public Prelocking_strategy
+{
+public:
+  virtual bool handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
+                              Sroutine_hash_entry *rt, sp_head *sp,
+                              bool *need_prelocking);
+  virtual bool handle_table(THD *thd, Query_tables_list *prelocking_ctx,
+                            TABLE_LIST *table_list, bool *need_prelocking);
+  virtual bool handle_view(THD *thd, Query_tables_list *prelocking_ctx,
+                           TABLE_LIST *table_list, bool *need_prelocking);
+};
+
+
+bool Delayed_prelocking_strategy::
+handle_table(THD *thd, Query_tables_list *prelocking_ctx,
+             TABLE_LIST *table_list, bool *need_prelocking)
+{
+  DBUG_ASSERT(table_list->lock_type == TL_WRITE_DELAYED);
+
+  if (!(table_list->table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED))
+  {
+    my_error(ER_DELAYED_NOT_SUPPORTED, MYF(0), table_list->table_name);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+
+bool Delayed_prelocking_strategy::
+handle_routine(THD *thd, Query_tables_list *prelocking_ctx,
+               Sroutine_hash_entry *rt, sp_head *sp,
+               bool *need_prelocking)
+{
+  /* LEX used by the delayed insert thread has no routines. */
+  DBUG_ASSERT(0);
+  return FALSE;
+}
+
+
+bool Delayed_prelocking_strategy::
+handle_view(THD *thd, Query_tables_list *prelocking_ctx,
+            TABLE_LIST *table_list, bool *need_prelocking)
+{
+  /* We don't open views in the delayed insert thread. */
+  DBUG_ASSERT(0);
+  return FALSE;
+}
+
+
+/**
    Open and lock table for use by delayed thread and check that
    this table is suitable for delayed inserts.
 
@@ -2505,21 +2562,21 @@ void kill_delayed_threads(void)
 
 bool Delayed_insert::open_and_lock_table()
 {
+  Delayed_prelocking_strategy prelocking_strategy;
+
+  /*
+    Use special prelocking strategy to get ER_DELAYED_NOT_SUPPORTED
+    error for tables with engines which don't support delayed inserts.
+  */
   if (!(table= open_n_lock_single_table(&thd, &table_list,
                                         TL_WRITE_DELAYED,
-                                        MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK)))
+                                        MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK,
+                                        &prelocking_strategy)))
   {
     thd.fatal_error();				// Abort waiting inserts
     return TRUE;
   }
-  if (!(table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED))
-  {
-    /* To rollback InnoDB statement transaction. */
-    trans_rollback_stmt(&thd);
-    my_error(ER_DELAYED_NOT_SUPPORTED, MYF(ME_FATALERROR),
-             table_list.table_name);
-    return TRUE;
-  }
+
   if (table->triggers)
   {
     /*

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2010-09-01 13:14:50 +0000
+++ b/sql/sql_lex.h	2010-10-01 10:23:16 +0000
@@ -2367,15 +2367,19 @@ struct LEX: public Query_tables_list
     This pointer is required to add possibly omitted DEFINER-clause to the
     DDL-statement before dumping it to the binlog.
 
-    keyword_delayed_begin points to the begin of the DELAYED keyword in
-    INSERT DELAYED statement.
+    keyword_delayed_begin_offset is the offset to the beginning of the DELAYED
+    keyword in INSERT DELAYED statement. keyword_delayed_end_offset is the
+    offset to the character right after the DELAYED keyword.
   */
   union {
     const char *stmt_definition_begin;
-    const char *keyword_delayed_begin;
+    uint keyword_delayed_begin_offset;
   };
 
-  const char *stmt_definition_end;
+  union {
+    const char *stmt_definition_end;
+    uint keyword_delayed_end_offset;
+  };
 
   /**
     During name resolution search only in the table list given by 

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-08-30 08:38:30 +0000
+++ b/sql/sql_parse.cc	2010-10-01 10:23:16 +0000
@@ -178,8 +178,7 @@ static bool some_non_temp_table_to_be_up
   for (TABLE_LIST *table= tables; table; table= table->next_global)
   {
     DBUG_ASSERT(table->db && table->table_name);
-    if (table->updating &&
-        !find_temporary_table(thd, table->db, table->table_name))
+    if (table->updating && !find_temporary_table(thd, table))
       return 1;
   }
   return 0;
@@ -403,6 +402,7 @@ void init_update_queries(void)
   sql_command_flags[SQLCOM_REPAIR]=    CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
   sql_command_flags[SQLCOM_OPTIMIZE]|= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
   sql_command_flags[SQLCOM_ANALYZE]=   CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
+  sql_command_flags[SQLCOM_CHECK]=     CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
 
   sql_command_flags[SQLCOM_CREATE_USER]|=       CF_AUTO_COMMIT_TRANS;
   sql_command_flags[SQLCOM_DROP_USER]|=         CF_AUTO_COMMIT_TRANS;
@@ -416,7 +416,6 @@ void init_update_queries(void)
 
   sql_command_flags[SQLCOM_FLUSH]=              CF_AUTO_COMMIT_TRANS;
   sql_command_flags[SQLCOM_RESET]=              CF_AUTO_COMMIT_TRANS;
-  sql_command_flags[SQLCOM_CHECK]=              CF_AUTO_COMMIT_TRANS;
   sql_command_flags[SQLCOM_CREATE_SERVER]=      CF_AUTO_COMMIT_TRANS;
   sql_command_flags[SQLCOM_ALTER_SERVER]=       CF_AUTO_COMMIT_TRANS;
   sql_command_flags[SQLCOM_DROP_SERVER]=        CF_AUTO_COMMIT_TRANS;
@@ -634,45 +633,6 @@ end:
 }
 
 
-/**
-  @brief Check access privs for a MERGE table and fix children lock types.
-
-  @param[in]        thd         thread handle
-  @param[in]        db          database name
-  @param[in,out]    table_list  list of child tables (merge_list)
-                                lock_type and optionally db set per table
-
-  @return           status
-    @retval         0           OK
-    @retval         != 0        Error
-
-  @detail
-    This function is used for write access to MERGE tables only
-    (CREATE TABLE, ALTER TABLE ... UNION=(...)). Set TL_WRITE for
-    every child. Set 'db' for every child if not present.
-*/
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list)
-{
-  int error= 0;
-
-  if (table_list)
-  {
-    /* Check that all tables use the current database */
-    TABLE_LIST *tlist;
-
-    for (tlist= table_list; tlist; tlist= tlist->next_local)
-    {
-      if (!tlist->db || !tlist->db[0])
-        tlist->db= db; /* purecov: inspected */
-    }
-    error= check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
-                              table_list, FALSE, UINT_MAX, FALSE);
-  }
-  return error;
-}
-#endif
-
 /* This works because items are allocated with sql_alloc() */
 
 void free_items(Item *item)
@@ -6956,10 +6916,16 @@ bool create_table_precheck(THD *thd, TAB
   if (check_access(thd, want_priv, create_table->db,
                    &create_table->grant.privilege,
                    &create_table->grant.m_internal,
-                   0, 0) ||
-      check_merge_table_access(thd, create_table->db,
-                               lex->create_info.merge_list.first))
+                   0, 0))
+    goto err;
+
+  /* If it is a merge table, check privileges for merge children. */
+  if (lex->create_info.merge_list.first &&
+      check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL,
+                         lex->create_info.merge_list.first,
+                         FALSE, UINT_MAX, FALSE))
     goto err;
+
   if (want_priv != CREATE_TMP_ACL &&
       check_grant(thd, want_priv, create_table, FALSE, 1, FALSE))
     goto err;

=== modified file 'sql/sql_parse.h'
--- a/sql/sql_parse.h	2010-08-20 08:48:59 +0000
+++ b/sql/sql_parse.h	2010-10-01 10:23:16 +0000
@@ -152,7 +152,6 @@ bool check_single_table_access(THD *thd,
 bool check_routine_access(THD *thd,ulong want_access,char *db,char *name,
 			  bool is_proc, bool no_errors);
 bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
-bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list);
 bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
 bool check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
                   GRANT_INTERNAL_INFO *grant_internal_info,
@@ -175,8 +174,6 @@ inline bool check_some_access(THD *thd, 
   table->grant.privilege= want_access;
   return false;
 }
-inline bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list)
-{ return false; }
 inline bool check_some_routine_access(THD *thd, const char *db,
                                       const char *name, bool is_proc)
 { return false; }

=== modified file 'sql/sql_reload.cc'
--- a/sql/sql_reload.cc	2010-08-20 08:48:59 +0000
+++ b/sql/sql_reload.cc	2010-10-01 10:23:16 +0000
@@ -329,7 +329,6 @@ bool reload_acl_and_cache(THD *thd, unsi
   -------------------------------------
   - you can't flush WITH READ LOCK a non-existent table
   - you can't flush WITH READ LOCK under LOCK TABLES
-  - currently incompatible with the GRL (@todo: fix)
 
   Effect on views and temporary tables.
   ------------------------------------
@@ -339,6 +338,13 @@ bool reload_acl_and_cache(THD *thd, unsi
   if there is a base table, it's used, otherwise ER_NO_SUCH_TABLE
   is returned.
 
+  Handling of MERGE tables
+  ------------------------
+  For MERGE table this statement will open and lock child tables
+  for read (it is impossible to lock parent table without it).
+  Child tables won't be flushed unless they are explicitly present
+  in the statement's table list.
+
   Implicit commit
   ---------------
   This statement causes an implicit commit before and
@@ -355,7 +361,6 @@ bool flush_tables_with_read_lock(THD *th
 {
   Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
   TABLE_LIST *table_list;
-  MDL_request_list mdl_requests;
 
   /*
     This is called from SQLCOM_FLUSH, the transaction has
@@ -369,17 +374,13 @@ bool flush_tables_with_read_lock(THD *th
   }
 
   /*
-    Acquire SNW locks on tables to be flushed. We can't use
-    lock_table_names() here as this call will also acquire global IX
-    and database-scope IX locks on the tables, and this will make
+    Acquire SNW locks on tables to be flushed. Don't acquire global
+    IX and database-scope IX locks on the tables as this will make
     this statement incompatible with FLUSH TABLES WITH READ LOCK.
   */
-  for (table_list= all_tables; table_list;
-       table_list= table_list->next_global)
-    mdl_requests.push_front(&table_list->mdl_request);
-
-  if (thd->mdl_context.acquire_locks(&mdl_requests,
-                                     thd->variables.lock_wait_timeout))
+  if (lock_table_names(thd, all_tables, NULL,
+                       thd->variables.lock_wait_timeout,
+                       MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK))
     goto error;
 
   DEBUG_SYNC(thd,"flush_tables_with_read_lock_after_acquire_locks");
@@ -391,21 +392,24 @@ bool flush_tables_with_read_lock(THD *th
     tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
                      table_list->db,
                      table_list->table_name, FALSE);
-
-    /* Skip views and temporary tables. */
-    table_list->required_type= FRMTYPE_TABLE; /* Don't try to flush views. */
-    table_list->open_type= OT_BASE_ONLY;      /* Ignore temporary tables. */
+    /* Reset ticket to satisfy asserts in open_tables(). */
+    table_list->mdl_request.ticket= NULL;
   }
 
   /*
     Before opening and locking tables the below call also waits
     for old shares to go away, so the fact that we don't pass
     MYSQL_LOCK_IGNORE_FLUSH flag to it is important.
+    Also we don't pass MYSQL_OPEN_HAS_MDL_LOCK flag as we want
+    to open underlying tables if merge table is flushed.
+    For underlying tables of the merge the below call has to
+    acquire SNW locks to ensure that they can be locked for
+    read without further waiting.
   */
-  if  (open_and_lock_tables(thd, all_tables, FALSE,
-                            MYSQL_OPEN_HAS_MDL_LOCK,
-                            &lock_tables_prelocking_strategy) ||
-       thd->locked_tables_list.init_locked_tables(thd))
+  if (open_and_lock_tables(thd, all_tables, FALSE,
+                           MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK,
+                           &lock_tables_prelocking_strategy) ||
+      thd->locked_tables_list.init_locked_tables(thd))
   {
     goto error;
   }

=== modified file 'sql/sql_rename.cc'
--- a/sql/sql_rename.cc	2010-08-20 08:48:59 +0000
+++ b/sql/sql_rename.cc	2010-10-01 10:23:16 +0000
@@ -285,6 +285,7 @@ do_rename(THD *thd, TABLE_LIST *ren_tabl
         {
           if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
                                                           old_alias,
+                                                          ren_table->table_name,
                                                           new_db,
                                                           new_alias)))
           {

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-09-29 14:41:24 +0000
+++ b/sql/sql_table.cc	2010-10-01 10:23:16 +0000
@@ -22,7 +22,7 @@
 #include "sql_rename.h" // do_rename
 #include "sql_parse.h"                        // test_if_data_home_dir
 #include "sql_cache.h"                          // query_cache_*
-#include "sql_base.h"   // open_temporary_table, lock_table_names
+#include "sql_base.h"   // open_table_uncached, lock_table_names
 #include "lock.h"       // wait_if_global_read_lock
                         // start_waiting_global_read_lock,
                         // mysql_unlock_tables
@@ -2184,7 +2184,7 @@ int mysql_rm_table_part2(THD *thd, TABLE
     {
       for (table= tables; table; table= table->next_local)
         if (table->open_type != OT_BASE_ONLY &&
-	    find_temporary_table(thd, table->db, table->table_name))
+	    find_temporary_table(thd, table))
         {
           /*
             A temporary table.
@@ -4401,9 +4401,14 @@ bool mysql_create_table_no_lock(THD *thd
 
   if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
   {
-    TABLE *table= NULL;
-    /* Open table and put in temporary table list */
-    if (!(table= open_temporary_table(thd, path, db, table_name, 1)))
+    /*
+      Open a table (skipping table cache) and add it into
+      THD::temporary_tables list.
+    */
+
+    TABLE *table= open_table_uncached(thd, path, db, table_name, TRUE);
+
+    if (!table)
     {
       (void) rm_temporary_table(create_info->db_type, path);
       goto err;
@@ -6105,7 +6110,8 @@ bool mysql_alter_table(THD *thd,char *ne
         *fn_ext(new_name)=0;
         if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
           error= -1;
-        else if (Table_triggers_list::change_table_name(thd, db, table_name,
+        else if (Table_triggers_list::change_table_name(thd, db,
+                                                        alias, table_name,
                                                         new_db, new_alias))
         {
           (void) mysql_rename_table(old_db_type, new_db, new_alias, db,
@@ -6493,8 +6499,8 @@ bool mysql_alter_table(THD *thd,char *ne
       /* table is a normal table: Create temporary table in same directory */
       build_table_filename(path, sizeof(path) - 1, new_db, tmp_name, "",
                            FN_IS_TMP);
-      /* Open our intermediate table */
-      new_table= open_temporary_table(thd, path, new_db, tmp_name, 1);
+      /* Open our intermediate table. */
+      new_table= open_table_uncached(thd, path, new_db, tmp_name, TRUE);
     }
     if (!new_table)
       goto err_new_table_cleanup;
@@ -6742,7 +6748,7 @@ bool mysql_alter_table(THD *thd,char *ne
             (need_copy_table != ALTER_TABLE_METADATA_ONLY ||
              mysql_rename_table(save_old_db_type, db, table_name, new_db,
                                 new_alias, NO_FRM_RENAME)) &&
-            Table_triggers_list::change_table_name(thd, db, table_name,
+            Table_triggers_list::change_table_name(thd, db, alias, table_name,
                                                    new_db, new_alias)))
   {
     /* Try to get everything back. */
@@ -6834,7 +6840,7 @@ bool mysql_alter_table(THD *thd,char *ne
     char path[FN_REFLEN];
     TABLE *t_table;
     build_table_filename(path + 1, sizeof(path) - 1, new_db, table_name, "", 0);
-    t_table= open_temporary_table(thd, path, new_db, tmp_name, 0);
+    t_table= open_table_uncached(thd, path, new_db, tmp_name, FALSE);
     if (t_table)
     {
       intern_close_table(t_table);

=== modified file 'sql/sql_trigger.cc'
--- a/sql/sql_trigger.cc	2010-09-10 08:06:58 +0000
+++ b/sql/sql_trigger.cc	2010-10-01 10:23:16 +0000
@@ -458,7 +458,7 @@ bool mysql_create_or_drop_trigger(THD *t
   DBUG_ASSERT(tables->next_global == 0);
 
   /* We do not allow creation of triggers on temporary tables. */
-  if (create && find_temporary_table(thd, tables->db, tables->table_name))
+  if (create && find_temporary_table(thd, tables))
   {
     my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
     goto end;
@@ -1874,6 +1874,7 @@ Table_triggers_list::change_table_name_i
 
   @param[in,out] thd Thread context
   @param[in] db Old database of subject table
+  @param[in] old_alias Old alias of subject table
   @param[in] old_table Old name of subject table
   @param[in] new_db New database for subject table
   @param[in] new_table New name of subject table
@@ -1890,6 +1891,7 @@ Table_triggers_list::change_table_name_i
 */
 
 bool Table_triggers_list::change_table_name(THD *thd, const char *db,
+                                            const char *old_alias,
                                             const char *old_table,
                                             const char *new_db,
                                             const char *new_table)
@@ -1911,7 +1913,7 @@ bool Table_triggers_list::change_table_n
                                              MDL_EXCLUSIVE));
 
   DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) ||
-              my_strcasecmp(table_alias_charset, old_table, new_table));
+              my_strcasecmp(table_alias_charset, old_alias, new_table));
 
   if (Table_triggers_list::check_n_load(thd, db, old_table, &table, TRUE))
   {
@@ -1920,7 +1922,7 @@ bool Table_triggers_list::change_table_n
   }
   if (table.triggers)
   {
-    LEX_STRING old_table_name= { (char *) old_table, strlen(old_table) };
+    LEX_STRING old_table_name= { (char *) old_alias, strlen(old_alias) };
     LEX_STRING new_table_name= { (char *) new_table, strlen(new_table) };
     /*
       Since triggers should be in the same schema as their subject tables

=== modified file 'sql/sql_trigger.h'
--- a/sql/sql_trigger.h	2010-07-02 18:15:21 +0000
+++ b/sql/sql_trigger.h	2010-10-01 10:23:16 +0000
@@ -157,6 +157,7 @@ public:
                            TABLE *table, bool names_only);
   static bool drop_all_triggers(THD *thd, char *db, char *table_name);
   static bool change_table_name(THD *thd, const char *db,
+                                const char *old_alias,
                                 const char *old_table,
                                 const char *new_db,
                                 const char *new_table);

=== modified file 'sql/sql_truncate.cc'
--- a/sql/sql_truncate.cc	2010-08-18 11:29:04 +0000
+++ b/sql/sql_truncate.cc	2010-08-31 10:03:36 +0000
@@ -208,8 +208,8 @@ static bool recreate_temporary_table(THD
   ha_create_table(thd, share->normalized_path.str, share->db.str,
                   share->table_name.str, &create_info, 1);
 
-  if (open_temporary_table(thd, share->path.str, share->db.str,
-                           share->table_name.str, 1))
+  if (open_table_uncached(thd, share->path.str, share->db.str,
+                          share->table_name.str, TRUE))
   {
     error= FALSE;
     thd->thread_specific_used= TRUE;

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2010-09-01 13:14:50 +0000
+++ b/sql/sql_yacc.yy	2010-10-01 10:23:16 +0000
@@ -10611,7 +10611,10 @@ insert_lock_option:
         | LOW_PRIORITY  { $$= TL_WRITE_LOW_PRIORITY; }
         | DELAYED_SYM
         {
-          Lex->keyword_delayed_begin= YYLIP->get_tok_start();
+          Lex->keyword_delayed_begin_offset= (uint)(YYLIP->get_tok_start() -
+                                                    YYTHD->query());
+          Lex->keyword_delayed_end_offset= Lex->keyword_delayed_begin_offset +
+                                           YYLIP->yyLength() + 1;
           $$= TL_WRITE_DELAYED;
         }
         | HIGH_PRIORITY { $$= TL_WRITE; }
@@ -10621,7 +10624,10 @@ replace_lock_option:
           opt_low_priority { $$= $1; }
         | DELAYED_SYM
         {
-          Lex->keyword_delayed_begin= YYLIP->get_tok_start();
+          Lex->keyword_delayed_begin_offset= (uint)(YYLIP->get_tok_start() -
+                                                    YYTHD->query());
+          Lex->keyword_delayed_end_offset= Lex->keyword_delayed_begin_offset +
+                                           YYLIP->yyLength() + 1;
           $$= TL_WRITE_DELAYED;
         }
         ;
@@ -11442,7 +11448,11 @@ opt_with_read_lock:
             TABLE_LIST *tables= Lex->query_tables;
             Lex->type|= REFRESH_READ_LOCK;
             for (; tables; tables= tables->next_global)
+            {
               tables->mdl_request.set_type(MDL_SHARED_NO_WRITE);
+              tables->required_type= FRMTYPE_TABLE; /* Don't try to flush views. */
+              tables->open_type= OT_BASE_ONLY;      /* Ignore temporary tables. */
+            }
           }
         ;
 
@@ -13409,6 +13419,13 @@ handler:
           handler_read_or_scan where_clause opt_limit_clause
           {
             Lex->expr_allows_subselect= TRUE;
+            /* Stored functions are not supported for HANDLER READ. */
+            if (Lex->uses_stored_routines())
+            {
+              my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+                       "stored functions in HANDLER ... READ");
+              MYSQL_YYABORT;
+            }
           }
         ;
 

=== modified file 'sql/table.cc'
--- a/sql/table.cc	2010-09-13 10:26:57 +0000
+++ b/sql/table.cc	2010-10-01 10:23:16 +0000
@@ -3092,30 +3092,7 @@ bool TABLE_SHARE::visit_subgraph(Wait_fo
     holding a write-lock on MDL_lock::m_rwlock.
   */
   if (gvisitor->m_lock_open_count++ == 0)
-  {
-    /*
-      To circumvent bug #56405 "Deadlock in the MDL deadlock detector"
-      we don't try to lock LOCK_open mutex if some thread doing
-      deadlock detection already owns it and current search depth is
-      greater than 0. Instead we report a deadlock.
-
-      TODO/FIXME: The proper fix for this bug is to use rwlocks for
-                  protection of table shares/instead of LOCK_open.
-                  Unfortunately it requires more effort/has significant
-                  performance effect.
-    */
-    mysql_mutex_lock(&LOCK_dd_owns_lock_open);
-    if (gvisitor->m_current_search_depth > 0 && dd_owns_lock_open > 0)
-    {
-      mysql_mutex_unlock(&LOCK_dd_owns_lock_open);
-      --gvisitor->m_lock_open_count;
-      gvisitor->abort_traversal(src_ctx);
-      return TRUE;
-    }
-    ++dd_owns_lock_open;
-    mysql_mutex_unlock(&LOCK_dd_owns_lock_open);
     mysql_mutex_lock(&LOCK_open);
-  }
 
   I_P_List_iterator <TABLE, TABLE_share> tables_it(used_tables);
 
@@ -3130,12 +3107,8 @@ bool TABLE_SHARE::visit_subgraph(Wait_fo
     goto end;
   }
 
-  ++gvisitor->m_current_search_depth;
   if (gvisitor->enter_node(src_ctx))
-  {
-    --gvisitor->m_current_search_depth;
     goto end;
-  }
 
   while ((table= tables_it++))
   {
@@ -3158,16 +3131,10 @@ bool TABLE_SHARE::visit_subgraph(Wait_fo
 
 end_leave_node:
   gvisitor->leave_node(src_ctx);
-  --gvisitor->m_current_search_depth;
 
 end:
   if (gvisitor->m_lock_open_count-- == 1)
-  {
     mysql_mutex_unlock(&LOCK_open);
-    mysql_mutex_lock(&LOCK_dd_owns_lock_open);
-    --dd_owns_lock_open;
-    mysql_mutex_unlock(&LOCK_dd_owns_lock_open);
-  }
 
   return result;
 }
@@ -3263,6 +3230,65 @@ bool TABLE_SHARE::wait_for_old_version(T
 }
 
 
+/**
+  Initialize TABLE instance (newly created, or coming either from table
+  cache or THD::temporary_tables list) and prepare it for further use
+  during statement execution. Set the 'alias' attribute from the specified
+  TABLE_LIST element. Remember the TABLE_LIST element in the
+  TABLE::pos_in_table_list member.
+
+  @param thd  Thread context.
+  @param tl   TABLE_LIST element.
+*/
+
+void TABLE::init(THD *thd, TABLE_LIST *tl)
+{
+  DBUG_ASSERT(s->ref_count > 0 || s->tmp_table != NO_TMP_TABLE);
+
+  if (thd->lex->need_correct_ident())
+    alias_name_used= my_strcasecmp(table_alias_charset,
+                                   s->table_name.str,
+                                   tl->alias);
+  /* Fix alias if table name changes. */
+  if (strcmp(alias, tl->alias))
+  {
+    uint length= (uint) strlen(tl->alias)+1;
+    alias= (char*) my_realloc((char*) alias, length, MYF(MY_WME));
+    memcpy((char*) alias, tl->alias, length);
+  }
+
+  tablenr= thd->current_tablenr++;
+  used_fields= 0;
+  const_table= 0;
+  null_row= 0;
+  maybe_null= 0;
+  force_index= 0;
+  force_index_order= 0;
+  force_index_group= 0;
+  status= STATUS_NO_RECORD;
+  insert_values= 0;
+  fulltext_searched= 0;
+  file->ft_handler= 0;
+  reginfo.impossible_range= 0;
+
+  /* Catch wrong handling of the auto_increment_field_not_null. */
+  DBUG_ASSERT(!auto_increment_field_not_null);
+  auto_increment_field_not_null= FALSE;
+
+  if (timestamp_field)
+    timestamp_field_type= timestamp_field->get_auto_set_type();
+
+  pos_in_table_list= tl;
+
+  clear_column_bitmaps();
+
+  DBUG_ASSERT(key_read == 0);
+
+  /* Tables may be reused in a sub statement. */
+  DBUG_ASSERT(!file->extra(HA_EXTRA_IS_ATTACHED_CHILDREN));
+}
+
+
 /*
   Create Item_field for each column in the table.
 

=== modified file 'sql/table.h'
--- a/sql/table.h	2010-09-29 14:41:24 +0000
+++ b/sql/table.h	2010-10-01 10:23:16 +0000
@@ -83,18 +83,6 @@ enum enum_table_ref_type
 };
 
 
-/**
-  Opening modes for open_temporary_table and open_table_from_share
-*/
-
-enum open_table_mode
-{
-  OTM_OPEN= 0,
-  OTM_CREATE= 1,
-  OTM_ALTER= 2
-};
-
-
 /*************************************************************************/
 
 /**
@@ -1096,6 +1084,7 @@ public:
 #endif
   MDL_ticket *mdl_ticket;
 
+  void init(THD *thd, TABLE_LIST *tl);
   bool fill_item_list(List<Item> *item_list) const;
   void reset_item_list(List<Item> *item_list) const;
   void clear_column_bitmaps(void);

=== modified file 'sql/transaction.cc'
--- a/sql/transaction.cc	2010-07-27 15:01:56 +0000
+++ b/sql/transaction.cc	2010-10-01 10:23:16 +0000
@@ -565,7 +565,8 @@ bool trans_xa_end(THD *thd)
   else if (!xa_trans_rolled_back(&thd->transaction.xid_state))
     thd->transaction.xid_state.xa_state= XA_IDLE;
 
-  DBUG_RETURN(thd->transaction.xid_state.xa_state != XA_IDLE);
+  DBUG_RETURN(thd->is_error() ||
+              thd->transaction.xid_state.xa_state != XA_IDLE);
 }
 
 
@@ -596,7 +597,8 @@ bool trans_xa_prepare(THD *thd)
   else
     thd->transaction.xid_state.xa_state= XA_PREPARED;
 
-  DBUG_RETURN(thd->transaction.xid_state.xa_state != XA_PREPARED);
+  DBUG_RETURN(thd->is_error() ||
+              thd->transaction.xid_state.xa_state != XA_PREPARED);
 }
 
 

=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc	2010-07-27 14:32:42 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc	2010-09-08 08:25:37 +0000
@@ -478,6 +478,8 @@ int ha_myisammrg::add_children_list(void
     /* Set the expected table version, to not cause spurious re-prepare. */
     child_l->set_table_ref_id(mrg_child_def->get_child_table_ref_type(),
                               mrg_child_def->get_child_def_version());
+    /* Use the same metadata lock type for children. */
+    child_l->mdl_request.set_type(parent_l->mdl_request.type);
     /* Link TABLE_LIST object into the children list. */
     if (this->children_last_l)
       child_l->prev_global= this->children_last_l;


Attachment: [text/bzr-bundle] bzr/jon.hauglid@oracle.com-20101001102316-x7emg5usg171d3br.bundle
Thread
bzr commit into mysql-trunk-merge branch (jon.hauglid:3204) Jon Olav Hauglid1 Oct