List:Commits« Previous MessageNext Message »
From:Marc Alff Date:May 19 2011 4:52pm
Subject:bzr push into mysql-trunk-pfs-tuning branch (marc.alff:3374 to 3375)
View as plain text  
 3375 Marc Alff	2011-05-19 [merge]
      Merge mysql-trunk --> mysql-trunk-pfs-tuning

    added:
      include/mysql/thread_pool_priv.h
      mysql-test/include/not_threadpool.inc
      mysql-test/r/status_bug17954.result
      mysql-test/t/status_bug17954.test
      sql/mem_root_array.h
      unittest/gunit/dynarray-t.cc
    modified:
      BUILD/build_mccge.sh
      client/mysql.cc
      include/my_compiler.h
      include/my_sys.h
      include/mysql/plugin_audit.h.pp
      include/mysql/plugin_auth.h.pp
      include/mysql/plugin_ftparser.h.pp
      include/mysql/service_thd_wait.h
      libmysqld/lib_sql.cc
      mysql-test/include/have_archive_plugin.inc
      mysql-test/include/have_blackhole_plugin.inc
      mysql-test/include/mrr_tests.inc
      mysql-test/include/plugin.defs
      mysql-test/include/range.inc
      mysql-test/include/subquery.inc
      mysql-test/r/func_in_all.result
      mysql-test/r/func_time.result
      mysql-test/r/group_min_max.result
      mysql-test/r/innodb_mrr.result
      mysql-test/r/innodb_mrr_all.result
      mysql-test/r/innodb_mrr_cost.result
      mysql-test/r/innodb_mrr_cost_all.result
      mysql-test/r/innodb_mrr_cost_icp.result
      mysql-test/r/innodb_mrr_icp.result
      mysql-test/r/innodb_mrr_none.result
      mysql-test/r/myisam_mrr.result
      mysql-test/r/myisam_mrr_all.result
      mysql-test/r/myisam_mrr_cost.result
      mysql-test/r/myisam_mrr_cost_all.result
      mysql-test/r/myisam_mrr_cost_icp.result
      mysql-test/r/myisam_mrr_icp.result
      mysql-test/r/myisam_mrr_none.result
      mysql-test/r/range_icp.result
      mysql-test/r/range_icp_mrr.result
      mysql-test/r/range_mrr.result
      mysql-test/r/range_mrr_cost.result
      mysql-test/r/range_none.result
      mysql-test/r/status.result
      mysql-test/r/subquery_all.result
      mysql-test/r/subquery_all_jcl6.result
      mysql-test/r/subquery_nomat_nosj.result
      mysql-test/r/subquery_nomat_nosj_jcl6.result
      mysql-test/r/subquery_none.result
      mysql-test/r/subquery_none_jcl6.result
      mysql-test/suite/innodb/r/innodb-index.result
      mysql-test/suite/innodb/r/innodb.result
      mysql-test/suite/innodb/r/innodb_mysql.result
      mysql-test/suite/innodb/t/innodb-index.test
      mysql-test/suite/innodb/t/innodb.test
      mysql-test/suite/innodb/t/innodb_mysql.test
      mysql-test/suite/perfschema/t/no_threads.test
      mysql-test/suite/perfschema/t/one_thread_per_con.test
      mysql-test/suite/rpl/r/rpl_checksum.result
      mysql-test/suite/rpl/r/rpl_relayspace.result
      mysql-test/suite/rpl/t/rpl_checksum.test
      mysql-test/suite/rpl/t/rpl_relayspace.test
      mysql-test/suite/sys_vars/t/all_vars.test
      mysql-test/suite/sys_vars/t/slow_launch_time_func.test
      mysql-test/suite/sys_vars/t/thread_cache_size_func.test
      mysql-test/suite/sys_vars/t/wait_timeout_func.test
      mysql-test/t/func_time.test
      mysql-test/t/information_schema.test
      mysql-test/t/information_schema_db.test
      mysql-test/t/kill.test
      mysql-test/t/mysqlshow.test
      mysql-test/t/named_pipe.test
      mysql-test/t/no-threads.test
      mysql-test/t/shm.test
      mysql-test/t/status.test
      mysys/my_sync.c
      sql/debug_sync.cc
      sql/debug_sync.h
      sql/filesort.cc
      sql/filesort_utils.cc
      sql/ha_ndbcluster.cc
      sql/handler.cc
      sql/item_cmpfunc.cc
      sql/item_func.cc
      sql/item_func.h
      sql/item_timefunc.cc
      sql/log.cc
      sql/log.h
      sql/mdl.cc
      sql/mysqld.cc
      sql/mysqld.h
      sql/opt_range.cc
      sql/rpl_rli.cc
      sql/scheduler.cc
      sql/scheduler.h
      sql/sp_head.cc
      sql/sp_head.h
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_connect.cc
      sql/sql_connect.h
      sql/sql_const.h
      sql/sql_cursor.h
      sql/sql_prepare.cc
      sql/sql_select.cc
      sql/sql_select.h
      sql/sql_table.cc
      sql/sql_test.cc
      sql/sql_test.h
      sql/table.cc
      sql/uniques.cc
      storage/innobase/srv/srv0conc.c
      unittest/gunit/CMakeLists.txt
      unittest/gunit/mdl-t.cc
      unittest/gunit/mdl_mytap-t.cc
 3374 Marc Alff	2011-05-17 [merge]
      Merge mysql-trunk --> mysql-trunk-pfs-tuning

    removed:
      mysql-test/suite/perfschema/r/pfs_upgrade_lc0.result
      mysql-test/suite/perfschema/r/pfs_upgrade_lc1.result
      mysql-test/suite/perfschema/r/pfs_upgrade_lc2.result
      mysql-test/suite/perfschema/r/schema_lc0.result
      mysql-test/suite/perfschema/r/schema_lc1.result
      mysql-test/suite/perfschema/r/schema_lc2.result
      mysql-test/suite/perfschema/t/pfs_upgrade_lc0.test
      mysql-test/suite/perfschema/t/pfs_upgrade_lc1.test
      mysql-test/suite/perfschema/t/pfs_upgrade_lc2.test
      mysql-test/suite/perfschema/t/schema_lc0.test
      mysql-test/suite/perfschema/t/schema_lc1.test
      mysql-test/suite/perfschema/t/schema_lc2.test
    added:
      mysql-test/collections/mysql-trunk-bug27480.push
      mysql-test/extra/rpl_tests/rpl_temp_error.test
      mysql-test/include/start_slave_io.inc
      mysql-test/include/start_slave_sql.inc
      mysql-test/lib/mtr_results.pm
      mysql-test/r/implicit_char_to_num_conversion.result
      mysql-test/suite/perfschema/r/pfs_upgrade.result
      mysql-test/suite/perfschema/r/schema.result
      mysql-test/suite/perfschema/t/pfs_upgrade.test
      mysql-test/suite/perfschema/t/schema.test
      mysql-test/suite/rpl/r/rpl_DML_error.result
      mysql-test/suite/rpl/t/rpl_DML_error.test
      mysql-test/t/implicit_char_to_num_conversion.test
      unittest/gunit/opt_range-t.cc
      unittest/gunit/test_utils.cc
      unittest/gunit/test_utils.h
    modified:
      .bzrignore
      BUILD/SETUP.sh
      CMakeLists.txt
      client/mysql.cc*
      client/mysqlbinlog.cc
      client/mysqltest.cc
      extra/replace.c
      include/mysql.h
      include/mysql.h.pp
      libmysql/libmysql.c
      mysql-test/collections/default.experimental
      mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test
      mysql-test/extra/rpl_tests/check_type.inc
      mysql-test/extra/rpl_tests/rpl_drop_create_temp_table.inc
      mysql-test/extra/rpl_tests/rpl_drop_create_temp_table.test
      mysql-test/extra/rpl_tests/rpl_innodb.test
      mysql-test/extra/rpl_tests/rpl_mixing_engines.inc
      mysql-test/include/handler.inc
      mysql-test/include/wait_show_condition.inc
      mysql-test/lib/My/CoreDump.pm
      mysql-test/lib/My/Test.pm
      mysql-test/lib/mtr_report.pm
      mysql-test/mysql-test-run.pl
      mysql-test/r/alter_table.result
      mysql-test/r/ctype_binary.result
      mysql-test/r/ctype_cp1251.result
      mysql-test/r/ctype_latin1.result
      mysql-test/r/ctype_ucs.result
      mysql-test/r/ctype_utf8.result
      mysql-test/r/distinct.result
      mysql-test/r/events_1.result
      mysql-test/r/events_restart.result
      mysql-test/r/explain.result
      mysql-test/r/flush_read_lock.result
      mysql-test/r/grant2.result
      mysql-test/r/grant4.result
      mysql-test/r/handler_innodb.result
      mysql-test/r/handler_myisam.result
      mysql-test/r/having.result
      mysql-test/r/innodb_mysql_lock.result
      mysql-test/r/merge.result
      mysql-test/r/metadata.result
      mysql-test/r/mysqlbinlog_base64.result
      mysql-test/r/mysqldump.result
      mysql-test/r/ps_ddl.result
      mysql-test/r/read_only_innodb.result
      mysql-test/r/temp_table.result
      mysql-test/r/trigger.result
      mysql-test/r/type_newdecimal.result
      mysql-test/r/type_ranges.result
      mysql-test/r/variables-big.result
      mysql-test/suite/binlog/r/binlog_innodb_row.result
      mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result
      mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result
      mysql-test/suite/binlog/t/binlog_bug23533.test
      mysql-test/suite/binlog/t/binlog_innodb_row.test
      mysql-test/suite/funcs_1/r/is_columns_mysql.result
      mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result
      mysql-test/suite/innodb/r/innodb_mysql.result
      mysql-test/suite/innodb/t/innodb_mysql.test
      mysql-test/suite/rpl/r/rpl_begin_commit_rollback.result
      mysql-test/suite/rpl/r/rpl_crash_safe_master.result
      mysql-test/suite/rpl/r/rpl_create_if_not_exists.result
      mysql-test/suite/rpl/r/rpl_loaddatalocal.result
      mysql-test/suite/rpl/r/rpl_mixed_drop_create_temp_table.result
      mysql-test/suite/rpl/r/rpl_mixed_mixing_engines.result
      mysql-test/suite/rpl/r/rpl_non_direct_mixed_mixing_engines.result
      mysql-test/suite/rpl/r/rpl_non_direct_row_mixing_engines.result
      mysql-test/suite/rpl/r/rpl_non_direct_stm_mixing_engines.result
      mysql-test/suite/rpl/r/rpl_row_crash_safe.result
      mysql-test/suite/rpl/r/rpl_row_drop_create_temp_table.result
      mysql-test/suite/rpl/r/rpl_row_ignorable_event.result
      mysql-test/suite/rpl/r/rpl_row_mixing_engines.result
      mysql-test/suite/rpl/r/rpl_server_id2.result
      mysql-test/suite/rpl/r/rpl_show_slave_hosts.result
      mysql-test/suite/rpl/r/rpl_stm_drop_create_temp_table.result
      mysql-test/suite/rpl/r/rpl_stm_innodb.result
      mysql-test/suite/rpl/r/rpl_stm_mixed_crash_safe.result
      mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result
      mysql-test/suite/rpl/r/rpl_typeconv.result
      mysql-test/suite/rpl/t/rpl_begin_commit_rollback.test
      mysql-test/suite/rpl/t/rpl_crash_safe_master.test
      mysql-test/suite/rpl/t/rpl_create_if_not_exists.test
      mysql-test/suite/rpl/t/rpl_loaddatalocal.test
      mysql-test/suite/rpl/t/rpl_row_ignorable_event.test
      mysql-test/suite/rpl/t/rpl_row_until.test
      mysql-test/suite/rpl/t/rpl_server_id2.test
      mysql-test/suite/rpl/t/rpl_show_slave_hosts.test
      mysql-test/suite/rpl/t/rpl_typeconv.test
      mysql-test/t/alter_table.test
      mysql-test/t/distinct.test
      mysql-test/t/events_1.test
      mysql-test/t/events_restart.test
      mysql-test/t/explain.test
      mysql-test/t/flush_read_lock.test
      mysql-test/t/grant2.test
      mysql-test/t/grant4.test
      mysql-test/t/handler_myisam.test
      mysql-test/t/having.test
      mysql-test/t/innodb_mysql_lock.test
      mysql-test/t/merge.test
      mysql-test/t/mysqlbinlog_base64.test
      mysql-test/t/mysqlbinlog_raw_mode.test
      mysql-test/t/mysqldump.test
      mysql-test/t/ps_ddl.test
      mysql-test/t/temp_table.test
      mysql-test/t/trigger.test
      mysql-test/t/type_newdecimal.test
      mysql-test/t/variables-big.test
      mysys/lf_alloc-pin.c
      mysys/thr_alarm.c
      packaging/WiX/ca/CMakeLists.txt
      packaging/WiX/create_msi.cmake.in
      packaging/WiX/custom_ui.wxs
      scripts/make_win_bin_dist
      scripts/mysql_system_tables.sql
      sql/binlog.cc
      sql/binlog.h
      sql/event_db_repository.cc
      sql/field.cc
      sql/ha_ndbcluster.cc
      sql/ha_ndbcluster_binlog.cc
      sql/ha_partition.cc
      sql/ha_partition.h
      sql/handler.cc
      sql/handler.h
      sql/item.cc
      sql/item_cmpfunc.cc
      sql/item_func.cc
      sql/item_row.cc
      sql/item_strfunc.cc
      sql/item_xmlfunc.cc
      sql/item_xmlfunc.h
      sql/log_event.cc
      sql/my_decimal.cc
      sql/my_decimal.h
      sql/mysqld.cc
      sql/mysqld.h
      sql/opt_range.cc
      sql/protocol.cc
      sql/rpl_info_file.cc
      sql/rpl_injector.cc
      sql/rpl_injector.h
      sql/rpl_master.cc
      sql/rpl_reporting.cc
      sql/rpl_rli.cc
      sql/rpl_rli.h
      sql/rpl_slave.cc
      sql/share/errmsg-utf8.txt
      sql/sp_head.cc
      sql/sql_acl.cc
      sql/sql_acl.h
      sql/sql_admin.cc
      sql/sql_alter.cc
      sql/sql_analyse.cc
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_db.cc
      sql/sql_delete.cc
      sql/sql_handler.cc
      sql/sql_handler.h
      sql/sql_insert.cc
      sql/sql_lex.h
      sql/sql_load.cc
      sql/sql_parse.cc
      sql/sql_parse.h
      sql/sql_partition.cc
      sql/sql_partition.h
      sql/sql_partition_admin.cc
      sql/sql_prepare.cc
      sql/sql_priv.h
      sql/sql_rename.cc
      sql/sql_select.cc
      sql/sql_show.cc
      sql/sql_table.cc
      sql/sql_truncate.cc
      sql/sql_update.cc
      sql/sql_view.cc
      sql/sql_yacc.yy
      sql/sys_vars.cc
      sql/table.cc
      sql/table.h
      sql/transaction.cc
      storage/archive/ha_archive.cc
      storage/innobase/handler/i_s.cc
      storage/myisammrg/ha_myisammrg.cc
      storage/ndb/src/kernel/blocks/lgman.cpp
      storage/perfschema/pfs.cc
      storage/perfschema/pfs_instr_class.cc
      storage/perfschema/pfs_instr_class.h
      storage/perfschema/pfs_setup_object.h
      storage/perfschema/table_setup_instruments.cc
      storage/perfschema/table_setup_instruments.h
      strings/decimal.c
      unittest/gunit/CMakeLists.txt
      unittest/gunit/item-t.cc
      unittest/mysys/lf-t.c
      vio/viosocket.c
=== modified file 'BUILD/build_mccge.sh'
--- a/BUILD/build_mccge.sh	2011-01-21 16:14:47 +0000
+++ b/BUILD/build_mccge.sh	2011-05-04 09:54:04 +0000
@@ -293,7 +293,8 @@ extended_usage()
     version string suffix: [none]
 
   All packages except Classic include support for user-defined
-  partitioning.
+  partitioning. All packages include support for Performance
+  Schema.
 
   If --with-debug is used, an additional "-debug" is appended to the
   version string.

