List:Commits« Previous MessageNext Message »
From:Jon Olav Hauglid Date:September 3 2010 7:43am
Subject:bzr commit into mysql-5.5-runtime branch (jon.hauglid:3132)
View as plain text  
#At file:///export/home/x/mysql-5.5-runtime-test/ based on revid:jon.hauglid@stripped

 3132 Jon Olav Hauglid	2010-09-03 [merge]
      Merge from mysql-5.5-bugfixing to mysql-5.5-runtime.

    added:
      include/mysql/service_thd_wait.h
      include/mysql/service_thread_scheduler.h
      libservices/my_thread_scheduler_service.c
      libservices/thd_wait_service.c
      mysql-test/include/not_blackhole.inc
      mysql-test/r/partition_not_blackhole.result
      mysql-test/std_data/parts/t1_blackhole.frm
      mysql-test/std_data/parts/t1_blackhole.par
      mysql-test/t/partition_not_blackhole-master.opt
      mysql-test/t/partition_not_blackhole.test
      sql/sql_callback.h
    modified:
      client/mysqltest.cc
      configure.in
      include/Makefile.am
      include/mysql/plugin.h
      include/mysql/plugin_audit.h.pp
      include/mysql/plugin_ftparser.h.pp
      include/mysql/services.h
      include/service_versions.h
      include/thr_lock.h
      include/violite.h
      libmysqld/Makefile.am
      libservices/CMakeLists.txt
      libservices/Makefile.am
      mysql-test/CMakeLists.txt
      mysql-test/r/delete.result
      mysql-test/r/func_gconcat.result
      mysql-test/r/func_group.result
      mysql-test/r/func_misc.result
      mysql-test/r/func_time.result
      mysql-test/r/mysqld--help-notwin.result
      mysql-test/r/mysqld--help-win.result
      mysql-test/r/range.result
      mysql-test/suite/innodb/r/innodb_mysql.result
      mysql-test/suite/innodb/t/innodb_mysql.test
      mysql-test/suite/rpl/r/rpl_flush_logs.result
      mysql-test/suite/rpl/t/rpl_drop.test
      mysql-test/suite/rpl/t/rpl_flush_logs.test
      mysql-test/t/delete.test
      mysql-test/t/func_gconcat.test
      mysql-test/t/func_group.test
      mysql-test/t/func_misc.test
      mysql-test/t/func_time.test
      mysql-test/t/range.test
      mysys/my_getopt.c
      mysys/my_init.c
      mysys/thr_lock.c
      sql/CMakeLists.txt
      sql/authors.h
      sql/ha_partition.cc
      sql/item_func.cc
      sql/item_sum.cc
      sql/item_sum.h
      sql/log.cc
      sql/log.h
      sql/mysqld.cc
      sql/mysqld.h
      sql/opt_range.cc
      sql/scheduler.cc
      sql/scheduler.h
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_connect.cc
      sql/sql_connect.h
      sql/sql_plugin_services.h
      sql/sql_select.cc
      sql/sql_select.h
      sql/sql_show.cc
      sql/sql_yacc.yy
      sql/sys_vars.cc
      sql/table.h
      storage/innobase/buf/buf0flu.c
      storage/innobase/buf/buf0rea.c
      storage/innobase/srv/srv0srv.c
      vio/vio.c
      vio/vio_priv.h
      vio/viosocket.c
      vio/viossl.c
=== modified file 'client/mysqltest.cc'
--- a/client/mysqltest.cc	2010-08-16 06:46:21 +0000
+++ b/client/mysqltest.cc	2010-08-27 11:33:32 +0000
@@ -6228,8 +6228,10 @@ get_one_option(int optid, const struct m
     print_version();
     exit(0);
   case OPT_MYSQL_PROTOCOL:
+#ifndef EMBEDDED_LIBRARY
     opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
                                     opt->name);
+#endif
     break;
   case '?':
     usage();

=== modified file 'configure.in'
--- a/configure.in	2010-08-18 11:29:04 +0000
+++ b/configure.in	2010-08-25 14:05:33 +0000
@@ -27,7 +27,7 @@ dnl
 dnl When changing the major version number please also check the switch
 dnl statement in mysqlbinlog::check_master_version().  You may also need
 dnl to update version.c in ndb.
-AC_INIT([MySQL Server], [5.5.6-m3], [], [mysql])
+AC_INIT([MySQL Server], [5.5.7-m3], [], [mysql])
 
 AC_CONFIG_SRCDIR([sql/mysqld.cc])
 AC_CANONICAL_SYSTEM

=== modified file 'include/Makefile.am'
--- a/include/Makefile.am	2010-07-23 20:14:35 +0000
+++ b/include/Makefile.am	2010-08-16 12:50:27 +0000
@@ -26,6 +26,8 @@ HEADERS_ABI =		mysql.h mysql_com.h mysql
 pkginclude_HEADERS =	$(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \
 			my_xml.h mysql_embed.h mysql/services.h \
 			mysql/service_my_snprintf.h mysql/service_thd_alloc.h \
+			mysql/service_thread_scheduler.h \
+			mysql/service_thd_wait.h \
 		  	my_pthread.h my_no_pthread.h \
 			decimal.h errmsg.h my_global.h my_net.h \
 			my_getopt.h sslopt-longopts.h my_dir.h \

=== modified file 'include/mysql/plugin.h'
--- a/include/mysql/plugin.h	2010-08-18 07:48:38 +0000
+++ b/include/mysql/plugin.h	2010-08-30 14:07:40 +0000
@@ -71,7 +71,7 @@ typedef struct st_mysql_xid MYSQL_XID;
   Plugin API. Common for all plugin types.
 */
 
-#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101
+#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0102
 
 /*
   The allowable types of plugins

=== modified file 'include/mysql/plugin_audit.h.pp'
--- a/include/mysql/plugin_audit.h.pp	2010-08-27 06:45:35 +0000
+++ b/include/mysql/plugin_audit.h.pp	2010-08-30 14:07:40 +0000
@@ -31,6 +31,27 @@ void *thd_memdup(void* thd, const void* 
 MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
                                       const char *str, unsigned int size,
                                       int allocate_lex_string);
+#include <mysql/service_thd_wait.h>
+typedef enum _thd_wait_type_e {
+  THD_WAIT_MUTEX= 1,
+  THD_WAIT_DISKIO= 2,
+  THD_WAIT_ROW_TABLE_LOCK= 3,
+  THD_WAIT_GLOBAL_LOCK= 4
+} thd_wait_type;
+extern struct thd_wait_service_st {
+  void (*thd_wait_begin_func)(void*, thd_wait_type);
+  void (*thd_wait_end_func)(void*);
+} *thd_wait_service;
+void thd_wait_begin(void* thd, thd_wait_type wait_type);
+void thd_wait_end(void* thd);
+#include <mysql/service_thread_scheduler.h>
+struct scheduler_functions;
+extern struct my_thread_scheduler_service {
+  int (*set)(struct scheduler_functions *scheduler);
+  int (*reset)();
+} *my_thread_scheduler_service;
+int my_thread_scheduler_set(struct scheduler_functions *scheduler);
+int my_thread_scheduler_reset();
 struct st_mysql_xid {
   long formatID;
   long gtrid_length;

=== modified file 'include/mysql/plugin_ftparser.h.pp'
--- a/include/mysql/plugin_ftparser.h.pp	2010-08-27 06:45:35 +0000
+++ b/include/mysql/plugin_ftparser.h.pp	2010-08-30 14:07:40 +0000
@@ -31,6 +31,27 @@ void *thd_memdup(void* thd, const void* 
 MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
                                       const char *str, unsigned int size,
                                       int allocate_lex_string);
+#include <mysql/service_thd_wait.h>
+typedef enum _thd_wait_type_e {
+  THD_WAIT_MUTEX= 1,
+  THD_WAIT_DISKIO= 2,
+  THD_WAIT_ROW_TABLE_LOCK= 3,
+  THD_WAIT_GLOBAL_LOCK= 4
+} thd_wait_type;
+extern struct thd_wait_service_st {
+  void (*thd_wait_begin_func)(void*, thd_wait_type);
+  void (*thd_wait_end_func)(void*);
+} *thd_wait_service;
+void thd_wait_begin(void* thd, thd_wait_type wait_type);
+void thd_wait_end(void* thd);
+#include <mysql/service_thread_scheduler.h>
+struct scheduler_functions;
+extern struct my_thread_scheduler_service {
+  int (*set)(struct scheduler_functions *scheduler);
+  int (*reset)();
+} *my_thread_scheduler_service;
+int my_thread_scheduler_set(struct scheduler_functions *scheduler);
+int my_thread_scheduler_reset();
 struct st_mysql_xid {
   long formatID;
   long gtrid_length;

=== added file 'include/mysql/service_thd_wait.h'
--- a/include/mysql/service_thd_wait.h	1970-01-01 00:00:00 +0000
+++ b/include/mysql/service_thd_wait.h	2010-06-07 14:01:39 +0000
@@ -0,0 +1,83 @@
+/* Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef MYSQL_SERVICE_THD_WAIT_INCLUDED
+#define MYSQL_SERVICE_THD_WAIT_INCLUDED
+
+/**
+  @file include/mysql/service_thd_wait.h
+  This service provides functions for plugins and storage engines to report
+  when they are going to sleep/stall.
+  
+  SYNOPSIS
+  thd_wait_begin() - call just before a wait begins
+  thd                     Thread object
+                          Use NULL if the thd is NOT known.
+  wait_type               Type of wait
+                          1 -- short wait (e.g. for mutex)
+                          2 -- medium wait (e.g. for disk io)
+                          3 -- large wait (e.g. for locked row/table)
+  NOTES
+    This is used by the threadpool to have better knowledge of which
+    threads that currently are actively running on CPUs. When a thread
+    reports that it's going to sleep/stall, the threadpool scheduler is
+    free to start another thread in the pool most likely. The expected wait
+    time is simply an indication of how long the wait is expected to
+    become, the real wait time could be very different.
+
+  thd_wait_end() called immediately after the wait is complete
+
+  thd_wait_end() MUST be called if thd_wait_begin() was called.
+
+  Using thd_wait_...() service is optional but recommended.  Using it will
+  improve performance as the thread pool will be more active at managing the
+  thread workload.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum _thd_wait_type_e {
+  THD_WAIT_MUTEX= 1,
+  THD_WAIT_DISKIO= 2,
+  THD_WAIT_ROW_TABLE_LOCK= 3,
+  THD_WAIT_GLOBAL_LOCK= 4
+} thd_wait_type;
+
+extern struct thd_wait_service_st {
+  void (*thd_wait_begin_func)(MYSQL_THD, thd_wait_type);
+  void (*thd_wait_end_func)(MYSQL_THD);
+} *thd_wait_service;
+
+#ifdef MYSQL_DYNAMIC_PLUGIN
+
+#define thd_wait_begin(_THD, _WAIT_TYPE) \
+  thd_wait_service->thd_wait_begin_func(_THD, _WAIT_TYPE)
+#define thd_wait_end(_THD) thd_wait_service->thd_wait_end_func(_THD)
+
+#else
+
+void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type);
+void thd_wait_end(MYSQL_THD thd);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

=== added file 'include/mysql/service_thread_scheduler.h'
--- a/include/mysql/service_thread_scheduler.h	1970-01-01 00:00:00 +0000
+++ b/include/mysql/service_thread_scheduler.h	2010-06-07 14:01:39 +0000
@@ -0,0 +1,65 @@
+/*
+  Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef SERVICE_THREAD_SCHEDULER_INCLUDED
+#define SERVICE_THREAD_SCHEDULER_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct scheduler_functions;
+
+extern struct my_thread_scheduler_service {
+  int (*set)(struct scheduler_functions *scheduler);
+  int (*reset)();
+} *my_thread_scheduler_service;
+
+#ifdef MYSQL_DYNAMIC_PLUGIN
+
+#define my_thread_scheduler_set(F) my_thread_scheduler_service->set((F))
+#define my_thread_scheduler_reset() my_thread_scheduler_service->reset()
+
+#else
+
+/**
+  Set the thread scheduler to use for the server.
+
+  @param scheduler Pointer to scheduler callbacks to use.
+  @retval 0 Scheduler installed correctly.
+  @retval 1 Invalid value (NULL) used for scheduler.
+*/
+int my_thread_scheduler_set(struct scheduler_functions *scheduler);
+
+/**
+  Restore the previous thread scheduler.
+
+  @note If no thread scheduler was installed previously with
+  thd_set_thread_scheduler, this function will report an error.
+
+  @retval 0 Scheduler installed correctly.
+  @retval 1 No scheduler installed.
+*/
+int my_thread_scheduler_reset();
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SERVICE_THREAD_SCHEDULER_INCLUDED */

=== modified file 'include/mysql/services.h'
--- a/include/mysql/services.h	2009-11-02 20:05:42 +0000
+++ b/include/mysql/services.h	2010-06-07 14:01:39 +0000
@@ -20,6 +20,8 @@ extern "C" {
 
 #include <mysql/service_my_snprintf.h>
 #include <mysql/service_thd_alloc.h>
+#include <mysql/service_thd_wait.h>
+#include <mysql/service_thread_scheduler.h>
 
 #ifdef __cplusplus
 }

=== modified file 'include/service_versions.h'
--- a/include/service_versions.h	2009-11-02 20:05:42 +0000
+++ b/include/service_versions.h	2010-06-07 14:01:39 +0000
@@ -21,4 +21,5 @@
 
 #define VERSION_my_snprintf     0x0100
 #define VERSION_thd_alloc       0x0100
-
+#define VERSION_thd_wait        0x0100
+#define VERSION_my_thread_scheduler 0x0100

=== modified file 'include/thr_lock.h'
--- a/include/thr_lock.h	2010-07-27 12:42:36 +0000
+++ b/include/thr_lock.h	2010-08-16 12:50:27 +0000
@@ -155,6 +155,8 @@ void    thr_downgrade_write_lock(THR_LOC
                                  enum thr_lock_type new_lock_type);
 my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data,
                                   ulong lock_wait_timeout);
+void thr_set_lock_wait_callback(void (*before_wait)(void),
+                                void (*after_wait)(void));
 #ifdef	__cplusplus
 }
 #endif

=== modified file 'include/violite.h'
--- a/include/violite.h	2010-04-13 15:04:45 +0000
+++ b/include/violite.h	2010-06-07 14:01:39 +0000
@@ -217,6 +217,7 @@ struct st_vio
   void	  (*timeout)(Vio*, unsigned int which, unsigned int timeout);
   my_bool (*poll_read)(Vio *vio, uint timeout);
   my_bool (*is_connected)(Vio*);
+  my_bool (*has_data) (Vio*);
 #ifdef HAVE_OPENSSL
   void	  *ssl_arg;
 #endif

=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am	2010-08-18 11:29:04 +0000
+++ b/libmysqld/Makefile.am	2010-09-01 03:38:53 +0000
@@ -1,21 +1,17 @@
-# Copyright (C) 2001-2006 MySQL AB
+# Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
 # 
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; version 2
-# of the License.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
 # 
-# This library is distributed in the hope that it will be useful,
+# This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Library General Public License for more details.
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
 # 
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the Free
-# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-# MA 02111-1307, USA
-#
-# This file is public domain and comes with NO WARRANTY of any kind
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
 MYSQLDATAdir =		$(localstatedir)
 MYSQLSHAREdir =		$(pkgdatadir)

=== modified file 'libservices/CMakeLists.txt'
--- a/libservices/CMakeLists.txt	2010-08-12 15:19:57 +0000
+++ b/libservices/CMakeLists.txt	2010-08-16 12:50:27 +0000
@@ -15,7 +15,11 @@
 
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
 
-SET(MYSQLSERVICES_SOURCES my_snprintf_service.c thd_alloc_service.c)
+SET(MYSQLSERVICES_SOURCES
+  my_snprintf_service.c
+  thd_alloc_service.c
+  thd_wait_service.c
+  my_thread_scheduler_service.c)
 
 ADD_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES})
 INSTALL(TARGETS mysqlservices DESTINATION ${INSTALL_LIBDIR})

=== modified file 'libservices/Makefile.am'
--- a/libservices/Makefile.am	2009-11-02 20:05:42 +0000
+++ b/libservices/Makefile.am	2010-06-07 14:01:39 +0000
@@ -15,5 +15,7 @@
 
 AM_CPPFLAGS =		-I$(top_srcdir)/include
 pkglib_LIBRARIES =	libmysqlservices.a
-libmysqlservices_a_SOURCES =  my_snprintf_service.c thd_alloc_service.c
+libmysqlservices_a_SOURCES =	my_snprintf_service.c thd_alloc_service.c \
+				thd_wait_service.c \
+				my_thread_scheduler_service.c
 EXTRA_DIST = CMakeLists.txt

=== added file 'libservices/my_thread_scheduler_service.c'
--- a/libservices/my_thread_scheduler_service.c	1970-01-01 00:00:00 +0000
+++ b/libservices/my_thread_scheduler_service.c	2010-06-07 14:01:39 +0000
@@ -0,0 +1,21 @@
+/*
+  Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA
+*/
+
+#include <service_versions.h>
+SERVICE_VERSION my_thread_scheduler_service=
+  (void*)VERSION_my_thread_scheduler;