=== modified file 'client/mysql.cc'
--- a/client/mysql.cc	2011-05-06 08:26:00 +0000
+++ b/client/mysql.cc	2011-05-18 14:36:45 +0000
@@ -3764,8 +3764,6 @@ com_tee(String *buffer __attribute__((un
 {
   char file_name[FN_REFLEN], *end, *param;
 
-  if (status.batch)
-    return 0;
   while (my_isspace(charset_info,*line))
     line++;
   if (!(param = strchr(line, ' '))) // if outfile wasn't given, use the default

=== modified file 'include/my_compiler.h'
--- a/include/my_compiler.h	2011-02-22 21:03:32 +0000
+++ b/include/my_compiler.h	2011-05-04 08:45:51 +0000
@@ -140,6 +140,14 @@ struct my_aligned_storage
 
 #endif /* __cplusplus */
 
+# ifndef MY_ALIGNED
+/*
+  Make sure MY_ALIGNED can be used also on platforms where we don't
+  have a way of aligning data structures.
+*/
+#define MY_ALIGNED(size)
+#endif
+
 #include <my_attribute.h>
 
 #endif /* MY_COMPILER_INCLUDED */

=== modified file 'include/my_sys.h'
--- a/include/my_sys.h	2011-05-04 21:19:21 +0000
+++ b/include/my_sys.h	2011-05-19 16:52:11 +0000
@@ -625,6 +625,8 @@ extern FILE *my_freopen(const char *path
 extern int my_fclose(FILE *fd,myf MyFlags);
 extern File my_fileno(FILE *fd);
 extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags);
+extern void thr_set_sync_wait_callback(void (*before_sync)(void),
+                                       void (*after_sync)(void));
 extern int my_sync(File fd, myf my_flags);
 extern int my_sync_dir(const char *dir_name, myf my_flags);
 extern int my_sync_dir_by_file(const char *file_name, myf my_flags);

=== modified file 'include/mysql/plugin_audit.h.pp'
--- a/include/mysql/plugin_audit.h.pp	2011-03-09 20:54:55 +0000
+++ b/include/mysql/plugin_audit.h.pp	2011-05-04 09:54:04 +0000
@@ -34,16 +34,23 @@ MYSQL_LEX_STRING *thd_make_lex_string(vo
                                       int allocate_lex_string);
 #include <mysql/service_thd_wait.h>
 typedef enum _thd_wait_type_e {
-  THD_WAIT_MUTEX= 1,
+  THD_WAIT_SLEEP= 1,
   THD_WAIT_DISKIO= 2,
-  THD_WAIT_ROW_TABLE_LOCK= 3,
-  THD_WAIT_GLOBAL_LOCK= 4
+  THD_WAIT_ROW_LOCK= 3,
+  THD_WAIT_GLOBAL_LOCK= 4,
+  THD_WAIT_META_DATA_LOCK= 5,
+  THD_WAIT_TABLE_LOCK= 6,
+  THD_WAIT_USER_LOCK= 7,
+  THD_WAIT_BINLOG= 8,
+  THD_WAIT_GROUP_COMMIT= 9,
+  THD_WAIT_SYNC= 10,
+  THD_WAIT_LAST= 11 
 } thd_wait_type;
 extern struct thd_wait_service_st {
-  void (*thd_wait_begin_func)(void*, thd_wait_type);
+  void (*thd_wait_begin_func)(void*, int);
   void (*thd_wait_end_func)(void*);
 } *thd_wait_service;
-void thd_wait_begin(void* thd, thd_wait_type wait_type);
+void thd_wait_begin(void* thd, int wait_type);
 void thd_wait_end(void* thd);
 #include <mysql/service_thread_scheduler.h>
 struct scheduler_functions;

=== modified file 'include/mysql/plugin_auth.h.pp'
--- a/include/mysql/plugin_auth.h.pp	2011-03-09 20:54:55 +0000
+++ b/include/mysql/plugin_auth.h.pp	2011-05-04 09:54:04 +0000
@@ -34,16 +34,23 @@ MYSQL_LEX_STRING *thd_make_lex_string(vo
                                       int allocate_lex_string);
 #include <mysql/service_thd_wait.h>
 typedef enum _thd_wait_type_e {
-  THD_WAIT_MUTEX= 1,
+  THD_WAIT_SLEEP= 1,
   THD_WAIT_DISKIO= 2,
-  THD_WAIT_ROW_TABLE_LOCK= 3,
-  THD_WAIT_GLOBAL_LOCK= 4
+  THD_WAIT_ROW_LOCK= 3,
+  THD_WAIT_GLOBAL_LOCK= 4,
+  THD_WAIT_META_DATA_LOCK= 5,
+  THD_WAIT_TABLE_LOCK= 6,
+  THD_WAIT_USER_LOCK= 7,
+  THD_WAIT_BINLOG= 8,
+  THD_WAIT_GROUP_COMMIT= 9,
+  THD_WAIT_SYNC= 10,
+  THD_WAIT_LAST= 11
 } thd_wait_type;
 extern struct thd_wait_service_st {
-  void (*thd_wait_begin_func)(void*, thd_wait_type);
+  void (*thd_wait_begin_func)(void*, int);
   void (*thd_wait_end_func)(void*);
 } *thd_wait_service;
-void thd_wait_begin(void* thd, thd_wait_type wait_type);
+void thd_wait_begin(void* thd, int wait_type);
 void thd_wait_end(void* thd);
 #include <mysql/service_thread_scheduler.h>
 struct scheduler_functions;

=== modified file 'include/mysql/plugin_ftparser.h.pp'
--- a/include/mysql/plugin_ftparser.h.pp	2011-03-09 20:54:55 +0000
+++ b/include/mysql/plugin_ftparser.h.pp	2011-05-04 09:54:04 +0000
@@ -34,16 +34,23 @@ MYSQL_LEX_STRING *thd_make_lex_string(vo
                                       int allocate_lex_string);
 #include <mysql/service_thd_wait.h>
 typedef enum _thd_wait_type_e {
-  THD_WAIT_MUTEX= 1,
+  THD_WAIT_SLEEP= 1,
   THD_WAIT_DISKIO= 2,
-  THD_WAIT_ROW_TABLE_LOCK= 3,
-  THD_WAIT_GLOBAL_LOCK= 4
+  THD_WAIT_ROW_LOCK= 3,
+  THD_WAIT_GLOBAL_LOCK= 4,
+  THD_WAIT_META_DATA_LOCK= 5,
+  THD_WAIT_TABLE_LOCK= 6,
+  THD_WAIT_USER_LOCK= 7,
+  THD_WAIT_BINLOG= 8,
+  THD_WAIT_GROUP_COMMIT= 9,
+  THD_WAIT_SYNC= 10,
+  THD_WAIT_LAST= 11 
 } thd_wait_type;
 extern struct thd_wait_service_st {
-  void (*thd_wait_begin_func)(void*, thd_wait_type);
+  void (*thd_wait_begin_func)(void*, int);
   void (*thd_wait_end_func)(void*);
 } *thd_wait_service;
-void thd_wait_begin(void* thd, thd_wait_type wait_type);
+void thd_wait_begin(void* thd, int wait_type);
 void thd_wait_end(void* thd);
 #include <mysql/service_thread_scheduler.h>
 struct scheduler_functions;

=== modified file 'include/mysql/service_thd_wait.h'
--- a/include/mysql/service_thd_wait.h	2010-06-07 14:01:39 +0000
+++ b/include/mysql/service_thd_wait.h	2011-03-04 12:12:31 +0000
@@ -50,15 +50,35 @@
 extern "C" {
 #endif
 
+/*
+  One should only report wait events that could potentially block for a
+  long time. A mutex wait is too short of an event to report. The reason
+  is that an event which is reported leads to a new thread starts
+  executing a query and this has a negative impact of usage of CPU caches
+  and thus the expected gain of starting a new thread must be higher than
+  the expected cost of lost performance due to starting a new thread.
+
+  Good examples of events that should be reported are waiting for row locks
+  that could easily be for many milliseconds or even seconds and the same
+  holds true for global read locks, table locks and other meta data locks.
+  Another event of interest is going to sleep for an extended time.
+*/
 typedef enum _thd_wait_type_e {
-  THD_WAIT_MUTEX= 1,
+  THD_WAIT_SLEEP= 1,
   THD_WAIT_DISKIO= 2,
-  THD_WAIT_ROW_TABLE_LOCK= 3,
-  THD_WAIT_GLOBAL_LOCK= 4
+  THD_WAIT_ROW_LOCK= 3,
+  THD_WAIT_GLOBAL_LOCK= 4,
+  THD_WAIT_META_DATA_LOCK= 5,
+  THD_WAIT_TABLE_LOCK= 6,
+  THD_WAIT_USER_LOCK= 7,
+  THD_WAIT_BINLOG= 8,
+  THD_WAIT_GROUP_COMMIT= 9,
+  THD_WAIT_SYNC= 10,
+  THD_WAIT_LAST= 11
 } thd_wait_type;
 
 extern struct thd_wait_service_st {
-  void (*thd_wait_begin_func)(MYSQL_THD, thd_wait_type);
+  void (*thd_wait_begin_func)(MYSQL_THD, int);
   void (*thd_wait_end_func)(MYSQL_THD);
 } *thd_wait_service;
 
@@ -70,7 +90,7 @@ extern struct thd_wait_service_st {
 
 #else
 
-void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type);
+void thd_wait_begin(MYSQL_THD thd, int wait_type);
 void thd_wait_end(MYSQL_THD thd);
 
 #endif

=== added file 'include/mysql/thread_pool_priv.h'
--- a/include/mysql/thread_pool_priv.h	1970-01-01 00:00:00 +0000
+++ b/include/mysql/thread_pool_priv.h	2011-05-18 07:38:05 +0000
@@ -0,0 +1,119 @@
+/*
+  Copyright (C) 2010, 2011 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 THREAD_POOL_PRIV_INCLUDED
+#define THREAD_POOL_PRIV_INCLUDED
+
+/*
+  The thread pool requires access to some MySQL server error codes, this is
+  accessed from mysqld_error.h.
+  We need access to the struct that defines the thread pool plugin interface
+  which is accessed through scheduler.h.
+  All accesses to THD variables and functions are defined in this header file.
+  A thread pool can also use DEBUG_SYNC and must thus include
+  debug_sync.h
+  To handle definitions of Information Schema plugins it is also required
+  to include sql_profile.h and table.h.
+*/
+#include <mysqld_error.h> /* To get ER_ERROR_ON_READ */
+#define MYSQL_SERVER 1
+#include <scheduler.h>
+#include <debug_sync.h>
+#include <sql_profile.h>
+#include <table.h>
+
+/* Needed to get access to scheduler variables */
+void* thd_get_scheduler_data(THD *thd);
+void thd_set_scheduler_data(THD *thd, void *data);
+PSI_thread* thd_get_psi(THD *thd);
+void thd_set_psi(THD *thd, PSI_thread *psi);
+
+/* Interface to THD variables and functions */
+void thd_set_killed(THD *thd);
+void thd_clear_errors(THD *thd);
+void thd_set_thread_stack(THD *thd, char *stack_start);
+void thd_lock_thread_count(THD *thd);
+void thd_unlock_thread_count(THD *thd);
+void thd_close_connection(THD *thd);
+THD *thd_get_current_thd();
+void thd_new_connection_setup(THD *thd, char *stack_start);
+void thd_lock_data(THD *thd);
+void thd_unlock_data(THD *thd);
+bool thd_is_transaction_active(THD *thd);
+int thd_connection_has_data(THD *thd);
+void thd_set_net_read_write(THD *thd, uint val);
+void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var);
+my_socket thd_get_fd(THD *thd);
+
+/* Print to the MySQL error log */
+void sql_print_error(const char *format, ...);
+
+/* Store a table record */
+bool schema_table_store_record(THD *thd, TABLE *table);
+
+/*
+  The thread pool must be able to execute statements using the connection
+  state in THD object. This is the main objective of the thread pool to
+  schedule the start of these commands.
+*/
+bool do_command(THD *thd);
+
+/*
+  The thread pool requires an interface to the connection logic in the
+  MySQL Server since the thread pool will maintain the event logic on
+  the TCP connection of the MySQL Server. Thus new connections, dropped
+  connections will be discovered by the thread pool and it needs to
+  ensure that the proper MySQL Server logic attached to these events is
+  executed.
+*/
+/* Initialise a new connection handler thread */
+bool init_new_connection_handler_thread();
+/* Set up connection thread before use as execution thread */
+bool setup_connection_thread_globals(THD *thd);
+/* Prepare connection as part of connection set-up */
+bool thd_prepare_connection(THD *thd);
+/* Release auditing before executing statement */
+void mysql_audit_release(THD *thd);
+/* Check if connection is still alive */
+bool thd_is_connection_alive(THD *thd);
+/* Close connection with possible error code */
+void close_connection(THD *thd, uint errcode);
+/* End the connection before closing it */
+void end_connection(THD *thd);
+/* Decrement connection counter */
+void dec_connection_count();
+/* Destroy THD object */
+void delete_thd(THD *thd);
+
+/*
+  thread_created is maintained by thread pool when activated since
+  user threads are created by the thread pool (and also special
+  threads to maintain the thread pool). This is done through
+  inc_thread_created.
+
+  max_connections is needed to calculate the maximum number of threads
+  that is allowed to be started by the thread pool. The method
+  get_max_connections() gets reference to this variable.
+
+  connection_attrib is the thread attributes for connection threads,
+  the method get_connection_attrib provides a reference to these
+  attributes.
+*/
+void inc_thread_created(void);
+ulong get_max_connections(void);
+pthread_attr_t *get_connection_attrib(void);
+#endif

=== modified file 'libmysqld/lib_sql.cc'
--- a/libmysqld/lib_sql.cc	2011-03-09 20:54:55 +0000
+++ b/libmysqld/lib_sql.cc	2011-05-18 14:36:45 +0000
@@ -50,6 +50,24 @@ extern "C" void unireg_clear(int exit_co
   DBUG_VOID_RETURN;
 }
 
+/*
+  Wrapper error handler for embedded server to call client/server error 
+  handler based on whether thread is in client/server context
+*/
+
+static void embedded_error_handler(uint error, const char *str, myf MyFlags)
+{
+  DBUG_ENTER("embedded_error_handler");
+
+  /* 
+    If current_thd is NULL, it means restore_global has been called and 
+    thread is in client context, then call client error handler else call 
+    server error handler.
+  */
+  DBUG_RETURN(current_thd ? my_message_sql(error, str, MyFlags):
+              my_message_stderr(error, str, MyFlags));
+}
+
 
 /*
   Reads error information from the MYSQL_DATA and puts
@@ -106,7 +124,8 @@ emb_advanced_command(MYSQL *mysql, enum
   if (mysql->status != MYSQL_STATUS_READY)
   {
     set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
-    return 1;
+    result= 1;
+    goto end;
   }
 
   /* Clear result variables */
@@ -147,6 +166,9 @@ emb_advanced_command(MYSQL *mysql, enum
 #if defined(ENABLED_PROFILING)
   thd->profiling.finish_current_query();
 #endif
+
+end:
+  thd->restore_globals();
   return result;
 }
 
@@ -555,7 +577,10 @@ int init_embedded_server(int argc, char
     return 1;
   }
 
-  error_handler_hook = my_message_sql;
+  /* 
+    set error_handler_hook to embedded_error_handler wrapper.
+  */
+  error_handler_hook= embedded_error_handler;
 
   acl_error= 0;
 #ifndef NO_EMBEDDED_ACCESS_CHECKS

=== modified file 'mysql-test/include/have_archive_plugin.inc'
--- a/mysql-test/include/have_archive_plugin.inc	2010-04-27 08:29:51 +0000
+++ b/mysql-test/include/have_archive_plugin.inc	2011-05-04 09:54:04 +0000
@@ -1,5 +1,10 @@
+disable_query_log;
 if (`select plugin_library IS NULL from information_schema.plugins where plugin_name LIKE '%archive%'`)
 {
   --skip archive plugin not available
 }
 
+if (`SELECT @@plugin_dir != '$ARCHIVE_PLUGIN_DIR'`) {
+  --skip Archive plugin requires that --plugin-dir is set to the archive plugin dir (either the .opt file does not contain \$ARCHIVE_PLUGIN_OPT or another plugin is in use)
+}
+enable_query_log;
\ No newline at end of file

=== modified file 'mysql-test/include/have_blackhole_plugin.inc'
--- a/mysql-test/include/have_blackhole_plugin.inc	2010-04-27 08:29:51 +0000
+++ b/mysql-test/include/have_blackhole_plugin.inc	2011-05-04 09:54:04 +0000
@@ -1,5 +1,11 @@
+disable_query_log;
 if (`select plugin_library IS NULL from information_schema.plugins where plugin_name LIKE '%blackhole%'`)
 {
   --skip blackhole plugin not available;
 }
 
+if (`SELECT @@plugin_dir != '$BLACKHOLE_PLUGIN_DIR'`) {
+  --skip Blackhole plugin requires that --plugin-dir is set to the blackhole plugin dir (either the .opt file does not contain \$BLACKHOLE_PLUGIN_OPT or another plugin is in use)
+}
+enable_query_log;
+

=== modified file 'mysql-test/include/mrr_tests.inc'
--- a/mysql-test/include/mrr_tests.inc	2011-01-07 08:38:31 +0000
+++ b/mysql-test/include/mrr_tests.inc	2011-05-05 11:10:39 +0000
@@ -377,3 +377,36 @@ eval EXPLAIN $query;
 eval $query;
 
 DROP TABLE t1, t2;
+
+--echo #
+--echo # Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+--echo #
+
+# This test should run with join cache level 0
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+
+CREATE TABLE t1 (
+  pk INTEGER,
+  c1 VARCHAR(1) NOT NULL,
+  PRIMARY KEY (pk)
+);
+
+CREATE TABLE t2 (
+  c1 VARCHAR(1) NOT NULL
+);
+
+INSERT INTO t2 VALUES ('v'), ('c');
+
+let query=
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+
+eval EXPLAIN $query;
+eval $query;
+
+DROP TABLE t1,t2;
+
+# Restore join cache level to its original value
+set optimizer_join_cache_level= @save_join_cache_level;

=== added file 'mysql-test/include/not_threadpool.inc'
--- a/mysql-test/include/not_threadpool.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/not_threadpool.inc	2011-01-14 08:28:23 +0000
@@ -0,0 +1,5 @@
+if (`SELECT count(*) FROM information_schema.GLOBAL_VARIABLES WHERE
+      VARIABLE_NAME = 'THREAD_HANDLING' AND
+      VARIABLE_VALUE = 'loaded-dynamically'`){
+  skip Test requires: 'not_threadpool';
+}

=== modified file 'mysql-test/include/plugin.defs'
--- a/mysql-test/include/plugin.defs	2011-01-31 15:32:57 +0000
+++ b/mysql-test/include/plugin.defs	2011-02-10 17:15:19 +0000
@@ -39,3 +39,4 @@ ha_archive         storage/archive    AR
 ha_blackhole       storage/blackhole  BLACKHOLE_PLUGIN
 ha_federated       storage/federated  FEDERATED_PLUGIN
 mypluglib          plugin/fulltext    SIMPLE_PARSER
+thread_pool        plugin/thread_pool THREADPOOL_PLUGIN thread_pool,TP_THREAD_STATE,TP_THREAD_GROUP_STATE,TP_THREAD_GROUP_STATS

=== modified file 'mysql-test/include/range.inc'
--- a/mysql-test/include/range.inc	2011-02-01 12:47:39 +0000
+++ b/mysql-test/include/range.inc	2011-05-19 12:03:55 +0000
@@ -1471,3 +1471,35 @@ INSERT INTO t2 VALUES (1, 1, 2);
 EXPLAIN SELECT * FROM t2 WHERE a = 1 AND b >= 2 AND c >= 2;
 
 DROP TABLE t1, t2;
+
+--echo #
+--echo # BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER 
+--echo #               AWAY QUALIFYING ROWS
+--echo #
+
+CREATE TABLE t10(
+  K INT NOT NULL AUTO_INCREMENT,
+  I INT, J INT,
+  PRIMARY KEY(K),
+  KEY(I,J)
+);
+INSERT INTO t10(I,J) VALUES (6,1),(6,2),(6,3),(6,4),(6,5),
+                            (6,6),(6,7),(6,8),(6,9),(6,0);
+
+CREATE TABLE t100 LIKE t10;
+INSERT INTO t100(I,J) SELECT X.I, X.K+(10*Y.K) FROM t10 AS X,t10 AS Y;
+
+# Insert offending value:
+INSERT INTO t100(I,J) VALUES(8,26);
+
+let $query= SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+
+#Verify that 'range' access will be used
+--echo
+--eval EXPLAIN $query
+
+# Only row 101,8,26 should be returned
+--echo
+--eval $query
+
+DROP TABLE t10,t100;

=== modified file 'mysql-test/include/subquery.inc'
--- a/mysql-test/include/subquery.inc	2011-04-15 08:11:49 +0000
+++ b/mysql-test/include/subquery.inc	2011-05-05 07:41:53 +0000
@@ -4740,8 +4740,6 @@ CREATE VIEW v1 AS SELECT 1 LIKE ( 1 IN (
 CREATE VIEW v2 AS SELECT 1 LIKE '%' ESCAPE ( 1 IN ( SELECT 1 ) );
 DROP VIEW v1, v2;
 
---echo End of 5.1 tests.
-
 #
 # Bug #47904 Incorrect results w/ table subquery, derived SQs, and LEFT JOIN on index
 #
@@ -5101,6 +5099,54 @@ SELECT 1 FROM
 
 DROP TABLE t1;
 
+--echo #
+--echo # Bug#11764086: Null left operand to NOT IN in WHERE clause
+--echo # behaves differently than real NULL
+--echo #
+
+CREATE TABLE parent (id int);
+INSERT INTO parent VALUES (1), (2);
+
+CREATE TABLE child (parent_id int, other int);
+INSERT INTO child VALUES (1,NULL);
+
+--echo # Offending query (c.parent_id is NULL for null-complemented rows only)
+
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id NOT IN (
+              SELECT parent_id 
+              FROM   child
+              WHERE  parent_id = 3
+          );
+
+--echo # Some syntactic variations with IS FALSE and IS NOT TRUE
+
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+              SELECT parent_id 
+              FROM   child
+              WHERE  parent_id = 3
+          ) IS NOT TRUE;
+
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+              SELECT parent_id 
+              FROM   child
+              WHERE  parent_id = 3
+          ) IS FALSE;
+
+DROP TABLE parent, child;
+
+--echo # End of test for bug#11764086.
 
 --echo End of 5.5 tests.
 

=== modified file 'mysql-test/r/func_in_all.result'
--- a/mysql-test/r/func_in_all.result	2011-04-12 10:31:30 +0000
+++ b/mysql-test/r/func_in_all.result	2011-04-28 11:53:14 +0000
@@ -806,5 +806,16 @@ WHERE 1+NULL NOT IN
 (SELECT i FROM subq WHERE subq.pk = t1.pk);
 pk	i
 DROP TABLE t1,subq;
+#
+# Bug #11766270  59343: YEAR(4): INCORRECT RESULT AND VALGRIND WARNINGS WITH MIN/MAX, UNION
+#
+CREATE TABLE t1(f1 YEAR(4));
+INSERT INTO t1 VALUES (0000),(2001);
+(SELECT MAX(f1) FROM t1) UNION (SELECT MAX(f1) FROM t1);
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
+def				MAX(f1)	MAX(f1)	13	4	4	Y	32864	0	63
+MAX(f1)
+2001
+DROP TABLE t1;
 End of 5.1 tests
 set optimizer_switch=default;

=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result	2011-04-27 07:55:04 +0000
+++ b/mysql-test/r/func_time.result	2011-05-18 07:07:52 +0000
@@ -1389,6 +1389,15 @@ NULL
 SELECT DATE_FORMAT('0000-00-11', '%w');
 DATE_FORMAT('0000-00-11', '%w')
 NULL
+#
+# Bug#12403504  AFTER FIX FOR #11889186 : ASSERTION FAILED: DELSUM+(INT) Y/4-TEMP > 0
+#
+SELECT MAKEDATE(11111111,1);
+MAKEDATE(11111111,1)
+NULL
+SELECT WEEK(DATE_ADD(FROM_DAYS(1),INTERVAL 1 MONTH), 1);
+WEEK(DATE_ADD(FROM_DAYS(1),INTERVAL 1 MONTH), 1)
+NULL
 End of 5.1 tests
 #
 # BUG#43578 "MyISAM&Maria gives wrong rows with range access

=== modified file 'mysql-test/r/group_min_max.result'
--- a/mysql-test/r/group_min_max.result	2011-04-27 09:10:45 +0000
+++ b/mysql-test/r/group_min_max.result	2011-05-19 12:03:55 +0000
@@ -876,10 +876,10 @@ id	select_type	table	type	possible_keys
 1	SIMPLE	t1	range	NULL	idx_t1_1	163	NULL	17	Using where; Using index for group-by
 explain select a1,a2,b,       max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	range	NULL	idx_t1_1	163	NULL	17	Using where; Using index for group-by
+1	SIMPLE	t1	range	NULL	idx_t1_1	147	NULL	17	Using where; Using index for group-by
 explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	range	NULL	idx_t1_1	163	NULL	17	Using where; Using index for group-by
+1	SIMPLE	t1	range	NULL	idx_t1_1	147	NULL	17	Using where; Using index for group-by
 explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	range	NULL	idx_t1_1	163	NULL	17	Using where; Using index for group-by
@@ -924,7 +924,7 @@ id	select_type	table	type	possible_keys
 1	SIMPLE	t2	range	NULL	idx_t2_1	163	NULL	#	Using where; Using index for group-by
 explain select a1,a2,b,       max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	range	NULL	idx_t2_1	163	NULL	#	Using where; Using index for group-by
+1	SIMPLE	t2	range	NULL	idx_t2_1	146	NULL	#	Using where; Using index for group-by
 explain select a1,a2,b,min(c),max(c) from t2 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	range	NULL	idx_t2_1	163	NULL	#	Using where; Using index for group-by

=== modified file 'mysql-test/r/innodb_mrr.result'
--- a/mysql-test/r/innodb_mrr.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/innodb_mrr.result	2011-05-05 11:10:39 +0000
@@ -543,6 +543,32 @@ ORDER BY i1;
 i1
 DROP TABLE t1, t2;
 #
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
+#
 # Bug#41029 "MRR: SELECT FOR UPDATE fails to lock gaps (InnoDB table)"
 #
 SET AUTOCOMMIT=0;

=== modified file 'mysql-test/r/innodb_mrr_all.result'
--- a/mysql-test/r/innodb_mrr_all.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/innodb_mrr_all.result	2011-05-05 11:10:39 +0000
@@ -543,6 +543,32 @@ ORDER BY i1;
 i1
 DROP TABLE t1, t2;
 #
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using index condition; Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
+#
 # Bug#41029 "MRR: SELECT FOR UPDATE fails to lock gaps (InnoDB table)"
 #
 SET AUTOCOMMIT=0;

=== modified file 'mysql-test/r/innodb_mrr_cost.result'
--- a/mysql-test/r/innodb_mrr_cost.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/innodb_mrr_cost.result	2011-05-05 11:10:39 +0000
@@ -543,6 +543,32 @@ ORDER BY i1;
 i1
 DROP TABLE t1, t2;
 #
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
+#
 # Bug#41029 "MRR: SELECT FOR UPDATE fails to lock gaps (InnoDB table)"
 #
 SET AUTOCOMMIT=0;

=== modified file 'mysql-test/r/innodb_mrr_cost_all.result'
--- a/mysql-test/r/innodb_mrr_cost_all.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/innodb_mrr_cost_all.result	2011-05-05 11:10:39 +0000
@@ -543,6 +543,32 @@ ORDER BY i1;
 i1
 DROP TABLE t1, t2;
 #
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using index condition; Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
+#
 # Bug#41029 "MRR: SELECT FOR UPDATE fails to lock gaps (InnoDB table)"
 #
 SET AUTOCOMMIT=0;

=== modified file 'mysql-test/r/innodb_mrr_cost_icp.result'
--- a/mysql-test/r/innodb_mrr_cost_icp.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/innodb_mrr_cost_icp.result	2011-05-05 11:10:39 +0000
@@ -543,6 +543,32 @@ ORDER BY i1;
 i1
 DROP TABLE t1, t2;
 #
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using index condition; Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
+#
 # Bug#41029 "MRR: SELECT FOR UPDATE fails to lock gaps (InnoDB table)"
 #
 SET AUTOCOMMIT=0;

=== modified file 'mysql-test/r/innodb_mrr_icp.result'
--- a/mysql-test/r/innodb_mrr_icp.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/innodb_mrr_icp.result	2011-05-05 11:10:39 +0000
@@ -543,6 +543,32 @@ ORDER BY i1;
 i1
 DROP TABLE t1, t2;
 #
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using index condition; Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
+#
 # Bug#41029 "MRR: SELECT FOR UPDATE fails to lock gaps (InnoDB table)"
 #
 SET AUTOCOMMIT=0;

=== modified file 'mysql-test/r/innodb_mrr_none.result'
--- a/mysql-test/r/innodb_mrr_none.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/innodb_mrr_none.result	2011-05-05 11:10:39 +0000
@@ -542,6 +542,32 @@ ORDER BY i1;
 i1
 DROP TABLE t1, t2;
 #
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
+#
 # Bug#41029 "MRR: SELECT FOR UPDATE fails to lock gaps (InnoDB table)"
 #
 SET AUTOCOMMIT=0;

=== modified file 'mysql-test/r/myisam_mrr.result'
--- a/mysql-test/r/myisam_mrr.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/myisam_mrr.result	2011-05-05 11:10:39 +0000
@@ -544,5 +544,31 @@ AND t2.pk IS  NULL
 ORDER BY i1;
 i1
 DROP TABLE t1, t2;
+#
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using where; Using MRR
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
 set @@read_rnd_buffer_size= @read_rnd_buffer_size_save;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_mrr_all.result'
--- a/mysql-test/r/myisam_mrr_all.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/myisam_mrr_all.result	2011-05-05 11:10:39 +0000
@@ -544,5 +544,31 @@ AND t2.pk IS  NULL
 ORDER BY i1;
 i1
 DROP TABLE t1, t2;
+#
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using index condition; Using where; Using MRR
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
 set @@read_rnd_buffer_size= @read_rnd_buffer_size_save;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_mrr_cost.result'
--- a/mysql-test/r/myisam_mrr_cost.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/myisam_mrr_cost.result	2011-05-05 11:10:39 +0000
@@ -544,5 +544,31 @@ AND t2.pk IS  NULL
 ORDER BY i1;
 i1
 DROP TABLE t1, t2;
+#
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
 set @@read_rnd_buffer_size= @read_rnd_buffer_size_save;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_mrr_cost_all.result'
--- a/mysql-test/r/myisam_mrr_cost_all.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/myisam_mrr_cost_all.result	2011-05-05 11:10:39 +0000
@@ -544,5 +544,31 @@ AND t2.pk IS  NULL
 ORDER BY i1;
 i1
 DROP TABLE t1, t2;
+#
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using index condition; Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
 set @@read_rnd_buffer_size= @read_rnd_buffer_size_save;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_mrr_cost_icp.result'
--- a/mysql-test/r/myisam_mrr_cost_icp.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/myisam_mrr_cost_icp.result	2011-05-05 11:10:39 +0000
@@ -544,5 +544,31 @@ AND t2.pk IS  NULL
 ORDER BY i1;
 i1
 DROP TABLE t1, t2;
+#
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using index condition; Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
 set @@read_rnd_buffer_size= @read_rnd_buffer_size_save;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_mrr_icp.result'
--- a/mysql-test/r/myisam_mrr_icp.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/myisam_mrr_icp.result	2011-05-05 11:10:39 +0000
@@ -544,5 +544,31 @@ AND t2.pk IS  NULL
 ORDER BY i1;
 i1
 DROP TABLE t1, t2;
+#
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using index condition; Using where; Using MRR
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
 set @@read_rnd_buffer_size= @read_rnd_buffer_size_save;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/myisam_mrr_none.result'
--- a/mysql-test/r/myisam_mrr_none.result	2011-01-07 08:38:31 +0000
+++ b/mysql-test/r/myisam_mrr_none.result	2011-05-05 11:10:39 +0000
@@ -543,5 +543,31 @@ AND t2.pk IS  NULL
 ORDER BY i1;
 i1
 DROP TABLE t1, t2;
+#
+# Bug#12321461: CRASH IN DSMRR_IMPL::DSMRR_INIT ON SELECT STRAIGHT_JOIN
+#
+set @save_join_cache_level= @@optimizer_join_cache_level;
+set optimizer_join_cache_level=0;
+CREATE TABLE t1 (
+pk INTEGER,
+c1 VARCHAR(1) NOT NULL,
+PRIMARY KEY (pk)
+);
+CREATE TABLE t2 (
+c1 VARCHAR(1) NOT NULL
+);
+INSERT INTO t2 VALUES ('v'), ('c');
+EXPLAIN SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	2	
+1	SIMPLE	t1	range	PRIMARY	PRIMARY	4	NULL	1	Using where
+SELECT STRAIGHT_JOIN t1.c1
+FROM t1 RIGHT OUTER JOIN t2 ON t1.c1 = t2.c1
+WHERE t1.pk > 176;
+c1
+DROP TABLE t1,t2;
+set optimizer_join_cache_level= @save_join_cache_level;
 set @@read_rnd_buffer_size= @read_rnd_buffer_size_save;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/range_icp.result'
--- a/mysql-test/r/range_icp.result	2011-02-01 12:47:39 +0000
+++ b/mysql-test/r/range_icp.result	2011-05-19 12:03:55 +0000
@@ -1849,4 +1849,28 @@ EXPLAIN SELECT * FROM t2 WHERE a = 1 AND
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ref	k,l,m,n	l	5	const	69	Using index condition; Using where
 DROP TABLE t1, t2;
+#
+# BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER 
+#               AWAY QUALIFYING ROWS
+#
+CREATE TABLE t10(
+K INT NOT NULL AUTO_INCREMENT,
+I INT, J INT,
+PRIMARY KEY(K),
+KEY(I,J)
+);
+INSERT INTO t10(I,J) VALUES (6,1),(6,2),(6,3),(6,4),(6,5),
+(6,6),(6,7),(6,8),(6,9),(6,0);
+CREATE TABLE t100 LIKE t10;
+INSERT INTO t100(I,J) SELECT X.I, X.K+(10*Y.K) FROM t10 AS X,t10 AS Y;
+INSERT INTO t100(I,J) VALUES(8,26);
+
+EXPLAIN SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t100	range	I	I	10	NULL	4	Using index condition
+
+SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+K	I	J
+101	8	26
+DROP TABLE t10,t100;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/range_icp_mrr.result'
--- a/mysql-test/r/range_icp_mrr.result	2011-02-01 12:47:39 +0000
+++ b/mysql-test/r/range_icp_mrr.result	2011-05-19 12:03:55 +0000
@@ -1849,4 +1849,28 @@ EXPLAIN SELECT * FROM t2 WHERE a = 1 AND
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ref	k,l,m,n	l	5	const	69	Using index condition; Using where
 DROP TABLE t1, t2;
+#
+# BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER 
+#               AWAY QUALIFYING ROWS
+#
+CREATE TABLE t10(
+K INT NOT NULL AUTO_INCREMENT,
+I INT, J INT,
+PRIMARY KEY(K),
+KEY(I,J)
+);
+INSERT INTO t10(I,J) VALUES (6,1),(6,2),(6,3),(6,4),(6,5),
+(6,6),(6,7),(6,8),(6,9),(6,0);
+CREATE TABLE t100 LIKE t10;
+INSERT INTO t100(I,J) SELECT X.I, X.K+(10*Y.K) FROM t10 AS X,t10 AS Y;
+INSERT INTO t100(I,J) VALUES(8,26);
+
+EXPLAIN SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t100	range	I	I	10	NULL	4	Using index condition; Using MRR
+
+SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+K	I	J
+101	8	26
+DROP TABLE t10,t100;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/range_mrr.result'
--- a/mysql-test/r/range_mrr.result	2011-02-01 12:47:39 +0000
+++ b/mysql-test/r/range_mrr.result	2011-05-19 12:03:55 +0000
@@ -1849,4 +1849,28 @@ EXPLAIN SELECT * FROM t2 WHERE a = 1 AND
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ref	k,l,m,n	l	5	const	69	Using where
 DROP TABLE t1, t2;
+#
+# BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER 
+#               AWAY QUALIFYING ROWS
+#
+CREATE TABLE t10(
+K INT NOT NULL AUTO_INCREMENT,
+I INT, J INT,
+PRIMARY KEY(K),
+KEY(I,J)
+);
+INSERT INTO t10(I,J) VALUES (6,1),(6,2),(6,3),(6,4),(6,5),
+(6,6),(6,7),(6,8),(6,9),(6,0);
+CREATE TABLE t100 LIKE t10;
+INSERT INTO t100(I,J) SELECT X.I, X.K+(10*Y.K) FROM t10 AS X,t10 AS Y;
+INSERT INTO t100(I,J) VALUES(8,26);
+
+EXPLAIN SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t100	range	I	I	10	NULL	4	Using where; Using MRR
+
+SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+K	I	J
+101	8	26
+DROP TABLE t10,t100;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/range_mrr_cost.result'
--- a/mysql-test/r/range_mrr_cost.result	2011-02-01 12:47:39 +0000
+++ b/mysql-test/r/range_mrr_cost.result	2011-05-19 12:03:55 +0000
@@ -1849,4 +1849,28 @@ EXPLAIN SELECT * FROM t2 WHERE a = 1 AND
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ref	k,l,m,n	l	5	const	69	Using where
 DROP TABLE t1, t2;
+#
+# BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER 
+#               AWAY QUALIFYING ROWS
+#
+CREATE TABLE t10(
+K INT NOT NULL AUTO_INCREMENT,
+I INT, J INT,
+PRIMARY KEY(K),
+KEY(I,J)
+);
+INSERT INTO t10(I,J) VALUES (6,1),(6,2),(6,3),(6,4),(6,5),
+(6,6),(6,7),(6,8),(6,9),(6,0);
+CREATE TABLE t100 LIKE t10;
+INSERT INTO t100(I,J) SELECT X.I, X.K+(10*Y.K) FROM t10 AS X,t10 AS Y;
+INSERT INTO t100(I,J) VALUES(8,26);
+
+EXPLAIN SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t100	range	I	I	10	NULL	4	Using where
+
+SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+K	I	J
+101	8	26
+DROP TABLE t10,t100;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/range_none.result'
--- a/mysql-test/r/range_none.result	2011-02-01 12:47:39 +0000
+++ b/mysql-test/r/range_none.result	2011-05-19 12:03:55 +0000
@@ -1848,4 +1848,28 @@ EXPLAIN SELECT * FROM t2 WHERE a = 1 AND
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t2	ref	k,l,m,n	l	5	const	69	Using where
 DROP TABLE t1, t2;
+#
+# BUG#11765831: 'RANGE ACCESS' MAY INCORRECTLY FILTER 
+#               AWAY QUALIFYING ROWS
+#
+CREATE TABLE t10(
+K INT NOT NULL AUTO_INCREMENT,
+I INT, J INT,
+PRIMARY KEY(K),
+KEY(I,J)
+);
+INSERT INTO t10(I,J) VALUES (6,1),(6,2),(6,3),(6,4),(6,5),
+(6,6),(6,7),(6,8),(6,9),(6,0);
+CREATE TABLE t100 LIKE t10;
+INSERT INTO t100(I,J) SELECT X.I, X.K+(10*Y.K) FROM t10 AS X,t10 AS Y;
+INSERT INTO t100(I,J) VALUES(8,26);
+
+EXPLAIN SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t100	range	I	I	10	NULL	4	Using where
+
+SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
+K	I	J
+101	8	26
+DROP TABLE t10,t100;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/status.result'
--- a/mysql-test/r/status.result	2011-02-22 14:24:33 +0000
+++ b/mysql-test/r/status.result	2011-05-04 09:54:04 +0000
@@ -238,11 +238,5 @@ SELECT 9;
 9
 DROP PROCEDURE p1;
 DROP FUNCTION f1;
-DROP VIEW IF EXISTS v1;
-CREATE VIEW v1 AS SELECT VARIABLE_NAME AS NAME, CONVERT(VARIABLE_VALUE, UNSIGNED) AS VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS;
-SELECT VALUE INTO @tc FROM v1 WHERE NAME = 'Threads_connected';
-SELECT NAME FROM v1 WHERE NAME = 'Threads_created' AND VALUE < @tc;
-NAME
-DROP VIEW v1;
 set @@global.concurrent_insert= @old_concurrent_insert;
 SET GLOBAL log_output = @old_log_output;

=== added file 'mysql-test/r/status_bug17954.result'
--- a/mysql-test/r/status_bug17954.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/status_bug17954.result	2011-01-14 08:28:23 +0000
@@ -0,0 +1,13 @@
+set @old_concurrent_insert= @@global.concurrent_insert;
+set @@global.concurrent_insert= 0;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL LOG_OUTPUT = 'FILE';
+flush status;
+DROP VIEW IF EXISTS v1;
+CREATE VIEW v1 AS SELECT VARIABLE_NAME AS NAME, CONVERT(VARIABLE_VALUE, UNSIGNED) AS VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS;
+SELECT VALUE INTO @tc FROM v1 WHERE NAME = 'Threads_connected';
+SELECT NAME FROM v1 WHERE NAME = 'Threads_created' AND VALUE < @tc;
+NAME
+DROP VIEW v1;
+set @@global.concurrent_insert= @old_concurrent_insert;
+SET GLOBAL log_output = @old_log_output;

=== modified file 'mysql-test/r/subquery_all.result'
--- a/mysql-test/r/subquery_all.result	2011-04-15 08:11:49 +0000
+++ b/mysql-test/r/subquery_all.result	2011-05-05 07:41:53 +0000
@@ -5900,7 +5900,6 @@ Note	1249	Select 2 was reduced during op
 CREATE VIEW v1 AS SELECT 1 LIKE ( 1 IN ( SELECT 1 ) );
 CREATE VIEW v2 AS SELECT 1 LIKE '%' ESCAPE ( 1 IN ( SELECT 1 ) );
 DROP VIEW v1, v2;
-End of 5.1 tests.
 Set up test tables.
 CREATE TABLE t1 (
 t1_id INT UNSIGNED,
@@ -6242,6 +6241,54 @@ SELECT 1 FROM
 1) FROM t1) AS e;
 ERROR 21000: Operand should contain 1 column(s)
 DROP TABLE t1;
+#
+# Bug#11764086: Null left operand to NOT IN in WHERE clause
+# behaves differently than real NULL
+#
+CREATE TABLE parent (id int);
+INSERT INTO parent VALUES (1), (2);
+CREATE TABLE child (parent_id int, other int);
+INSERT INTO child VALUES (1,NULL);
+# Offending query (c.parent_id is NULL for null-complemented rows only)
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id NOT IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+);
+id	parent_id
+1	1
+2	NULL
+# Some syntactic variations with IS FALSE and IS NOT TRUE
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS NOT TRUE;
+id	parent_id
+1	1
+2	NULL
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS FALSE;
+id	parent_id
+1	1
+2	NULL
+DROP TABLE parent, child;
+# End of test for bug#11764086.
 End of 5.5 tests.
 #
 # BUG#48920: COUNT DISTINCT returns 1 for NULL values when in a subquery 

=== modified file 'mysql-test/r/subquery_all_jcl6.result'
--- a/mysql-test/r/subquery_all_jcl6.result	2011-03-29 08:10:26 +0000
+++ b/mysql-test/r/subquery_all_jcl6.result	2011-05-05 07:41:53 +0000
@@ -5904,7 +5904,6 @@ Note	1249	Select 2 was reduced during op
 CREATE VIEW v1 AS SELECT 1 LIKE ( 1 IN ( SELECT 1 ) );
 CREATE VIEW v2 AS SELECT 1 LIKE '%' ESCAPE ( 1 IN ( SELECT 1 ) );
 DROP VIEW v1, v2;
-End of 5.1 tests.
 Set up test tables.
 CREATE TABLE t1 (
 t1_id INT UNSIGNED,
@@ -6217,6 +6216,24 @@ id	select_type	table	type	possible_keys
 DROP TABLE t2;
 DROP TABLE t1;
 #
+# Bug #11765713 58705:
+# OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES
+# CREATED BY OPT_SUM_QUERY
+#
+CREATE TABLE t1(a INT NOT NULL, KEY (a));
+INSERT INTO t1 VALUES (0), (1);
+SELECT 1 as foo FROM t1 WHERE a < SOME
+(SELECT a FROM t1 WHERE a <=>
+(SELECT a FROM t1)
+);
+ERROR 21000: Subquery returns more than 1 row
+SELECT 1 as foo FROM t1 WHERE a < SOME
+(SELECT a FROM t1 WHERE a <=>
+(SELECT a FROM t1 where a is null)
+);
+foo
+DROP TABLE t1;
+#
 # Bug #57704: Cleanup code dies with void TABLE::set_keyread(bool): 
 #             Assertion `file' failed.
 #
@@ -6228,6 +6245,54 @@ SELECT 1 FROM
 1) FROM t1) AS e;
 ERROR 21000: Operand should contain 1 column(s)
 DROP TABLE t1;
+#
+# Bug#11764086: Null left operand to NOT IN in WHERE clause
+# behaves differently than real NULL
+#
+CREATE TABLE parent (id int);
+INSERT INTO parent VALUES (1), (2);
+CREATE TABLE child (parent_id int, other int);
+INSERT INTO child VALUES (1,NULL);
+# Offending query (c.parent_id is NULL for null-complemented rows only)
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id NOT IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+);
+id	parent_id
+1	1
+2	NULL
+# Some syntactic variations with IS FALSE and IS NOT TRUE
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS NOT TRUE;
+id	parent_id
+1	1
+2	NULL
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS FALSE;
+id	parent_id
+1	1
+2	NULL
+DROP TABLE parent, child;
+# End of test for bug#11764086.
 End of 5.5 tests.
 #
 # BUG#48920: COUNT DISTINCT returns 1 for NULL values when in a subquery 