=== added file 'libservices/thd_wait_service.c'
--- a/libservices/thd_wait_service.c	1970-01-01 00:00:00 +0000
+++ b/libservices/thd_wait_service.c	2010-06-07 14:01:39 +0000
@@ -0,0 +1,19 @@
+/*
+  Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <service_versions.h>
+SERVICE_VERSION *thd_wait_service= (void*)VERSION_thd_wait;

=== modified file 'mysql-test/CMakeLists.txt'
--- a/mysql-test/CMakeLists.txt	2010-08-19 12:11:31 +0000
+++ b/mysql-test/CMakeLists.txt	2010-09-02 22:17:08 +0000
@@ -13,6 +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
 
+IF(INSTALL_MYSQLTESTDIR)
 INSTALL(
  DIRECTORY .
  DESTINATION ${INSTALL_MYSQLTESTDIR}
@@ -28,6 +29,7 @@ INSTALL(
  PATTERN "*.am" EXCLUDE
  PATTERN "*.in" EXCLUDE
 )
+ENDIF()
 
 
 
@@ -48,9 +50,11 @@ IF(UNIX)
    ./mysql-test-run.pl mysql-test-run
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
   ) 
-  INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/mtr 
-    ${CMAKE_CURRENT_BINARY_DIR}/mysql-test-run 
-    DESTINATION ${INSTALL_MYSQLTESTDIR})
+  IF(INSTALL_MYSQLTESTDIR)
+    INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/mtr 
+      ${CMAKE_CURRENT_BINARY_DIR}/mysql-test-run 
+      DESTINATION ${INSTALL_MYSQLTESTDIR})
+  ENDIF()
 ENDIF()
 
 IF(CMAKE_GENERATOR MATCHES "Visual Studio")

=== added file 'mysql-test/include/not_blackhole.inc'
--- a/mysql-test/include/not_blackhole.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/not_blackhole.inc	2010-07-08 12:36:55 +0000
@@ -0,0 +1,5 @@
+if (`SELECT count(*) FROM information_schema.engines WHERE
+     (support = 'YES' OR support = 'DEFAULT') AND
+     engine = 'blackhole'`){
+  skip Blackhole engine enabled;
+}

=== modified file 'mysql-test/r/delete.result'
--- a/mysql-test/r/delete.result	2010-05-23 20:41:18 +0000
+++ b/mysql-test/r/delete.result	2010-08-30 22:22:01 +0000
@@ -499,4 +499,13 @@ INDEX(a), INDEX(b), INDEX(c));
 INSERT INTO t1 VALUES (1,2,3), (4,5,6), (7,8,9);
 DELETE FROM t1 WHERE a = 10 OR b = 20 ORDER BY c LIMIT 1;
 DROP TABLE t1;
+#
+# Bug #53034: Multiple-table DELETE statements not accepting
+#             "Access compatibility" syntax
+#
+CREATE TABLE t1 (id INT);
+CREATE TABLE t2 LIKE t1;
+CREATE TABLE t3 LIKE t1;
+DELETE FROM t1.*, test.t2.*, a.* USING t1, t2, t3 AS a;
+DROP TABLE t1, t2, t3;
 End of 5.1 tests

=== modified file 'mysql-test/r/func_gconcat.result'
--- a/mysql-test/r/func_gconcat.result	2010-04-03 17:35:51 +0000
+++ b/mysql-test/r/func_gconcat.result	2010-08-20 11:22:46 +0000
@@ -1003,6 +1003,7 @@ SELECT 1 FROM
 1
 1
 DROP TABLE t1;
+End of 5.0 tests
 #
 # Bug #52397: another crash with explain extended and group_concat
 #
@@ -1019,6 +1020,25 @@ Warnings:
 Note	1003	select 1 AS `1` from dual
 DROP TABLE t1;
 End of 5.0 tests
+#
+# Bug #54476: crash when group_concat and 'with rollup' in prepared statements
+# 
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+PREPARE stmt FROM "SELECT GROUP_CONCAT(t1.a ORDER BY t1.a) FROM t1 JOIN t1 t2 GROUP BY t1.a WITH ROLLUP";
+EXECUTE stmt;
+GROUP_CONCAT(t1.a ORDER BY t1.a)
+1,1
+2,2
+1,1,2,2
+EXECUTE stmt;
+GROUP_CONCAT(t1.a ORDER BY t1.a)
+1,1
+2,2
+1,1,2,2
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+End of 5.1 tests
 DROP TABLE IF EXISTS t1, t2;
 CREATE TABLE t1 (a VARCHAR(6), b INT);
 CREATE TABLE t2 (a VARCHAR(6), b INT);

=== modified file 'mysql-test/r/func_group.result'
--- a/mysql-test/r/func_group.result	2010-08-25 09:21:54 +0000
+++ b/mysql-test/r/func_group.result	2010-08-30 08:36:02 +0000
@@ -1713,6 +1713,17 @@ f1	f2	f3	f4	f1 = f2
 NULL	NULL	NULL	NULL	NULL
 drop table t1;
 #
+# Bug #54465: assert: field_types == 0 || field_types[field_pos] ==
+#             MYSQL_TYPE_LONGLONG
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+SELECT MAX((SELECT 1 FROM t1 ORDER BY @var LIMIT 1)) m FROM t1 t2, t1 
+ORDER BY t1.a;
+m
+1
+DROP TABLE t1;
+#
 End of 5.1 tests
 #
 # Bug#55648: Server crash on MIN/MAX on maximum time value

=== modified file 'mysql-test/r/func_misc.result'
--- a/mysql-test/r/func_misc.result	2010-04-07 09:59:02 +0000
+++ b/mysql-test/r/func_misc.result	2010-08-20 11:22:46 +0000
@@ -337,6 +337,21 @@ select connection_id() > 0;
 connection_id() > 0
 1
 #
+# Bug #54461: crash with longblob and union or update with subquery
+#
+CREATE TABLE t1 (a INT, b LONGBLOB);
+INSERT INTO t1 VALUES (1, '2'), (2, '3'), (3, '2');
+SELECT DISTINCT LEAST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1;
+LEAST(a, (SELECT b FROM t1 LIMIT 1))
+1
+2
+SELECT DISTINCT GREATEST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1;
+GREATEST(a, (SELECT b FROM t1 LIMIT 1))
+2
+3
+1
+DROP TABLE t1;
+#
 # Bug #52165: Assertion failed: file .\dtoa.c, line 465
 # 
 CREATE TABLE t1 (a SET('a'), b INT);

=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result	2010-02-24 13:52:27 +0000
+++ b/mysql-test/r/func_time.result	2010-08-16 07:11:57 +0000
@@ -1305,4 +1305,12 @@ date_sub("0069-01-01 00:00:01",INTERVAL 
 select date_sub("0169-01-01 00:00:01",INTERVAL 2 SECOND);
 date_sub("0169-01-01 00:00:01",INTERVAL 2 SECOND)
 0168-12-31 23:59:59
+CREATE TABLE t1(a DOUBLE NOT NULL);
+INSERT INTO t1 VALUES (0),(9.216e-096);
+# should not crash
+SELECT 1 FROM t1 ORDER BY @x:=makedate(a,a);
+1
+1
+1
+DROP TABLE t1;
 End of 5.1 tests

=== modified file 'mysql-test/r/mysqld--help-notwin.result'
--- a/mysql-test/r/mysqld--help-notwin.result	2010-08-28 16:36:17 +0000
+++ b/mysql-test/r/mysqld--help-notwin.result	2010-08-30 14:07:40 +0000
@@ -688,7 +688,7 @@ The following options may be given as th
  How many threads we should keep in a cache for reuse
  --thread-handling=name 
  Define threads usage for handling queries, one of
- one-thread-per-connection, no-threads
+ one-thread-per-connection, no-threads, loaded-dynamically
  --thread-stack=#    The stack size for each thread
  --time-format=name  The TIME format (ignored)
  --timed-mutexes     Specify whether to time mutexes (only InnoDB mutexes are

=== modified file 'mysql-test/r/mysqld--help-win.result'
--- a/mysql-test/r/mysqld--help-win.result	2010-08-28 16:36:17 +0000
+++ b/mysql-test/r/mysqld--help-win.result	2010-08-30 14:07:40 +0000
@@ -692,7 +692,7 @@ The following options may be given as th
  How many threads we should keep in a cache for reuse
  --thread-handling=name 
  Define threads usage for handling queries, one of
- one-thread-per-connection, no-threads
+ one-thread-per-connection, no-threads, loaded-dynamically
  --thread-stack=#    The stack size for each thread
  --time-format=name  The TIME format (ignored)
  --timed-mutexes     Specify whether to time mutexes (only InnoDB mutexes are

=== added file 'mysql-test/r/partition_not_blackhole.result'
--- a/mysql-test/r/partition_not_blackhole.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/partition_not_blackhole.result	2010-07-08 12:36:55 +0000
@@ -0,0 +1,16 @@
+DROP TABLE IF EXISTS t1;
+#
+# Bug#46086: crash when dropping a partitioned table and
+#            the original engine is disabled
+# Copy a .frm and .par file which was created with:
+# create table `t1` (`id` int primary key) engine=blackhole
+# partition by key () partitions 1;
+SHOW TABLES;
+Tables_in_test
+t1
+SHOW CREATE TABLE t1;
+ERROR HY000: Incorrect information in file: './test/t1.frm'
+DROP TABLE t1;
+ERROR 42S02: Unknown table 't1'
+t1.frm
+t1.par

=== modified file 'mysql-test/r/range.result'
--- a/mysql-test/r/range.result	2010-08-11 15:55:07 +0000
+++ b/mysql-test/r/range.result	2010-08-26 12:35:38 +0000
@@ -1653,4 +1653,17 @@ a	b
 0	0
 1	1
 DROP TABLE t1;
+#
+# Bug #54802: 'NOT BETWEEN' evaluation is incorrect
+#
+CREATE TABLE t1 (c_key INT, c_notkey INT, KEY(c_key));
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
+EXPLAIN SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	c_key	NULL	NULL	NULL	3	Using where
+SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key;
+c_key	c_notkey
+1	1
+3	3
+DROP TABLE t1;
 End of 5.1 tests

=== added file 'mysql-test/std_data/parts/t1_blackhole.frm'
Binary files a/mysql-test/std_data/parts/t1_blackhole.frm	1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/parts/t1_blackhole.frm	2010-07-08 12:36:55 +0000 differ

=== added file 'mysql-test/std_data/parts/t1_blackhole.par'
Binary files a/mysql-test/std_data/parts/t1_blackhole.par	1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/parts/t1_blackhole.par	2010-07-08 12:36:55 +0000 differ

=== modified file 'mysql-test/suite/innodb/r/innodb_mysql.result'
--- a/mysql-test/suite/innodb/r/innodb_mysql.result	2010-08-18 09:35:41 +0000
+++ b/mysql-test/suite/innodb/r/innodb_mysql.result	2010-08-30 08:36:02 +0000
@@ -2549,6 +2549,64 @@ LOCK TABLES t1 READ;
 ALTER TABLE t1 COMMENT 'test';
 UNLOCK TABLES;
 DROP TABLE t1;
+#
+# Bug#55656: mysqldump can be slower after bug #39653 fix
+#
+CREATE TABLE t1 (a INT , b INT, c INT, d INT,
+KEY (b), PRIMARY KEY (a,b)) ENGINE=INNODB;
+INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3);
+EXPLAIN SELECT COUNT(*) FROM t1;
+id	1
+select_type	SIMPLE
+table	t1
+type	index
+possible_keys	NULL
+key	b
+key_len	4
+ref	NULL
+rows	3
+Extra	Using index
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b);
+EXPLAIN SELECT COUNT(*) FROM t1;
+id	1
+select_type	SIMPLE
+table	t1
+type	index
+possible_keys	NULL
+key	b
+key_len	8
+ref	NULL
+rows	3
+Extra	Using index
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b,c);
+EXPLAIN SELECT COUNT(*) FROM t1;
+id	1
+select_type	SIMPLE
+table	t1
+type	index
+possible_keys	NULL
+key	b
+key_len	13
+ref	NULL
+rows	3
+Extra	Using index
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b,c,d);
+EXPLAIN SELECT COUNT(*) FROM t1;
+id	1
+select_type	SIMPLE
+table	t1
+type	index
+possible_keys	NULL
+key	PRIMARY
+key_len	8
+ref	NULL
+rows	3
+Extra	Using index
+DROP TABLE t1;
+#
 End of 5.1 tests
 #
 # Test for bug #39932 "create table fails if column for FK is in different

=== modified file 'mysql-test/suite/innodb/t/innodb_mysql.test'
--- a/mysql-test/suite/innodb/t/innodb_mysql.test	2010-08-16 06:46:21 +0000
+++ b/mysql-test/suite/innodb/t/innodb_mysql.test	2010-08-27 11:33:32 +0000
@@ -746,6 +746,31 @@ UNLOCK TABLES;
 
 DROP TABLE t1;
 
+--echo #
+--echo # Bug#55656: mysqldump can be slower after bug #39653 fix
+--echo #
+
+CREATE TABLE t1 (a INT , b INT, c INT, d INT,
+  KEY (b), PRIMARY KEY (a,b)) ENGINE=INNODB;
+INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3);
+--query_vertical EXPLAIN SELECT COUNT(*) FROM t1
+
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b);
+--query_vertical EXPLAIN SELECT COUNT(*) FROM t1
+
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b,c);
+--query_vertical EXPLAIN SELECT COUNT(*) FROM t1
+
+DROP INDEX b ON t1;
+CREATE INDEX b ON t1(a,b,c,d);
+--query_vertical EXPLAIN SELECT COUNT(*) FROM t1
+
+DROP TABLE t1;
+
+--echo #
+
 
 --echo End of 5.1 tests
 

=== modified file 'mysql-test/suite/rpl/r/rpl_flush_logs.result'
--- a/mysql-test/suite/rpl/r/rpl_flush_logs.result	2009-12-03 08:59:58 +0000
+++ b/mysql-test/suite/rpl/r/rpl_flush_logs.result	2010-08-30 09:09:28 +0000
@@ -4,12 +4,8 @@ reset master;
 reset slave;
 drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
 start slave;
-# Make sure the 'master_log.err-old' file does not
-# exist before execute 'flush error logs' statement.
 # Test if support 'flush error logs' statement.
 flush error logs;
-# Check the 'master_log.err-old' file is created
-# after executed 'flush error logs' statement.
 # Make sure binary logs was not be flushed
 # after execute 'flush error logs' statement.
 # Make sure relay logs was not be flushed 
@@ -42,12 +38,8 @@ flush binary logs;
 # after executed 'flush binary logs' statement.
 # Make sure the 'slave-relay-bin.000007' file does not exist
 # exist before execute 'flush error logs, relay logs' statement.
-# Make sure the 'master_log.err-old' file does not exist
-# before execute 'flush error logs, relay logs' statement.
 # Test if support to combine all kinds of logs into one statement.
 flush error logs, relay logs;
-# Check the 'master_log.err-old' file is created
-# after executed 'flush error logs, relay logs' statement.
 # Make sure binary logs was not be flushed
 # after execute 'flush error logs, relay logs' statement.
 # Check the 'slave-relay-bin.000007' file is created after
@@ -55,12 +47,8 @@ flush error logs, relay logs;
 # Make sure the 'slave-relay-bin.000008' and 'slave-relay-bin.000009' 
 # files do not exist before execute 'flush error logs, relay logs' 
 # statement.
-# Make sure the 'master_log.err-old' file does not exist
-# before execute 'flush logs' statement.
 # Test if 'flush logs' statement works fine and flush all the logs.
 flush logs;
-# Check the 'master_log.err-old' file is created
-# after executed 'flush logs' statement.
 # Check 'master-bin.000003' is created
 # after execute 'flush logs' statement.
 # Check the 'slave-relay-bin.000008' and 'slave-relay-bin.000009' 

=== modified file 'mysql-test/suite/rpl/t/rpl_drop.test'
--- a/mysql-test/suite/rpl/t/rpl_drop.test	2009-11-27 23:34:47 +0000
+++ b/mysql-test/suite/rpl/t/rpl_drop.test	2010-08-20 11:22:46 +0000
@@ -10,3 +10,4 @@ drop table t1, t2;
 sync_slave_with_master;
 
 # End of 4.1 tests
+

=== modified file 'mysql-test/suite/rpl/t/rpl_flush_logs.test'
--- a/mysql-test/suite/rpl/t/rpl_flush_logs.test	2009-12-03 08:59:58 +0000
+++ b/mysql-test/suite/rpl/t/rpl_flush_logs.test	2010-08-30 09:09:28 +0000
@@ -9,17 +9,10 @@
 connection master;
 
 # Test 'flush error logs' statement.
---echo # Make sure the 'master_log.err-old' file does not
---echo # exist before execute 'flush error logs' statement.
---error 1
-file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old;
 
 --echo # Test if support 'flush error logs' statement.
 flush error logs;
 
---echo # Check the 'master_log.err-old' file is created
---echo # after executed 'flush error logs' statement.
-file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old;
 file_exists $MYSQLTEST_VARDIR/tmp/master_log.err;
 
 --echo # Make sure binary logs was not be flushed
@@ -109,19 +102,10 @@ sync_slave_with_master;
 file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000007;
 
 connection master;
-remove_file $MYSQLTEST_VARDIR/tmp/master_log.err-old;
-
---echo # Make sure the 'master_log.err-old' file does not exist
---echo # before execute 'flush error logs, relay logs' statement.
---error 1
-file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old;
 
 --echo # Test if support to combine all kinds of logs into one statement.
 flush error logs, relay logs;
 
---echo # Check the 'master_log.err-old' file is created
---echo # after executed 'flush error logs, relay logs' statement.
-file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old;
 file_exists $MYSQLTEST_VARDIR/tmp/master_log.err;
 
 --echo # Make sure binary logs was not be flushed
@@ -145,19 +129,10 @@ file_exists $MYSQLTEST_VARDIR/mysqld.2/d
 file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000009;
 
 connection master;
-remove_file $MYSQLTEST_VARDIR/tmp/master_log.err-old;
-
---echo # Make sure the 'master_log.err-old' file does not exist
---echo # before execute 'flush logs' statement.
---error 1
-file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old;
 
 --echo # Test if 'flush logs' statement works fine and flush all the logs.
 flush logs;
 
---echo # Check the 'master_log.err-old' file is created
---echo # after executed 'flush logs' statement.
-file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old;
 file_exists $MYSQLTEST_VARDIR/tmp/master_log.err;
 
 --echo # Check 'master-bin.000003' is created

=== modified file 'mysql-test/t/delete.test'
--- a/mysql-test/t/delete.test	2010-05-23 20:41:18 +0000
+++ b/mysql-test/t/delete.test	2010-08-30 22:22:01 +0000
@@ -540,4 +540,17 @@ DELETE FROM t1 WHERE a = 10 OR b = 20 OR
 
 DROP TABLE t1;
 
+--echo #
+--echo # Bug #53034: Multiple-table DELETE statements not accepting
+--echo #             "Access compatibility" syntax
+--echo #
+
+CREATE TABLE t1 (id INT);
+CREATE TABLE t2 LIKE t1;
+CREATE TABLE t3 LIKE t1;
+
+DELETE FROM t1.*, test.t2.*, a.* USING t1, t2, t3 AS a;
+
+DROP TABLE t1, t2, t3;
+
 --echo End of 5.1 tests

=== modified file 'mysql-test/t/func_gconcat.test'
--- a/mysql-test/t/func_gconcat.test	2010-04-03 17:35:51 +0000
+++ b/mysql-test/t/func_gconcat.test	2010-08-20 11:22:46 +0000
@@ -708,6 +708,7 @@ SELECT 1 FROM
 
 DROP TABLE t1;
 
+--echo End of 5.0 tests
 
 --echo #
 --echo # Bug #52397: another crash with explain extended and group_concat
@@ -722,6 +723,26 @@ DROP TABLE t1;
 
 --echo End of 5.0 tests
 
+
+--echo #
+--echo # Bug #54476: crash when group_concat and 'with rollup' in prepared statements
+--echo # 
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+
+PREPARE stmt FROM "SELECT GROUP_CONCAT(t1.a ORDER BY t1.a) FROM t1 JOIN t1 t2 GROUP BY t1.a WITH ROLLUP";
+EXECUTE stmt;
+EXECUTE stmt;
+
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+
+
+--echo End of 5.1 tests
+
+
+
 #
 # Bug#36785: Wrong error message when group_concat() exceeds max length
 #

=== modified file 'mysql-test/t/func_group.test'
--- a/mysql-test/t/func_group.test	2010-08-25 09:21:54 +0000
+++ b/mysql-test/t/func_group.test	2010-08-30 08:36:02 +0000
@@ -1082,6 +1082,20 @@ select a.f1 as a, b.f4 as b, a.f1 > b.f4
 from t1 a, t1 b;
 select *, f1 = f2 from t1;
 drop table t1;
+
+--echo #
+--echo # Bug #54465: assert: field_types == 0 || field_types[field_pos] ==
+--echo #             MYSQL_TYPE_LONGLONG
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+
+SELECT MAX((SELECT 1 FROM t1 ORDER BY @var LIMIT 1)) m FROM t1 t2, t1 
+       ORDER BY t1.a;
+
+DROP TABLE t1;
+
 --echo #
 --echo End of 5.1 tests
 

=== modified file 'mysql-test/t/func_misc.test'
--- a/mysql-test/t/func_misc.test	2010-04-07 09:59:02 +0000
+++ b/mysql-test/t/func_misc.test	2010-08-20 11:22:46 +0000
@@ -468,6 +468,19 @@ select NAME_CONST('_id',1234) as id;
 select connection_id() > 0;
 
 --echo #
+--echo # Bug #54461: crash with longblob and union or update with subquery
+--echo #
+
+CREATE TABLE t1 (a INT, b LONGBLOB);
+INSERT INTO t1 VALUES (1, '2'), (2, '3'), (3, '2');
+
+SELECT DISTINCT LEAST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1;
+SELECT DISTINCT GREATEST(a, (SELECT b FROM t1 LIMIT 1)) FROM t1 UNION SELECT 1;
+
+DROP TABLE t1;
+
+
+--echo #
 --echo # Bug #52165: Assertion failed: file .\dtoa.c, line 465
 --echo # 
 
@@ -478,4 +491,5 @@ SELECT COALESCE(a) = COALESCE(b) FROM t1
 
 DROP TABLE t1;
 
+
 --echo End of tests

=== modified file 'mysql-test/t/func_time.test'
--- a/mysql-test/t/func_time.test	2010-02-17 09:18:17 +0000
+++ b/mysql-test/t/func_time.test	2010-08-16 07:11:57 +0000
@@ -821,4 +821,15 @@ select date_sub("0069-01-01 00:00:01",IN
 select date_sub("0169-01-01 00:00:01",INTERVAL 2 SECOND);
 
 
+#
+# Bug #55565: debug assertion when ordering by expressions with user
+# variable assignments
+#
+
+CREATE TABLE t1(a DOUBLE NOT NULL);
+INSERT INTO t1 VALUES (0),(9.216e-096);
+--echo # should not crash
+SELECT 1 FROM t1 ORDER BY @x:=makedate(a,a);
+DROP TABLE t1;
+
 --echo End of 5.1 tests

=== added file 'mysql-test/t/partition_not_blackhole-master.opt'
--- a/mysql-test/t/partition_not_blackhole-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/partition_not_blackhole-master.opt	2010-07-08 12:36:55 +0000
@@ -0,0 +1 @@
+--loose-skip-blackhole

=== added file 'mysql-test/t/partition_not_blackhole.test'
--- a/mysql-test/t/partition_not_blackhole.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/partition_not_blackhole.test	2010-08-20 19:17:51 +0000
@@ -0,0 +1,26 @@
+--source include/have_partition.inc
+--source include/not_blackhole.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+let $MYSQLD_DATADIR= `SELECT @@datadir`;
+
+--echo #
+--echo # Bug#46086: crash when dropping a partitioned table and
+--echo #            the original engine is disabled
+--echo # Copy a .frm and .par file which was created with:
+--echo # create table `t1` (`id` int primary key) engine=blackhole
+--echo # partition by key () partitions 1;
+--copy_file std_data/parts/t1_blackhole.frm $MYSQLD_DATADIR/test/t1.frm
+--copy_file std_data/parts/t1_blackhole.par $MYSQLD_DATADIR/test/t1.par
+SHOW TABLES;
+--replace_result $MYSQLD_DATADIR ./
+--error ER_NOT_FORM_FILE
+SHOW CREATE TABLE t1;
+--error ER_BAD_TABLE_ERROR
+DROP TABLE t1;
+--list_files $MYSQLD_DATADIR/test t1*
+--remove_file $MYSQLD_DATADIR/test/t1.frm
+--remove_file $MYSQLD_DATADIR/test/t1.par

=== modified file 'mysql-test/t/range.test'
--- a/mysql-test/t/range.test	2010-08-11 12:13:59 +0000
+++ b/mysql-test/t/range.test	2010-08-24 15:51:32 +0000
@@ -1313,4 +1313,16 @@ SELECT * FROM t1 FORCE INDEX (PRIMARY) 
 
 DROP TABLE t1;
 
+--echo #
+--echo # Bug #54802: 'NOT BETWEEN' evaluation is incorrect
+--echo #
+
+CREATE TABLE t1 (c_key INT, c_notkey INT, KEY(c_key));
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
+
+EXPLAIN SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key;
+SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key;
+
+DROP TABLE t1;
+
 --echo End of 5.1 tests

=== modified file 'mysys/my_getopt.c'
--- a/mysys/my_getopt.c	2010-08-26 14:34:18 +0000
+++ b/mysys/my_getopt.c	2010-09-02 01:13:24 +0000
@@ -163,7 +163,6 @@ int handle_options(int *argc, char ***ar
   int error, i;
   my_bool is_cmdline_arg= 1;
 
-  LINT_INIT(opt_found);
   /* handle_options() assumes arg0 (program name) always exists */
   DBUG_ASSERT(argc && *argc >= 1);
   DBUG_ASSERT(argv && *argv);