=== modified file 'mysql-test/r/subquery_nomat_nosj.result'
--- a/mysql-test/r/subquery_nomat_nosj.result	2011-04-15 08:11:49 +0000
+++ b/mysql-test/r/subquery_nomat_nosj.result	2011-05-05 07:41:53 +0000
@@ -5900,7 +5900,6 @@ Note	1249	Select 2 was reduced during op
 CREATE VIEW v1 AS SELECT 1 LIKE ( 1 IN ( SELECT 1 ) );
 CREATE VIEW v2 AS SELECT 1 LIKE '%' ESCAPE ( 1 IN ( SELECT 1 ) );
 DROP VIEW v1, v2;
-End of 5.1 tests.
 Set up test tables.
 CREATE TABLE t1 (
 t1_id INT UNSIGNED,
@@ -6242,6 +6241,54 @@ SELECT 1 FROM
 1) FROM t1) AS e;
 ERROR 21000: Operand should contain 1 column(s)
 DROP TABLE t1;
+#
+# Bug#11764086: Null left operand to NOT IN in WHERE clause
+# behaves differently than real NULL
+#
+CREATE TABLE parent (id int);
+INSERT INTO parent VALUES (1), (2);
+CREATE TABLE child (parent_id int, other int);
+INSERT INTO child VALUES (1,NULL);
+# Offending query (c.parent_id is NULL for null-complemented rows only)
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id NOT IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+);
+id	parent_id
+1	1
+2	NULL
+# Some syntactic variations with IS FALSE and IS NOT TRUE
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS NOT TRUE;
+id	parent_id
+1	1
+2	NULL
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS FALSE;
+id	parent_id
+1	1
+2	NULL
+DROP TABLE parent, child;
+# End of test for bug#11764086.
 End of 5.5 tests.
 #
 # BUG#48920: COUNT DISTINCT returns 1 for NULL values when in a subquery 

=== modified file 'mysql-test/r/subquery_nomat_nosj_jcl6.result'
--- a/mysql-test/r/subquery_nomat_nosj_jcl6.result	2011-03-29 08:10:26 +0000
+++ b/mysql-test/r/subquery_nomat_nosj_jcl6.result	2011-05-05 07:41:53 +0000
@@ -5904,7 +5904,6 @@ Note	1249	Select 2 was reduced during op
 CREATE VIEW v1 AS SELECT 1 LIKE ( 1 IN ( SELECT 1 ) );
 CREATE VIEW v2 AS SELECT 1 LIKE '%' ESCAPE ( 1 IN ( SELECT 1 ) );
 DROP VIEW v1, v2;
-End of 5.1 tests.
 Set up test tables.
 CREATE TABLE t1 (
 t1_id INT UNSIGNED,
@@ -6217,6 +6216,24 @@ id	select_type	table	type	possible_keys
 DROP TABLE t2;
 DROP TABLE t1;
 #
+# Bug #11765713 58705:
+# OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES
+# CREATED BY OPT_SUM_QUERY
+#
+CREATE TABLE t1(a INT NOT NULL, KEY (a));
+INSERT INTO t1 VALUES (0), (1);
+SELECT 1 as foo FROM t1 WHERE a < SOME
+(SELECT a FROM t1 WHERE a <=>
+(SELECT a FROM t1)
+);
+ERROR 21000: Subquery returns more than 1 row
+SELECT 1 as foo FROM t1 WHERE a < SOME
+(SELECT a FROM t1 WHERE a <=>
+(SELECT a FROM t1 where a is null)
+);
+foo
+DROP TABLE t1;
+#
 # Bug #57704: Cleanup code dies with void TABLE::set_keyread(bool): 
 #             Assertion `file' failed.
 #
@@ -6228,6 +6245,54 @@ SELECT 1 FROM
 1) FROM t1) AS e;
 ERROR 21000: Operand should contain 1 column(s)
 DROP TABLE t1;
+#
+# Bug#11764086: Null left operand to NOT IN in WHERE clause
+# behaves differently than real NULL
+#
+CREATE TABLE parent (id int);
+INSERT INTO parent VALUES (1), (2);
+CREATE TABLE child (parent_id int, other int);
+INSERT INTO child VALUES (1,NULL);
+# Offending query (c.parent_id is NULL for null-complemented rows only)
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id NOT IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+);
+id	parent_id
+1	1
+2	NULL
+# Some syntactic variations with IS FALSE and IS NOT TRUE
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS NOT TRUE;
+id	parent_id
+1	1
+2	NULL
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS FALSE;
+id	parent_id
+1	1
+2	NULL
+DROP TABLE parent, child;
+# End of test for bug#11764086.
 End of 5.5 tests.
 #
 # BUG#48920: COUNT DISTINCT returns 1 for NULL values when in a subquery 

=== modified file 'mysql-test/r/subquery_none.result'
--- a/mysql-test/r/subquery_none.result	2011-04-15 08:11:49 +0000
+++ b/mysql-test/r/subquery_none.result	2011-05-05 07:41:53 +0000
@@ -5899,7 +5899,6 @@ Note	1249	Select 2 was reduced during op
 CREATE VIEW v1 AS SELECT 1 LIKE ( 1 IN ( SELECT 1 ) );
 CREATE VIEW v2 AS SELECT 1 LIKE '%' ESCAPE ( 1 IN ( SELECT 1 ) );
 DROP VIEW v1, v2;
-End of 5.1 tests.
 Set up test tables.
 CREATE TABLE t1 (
 t1_id INT UNSIGNED,
@@ -6241,6 +6240,54 @@ SELECT 1 FROM
 1) FROM t1) AS e;
 ERROR 21000: Operand should contain 1 column(s)
 DROP TABLE t1;
+#
+# Bug#11764086: Null left operand to NOT IN in WHERE clause
+# behaves differently than real NULL
+#
+CREATE TABLE parent (id int);
+INSERT INTO parent VALUES (1), (2);
+CREATE TABLE child (parent_id int, other int);
+INSERT INTO child VALUES (1,NULL);
+# Offending query (c.parent_id is NULL for null-complemented rows only)
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id NOT IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+);
+id	parent_id
+1	1
+2	NULL
+# Some syntactic variations with IS FALSE and IS NOT TRUE
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS NOT TRUE;
+id	parent_id
+1	1
+2	NULL
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS FALSE;
+id	parent_id
+1	1
+2	NULL
+DROP TABLE parent, child;
+# End of test for bug#11764086.
 End of 5.5 tests.
 #
 # BUG#48920: COUNT DISTINCT returns 1 for NULL values when in a subquery 

=== modified file 'mysql-test/r/subquery_none_jcl6.result'
--- a/mysql-test/r/subquery_none_jcl6.result	2011-02-14 11:21:26 +0000
+++ b/mysql-test/r/subquery_none_jcl6.result	2011-05-05 07:41:53 +0000
@@ -5903,7 +5903,6 @@ Note	1249	Select 2 was reduced during op
 CREATE VIEW v1 AS SELECT 1 LIKE ( 1 IN ( SELECT 1 ) );
 CREATE VIEW v2 AS SELECT 1 LIKE '%' ESCAPE ( 1 IN ( SELECT 1 ) );
 DROP VIEW v1, v2;
-End of 5.1 tests.
 Set up test tables.
 CREATE TABLE t1 (
 t1_id INT UNSIGNED,
@@ -6216,6 +6215,24 @@ id	select_type	table	type	possible_keys
 DROP TABLE t2;
 DROP TABLE t1;
 #
+# Bug #11765713 58705:
+# OPTIMIZER LET ENGINE DEPEND ON UNINITIALIZED VALUES
+# CREATED BY OPT_SUM_QUERY
+#
+CREATE TABLE t1(a INT NOT NULL, KEY (a));
+INSERT INTO t1 VALUES (0), (1);
+SELECT 1 as foo FROM t1 WHERE a < SOME
+(SELECT a FROM t1 WHERE a <=>
+(SELECT a FROM t1)
+);
+ERROR 21000: Subquery returns more than 1 row
+SELECT 1 as foo FROM t1 WHERE a < SOME
+(SELECT a FROM t1 WHERE a <=>
+(SELECT a FROM t1 where a is null)
+);
+foo
+DROP TABLE t1;
+#
 # Bug #57704: Cleanup code dies with void TABLE::set_keyread(bool): 
 #             Assertion `file' failed.
 #
@@ -6227,6 +6244,54 @@ SELECT 1 FROM
 1) FROM t1) AS e;
 ERROR 21000: Operand should contain 1 column(s)
 DROP TABLE t1;
+#
+# Bug#11764086: Null left operand to NOT IN in WHERE clause
+# behaves differently than real NULL
+#
+CREATE TABLE parent (id int);
+INSERT INTO parent VALUES (1), (2);
+CREATE TABLE child (parent_id int, other int);
+INSERT INTO child VALUES (1,NULL);
+# Offending query (c.parent_id is NULL for null-complemented rows only)
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id NOT IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+);
+id	parent_id
+1	1
+2	NULL
+# Some syntactic variations with IS FALSE and IS NOT TRUE
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS NOT TRUE;
+id	parent_id
+1	1
+2	NULL
+SELECT    p.id, c.parent_id
+FROM      parent p
+LEFT JOIN child  c
+ON        p.id = c.parent_id
+WHERE     c.parent_id IN (
+SELECT parent_id 
+FROM   child
+WHERE  parent_id = 3
+) IS FALSE;
+id	parent_id
+1	1
+2	NULL
+DROP TABLE parent, child;
+# End of test for bug#11764086.
 End of 5.5 tests.
 #
 # BUG#48920: COUNT DISTINCT returns 1 for NULL values when in a subquery 