@@ -188,6 +187,7 @@ int handle_options(int *argc, char ***ar
   {
     char **first= pos;
     char *cur_arg= *pos;
+    opt_found= 0;
     if (!is_cmdline_arg && (cur_arg == args_separator))
     {
       is_cmdline_arg= 1;

=== modified file 'mysys/my_init.c'
--- a/mysys/my_init.c	2010-07-23 20:16:29 +0000
+++ b/mysys/my_init.c	2010-08-16 12:50:27 +0000
@@ -477,7 +477,7 @@ static my_bool win32_init_tcp_ip()
 {
   if (win32_have_tcpip())
   {
-    WORD wVersionRequested = MAKEWORD( 2, 0 );
+    WORD wVersionRequested = MAKEWORD( 2, 2 );
     WSADATA wsaData;
  	/* Be a good citizen: maybe another lib has already initialised
  		sockets, so dont clobber them unless necessary */

=== modified file 'mysys/thr_lock.c'
--- a/mysys/thr_lock.c	2010-08-06 11:29:37 +0000
+++ b/mysys/thr_lock.c	2010-08-30 14:07:40 +0000
@@ -91,6 +91,16 @@ enum thr_lock_type thr_upgraded_concurre
 LIST *thr_lock_thread_list;			/* List of threads in use */
 ulong max_write_lock_count= ~(ulong) 0L;
 
+static void (*before_lock_wait)(void)= 0;
+static void (*after_lock_wait)(void)= 0;
+
+void thr_set_lock_wait_callback(void (*before_wait)(void),
+                                void (*after_wait)(void))
+{
+  before_lock_wait= before_wait;
+  after_lock_wait= after_wait;
+}
+
 static inline mysql_cond_t *get_cond(void)
 {
   return &my_thread_var->suspend;
@@ -431,6 +441,19 @@ wait_for_lock(struct st_lock_list *wait,
   old_proc_info= proc_info_hook(NULL, "Waiting for table level lock",
                                 __func__, __FILE__, __LINE__);
 
+  /*
+    Since before_lock_wait potentially can create more threads to
+    scheduler work for, we don't want to call the before_lock_wait
+    callback unless it will really start to wait.
+
+    For similar reasons, we do not want to call before_lock_wait and
+    after_lock_wait for each lap around the loop, so we restrict
+    ourselves to call it before_lock_wait once before starting to wait
+    and once after the thread has exited the wait loop.
+   */
+  if ((!thread_var->abort || in_wait_list) && before_lock_wait)
+    (*before_lock_wait)();
+
   set_timespec(wait_timeout, lock_wait_timeout);
   while (!thread_var->abort || in_wait_list)
   {
@@ -462,6 +485,14 @@ wait_for_lock(struct st_lock_list *wait,
       /* purecov: end */
     }
   }
+
+  /*
+    We call the after_lock_wait callback once the wait loop has
+    finished.
+   */
+  if (after_lock_wait)
+    (*after_lock_wait)();
+
   DBUG_PRINT("thr_lock", ("aborted: %d  in_wait_list: %d",
                           thread_var->abort, in_wait_list));
 

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2010-08-18 11:29:04 +0000
+++ b/sql/CMakeLists.txt	2010-09-02 22:17:08 +0000
@@ -271,8 +271,7 @@ IF(WIN32 AND MYSQLD_EXECUTABLE)
      COMMAND ${CMAKE_COMMAND}
      ${CONFIG_PARAM} -P ${CMAKE_CURRENT_BINARY_DIR}/create_initial_db.cmake
      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data
-     COMMAND  ${CMAKE_COMMAND} -E touch initdb.dep
-     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+     COMMAND  ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/initdb.dep
      DEPENDS mysqld
   )
   ADD_CUSTOM_TARGET(initial_database  

=== modified file 'sql/authors.h'
--- a/sql/authors.h	2010-05-11 16:02:50 +0000
+++ b/sql/authors.h	2010-08-16 12:50:27 +0000
@@ -93,6 +93,7 @@ struct show_table_authors_st show_table_
   { "Arjen Lentz", "Brisbane, Australia",
     "Documentation (2001-2004), Dutch error messages, LOG2()" },
   { "Marc Liyanage", "", "Created Mac OS X packages" },
+  { "Kelly Long", "Denver, CO, USA", "Pool Of Threads" },
   { "Zarko Mocnik", "", "Sorting for Slovenian language" },
   { "Per-Erik Martin", "Uppsala, Sweden", "Stored Procedures (5.0)" },
   { "Alexis Mikhailov", "", "User-defined functions" },

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2010-07-23 20:09:27 +0000
+++ b/sql/ha_partition.cc	2010-08-19 08:22:23 +0000
@@ -2446,9 +2446,14 @@ bool ha_partition::get_from_handler_file
   tot_partition_words= (m_tot_parts + 3) / 4;
   engine_array= (handlerton **) my_alloca(m_tot_parts * sizeof(handlerton*));
   for (i= 0; i < m_tot_parts; i++)
+  {
     engine_array[i]= ha_resolve_by_legacy_type(ha_thd(),
                                                (enum legacy_db_type)
-                                               *(uchar *) ((file_buffer) + 12 + i));
+                                               *(uchar *) ((file_buffer) +
+                                                           12 + i));
+    if (!engine_array[i])
+      goto err3;
+  }
   address_tot_name_len= file_buffer + 12 + 4 * tot_partition_words;
   tot_name_words= (uint4korr(address_tot_name_len) + 3) / 4;
   if (len_words != (tot_partition_words + tot_name_words + 4))

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2010-08-19 11:55:35 +0000
+++ b/sql/item_func.cc	2010-08-25 10:22:34 +0000
@@ -2533,6 +2533,8 @@ void Item_func_min_max::fix_length_and_d
                                                                  decimals,
                                                                  unsigned_flag));
   }
+  else if (cmp_type == REAL_RESULT)
+    fix_char_length(float_length(decimals));
   cached_field_type= agg_field_type(args, arg_count);
 }
 

=== modified file 'sql/item_sum.cc'
--- a/sql/item_sum.cc	2010-07-19 17:11:47 +0000
+++ b/sql/item_sum.cc	2010-08-30 07:36:04 +0000
@@ -434,26 +434,6 @@ void Item_sum::mark_as_sum_func()
 }
 
 
-void Item_sum::make_field(Send_field *tmp_field)
-{
-  if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
-  {
-    ((Item_field*) args[0])->field->make_field(tmp_field);
-    /* For expressions only col_name should be non-empty string. */
-    char *empty_string= (char*)"";
-    tmp_field->db_name= empty_string;
-    tmp_field->org_table_name= empty_string;
-    tmp_field->table_name= empty_string;
-    tmp_field->org_col_name= empty_string;
-    tmp_field->col_name= name;
-    if (maybe_null)
-      tmp_field->flags&= ~NOT_NULL_FLAG;
-  }
-  else
-    init_make_field(tmp_field, field_type());
-}
-
-
 void Item_sum::print(String *str, enum_query_type query_type)
 {
   /* orig_args is not filled with valid values until fix_fields() */
@@ -984,7 +964,8 @@ bool Aggregator_distinct::add()
   {
     int error;
     copy_fields(tmp_table_param);
-    copy_funcs(tmp_table_param->items_to_copy);
+    if (copy_funcs(tmp_table_param->items_to_copy, table->in_use))
+      return TRUE;
 
     for (Field **field=table->field ; *field ; field++)
       if ((*field)->is_real_null(0))
@@ -3058,7 +3039,6 @@ Item_func_group_concat::Item_func_group_
   tree(item->tree),
   unique_filter(item->unique_filter),
   table(item->table),
-  order(item->order),
   context(item->context),
   arg_count_order(item->arg_count_order),
   arg_count_field(item->arg_count_field),
@@ -3071,6 +3051,24 @@ Item_func_group_concat::Item_func_group_
 {
   quick_group= item->quick_group;
   result.set_charset(collation.collation);
+
+  /*
+    Since the ORDER structures pointed to by the elements of the 'order' array
+    may be modified in find_order_in_list() called from
+    Item_func_group_concat::setup(), create a copy of those structures so that
+    such modifications done in this object would not have any effect on the
+    object being copied.
+  */
+  ORDER *tmp;
+  if (!(order= (ORDER **) thd->alloc(sizeof(ORDER *) * arg_count_order +
+                                     sizeof(ORDER) * arg_count_order)))
+    return;
+  tmp= (ORDER *)(order + arg_count_order);
+  for (uint i= 0; i < arg_count_order; i++, tmp++)
+  {
+    memcpy(tmp, item->order[i], sizeof(ORDER));
+    order[i]= tmp;
+  }
 }
 
 
@@ -3136,7 +3134,8 @@ bool Item_func_group_concat::add()
   if (always_null)
     return 0;
   copy_fields(tmp_table_param);
-  copy_funcs(tmp_table_param->items_to_copy);
+  if (copy_funcs(tmp_table_param->items_to_copy, table->in_use))
+    return TRUE;
 
   for (uint i= 0; i < arg_count_field; i++)
   {

=== modified file 'sql/item_sum.h'
--- a/sql/item_sum.h	2010-07-19 17:11:47 +0000
+++ b/sql/item_sum.h	2010-08-30 07:36:04 +0000
@@ -427,7 +427,6 @@ public:  
     forced_const= TRUE; 
   }
   virtual bool const_item() const { return forced_const; }
-  void make_field(Send_field *field);
   virtual void print(String *str, enum_query_type query_type);
   void fix_num_length_and_dec();
 

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2010-08-20 02:59:58 +0000
+++ b/sql/log.cc	2010-08-30 08:36:02 +0000
@@ -5447,70 +5447,93 @@ void sql_perror(const char *message)
 }
 
 
+#ifdef __WIN__
+extern "C" my_bool reopen_fstreams(const char *filename,
+                                   FILE *outstream, FILE *errstream)
+{
+  int handle_fd;
+  int stream_fd;
+  HANDLE osfh;
+
+  DBUG_ASSERT(filename && (outstream || errstream));
+
+  if ((osfh= CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE |
+                        FILE_SHARE_DELETE, NULL,
+                        OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+                        NULL)) == INVALID_HANDLE_VALUE)
+    return TRUE;
+
+  if ((handle_fd= _open_osfhandle((intptr_t)osfh,
+                                  _O_APPEND | _O_TEXT)) == -1)
+  {
+    CloseHandle(osfh);
+    return TRUE;
+  }
+
+  if (outstream)
+  {
+    stream_fd= _fileno(outstream);
+    if (_dup2(handle_fd, stream_fd) < 0)
+    {
+      CloseHandle(osfh);
+      return TRUE;
+    }
+  }
+
+  if (errstream)
+  {
+    stream_fd= _fileno(errstream);
+    if (_dup2(handle_fd, stream_fd) < 0)
+    {
+      CloseHandle(osfh);
+      return TRUE;
+    }
+  }
+
+  _close(handle_fd);
+  return FALSE;
+}
+#else
+extern "C" my_bool reopen_fstreams(const char *filename,
+                                   FILE *outstream, FILE *errstream)
+{
+  if (outstream && !freopen(filename, "a+", outstream))
+    return TRUE;
+
+  if (errstream && !freopen(filename, "a+", errstream))
+    return TRUE;
+
+  return FALSE;
+}
+#endif
+
+
 /*
   Unfortunately, there seems to be no good way
   to restore the original streams upon failure.
 */
 static bool redirect_std_streams(const char *file)
 {
-  if (freopen(file, "a+", stdout) && freopen(file, "a+", stderr))
-  {
-    setbuf(stderr, NULL);
-    return FALSE;
-  }
+  if (reopen_fstreams(file, stdout, stderr))
+    return TRUE;
 
-  return TRUE;
+  setbuf(stderr, NULL);
+  return FALSE;
 }
 
 
 bool flush_error_log()
 {
-  bool result=0;
+  bool result= 0;
   if (opt_error_log)
   {
-    char err_renamed[FN_REFLEN], *end;
-    end= strmake(err_renamed,log_error_file,FN_REFLEN-5);
-    strmov(end, "-old");
     mysql_mutex_lock(&LOCK_error_log);
-#ifdef __WIN__
-    char err_temp[FN_REFLEN+5];
-    /*
-     On Windows is necessary a temporary file for to rename
-     the current error file.
-    */
-    strxmov(err_temp, err_renamed,"-tmp",NullS);
-    my_delete(err_temp, MYF(0));
-    if (freopen(err_temp,"a+",stdout))
-    {
-      int fd;
-      size_t bytes;
-      uchar buf[IO_SIZE];
-
-      freopen(err_temp,"a+",stderr);
-      setbuf(stderr, NULL);
-      my_delete(err_renamed, MYF(0));
-      my_rename(log_error_file, err_renamed, MYF(0));
-      redirect_std_streams(log_error_file);
-
-      if ((fd= my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
-      {
-        while ((bytes= mysql_file_read(fd, buf, IO_SIZE, MYF(0))) &&
-               bytes != MY_FILE_ERROR)
-          my_fwrite(stderr, buf, bytes, MYF(0));
-        mysql_file_close(fd, MYF(0));
-      }
-      my_delete(err_temp, MYF(0));
-    }
-    else
-     result= 1;
-#else
-   my_rename(log_error_file, err_renamed, MYF(0));
-   if (redirect_std_streams(log_error_file))
-     result= 1;
-#endif
+    if (redirect_std_streams(log_error_file))
+      result= 1;
     mysql_mutex_unlock(&LOCK_error_log);
   }
-   return result;
+  return result;
 }
 
 void MYSQL_BIN_LOG::signal_update()

=== modified file 'sql/log.h'
--- a/sql/log.h	2010-07-23 20:13:36 +0000
+++ b/sql/log.h	2010-08-20 11:22:46 +0000
@@ -394,10 +394,10 @@ public:
   /* Use this to start writing a new log file */
   void new_file();
 
-  bool write(Log_event* event_info);
+  bool write(Log_event* event_info); // binary log write
   bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
-  bool write_incident(THD *thd, bool lock);
 
+  bool write_incident(THD *thd, bool lock);
   int  write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
   void set_write_error(THD *thd);
   bool check_write_error(THD *thd);

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2010-08-25 19:00:38 +0000
+++ b/sql/mysqld.cc	2010-08-30 14:07:40 +0000
@@ -64,7 +64,9 @@
 #include "events.h"
 #include "sql_audit.h"
 #include "probes_mysql.h"
+#include "scheduler.h"
 #include "debug_sync.h"
+#include "sql_callback.h"
 
 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
 #include "../storage/perfschema/pfs_server.h"
@@ -193,6 +195,9 @@ typedef fp_except fp_except_t;
 # endif
 #endif
 
+extern "C" my_bool reopen_fstreams(const char *filename,
+                                   FILE *outstream, FILE *errstream);
+
 inline void setup_fpu()
 {
 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
@@ -456,7 +461,7 @@ ulong slave_trans_retries;
 uint  slave_net_timeout;
 ulong slave_exec_mode_options;
 ulonglong slave_type_conversions_options;
-ulong thread_cache_size=0, thread_pool_size= 0;
+ulong thread_cache_size=0;
 ulong binlog_cache_size=0;
 ulonglong  max_binlog_cache_size=0;
 ulong query_cache_size=0;
@@ -898,8 +903,6 @@ my_bool opt_enable_shared_memory;
 HANDLE smem_event_connect_request= 0;
 #endif
 
-scheduler_functions thread_scheduler;
-
 my_bool opt_use_ssl  = 0;
 char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
      *opt_ssl_cipher= NULL, *opt_ssl_key= NULL;
@@ -1087,7 +1090,8 @@ static void close_connections(void)
       continue;
 
     tmp->killed= THD::KILL_CONNECTION;
-    thread_scheduler.post_kill_notification(tmp);
+    MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp));
+    mysql_mutex_lock(&tmp->LOCK_thd_data);
     if (tmp->mysys_var)
     {
       tmp->mysys_var->abort=1;
@@ -1100,6 +1104,7 @@ static void close_connections(void)
       }
       mysql_mutex_unlock(&tmp->mysys_var->mutex);
     }
+    mysql_mutex_unlock(&tmp->LOCK_thd_data);
   }
   mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list
 
@@ -1479,7 +1484,7 @@ void clean_up(bool print_message)
   if (print_message && my_default_lc_messages && server_start_time)
     sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname);
   cleanup_errmsgs();
-  thread_scheduler.end();
+  MYSQL_CALLBACK(thread_scheduler, end, ());
   finish_client_errs();
   DBUG_PRINT("quit", ("Error messages freed"));
   /* Tell main we are ready */
@@ -1752,7 +1757,7 @@ static void network_init(void)
   DBUG_ENTER("network_init");
   LINT_INIT(ret);
 
-  if (thread_scheduler.init())
+  if (MYSQL_CALLBACK_ELSE(thread_scheduler, init, (), 0))
     unireg_abort(1);			/* purecov: inspected */
 
   set_ports();
@@ -2000,7 +2005,7 @@ extern "C" sig_handler end_thread_signal
   if (thd && ! thd->bootstrap)
   {
     statistic_increment(killed_threads, &LOCK_status);
-    thread_scheduler.end_thread(thd,0);		/* purecov: inspected */
+    MYSQL_CALLBACK(thread_scheduler, end_thread, (thd,0)); /* purecov: inspected */
   }
   DBUG_VOID_RETURN;				/* purecov: deadcode */
 }
@@ -2396,7 +2401,7 @@ and this may fail.\n\n");
           (ulong) dflt_key_cache->key_cache_mem_size);
   fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
   fprintf(stderr, "max_used_connections=%lu\n", max_used_connections);
-  fprintf(stderr, "max_threads=%u\n", thread_scheduler.max_threads);
+  fprintf(stderr, "max_threads=%u\n", thread_scheduler->max_threads);
   fprintf(stderr, "thread_count=%u\n", thread_count);
   fprintf(stderr, "connection_count=%u\n", connection_count);
   fprintf(stderr, "It is possible that mysqld could use up to \n\
@@ -2404,7 +2409,7 @@ key_buffer_size + (read_buffer_size + so
 bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size +
 		     (global_system_variables.read_buff_size +
 		      global_system_variables.sortbuff_size) *
-		     thread_scheduler.max_threads +
+		     thread_scheduler->max_threads +
                      max_connections * sizeof(THD)) / 1024);
   fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
 
@@ -2651,7 +2656,7 @@ pthread_handler_t signal_hand(void *arg 
     This should actually be '+ max_number_of_slaves' instead of +10,
     but the +10 should be quite safe.
   */
-  init_thr_alarm(thread_scheduler.max_threads +
+  init_thr_alarm(thread_scheduler->max_threads +
 		 global_system_variables.max_insert_delayed_threads + 10);
   if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
   {
@@ -3738,13 +3743,15 @@ static int init_server_components()
       opt_error_log= 0;                         // Too long file name
     else
     {
+      my_bool res;
 #ifndef EMBEDDED_LIBRARY
-      if (freopen(log_error_file, "a+", stdout))
+      res= reopen_fstreams(log_error_file, stdout, stderr);
+#else
+      res= reopen_fstreams(log_error_file, NULL, stderr);
 #endif
-      {
-        if (freopen(log_error_file, "a+", stderr))
-          setbuf(stderr, NULL);
-      }
+
+      if (!res)
+        setbuf(stderr, NULL);
     }
   }
 
@@ -4353,23 +4360,6 @@ int mysqld_main(int argc, char **argv)
   }
 #endif
 
-#ifdef	__WIN__
-  /*
-    Before performing any socket operation (like retrieving hostname
-    in init_common_variables we have to call WSAStartup
-  */
-  {
-    WSADATA WsaData;
-    if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
-    {
-      /* errors are not read yet, so we use english text here */
-      my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0));
-      /* Not enough initializations for unireg_abort() */
-      return 1;
-    }
-  }
-#endif /* __WIN__ */
-
   if (init_common_variables())
     unireg_abort(1);				// Will do exit
 
@@ -4457,8 +4447,8 @@ int mysqld_main(int argc, char **argv)
 #ifdef __WIN__
   if (!opt_console)
   {
-    freopen(log_error_file,"a+",stdout);
-    freopen(log_error_file,"a+",stderr);
+    if (reopen_fstreams(log_error_file, stdout, stderr))
+      unireg_abort(1);
     setbuf(stderr, NULL);
     FreeConsole();				// Remove window
   }
@@ -5028,7 +5018,7 @@ static void create_new_thread(THD *thd)
 
   thread_count++;
 
-  thread_scheduler.add_connection(thd);
+  MYSQL_CALLBACK(thread_scheduler, add_connection, (thd));
 
   DBUG_VOID_RETURN;
 }
@@ -7344,14 +7334,12 @@ static int get_options(int *argc_ptr, ch
     return 1;
 
 #ifdef EMBEDDED_LIBRARY
-  one_thread_scheduler(&thread_scheduler);
+  one_thread_scheduler();
 #else
   if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION)
-    one_thread_per_connection_scheduler(&thread_scheduler);
-  else if (thread_handling == SCHEDULER_NO_THREADS)
-    one_thread_scheduler(&thread_scheduler);
-  else
-    pool_of_threads_scheduler(&thread_scheduler);  /* purecov: tested */
+    one_thread_per_connection_scheduler();
+  else                  /* thread_handling == SCHEDULER_NO_THREADS) */
+    one_thread_scheduler();
 #endif
 
   global_system_variables.engine_condition_pushdown=

=== modified file 'sql/mysqld.h'
--- a/sql/mysqld.h	2010-08-18 11:29:04 +0000
+++ b/sql/mysqld.h	2010-08-30 14:07:40 +0000
@@ -28,7 +28,7 @@ class THD;
 struct handlerton;
 class Time_zone;
 
-class scheduler_functions;
+struct scheduler_functions;
 
 typedef struct st_mysql_const_lex_string LEX_CSTRING;
 typedef struct st_mysql_show_var SHOW_VAR;
@@ -175,7 +175,7 @@ extern ulong binlog_cache_size, open_fil
 extern ulonglong max_binlog_cache_size;
 extern ulong max_binlog_size, max_relay_log_size;
 extern ulong opt_binlog_rows_event_max_size;
-extern ulong rpl_recovery_rank, thread_cache_size, thread_pool_size;
+extern ulong rpl_recovery_rank, thread_cache_size;
 extern ulong back_log;
 extern char language[FN_REFLEN];
 extern ulong server_id, concurrency;
@@ -207,7 +207,7 @@ extern my_bool old_mode;
 extern LEX_STRING opt_init_connect, opt_init_slave;
 extern int bootstrap_error;
 extern I_List<THD> threads;
-extern scheduler_functions thread_scheduler;
+extern char err_shared_dir[];
 extern TYPELIB thread_handling_typelib;
 extern my_decimal decimal_zero;
 

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2010-07-15 13:47:50 +0000
+++ b/sql/opt_range.cc	2010-08-26 12:35:38 +0000
@@ -5620,7 +5620,11 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_P
         SEL_TREE *tmp= get_full_func_mm_tree(param, cond_func, 
                                     field_item, (Item*)(intptr)i, inv);
         if (inv)
+        {
           tree= !tree ? tmp : tree_or(param, tree, tmp);
+          if (tree == NULL)
+            break;
+        }
         else 
           tree= tree_and(param, tree, tmp);
       }

=== modified file 'sql/scheduler.cc'
--- a/sql/scheduler.cc	2010-03-31 14:05:33 +0000
+++ b/sql/scheduler.cc	2010-06-15 07:44:26 +0000
@@ -25,55 +25,103 @@
 #include "unireg.h"                    // REQUIRED: for other includes
 #include "scheduler.h"
 #include "sql_connect.h"         // init_new_connection_handler_thread