=== modified file 'mysql-test/suite/innodb/r/innodb-index.result'
--- a/mysql-test/suite/innodb/r/innodb-index.result	2010-10-07 11:57:34 +0000
+++ b/mysql-test/suite/innodb/r/innodb-index.result	2011-05-19 12:43:26 +0000
@@ -434,7 +434,6 @@ t3	CREATE TABLE `t3` (
   KEY `c` (`c`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 alter table t2 drop index b, add index (b);
-ERROR 42000: Incorrect index name 'b'
 show create table t2;
 Table	Create Table
 t2	CREATE TABLE `t2` (
@@ -445,8 +444,8 @@ t2	CREATE TABLE `t2` (
   `e` int(11) DEFAULT NULL,
   PRIMARY KEY (`a`),
   UNIQUE KEY `dc` (`d`,`c`),
-  KEY `b` (`b`),
   KEY `c` (`c`),
+  KEY `b` (`b`),
   CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`b`) ON DELETE CASCADE,
   CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`c`) REFERENCES `t3` (`c`),
   CONSTRAINT `t2_ibfk_3` FOREIGN KEY (`d`) REFERENCES `t4` (`d`)

=== modified file 'mysql-test/suite/innodb/r/innodb.result'
--- a/mysql-test/suite/innodb/r/innodb.result	2011-02-21 02:57:30 +0000
+++ b/mysql-test/suite/innodb/r/innodb.result	2011-05-19 12:43:26 +0000
@@ -704,7 +704,6 @@ select count(*) from t1 where cat_code='
 count(*)
 0
 alter table t1 drop index sca_pic, add index (sca_pic, cat_code);
-ERROR 42000: Incorrect index name 'sca_pic'
 alter table t1 drop index sca_pic;
 alter table t1 add index (sca_pic, cat_code);
 select count(*) from t1 where sca_code='PD' and sca_pic is null;
@@ -1673,7 +1672,7 @@ variable_value - @innodb_rows_deleted_or
 71
 SELECT variable_value - @innodb_rows_inserted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_inserted';
 variable_value - @innodb_rows_inserted_orig
-1066
+1069
 SELECT variable_value - @innodb_rows_updated_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_updated';
 variable_value - @innodb_rows_updated_orig
 866

=== modified file 'mysql-test/suite/innodb/r/innodb_mysql.result'
--- a/mysql-test/suite/innodb/r/innodb_mysql.result	2011-05-04 07:51:15 +0000
+++ b/mysql-test/suite/innodb/r/innodb_mysql.result	2011-05-19 12:43:26 +0000
@@ -2843,4 +2843,14 @@ Table	Op	Msg_type	Msg_text
 test.t1	optimize	note	Table does not support optimize, doing recreate + analyze instead
 test.t1	optimize	status	OK
 DROP TABLE t1;
+#
+# Bug#11762345 54927: DROPPING AND ADDING AN INDEX IN ONE
+#              COMMAND CAN FAIL IN INNODB PLUGIN 1.0
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (id int, a  int, b  int, PRIMARY KEY (id),
+INDEX a (a)) ENGINE=innodb;
+ALTER TABLE t1 DROP INDEX a, ADD INDEX a (b, a);
+ALTER TABLE t1 DROP INDEX a, ADD INDEX (a, b);
+DROP TABLE t1;
 End of 6.0 tests

=== modified file 'mysql-test/suite/innodb/t/innodb-index.test'
--- a/mysql-test/suite/innodb/t/innodb-index.test	2010-07-16 21:00:50 +0000
+++ b/mysql-test/suite/innodb/t/innodb-index.test	2011-05-19 12:43:26 +0000
@@ -131,8 +131,6 @@ show create table t4;
 --error ER_CANT_CREATE_TABLE
 alter table t3 add constraint dc foreign key (a) references t1(a);
 show create table t3;
-# this should be fixed by MySQL (see Bug #51451)
---error ER_WRONG_NAME_FOR_INDEX
 alter table t2 drop index b, add index (b);
 show create table t2;
 --error ER_ROW_IS_REFERENCED_2

=== modified file 'mysql-test/suite/innodb/t/innodb.test'
--- a/mysql-test/suite/innodb/t/innodb.test	2011-02-21 02:57:30 +0000
+++ b/mysql-test/suite/innodb/t/innodb.test	2011-05-19 12:43:26 +0000
@@ -452,8 +452,6 @@ alter table t1 add index sca_pic (cat_co
 select count(*) from t1 where sca_code='PD' and sca_pic is null;
 select count(*) from t1 where cat_code='E';
 
-# this should be fixed by MySQL (see Bug #51451)
---error ER_WRONG_NAME_FOR_INDEX
 alter table t1 drop index sca_pic, add index (sca_pic, cat_code);
 alter table t1 drop index sca_pic;
 alter table t1 add index (sca_pic, cat_code);

=== modified file 'mysql-test/suite/innodb/t/innodb_mysql.test'
--- a/mysql-test/suite/innodb/t/innodb_mysql.test	2011-01-17 16:27:07 +0000
+++ b/mysql-test/suite/innodb/t/innodb_mysql.test	2011-05-19 12:43:26 +0000
@@ -1007,4 +1007,23 @@ OPTIMIZE TABLE t1;
 DROP TABLE t1;
 
 
+--echo #
+--echo # Bug#11762345 54927: DROPPING AND ADDING AN INDEX IN ONE
+--echo #              COMMAND CAN FAIL IN INNODB PLUGIN 1.0
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (id int, a  int, b  int, PRIMARY KEY (id),
+                 INDEX a (a)) ENGINE=innodb;
+
+ALTER TABLE t1 DROP INDEX a, ADD INDEX a (b, a);
+# This used to fail
+ALTER TABLE t1 DROP INDEX a, ADD INDEX (a, b);
+
+DROP TABLE t1;
+
+
 --echo End of 6.0 tests

=== modified file 'mysql-test/suite/perfschema/t/no_threads.test'
--- a/mysql-test/suite/perfschema/t/no_threads.test	2010-11-09 08:16:50 +0000
+++ b/mysql-test/suite/perfschema/t/no_threads.test	2011-05-04 09:54:04 +0000
@@ -17,6 +17,7 @@
 
 --source include/not_embedded.inc
 --source include/have_perfschema.inc
+--source include/not_threadpool.inc
 
 
 # Setup : in this main thread

=== modified file 'mysql-test/suite/perfschema/t/one_thread_per_con.test'
--- a/mysql-test/suite/perfschema/t/one_thread_per_con.test	2010-11-08 19:35:17 +0000
+++ b/mysql-test/suite/perfschema/t/one_thread_per_con.test	2011-05-04 09:54:04 +0000
@@ -17,6 +17,7 @@
 
 --source include/not_embedded.inc
 --source include/have_perfschema.inc
+--source include/not_threadpool.inc
 
 # Setup
 

=== modified file 'mysql-test/suite/rpl/r/rpl_checksum.result'
--- a/mysql-test/suite/rpl/r/rpl_checksum.result	2011-03-08 19:12:46 +0000
+++ b/mysql-test/suite/rpl/r/rpl_checksum.result	2011-05-17 22:52:04 +0000
@@ -68,6 +68,7 @@ Last_IO_Error = 'Got fatal error 1236 fr
 select count(*) as zero from t1;
 zero
 0
+include/stop_slave.inc
 set @@global.debug='';
 include/start_slave.inc
 set @@global.master_verify_checksum = 1;
@@ -84,12 +85,13 @@ include/wait_for_slave_io_error.inc [err
 Last_IO_Error = 'Relay log write failure: could not queue event from master'
 set @@global.debug='';
 start slave io_thread;
-include/wait_for_slave_param.inc [Read_Master_Log_Pos]
+include/sync_slave_io_with_master.inc
 set @@global.slave_sql_verify_checksum = 1;
 set @@global.debug='d,simulate_checksum_test_failure';
 start slave sql_thread;
 include/wait_for_slave_sql_error.inc [errno=1593]
 Last_SQL_Error = 'Error initializing relay log position: I/O error reading event at position 4'
+include/stop_slave.inc
 set @@global.debug='';
 include/start_slave.inc
 select count(*) as 'must be zero' from t2;

=== modified file 'mysql-test/suite/rpl/r/rpl_relayspace.result'
--- a/mysql-test/suite/rpl/r/rpl_relayspace.result	2010-12-19 17:15:12 +0000
+++ b/mysql-test/suite/rpl/r/rpl_relayspace.result	2011-05-19 15:47:05 +0000
@@ -1,7 +1,6 @@
 include/master-slave.inc
 [connection master]
-stop slave;
-include/wait_for_slave_to_stop.inc
+include/stop_slave.inc
 create table t1 (a int);
 drop table t1;
 create table t1 (a int);
@@ -9,10 +8,8 @@ drop table t1;
 reset slave;
 start slave io_thread;
 include/wait_for_slave_param.inc [Slave_IO_State]
-stop slave io_thread;
+include/stop_slave_io.inc
 reset slave;
-start slave;
-select master_pos_wait('master-bin.001',200,6)=-1;
-master_pos_wait('master-bin.001',200,6)=-1
-0
+include/start_slave.inc
+include/assert.inc [Assert that master_pos_wait does not timeout nor it returns NULL]
 include/rpl_end.inc

=== modified file 'mysql-test/suite/rpl/t/rpl_checksum.test'
--- a/mysql-test/suite/rpl/t/rpl_checksum.test	2011-03-08 19:12:46 +0000
+++ b/mysql-test/suite/rpl/t/rpl_checksum.test	2011-05-17 22:52:04 +0000
@@ -108,6 +108,11 @@ source include/wait_for_slave_io_error.i
 select count(*) as zero from t1;
 
 ###connection master;
+
+# *always* make sure the slave threads are stopped 
+# or in waiting state before updating the global debug
+# variable (see BUG#11765758 for details).
+--source include/stop_slave.inc
 set @@global.debug='';
 
 connection slave;
@@ -145,27 +150,24 @@ start slave io_thread;
 let $slave_io_errno= 1595; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE
 --let $show_slave_io_error= 1
 source include/wait_for_slave_io_error.inc;
+# no need to stop the IO thread, it is already stopped
 set @@global.debug='';
 
 # to make IO thread re-read it again w/o the failure
 start slave io_thread;
-let $slave_param= Read_Master_Log_Pos;
-let $slave_param_value= $pos_master;
-source include/wait_for_slave_param.inc;
+--connection master
+--source include/sync_slave_io_with_master.inc
 
 # C3. Failure by SQL thread
 # instruction to sql thread;
 set @@global.slave_sql_verify_checksum = 1;
-
 set @@global.debug='d,simulate_checksum_test_failure';
-
 start slave sql_thread;
 let $slave_sql_errno= 1593; # ER_SLAVE_FATAL_ERROR
 --let $show_slave_sql_error= 1
 source include/wait_for_slave_sql_error.inc;
-
+--source include/stop_slave.inc
 # resuming SQL thread to parse out the event w/o the failure
-
 set @@global.debug=''; 
 source include/start_slave.inc;
 

=== modified file 'mysql-test/suite/rpl/t/rpl_relayspace.test'
--- a/mysql-test/suite/rpl/t/rpl_relayspace.test	2010-12-19 17:15:12 +0000
+++ b/mysql-test/suite/rpl/t/rpl_relayspace.test	2011-05-19 15:47:05 +0000
@@ -2,9 +2,9 @@
 # to force the deadlock after one event.
 
 source include/master-slave.inc;
+--let $master_log_file= query_get_value(SHOW MASTER STATUS, File, 1)
 connection slave;
-stop slave;
---source include/wait_for_slave_to_stop.inc
+--source include/stop_slave.inc
 connection master;
 # This will generate a master's binlog > 10 bytes
 create table t1 (a int);
@@ -20,20 +20,33 @@ let $slave_param_value= Waiting for the
 source include/wait_for_slave_param.inc;
 
 # A bug caused the I/O thread to refuse stopping.
-stop slave io_thread;
+--source include/stop_slave_io.inc
 reset slave;
-start slave;
-# The I/O thread stops filling the relay log when
-# it's >10b. And the SQL thread cannot purge this relay log
-# as purge is done only when the SQL thread switches to another
-# relay log, which does not exist here.
-# So we should have a deadlock.
-# if it is not resolved automatically we'll detect
-# it with master_pos_wait that waits for farther than 1Ob;
-# it will timeout after 10 seconds;
-# also the slave will probably not cooperate to shutdown
-# (as 2 threads are locked)
-select master_pos_wait('master-bin.001',200,6)=-1;
+--source include/start_slave.inc
+
+# The I/O thread stops filling the relay log when it's >10b. And the
+# SQL thread cannot purge this relay log as purge is done only when
+# the SQL thread switches to another relay log, which does not exist
+# here.  So we should have a deadlock.  If it is not resolved
+# automatically we'll detect it with master_pos_wait that waits for
+# farther than 1Ob; it will timeout after 300 seconds (which is inline
+# with the default used for sync_slave_with_master and will protect us
+# against slow test envs); also the slave will probably not cooperate
+# to shutdown (as 2 threads are locked)
+--let $outcome= `SELECT MASTER_POS_WAIT('$master_log_file',200,300) AS mpw;`
+
+# master_pos_wait returns:
+#
+# * >= 0, the number of events the slave had to wait to advance to the
+#         position
+#
+# * -1,   if there was a timeout
+#
+# * NULL, if an error occurred, or the SQL thread was not started,
+#         slave master info is not initialized, the arguments are incorrect
+--let $assert_text= Assert that master_pos_wait does not timeout nor it returns NULL
+--let $assert_cond= $outcome IS NOT NULL AND $outcome <> -1
+--source include/assert.inc
 
 # End of 4.1 tests
 --source include/rpl_end.inc

=== modified file 'mysql-test/suite/sys_vars/t/all_vars.test'
--- a/mysql-test/suite/sys_vars/t/all_vars.test	2010-12-08 15:30:01 +0000
+++ b/mysql-test/suite/sys_vars/t/all_vars.test	2011-05-04 09:54:04 +0000
@@ -14,6 +14,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 --source include/not_embedded.inc
+--source include/not_threadpool.inc
 
 # 2010-01-28 OBN Added support to load 'innodb' and 'semisync' if possible.
 # As we need to have there variables loaded if the components exist but do 

=== modified file 'mysql-test/suite/sys_vars/t/slow_launch_time_func.test'
--- a/mysql-test/suite/sys_vars/t/slow_launch_time_func.test	2010-11-17 10:16:13 +0000
+++ b/mysql-test/suite/sys_vars/t/slow_launch_time_func.test	2011-01-14 08:28:23 +0000
@@ -31,6 +31,7 @@
 #
 
 --source include/not_embedded.inc
+--source include/not_threadpool.inc
 
 SET @global_slow_launch_time = @@GLOBAL.slow_launch_time;
 

=== modified file 'mysql-test/suite/sys_vars/t/thread_cache_size_func.test'
--- a/mysql-test/suite/sys_vars/t/thread_cache_size_func.test	2008-12-19 15:12:15 +0000
+++ b/mysql-test/suite/sys_vars/t/thread_cache_size_func.test	2011-01-14 08:28:23 +0000
@@ -28,6 +28,7 @@
 #
 
 --source include/not_embedded.inc
+--source include/not_threadpool.inc
 
 SET @global_thread_cache_size = @@GLOBAL.thread_cache_size;
 

=== modified file 'mysql-test/suite/sys_vars/t/wait_timeout_func.test'
--- a/mysql-test/suite/sys_vars/t/wait_timeout_func.test	2009-03-20 17:11:22 +0000
+++ b/mysql-test/suite/sys_vars/t/wait_timeout_func.test	2011-01-14 08:28:23 +0000
@@ -22,6 +22,7 @@
 ###############################################################################
 
 --source include/not_embedded.inc
+--source include/not_threadpool.inc
 
 SET @start_value= @@global.wait_timeout;
 

=== modified file 'mysql-test/t/func_time.test'
--- a/mysql-test/t/func_time.test	2011-04-27 07:55:04 +0000
+++ b/mysql-test/t/func_time.test	2011-05-18 07:07:52 +0000
@@ -902,6 +902,13 @@ SELECT DATE_FORMAT('0000-00-11', '%W');
 SELECT DATE_FORMAT('0000-00-11', '%a');
 SELECT DATE_FORMAT('0000-00-11', '%w');
 
+--echo #
+--echo # Bug#12403504  AFTER FIX FOR #11889186 : ASSERTION FAILED: DELSUM+(INT) Y/4-TEMP > 0
+--echo #
+
+SELECT MAKEDATE(11111111,1);
+SELECT WEEK(DATE_ADD(FROM_DAYS(1),INTERVAL 1 MONTH), 1);
+
 --echo End of 5.1 tests
 
 --echo #

=== modified file 'mysql-test/t/information_schema.test'
--- a/mysql-test/t/information_schema.test	2011-03-11 18:53:12 +0000
+++ b/mysql-test/t/information_schema.test	2011-05-04 09:54:04 +0000
@@ -1,6 +1,9 @@
 # This test  uses grants, which can't get tested for embedded server
 -- source include/not_embedded.inc
 
+#Don't run this test when thread_pool active
+--source include/not_threadpool.inc
+
 # check that CSV engine was compiled in, as the result of the test depends
 # on the presence of the log tables (which are CSV-based).
 --source include/have_csv.inc

=== modified file 'mysql-test/t/information_schema_db.test'
--- a/mysql-test/t/information_schema_db.test	2009-10-23 11:22:21 +0000
+++ b/mysql-test/t/information_schema_db.test	2010-11-19 13:43:13 +0000
@@ -2,6 +2,9 @@
 # in the embedded server by default). So skip the test in embedded-server mode.
 -- source include/not_embedded.inc
 
+#Don't run this test when thread_pool active
+--source include/not_threadpool.inc
+
 -- source include/testdb_only.inc
 
 --disable_warnings

=== modified file 'mysql-test/t/kill.test'
--- a/mysql-test/t/kill.test	2010-11-18 16:34:56 +0000
+++ b/mysql-test/t/kill.test	2011-05-04 09:54:04 +0000
@@ -9,6 +9,7 @@
 
 -- source include/not_embedded.inc
 -- source include/have_debug_sync.inc
+-- source include/not_threadpool.inc
 
 --disable_warnings
 SET DEBUG_SYNC = 'RESET';

=== modified file 'mysql-test/t/mysqlshow.test'
--- a/mysql-test/t/mysqlshow.test	2010-09-30 10:28:49 +0000
+++ b/mysql-test/t/mysqlshow.test	2011-05-04 09:54:04 +0000
@@ -2,6 +2,8 @@
 -- source include/not_embedded.inc
 # Test lists tables in Information_schema, and InnoDB adds some
 -- source include/have_innodb.inc
+# Don't test when thread_pool active
+--source include/not_threadpool.inc
 
 --disable_warnings
 DROP TABLE IF EXISTS t1,t2,test1,test2;

=== modified file 'mysql-test/t/named_pipe.test'
--- a/mysql-test/t/named_pipe.test	2010-11-17 10:16:13 +0000
+++ b/mysql-test/t/named_pipe.test	2011-01-14 08:46:53 +0000
@@ -3,6 +3,9 @@
 # other platforms
 --source include/windows.inc
 
+# thread pool causes different results
+-- source include/not_threadpool.inc
+
 # Only run this test if named pipe is avaliable
 let $nmp= query_get_value("SHOW VARIABLES LIKE 'named_pipe'", Value, 1);
 if ($nmp != ON){

=== modified file 'mysql-test/t/no-threads.test'
--- a/mysql-test/t/no-threads.test	2007-12-11 22:30:42 +0000
+++ b/mysql-test/t/no-threads.test	2010-11-19 13:43:13 +0000
@@ -1,3 +1,4 @@
+--source include/not_threadpool.inc
 #
 # Test the --thread-handler=no-threads option
 #

=== modified file 'mysql-test/t/shm.test'
--- a/mysql-test/t/shm.test	2010-11-17 10:16:13 +0000
+++ b/mysql-test/t/shm.test	2011-01-14 08:46:53 +0000
@@ -2,6 +2,9 @@
 # to optimize things we skip this test on all other platforms
 --source include/windows.inc
 
+# thread pool causes different results
+-- source include/not_threadpool.inc
+
 # Only run this test if shared memory is avaliable
 let $shm= query_get_value("SHOW VARIABLES LIKE 'shared_memory'", Value, 1);
 if ($shm != ON){

=== modified file 'mysql-test/t/status.test'
--- a/mysql-test/t/status.test	2010-08-06 11:29:37 +0000
+++ b/mysql-test/t/status.test	2011-01-14 08:36:24 +0000
@@ -354,21 +354,6 @@ DROP FUNCTION f1;
 
 # End of 5.1 tests
 
-#
-# Bug#17954 Threads_connected > Threads_created
-#
-
---disable_warnings
-DROP VIEW IF EXISTS v1;
---enable_warnings
-
-CREATE VIEW v1 AS SELECT VARIABLE_NAME AS NAME, CONVERT(VARIABLE_VALUE, UNSIGNED) AS VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS;
-
-SELECT VALUE INTO @tc FROM v1 WHERE NAME = 'Threads_connected';
-SELECT NAME FROM v1 WHERE NAME = 'Threads_created' AND VALUE < @tc;
-
-DROP VIEW v1;
-
 # Restore global concurrent_insert value. Keep in the end of the test file.
 --connection default
 set @@global.concurrent_insert= @old_concurrent_insert;

=== added file 'mysql-test/t/status_bug17954.test'
--- a/mysql-test/t/status_bug17954.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/status_bug17954.test	2011-01-14 08:36:24 +0000
@@ -0,0 +1,54 @@
+# This test requires that --log-output includes 'table', and the general
+# log is on
+
+# embedded server causes different stat
+-- source include/not_embedded.inc
+
+# thread pool causes different results
+-- source include/not_threadpool.inc
+
+# Save the initial number of concurrent sessions
+--source include/count_sessions.inc
+
+# Disable concurrent inserts to avoid sporadic test failures as it might
+# affect the the value of variables used throughout the test case.
+set @old_concurrent_insert= @@global.concurrent_insert;
+set @@global.concurrent_insert= 0;
+
+# Disable logging to table, since this will also cause table locking and unlocking, which will
+# show up in SHOW STATUS and may cause sporadic failures
+
+SET @old_log_output = @@global.log_output;
+SET GLOBAL LOG_OUTPUT = 'FILE';
+
+# PS causes different statistics
+--disable_ps_protocol
+
+flush status;
+
+#
+# Bug#17954 Threads_connected > Threads_created
+#
+
+--disable_warnings
+DROP VIEW IF EXISTS v1;
+--enable_warnings
+
+CREATE VIEW v1 AS SELECT VARIABLE_NAME AS NAME, CONVERT(VARIABLE_VALUE, UNSIGNED) AS VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS;
+
+SELECT VALUE INTO @tc FROM v1 WHERE NAME = 'Threads_connected';
+SELECT NAME FROM v1 WHERE NAME = 'Threads_created' AND VALUE < @tc;
+#SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS where variable_name like '%thread%';
+#SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS;
+#SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES;
+
+DROP VIEW v1;
+
+# Restore global concurrent_insert value. Keep in the end of the test file.
+--connection default
+set @@global.concurrent_insert= @old_concurrent_insert;
+SET GLOBAL log_output = @old_log_output;
+
+# Wait till we reached the initial number of concurrent sessions
+--source include/wait_until_count_sessions.inc
+

=== modified file 'mysys/my_sync.c'
--- a/mysys/my_sync.c	2010-10-19 17:05:25 +0000
+++ b/mysys/my_sync.c	2011-03-04 11:42:20 +0000
@@ -17,6 +17,16 @@
 #include "mysys_err.h"
 #include <errno.h>
 
+static void (*before_sync_wait)(void)= 0;
+static void (*after_sync_wait)(void)= 0;
+
+void thr_set_sync_wait_callback(void (*before_wait)(void),
+                                void (*after_wait)(void))
+{
+  before_sync_wait= before_wait;
+  after_sync_wait= after_wait;
+}
+
 /*
   Sync data in file to disk
 
@@ -46,6 +56,8 @@ int my_sync(File fd, myf my_flags)
   DBUG_ENTER("my_sync");
   DBUG_PRINT("my",("Fd: %d  my_flags: %d", fd, my_flags));
 
+  if (before_sync_wait)
+    (*before_sync_wait)();
   do
   {
 #if defined(F_FULLFSYNC)
@@ -75,6 +87,8 @@ int my_sync(File fd, myf my_flags)
     int er= errno;
     if (!(my_errno= er))
       my_errno= -1;                             /* Unknown error */
+    if (after_sync_wait)
+      (*after_sync_wait)();
     if ((my_flags & MY_IGNORE_BADFD) &&
         (er == EBADF || er == EINVAL || er == EROFS))
     {
@@ -84,6 +98,11 @@ int my_sync(File fd, myf my_flags)
     else if (my_flags & MY_WME)
       my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno);
   }
+  else
+  {
+    if (after_sync_wait)
+      (*after_sync_wait)();
+  }
   DBUG_RETURN(res);
 } /* my_sync */
 

=== modified file 'sql/debug_sync.cc'
--- a/sql/debug_sync.cc	2011-04-19 03:29:06 +0000
+++ b/sql/debug_sync.cc	2011-05-04 09:54:04 +0000
@@ -1742,11 +1742,20 @@ static void debug_sync_execute(THD *thd,
         We don't use enter_cond()/exit_cond(). They do not save old
         mutex and cond. This would prohibit the use of DEBUG_SYNC
         between other places of enter_cond() and exit_cond().
+
+        We need to check for existence of thd->mysys_var to also make
+        it possible to use DEBUG_SYNC framework in scheduler when this
+        variable has been set to NULL.
       */
-      old_mutex= thd->mysys_var->current_mutex;
-      old_cond= thd->mysys_var->current_cond;
-      thd->mysys_var->current_mutex= &debug_sync_global.ds_mutex;
-      thd->mysys_var->current_cond= &debug_sync_global.ds_cond;
+      if (thd->mysys_var)
+      {
+        old_mutex= thd->mysys_var->current_mutex;
+        old_cond= thd->mysys_var->current_cond;
+        thd->mysys_var->current_mutex= &debug_sync_global.ds_mutex;
+        thd->mysys_var->current_cond= &debug_sync_global.ds_cond;
+      }
+      else
+        old_mutex= NULL;
 
       set_timespec(abstime, action->timeout);
       DBUG_EXECUTE("debug_sync_exec", {
@@ -1801,11 +1810,16 @@ static void debug_sync_execute(THD *thd,
         is locked. (See comment in THD::exit_cond().)
       */
       mysql_mutex_unlock(&debug_sync_global.ds_mutex);
-      mysql_mutex_lock(&thd->mysys_var->mutex);
-      thd->mysys_var->current_mutex= old_mutex;
-      thd->mysys_var->current_cond= old_cond;
-      thd_proc_info(thd, old_proc_info);
-      mysql_mutex_unlock(&thd->mysys_var->mutex);
+      if (old_mutex)
+      {
+        mysql_mutex_lock(&thd->mysys_var->mutex);
+        thd->mysys_var->current_mutex= old_mutex;
+        thd->mysys_var->current_cond= old_cond;
+        thd_proc_info(thd, old_proc_info);
+        mysql_mutex_unlock(&thd->mysys_var->mutex);
+      }
+      else
+        thd_proc_info(thd, old_proc_info);
     }
     else
     {

=== modified file 'sql/debug_sync.h'
--- a/sql/debug_sync.h	2011-03-22 11:44:40 +0000
+++ b/sql/debug_sync.h	2011-05-04 09:54:04 +0000
@@ -35,7 +35,7 @@ class THD;
              } while (0)
 
 /* Command line option --debug-sync-timeout. See mysqld.cc. */
-extern uint opt_debug_sync_timeout;
+extern MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout;
 
 /* Default WAIT_FOR timeout if command line option is given without argument. */
 #define DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT 300

=== modified file 'sql/filesort.cc'
--- a/sql/filesort.cc	2011-04-04 08:47:25 +0000
+++ b/sql/filesort.cc	2011-05-02 13:22:25 +0000
@@ -1226,7 +1226,7 @@ bool check_if_pq_applicable(Sort_param *
                                        row_length);
       /*
         PQ has cost:
-        (insert + qsort) * log(queue size) / TIME_FOR_COMPARE_ROWID +
+        (insert + qsort) * log(queue size) * ROWID_COMPARE_COST +
         cost of file lookup afterwards.
         The lookup cost is a bit pessimistic: we take scan_time and assume
         that on average we find the row after scanning half of the file.
@@ -1235,7 +1235,7 @@ bool check_if_pq_applicable(Sort_param *
       */
       const double pq_cpu_cost= 
         (PQ_slowness * num_rows + param->max_keys_per_buffer) *
-        log((double) param->max_keys_per_buffer) / TIME_FOR_COMPARE_ROWID;
+        log((double) param->max_keys_per_buffer) * ROWID_COMPARE_COST;
       const double pq_io_cost=
         param->max_rows * table->file->scan_time() / 2.0;
       const double pq_cost= pq_cpu_cost + pq_io_cost;

=== modified file 'sql/filesort_utils.cc'
--- a/sql/filesort_utils.cc	2010-12-17 09:41:21 +0000
+++ b/sql/filesort_utils.cc	2011-05-02 13:22:25 +0000
@@ -26,8 +26,7 @@ double get_merge_cost(ha_rows num_elemen
 {
   return 
     2.0 * ((double) num_elements * elem_size) / IO_SIZE
-    + (double) num_elements * log((double) num_buffers) /
-      (TIME_FOR_COMPARE_ROWID * M_LN2);
+    + num_elements * log((double) num_buffers) * ROWID_COMPARE_COST / M_LN2;
 }
 }
 
@@ -49,8 +48,7 @@ double get_merge_many_buffs_cost_fast(ha
   // Calculate CPU cost of sorting buffers.
   total_cost=
     ( num_buffers * num_keys_per_buffer * log(1.0 + num_keys_per_buffer) +
-      last_n_elems * log(1.0 + last_n_elems) )
-    / TIME_FOR_COMPARE_ROWID;
+      last_n_elems * log(1.0 + last_n_elems) ) * ROWID_COMPARE_COST;
   
   // Simulate behavior of merge_many_buff().
   while (num_buffers >= MERGEBUFF2)

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2011-05-12 17:29:19 +0000
+++ b/sql/ha_ndbcluster.cc	2011-05-18 10:43:46 +0000
@@ -9042,7 +9042,7 @@ ha_ndbcluster::multi_range_read_info_con
       cost->io_count= index_only_read_time(keyno, total_rows);
     else
       cost->io_count= read_time(keyno, n_ranges, total_rows);
-    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
+    cost->cpu_cost= total_rows * ROW_EVALUATE_COST + 0.01;
   }
   return total_rows;
 }

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2011-05-17 13:51:11 +0000
+++ b/sql/handler.cc	2011-05-19 16:52:11 +0000
@@ -4549,7 +4549,7 @@ handler::multi_range_read_info_const(uin
       cost->io_count= index_only_read_time(keyno, total_rows);
     else
       cost->io_count= read_time(keyno, n_ranges, total_rows);
-    cost->cpu_cost= (double) total_rows / TIME_FOR_COMPARE + 0.01;
+    cost->cpu_cost= total_rows * ROW_EVALUATE_COST + 0.01;
   }
   return total_rows;
 }
@@ -4774,19 +4774,19 @@ int DsMrr_impl::dsmrr_init(handler *h_ar
   /* 
     This assert will hit if we have pushed an index condition to the
     primary key index and then "change our mind" and use a different
-    index for retrieving data with MRR.
-
-    This assert is too strict for the existing code. If an index
-    condition has been pushed on the primary index the existing code
-    does not clean up information about the pushed index condition when
-    the index scan is completed. Disables the assert until we have
-    a fix for better cleaning up after a pushed index condition. 
+    index for retrieving data with MRR. One of the following criteria
+    must be true:
+      1. We have not pushed an index conditon on this handler.
+      2. We have pushed an index condition and this is on the currently used
+         index.
+      3. We have pushed an index condition but this is not for the primary key.
+      4. We have pushed an index condition and this has been transferred to 
+         the clone (h2) of the handler object.
   */
-  /*
   DBUG_ASSERT(!h->pushed_idx_cond ||
               h->pushed_idx_cond_keyno == h->active_index ||
-              h->pushed_idx_cond_keyno != table->s->primary_key);
-  */
+              h->pushed_idx_cond_keyno != table->s->primary_key ||
+              (h2 && h->pushed_idx_cond_keyno == h2->active_index));
 
   rowids_buf= buf->buffer;
 
@@ -4859,7 +4859,26 @@ int DsMrr_impl::dsmrr_init(handler *h_ar
     /*
       We get here when the access alternates betwen MRR scan(s) and non-MRR
       scans.
+    */
 
+    /* 
+      Verify consistency between the two handler objects:
+      1. The main handler should either use the primary key or not have an
+         active index at this point since the clone handler (h2) is used for
+         reading the index.
+      2. The index used for ICP should be the same for the two handlers or
+         it should not be set on the clone handler (h2).
+      3. The ICP function should be the same for the two handlers or it should
+         not be set for the clone handler (h2).
+    */
+    DBUG_ASSERT(h->active_index == table->s->primary_key ||
+                h->active_index == MAX_KEY);
+    DBUG_ASSERT(h->pushed_idx_cond_keyno == h2->pushed_idx_cond_keyno || 
+                h2->pushed_idx_cond_keyno == MAX_KEY);
+    DBUG_ASSERT(h->pushed_idx_cond == h2->pushed_idx_cond || 
+                h2->pushed_idx_cond == NULL);
+
+    /*
       Calling h->index_end() will invoke dsmrr_close() for this object,
       which will delete h2. We need to keep it, so save put it away and dont
       let it be deleted:
@@ -5295,7 +5314,7 @@ void get_sort_and_sweep_cost(TABLE *tabl
   {
     get_sweep_read_cost(table, nrows, FALSE, cost);
     /* Add cost of qsort call: n * log2(n) * cost(rowid_comparison) */
-    double cmp_op= rows2double(nrows) * (1.0 / TIME_FOR_COMPARE_ROWID);
+    double cmp_op= rows2double(nrows) * ROWID_COMPARE_COST;
     if (cmp_op < 3)
       cmp_op= 3;
     cost->cpu_cost += cmp_op * log2(cmp_op);

=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc	2011-05-06 13:32:53 +0000
+++ b/sql/item_cmpfunc.cc	2011-05-18 10:43:46 +0000
@@ -1764,6 +1764,17 @@ bool Item_in_optimizer::fix_fields(THD *
   with_sum_func= with_sum_func || args[1]->with_sum_func;
   used_tables_cache|= args[1]->used_tables();
   not_null_tables_cache|= args[1]->not_null_tables();
+
+  if (!sub->is_top_level_item())
+  {
+    /*
+      This is a NOT IN subquery predicate (or equivalent). Null values passed
+      from outer tables and used in the left-hand expression of the predicate
+      must be considered in the evaluation, hence filter out these tables
+      from the set of null-rejecting tables.
+    */
+    not_null_tables_cache&= ~args[0]->not_null_tables();
+  }
   const_item_cache&= args[1]->const_item();
   fixed= 1;
   return FALSE;
@@ -1791,6 +1802,7 @@ void Item_in_optimizer::fix_after_pullou
   const_item_cache&= args[1]->const_item();
 }
 
+
 /**
    The implementation of optimized \<outer expression\> [NOT] IN \<subquery\>
    predicates. The implementation works as follows.

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2011-05-10 13:37:37 +0000
+++ b/sql/item_func.cc	2011-05-12 18:44:56 +0000
@@ -47,6 +47,8 @@
 #include "sp.h"
 #include "set_var.h"
 #include "debug_sync.h"
+#include <mysql/plugin.h>
+#include <mysql/service_thd_wait.h>
 
 #ifdef NO_EMBEDDED_ACCESS_CHECKS
 #define sp_restore_security_context(A,B) while (0) {}
@@ -3899,6 +3901,7 @@ longlong Item_func_get_lock::val_int()
   timed_cond.set_timeout(timeout * ULL(1000000000));
 
   error= 0;
+  thd_wait_begin(thd, THD_WAIT_USER_LOCK);
   while (ull->locked && !thd->killed)
   {
     DBUG_PRINT("info", ("waiting on lock"));
@@ -3910,6 +3913,7 @@ longlong Item_func_get_lock::val_int()
     }
     error= 0;
   }
+  thd_wait_end(thd);
 
   if (ull->locked)
   {
@@ -4126,6 +4130,7 @@ longlong Item_func_sleep::val_int()
   thd->mysys_var->current_cond=  &cond;
 
   error= 0;
+  thd_wait_begin(thd, THD_WAIT_SLEEP);
   while (!thd->killed)
   {
     error= timed_cond.wait(&cond, &LOCK_user_locks);
@@ -4133,6 +4138,7 @@ longlong Item_func_sleep::val_int()
       break;
     error= 0;
   }
+  thd_wait_end(thd);
   mysql_mutex_unlock(&LOCK_user_locks);
   mysql_mutex_lock(&thd->mysys_var->mutex);
   thd->mysys_var->current_mutex= 0;

=== modified file 'sql/item_func.h'
--- a/sql/item_func.h	2011-04-15 09:04:21 +0000
+++ b/sql/item_func.h	2011-05-05 07:41:53 +0000
@@ -37,7 +37,11 @@ protected:
   uint allowed_arg_cols;
 public:
   uint arg_count;
-  table_map used_tables_cache, not_null_tables_cache;
+  /// Value used in calculation of result of used_tables()
+  table_map used_tables_cache;
+  /// Value used in calculation of result of not_null_tables()
+  table_map not_null_tables_cache;
+  /// Value used in calculation of result of const_item()
   bool const_item_cache;
   enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
 		  GE_FUNC,GT_FUNC,FT_FUNC,

=== modified file 'sql/item_timefunc.cc'
--- a/sql/item_timefunc.cc	2011-05-10 13:41:34 +0000
+++ b/sql/item_timefunc.cc	2011-05-18 07:07:52 +0000
@@ -1588,6 +1588,11 @@ bool Item_func_from_days::get_date(MYSQL
     return 1;
   bzero(ltime, sizeof(MYSQL_TIME));
   get_date_from_daynr((long) value, &ltime->year, &ltime->month, &ltime->day);
+
+  if ((null_value= (fuzzy_date & TIME_NO_ZERO_DATE) &&
+       (ltime->year == 0 || ltime->month == 0 || ltime->day == 0)))
+    return TRUE;
+
   ltime->time_type= MYSQL_TIMESTAMP_DATE;
   return 0;
 }
@@ -2776,7 +2781,7 @@ String *Item_func_makedate::val_str(Stri
   long days;
 
   if (args[0]->null_value || args[1]->null_value ||
-      year < 0 || daynr <= 0)
+      year < 0 || year > 9999 || daynr <= 0)
     goto err;
 
   if (year < 100)
@@ -2819,7 +2824,7 @@ longlong Item_func_makedate::val_int()
   long days;
 
   if (args[0]->null_value || args[1]->null_value ||
-      year < 0 || daynr <= 0)
+      year < 0 || year > 9999 || daynr <= 0)
     goto err;
 
   if (year < 100)

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2011-05-12 15:02:29 +0000
+++ b/sql/log.cc	2011-05-12 18:44:56 +0000
@@ -2485,7 +2485,7 @@ int TC_LOG_MMAP::open(const char *opt_na
   {
     pg->next=pg+1;
     pg->waiters=0;
-    pg->state=POOL;
+    pg->state=PS_POOL;
     mysql_mutex_init(key_PAGE_lock, &pg->lock, MY_MUTEX_INIT_FAST);
     mysql_cond_init(key_PAGE_cond, &pg->cond, 0);
     pg->start=(my_xid *)(data + i*tc_log_page_size);
@@ -2659,7 +2659,7 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xi
   cookie= (ulong)((uchar *)p->ptr - data);      // can never be zero
   *p->ptr++= xid;
   p->free--;
-  p->state= DIRTY;
+  p->state= PS_DIRTY;
 
   /* to sync or not to sync - this is the question */
   mysql_mutex_unlock(&LOCK_active);
@@ -2671,13 +2671,13 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xi
     p->waiters++;
     /*
       note - it must be while (), not do ... while () here
-      as p->state may be not DIRTY when we come here
+      as p->state may be not PS_DIRTY when we come here
     */
-    while (p->state == DIRTY && syncing)
+    while (p->state == PS_DIRTY && syncing)
       mysql_cond_wait(&p->cond, &LOCK_sync);
     p->waiters--;
-    err= p->state == ERROR;
-    if (p->state != DIRTY)                   // page was synced
+    err= p->state == PS_ERROR;
+    if (p->state != PS_DIRTY)                   // page was synced
     {
       if (p->waiters == 0)
         mysql_cond_signal(&COND_pool);       // in case somebody's waiting
@@ -2715,7 +2715,7 @@ int TC_LOG_MMAP::sync()
   pool_last->next=syncing;
   pool_last=syncing;
   syncing->next=0;
-  syncing->state= err ? ERROR : POOL;
+  syncing->state= err ? PS_ERROR : PS_POOL;
   mysql_cond_broadcast(&syncing->cond);      // signal "sync done"
   mysql_cond_signal(&COND_pool);             // in case somebody's waiting
   mysql_mutex_unlock(&LOCK_pool);

=== modified file 'sql/log.h'
--- a/sql/log.h	2011-03-10 10:08:09 +0000
+++ b/sql/log.h	2011-05-04 09:54:04 +0000
@@ -51,9 +51,9 @@ class TC_LOG_MMAP: public TC_LOG
 {
   public:                // only to keep Sun Forte on sol9x86 happy
   typedef enum {
-    POOL,                 // page is in pool
-    ERROR,                // last sync failed
-    DIRTY                 // new xids added since last sync
+    PS_POOL,                 // page is in pool
+    PS_ERROR,                // last sync failed
+    PS_DIRTY                 // new xids added since last sync
   } PAGE_STATE;
 
   private:

=== modified file 'sql/mdl.cc'
--- a/sql/mdl.cc	2011-04-19 03:29:06 +0000
+++ b/sql/mdl.cc	2011-05-13 12:39:59 +0000
@@ -18,6 +18,8 @@
 #include "debug_sync.h"
 #include <hash.h>
 #include <mysqld_error.h>
+#include <mysql/plugin.h>
+#include <mysql/service_thd_wait.h>
 
 #ifdef HAVE_PSI_INTERFACE
 static PSI_mutex_key key_MDL_map_mutex;
@@ -970,10 +972,14 @@ MDL_wait::timed_wait(MDL_context_owner *
 
   old_msg= owner->enter_cond(&m_COND_wait_status, &m_LOCK_wait_status,
                              wait_state_name);
+  thd_wait_begin(NULL, THD_WAIT_META_DATA_LOCK);
   while (!m_wait_status && !owner->is_killed() &&
          wait_result != ETIMEDOUT && wait_result != ETIME)
+  {
     wait_result= mysql_cond_timedwait(&m_COND_wait_status, &m_LOCK_wait_status,
                                       abs_timeout);
+  }
+  thd_wait_end(NULL);
 
   if (m_wait_status == EMPTY)
   {

=== added file 'sql/mem_root_array.h'
--- a/sql/mem_root_array.h	1970-01-01 00:00:00 +0000
+++ b/sql/mem_root_array.h	2011-05-18 08:29:46 +0000
@@ -0,0 +1,175 @@
+/* Copyright (c) 2011, 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 MEM_ROOT_ARRAY_INCLUDED
+#define MEM_ROOT_ARRAY_INCLUDED
+
+#include <my_alloc.h>
+
+/**
+   A typesafe replacement for DYNAMIC_ARRAY.
+   We use MEM_ROOT for allocating storage, rather than the C++ heap.
+   The interface is chosen to be similar to std::vector.
+
+   @remark
+   Unlike DYNAMIC_ARRAY, elements are properly copied
+   (rather than memcpy()d) if the underlying array needs to be expanded.
+
+   @remark
+   Depending on has_trivial_destructor, we destroy objects which are
+   removed from the array (including when the array object itself is destroyed).
+
+   @remark
+   Note that MEM_ROOT has no facility for reusing free space,
+   so don't use this if multiple re-expansions are likely to happen.
+
+   @param Element_type The type of the elements of the container.
+          Elements must be copyable.
+   @param has_trivial_destructor If true, we don't destroy elements.
+          We could have used type traits to determine this.
+          __has_trivial_destructor is supported by some (but not all)
+          compilers we use.
+*/
+template<typename Element_type, bool has_trivial_destructor>
+class Mem_root_array
+{
+public:
+  Mem_root_array(MEM_ROOT *root)
+    : m_root(root), m_array(NULL), m_size(0), m_capacity(0)
+  {
+    DBUG_ASSERT(m_root != NULL);
+  }
+
+  ~Mem_root_array()
+  {
+    clear();
+  }
+
+  Element_type &at(size_t n)
+  {
+    DBUG_ASSERT(n < size());
+    return m_array[n];
+  }
+
+  const Element_type &at(size_t n) const
+  {
+    DBUG_ASSERT(n < size());
+    return m_array[n];
+  }
+
+  // Returns a pointer to the first element in the array.
+  Element_type *begin() { return &m_array[0]; }
+
+  // Returns a pointer to the past-the-end element in the array.
+  Element_type *end() { return &m_array[size()]; }
+
+  // Erases all of the elements. 
+  void clear()
+  {
+    if (!empty())
+      chop(0);
+  }
+
+  /*
+    Chops the tail off the array, erasing all tail elements.
+    @param pos Index of first element to erase.
+  */
+  void chop(const size_t pos)
+  {
+    DBUG_ASSERT(pos < m_size);
+    if (!has_trivial_destructor)
+    {
+      for (size_t ix= pos; ix < m_size; ++ix)
+      {
+        Element_type *p= &m_array[ix];
+        p->~Element_type();              // Destroy discarded element.
+      }
+    }
+    m_size= pos;
+  }
+
+  /*
+    Reserves space for array elements.
+    Copies over existing elements, in case we are re-expanding the array.
+
+    @param  n number of elements.
+    @retval true if out-of-memory, false otherwise.
+  */
+  bool reserve(size_t n)
+  {
+    if (n <= m_capacity)
+      return false;
+
+    void *mem= alloc_root(m_root, n * element_size());
+    if (!mem)
+      return true;
+    Element_type *array= static_cast<Element_type*>(mem);
+
+    // Copy all the existing elements into the new array.
+    for (size_t ix= 0; ix < m_size; ++ix)
+    {
+      Element_type *new_p= &array[ix];
+      Element_type *old_p= &m_array[ix];
+      new (new_p) Element_type(*old_p);         // Copy into new location.
+      if (!has_trivial_destructor)
+        old_p->~Element_type();                 // Destroy the old element.
+    }
+
+    // Forget the old array.
+    m_array= array;
+    m_capacity= n;
+    return false;
+  }
+
+  /*
+    Adds a new element at the end of the array, after its current last
+    element. The content of this new element is initialized to a copy of
+    the input argument.
+
+    @param  element Object to copy.
+    @retval true if out-of-memory, false otherwise.
+  */
+  bool push_back(const Element_type &element)
+  {
+    const size_t min_capacity= 20;
+    const size_t expansion_factor= 2;
+    if (0 == m_capacity && reserve(min_capacity))
+      return true;
+    if (m_size == m_capacity && reserve(m_capacity * expansion_factor))
+      return true;
+    Element_type *p= &m_array[m_size++];
+    new (p) Element_type(element);
+    return false;
+  }
+
+  size_t capacity()     const { return m_capacity; }
+  size_t element_size() const { return sizeof(Element_type); }
+  bool   empty()        const { return size() == 0; }
+  size_t size()         const { return m_size; }
+
+private:
+  MEM_ROOT *const m_root;
+  Element_type   *m_array;
+  size_t          m_size;
+  size_t          m_capacity;
+
+  // Not (yet) implemented.
+  Mem_root_array(const Mem_root_array&);
+  Mem_root_array &operator=(const Mem_root_array&);
+};
+
+
+#endif  // MEM_ROOT_ARRAY_INCLUDED

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2011-05-17 13:51:11 +0000
+++ b/sql/mysqld.cc	2011-05-19 16:52:11 +0000
@@ -417,7 +417,7 @@ my_bool opt_super_large_pages= 0;
 my_bool opt_myisam_use_mmap= 0;
 uint   opt_large_page_size= 0;
 #if defined(ENABLED_DEBUG_SYNC)
-uint    opt_debug_sync_timeout= 0;
+MYSQL_PLUGIN_IMPORT uint    opt_debug_sync_timeout= 0;
 #endif /* defined(ENABLED_DEBUG_SYNC) */
 my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
 /*
@@ -2020,6 +2020,36 @@ extern "C" sig_handler end_thread_signal
 
 
 /*
+  Decrease number of connections
+
+  SYNOPSIS
+    dec_connection_count()
+*/
+
+void dec_connection_count()
+{
+  mysql_mutex_lock(&LOCK_connection_count);
+  --connection_count;
+  mysql_mutex_unlock(&LOCK_connection_count);
+}
+
+
+/*
+  Delete the THD object and decrease number of threads
+
+  SYNOPSIS
+    delete_thd()
+    thd		 Thread handler
+*/
+
+void delete_thd(THD *thd)
+{
+  thread_count--;
+  delete thd;
+}
+
+
+/*
   Unlink thd from global list of available connections and free thd
 
   SYNOPSIS
@@ -2034,15 +2064,10 @@ void unlink_thd(THD *thd)
 {
   DBUG_ENTER("unlink_thd");
   DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
-  thd->cleanup();
-
-  mysql_mutex_lock(&LOCK_connection_count);
-  --connection_count;
-  mysql_mutex_unlock(&LOCK_connection_count);
 
+  dec_connection_count();
   mysql_mutex_lock(&LOCK_thread_count);
-  thread_count--;
-  delete thd;
+  delete_thd(thd);
   DBUG_VOID_RETURN;
 }
 
@@ -5266,6 +5291,14 @@ static bool read_init_file(char *file_na
 }
 
 
+/**
+  Increment number of created threads
+*/
+void inc_thread_created(void)
+{
+  thread_created++;
+}
+
 #ifndef EMBEDDED_LIBRARY
 
 /*

=== modified file 'sql/mysqld.h'
--- a/sql/mysqld.h	2011-05-13 13:59:55 +0000
+++ b/sql/mysqld.h	2011-05-19 09:11:38 +0000
@@ -231,6 +231,10 @@ extern char err_shared_dir[];
 extern TYPELIB thread_handling_typelib;
 extern my_decimal decimal_zero;
 
+/*
+  THR_MALLOC is a key which will be used to set/get MEM_ROOT** for a thread,
+  using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr().
+*/
 extern pthread_key(MEM_ROOT**,THR_MALLOC);
 
 #ifdef HAVE_PSI_INTERFACE
@@ -632,6 +636,10 @@ get_thread_running()
 extern "C" THD *_current_thd_noinline();
 #define _current_thd() _current_thd_noinline()
 #else
+/*
+  THR_THD is a key which will be used to set/get THD* for a thread,
+  using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr().
+*/
 extern pthread_key(THD*, THR_THD);
 inline THD *_current_thd(void)
 {

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2011-05-06 13:26:31 +0000
+++ b/sql/opt_range.cc	2011-05-19 12:03:55 +0000
@@ -2223,8 +2223,8 @@ int SQL_SELECT::test_quick_select(THD *t
   records= head->file->stats.records;
   if (!records)
     records++;					/* purecov: inspected */
-  scan_time= (double) records / TIME_FOR_COMPARE + 1;
-  read_time= (double) head->file->scan_time() + scan_time + 1.1;
+  scan_time= records * ROW_EVALUATE_COST + 1;
+  read_time= head->file->scan_time() + scan_time + 1.1;
   if (head->force_index)
     scan_time= read_time= DBL_MAX;
   if (limit < records)
@@ -2324,7 +2324,7 @@ int SQL_SELECT::test_quick_select(THD *t
       double key_read_time= 
         param.table->file->index_only_read_time(key_for_use, 
                                                 rows2double(records)) +
-        (double) records / TIME_FOR_COMPARE;
+        records * ROW_EVALUATE_COST;
       DBUG_PRINT("info",  ("'all'+'using index' scan will be using key %d, "
                            "read time %g", key_for_use, key_read_time));
       if (key_read_time < read_time)
@@ -3877,7 +3877,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick
       Add one ROWID comparison for each row retrieved on non-CPK scan.  (it
       is done in QUICK_RANGE_SELECT::row_in_ranges)
      */
-    imerge_cost += non_cpk_scan_records / TIME_FOR_COMPARE_ROWID;
+    imerge_cost += non_cpk_scan_records * ROWID_COMPARE_COST;
   }
 
   /* Calculate cost(rowid_to_row_scan) */
@@ -3966,7 +3966,7 @@ skip_to_ror_scan:
       cost= param->table->file->
               read_time(param->real_keynr[(*cur_child)->key_idx], 1,
                         (*cur_child)->records) +
-              rows2double((*cur_child)->records) / TIME_FOR_COMPARE;
+              rows2double((*cur_child)->records) * ROW_EVALUATE_COST;
     }
     else
       cost= read_time;
@@ -4013,8 +4013,8 @@ skip_to_ror_scan:
     get_sweep_read_cost(param->table, roru_total_records, is_interrupted,
                         &sweep_cost);
     roru_total_cost= roru_index_costs +
-                     rows2double(roru_total_records)*log((double)n_child_scans) /
-                     (TIME_FOR_COMPARE_ROWID * M_LN2) +
+                     rows2double(roru_total_records) *
+                     log((double)n_child_scans) * ROWID_COMPARE_COST / M_LN2 +
                      sweep_cost.total_cost();
   }
 
@@ -4469,11 +4469,11 @@ static bool ror_intersect_add(ROR_INTERS
   {
     /*
       CPK scan is used to filter out rows. We apply filtering for 
-      each record of every scan. Assuming 1/TIME_FOR_COMPARE_ROWID
+      each record of every scan. Assuming ROWID_COMPARE_COST
       per check this gives us:
     */
-    info->index_scan_costs += rows2double(info->index_records) / 
-                              TIME_FOR_COMPARE_ROWID;
+    info->index_scan_costs += rows2double(info->index_records) * 
+                              ROWID_COMPARE_COST;
   }
   else
   {
@@ -4856,9 +4856,9 @@ TRP_ROR_INTERSECT *get_best_covering_ror
                                            tree->ror_scans, ror_scan_mark););
 
   /* Add priority queue use cost. */
-  total_cost += rows2double(records)*
-                log((double)(ror_scan_mark - tree->ror_scans)) /
-                (TIME_FOR_COMPARE_ROWID * M_LN2);
+  total_cost += rows2double(records) *
+                log((double)(ror_scan_mark - tree->ror_scans)) *
+                ROWID_COMPARE_COST / M_LN2;
   DBUG_PRINT("info", ("Covering ROR-intersect full cost: %g", total_cost));
 
   if (total_cost > read_time)
@@ -7069,11 +7069,53 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *
         This is the case ("cmp>=0" means that tmp.max >= key2.min):
         key2:              [----]
         tmp:     [------------*****]
+      */
+
+      if (!tmp->next_key_part)
+      {
+        /*
+          tmp->next_key_part is empty: cut the range that is covered
+          by tmp from key2. 
+          Reason: (key2->next_key_part OR tmp->next_key_part) will be
+          empty and therefore equal to tmp->next_key_part. Thus, this
+          part of the key2 range is completely covered by tmp.
+        */
+        if (tmp->cmp_max_to_max(key2) >= 0)
+        {
+          /*
+            tmp covers the entire range in key2. 
+            key2:              [----]
+            tmp:     [-----------------]
+
+            Move on to next range in key2
+          */
+          key2->increment_use_count(-1); // Free not used tree
+          key2=key2->next;
+          continue;
+        }
+        else
+        {
+          /*
+            This is the case:
+            key2:           [-------]
+            tmp:     [---------]
+
+            Result:
+            key2:               [---]
+            tmp:     [---------]
+          */
+          key2->copy_max_to_min(tmp);
+          continue;
+        }
+      }
 
+      /*
         The ranges are overlapping but have not been merged because
-        next_key_part of tmp and key2 are different
+        next_key_part of tmp and key2 differ. 
+        key2:              [----]
+        tmp:     [------------*****]
 
-        Result:
+        Split tmp in two where key2 starts:
         key2:              [----]
         key1:    [--------][--*****]
                  ^         ^
@@ -7082,7 +7124,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *
       SEL_ARG *new_arg=tmp->clone_first(key2);
       if (!new_arg)
         return 0;                               // OOM
-      if ((new_arg->next_key_part= key1->next_key_part))
+      if ((new_arg->next_key_part= tmp->next_key_part))
         new_arg->increment_use_count(key1->use_count+1);
       tmp->copy_min_to_min(key2);
       key1=key1->insert(new_arg);
@@ -7191,12 +7233,21 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *
                       ^        ^
                       new_arg  tmp
           Steps:
+           0) If tmp->next_key_part is empty: do nothing. Reason:
+              (key2_cpy->next_key_part OR tmp->next_key_part) will be
+              empty and therefore equal to tmp->next_key_part. Thus,
+              the range in key2_cpy is completely covered by tmp
            1) Make new_arg with range [tmp.min, key2_cpy.max].
               new_arg->next_key_part is OR between next_key_part
               of tmp and key2_cpy
            2) Make tmp the range [key2.max, tmp.max]
            3) Insert new_arg into key1
         */
+        if (!tmp->next_key_part) // Step 0
+        {
+          key2_cpy.increment_use_count(-1);     // Free not used tree
+          break;
+        }
         SEL_ARG *new_arg=tmp->clone_last(&key2_cpy);
         if (!new_arg)
           return 0; // OOM
@@ -10776,7 +10827,7 @@ void cost_group_min_max(TABLE* table, KE
     no CPU cost. We leave it here to make this cost comparable to that of index
     scan as computed in SQL_SELECT::test_quick_select().
   */
-  cpu_cost= (double) num_groups / TIME_FOR_COMPARE;
+  cpu_cost= num_groups * ROW_EVALUATE_COST;
 
   *read_cost= io_cost + cpu_cost;
   *records= num_groups;

=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc	2011-05-13 13:59:55 +0000
+++ b/sql/rpl_rli.cc	2011-05-19 08:48:55 +0000
@@ -27,6 +27,8 @@
 #include "transaction.h"
 #include "sql_parse.h"                          // end_trans, ROLLBACK
 #include "rpl_slave.h"
+#include <mysql/plugin.h>
+#include <mysql/service_thd_wait.h>
 
 /*
   Please every time you add a new field to the relay log info, update
@@ -534,6 +536,7 @@ int Relay_log_info::wait_for_pos(THD* th
       We are going to mysql_cond_(timed)wait(); if the SQL thread stops it
       will wake us up.
     */
+    thd_wait_begin(thd, THD_WAIT_BINLOG);
     if (timeout > 0)
     {
       /*
@@ -551,6 +554,7 @@ int Relay_log_info::wait_for_pos(THD* th
     }
     else
       mysql_cond_wait(&data_cond, &data_lock);
+    thd_wait_end(thd);
     DBUG_PRINT("info",("Got signal of master update or timed out"));
     if (error == ETIMEDOUT || error == ETIME)
     {

=== modified file 'sql/scheduler.cc'
--- a/sql/scheduler.cc	2011-03-22 11:44:40 +0000
+++ b/sql/scheduler.cc	2011-05-04 09:54:04 +0000
@@ -76,14 +76,26 @@ scheduler_functions *thread_scheduler= N
 */
 
 /**@{*/
-static void scheduler_wait_begin(void) {
+extern "C"
+{
+static void scheduler_wait_lock_begin(void) {
+  MYSQL_CALLBACK(thread_scheduler,
+                 thd_wait_begin, (current_thd, THD_WAIT_TABLE_LOCK));
+}
+
+static void scheduler_wait_lock_end(void) {
+  MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd));
+}
+
+static void scheduler_wait_sync_begin(void) {
   MYSQL_CALLBACK(thread_scheduler,
-                 thd_wait_begin, (current_thd, THD_WAIT_ROW_TABLE_LOCK));
+                 thd_wait_begin, (current_thd, THD_WAIT_TABLE_LOCK));
 }
 
-static void scheduler_wait_end(void) {
+static void scheduler_wait_sync_end(void) {
   MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd));
 }
+};
 /**@}*/
 
 /**
@@ -94,7 +106,10 @@ static void scheduler_wait_end(void) {
   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);
+  thr_set_lock_wait_callback(scheduler_wait_lock_begin,
+                             scheduler_wait_lock_end);
+  thr_set_sync_wait_callback(scheduler_wait_sync_begin,
+                             scheduler_wait_sync_end);
 }
 
 /*
@@ -133,10 +148,6 @@ void one_thread_scheduler()
 thd_scheduler::thd_scheduler()
   : m_psi(NULL), data(NULL)
 {
-#ifndef DBUG_OFF
-  dbug_explain[0]= '\0';
-  set_explain= FALSE;
-#endif
 }
 
 

=== modified file 'sql/scheduler.h'
--- a/sql/scheduler.h	2011-03-22 11:44:40 +0000
+++ b/sql/scheduler.h	2011-05-04 09:54:04 +0000
@@ -68,11 +68,6 @@ enum scheduler_types
 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
-};
-
 /*
  To be used for pool-of-threads (implemeneted differently on various OSs)
 */
@@ -93,15 +88,15 @@ public:
 
   void *data;                  /* scheduler-specific data structure */
 
-#  ifndef DBUG_OFF
-  char dbug_explain[512];
-  bool set_explain;
-#  endif
-
   thd_scheduler();
   ~thd_scheduler();
 };
 
+void *thd_get_scheduler_data(THD *thd);
+void thd_set_scheduler_data(THD *thd, void *data);
+PSI_thread* thd_get_psi(THD *thd);
+void thd_set_psi(THD *thd, PSI_thread *psi);
+
 extern scheduler_functions *thread_scheduler;
 
 #endif

=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc	2011-05-12 17:29:19 +0000
+++ b/sql/sp_head.cc	2011-05-12 18:42:28 +0000
@@ -547,7 +547,7 @@ sp_head::operator delete(void *ptr, size
 
 
 sp_head::sp_head()
-  :Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
+  :Query_arena(&main_mem_root, STMT_INITIALIZED_FOR_SP),
    m_flags(0),
    m_sp_cache_version(0),
    unsafe_flags(0),
@@ -1205,7 +1205,7 @@ sp_head::execute(THD *thd, bool merge_da
   Query_arena *old_arena;
   /* per-instruction arena */
   MEM_ROOT execute_mem_root;
-  Query_arena execute_arena(&execute_mem_root, INITIALIZED_FOR_SP),
+  Query_arena execute_arena(&execute_mem_root, STMT_INITIALIZED_FOR_SP),
               backup_arena;
   query_id_t old_query_id;
   TABLE *old_derived_tables;
@@ -1486,7 +1486,7 @@ sp_head::execute(THD *thd, bool merge_da
   thd->m_reprepare_observer= save_reprepare_observer;
 
   thd->stmt_arena= old_arena;
-  state= EXECUTED;
+  state= STMT_EXECUTED;
 
   /*
     Restore the caller's original warning information area:
@@ -1644,7 +1644,7 @@ sp_head::execute_trigger(THD *thd,
   sp_rcontext *nctx = NULL;
   bool err_status= FALSE;
   MEM_ROOT call_mem_root;
-  Query_arena call_arena(&call_mem_root, Query_arena::INITIALIZED_FOR_SP);
+  Query_arena call_arena(&call_mem_root, Query_arena::STMT_INITIALIZED_FOR_SP);
   Query_arena backup_arena;
 
   DBUG_ENTER("sp_head::execute_trigger");
@@ -1785,7 +1785,7 @@ sp_head::execute_function(THD *thd, Item
   String binlog_buf(buf, sizeof(buf), &my_charset_bin);
   bool err_status= FALSE;
   MEM_ROOT call_mem_root;
-  Query_arena call_arena(&call_mem_root, Query_arena::INITIALIZED_FOR_SP);
+  Query_arena call_arena(&call_mem_root, Query_arena::STMT_INITIALIZED_FOR_SP);
   Query_arena backup_arena;
   DBUG_ENTER("sp_head::execute_function");
   DBUG_PRINT("info", ("function %s", m_name.str));
@@ -2542,7 +2542,7 @@ sp_head::restore_thd_mem_root(THD *thd)
   DBUG_ENTER("sp_head::restore_thd_mem_root");
   Item *flist= free_list;       // The old list
   set_query_arena(thd);         // Get new free_list and mem_root
-  state= INITIALIZED_FOR_SP;
+  state= STMT_INITIALIZED_FOR_SP;
 
   DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx",
                       (ulong) &mem_root, (ulong) &thd->mem_root));
@@ -3007,7 +3007,7 @@ sp_lex_keeper::reset_lex_and_exec_core(T
       (thd->stmt_da->sql_errno() != ER_CANT_REOPEN_TABLE &&
        thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE &&
        thd->stmt_da->sql_errno() != ER_UPDATE_TABLE_USED))
-    thd->stmt_arena->state= Query_arena::EXECUTED;
+    thd->stmt_arena->state= Query_arena::STMT_EXECUTED;
 
   /*
     Merge here with the saved parent's values

=== modified file 'sql/sp_head.h'
--- a/sql/sp_head.h	2011-03-22 11:44:40 +0000
+++ b/sql/sp_head.h	2011-05-04 09:54:04 +0000
@@ -556,7 +556,7 @@ public:
 
   /// Should give each a name or type code for debugging purposes?
   sp_instr(uint ip, sp_pcontext *ctx)
-    :Query_arena(0, INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx)
+    :Query_arena(0, STMT_INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx)
   {}
 
   virtual ~sp_instr()

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2011-05-17 13:51:11 +0000
+++ b/sql/sql_class.cc	2011-05-19 16:52:11 +0000
@@ -198,6 +198,251 @@ bool foreign_key_prefix(Key *a, Key *b)
 ** Thread specific functions
 ****************************************************************************/
 
+/**
+  Get reference to scheduler data object
+
+  @param thd            THD object
+
+  @retval               Scheduler data object on THD
+*/
+void *thd_get_scheduler_data(THD *thd)
+{
+  return thd->scheduler.data;
+}
+
+/**
+  Set reference to Scheduler data object for THD object
+
+  @param thd            THD object
+  @param psi            Scheduler data object to set on THD
+*/
+void thd_set_scheduler_data(THD *thd, void *data)
+{
+  thd->scheduler.data= data;
+}
+
+/**
+  Get reference to Performance Schema object for THD object
+
+  @param thd            THD object
+
+  @retval               Performance schema object for thread on THD
+*/
+PSI_thread *thd_get_psi(THD *thd)
+{
+  return thd->scheduler.m_psi;
+}
+
+/**
+  Set reference to Performance Schema object for THD object
+
+  @param thd            THD object
+  @param psi            Performance schema object for thread
+*/
+void thd_set_psi(THD *thd, PSI_thread *psi)
+{
+  thd->scheduler.m_psi= psi;
+}
+
+/**
+  Set the state on connection to killed
+
+  @param thd               THD object
+*/
+void thd_set_killed(THD *thd)
+{
+  thd->killed= THD::KILL_CONNECTION;
+}
+
+/**
+  Clear errors from the previous THD
+
+  @param thd              THD object
+*/
+void thd_clear_errors(THD *thd)
+{
+  my_errno= 0;
+  thd->mysys_var->abort= 0;
+}
+
+/**
+  Set thread stack in THD object
+
+  @param thd              Thread object
+  @param stack_start      Start of stack to set in THD object
+*/
+void thd_set_thread_stack(THD *thd, char *stack_start)
+{
+  thd->thread_stack= stack_start;
+}
+
+/**
+  Lock connection data for the set of connections this connection
+  belongs to
+
+  @param thd                       THD object
+*/
+void thd_lock_thread_count(THD *)
+{
+  mysql_mutex_lock(&LOCK_thread_count);
+}
+
+/**
+  Lock connection data for the set of connections this connection
+  belongs to
+
+  @param thd                       THD object
+*/
+void thd_unlock_thread_count(THD *)
+{
+  mysql_cond_broadcast(&COND_thread_count);
+  mysql_mutex_unlock(&LOCK_thread_count);
+}
+
+/**
+  Close the socket used by this connection
+
+  @param thd                THD object
+*/
+void thd_close_connection(THD *thd)
+{
+  if (thd->net.vio)
+    vio_close(thd->net.vio);
+}
+
+/**
+  Get current THD object from thread local data
+
+  @retval     The THD object for the thread, NULL if not connection thread
+*/
+THD *thd_get_current_thd()
+{
+  return current_thd;
+}
+
+/**
+  Set up various THD data for a new connection
+
+  thd_new_connection_setup
+
+  @param              thd            THD object
+  @param              stack_start    Start of stack for connection
+*/
+void thd_new_connection_setup(THD *thd, char *stack_start)
+{
+#ifdef HAVE_PSI_INTERFACE
+  thd_set_psi(thd,
+              PSI_CALL(new_thread)(key_thread_one_connection,
+                                   thd,
+                                   thd->thread_id));
+#endif
+  thd->set_time();
+  thd->prior_thr_create_utime= thd->thr_create_utime= thd->start_utime=
+    my_micro_time();
+  threads.append(thd);
+  thd_unlock_thread_count(thd);
+  DBUG_PRINT("info", ("init new connection. thd: 0x%lx fd: %d",
+          (ulong)thd, thd->net.vio->sd));
+  thd_set_thread_stack(thd, stack_start);
+}
+
+/**
+  Lock data that needs protection in THD object
+
+  @param thd                   THD object
+*/
+void thd_lock_data(THD *thd)
+{
+  mysql_mutex_lock(&thd->LOCK_thd_data);
+}
+
+/**
+  Unlock data that needs protection in THD object
+
+  @param thd                   THD object
+*/
+void thd_unlock_data(THD *thd)
+{
+  mysql_mutex_unlock(&thd->LOCK_thd_data);
+}
+
+/**
+  Support method to check if connection has already started transcaction
+
+  @param client_cntx    Low level client context
+
+  @retval               TRUE if connection already started transaction
+*/
+bool thd_is_transaction_active(THD *thd)
+{
+  return thd->transaction.is_active();
+}
+
+/**
+  Check if there is buffered data on the socket representing the connection
+
+  @param thd                  THD object
+*/
+int thd_connection_has_data(THD *thd)
+{
+  Vio *vio= thd->net.vio;
+  return vio->has_data(vio);
+}
+
+/**
+  Set reading/writing on socket, used by SHOW PROCESSLIST
+
+  @param thd                       THD object
+  @param val                       Value to set it to (0 or 1)
+*/
+void thd_set_net_read_write(THD *thd, uint val)
+{
+  thd->net.reading_or_writing= val;
+}
+
+/**
+  Set reference to mysys variable in THD object
+
+  @param thd             THD object
+  @param mysys_var       Reference to set
+*/
+void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var)
+{
+  thd->set_mysys_var(mysys_var);
+}
+
+/**
+  Get socket file descriptor for this connection
+
+  @param thd            THD object
+
+  @retval               Socket of the connection
+*/
+my_socket thd_get_fd(THD *thd)
+{
+  return thd->net.vio->sd;
+}
+
+/**
+  Get thread attributes for connection threads
+
+  @retval      Reference to thread attribute for connection threads
+*/
+pthread_attr_t *get_connection_attrib(void)
+{
+  return &connection_attrib;
+}
+
+/**
+  Get max number of connections
+
+  @retval         Max number of connections for MySQL Server
+*/
+ulong get_max_connections(void)
+{
+  return max_connections;
+}
+
 /*
   The following functions form part of the C plugin API
 */
@@ -478,7 +723,7 @@ bool Drop_table_error_handler::handle_co
 
 
 THD::THD(bool enable_plugins)
-   :Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
+   :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
               /* statement id */ 0),
    rli_fake(0),
    user_time(0), in_sub_stmt(0),
@@ -1381,6 +1626,25 @@ bool THD::store_globals()
   return 0;
 }
 
+/*
+  Remove the thread specific info (THD and mem_root pointer) stored during
+  store_global call for this thread.
+*/
+bool THD::restore_globals()
+{
+  /*
+    Assert that thread_stack is initialized: it's necessary to be able
+    to track stack overrun.
+  */
+  DBUG_ASSERT(thread_stack);
+  
+  /* Undocking the thread specific data. */
+  my_pthread_setspecific_ptr(THR_THD, NULL);
+  my_pthread_setspecific_ptr(THR_MALLOC, NULL);
+  
+  return 0;
+}
+
 
 /*
   Cleanup after query.
@@ -3331,7 +3595,7 @@ extern "C" void thd_pool_wait_end(MYSQL_
 
   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)
+extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type)
 {
   MYSQL_CALLBACK(thread_scheduler, thd_wait_begin, (thd, wait_type));
 }
@@ -3347,7 +3611,7 @@ extern "C" void thd_wait_end(MYSQL_THD t
   MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (thd));
 }
 #else
-extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type)
+extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type)
 {
   /* do NOTHING for the embedded library */
   return;

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2011-05-17 13:51:11 +0000
+++ b/sql/sql_class.h	2011-05-19 16:52:11 +0000
@@ -665,14 +665,14 @@ public:
   /*
     The states relfects three diffrent life cycles for three
     different types of statements:
-    Prepared statement: INITIALIZED -> PREPARED -> EXECUTED.
-    Stored procedure:   INITIALIZED_FOR_SP -> EXECUTED.
-    Other statements:   CONVENTIONAL_EXECUTION never changes.
+    Prepared statement: STMT_INITIALIZED -> STMT_PREPARED -> STMT_EXECUTED.
+    Stored procedure:   STMT_INITIALIZED_FOR_SP -> STMT_EXECUTED.
+    Other statements:   STMT_CONVENTIONAL_EXECUTION never changes.
   */
   enum enum_state
   {
-    INITIALIZED= 0, INITIALIZED_FOR_SP= 1, PREPARED= 2,
-    CONVENTIONAL_EXECUTION= 3, EXECUTED= 4, ERROR= -1
+    STMT_INITIALIZED= 0, STMT_INITIALIZED_FOR_SP= 1, STMT_PREPARED= 2,
+    STMT_CONVENTIONAL_EXECUTION= 3, STMT_EXECUTED= 4, STMT_ERROR= -1
   };
 
   enum_state state;
@@ -695,13 +695,13 @@ public:
   virtual Type type() const;
   virtual ~Query_arena() {};
 
-  inline bool is_stmt_prepare() const { return state == INITIALIZED; }
+  inline bool is_stmt_prepare() const { return state == STMT_INITIALIZED; }
   inline bool is_stmt_prepare_or_first_sp_execute() const
-  { return (int)state < (int)PREPARED; }
+  { return (int)state < (int)STMT_PREPARED; }
   inline bool is_stmt_prepare_or_first_stmt_execute() const
-  { return (int)state <= (int)PREPARED; }
+  { return (int)state <= (int)STMT_PREPARED; }
   inline bool is_conventional() const
-  { return state == CONVENTIONAL_EXECUTION; }
+  { return state == STMT_CONVENTIONAL_EXECUTION; }
 
   inline void* alloc(size_t size) { return alloc_root(mem_root,size); }
   inline void* calloc(size_t size)
@@ -2521,6 +2521,7 @@ public:
   void cleanup(void);
   void cleanup_after_query();
   bool store_globals();
+  bool restore_globals();
 #ifdef SIGNAL_WITH_VIO_CLOSE
   inline void set_active_vio(Vio* vio)
   {

=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc	2011-04-15 09:33:58 +0000
+++ b/sql/sql_connect.cc	2011-05-12 18:44:56 +0000
@@ -705,6 +705,32 @@ pthread_handler_t handle_one_connection(
   return 0;
 }
 
+bool thd_prepare_connection(THD *thd)
+{
+  bool rc;
+  lex_start(thd);
+  rc= login_connection(thd);
+  MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd);
+  if (rc)
+    return rc;
+
+  MYSQL_CONNECTION_START(thd->thread_id, &thd->security_ctx->priv_user[0],
+                         (char *) thd->security_ctx->host_or_ip);
+
+  prepare_new_connection_state(thd);
+  return FALSE;
+}
+
+bool thd_is_connection_alive(THD *thd)
+{
+  NET *net= &thd->net;
+  if (!net->error &&
+      net->vio != 0 &&
+      !(thd->killed == THD::KILL_CONNECTION))
+    return TRUE;
+  return FALSE;
+}
+
 void do_handle_one_connection(THD *thd_arg)
 {
   THD *thd= thd_arg;
@@ -747,22 +773,13 @@ void do_handle_one_connection(THD *thd_a
 
   for (;;)
   {
-    NET *net= &thd->net;
     bool rc;
 
-    lex_start(thd);
-    rc= login_connection(thd);
-    MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd);
+    rc= thd_prepare_connection(thd);
     if (rc)
       goto end_thread;
 
-    MYSQL_CONNECTION_START(thd->thread_id, &thd->security_ctx->priv_user[0],
-                           (char *) thd->security_ctx->host_or_ip);
-
-    prepare_new_connection_state(thd);
-
-    while (!net->error && net->vio != 0 &&
-           !(thd->killed == THD::KILL_CONNECTION))
+    while (thd_is_connection_alive(thd))
     {
       mysql_audit_release(thd);
       if (do_command(thd))

=== modified file 'sql/sql_connect.h'
--- a/sql/sql_connect.h	2011-02-18 09:56:51 +0000
+++ b/sql/sql_connect.h	2011-05-04 09:54:04 +0000
@@ -35,6 +35,8 @@ void time_out_user_resource_limits(THD *
 void decrease_user_connections(USER_CONN *uc);
 bool thd_init_client_charset(THD *thd, uint cs_number);
 bool setup_connection_thread_globals(THD *thd);
+bool thd_prepare_connection(THD *thd);
+bool thd_is_connection_alive(THD *thd);
 
 int check_user(THD *thd, enum enum_server_command command,
 	       const char *passwd, uint passwd_len, const char *db,

=== modified file 'sql/sql_const.h'
--- a/sql/sql_const.h	2010-12-17 09:41:21 +0000
+++ b/sql/sql_const.h	2011-05-02 13:22:25 +0000
@@ -158,16 +158,15 @@
 
 /**
   The following is used to decide if MySQL should use table scanning
-  instead of reading with keys.  The number says how many evaluation of the
-  WHERE clause is comparable to reading one extra row from a table.
+  instead of reading with keys.  The number says how costly evaluation of the
+  filter condition for a row is compared to reading one extra row from a table.
 */
-#define TIME_FOR_COMPARE   5.0	// 5 compares == one read
+#define ROW_EVALUATE_COST  0.20
 
 /**
-  Number of comparisons of table rowids equivalent to reading one row from a 
-  table.
+  Cost of comparing a rowid compared to reading one row from a table.
 */
-#define TIME_FOR_COMPARE_ROWID  (TIME_FOR_COMPARE*2.0)
+#define ROWID_COMPARE_COST 0.10  // Half the cost of a general row comparison
 
 /*
   For sequential disk seeks the cost formula is:

=== modified file 'sql/sql_cursor.h'
--- a/sql/sql_cursor.h	2011-03-22 11:44:40 +0000
+++ b/sql/sql_cursor.h	2011-05-04 09:54:04 +0000
@@ -42,7 +42,7 @@ protected:
   select_result *result;
 public:
   Server_side_cursor(MEM_ROOT *mem_root_arg, select_result *result_arg)
-    :Query_arena(mem_root_arg, INITIALIZED), result(result_arg)
+    :Query_arena(mem_root_arg, STMT_INITIALIZED), result(result_arg)
   {}
 
   virtual bool is_open() const= 0;

=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc	2011-05-04 07:51:15 +0000
+++ b/sql/sql_prepare.cc	2011-05-12 18:42:28 +0000
@@ -2721,7 +2721,7 @@ void mysqld_stmt_reset(THD *thd, char *p
   */
   reset_stmt_params(stmt);
 
-  stmt->state= Query_arena::PREPARED;
+  stmt->state= Query_arena::STMT_PREPARED;
 
   general_log_print(thd, thd->get_command(), NullS);
 
@@ -2840,7 +2840,7 @@ void mysql_stmt_get_longdata(THD *thd, c
   if (param_number >= stmt->param_count)
   {
     /* Error will be sent in execute call */
-    stmt->state= Query_arena::ERROR;
+    stmt->state= Query_arena::STMT_ERROR;
     stmt->last_errno= ER_WRONG_ARGUMENTS;
     sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
             "mysqld_stmt_send_long_data");
@@ -2864,7 +2864,7 @@ void mysql_stmt_get_longdata(THD *thd, c
 #endif
   if (thd->stmt_da->is_error())
   {
-    stmt->state= Query_arena::ERROR;
+    stmt->state= Query_arena::STMT_ERROR;
     stmt->last_errno= thd->stmt_da->sql_errno();
     strncpy(stmt->last_error, thd->stmt_da->message(), MYSQL_ERRMSG_SIZE);
   }
@@ -3023,7 +3023,7 @@ end:
 
 Prepared_statement::Prepared_statement(THD *thd_arg)
   :Statement(NULL, &main_mem_root,
-             INITIALIZED, ++thd_arg->statement_id_counter),
+             STMT_INITIALIZED, ++thd_arg->statement_id_counter),
   thd(thd_arg),
   result(thd_arg),
   param_array(0),
@@ -3296,7 +3296,7 @@ bool Prepared_statement::prepare(const c
   {
     setup_set_params();
     lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_PREPARE;
-    state= Query_arena::PREPARED;
+    state= Query_arena::STMT_PREPARED;
     flags&= ~ (uint) IS_IN_USE;
 
     /* 
@@ -3414,7 +3414,7 @@ Prepared_statement::execute_loop(String
   int reprepare_attempt= 0;
 
   /* Check if we got an error when sending long data */
-  if (state == Query_arena::ERROR)
+  if (state == Query_arena::STMT_ERROR)
   {
     my_message(last_errno, last_error, MYF(0));
     return TRUE;
@@ -3477,7 +3477,7 @@ Prepared_statement::execute_server_runna
   Item_change_list save_change_list;
   thd->change_list.move_elements_to(&save_change_list);
 
-  state= CONVENTIONAL_EXECUTION;
+  state= STMT_CONVENTIONAL_EXECUTION;
 
   if (!(lex= new (mem_root) st_lex_local))
     return TRUE;
@@ -3816,8 +3816,8 @@ bool Prepared_statement::execute(String
   thd->set_statement(&stmt_backup);
   thd->stmt_arena= old_stmt_arena;
 
-  if (state == Query_arena::PREPARED)
-    state= Query_arena::EXECUTED;
+  if (state == Query_arena::STMT_PREPARED)
+    state= Query_arena::STMT_EXECUTED;
 
   if (error == 0 && this->lex->sql_command == SQLCOM_CALL)
   {

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-05-16 11:01:28 +0000
+++ b/sql/sql_select.cc	2011-05-18 10:43:46 +0000
@@ -38,8 +38,7 @@
 #include "sql_parse.h"                          // check_stack_overrun
 #include "sql_partition.h"       // make_used_partitions_str
 #include "sql_acl.h"             // *_ACL
-#include "sql_test.h"            // print_where, print_keyuse_array,
-                                 // print_sjm, print_plan, TEST_join
+#include "sql_test.h"            // misc. debug printing utilities
 #include "records.h"             // init_read_record, end_read_record
 #include "filesort.h"            // filesort_free_buffers
 #include "sql_union.h"           // mysql_union
@@ -59,11 +58,11 @@ const char *join_type_str[]={ "UNKNOWN",
 
 struct st_sargable_param;
 
-static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
+static void optimize_keyuse(JOIN *join, Key_use_array *keyuse_array);
 static bool make_join_statistics(JOIN *join, TABLE_LIST *leaves, Item *conds,
-				 DYNAMIC_ARRAY *keyuse);
+                                Key_use_array *keyuse);
 static bool optimize_semijoin_nests(JOIN *join);
-static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
+static bool update_ref_and_keys(THD *thd, Key_use_array *keyuse,
                                 JOIN_TAB *join_tab,
                                 uint tables, Item *conds,
                                 COND_EQUAL *cond_equal,
@@ -3547,7 +3546,7 @@ bool JOIN::destroy()
   while ((sj_nest= sj_list_it++))
     sj_nest->sj_mat_exec= NULL;
 
-  delete_dynamic(&keyuse);
+  keyuse.clear();
   delete procedure;
   DBUG_RETURN(test(error));
 }
@@ -4710,7 +4709,7 @@ static uint get_tmp_table_rec_length(Lis
 
 static bool
 make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, Item *conds,
-		     DYNAMIC_ARRAY *keyuse_array)
+                     Key_use_array *keyuse_array)
 {
   int error;
   TABLE *table;
@@ -6092,7 +6091,7 @@ max_part_bit(key_part_map bits)
 */
 
 static bool
-add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
+add_key_part(Key_use_array *keyuse_array, KEY_FIELD *key_field)
 {
   Field *field=key_field->field;
   TABLE *form= field->table;
@@ -6122,7 +6121,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array
                                key_field->null_rejecting,
                                key_field->cond_guard,
                                key_field->sj_pred_no);
-          if (insert_dynamic(keyuse_array, &keyuse))
+          if (keyuse_array->push_back(keyuse))
             return TRUE;
 	}
       }
@@ -6135,7 +6134,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array
 #define FT_KEYPART   (MAX_REF_PARTS+10)
 
 static bool
-add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
+add_ft_keys(Key_use_array *keyuse_array,
             JOIN_TAB *stat,Item *cond,table_map usable_tables)
 {
   Item_func_match *cond_func=NULL;
@@ -6197,7 +6196,7 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
                        false,         // null_rejecting
                        NULL,          // cond_guard
                        UINT_MAX);     // sj_pred_no
-  return insert_dynamic(keyuse_array, &keyuse);
+  return keyuse_array->push_back(keyuse);
 }
 
 
@@ -6313,7 +6312,7 @@ static void add_key_fields_for_nj(JOIN *
 */
 
 static bool
-update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
+update_ref_and_keys(THD *thd, Key_use_array *keyuse,JOIN_TAB *join_tab,
                     uint tables, Item *cond, COND_EQUAL *cond_equal,
                     table_map normal_tables, SELECT_LEX *select_lex,
                     SARGABLE_PARAM **sargables)
@@ -6356,8 +6355,6 @@ update_ref_and_keys(THD *thd, DYNAMIC_AR
   /* set a barrier for the array of SARGABLE_PARAM */
   (*sargables)[0].field= 0; 
 
-  if (my_init_dynamic_array(keyuse, sizeof(Key_use), 20, 64))
-    return TRUE;
   if (cond)
   {
     add_key_fields(join_tab->join, &end, &and_level, cond, normal_tables,
@@ -6431,21 +6428,21 @@ update_ref_and_keys(THD *thd, DYNAMIC_AR
       used in the query, we drop the partial key parts from consideration).
     Special treatment for ft-keys.
   */
-  if (keyuse->elements)
+  if (!keyuse->empty())
   {
     Key_use *save_pos, *use;
 
-    my_qsort(keyuse->buffer, keyuse->elements, sizeof(Key_use),
+    my_qsort(keyuse->begin(), keyuse->size(), keyuse->element_size(),
              reinterpret_cast<qsort_cmp>(sort_keyuse));
 
     const Key_use key_end(NULL, NULL, 0, 0, 0, 0, 0, 0, false, NULL, 0);
-    if (insert_dynamic(keyuse, &key_end)) // added for easy testing
+    if (keyuse->push_back(key_end)) // added for easy testing
       return TRUE;
 
-    use= save_pos= dynamic_element(keyuse, 0, Key_use *);
+    use= save_pos= keyuse->begin();
     const Key_use *prev= &key_end;
     found_eq_constant=0;
-    for (i=0 ; i < keyuse->elements-1 ; i++,use++)
+    for (i=0 ; i < keyuse->size()-1 ; i++,use++)
     {
       if (!use->used_tables && use->optimize != KEY_OPTIMIZE_REF_OR_NULL)
 	use->table->const_key_parts[use->key]|= use->keypart_map;
@@ -6478,9 +6475,9 @@ update_ref_and_keys(THD *thd, DYNAMIC_AR
       use->table->reginfo.join_tab->checked_keys.set_bit(use->key);
       save_pos++;
     }
-    i= (uint) (save_pos - (Key_use *)keyuse->buffer);
-    (void) set_dynamic(keyuse, &key_end, i);
-    keyuse->elements=i;
+    i= (uint) (save_pos - keyuse->begin());
+    keyuse->at(i) = key_end;
+    keyuse->chop(i);
   }
   DBUG_EXECUTE("opt", print_keyuse_array(keyuse););
   return FALSE;
@@ -6490,12 +6487,11 @@ update_ref_and_keys(THD *thd, DYNAMIC_AR
   Update some values in keyuse for faster choose_table_order() loop.
 */
 
-static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
+static void optimize_keyuse(JOIN *join, Key_use_array *keyuse_array)
 {
-  Key_use *end, *keyuse= dynamic_element(keyuse_array, 0, Key_use *);
-
-  for (end= keyuse+ keyuse_array->elements ; keyuse < end ; keyuse++)
+  for (size_t ix= 0; ix < keyuse_array->size(); ++ix)
   {
+    Key_use *keyuse= &keyuse_array->at(ix);
     table_map map;
     /*
       If we find a ref, assume this table matches a proportional
@@ -7067,10 +7063,10 @@ best_access_path(JOIN      *join,
                  POSITION *pos,
                  POSITION *loose_scan_pos)
 {
-  THD *thd= join->thd;
+  THD *const thd= join->thd;
   Key_use *best_key=        NULL;
   uint best_max_key_part=   0;
-  my_bool found_constraint= 0;
+  bool found_constraint=    false;
   double best=              DBL_MAX;
   double best_time=         DBL_MAX;
   double records=           DBL_MAX;
@@ -7083,7 +7079,7 @@ best_access_path(JOIN      *join,
   double best_quick_records= DBL_MAX;
   table_map best_ref_depends_map= 0;
   double tmp;
-  bool best_uses_jbuf= FALSE;
+  bool best_uses_jbuf= false;
 
   Loose_scan_opt loose_scan_opt;
   DBUG_ENTER("best_access_path");
@@ -7096,28 +7092,27 @@ best_access_path(JOIN      *join,
   */
   if (unlikely(s->keyuse != NULL))
   {                                            /* Use key if possible */
-    TABLE *table= s->table;
-    Key_use *keyuse;
+    TABLE *const table= s->table;
     double best_records= DBL_MAX;
-    uint max_key_part=0;
 
     /* Test how we can use keys */
     ha_rows rec=
       s->records/MATCHING_ROWS_IN_OTHER_TABLE;  // Assumed records/key
-    for (keyuse=s->keyuse ; keyuse->table == table ;)
+    for (Key_use *keyuse=s->keyuse; keyuse->table == table; )
     {
       key_part_map found_part= 0;
       table_map found_ref= 0;
-      uint key= keyuse->key;
-      KEY *keyinfo= table->key_info+key;
-      bool ft_key=  (keyuse->keypart == FT_KEYPART);
+      const uint key= keyuse->key;
+      uint max_key_part= 0;
+      KEY *const keyinfo= table->key_info+key;
+      const bool ft_key= (keyuse->keypart == FT_KEYPART);
       /* Bitmap of keyparts where the ref access is over 'keypart=const': */
       key_part_map const_part= 0;
       /* The or-null keypart in ref-or-null access: */
       key_part_map ref_or_null_part= 0;
 
       /* Calculate how many key segments of the current key we can use */
-      Key_use *start_key= keyuse;
+      Key_use *const start_key= keyuse;
 
       loose_scan_opt.next_ref_key();
       DBUG_PRINT("info", ("Considering ref access on key %s",
@@ -7131,7 +7126,7 @@ best_access_path(JOIN      *join,
       
       do /* For each keypart */
       {
-        uint keypart= keyuse->keypart;
+        const uint keypart= keyuse->keypart;
         table_map best_part_found_ref= 0;
         double best_prev_record_reads= DBL_MAX;
         
@@ -7453,12 +7448,12 @@ best_access_path(JOIN      *join,
         loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp);
 
       } /* not ft_key */
-      if (tmp < best_time - records/(double) TIME_FOR_COMPARE ||
+      if (tmp < best_time - records * ROW_EVALUATE_COST ||
           (quick_matches_more_parts && 
            quick_records < best_quick_records))
       {
         best_quick_records = quick_records;
-        best_time= tmp + records/(double) TIME_FOR_COMPARE;
+        best_time= tmp + records * ROW_EVALUATE_COST;
         best= tmp;
         best_records= records;
         best_key= start_key;
@@ -7543,7 +7538,7 @@ best_access_path(JOIN      *join,
       */
       tmp= record_count *
         (s->quick->read_time +
-         (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
+         (s->found_records - rnd_records) * ROW_EVALUATE_COST);
 
       loose_scan_opt.check_range_access(join, idx, s->quick);
     }
@@ -7563,8 +7558,7 @@ best_access_path(JOIN      *join,
           - skip rows which does not satisfy join condition
         */
         tmp= record_count *
-          (tmp +
-           (s->records - rnd_records)/(double) TIME_FOR_COMPARE);
+             (tmp + (s->records - rnd_records) * ROW_EVALUATE_COST);
       }
       else
       {
@@ -7583,18 +7577,18 @@ best_access_path(JOIN      *join,
            we read the table (see flush_cached_records for details). Here we
            take into account cost to read and skip these records.
         */
-        tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
+        tmp+= (s->records - rnd_records) * ROW_EVALUATE_COST;
       }
     }
 
     /*
       We estimate the cost of evaluating WHERE clause for found records
-      as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
+      as record_count * rnd_records * ROW_EVALUATE_COST. This cost plus
       tmp give us total cost of using TABLE SCAN
     */
     if (best == DBL_MAX ||
-        (tmp  + record_count/(double) TIME_FOR_COMPARE*rnd_records <
-         best + record_count/(double) TIME_FOR_COMPARE*records))
+        (tmp  + (record_count * ROW_EVALUATE_COST * rnd_records) <
+         best + (record_count * ROW_EVALUATE_COST * records)))
     {
       /*
         If the table has a range (s->quick is set) make_join_select()
@@ -7915,7 +7909,7 @@ void Optimize_table_order::optimize_stra
     /* compute the cost of the new plan extended with 's' */
     record_count*= join->positions[idx].records_read;
     read_time+=    join->positions[idx].read_time
-                   + record_count / (double) TIME_FOR_COMPARE;
+                   + record_count * ROW_EVALUATE_COST;
     advance_sj_state(join_tables, s, idx, &record_count, &read_time,
                      &loose_scan_pos);
 
@@ -8169,7 +8163,7 @@ bool Optimize_table_order::greedy_search
     /* compute the cost of the new plan extended with 'best_table' */
     record_count*= join->positions[idx].records_read;
     read_time+=    join->positions[idx].read_time
-                   + record_count / (double) TIME_FOR_COMPARE;
+                   + record_count * ROW_EVALUATE_COST;
 
     remaining_tables&= ~(best_table->table->map);
     --size_remain;
@@ -8215,7 +8209,7 @@ void get_partial_join_cost(JOIN *join, u
     {
       record_count *= join->best_positions[i].records_read;
       read_time += join->best_positions[i].read_time
-                   + record_count / (double) TIME_FOR_COMPARE;
+                   + record_count * ROW_EVALUATE_COST;
     }
   }
   *read_time_arg= read_time;
@@ -8394,7 +8388,7 @@ bool Optimize_table_order::best_extensio
       current_record_count= record_count * position->records_read;
       current_read_time=    read_time
                             + position->read_time
-                            + current_record_count / (double) TIME_FOR_COMPARE;
+                            + current_record_count * ROW_EVALUATE_COST;
 
       if (has_sj)
       {
@@ -10663,19 +10657,17 @@ void revise_cache_usage(JOIN_TAB *join_t
 }
 
 
-/* 
+/**
   Check whether a join buffer can be used to join the specified table   
 
-  SYNOPSIS
-    check_join_cache_usage()
-      tab                 joined table to check join buffer usage for
-      join                join for which the check is performed
-      options             options of the join
-      no_jbuf_after       don't use join buffering after table with this number
-      icp_other_tables_ok OUT TRUE if condition pushdown supports
-                          other tables presence
+  @param tab             joined table to check join buffer usage for
+  @param join            join for which the check is performed
+  @param options         options of the join
+  @param no_jbuf_after   don't use join buffering after table with this number
+  @param icp_other_tables_ok[out] TRUE if condition pushdown supports
+                                  other tables presence
 
-  DESCRIPTION
+  @details
     The function finds out whether the table 'tab' can be joined using a join
     buffer. This check is performed after the best execution plan for 'join'
     has been chosen. If the function decides that a join buffer can be employed
@@ -10711,7 +10703,7 @@ void revise_cache_usage(JOIN_TAB *join_t
     failure to do this results in an invocation of the function that destructs
     the created object.
  
-  NOTES
+  @note
     An inner table of a nested outer join or a nested semi-join can be currently
     joined only when a linked cache object is employed. In these cases setting
     join cache level to an odd number results in denial of usage of any join
@@ -10723,7 +10715,7 @@ void revise_cache_usage(JOIN_TAB *join_t
     an index. For these engines setting the value of join_cache_level to 5 or 6
     results in that no join buffer is used to join the table. 
    
-  TODO
+  @todo
     Support BKA inside SJ-Materialization nests. When doing this, we'll need
     to only store sj-inner tables in the join buffer.
 #if 0
@@ -10747,7 +10739,7 @@ void revise_cache_usage(JOIN_TAB *join_t
         }
 #endif
 
-  RETURN
+  @return
     Bitmap describing the chosen cache's properties:
     1) the algorithm (JOIN_CACHE::ALG_NONE, JOIN_CACHE::ALG_BNL,
     JOIN_CACHE::ALG_BKA, JOIN_CACHE::ALG_BKA_UNIQUE)
@@ -11247,33 +11239,28 @@ bool setup_sj_materialization(JOIN_TAB *
 }
 
 
-/*
+/**
   Plan refinement stage: do various setup things for the executor
 
-  SYNOPSIS
-    make_join_readinfo()
-      join           Join being processed
-      options        Join's options (checking for SELECT_DESCRIBE, 
-                     SELECT_NO_JOIN_CACHE)
-      no_jbuf_after  Don't use join buffering after table with this number.
+  @param join          Join being processed
+  @param options       Join's options (checking for SELECT_DESCRIBE, 
+                       SELECT_NO_JOIN_CACHE)
+  @param no_jbuf_after Don't use join buffering after table with this number.
 
-  DESCRIPTION
+  @return false if successful, true if error (Out of memory)
+
+  @details
     Plan refinement stage: do various set ups for the executioner
       - setup join buffering use
       - push index conditions
       - increment relevant counters
       - etc
-
-  RETURN 
-    FALSE - OK
-    TRUE  - Out of memory
 */
 
 static bool
 make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
 {
-  uint i, jcl;
-  bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
+  const bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
   uint first_sjm_table= MAX_TABLES;
   uint last_sjm_table= MAX_TABLES;
 
@@ -11285,11 +11272,12 @@ make_join_readinfo(JOIN *join, ulonglong
   if (setup_semijoin_dups_elimination(join, options, no_jbuf_after))
     DBUG_RETURN(TRUE); /* purecov: inspected */
 
-  for (i=join->const_tables ; i < join->tables ; i++)
+  for (uint i= join->const_tables; i < join->tables; i++)
   {
-    JOIN_TAB *tab=join->join_tab+i;
-    TABLE *table=tab->table;
+    JOIN_TAB *const tab= join->join_tab+i;
+    TABLE    *const table= tab->table;
     bool icp_other_tables_ok;
+    uint jcl;
     tab->read_record.table= table;
     tab->read_record.file=table->file;
     tab->read_record.unlock_row= rr_unlock_row;
@@ -11440,12 +11428,12 @@ make_join_readinfo(JOIN *join, ulonglong
     If a join buffer is used to join a table the ordering by an index
     for the first non-constant table cannot be employed anymore.
   */
-  for (i=join->const_tables ; i < join->tables ; i++)
+  for (uint i= join->const_tables; i < join->tables; i++)
   {
-    JOIN_TAB *tab=join->join_tab+i;
+    JOIN_TAB *const tab=join->join_tab + i;
     if (tab->use_join_cache)
     {
-      JOIN_TAB *sort_by_tab= join->get_sort_by_join_tab();
+      JOIN_TAB *const sort_by_tab= join->get_sort_by_join_tab();
       if (sort_by_tab)
       {
         join->need_tmp= 1;

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2011-05-02 11:51:41 +0000
+++ b/sql/sql_select.h	2011-05-18 10:43:46 +0000
@@ -30,6 +30,7 @@
 #include "records.h"                          /* READ_RECORD */
 #include "opt_range.h"                /* SQL_SELECT, QUICK_SELECT_I */
 
+#include "mem_root_array.h"
 
 /* Values in optimize */
 #define KEY_OPTIMIZE_EXISTS		1
@@ -37,12 +38,24 @@
 
 /**
   Information about usage of an index to satisfy an equality condition.
-
-  @note such objects are stored in DYNAMIC_ARRAY which uses sizeof(), so keep
-  this class as POD as possible.
 */
 class Key_use {
 public:
+  // We need the default constructor for unit testing.
+  Key_use()
+    : table(NULL),
+      val(NULL),
+      used_tables(0),
+      key(0),
+      keypart(0),
+      optimize(0),
+      keypart_map(0),
+      ref_table_rows(0),
+      null_rejecting(false),
+      cond_guard(NULL),
+      sj_pred_no(UINT_MAX)
+  {}
+
   Key_use(TABLE *table_arg, Item *val_arg, table_map used_tables_arg,
           uint key_arg, uint keypart_arg, uint optimize_arg,
           key_part_map keypart_map_arg, ha_rows ref_table_rows_arg,
@@ -85,7 +98,7 @@ public:
   bool *cond_guard;
   /**
      0..64    <=> This was created from semi-join IN-equality # sj_pred_no.
-     MAX_UINT  Otherwise
+     UINT_MAX  Otherwise
 
      Not used if the index is fulltext (such index cannot be used for
      semijoin).
@@ -93,6 +106,10 @@ public:
   uint         sj_pred_no;
 };
 
+
+// Key_use has a trivial destructor, no need to run it from Mem_root_array.
+typedef Mem_root_array<Key_use, true> Key_use_array;
+
 class store_key;
 
 typedef struct st_table_ref : public Sql_alloc
@@ -1816,7 +1833,9 @@ public:
   bool          skip_sort_order;
 
   bool need_tmp, hidden_group_fields;
-  DYNAMIC_ARRAY keyuse;
+
+  Key_use_array keyuse;
+
   List<Item> all_fields; ///< to store all fields that used in query
   ///Above list changed to use temporary table
   List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
@@ -1892,7 +1911,9 @@ public:
 
   JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
        select_result *result_arg)
-    :fields_list(fields_arg), sj_subselects(thd_arg->mem_root, 4)
+    : keyuse(thd_arg->mem_root),
+      fields_list(fields_arg),
+      sj_subselects(thd_arg->mem_root, 4)
   {
     init(thd_arg, fields_arg, select_options_arg, result_arg);
   }
@@ -1946,7 +1967,7 @@ public:
     all_fields= fields_arg;
     if (&fields_list != &fields_arg)      /* Avoid valgrind-warning */
       fields_list= fields_arg;
-    bzero((char*) &keyuse,sizeof(keyuse));
+    keyuse.clear();
     tmp_table_param.init();
     tmp_table_param.end_write_records= HA_POS_ERROR;
     rollup.state= ROLLUP::STATE_NONE;

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2011-05-12 17:29:19 +0000
+++ b/sql/sql_table.cc	2011-05-19 12:43:26 +0000
@@ -4973,41 +4973,48 @@ err:
 
 /**
   @brief Check if both DROP and CREATE are present for an index in ALTER TABLE
- 
-  @details Checks if any index is being modified (present as both DROP INDEX 
-    and ADD INDEX) in the current ALTER TABLE statement. Needed for disabling 
+
+  @details Checks if any index is being modified (present as both DROP INDEX
+    and ADD INDEX) in the current ALTER TABLE statement. Needed for disabling
     in-place ALTER TABLE.
-  
-  @param table       The table being altered
-  @param alter_info  The ALTER TABLE structure
-  @return presence of index being altered  
+
+  @param table              The table being altered.
+  @param key_info_buffer    Array of KEY structs for new indexes.
+  @param index_drop_buffer  Array of offsets into table->key_info for indexes
+                            to be dropped.
+  @param index_drop_count   Number of indexes to be dropped.
+  @param index_add_buffer   Array of offsets into key_info_buffer representing
+                            new indexes.
+  @param index_add_count    Number of indexes to add.
+  @return presence of index being both dropped and added
   @retval FALSE  No such index
   @retval TRUE   Have at least 1 index modified
 */
 
 static bool
-is_index_maintenance_unique (TABLE *table, Alter_info *alter_info)
+is_index_maintenance_unique (const TABLE *table, const KEY *key_info_buffer,
+                             const uint *index_drop_buffer,
+                             uint index_drop_count,
+                             const uint *index_add_buffer, uint index_add_count)
 {
-  List_iterator<Key> key_it(alter_info->key_list);
-  List_iterator<Alter_drop> drop_it(alter_info->drop_list);
-  Key *key;
+  const KEY *add_key;
+  const KEY *drop_key;
+  const uint *idx_add_p;
+  const uint *idx_drop_p;
 
-  while ((key= key_it++))
+  for (idx_add_p= index_add_buffer;
+       idx_add_p < index_add_buffer + index_add_count; idx_add_p++)
   {
-    if (key->name.str)
+    add_key= key_info_buffer + *idx_add_p;
+    for (idx_drop_p= index_drop_buffer;
+         idx_drop_p < index_drop_buffer + index_drop_count; idx_drop_p++)
     {
-      Alter_drop *drop;
-
-      drop_it.rewind();
-      while ((drop= drop_it++))
-      {
-        if (drop->type == Alter_drop::KEY &&
-            !my_strcasecmp(system_charset_info, key->name.str, drop->name))
-          return TRUE;
-      }
+      drop_key= table->key_info + *idx_drop_p;
+      if (!my_strcasecmp(system_charset_info, add_key->name, drop_key->name))
+        return true;
     }
   }
-  return FALSE;
+  return false;
 }
 
 
@@ -6298,15 +6305,9 @@ bool mysql_alter_table(THD *thd,char *ne
   */
   new_db_type= create_info->db_type;
 
-  if (is_index_maintenance_unique (table, alter_info))
-    need_copy_table= ALTER_TABLE_DATA_CHANGED;
-
   if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
     goto err;
 
-  if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
-    need_copy_table= alter_info->change_level;
-
   set_table_default_charset(thd, create_info, db);
 
   if (thd->variables.old_alter_table
@@ -6318,6 +6319,8 @@ bool mysql_alter_table(THD *thd,char *ne
     need_copy_table= ALTER_TABLE_DATA_CHANGED;
   else
   {
+    need_copy_table= alter_info->change_level;
+
     Alter_table_change_level need_copy_table_res;
     /* Check how much the tables differ. */
     if (mysql_compare_tables(table, alter_info,
@@ -6328,16 +6331,24 @@ bool mysql_alter_table(THD *thd,char *ne
                              &index_add_buffer, &index_add_count,
                              &candidate_key_count, FALSE))
       goto err;
-   
+
     DBUG_EXECUTE_IF("alter_table_only_metadata_change", {
       if (need_copy_table_res != ALTER_TABLE_METADATA_ONLY)
         goto err; });
     DBUG_EXECUTE_IF("alter_table_only_index_change", {
       if (need_copy_table_res != ALTER_TABLE_INDEX_CHANGED)
         goto err; });
-   
+
     if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
       need_copy_table= need_copy_table_res;
+
+    if (need_copy_table == ALTER_TABLE_INDEX_CHANGED)
+    {
+      if (is_index_maintenance_unique(table, key_info_buffer,
+                                      index_drop_buffer, index_drop_count,
+                                      index_add_buffer, index_add_count))
+        need_copy_table= ALTER_TABLE_DATA_CHANGED;
+    }
   }
 
   /*

=== modified file 'sql/sql_test.cc'
--- a/sql/sql_test.cc	2010-11-05 22:19:41 +0000
+++ b/sql/sql_test.cc	2011-05-18 08:29:46 +0000
@@ -239,7 +239,7 @@ TEST_join(JOIN *join)
 
 #define FT_KEYPART   (MAX_REF_PARTS+10)
 
-void print_keyuse(Key_use *keyuse)
+void print_keyuse(const Key_use *keyuse)
 {
   char buff[256];
   char buf2[64]; 
@@ -266,14 +266,14 @@ void print_keyuse(Key_use *keyuse)
 
 
 /* purecov: begin inspected */
-void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array)
+void print_keyuse_array(const Key_use_array *keyuse_array)
 {
   DBUG_LOCK_FILE;
-  fprintf(DBUG_FILE, "Key_use array (%d elements)\n", keyuse_array->elements);
+  fprintf(DBUG_FILE, "Key_use array (%d elements)\n",
+          (int) keyuse_array->size());
   DBUG_UNLOCK_FILE;
-  for(uint i=0; i < keyuse_array->elements; i++)
-    print_keyuse(reinterpret_cast<Key_use *>
-                 (dynamic_array_ptr(keyuse_array, i)));
+  for(uint i=0; i < keyuse_array->size(); i++)
+    print_keyuse(&keyuse_array->at(i));
 }
 
 

=== modified file 'sql/sql_test.h'
--- a/sql/sql_test.h	2010-08-19 07:10:58 +0000
+++ b/sql/sql_test.h	2011-05-18 08:29:46 +0000
@@ -17,6 +17,7 @@
 #define SQL_TEST_INCLUDED
 
 #include "mysqld.h"
+#include "sql_select.h"
 
 class JOIN;
 struct TABLE_LIST;
@@ -31,7 +32,7 @@ void print_plan(JOIN* join,uint idx, dou
                 double current_read_time, const char *info);
 void dump_TABLE_LIST_graph(SELECT_LEX *select_lex, TABLE_LIST* tl);
 void print_sjm(TABLE_LIST *emb_sj_nest);
-void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array);
+void print_keyuse_array(const Key_use_array *keyuse_array);
 #endif
 void mysql_print_status();
 

=== modified file 'sql/table.cc'
--- a/sql/table.cc	2011-05-17 13:51:11 +0000
+++ b/sql/table.cc	2011-05-19 16:52:11 +0000
@@ -2025,7 +2025,8 @@ int open_table_from_share(THD *thd, TABL
 
     Query_arena *backup_stmt_arena_ptr= thd->stmt_arena;
     Query_arena backup_arena;
-    Query_arena part_func_arena(&outparam->mem_root, Query_arena::INITIALIZED);
+    Query_arena part_func_arena(&outparam->mem_root,
+                                Query_arena::STMT_INITIALIZED);
     thd->set_n_backup_active_arena(&part_func_arena, &backup_arena);
     thd->stmt_arena= &part_func_arena;
     bool tmp;

=== modified file 'sql/uniques.cc'
--- a/sql/uniques.cc	2011-03-09 20:54:55 +0000
+++ b/sql/uniques.cc	2011-05-02 13:22:25 +0000
@@ -122,7 +122,7 @@ inline double log2_n_fact(double x)
     the same length, so each of total_buf_size elements will be added to a sort
     heap with (n_buffers-1) elements. This gives the comparison cost:
 
-      total_buf_elems* log2(n_buffers) / TIME_FOR_COMPARE_ROWID;
+      total_buf_elems * log2(n_buffers) * ROWID_COMPARE_COST;
 */
 
 static double get_merge_buffers_cost(uint *buff_elems, uint elem_size,
@@ -137,7 +137,7 @@ static double get_merge_buffers_cost(uin
 
   /* Using log2(n)=log(n)/log(2) formula */
   return 2*((double)total_buf_elems*elem_size) / IO_SIZE +
-     total_buf_elems*log((double) n_buffers) / (TIME_FOR_COMPARE_ROWID * M_LN2);
+     total_buf_elems*log((double) n_buffers) * ROWID_COMPARE_COST / M_LN2;
 }
 
 
@@ -267,7 +267,6 @@ double Unique::get_use_cost(uint *buffer
   ulong max_elements_in_tree;
   ulong last_tree_elems;
   int   n_full_trees; /* number of trees in unique - 1 */
-  double result;
 
   max_elements_in_tree= ((ulong) max_in_memory_size /
                          ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size));
@@ -276,10 +275,10 @@ double Unique::get_use_cost(uint *buffer
   last_tree_elems= nkeys % max_elements_in_tree;
 
   /* Calculate cost of creating trees */
-  result= 2*log2_n_fact(last_tree_elems + 1.0);
+  double result= 2 * log2_n_fact(last_tree_elems + 1.0);
   if (n_full_trees)
     result+= n_full_trees * log2_n_fact(max_elements_in_tree + 1.0);
-  result /= TIME_FOR_COMPARE_ROWID;
+  result*= ROWID_COMPARE_COST;
 
   DBUG_PRINT("info",("unique trees sizes: %u=%u*%lu + %lu", nkeys,
                      n_full_trees, n_full_trees?max_elements_in_tree:0,

=== modified file 'storage/innobase/srv/srv0conc.c'
--- a/storage/innobase/srv/srv0conc.c	2011-04-18 02:17:16 +0000
+++ b/storage/innobase/srv/srv0conc.c	2011-05-13 12:47:07 +0000
@@ -293,7 +293,7 @@ retry:
 #endif /* UNIV_SYNC_DEBUG */
 	trx->op_info = "waiting in InnoDB queue";
 
-	thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK);
+	thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK);
 	os_event_wait(slot->event);
 	thd_wait_end(trx->mysql_thd);
 

=== modified file 'unittest/gunit/CMakeLists.txt'
--- a/unittest/gunit/CMakeLists.txt	2011-05-13 09:36:13 +0000
+++ b/unittest/gunit/CMakeLists.txt	2011-05-18 08:29:46 +0000
@@ -206,6 +206,7 @@ ENDIF()
 SET(TESTS
   bounded_queue
   dbug
+  dynarray
   mdl
   mdl_mytap
   my_bitmap

=== added file 'unittest/gunit/dynarray-t.cc'
--- a/unittest/gunit/dynarray-t.cc	1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/dynarray-t.cc	2011-05-18 08:29:46 +0000
@@ -0,0 +1,408 @@
+/* Copyright (c) 2011, 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 */
+
+// First include (the generated) my_config.h, to get correct platform defines,
+// then gtest.h (before any other MySQL headers), to avoid min() macros etc ...
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include <algorithm>
+#include <functional>
+#include <vector>
+
+#include "sql_select.h"
+#include "mem_root_array.h"
+
+/**
+   WL#5774 Decrease number of malloc's for normal DML queries.
+   One of the malloc's was due to DYNAMIC_ARRAY keyuse;
+   We replace the DYNAMIC_ARRAY with a std::vector-like class Mem_root_array.
+
+   Below are unit tests for comparing performance, and for testing
+   functionality of Mem_root_array.
+*/
+
+pthread_key(MEM_ROOT**, THR_MALLOC);
+pthread_key(THD*, THR_THD);
+
+extern "C" void sql_alloc_error_handler(void)
+{
+  ADD_FAILURE();
+}
+
+
+/*
+  Rewrite of sort_keyuse() to comparison operator for use by std::less<>
+  It is a template argument, so static rather than in unnamed namespace.
+*/
+static inline bool operator<(const Key_use &a, const Key_use &b)
+{
+  if (a.table->tablenr != b.table->tablenr)
+    return a.table->tablenr < b.table->tablenr;
+  if (a.key != b.key)
+    return a.key < b.key;
+  if (a.keypart != b.keypart)
+    return a.keypart < b.keypart;
+  const bool atab = test((a.used_tables & ~OUTER_REF_TABLE_BIT));
+  const bool btab = test((b.used_tables & ~OUTER_REF_TABLE_BIT));
+  if (atab != btab)
+    return atab < btab;
+  return
+    ((a.optimize & KEY_OPTIMIZE_REF_OR_NULL) <
+     (b.optimize & KEY_OPTIMIZE_REF_OR_NULL));
+}
+
+
+/*
+  Compare for equality.
+  It is a template argument, so static rather than in unnamed namespace.
+*/
+static inline bool operator==(const Key_use &lhs, const Key_use &rhs)
+{
+  return
+    lhs.table->tablenr == rhs.table->tablenr &&
+    lhs.key            == rhs.key            &&
+    lhs.keypart        == rhs.keypart        &&
+    test((lhs.used_tables & ~OUTER_REF_TABLE_BIT))
+    ==
+    test((rhs.used_tables & ~OUTER_REF_TABLE_BIT)) &&
+    (lhs.optimize & KEY_OPTIMIZE_REF_OR_NULL)
+    ==
+    (rhs.optimize & KEY_OPTIMIZE_REF_OR_NULL);
+}
+
+
+namespace {
+
+/*
+  Cut'n paste this function from sql_select.cc,
+  to avoid linking in the entire server for this unit test.
+*/
+inline int sort_keyuse(Key_use *a, Key_use *b)
+{
+  int res;
+  if (a->table->tablenr != b->table->tablenr)
+    return (int) (a->table->tablenr - b->table->tablenr);
+  if (a->key != b->key)
+    return (int) (a->key - b->key);
+  if (a->keypart != b->keypart)
+    return (int) (a->keypart - b->keypart);
+  // Place const values before other ones
+  if ((res= test((a->used_tables & ~OUTER_REF_TABLE_BIT)) -
+       test((b->used_tables & ~OUTER_REF_TABLE_BIT))))
+    return res;
+  /* Place rows that are not 'OPTIMIZE_REF_OR_NULL' first */
+  return (int) ((a->optimize & KEY_OPTIMIZE_REF_OR_NULL) -
+		(b->optimize & KEY_OPTIMIZE_REF_OR_NULL));
+}
+
+
+std::ostream &operator<<(std::ostream &s, const Key_use &v)
+{
+  return s << "{"
+           << v.table->tablenr << ", "
+           << v.key            << ", "
+           << v.keypart        << ", "
+           << v.used_tables    << ", "
+           << v.optimize
+           << "}"
+    ;
+}
+
+
+// We generate some random data at startup, for testing of sorting.
+void generate_test_data(Key_use *keys, TABLE *tables, int n)
+{
+  int ix;
+  for (ix= 0; ix < n; ++ix)
+  {
+    tables[ix].tablenr= ix % 3;
+    keys[ix]=
+      Key_use(&tables[ix],
+              NULL,                           // Item      *val
+              0,                              // table_map  used_tables
+              ix % 4,                         // uint       key
+              ix % 2,                         // uint       keypart
+              0,                              // uint       optimize
+              0,                              //            keypart_map
+              0,                              // ha_rows    ref_table_rows
+              true,                           // bool       null_rejecting
+              NULL,                           // bool      *cond_guard
+              0                               // uint       sj_pred_no
+              );
+  }
+  std::random_shuffle(&keys[0], &keys[n]);
+}
+
+
+// Play around with these constants to see std::sort speedup vs. my_qsort.
+const int num_elements= 200;
+const int num_iterations= 10;
+
+/*
+  This class is used for comparing performance of
+    std::vector<> and std::sort()
+  vs
+    DYNAMIC_ARRAY and my_qsort()
+ */
+class DynArrayTest : public ::testing::Test
+{
+public:
+  DynArrayTest() {}
+
+  static void SetUpTestCase()
+  {
+    generate_test_data(test_data, table_list, num_elements);
+  }
+
+  virtual void SetUp()
+  {
+    my_init_dynamic_array(&m_keyuse_dyn, sizeof(Key_use), num_elements, 64);
+    m_keyuse_vec.reserve(num_elements);
+  }
+
+  void insert_and_sort_dynamic()
+  {
+    reset_dynamic(&m_keyuse_dyn);
+    for (int ix= 0; ix < num_elements; ++ix)
+    {
+      insert_dynamic(&m_keyuse_dyn, &test_data[ix]);
+    }
+    my_qsort(m_keyuse_dyn.buffer, m_keyuse_dyn.elements, sizeof(Key_use),
+             reinterpret_cast<qsort_cmp>(sort_keyuse));
+  }
+
+  void insert_and_sort_vector()
+  {
+    m_keyuse_vec.clear();
+    for (int ix= 0; ix < num_elements; ++ix)
+    {
+      m_keyuse_vec.push_back(test_data[ix]);
+    }
+    std::sort(m_keyuse_vec.begin(), m_keyuse_vec.end(), std::less<Key_use>());
+  }
+
+  DYNAMIC_ARRAY           m_keyuse_dyn;
+  std::vector<Key_use>    m_keyuse_vec;
+private:
+  static Key_use test_data[num_elements];
+  static TABLE   table_list[num_elements];
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DynArrayTest);
+};
+
+Key_use DynArrayTest::test_data[num_elements];
+TABLE   DynArrayTest::table_list[num_elements];
+
+
+// Test insert_dynamic() and my_qsort().
+TEST_F(DynArrayTest, DynArray)
+{
+  for (int ix= 0; ix < num_iterations; ++ix)
+    insert_and_sort_dynamic();
+}
+
+
+// Test vector::push_back() and std::sort()
+TEST_F(DynArrayTest, Vector)
+{
+  for (int ix= 0; ix < num_iterations; ++ix)
+    insert_and_sort_vector();
+}
+
+
+/*
+  This class is for unit testing of Mem_root_array.
+ */
+class MemRootTest : public ::testing::Test
+{
+protected:
+  MemRootTest()
+    : m_mem_root_p(&m_mem_root),
+      m_array_mysys(m_mem_root_p),
+      m_array_std(m_mem_root_p)
+  {}
+
+  virtual void SetUp()
+  {
+    init_sql_alloc(&m_mem_root, 1024, 0);
+    ASSERT_EQ(0, my_pthread_setspecific_ptr(THR_MALLOC, &m_mem_root_p));
+    MEM_ROOT *root= *my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
+    ASSERT_EQ(root, m_mem_root_p);
+
+    m_array_mysys.reserve(num_elements);
+    m_array_std.reserve(num_elements);
+  }
+
+  virtual void TearDown()
+  {
+    free_root(&m_mem_root, MYF(0));
+  }
+
+  static void SetUpTestCase()
+  {
+    generate_test_data(test_data, table_list, num_elements);
+    ASSERT_EQ(0, pthread_key_create(&THR_THD, NULL));
+    ASSERT_EQ(0, pthread_key_create(&THR_MALLOC, NULL));
+  }
+
+  static void TearDownTestCase()
+  {
+    pthread_key_delete(THR_THD);
+    pthread_key_delete(THR_MALLOC);
+  }
+
+  void insert_and_sort_mysys()
+  {
+    m_array_mysys.clear();
+    for (int ix= 0; ix < num_elements; ++ix)
+    {
+      m_array_mysys.push_back(test_data[ix]);
+    }
+    my_qsort(m_array_mysys.begin(), m_array_mysys.size(),
+             m_array_mysys.element_size(),
+             reinterpret_cast<qsort_cmp>(sort_keyuse));
+  }
+
+  void insert_and_sort_std()
+  {
+    m_array_std.clear();
+    for (int ix= 0; ix < num_elements; ++ix)
+    {
+      m_array_std.push_back(test_data[ix]);
+    }
+    std::sort(m_array_std.begin(), m_array_std.end(), std::less<Key_use>());
+  }
+
+  MEM_ROOT m_mem_root;
+  MEM_ROOT *m_mem_root_p;
+  Key_use_array m_array_mysys;
+  Key_use_array m_array_std;
+private:
+  static Key_use test_data[num_elements];
+  static TABLE   table_list[num_elements];
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MemRootTest);
+};
+
+Key_use MemRootTest::test_data[num_elements];
+TABLE   MemRootTest::table_list[num_elements];
+
+
+// Test Mem_root_array::push_back() and my_qsort()
+TEST_F(MemRootTest, KeyUseMysys)
+{
+  for (int ix= 0; ix < num_iterations; ++ix)
+    insert_and_sort_mysys();
+}
+
+
+// Test Mem_root_array::push_back() and std::sort()
+TEST_F(MemRootTest, KeyUseStd)
+{
+  for (int ix= 0; ix < num_iterations; ++ix)
+    insert_and_sort_std();
+}
+
+
+// Test that my_qsort() and std::sort() generate same order.
+TEST_F(MemRootTest, KeyUseCompare)
+{
+  insert_and_sort_mysys();
+  insert_and_sort_std();
+  for (int ix= 0; ix < num_elements; ++ix)
+  {
+    Key_use k1= m_array_mysys.at(ix);
+    Key_use k2= m_array_std.at(ix);
+    EXPECT_EQ(k1, k2);
+  }
+}
+
+
+// Test that Mem_root_array re-expanding works.
+TEST_F(MemRootTest, Reserve)
+{
+  Mem_root_array<uint, true> intarr(m_mem_root_p);
+  intarr.reserve(2);
+  const uint num_pushes= 20;
+  for (uint ix=0; ix < num_pushes; ++ix)
+  {
+    EXPECT_EQ(ix, intarr.size());
+    EXPECT_FALSE(intarr.push_back(ix));
+    EXPECT_EQ(ix, intarr.at(ix));
+  }
+  for (uint ix=0; ix < num_pushes; ++ix)
+  {
+    EXPECT_EQ(ix, intarr.at(ix));
+  }
+  EXPECT_EQ(sizeof(uint), intarr.element_size());
+  EXPECT_EQ(num_pushes, intarr.size());
+  EXPECT_LE(num_pushes, intarr.capacity());
+}
+
+
+class DestroyCounter
+{
+public:
+  DestroyCounter(const DestroyCounter &rhs) : p_counter(rhs.p_counter) {}
+  DestroyCounter(size_t *p) : p_counter(p) {}
+  ~DestroyCounter() { (*p_counter)+= 1; }
+private:
+  size_t *p_counter;
+};
+
+
+// Test chop() and clear() and that destructors are executed.
+TEST_F(MemRootTest, ChopAndClear)
+{
+  Mem_root_array<DestroyCounter, false> array(m_mem_root_p);
+  const size_t nn= 4;
+  array.reserve(nn);
+  size_t counter= 0;
+  DestroyCounter foo(&counter);
+  for (size_t ix= 0; ix < array.capacity(); ++ix)
+    array.push_back(foo);
+
+  EXPECT_EQ(0U, counter);
+  array.chop(nn / 2);
+  EXPECT_EQ(nn / 2, counter);
+  EXPECT_EQ(nn / 2, array.size());
+
+  array.clear();
+  EXPECT_EQ(nn, counter);
+}
+
+
+// Test that elements are destroyed if push_back() needs to call reserve().
+TEST_F(MemRootTest, ReserveDestroy)
+{
+  Mem_root_array<DestroyCounter, false> array(m_mem_root_p);
+  const size_t nn= 4;
+  array.reserve(nn / 2);
+  size_t counter= 0;
+  DestroyCounter foo(&counter);
+  for (size_t ix= 0; ix < nn; ++ix)
+    array.push_back(foo);
+  
+  EXPECT_EQ(nn / 2, counter);
+  EXPECT_EQ(nn, array.size());
+
+  counter= 0;
+  array.clear();
+  EXPECT_EQ(nn, counter);
+}
+
+
+}

=== modified file 'unittest/gunit/mdl-t.cc'
--- a/unittest/gunit/mdl-t.cc	2011-01-27 15:31:18 +0000
+++ b/unittest/gunit/mdl-t.cc	2011-05-19 09:47:59 +0000
@@ -40,6 +40,18 @@ mysql_mutex_t LOCK_open;
 uint    opt_debug_sync_timeout= 0;
 
 /*
+  Mock thd_wait_begin/end functions
+*/
+
+extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type)
+{
+}
+
+extern "C" void thd_wait_end(MYSQL_THD thd)
+{
+}
+
+/*
   A mock error handler.
 */
 static uint expected_error= 0;

=== modified file 'unittest/gunit/mdl_mytap-t.cc'
--- a/unittest/gunit/mdl_mytap-t.cc	2011-01-27 15:31:18 +0000
+++ b/unittest/gunit/mdl_mytap-t.cc	2011-05-19 09:47:59 +0000
@@ -93,6 +93,17 @@ do { \
   EXPECT_TRUE(1 == 0)
 
 
+/*
+  Mock thd_wait_begin/end functions
+*/
+
+extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type)
+{
+}
+
+extern "C" void thd_wait_end(MYSQL_THD thd)
+{
+}
 
 /*
   A mock error handler.

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-pfs-tuning branch (marc.alff:3374 to 3375) Marc Alff19 May