+#include "scheduler.h"
+#include "sql_callback.h"
 
 /*
-  'Dummy' functions to be used when we don't need any handling for a scheduler
-  event
- */
+  End connection, in case when we are using 'no-threads'
+*/
 
-static bool init_dummy(void) {return 0;}
-static void post_kill_dummy(THD* thd) {}  
-static void end_dummy(void) {}
-static bool end_thread_dummy(THD *thd, bool cache_thread) { return 0; }
+static bool no_threads_end(THD *thd, bool put_in_cache)
+{
+  unlink_thd(thd);
+  mysql_mutex_unlock(&LOCK_thread_count);
+  return 1;                                     // Abort handle_one_connection
+}
 
-/*
-  Initialize default scheduler with dummy functions so that setup functions
-  only need to declare those that are relvant for their usage
+static scheduler_functions one_thread_scheduler_functions=
+{
+  1,                                     // max_threads
+  NULL,                                  // init
+  init_new_connection_handler_thread,    // init_new_connection_thread
+#ifndef EMBEDDED_LIBRARY
+  handle_connection_in_main_thread,      // add_connection
+#else
+  NULL,                                  // add_connection
+#endif // EMBEDDED_LIBRARY
+  NULL,                                  // thd_wait_begin
+  NULL,                                  // thd_wait_end
+  NULL,                                  // post_kill_notification
+  no_threads_end,                        // end_thread
+  NULL,                                  // end
+};
+
+#ifndef EMBEDDED_LIBRARY
+static scheduler_functions one_thread_per_connection_scheduler_functions=
+{
+  0,                                     // max_threads
+  NULL,                                  // init
+  init_new_connection_handler_thread,    // init_new_connection_thread
+  create_thread_to_handle_connection,    // add_connection
+  NULL,                                  // thd_wait_begin
+  NULL,                                  // thd_wait_end
+  NULL,                                  // post_kill_notification
+  one_thread_per_connection_end,         // end_thread
+  NULL,                                  // end
+};
+#endif  // EMBEDDED_LIBRARY
+
+
+scheduler_functions *thread_scheduler= NULL;
+
+/** @internal
+  Helper functions to allow mysys to call the thread scheduler when
+  waiting for locks.
 */
 
-scheduler_functions::scheduler_functions()
-  :init(init_dummy),
-   init_new_connection_thread(init_new_connection_handler_thread),
-   add_connection(0),                           // Must be defined
-   post_kill_notification(post_kill_dummy),
-   end_thread(end_thread_dummy), end(end_dummy)
-{}
+/**@{*/
+static void scheduler_wait_begin(void) {
+  MYSQL_CALLBACK(thread_scheduler,
+                 thd_wait_begin, (current_thd, THD_WAIT_ROW_TABLE_LOCK));
+}
+
+static void scheduler_wait_end(void) {
+  MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd));
+}
+/**@}*/
 
+/**
+  Common scheduler init function.
+
+  The scheduler is either initialized by calling
+  one_thread_scheduler() or one_thread_per_connection_scheduler() in
+  mysqld.cc, so this init function will always be called.
+ */
+static void scheduler_init() {
+  thr_set_lock_wait_callback(scheduler_wait_begin, scheduler_wait_end);
+}
 
 /*
-  End connection, in case when we are using 'no-threads'
+  Initialize scheduler for --thread-handling=one-thread-per-connection
 */
 
-static bool no_threads_end(THD *thd, bool put_in_cache)
+#ifndef EMBEDDED_LIBRARY
+void one_thread_per_connection_scheduler()
 {
-  unlink_thd(thd);
-  mysql_mutex_unlock(&LOCK_thread_count);
-  return 1;                                     // Abort handle_one_connection
+  scheduler_init();
+  one_thread_per_connection_scheduler_functions.max_threads= max_connections;
+  thread_scheduler= &one_thread_per_connection_scheduler_functions;
 }
-
+#endif
 
 /*
   Initailize scheduler for --thread-handling=no-threads
 */
 
-void one_thread_scheduler(scheduler_functions* func)
+void one_thread_scheduler()
 {
-  func->max_threads= 1;
-#ifndef EMBEDDED_LIBRARY
-  func->add_connection= handle_connection_in_main_thread;
-#endif
-  func->init_new_connection_thread= init_dummy;
-  func->end_thread= no_threads_end;
+  scheduler_init();
+  thread_scheduler= &one_thread_scheduler_functions;
 }
 
 
@@ -81,11 +129,58 @@ void one_thread_scheduler(scheduler_func
   Initialize scheduler for --thread-handling=one-thread-per-connection
 */
 
-#ifndef EMBEDDED_LIBRARY
-void one_thread_per_connection_scheduler(scheduler_functions* func)
+/*
+  thd_scheduler keeps the link between THD and events.
+  It's embedded in the THD class.
+*/
+
+thd_scheduler::thd_scheduler()
+  : m_psi(NULL), data(NULL)
+{
+#ifndef DBUG_OFF
+  dbug_explain[0]= '\0';
+  set_explain= FALSE;
+#endif
+}
+
+
+thd_scheduler::~thd_scheduler()
+{
+}
+
+static scheduler_functions *saved_thread_scheduler;
+static uint saved_thread_handling;
+
+extern "C"
+int my_thread_scheduler_set(scheduler_functions *scheduler)
+{
+  DBUG_ASSERT(scheduler != 0);
+
+  if (scheduler == NULL)
+    return 1;
+
+  saved_thread_scheduler= thread_scheduler;
+  saved_thread_handling= thread_handling;
+  thread_scheduler= scheduler;
+  // Scheduler loaded dynamically
+  thread_handling= SCHEDULER_TYPES_COUNT;
+  return 0;
+}
+
+
+extern "C"
+int my_thread_scheduler_reset()
 {
-  func->max_threads= max_connections;
-  func->add_connection= create_thread_to_handle_connection;
-  func->end_thread= one_thread_per_connection_end;
+  DBUG_ASSERT(saved_thread_scheduler != NULL);
+
+  if (saved_thread_scheduler == NULL)
+    return 1;
+
+  thread_scheduler= saved_thread_scheduler;
+  thread_handling= saved_thread_handling;
+  saved_thread_scheduler= 0;
+  return 0;
 }
-#endif /* EMBEDDED_LIBRARY */
+
+
+

=== modified file 'sql/scheduler.h'
--- a/sql/scheduler.h	2009-09-23 21:32:31 +0000
+++ b/sql/scheduler.h	2010-06-07 14:01:39 +0000
@@ -28,38 +28,77 @@ class THD;
 
 /* Functions used when manipulating threads */
 
-class scheduler_functions
+struct scheduler_functions
 {
-public:
   uint max_threads;
   bool (*init)(void);
   bool (*init_new_connection_thread)(void);
   void (*add_connection)(THD *thd);
+  void (*thd_wait_begin)(THD *thd, int wait_type);
+  void (*thd_wait_end)(THD *thd);
   void (*post_kill_notification)(THD *thd);
   bool (*end_thread)(THD *thd, bool cache_thread);
   void (*end)(void);
-  scheduler_functions();
 };
 
+
+/**
+  Scheduler types enumeration.
+
+  The default of --thread-handling is the first one in the
+  thread_handling_names array, this array has to be consistent with
+  the order in this array, so to change default one has to change the
+  first entry in this enum and the first entry in the
+  thread_handling_names array.
+
+  @note The last entry of the enumeration is also used to mark the
+  thread handling as dynamic. In this case the name of the thread
+  handling is fetched from the name of the plugin that implements it.
+*/
 enum scheduler_types
 {
   SCHEDULER_ONE_THREAD_PER_CONNECTION=0,
   SCHEDULER_NO_THREADS,
-  SCHEDULER_POOL_OF_THREADS
+  SCHEDULER_TYPES_COUNT
 };
 
-void one_thread_per_connection_scheduler(scheduler_functions* func);
-void one_thread_scheduler(scheduler_functions* func);
+void one_thread_per_connection_scheduler();
+void one_thread_scheduler();
 
 enum pool_command_op
 {
   NOT_IN_USE_OP= 0, NORMAL_OP= 1, CONNECT_OP, KILL_OP, DIE_OP
 };
 
-#define HAVE_POOL_OF_THREADS 0                  /* For easyer tests */
-#define pool_of_threads_scheduler(A) one_thread_per_connection_scheduler(A)
-
+/*
+ To be used for pool-of-threads (implemeneted differently on various OSs)
+*/
 class thd_scheduler
-{};
+{
+public:
+  /*
+    Thread instrumentation for the user job.
+    This member holds the instrumentation while the user job is not run
+    by a thread.
+
+    Note that this member is not conditionally declared
+    (ifdef HAVE_PSI_INTERFACE), because doing so will change the binary
+    layout of THD, which is exposed to plugin code that may be compiled
+    differently.
+  */
+  PSI_thread *m_psi;
+
+  void *data;                  /* scheduler-specific data structure */
+
+#  ifndef DBUG_OFF
+  char dbug_explain[512];
+  bool set_explain;
+#  endif
+
+  thd_scheduler();
+  ~thd_scheduler();
+};
+
+extern scheduler_functions *thread_scheduler;
 
-#endif /* SCHEDULER_INCLUDED */
+#endif

=== added file 'sql/sql_callback.h'
--- a/sql/sql_callback.h	1970-01-01 00:00:00 +0000
+++ b/sql/sql_callback.h	2010-06-07 14:01:39 +0000
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved.
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef SQL_CALLBACK_INCLUDED
+#define SQL_CALLBACK_INCLUDED
+
+/**
+   Macro used for an internal callback.
+
+   The macro will check that the object exists and that the function
+   is defined. If that is the case, it will call the function with the
+   given parameters.
+
+   If the object or the function is not defined, the callback will be
+   considered successful (nothing needed to be done) and will
+   therefore return no error.
+ */
+
+#define MYSQL_CALLBACK(OBJ, FUNC, PARAMS)         \
+  do {                                            \
+    if ((OBJ) && ((OBJ)->FUNC))                   \
+      (OBJ)->FUNC PARAMS;                         \
+  } while (0)
+
+#define MYSQL_CALLBACK_ELSE(OBJ, FUNC, PARAMS, ELSE)    \
+  (((OBJ) && ((OBJ)->FUNC)) ? (OBJ)->FUNC PARAMS : (ELSE))
+
+
+#endif /* SQL_CALLBACK_INCLUDED */

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2010-08-20 02:59:58 +0000
+++ b/sql/sql_class.cc	2010-08-30 14:07:40 +0000
@@ -57,6 +57,7 @@
 #include "transaction.h"
 #include "debug_sync.h"
 #include "sql_parse.h"                          // is_update_query
+#include "sql_callback.h"
 
 /*
   The following is used to initialise Table_ident with a internal
@@ -1075,6 +1076,7 @@ THD::~THD()
   DBUG_ENTER("~THD()");
   /* Ensure that no one is using THD */
   mysql_mutex_lock(&LOCK_thd_data);
+  mysys_var=0;					// Safety (shouldn't be needed)
   mysql_mutex_unlock(&LOCK_thd_data);
   add_to_status(&global_status_var, &status_var);
 
@@ -1100,7 +1102,6 @@ THD::~THD()
   my_free(db);
   db= NULL;
   free_root(&transaction.mem_root,MYF(0));
-  mysys_var=0;					// Safety (shouldn't be needed)
   mysql_mutex_destroy(&LOCK_thd_data);
 #ifndef DBUG_OFF
   dbug_sentry= THD_SENTRY_GONE;
@@ -1189,7 +1190,7 @@ void THD::awake(THD::killed_state state_
   {
     thr_alarm_kill(thread_id);
     if (!slave_thread)
-      thread_scheduler.post_kill_notification(this);
+      MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (this));
 #ifdef SIGNAL_WITH_VIO_CLOSE
     if (this != current_thd)
     {
@@ -1258,6 +1259,15 @@ bool THD::store_globals()
   if (my_pthread_setspecific_ptr(THR_THD,  this) ||
       my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
     return 1;
+  /*
+    mysys_var is concurrently readable by a killer thread.
+    It is protected by LOCK_thd_data, it is not needed to lock while the
+    pointer is changing from NULL not non-NULL. If the kill thread reads
+    NULL it doesn't refer to anything, but if it is non-NULL we need to
+    ensure that the thread doesn't proceed to assign another thread to
+    have the mysys_var reference (which in fact refers to the worker
+    threads local storage with key THR_KEY_mysys. 
+  */
   mysys_var=my_thread_var;
   /*
     Let mysqld define the thread id (not mysys)
@@ -3187,6 +3197,60 @@ extern "C" bool thd_sqlcom_can_generate_
 {
   return sqlcom_can_generate_row_events(thd);
 }
+
+#ifndef EMBEDDED_LIBRARY
+extern "C" void thd_pool_wait_begin(MYSQL_THD thd, int wait_type);
+extern "C" void thd_pool_wait_end(MYSQL_THD thd);
+
+/*
+  Interface for MySQL Server, plugins and storage engines to report
+  when they are going to sleep/stall.
+  
+  SYNOPSIS
+  thd_wait_begin()
+  thd                     Thread object
+  wait_type               Type of wait
+                          1 -- short wait (e.g. for mutex)
+                          2 -- medium wait (e.g. for disk io)
+                          3 -- large wait (e.g. for locked row/table)
+  NOTES
+    This is used by the threadpool to have better knowledge of which
+    threads that currently are actively running on CPUs. When a thread
+    reports that it's going to sleep/stall, the threadpool scheduler is
+    free to start another thread in the pool most likely. The expected wait
+    time is simply an indication of how long the wait is expected to
+    become, the real wait time could be very different.
+
+  thd_wait_end MUST be called immediately after waking up again.
+*/
+extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type)
+{
+  MYSQL_CALLBACK(thread_scheduler, thd_wait_begin, (thd, wait_type));
+}
+
+/**
+  Interface for MySQL Server, plugins and storage engines to report
+  when they waking up from a sleep/stall.
+
+  @param  thd   Thread handle
+*/
+extern "C" void thd_wait_end(MYSQL_THD thd)
+{
+  MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (thd));
+}
+#else
+extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type)
+{
+  /* do NOTHING for the embedded library */
+  return;
+}
+
+extern "C" void thd_wait_end(MYSQL_THD thd)
+{
+  /* do NOTHING for the embedded library */
+  return;
+}
+#endif
 #endif // INNODB_COMPATIBILITY_HOOKS */
 
 /****************************************************************************
@@ -3370,6 +3434,13 @@ void THD::set_query_id(query_id_t new_qu
   mysql_mutex_unlock(&LOCK_thd_data);
 }
 
+/** Assign a new value to thd->mysys_var.  */
+void THD::set_mysys_var(struct st_my_thread_var *new_mysys_var)
+{
+  mysql_mutex_lock(&LOCK_thd_data);
+  mysys_var= new_mysys_var;
+  mysql_mutex_unlock(&LOCK_thd_data);
+}
 
 /**
   Leave explicit LOCK TABLES or prelocked mode and restore value of

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2010-08-18 11:29:04 +0000
+++ b/sql/sql_class.h	2010-08-30 14:07:40 +0000
@@ -1634,6 +1634,10 @@ public:
         xid_state.xid.null();
       free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
     }
+    my_bool is_active()
+    {
+      return (all.ha_list != NULL);
+    }
     st_transactions()
     {
       bzero((char*)this, sizeof(*this));
@@ -2664,7 +2668,7 @@ public:
   virtual void set_statement(Statement *stmt);
 
   /**
-    Assign a new value to thd->query and thd->query_id.
+    Assign a new value to thd->query and thd->query_id and mysys_var.
     Protected with LOCK_thd_data mutex.
   */
   void set_query(char *query_arg, uint32 query_length_arg);
@@ -2677,6 +2681,7 @@ public:
     open_tables= open_tables_arg;
     mysql_mutex_unlock(&LOCK_thd_data);
   }
+  void set_mysys_var(struct st_my_thread_var *new_mysys_var);
   void enter_locked_tables_mode(enum_locked_tables_mode mode_arg)
   {
     DBUG_ASSERT(locked_tables_mode == LTM_NONE);

=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc	2010-08-05 12:53:09 +0000
+++ b/sql/sql_connect.cc	2010-08-16 12:50:27 +0000
@@ -35,6 +35,7 @@
 #include "hostname.h" // inc_host_errors, ip_to_hostname,
                       // reset_host_errors
 #include "sql_acl.h"  // acl_getroot, NO_ACCESS, SUPER_ACL
+#include "sql_callback.h"
 
 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 /*
@@ -966,7 +967,7 @@ bool setup_connection_thread_globals(THD
   {
     close_connection(thd, ER_OUT_OF_RESOURCES, 1);
     statistic_increment(aborted_connects,&LOCK_status);
-    thread_scheduler.end_thread(thd, 0);
+    MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
     return 1;                                   // Error
   }
   return 0;
@@ -989,7 +990,7 @@ bool setup_connection_thread_globals(THD
 */
 
 
-static bool login_connection(THD *thd)
+bool login_connection(THD *thd)
 {
   NET *net= &thd->net;
   int error;
@@ -1027,7 +1028,7 @@ static bool login_connection(THD *thd)
     This mainly updates status variables
 */
 
-static void end_connection(THD *thd)
+void end_connection(THD *thd)
 {
   NET *net= &thd->net;
   plugin_thdvar_cleanup(thd);
@@ -1068,7 +1069,7 @@ static void end_connection(THD *thd)
   Initialize THD to handle queries
 */
 
-static void prepare_new_connection_state(THD* thd)
+void prepare_new_connection_state(THD* thd)
 {
   Security_context *sctx= thd->security_ctx;
 
@@ -1137,11 +1138,11 @@ void do_handle_one_connection(THD *thd_a
 
   thd->thr_create_utime= my_micro_time();
 
-  if (thread_scheduler.init_new_connection_thread())
+  if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0))
   {
     close_connection(thd, ER_OUT_OF_RESOURCES, 1);
     statistic_increment(aborted_connects,&LOCK_status);
-    thread_scheduler.end_thread(thd,0);
+    MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
     return;
   }
 
@@ -1195,7 +1196,7 @@ void do_handle_one_connection(THD *thd_a
    
 end_thread:
     close_connection(thd, 0, 1);
-    if (thread_scheduler.end_thread(thd,1))
+    if (MYSQL_CALLBACK_ELSE(thread_scheduler, end_thread, (thd, 1), 0))
       return;                                 // Probably no-threads
 
     /*

=== modified file 'sql/sql_connect.h'
--- a/sql/sql_connect.h	2010-03-31 14:05:33 +0000
+++ b/sql/sql_connect.h	2010-06-07 14:01:39 +0000
@@ -40,4 +40,8 @@ int check_user(THD *thd, enum enum_serve
 	       const char *passwd, uint passwd_len, const char *db,
 	       bool check_count);
 
+bool login_connection(THD *thd);
+void prepare_new_connection_state(THD* thd);
+void end_connection(THD *thd);
+
 #endif /* SQL_CONNECT_INCLUDED */

=== modified file 'sql/sql_plugin_services.h'
--- a/sql/sql_plugin_services.h	2009-11-02 20:05:42 +0000
+++ b/sql/sql_plugin_services.h	2010-06-07 14:01:39 +0000
@@ -36,9 +36,23 @@ static struct thd_alloc_service_st thd_a
   thd_make_lex_string
 };
 
+static struct thd_wait_service_st thd_wait_handler= {
+  thd_wait_begin,
+  thd_wait_end
+};
+
+static struct my_thread_scheduler_service my_thread_scheduler_handler= {
+  my_thread_scheduler_set,
+  my_thread_scheduler_reset,
+};
+
+
 static struct st_service_ref list_of_services[]=
 {
   { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler },
-  { "thd_alloc_service",   VERSION_thd_alloc,   &thd_alloc_handler }
+  { "thd_alloc_service",   VERSION_thd_alloc,   &thd_alloc_handler },
+  { "thd_wait_service",    VERSION_thd_wait,    &thd_wait_handler },
+  { "my_thread_scheduler_service",
+    VERSION_my_thread_scheduler, &my_thread_scheduler_handler },
 };
 

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2010-08-16 06:46:21 +0000
+++ b/sql/sql_select.cc	2010-08-27 11:33:32 +0000
@@ -12723,7 +12723,9 @@ end_write(JOIN *join, JOIN_TAB *join_tab
   if (!end_of_records)
   {
     copy_fields(&join->tmp_table_param);
-    copy_funcs(join->tmp_table_param.items_to_copy);
+    if (copy_funcs(join->tmp_table_param.items_to_copy, join->thd))
+      DBUG_RETURN(NESTED_LOOP_ERROR);           /* purecov: inspected */
+
     if (!join->having || join->having->val_int())
     {
       int error;
@@ -12813,7 +12815,8 @@ end_update(JOIN *join, JOIN_TAB *join_ta
       memcpy(table->record[0]+key_part->offset, group->buff, 1);
   }
   init_tmptable_sum_functions(join->sum_funcs);
-  copy_funcs(join->tmp_table_param.items_to_copy);
+  if (copy_funcs(join->tmp_table_param.items_to_copy, join->thd))
+    DBUG_RETURN(NESTED_LOOP_ERROR);           /* purecov: inspected */
   if ((error=table->file->ha_write_row(table->record[0])))
   {
     if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
@@ -12848,7 +12851,8 @@ end_unique_update(JOIN *join, JOIN_TAB *
 
   init_tmptable_sum_functions(join->sum_funcs);
   copy_fields(&join->tmp_table_param);		// Groups are copied twice.
-  copy_funcs(join->tmp_table_param.items_to_copy);
+  if (copy_funcs(join->tmp_table_param.items_to_copy, join->thd))
+    DBUG_RETURN(NESTED_LOOP_ERROR);           /* purecov: inspected */
 
   if (!(error=table->file->ha_write_row(table->record[0])))
     join->send_records++;			// New group
@@ -12935,7 +12939,8 @@ end_write_group(JOIN *join, JOIN_TAB *jo
     if (idx < (int) join->send_group_parts)
     {
       copy_fields(&join->tmp_table_param);
-      copy_funcs(join->tmp_table_param.items_to_copy);
+      if (copy_funcs(join->tmp_table_param.items_to_copy, join->thd))
+	DBUG_RETURN(NESTED_LOOP_ERROR);
       if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
 	DBUG_RETURN(NESTED_LOOP_ERROR);
       if (join->procedure)
@@ -13238,6 +13243,34 @@ ok:
 }
 
 
+/**
+  Find shortest key suitable for full table scan.
+
+  @param table                 Table to scan
+  @param usable_keys           Allowed keys
+
+  @note
+     As far as 
+     1) clustered primary key entry data set is a set of all record
+        fields (key fields and not key fields) and
+     2) secondary index entry data is a union of its key fields and
+        primary key fields (at least InnoDB and its derivatives don't
+        duplicate primary key fields there, even if the primary and
+        the secondary keys have a common subset of key fields),
+     then secondary index entry data is always a subset of primary key entry.
+     Unfortunately, key_info[nr].key_length doesn't show the length
+     of key/pointer pair but a sum of key field lengths only, thus
+     we can't estimate index IO volume comparing only this key_length
+     value of secondary keys and clustered PK.
+     So, try secondary keys first, and choose PK only if there are no
+     usable secondary covering keys or found best secondary key include
+     all table fields (i.e. same as PK):
+
+  @return
+    MAX_KEY     no suitable key found
+    key index   otherwise
+*/
+
 uint find_shortest_key(TABLE *table, const key_map *usable_keys)
 {
   uint best= MAX_KEY;
@@ -13250,23 +13283,6 @@ uint find_shortest_key(TABLE *table, con
     uint min_length= (uint) ~0;
     for (uint nr=0; nr < table->s->keys ; nr++)
     {
-      /*
-       As far as 
-       1) clustered primary key entry data set is a set of all record
-          fields (key fields and not key fields) and
-       2) secondary index entry data is a union of its key fields and
-          primary key fields (at least InnoDB and its derivatives don't
-          duplicate primary key fields there, even if the primary and
-          the secondary keys have a common subset of key fields),
-       then secondary index entry data is always a subset of primary key
-       entry, and the PK is always longer.
-       Unfortunately, key_info[nr].key_length doesn't show the length
-       of key/pointer pair but a sum of key field lengths only, thus
-       we can't estimate index IO volume comparing only this key_length
-       value of seconday keys and clustered PK.
-       So, try secondary keys first, and choose PK only if there are no
-       usable secondary covering keys:
-      */
       if (nr == usable_clustered_pk)
         continue;
       if (usable_keys->is_set(nr))
@@ -13279,7 +13295,20 @@ uint find_shortest_key(TABLE *table, con
       }
     }
   }
-  return best != MAX_KEY ? best : usable_clustered_pk;
+  if (usable_clustered_pk != MAX_KEY)
+  {
+    /*
+     If the primary key is clustered and found shorter key covers all table
+     fields then primary key scan normally would be faster because amount of
+     data to scan is the same but PK is clustered.
+     It's safe to compare key parts with table fields since duplicate key
+     parts aren't allowed.
+     */
+    if (best == MAX_KEY ||
+        table->key_info[best].key_parts >= table->s->fields)
+      best= usable_clustered_pk;
+  }
+  return best;
 }
 
 /**
@@ -15807,14 +15836,39 @@ update_sum_func(Item_sum **func_ptr)
   return 0;
 }
 
-/** Copy result of functions to record in tmp_table. */
+/** 
+  Copy result of functions to record in tmp_table. 
 
-void
-copy_funcs(Item **func_ptr)
+  Uses the thread pointer to check for errors in 
+  some of the val_xxx() methods called by the 
+  save_in_result_field() function.
+  TODO: make the Item::val_xxx() return error code
+
+  @param func_ptr  array of the function Items to copy to the tmp table
+  @param thd       pointer to the current thread for error checking
+  @retval
+    FALSE if OK
+  @retval
+    TRUE on error  
+*/
+
+bool
+copy_funcs(Item **func_ptr, const THD *thd)
 {
   Item *func;
   for (; (func = *func_ptr) ; func_ptr++)
+  {
     func->save_in_result_field(1);
+    /*
+      Need to check the THD error state because Item::val_xxx() don't
+      return error code, but can generate errors
+      TODO: change it for a real status check when Item::val_xxx()
+      are extended to return status code.
+    */  
+    if (thd->is_error())
+      return TRUE;
+  }
+  return FALSE;
 }
 
 

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2010-07-27 12:42:36 +0000
+++ b/sql/sql_select.h	2010-08-17 12:12:52 +0000
@@ -606,7 +606,7 @@ bool setup_copy_fields(THD *thd, TMP_TAB
 		       List<Item> &new_list1, List<Item> &new_list2,
 		       uint elements, List<Item> &fields);
 void copy_fields(TMP_TABLE_PARAM *param);
-void copy_funcs(Item **func_ptr);
+bool copy_funcs(Item **func_ptr, const THD *thd);
 bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
 			     int error, bool ignore_last_dupp_error);
 uint find_shortest_key(TABLE *table, const key_map *usable_keys);

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	2010-08-18 11:29:04 +0000
+++ b/sql/sql_show.cc	2010-08-30 14:07:40 +0000
@@ -1815,6 +1815,7 @@ void mysqld_list_processes(THD *thd,cons
         if ((thd_info->db=tmp->db))             // Safe test
           thd_info->db=thd->strdup(thd_info->db);
         thd_info->command=(int) tmp->command;
+        mysql_mutex_lock(&tmp->LOCK_thd_data);
         if ((mysys_var= tmp->mysys_var))
           mysql_mutex_lock(&mysys_var->mutex);
         thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0);
@@ -1822,16 +1823,15 @@ void mysqld_list_processes(THD *thd,cons
         if (mysys_var)
           mysql_mutex_unlock(&mysys_var->mutex);
 
-        thd_info->start_time= tmp->start_time;
         thd_info->query=0;
         /* Lock THD mutex that protects its data when looking at it. */
-        mysql_mutex_lock(&tmp->LOCK_thd_data);
         if (tmp->query())
         {
           uint length= min(max_query_length, tmp->query_length());
           thd_info->query= (char*) thd->strmake(tmp->query(),length);
         }
         mysql_mutex_unlock(&tmp->LOCK_thd_data);
+        thd_info->start_time= tmp->start_time;
         thread_infos.append(thd_info);
       }
     }
@@ -1918,6 +1918,7 @@ int fill_schema_processlist(THD* thd, TA
         table->field[3]->set_notnull();
       }
 
+      mysql_mutex_lock(&tmp->LOCK_thd_data);
       if ((mysys_var= tmp->mysys_var))
         mysql_mutex_lock(&mysys_var->mutex);
       /* COMMAND */
@@ -1938,6 +1939,7 @@ int fill_schema_processlist(THD* thd, TA
 
       if (mysys_var)
         mysql_mutex_unlock(&mysys_var->mutex);
+      mysql_mutex_unlock(&tmp->LOCK_thd_data);
 
       /* INFO */
       /* Lock THD mutex that protects its data when looking at it. */
@@ -7490,13 +7492,16 @@ int finalize_schema_table(st_plugin_int 
   ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data;
   DBUG_ENTER("finalize_schema_table");
 
-  if (schema_table && plugin->plugin->deinit)
+  if (schema_table)
   {
-    DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str));
-    if (plugin->plugin->deinit(NULL))
+    if (plugin->plugin->deinit)
     {
-      DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
-                             plugin->name.str));
+      DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str));
+      if (plugin->plugin->deinit(NULL))
+      {
+        DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
+                               plugin->name.str));
+      }
     }
     my_free(schema_table);
   }

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2010-08-30 06:03:28 +0000
+++ b/sql/sql_yacc.yy	2010-09-01 13:12:42 +0000
@@ -1425,6 +1425,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 
 %type <table>
         table_ident table_ident_nodb references xid
+        table_ident_opt_wild
 
 %type <simple_string>
         remember_name remember_end opt_db text_or_password
@@ -10371,7 +10372,7 @@ table_alias_ref_list:
         ;
 
 table_alias_ref:
-          table_ident
+          table_ident_opt_wild
           {
             if (!Select->add_table_to_list(YYTHD, $1, NULL,
                                            TL_OPTION_UPDATING | TL_OPTION_ALIAS,
@@ -12161,6 +12162,21 @@ table_ident:
           }
         ;
 
+table_ident_opt_wild:
+          ident opt_wild
+          {
+            $$= new Table_ident($1);
+            if ($$ == NULL)
+              MYSQL_YYABORT;
+          }
+        | ident '.' ident opt_wild
+          {
+            $$= new Table_ident(YYTHD, $1,$3,0);
+            if ($$ == NULL)
+              MYSQL_YYABORT;
+          }
+        ;
+
 table_ident_nodb:
           ident
           {

=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc	2010-08-25 00:21:43 +0000
+++ b/sql/sys_vars.cc	2010-08-30 14:07:40 +0000
@@ -1673,19 +1673,13 @@ static Sys_var_ulong Sys_trans_prealloc_
 
 static const char *thread_handling_names[]=
 {
-  "one-thread-per-connection", "no-threads",
-#if HAVE_POOL_OF_THREADS == 1
-  "pool-of-threads",
-#endif
+  "one-thread-per-connection", "no-threads", "loaded-dynamically",
   0
 };
 static Sys_var_enum Sys_thread_handling(
        "thread_handling",
        "Define threads usage for handling queries, one of "
-       "one-thread-per-connection, no-threads"
-#if HAVE_POOL_OF_THREADS == 1
-       ", pool-of-threads"
-#endif
+       "one-thread-per-connection, no-threads, loaded-dynamically"
        , READ_ONLY GLOBAL_VAR(thread_handling), CMD_LINE(REQUIRED_ARG),
        thread_handling_names, DEFAULT(0));
 

=== modified file 'sql/table.h'
--- a/sql/table.h	2010-08-31 09:53:49 +0000
+++ b/sql/table.h	2010-09-03 07:42:51 +0000
@@ -192,7 +192,6 @@ typedef struct st_order {
   struct st_order *next;
   Item	 **item;			/* Point at item in select fields */
   Item	 *item_ptr;			/* Storage for initial item */
-  Item   **item_copy;			/* For SPs; the original item ptr */
   int    counter;                       /* position in SELECT list, correct
                                            only if counter_used is true*/
   bool	 asc;				/* true if ascending */

=== modified file 'storage/innobase/buf/buf0flu.c'
--- a/storage/innobase/buf/buf0flu.c	2010-07-30 14:39:16 +0000
+++ b/storage/innobase/buf/buf0flu.c	2010-08-30 14:07:40 +0000
@@ -43,6 +43,8 @@ Created 11/11/1995 Heikki Tuuri
 #include "log0log.h"
 #include "os0file.h"
 #include "trx0sys.h"
+#include "mysql/plugin.h"
+#include "mysql/service_thd_wait.h"
 
 /**********************************************************************
 These statistics are generated for heuristics used in estimating the
@@ -1744,10 +1746,14 @@ buf_flush_wait_batch_end(
 
 			buf_pool = buf_pool_from_array(i);
 
+			thd_wait_begin(NULL, THD_WAIT_DISKIO);
 			os_event_wait(buf_pool->no_flush[type]);
+			thd_wait_end(NULL);
 		}
 	} else {
+		thd_wait_begin(NULL, THD_WAIT_DISKIO);
 		os_event_wait(buf_pool->no_flush[type]);
+		thd_wait_end(NULL);
 	}
 }
 

=== modified file 'storage/innobase/buf/buf0rea.c'
--- a/storage/innobase/buf/buf0rea.c	2010-06-22 15:58:28 +0000
+++ b/storage/innobase/buf/buf0rea.c	2010-08-16 12:50:27 +0000
@@ -37,6 +37,8 @@ Created 11/5/1995 Heikki Tuuri
 #include "os0file.h"
 #include "srv0start.h"
 #include "srv0srv.h"
+#include "mysql/plugin.h"
+#include "mysql/service_thd_wait.h"
 
 /** The linear read-ahead area size */
 #define	BUF_READ_AHEAD_LINEAR_AREA	BUF_READ_AHEAD_AREA
@@ -135,6 +137,7 @@ buf_read_page_low(
 
 	ut_ad(buf_page_in_file(bpage));
 
+	thd_wait_begin(NULL, THD_WAIT_DISKIO);
 	if (zip_size) {
 		*err = fil_io(OS_FILE_READ | wake_later,
 			      sync, space, zip_size, offset, 0, zip_size,
@@ -146,6 +149,7 @@ buf_read_page_low(
 			      sync, space, 0, offset, 0, UNIV_PAGE_SIZE,
 			      ((buf_block_t*) bpage)->frame, bpage);
 	}
+	thd_wait_end(NULL);
 	ut_a(*err == DB_SUCCESS);
 
 	if (sync) {

=== modified file 'storage/innobase/srv/srv0srv.c'
--- a/storage/innobase/srv/srv0srv.c	2010-08-17 08:19:24 +0000
+++ b/storage/innobase/srv/srv0srv.c	2010-08-30 14:07:40 +0000
@@ -84,6 +84,8 @@ Created 10/8/1995 Heikki Tuuri
 #include "ha_prototypes.h"
 #include "trx0i_s.h"
 #include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
+#include "mysql/plugin.h"
+#include "mysql/service_thd_wait.h"
 
 /* This is set to TRUE if the MySQL user has set it in MySQL; currently
 affects only FOREIGN KEY definition parsing */
@@ -1232,7 +1234,9 @@ retry:
 
 	trx->op_info = "waiting in InnoDB queue";
 
+	thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK);
 	os_event_wait(slot->event);
+	thd_wait_end(trx->mysql_thd);
 
 	trx->op_info = "";
 
@@ -1597,7 +1601,9 @@ srv_suspend_mysql_thread(
 
 	/* Suspend this thread and wait for the event. */
 
+	thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK);
 	os_event_wait(event);
+	thd_wait_end(trx->mysql_thd);
 
 	/* After resuming, reacquire the data dictionary latch if
 	necessary. */

=== modified file 'vio/vio.c'
--- a/vio/vio.c	2010-07-08 21:20:08 +0000
+++ b/vio/vio.c	2010-08-16 12:50:27 +0000
@@ -44,6 +44,11 @@ static my_bool no_poll_read(Vio *vio __a
 
 #endif
 
+static my_bool has_no_data(Vio *vio __attribute__((unused)))
+{
+  return FALSE;
+}
+
 /*
  * Helper to fill most of the Vio* with defaults.
  */
@@ -83,6 +88,7 @@ static void vio_init(Vio* vio, enum enum
 
     vio->poll_read      =no_poll_read;
     vio->is_connected   =vio_is_connected_pipe;
+    vio->has_data       =has_no_data;
 
     vio->timeout=vio_win32_timeout;
     /* Set default timeout */
@@ -110,6 +116,7 @@ static void vio_init(Vio* vio, enum enum
 
     vio->poll_read      =no_poll_read;
     vio->is_connected   =vio_is_connected_shared_memory;
+    vio->has_data       =has_no_data;
 
     /* Currently, shared memory is on Windows only, hence the below is ok*/
     vio->timeout= vio_win32_timeout; 
@@ -137,6 +144,7 @@ static void vio_init(Vio* vio, enum enum
     vio->timeout	=vio_timeout;
     vio->poll_read      =vio_poll_read;
     vio->is_connected   =vio_is_connected;
+    vio->has_data       =vio_ssl_has_data;
     DBUG_VOID_RETURN;
   }
 #endif /* HAVE_OPENSSL */
@@ -155,6 +163,8 @@ static void vio_init(Vio* vio, enum enum
   vio->timeout          =vio_timeout;
   vio->poll_read        =vio_poll_read;
   vio->is_connected     =vio_is_connected;
+  vio->has_data=        (flags & VIO_BUFFERED_READ) ?
+                            vio_buff_has_data : has_no_data;
   DBUG_VOID_RETURN;
 }
 

=== modified file 'vio/vio_priv.h'
--- a/vio/vio_priv.h	2009-12-16 08:33:54 +0000
+++ b/vio/vio_priv.h	2010-06-07 14:01:39 +0000
@@ -49,6 +49,7 @@ int vio_close_shared_memory(Vio * vio);
 #endif
 
 void	vio_timeout(Vio *vio,uint which, uint timeout);
+my_bool vio_buff_has_data(Vio *vio);
 
 #ifdef HAVE_OPENSSL
 #include "my_net.h"			/* needed because of struct in_addr */
@@ -62,5 +63,7 @@ void vio_ssl_delete(Vio *vio);
 
 int vio_ssl_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode);
 
+my_bool vio_ssl_has_data(Vio *vio);
+
 #endif /* HAVE_OPENSSL */
 #endif /* VIO_PRIV_INCLUDED */

=== modified file 'vio/viosocket.c'
--- a/vio/viosocket.c	2010-05-21 13:17:01 +0000
+++ b/vio/viosocket.c	2010-08-16 12:50:27 +0000
@@ -98,6 +98,10 @@ size_t vio_read_buff(Vio *vio, uchar* bu
 #undef VIO_UNBUFFERED_READ_MIN_SIZE
 }
 
+my_bool vio_buff_has_data(Vio *vio)
+{
+  return (vio->read_pos != vio->read_end);
+}
 
 size_t vio_write(Vio * vio, const uchar* buf, size_t size)
 {

=== modified file 'vio/viossl.c'
--- a/vio/viossl.c	2010-07-15 11:13:30 +0000
+++ b/vio/viossl.c	2010-08-16 12:50:27 +0000
@@ -244,6 +244,9 @@ int vio_ssl_blocking(Vio *vio __attribut
   return (set_blocking_mode ? 0 : 1);
 }
 
-
+my_bool vio_ssl_has_data(Vio *vio)
+{
+  return SSL_pending(vio->ssl_arg) > 0 ? TRUE : FALSE;
+}
 
 #endif /* HAVE_OPENSSL */


Attachment: [text/bzr-bundle] bzr/jon.hauglid@oracle.com-20100903074251-zesazp04nton9ozx.bundle
Thread
bzr commit into mysql-5.5-runtime branch (jon.hauglid:3132) Jon Olav Hauglid3 Sep