List:Commits« Previous MessageNext Message »
From:Bjorn Munch Date:February 24 2011 3:56pm
Subject:bzr push into mysql-5.5-mtr branch (bjorn.munch:3169 to 3174)
View as plain text  
 3174 Bjorn Munch	2011-02-24
      vs-config option to ctest made not dependent on Windows

    modified:
      mysql-test/mysql-test-run.pl
 3173 Bjorn Munch	2011-02-24 [merge]
      null upmerge

 3172 Bjorn Munch	2011-02-24
      11762407 follow-up fixes to a few tests

    modified:
      mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result
      mysql-test/suite/rpl/r/rpl_slow_query_log.result
      mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test
      mysql-test/suite/rpl/t/rpl_slow_query_log.test
 3171 Bjorn Munch	2011-02-24 [merge]
      merge from 5.5 main

    removed:
      mysql-test/collections/test-bt
      mysql-test/collections/test-bt-debug
      mysql-test/collections/test-bt-debug-fast
      mysql-test/collections/test-bt-fast
      mysql-test/suite/rpl/t/rpl_failed_optimize-master.opt
    added:
      cmake/info_bin.cmake
      cmake/info_macros.cmake.in
      cmake/info_src.cmake
      mysql-test/collections/default.release
      mysql-test/r/file_contents.result
      mysql-test/r/multi_update_innodb.result
      mysql-test/r/mysqld--defaults-file.result
      mysql-test/suite/innodb/r/innodb_bug53756.result
      mysql-test/suite/innodb/r/innodb_bug59307.result
      mysql-test/suite/innodb/r/innodb_bug60049.result
      mysql-test/suite/innodb/t/innodb_bug53756-master.opt
      mysql-test/suite/innodb/t/innodb_bug53756.test
      mysql-test/suite/innodb/t/innodb_bug59307.test
      mysql-test/suite/innodb/t/innodb_bug60049-master.opt
      mysql-test/suite/innodb/t/innodb_bug60049.test
      mysql-test/t/file_contents.test
      mysql-test/t/multi_update_innodb.test
      mysql-test/t/mysqld--defaults-file.test
      storage/innobase/include/ut0bh.h
      storage/innobase/include/ut0bh.ic
      storage/innobase/ut/ut0bh.c
    modified:
      CMakeLists.txt
      README
      VERSION
      client/client_priv.h
      client/mysql.cc
      client/mysqldump.c
      client/readline.cc
      cmake/make_dist.cmake.in
      extra/comp_err.c
      include/my_bit.h
      include/my_bitmap.h
      include/my_global.h
      include/mysql_embed.h
      mysql-test/collections/default.experimental
      mysql-test/extra/rpl_tests/rpl_failed_optimize.test
      mysql-test/include/ctype_numconv.inc
      mysql-test/mysql-test-run.pl
      mysql-test/r/alter_table.result
      mysql-test/r/ctype_binary.result
      mysql-test/r/ctype_cp1250_ch.result
      mysql-test/r/ctype_cp1251.result
      mysql-test/r/ctype_eucjpms.result
      mysql-test/r/ctype_latin1.result
      mysql-test/r/ctype_ucs.result
      mysql-test/r/ctype_utf8.result
      mysql-test/r/ddl_i18n_koi8r.result
      mysql-test/r/ddl_i18n_utf8.result
      mysql-test/r/filesort_debug.result
      mysql-test/r/func_time.result
      mysql-test/r/gis.result
      mysql-test/r/group_by.result
      mysql-test/r/insert_select.result
      mysql-test/r/multi_update.result
      mysql-test/r/mysqldump.result
      mysql-test/r/partition.result
      mysql-test/r/signal_code.result
      mysql-test/r/sp-code.result
      mysql-test/r/variables.result
      mysql-test/r/xa.result
      mysql-test/suite/innodb/t/innodb_information_schema.test
      mysql-test/suite/rpl/r/rpl_failed_optimize.result
      mysql-test/suite/rpl/r/rpl_read_only.result
      mysql-test/suite/rpl/t/disabled.def
      mysql-test/suite/rpl/t/rpl_read_only.test
      mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test
      mysql-test/suite/sys_vars/r/all_vars.result
      mysql-test/t/alter_table.test
      mysql-test/t/ctype_cp1250_ch.test
      mysql-test/t/ctype_cp1251.test
      mysql-test/t/ctype_eucjpms.test
      mysql-test/t/filesort_debug.test
      mysql-test/t/func_time.test
      mysql-test/t/gis.test
      mysql-test/t/group_by.test
      mysql-test/t/insert_select.test
      mysql-test/t/multi_update.test
      mysql-test/t/mysqldump.test
      mysql-test/t/partition.test
      mysql-test/t/variables.test
      mysql-test/t/xa.test
      mysql-test/valgrind.supp
      mysys/charset.c
      mysys/default.c
      mysys/mf_format.c
      mysys/my_bitmap.c
      plugin/auth/auth_socket.c
      sql/filesort.cc
      sql/ha_ndbcluster_cond.cc
      sql/handler.cc
      sql/item_cmpfunc.cc
      sql/item_strfunc.cc
      sql/item_strfunc.h
      sql/item_timefunc.cc
      sql/item_timefunc.h
      sql/mysqld.cc
      sql/repl_failsafe.cc
      sql/repl_failsafe.h
      sql/set_var.cc
      sql/share/errmsg-utf8.txt
      sql/sp_head.cc
      sql/sql_acl.cc
      sql/sql_connect.cc
      sql/sql_connect.h
      sql/sql_lex.h
      sql/sql_load.cc
      sql/sql_parse.cc
      sql/sql_parse.h
      sql/sql_repl.cc
      sql/sql_repl.h
      sql/sql_select.cc
      sql/sql_string.h
      sql/sql_update.cc
      sql/sql_yacc.yy
      sql/sys_vars.cc
      sql/transaction.cc
      storage/innobase/CMakeLists.txt
      storage/innobase/btr/btr0btr.c
      storage/innobase/btr/btr0cur.c
      storage/innobase/buf/buf0rea.c
      storage/innobase/dict/dict0load.c
      storage/innobase/dict/dict0mem.c
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/handler/handler0alter.cc
      storage/innobase/include/btr0btr.h
      storage/innobase/include/btr0types.h
      storage/innobase/include/buf0flu.h
      storage/innobase/include/dict0dict.h
      storage/innobase/include/dict0dict.ic
      storage/innobase/include/dict0load.h
      storage/innobase/include/dict0mem.h
      storage/innobase/include/dict0types.h
      storage/innobase/include/page0zip.h
      storage/innobase/include/srv0srv.h
      storage/innobase/include/sync0sync.h
      storage/innobase/include/trx0purge.h
      storage/innobase/include/trx0rseg.h
      storage/innobase/include/trx0sys.h
      storage/innobase/include/trx0sys.ic
      storage/innobase/include/univ.i
      storage/innobase/page/page0cur.c
      storage/innobase/page/page0page.c
      storage/innobase/page/page0zip.c
      storage/innobase/row/row0mysql.c
      storage/innobase/row/row0upd.c
      storage/innobase/srv/srv0srv.c
      storage/innobase/srv/srv0start.c
      storage/innobase/sync/sync0rw.c
      storage/innobase/sync/sync0sync.c
      storage/innobase/trx/trx0purge.c
      storage/innobase/trx/trx0rseg.c
      storage/innobase/trx/trx0sys.c
      storage/innobase/trx/trx0trx.c
      storage/innobase/ut/ut0ut.c
      storage/myisam/mi_create.c
      support-files/mysql.spec.sh
      tests/mysql_client_test.c
      unittest/mysys/bitmap-t.c
 3170 Bjorn Munch	2011-02-24
      11766640 follow-up: fix for VS_CONFIG on Windows

    modified:
      mysql-test/lib/My/Find.pm
      mysql-test/mysql-test-run.pl
 3169 Bjorn Munch	2011-02-23 [merge]
      Upmerge 11762407 (54999) with additions

    modified:
      mysql-test/extra/binlog_tests/binlog.test
      mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test
      mysql-test/extra/rpl_tests/rpl_conflicts.test
      mysql-test/extra/rpl_tests/rpl_extra_col_master.test
      mysql-test/extra/rpl_tests/rpl_extra_col_slave.test
      mysql-test/extra/rpl_tests/rpl_loaddata.test
      mysql-test/extra/rpl_tests/rpl_row_basic.test
      mysql-test/extra/rpl_tests/rpl_row_tabledefs.test
      mysql-test/extra/rpl_tests/rpl_stm_EE_err2.test
      mysql-test/extra/rpl_tests/rpl_stop_middle_group.test
      mysql-test/include/mtr_warnings.sql
      mysql-test/r/flush_read_lock.result
      mysql-test/suite/binlog/r/binlog_base64_flag.result
      mysql-test/suite/binlog/r/binlog_row_binlog.result
      mysql-test/suite/binlog/r/binlog_stm_binlog.result
      mysql-test/suite/binlog/t/binlog_base64_flag.test
      mysql-test/suite/rpl/r/rpl_binlog_corruption.result
      mysql-test/suite/rpl/r/rpl_bug33931.result
      mysql-test/suite/rpl/r/rpl_circular_for_4_hosts.result
      mysql-test/suite/rpl/r/rpl_extra_col_master_innodb.result
      mysql-test/suite/rpl/r/rpl_extra_col_master_myisam.result
      mysql-test/suite/rpl/r/rpl_extra_col_slave_innodb.result
      mysql-test/suite/rpl/r/rpl_extra_col_slave_myisam.result
      mysql-test/suite/rpl/r/rpl_filter_tables_not_exist.result
      mysql-test/suite/rpl/r/rpl_heartbeat_basic.result
      mysql-test/suite/rpl/r/rpl_idempotency.result
      mysql-test/suite/rpl/r/rpl_ignore_table.result
      mysql-test/suite/rpl/r/rpl_incident.result
      mysql-test/suite/rpl/r/rpl_init_slave_errors.result
      mysql-test/suite/rpl/r/rpl_known_bugs_detection.result
      mysql-test/suite/rpl/r/rpl_loaddata.result
      mysql-test/suite/rpl/r/rpl_loaddata_fatal.result
      mysql-test/suite/rpl/r/rpl_mixed_binlog_max_cache_size.result
      mysql-test/suite/rpl/r/rpl_rotate_logs.result
      mysql-test/suite/rpl/r/rpl_row_basic_11bugs.result
      mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result
      mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result
      mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result
      mysql-test/suite/rpl/r/rpl_row_colSize.result
      mysql-test/suite/rpl/r/rpl_row_conflicts.result
      mysql-test/suite/rpl/r/rpl_row_idempotency.result
      mysql-test/suite/rpl/r/rpl_row_inexist_tbl.result
      mysql-test/suite/rpl/r/rpl_row_tabledefs_2myisam.result
      mysql-test/suite/rpl/r/rpl_row_tabledefs_3innodb.result
      mysql-test/suite/rpl/r/rpl_skip_error.result
      mysql-test/suite/rpl/r/rpl_slave_grp_exec.result
      mysql-test/suite/rpl/r/rpl_slave_load_tmpdir_not_exist.result
      mysql-test/suite/rpl/r/rpl_stm_EE_err2.result
      mysql-test/suite/rpl/r/rpl_stm_binlog_max_cache_size.result
      mysql-test/suite/rpl/r/rpl_stm_conflicts.result
      mysql-test/suite/rpl/r/rpl_stm_loaddata_concurrent.result
      mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result
      mysql-test/suite/rpl/r/rpl_stm_stop_middle_group.result
      mysql-test/suite/rpl/r/rpl_stop_slave.result
      mysql-test/suite/rpl/r/rpl_temporary_errors.result
      mysql-test/suite/rpl/r/rpl_typeconv.result
      mysql-test/suite/rpl/t/rpl_binlog_corruption.test
      mysql-test/suite/rpl/t/rpl_bug33931.test
      mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test
      mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test
      mysql-test/suite/rpl/t/rpl_heartbeat_basic.test
      mysql-test/suite/rpl/t/rpl_idempotency.test
      mysql-test/suite/rpl/t/rpl_ignore_table.test
      mysql-test/suite/rpl/t/rpl_incident.test
      mysql-test/suite/rpl/t/rpl_init_slave_errors.test
      mysql-test/suite/rpl/t/rpl_known_bugs_detection.test
      mysql-test/suite/rpl/t/rpl_loaddata_fatal.test
      mysql-test/suite/rpl/t/rpl_rotate_logs.test
      mysql-test/suite/rpl/t/rpl_row_basic_11bugs.test
      mysql-test/suite/rpl/t/rpl_row_colSize.test
      mysql-test/suite/rpl/t/rpl_row_idempotency.test
      mysql-test/suite/rpl/t/rpl_row_inexist_tbl.test
      mysql-test/suite/rpl/t/rpl_skip_error.test
      mysql-test/suite/rpl/t/rpl_slave_grp_exec.test
      mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test
      mysql-test/suite/rpl/t/rpl_stm_start_stop_slave.test
      mysql-test/suite/rpl/t/rpl_stop_slave.test
      mysql-test/suite/rpl/t/rpl_temporary_errors.test
      mysql-test/suite/rpl/t/rpl_typeconv.test
      mysql-test/t/flush_read_lock.test
=== modified file 'CMakeLists.txt'
--- a/CMakeLists.txt	2010-12-15 10:30:09 +0000
+++ b/CMakeLists.txt	2011-02-11 14:55:25 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 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
@@ -317,6 +317,24 @@ CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/inclu
                ${CMAKE_BINARY_DIR}/include/mysql_version.h )
 CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc.in
     ${CMAKE_BINARY_DIR}/sql/sql_builtin.cc)
+CONFIGURE_FILE(
+    ${CMAKE_SOURCE_DIR}/cmake/info_macros.cmake.in ${CMAKE_BINARY_DIR}/info_macros.cmake @ONLY)
+
+# Handle the "INFO_*" files.
+INCLUDE(${CMAKE_BINARY_DIR}/info_macros.cmake)
+# Source: This can be done during the cmake phase, all information is
+# available, but should be repeated on each "make" just in case someone
+# does "cmake ; make ; bzr pull ; make".
+CREATE_INFO_SRC(${CMAKE_BINARY_DIR}/Docs)
+ADD_CUSTOM_TARGET(INFO_SRC ALL
+  COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/info_src.cmake
+  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+)
+# Build flags: This must be postponed to the make phase.
+ADD_CUSTOM_TARGET(INFO_BIN ALL
+  COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/info_bin.cmake
+  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+)
 
 # Packaging
 IF(WIN32)
@@ -344,6 +362,7 @@ IF(NOT INSTALL_LAYOUT MATCHES "RPM")
   OPTIONAL
   )
   INSTALL(FILES README DESTINATION ${INSTALL_DOCREADMEDIR} COMPONENT Readme)
+  INSTALL(FILES ${CMAKE_BINARY_DIR}/Docs/INFO_SRC ${CMAKE_BINARY_DIR}/Docs/INFO_BIN DESTINATION ${INSTALL_DOCDIR})
   IF(UNIX)
     INSTALL(FILES Docs/INSTALL-BINARY DESTINATION ${INSTALL_DOCREADMEDIR} COMPONENT Readme)
   ENDIF()

=== modified file 'README'
--- a/README	2011-02-08 15:47:33 +0000
+++ b/README	2011-02-24 14:49:38 +0000
@@ -3,18 +3,29 @@ MySQL Server
 This is a release of MySQL, a dual-license SQL database server.
 For the avoidance of doubt, this particular copy of the software 
 is released under the version 2 of the GNU General Public License. 
-MySQL is brought to you by the MySQL team at Oracle.
+MySQL is brought to you by Oracle.
 
 Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 
 License information can be found in the COPYING file.
 
+MySQL FOSS License Exception
+We want free and open source software applications under certain
+licenses to be able to use specified GPL-licensed MySQL client
+libraries despite the fact that not all such FOSS licenses are
+compatible with version 2 of the GNU General Public License.  
+Therefore there are special exceptions to the terms and conditions 
+of the GPLv2 as applied to these client libraries, which are 
+identified and described in more detail in the FOSS License 
+Exception at 
+<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
+
 This distribution may include materials developed by third
 parties. For license and attribution notices for these
 materials, please refer to the documentation that accompanies
-this distribution (see the Licenses for Third-Party Components
-appendix). A copy of the license/notices is also reproduced 
-below. 
+this distribution (see the "Licenses for Third-Party Components"
+appendix) or view the online documentation at 
+<http://dev.mysql.com/doc/>.
 
 GPLv2 Disclaimer
 For the avoidance of doubt, except that if any license choice
@@ -38,8 +49,6 @@ Some Reference Manual sections of specia
   chapter.
 - For the new features/bugfix history, see the MySQL Change History 
   appendix.
-- For currently known bugs, see the Errors and Common Problems
-  appendix.
 
 You can browse the MySQL Reference Manual online or download it 
 in any of several formats at the URL given earlier in this file.

=== modified file 'VERSION'
--- a/VERSION	2011-02-08 13:59:03 +0000
+++ b/VERSION	2011-02-11 10:10:40 +0000
@@ -1,4 +1,4 @@
 MYSQL_VERSION_MAJOR=5
 MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=10
+MYSQL_VERSION_PATCH=11
 MYSQL_VERSION_EXTRA=

=== modified file 'client/client_priv.h'
--- a/client/client_priv.h	2011-01-16 03:59:05 +0000
+++ b/client/client_priv.h	2011-02-21 10:15:29 +0000
@@ -50,9 +50,6 @@ enum options_client
   OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_SERVER_ARG,
   OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME,
   OPT_SIGINT_IGNORE, OPT_HEXBLOB, OPT_ORDER_BY_PRIMARY, OPT_COUNT,
-#ifdef HAVE_NDBCLUSTER_DB
-  OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING,
-#endif
   OPT_TRIGGERS,
   OPT_MYSQL_ONLY_PRINT,
   OPT_MYSQL_LOCK_DIRECTORY,

=== modified file 'client/mysql.cc'
--- a/client/mysql.cc	2011-02-05 05:04:15 +0000
+++ b/client/mysql.cc	2011-02-09 06:50:11 +0000
@@ -1127,6 +1127,8 @@ int main(int argc,char *argv[])
   if (status.batch && !status.line_buff &&
       !(status.line_buff= batch_readline_init(MAX_BATCH_BUFFER_SIZE, stdin)))
   {
+    put_info("Can't initialize batch_readline - may be the input source is "
+             "a directory or a block device.", INFO_ERROR, 0);
     free_defaults(defaults_argv);
     my_end(0);
     exit(1);

=== modified file 'client/mysqldump.c'
--- a/client/mysqldump.c	2011-01-16 03:59:05 +0000
+++ b/client/mysqldump.c	2011-02-21 07:12:27 +0000
@@ -1153,6 +1153,9 @@ static int switch_db_collation(FILE *sql
 {
   if (strcmp(current_db_cl_name, required_db_cl_name) != 0)
   {
+    char quoted_db_buf[NAME_LEN * 2 + 3];
+    char *quoted_db_name= quote_name(db_name, quoted_db_buf, FALSE);
+
     CHARSET_INFO *db_cl= get_charset_by_name(required_db_cl_name, MYF(0));
 
     if (!db_cl)
@@ -1160,7 +1163,7 @@ static int switch_db_collation(FILE *sql
 
     fprintf(sql_file,
             "ALTER DATABASE %s CHARACTER SET %s COLLATE %s %s\n",
-            (const char *) db_name,
+            (const char *) quoted_db_name,
             (const char *) db_cl->csname,
             (const char *) db_cl->name,
             (const char *) delimiter);
@@ -1181,6 +1184,9 @@ static int restore_db_collation(FILE *sq
                                 const char *delimiter,
                                 const char *db_cl_name)
 {
+  char quoted_db_buf[NAME_LEN * 2 + 3];
+  char *quoted_db_name= quote_name(db_name, quoted_db_buf, FALSE);
+
   CHARSET_INFO *db_cl= get_charset_by_name(db_cl_name, MYF(0));
 
   if (!db_cl)
@@ -1188,7 +1194,7 @@ static int restore_db_collation(FILE *sq
 
   fprintf(sql_file,
           "ALTER DATABASE %s CHARACTER SET %s COLLATE %s %s\n",
-          (const char *) db_name,
+          (const char *) quoted_db_name,
           (const char *) db_cl->csname,
           (const char *) db_cl->name,
           (const char *) delimiter);

=== modified file 'client/readline.cc'
--- a/client/readline.cc	2011-02-05 05:04:15 +0000
+++ b/client/readline.cc	2011-02-09 11:16:33 +0000
@@ -18,6 +18,7 @@
 #include <my_global.h>
 #include <my_sys.h>
 #include <m_string.h>
+#include <my_dir.h>
 #include "my_readline.h"
 
 static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
@@ -30,6 +31,15 @@ static char *intern_read_line(LINE_BUFFE
 LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
 {
   LINE_BUFFER *line_buff;
+  MY_STAT input_file_stat;
+
+#ifndef __WIN__
+  if (my_fstat(fileno(file), &input_file_stat, MYF(MY_WME)) ||
+      MY_S_ISDIR(input_file_stat.st_mode) ||
+      MY_S_ISBLK(input_file_stat.st_mode))
+    return 0;
+#endif
+
   if (!(line_buff=(LINE_BUFFER*)
         my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
     return 0;

=== added file 'cmake/info_bin.cmake'
--- a/cmake/info_bin.cmake	1970-01-01 00:00:00 +0000
+++ b/cmake/info_bin.cmake	2011-02-11 14:55:25 +0000
@@ -0,0 +1,30 @@
+# 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+
+# The sole purpose of this cmake control file is to create the "INFO_BIN" file.
+
+# By having a separate cmake file for this, it is ensured this happens
+# only in the build (Unix: "make") phase, not when cmake runs.
+# This, in turn, avoids creating stuff in the source directory -
+# it should get into the binary directory only.
+
+
+# Get the macros which the "INFO_*" files.
+INCLUDE(${CMAKE_BINARY_DIR}/info_macros.cmake)
+
+# Here is where the action is.
+CREATE_INFO_BIN()
+

=== added file 'cmake/info_macros.cmake.in'
--- a/cmake/info_macros.cmake.in	1970-01-01 00:00:00 +0000
+++ b/cmake/info_macros.cmake.in	2011-02-11 14:55:25 +0000
@@ -0,0 +1,132 @@
+# 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
+
+
+# Handle/create the "INFO_*" files describing a MySQL (server) binary.
+# This is part of the fix for bug#42969.
+
+
+# Several of cmake's variables need to be translated from '@' notation
+# to '${}', this is done by the "configure" call in top level "CMakeLists.txt".
+# If further variables are used in this file, add them to this list.
+
+SET(VERSION "@VERSION@")
+SET(CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@")
+SET(CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@")
+SET(CMAKE_GENERATOR "@CMAKE_GENERATOR@")
+SET(CMAKE_SIZEOF_VOID_P "@CMAKE_SIZEOF_VOID_P@")
+SET(BZR_EXECUTABLE "@BZR_EXECUTABLE@")
+SET(CMAKE_CROSSCOMPILING "@CMAKE_CROSSCOMPILING@")
+SET(CMAKE_HOST_SYSTEM "@CMAKE_HOST_SYSTEM@")
+SET(CMAKE_HOST_SYSTEM_PROCESSOR "@CMAKE_HOST_SYSTEM_PROCESSOR@")
+SET(CMAKE_SYSTEM "@CMAKE_SYSTEM@")
+SET(CMAKE_SYSTEM_PROCESSOR "@CMAKE_SYSTEM_PROCESSOR@")
+ 
+ 
+# Create an "INFO_SRC" file with information about the source (only).
+# We use "bzr version-info", if possible, and the "VERSION" contents.
+#
+# Outside development (BZR tree), the "INFO_SRC" file will not be modified
+# provided it exists (from "make dist" or a source tarball creation).
+
+MACRO(CREATE_INFO_SRC target_dir)
+  SET(INFO_SRC "${target_dir}/INFO_SRC")
+
+  IF(EXISTS ${CMAKE_SOURCE_DIR}/.bzr)
+    # Sources are in a BZR repository: Always update.
+    EXECUTE_PROCESS(
+      COMMAND ${BZR_EXECUTABLE} version-info ${CMAKE_SOURCE_DIR}
+      OUTPUT_VARIABLE VERSION_INFO
+      RESULT_VARIABLE RESULT
+    )
+    FILE(WRITE ${INFO_SRC} "${VERSION_INFO}\n")
+    # to debug, add: FILE(APPEND ${INFO_SRC} "\nResult ${RESULT}\n")
+    # For better readability ...
+    FILE(APPEND ${INFO_SRC} "\nMySQL source ${VERSION}\n")
+  ELSEIF(EXISTS ${INFO_SRC})
+    # Outside a BZR tree, there is no need to change an existing "INFO_SRC",
+    # it cannot be improved.
+  ELSEIF(EXISTS ${CMAKE_SOURCE_DIR}/Docs/INFO_SRC)
+    # If we are building from a source distribution, it also contains "INFO_SRC".
+    # Similar, the export used for a release build already has the file.
+    FILE(READ ${CMAKE_SOURCE_DIR}/Docs/INFO_SRC SOURCE_INFO)
+    FILE(WRITE ${INFO_SRC} "${SOURCE_INFO}\n")
+  ELSEIF(EXISTS ${CMAKE_SOURCE_DIR}/INFO_SRC)
+    # This is not the proper location, but who knows ...
+    FILE(READ ${CMAKE_SOURCE_DIR}/INFO_SRC SOURCE_INFO)
+    FILE(WRITE ${INFO_SRC} "${SOURCE_INFO}\n")
+  ELSE()
+    # This is a fall-back.
+    FILE(WRITE ${INFO_SRC} "\nMySQL source ${VERSION}\n")
+  ENDIF()
+ENDMACRO(CREATE_INFO_SRC)
+
+
+# This is for the "real" build, must be run again with each cmake run
+# to make sure we report the current flags (not those of some previous run).
+
+MACRO(CREATE_INFO_BIN)
+  SET(INFO_BIN "Docs/INFO_BIN")
+
+  FILE(WRITE ${INFO_BIN} "===== Information about the build process: =====\n")
+  IF (WIN32)
+    EXECUTE_PROCESS(COMMAND cmd /c date /T OUTPUT_VARIABLE TMP_DATE)
+  ELSEIF(UNIX)
+    EXECUTE_PROCESS(COMMAND date "+%Y-%m-%d %H:%M:%S" OUTPUT_VARIABLE TMP_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
+  ELSE()
+    SET(TMP_DATE "(no date command known for this platform)")
+  ENDIF()
+  SITE_NAME(HOSTNAME)
+  FILE(APPEND ${INFO_BIN} "Build was run at ${TMP_DATE} on host '${HOSTNAME}'\n\n")
+
+  # According to the cmake docs, these variables should always be set.
+  # However, they are empty in my tests, using cmake 2.6.4 on Linux, various Unix, and Windows.
+  # Still, include this code, so we will profit if a build environment does provide that info.
+  IF(CMAKE_HOST_SYSTEM)
+    FILE(APPEND ${INFO_BIN} "Build was done on  ${CMAKE_HOST_SYSTEM} using ${CMAKE_HOST_SYSTEM_PROCESSOR}\n")
+  ENDIF()
+  IF(CMAKE_CROSSCOMPILING)
+    FILE(APPEND ${INFO_BIN} "Build was done for ${CMAKE_SYSTEM} using ${CMAKE_SYSTEM_PROCESSOR}\n")
+  ENDIF()
+
+  # ${CMAKE_VERSION} doesn't work in 2.6.0, use the separate components.
+  FILE(APPEND ${INFO_BIN} "Build was done using cmake ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} \n\n")
+
+  IF (WIN32)
+    FILE(APPEND ${INFO_BIN} "===== Compiler / generator used: =====\n")
+    FILE(APPEND ${INFO_BIN} ${CMAKE_GENERATOR} "\n\n")
+  ELSEIF(UNIX)
+    FILE(APPEND ${INFO_BIN} "===== Compiler flags used (from the 'sql/' subdirectory): =====\n")
+    IF(EXISTS sql/CMakeFiles/sql.dir/flags.make)
+      EXECUTE_PROCESS(COMMAND egrep "^# compile|^C_|^CXX_" sql/CMakeFiles/sql.dir/flags.make OUTPUT_VARIABLE COMPILE_FLAGS)
+      FILE(APPEND ${INFO_BIN} ${COMPILE_FLAGS} "\n")
+    ELSE()
+      FILE(APPEND ${INFO_BIN} "File 'sql/CMakeFiles/sql.dir/flags.make' is not yet found.\n\n")
+    ENDIF()
+  ENDIF()
+  FILE(APPEND ${INFO_BIN} "Pointer size: ${CMAKE_SIZEOF_VOID_P}\n\n")
+
+  FILE(APPEND ${INFO_BIN} "===== Feature flags used: =====\n")
+  IF(EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt)
+    # Attention: "-N" prevents cmake from entering a recursion, and it must be a separate flag from "-L".
+    EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -N -L ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE FEATURE_FLAGS)
+    FILE(APPEND ${INFO_BIN} ${FEATURE_FLAGS} "\n")
+  ELSE()
+    FILE(APPEND ${INFO_BIN} "File 'CMakeCache.txt' is not yet found.\n\n")
+  ENDIF()
+
+  FILE(APPEND ${INFO_BIN} "===== EOF =====\n")
+ENDMACRO(CREATE_INFO_BIN)
+

=== added file 'cmake/info_src.cmake'
--- a/cmake/info_src.cmake	1970-01-01 00:00:00 +0000
+++ b/cmake/info_src.cmake	2011-02-11 14:55:25 +0000
@@ -0,0 +1,31 @@
+# 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+
+# The sole purpose of this cmake control file is to create the "INFO_SRC" file.
+
+# As long as and "bzr pull" (or "bzr commit") is followed by a "cmake",
+# the call in top level "CMakeLists.txt" is sufficient.
+# This file is to provide a separate target for the "make" phase,
+# to ensure the BZR revision-id is correct even after a sequence
+#   cmake ; make ; bzr pull ; make
+
+
+# Get the macros which handle the "INFO_*" files.
+INCLUDE(${CMAKE_BINARY_DIR}/info_macros.cmake)
+
+# Here is where the action is.
+CREATE_INFO_SRC(${CMAKE_BINARY_DIR}/Docs)
+

=== modified file 'cmake/make_dist.cmake.in'
--- a/cmake/make_dist.cmake.in	2010-11-20 14:47:50 +0000
+++ b/cmake/make_dist.cmake.in	2011-02-11 14:55:25 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2009 Sun Microsystems, Inc
+# Copyright (c) 2009, 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
@@ -106,6 +106,12 @@ IF(MYSQL_DOCS_LOCATION)
   EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_directory "${MYSQL_DOCS_LOCATION}" "${PACKAGE_DIR}")
 ENDIF()
 
+# Ensure there is an "INFO_SRC" file.
+INCLUDE(${CMAKE_BINARY_DIR}/info_macros.cmake)
+IF(NOT EXISTS ${PACKAGE_DIR}/Docs/INFO_SRC)
+  CREATE_INFO_SRC(${PACKAGE_DIR}/Docs)
+ENDIF()
+
 # In case we used CPack, it could have copied some
 # extra files that are not usable on different machines.
 FILE(REMOVE ${PACKAGE_DIR}/CMakeCache.txt)

=== modified file 'extra/comp_err.c'
--- a/extra/comp_err.c	2010-07-20 19:30:10 +0000
+++ b/extra/comp_err.c	2011-02-16 13:48:30 +0000
@@ -219,14 +219,13 @@ static void print_escaped_string(FILE *f
 
 static int create_header_files(struct errors *error_head)
 {
-  uint er_last;
+  uint er_last= 0;
   FILE *er_definef, *sql_statef, *er_namef;
   struct errors *tmp_error;
   struct message *er_msg;
   const char *er_text;
 
   DBUG_ENTER("create_header_files");
-  LINT_INIT(er_last);
 
   if (!(er_definef= my_fopen(HEADERFILE, O_WRONLY, MYF(MY_WME))))
   {

=== modified file 'include/my_bit.h'
--- a/include/my_bit.h	2010-07-23 20:18:36 +0000
+++ b/include/my_bit.h	2011-02-16 15:33:02 +0000
@@ -1,3 +1,18 @@
+/* Copyright (c) 2007, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
 #ifndef MY_BIT_INCLUDED
 #define MY_BIT_INCLUDED
 
@@ -44,9 +59,12 @@ static inline uint my_count_bits(ulonglo
 #endif
 }
 
-static inline uint my_count_bits_ushort(ushort v)
+static inline uint my_count_bits_uint32(uint32 v)
 {
-  return _my_bits_nbits[v];
+  return (uint) (uchar) (_my_bits_nbits[(uchar)  v] +
+                         _my_bits_nbits[(uchar) (v >> 8)] +
+                         _my_bits_nbits[(uchar) (v >> 16)] +
+                         _my_bits_nbits[(uchar) (v >> 24)]);
 }
 
 

=== modified file 'include/my_bitmap.h'
--- a/include/my_bitmap.h	2011-01-11 09:07:37 +0000
+++ b/include/my_bitmap.h	2011-02-16 15:33:02 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB, 2009 Sun Microsystems, Inc
+/* Copyright (c) 2000, 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
@@ -125,9 +125,10 @@ bitmap_is_set(const MY_BITMAP *map,uint
 
 static inline my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2)
 {
-  *(map1)->last_word_ptr|= (map1)->last_word_mask;
-  *(map2)->last_word_ptr|= (map2)->last_word_mask;
-  return memcmp((map1)->bitmap, (map2)->bitmap, 4*no_words_in_map((map1)))==0;
+  if (memcmp(map1->bitmap, map2->bitmap, 4*(no_words_in_map(map1)-1)) != 0)
+    return FALSE;
+  return ((*map1->last_word_ptr | map1->last_word_mask) ==
+          (*map2->last_word_ptr | map2->last_word_mask));
 }
 
 #define bitmap_clear_all(MAP) \

=== modified file 'include/my_global.h'
--- a/include/my_global.h	2011-01-11 09:07:37 +0000
+++ b/include/my_global.h	2011-02-21 10:15:29 +0000
@@ -1476,7 +1476,6 @@ static inline double rint(double x)
 
 #undef HAVE_OPENSSL
 #undef HAVE_SMEM				/* No shared memory */
-#undef HAVE_NDBCLUSTER_DB /* No NDB cluster */
 
 #endif /* EMBEDDED_LIBRARY */
 

=== modified file 'include/mysql_embed.h'
--- a/include/mysql_embed.h	2010-11-09 14:53:53 +0000
+++ b/include/mysql_embed.h	2011-02-21 10:15:29 +0000
@@ -25,7 +25,6 @@
 
 #undef HAVE_DLOPEN				/* No udf functions */
 #undef HAVE_SMEM				/* No shared memory */
-#undef HAVE_NDBCLUSTER_DB /* No NDB cluster */
 
 #endif /* EMBEDDED_LIBRARY */
 #endif /* MYSQL_EMBED_INCLUDED */

=== modified file 'mysql-test/collections/default.experimental'
--- a/mysql-test/collections/default.experimental	2011-02-08 13:59:03 +0000
+++ b/mysql-test/collections/default.experimental	2011-02-18 12:57:50 +0000
@@ -5,8 +5,6 @@ binlog.binlog_multi_engine
 
 funcs_1.charset_collation_1              # depends on compile-time decisions
 
-innodb.innodb_information_schema         # Bug#48883 2010-05-11 alik Test "innodb_information_schema" takes fewer locks than expected
-
 main.func_math @freebsd                  # Bug#43020 2010-05-04 alik main.func_math fails on FreeBSD in PB2
 main.gis-rtree @freebsd                  # Bug#38965 2010-05-04 alik test cases gis-rtree, type_float, type_newdecimal fail in embedded server
 main.lock_multi_bug38499                 # Bug#47448 2009-09-19 alik main.lock_multi_bug38499 times out sporadically

=== added file 'mysql-test/collections/default.release'
--- a/mysql-test/collections/default.release	1970-01-01 00:00:00 +0000
+++ b/mysql-test/collections/default.release	2011-02-09 19:41:12 +0000
@@ -0,0 +1,11 @@
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=debug      --vardir=var-debug                       --skip-ndbcluster --skip-rpl --report-features --debug-server
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=normal     --vardir=var-normal                      --skip-ndbcluster --report-features
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=ps         --vardir=var-ps                          --skip-ndbcluster --ps-protocol
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=funcs1+ps  --vardir=var-funcs_1_ps --suite=funcs_1  --ps-protocol
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=funcs2     --vardir=var-funcs2     --suite=funcs_2
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=partitions --vardir=var-parts      --suite=parts
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=stress     --vardir=var-stress     --suite=stress
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=jp         --vardir=var-jp         --suite=jp
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=embedded   --vardir=var-embedded                    --embedded-server --skip-rpl --skip-ndbcluster
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=nist       --vardir=var-nist       --suite=nist
+perl mysql-test-run.pl --force --timer --parallel=auto --experimental=collections/default.experimental --comment=nist+ps    --vardir=var-nist_ps    --suite=nist     --ps-protocol

=== removed file 'mysql-test/collections/test-bt'
--- a/mysql-test/collections/test-bt	2011-02-21 12:56:43 +0000
+++ b/mysql-test/collections/test-bt	1970-01-01 00:00:00 +0000
@@ -1,10 +0,0 @@
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=normal  --skip-ndbcluster --report-features --experimental=collections/default.experimental --unit-tests
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=ps --skip-ndbcluster --ps-protocol --experimental=collections/default.experimental
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=funcs1+ps  --suite=funcs_1 --ps-protocol --experimental=collections/default.experimental
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=funcs2     --suite=funcs_2 --experimental=collections/default.experimental
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=partitions --suite=parts   --experimental=collections/default.experimental
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=stress     --suite=stress  --experimental=collections/default.experimental
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=jp         --suite=jp      --experimental=collections/default.experimental
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=embedded  --embedded-server --skip-rpl --skip-ndbcluster --experimental=collections/default.experimental
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=nist --suite=nist --experimental=collections/default.experimental
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=nist+ps --suite=nist --ps-protocol --experimental=collections/default.experimental

=== removed file 'mysql-test/collections/test-bt-debug'
--- a/mysql-test/collections/test-bt-debug	2011-02-21 12:56:43 +0000
+++ b/mysql-test/collections/test-bt-debug	1970-01-01 00:00:00 +0000
@@ -1 +0,0 @@
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=debug --skip-ndbcluster --skip-rpl --report-features --experimental=collections/default.experimental --unit-tests

=== removed file 'mysql-test/collections/test-bt-debug-fast'

=== removed file 'mysql-test/collections/test-bt-fast'
--- a/mysql-test/collections/test-bt-fast	2011-02-21 12:56:43 +0000
+++ b/mysql-test/collections/test-bt-fast	1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=ps  --skip-ndbcluster --ps-protocol --report-features --experimental=collections/default.experimental --unit-tests
-perl mysql-test-run.pl --force --timer --parallel=auto --comment=stress --suite=stress --experimental=collections/default.experimental

=== modified file 'mysql-test/extra/rpl_tests/rpl_failed_optimize.test'
--- a/mysql-test/extra/rpl_tests/rpl_failed_optimize.test	2010-12-19 17:07:28 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_failed_optimize.test	2011-02-15 11:59:12 +0000
@@ -2,22 +2,24 @@
 
 #
 # BUG#5551 "Failed OPTIMIZE TABLE is logged to binary log"
-# Replication should work when OPTIMIZE TABLE timeouts, and 
-# when OPTIMIZE TABLE is executed on a non-existing table
+# Replication should work when when OPTIMIZE TABLE is 
+# executed on a non-existing table.
 #
+# Due to patch for BUG#989, checking that an OPTIMIZE
+# that fails due to a lock wait timeout on an InnoDB table
+# is not valid anymore, as an mdl lock is hit before,
+# thence no timeout occurs, but instead a deadlock.
+#
+
 
 eval CREATE TABLE t1 ( a int ) ENGINE=$engine_type;
 BEGIN;
 INSERT INTO t1 VALUES (1);
 
 connection master1;
-OPTIMIZE TABLE t1;
-
 OPTIMIZE TABLE non_existing;  
 sync_slave_with_master;
 
-# End of 4.1 tests
-
 connection master;
 select * from t1;
 commit;

=== modified file 'mysql-test/include/ctype_numconv.inc'
--- a/mysql-test/include/ctype_numconv.inc	2010-11-19 17:15:47 +0000
+++ b/mysql-test/include/ctype_numconv.inc	2011-02-10 13:38:18 +0000
@@ -1738,6 +1738,35 @@ DROP TABLE t1;
 
 
 --echo #
+--echo # Bug #31384 	DATE_ADD() and DATE_SUB() return binary data
+--echo #
+SELECT @@collation_connection, @@character_set_results;
+CREATE TABLE t1 AS
+SELECT
+  DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
+  DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+  DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+  DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+--enable_metadata
+# PS protocol gives different "Max length" value for DATETIME.
+--disable_ps_protocol
+SELECT
+  DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
+  DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+  DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+  DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+--disable_metadata
+--enable_ps_protocol
+SELECT
+  HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
+  HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
+  HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
+  HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
+ 
+
+--echo #
 --echo # Bug#52159 returning time type from function and empty left join causes debug assertion
 --echo #
 CREATE FUNCTION f1() RETURNS TIME RETURN 1;

=== modified file 'mysql-test/lib/My/Find.pm'
--- a/mysql-test/lib/My/Find.pm	2011-01-18 10:21:37 +0000
+++ b/mysql-test/lib/My/Find.pm	2011-02-24 14:11:05 +0000
@@ -28,8 +28,6 @@ use My::Platform;
 use base qw(Exporter);
 our @EXPORT= qw(my_find_bin my_find_dir my_find_file NOT_REQUIRED);
 
-our $vs_config_dir;
-
 my $bin_extension= ".exe" if IS_WINDOWS;
 
 # Helper function to be used for fourth parameter to find functions
@@ -158,7 +156,8 @@ sub my_find_paths {
   # User can select to look in a special build dir
   # which is a subdirectory of any of the paths
   my @extra_dirs;
-  my $build_dir= $vs_config_dir || $ENV{MTR_VS_CONFIG} || $ENV{MTR_BUILD_DIR};
+  my $build_dir= $::opt_config_dir || $ENV{MTR_VS_CONFIG}
+                                   || $ENV{MTR_BUILD_DIR};
   push(@extra_dirs, $build_dir) if defined $build_dir;
 
   if (defined $extension){

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2011-02-21 12:56:43 +0000
+++ b/mysql-test/mysql-test-run.pl	2011-02-24 15:28:33 +0000
@@ -1579,12 +1579,6 @@ sub command_line_setup {
     $debug_d= "d,query,info,error,enter,exit";
   }
 
-  if ($opt_debug && $opt_debug ne "1")
-  {
-    $debug_d= "d,$opt_debug";
-    $debug_d= "d,query,info,error,enter,exit" if $opt_debug eq "std";
-  }
-
   mtr_report("Checking supported features...");
 
   check_ndbcluster_support(\%mysqld_variables);
@@ -2041,7 +2035,7 @@ sub read_plugin_defs($)
 
   # Need to check if we will be running mysqld-debug
   if ($opt_debug_server) {
-    $running_debug= 1 if find_mysqld($basedir) =~ /-debug$/;
+    $running_debug= 1 if find_mysqld($basedir) =~ /mysqld-debug/;
   }
 
   while (<PLUGDEF>) {
@@ -2185,6 +2179,7 @@ sub environment_setup {
   $ENV{'MYSQL_TMP_DIR'}=      $opt_tmpdir;
   $ENV{'MYSQLTEST_VARDIR'}=   $opt_vardir;
   $ENV{'MYSQL_LIBDIR'}=       "$basedir/lib";
+  $ENV{'MYSQL_BINDIR'}=       "$bindir";
   $ENV{'MYSQL_SHAREDIR'}=     $path_language;
   $ENV{'MYSQL_CHARSETSDIR'}=  $path_charsetsdir;
   
@@ -5677,6 +5672,7 @@ sub run_ctest() {
   chdir ($bindir) or die ("Could not chdir to $bindir");
   my $tinfo;
   my $no_ctest= (IS_WINDOWS) ? 256 : -1;
+  my $ctest_vs= "";
 
   # Just ignore if not configured/built to run ctest
   if (! -f "CTestTestfile.cmake") {
@@ -5684,9 +5680,12 @@ sub run_ctest() {
     return;
   }
 
+  # Add vs-config option if needed
+  $ctest_vs= "-C $opt_vs_config" if $opt_vs_config;
+
   # Also silently ignore if we don't have ctest and didn't insist
   # Now, run ctest and collect output
-  my $ctest_out= `ctest 2>&1`;
+  my $ctest_out= `ctest $ctest_vs 2>&1`;
   if ($? == $no_ctest && $opt_ctest == -1) {
     chdir($olddir);
     return;

=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result	2010-07-26 09:22:38 +0000
+++ b/mysql-test/r/alter_table.result	2011-02-21 11:30:08 +0000
@@ -1383,3 +1383,11 @@ ALTER TABLE t1 CHANGE a id INT;
 affected rows: 0
 info: Records: 0  Duplicates: 0  Warnings: 0
 DROP TABLE t1;
+#
+# Bug#11754461 CANNOT ALTER TABLE WHEN KEY PREFIX TOO LONG
+#
+DROP DATABASE IF EXISTS db1;
+CREATE DATABASE db1 CHARACTER SET utf8;
+CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100)));
+ALTER TABLE db1.t1 ADD baz INT;
+DROP DATABASE db1;

=== modified file 'mysql-test/r/ctype_binary.result'
--- a/mysql-test/r/ctype_binary.result	2010-11-19 17:15:47 +0000
+++ b/mysql-test/r/ctype_binary.result	2011-02-10 08:18:08 +0000
@@ -2767,6 +2767,46 @@ id	select_type	table	type	possible_keys
 1	SIMPLE	t1	range	date_column	date_column	9	NULL	1	Using where
 DROP TABLE t1;
 #
+# Bug #31384 	DATE_ADD() and DATE_SUB() return binary data
+#
+SELECT @@collation_connection, @@character_set_results;
+@@collation_connection	@@character_set_results
+binary	binary
+CREATE TABLE t1 AS
+SELECT
+DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
+DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `field_str1` varbinary(29) DEFAULT NULL,
+  `field1_str2` varbinary(29) DEFAULT NULL,
+  `field_date` date DEFAULT NULL,
+  `field_datetime` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SELECT
+DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
+DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
+def					field_str1	254	29	10	Y	128	31	63
+def					field1_str2	254	29	19	Y	128	31	63
+def					field_date	10	29	10	Y	128	31	63
+def					field_datetime	12	29	19	Y	128	31	63
+field_str1	field1_str2	field_date	field_datetime
+2007-08-02	2007-08-03 17:32:00	2007-08-02	2007-08-03 17:32:00
+SELECT
+HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
+HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
+HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
+HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
+field_str1	field1_str2	field_date	field_datetime
+323030372D30382D30322032333A35393A3030	323030372D30382D30332031373A33323A3030	323030372D30382D3032	323030372D30382D30332031373A33323A3030
+#
 # Bug#52159 returning time type from function and empty left join causes debug assertion
 #
 CREATE FUNCTION f1() RETURNS TIME RETURN 1;

=== modified file 'mysql-test/r/ctype_cp1250_ch.result'
--- a/mysql-test/r/ctype_cp1250_ch.result	2008-03-07 21:14:56 +0000
+++ b/mysql-test/r/ctype_cp1250_ch.result	2011-02-17 11:53:09 +0000
@@ -238,3 +238,6 @@ select a from t1 where a like "abcdefgh�
 a
 abcdefgh�
 drop table t1;
+set global LC_MESSAGES=convert((@@global.log_bin_trust_function_creators) 
+using cp1250);
+ERROR HY000: Unknown locale: '1'

=== modified file 'mysql-test/r/ctype_cp1251.result'
--- a/mysql-test/r/ctype_cp1251.result	2010-11-26 14:22:06 +0000
+++ b/mysql-test/r/ctype_cp1251.result	2011-02-18 07:32:40 +0000
@@ -386,6 +386,8 @@ FD	FD	FD	D18D	FD
 FE	FE	FE	D18E	FE	
 FF	FF	FF	D18F	FF	
 DROP TABLE t1;
+set global LC_TIME_NAMES=convert((-8388608) using cp1251);
+ERROR HY000: Unknown locale: '-8388608'
 #
 # End of 5.1 tests
 #
@@ -3157,6 +3159,46 @@ id	select_type	table	type	possible_keys
 1	SIMPLE	t1	range	date_column	date_column	9	NULL	1	Using where
 DROP TABLE t1;
 #
+# Bug #31384 	DATE_ADD() and DATE_SUB() return binary data
+#
+SELECT @@collation_connection, @@character_set_results;
+@@collation_connection	@@character_set_results
+cp1251_general_ci	cp1251
+CREATE TABLE t1 AS
+SELECT
+DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
+DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `field_str1` varchar(29) CHARACTER SET cp1251 DEFAULT NULL,
+  `field1_str2` varchar(29) CHARACTER SET cp1251 DEFAULT NULL,
+  `field_date` date DEFAULT NULL,
+  `field_datetime` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SELECT
+DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
+DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
+def					field_str1	254	29	10	Y	0	31	51
+def					field1_str2	254	29	19	Y	0	31	51
+def					field_date	10	29	10	Y	128	31	63
+def					field_datetime	12	29	19	Y	128	31	63
+field_str1	field1_str2	field_date	field_datetime
+2007-08-02	2007-08-03 17:32:00	2007-08-02	2007-08-03 17:32:00
+SELECT
+HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
+HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
+HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
+HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
+field_str1	field1_str2	field_date	field_datetime
+323030372D30382D30322032333A35393A3030	323030372D30382D30332031373A33323A3030	323030372D30382D3032	323030372D30382D30332031373A33323A3030
+#
 # Bug#52159 returning time type from function and empty left join causes debug assertion
 #
 CREATE FUNCTION f1() RETURNS TIME RETURN 1;
@@ -3177,5 +3219,20 @@ maketime(`a`,`a`,`a`)
 DROP TABLE t1;
 SET sql_mode=default;
 #
+# Bug#60101 COALESCE with cp1251 tables causes [Err] 1267 - Illegal mix of collations
+#
+CREATE TABLE t1 (test1 INT, test2 VARCHAR(255));
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `test1` int(11) DEFAULT NULL,
+  `test2` varchar(255) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT COALESCE(IF(test1=1, 1, NULL), test2) FROM t1;
+COALESCE(IF(test1=1, 1, NULL), test2)
+SELECT COALESCE(IF(test1=1, NULL, 1), test2) FROM t1;
+COALESCE(IF(test1=1, NULL, 1), test2)
+DROP TABLE t1;
+#
 # End of 5.5 tests
 #

=== modified file 'mysql-test/r/ctype_eucjpms.result'
--- a/mysql-test/r/ctype_eucjpms.result	2010-07-03 23:17:03 +0000
+++ b/mysql-test/r/ctype_eucjpms.result	2011-02-17 11:53:09 +0000
@@ -9859,6 +9859,8 @@ hex(convert(_eucjpms 0xA5FE41 using ucs2
 select hex(convert(_eucjpms 0x8FABF841 using ucs2));
 hex(convert(_eucjpms 0x8FABF841 using ucs2))
 003F0041
+set global LC_TIME_NAMES=convert((convert((0x63) using eucjpms)) using utf8);
+ERROR HY000: Unknown locale: 'c'
 #
 # Start of 5.5 tests
 #

=== modified file 'mysql-test/r/ctype_latin1.result'
--- a/mysql-test/r/ctype_latin1.result	2010-11-22 11:47:28 +0000
+++ b/mysql-test/r/ctype_latin1.result	2011-02-10 08:18:08 +0000
@@ -3186,6 +3186,46 @@ id	select_type	table	type	possible_keys
 1	SIMPLE	t1	range	date_column	date_column	9	NULL	1	Using where
 DROP TABLE t1;
 #
+# Bug #31384 	DATE_ADD() and DATE_SUB() return binary data
+#
+SELECT @@collation_connection, @@character_set_results;
+@@collation_connection	@@character_set_results
+latin1_swedish_ci	latin1
+CREATE TABLE t1 AS
+SELECT
+DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
+DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `field_str1` varchar(29) DEFAULT NULL,
+  `field1_str2` varchar(29) DEFAULT NULL,
+  `field_date` date DEFAULT NULL,
+  `field_datetime` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SELECT
+DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
+DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
+def					field_str1	254	29	10	Y	0	31	8
+def					field1_str2	254	29	19	Y	0	31	8
+def					field_date	10	29	10	Y	128	31	63
+def					field_datetime	12	29	19	Y	128	31	63
+field_str1	field1_str2	field_date	field_datetime
+2007-08-02	2007-08-03 17:32:00	2007-08-02	2007-08-03 17:32:00
+SELECT
+HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
+HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
+HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
+HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
+field_str1	field1_str2	field_date	field_datetime
+323030372D30382D30322032333A35393A3030	323030372D30382D30332031373A33323A3030	323030372D30382D3032	323030372D30382D30332031373A33323A3030
+#
 # Bug#52159 returning time type from function and empty left join causes debug assertion
 #
 CREATE FUNCTION f1() RETURNS TIME RETURN 1;

=== modified file 'mysql-test/r/ctype_ucs.result'
--- a/mysql-test/r/ctype_ucs.result	2010-11-19 17:15:47 +0000
+++ b/mysql-test/r/ctype_ucs.result	2011-02-10 08:18:08 +0000
@@ -4009,6 +4009,46 @@ id	select_type	table	type	possible_keys
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	2	Using where
 DROP TABLE t1;
 #
+# Bug #31384 	DATE_ADD() and DATE_SUB() return binary data
+#
+SELECT @@collation_connection, @@character_set_results;
+@@collation_connection	@@character_set_results
+ucs2_general_ci	latin1
+CREATE TABLE t1 AS
+SELECT
+DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
+DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `field_str1` varchar(29) CHARACTER SET ucs2 DEFAULT NULL,
+  `field1_str2` varchar(29) CHARACTER SET ucs2 DEFAULT NULL,
+  `field_date` date DEFAULT NULL,
+  `field_datetime` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SELECT
+DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
+DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
+def					field_str1	254	29	10	Y	0	31	8
+def					field1_str2	254	29	19	Y	0	31	8
+def					field_date	10	29	10	Y	128	31	63
+def					field_datetime	12	29	19	Y	128	31	63
+field_str1	field1_str2	field_date	field_datetime
+2007-08-02	2007-08-03 17:32:00	2007-08-02	2007-08-03 17:32:00
+SELECT
+HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
+HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
+HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
+HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
+field_str1	field1_str2	field_date	field_datetime
+0032003000300037002D00300038002D00300032002000320033003A00350039003A00300030	0032003000300037002D00300038002D00300033002000310037003A00330032003A00300030	323030372D30382D3032	323030372D30382D30332031373A33323A3030
+#
 # Bug#52159 returning time type from function and empty left join causes debug assertion
 #
 CREATE FUNCTION f1() RETURNS TIME RETURN 1;

=== modified file 'mysql-test/r/ctype_utf8.result'
--- a/mysql-test/r/ctype_utf8.result	2010-12-17 11:11:34 +0000
+++ b/mysql-test/r/ctype_utf8.result	2011-02-10 08:18:08 +0000
@@ -4898,6 +4898,46 @@ id	select_type	table	type	possible_keys
 1	SIMPLE	t1	range	date_column	date_column	9	NULL	1	Using where
 DROP TABLE t1;
 #
+# Bug #31384 	DATE_ADD() and DATE_SUB() return binary data
+#
+SELECT @@collation_connection, @@character_set_results;
+@@collation_connection	@@character_set_results
+utf8_general_ci	utf8
+CREATE TABLE t1 AS
+SELECT
+DATE_SUB('2007-08-03', INTERVAL 1 MINUTE) AS field_str1,
+DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `field_str1` varchar(29) CHARACTER SET utf8 DEFAULT NULL,
+  `field1_str2` varchar(29) CHARACTER SET utf8 DEFAULT NULL,
+  `field_date` date DEFAULT NULL,
+  `field_datetime` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SELECT
+DATE_SUB('2007-08-03', INTERVAL 1 DAY) AS field_str1,
+DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE) AS field1_str2,
+DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY) AS field_date,
+DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE) AS field_datetime;
+Catalog	Database	Table	Table_alias	Column	Column_alias	Type	Length	Max length	Is_null	Flags	Decimals	Charsetnr
+def					field_str1	254	87	10	Y	0	31	33
+def					field1_str2	254	87	19	Y	0	31	33
+def					field_date	10	29	10	Y	128	31	63
+def					field_datetime	12	29	19	Y	128	31	63
+field_str1	field1_str2	field_date	field_datetime
+2007-08-02	2007-08-03 17:32:00	2007-08-02	2007-08-03 17:32:00
+SELECT
+HEX(DATE_SUB('2007-08-03', INTERVAL 1 MINUTE)) AS field_str1,
+HEX(DATE_SUB('2007-08-03 17:33:00', INTERVAL 1 MINUTE)) AS field1_str2,
+HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date,
+HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime;
+field_str1	field1_str2	field_date	field_datetime
+323030372D30382D30322032333A35393A3030	323030372D30382D30332031373A33323A3030	323030372D30382D3032	323030372D30382D30332031373A33323A3030
+#
 # Bug#52159 returning time type from function and empty left join causes debug assertion
 #
 CREATE FUNCTION f1() RETURNS TIME RETURN 1;

=== modified file 'mysql-test/r/ddl_i18n_koi8r.result'
--- a/mysql-test/r/ddl_i18n_koi8r.result	2010-01-15 11:42:15 +0000
+++ b/mysql-test/r/ddl_i18n_koi8r.result	2011-02-22 14:02:49 +0000
@@ -724,7 +724,7 @@ utf8_general_ci	utf8_general_ci
 CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER SET cp866 */;
 
 USE `mysqltest1`;
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -757,8 +757,8 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -791,7 +791,7 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;
 
 ---> Dumping mysqltest1 to ddl_i18n_koi8r.sp.mysqltest1.sql
 
@@ -800,7 +800,7 @@ ALTER DATABASE mysqltest1 CHARACTER SET
 CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest2` /*!40100 DEFAULT CHARACTER SET cp866 */;
 
 USE `mysqltest2`;
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -833,8 +833,8 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -867,7 +867,7 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;
 
 ---> Dumping mysqltest2 to ddl_i18n_koi8r.sp.mysqltest2.sql
 
@@ -1742,7 +1742,7 @@ CREATE TABLE `t1` (
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 /*!40101 SET character_set_client = @saved_cs_client */;
 INSERT INTO `t1` VALUES (1),(0),(1);
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -1770,8 +1770,8 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -1799,7 +1799,7 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;
 
 ---> Dumping mysqltest1 to ddl_i18n_koi8r.triggers.mysqltest1.sql
 
@@ -1821,7 +1821,7 @@ CREATE TABLE `t1` (
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 /*!40101 SET character_set_client = @saved_cs_client */;
 INSERT INTO `t1` VALUES (1),(0),(1);
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -1849,8 +1849,8 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -1878,7 +1878,7 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;
 
 ---> Dumping mysqltest2 to ddl_i18n_koi8r.triggers.mysqltest2.sql
 
@@ -2486,7 +2486,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/
 USE `mysqltest1`;
 /*!50106 SET @save_time_zone= @@TIME_ZONE */ ;
 DELIMITER ;;
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;;
@@ -2512,9 +2512,9 @@ END */ ;;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;;
 /*!50003 SET character_set_results = @saved_cs_results */ ;;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;;
 DELIMITER ;;
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;;
@@ -2540,7 +2540,7 @@ END */ ;;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;;
 /*!50003 SET character_set_results = @saved_cs_results */ ;;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;;
 DELIMITER ;
 /*!50106 SET TIME_ZONE= @save_time_zone */ ;
 
@@ -2553,7 +2553,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/
 USE `mysqltest2`;
 /*!50106 SET @save_time_zone= @@TIME_ZONE */ ;
 DELIMITER ;;
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;;
@@ -2579,9 +2579,9 @@ END */ ;;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;;
 /*!50003 SET character_set_results = @saved_cs_results */ ;;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;;
 DELIMITER ;;
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;;
@@ -2607,7 +2607,7 @@ END */ ;;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;;
 /*!50003 SET character_set_results = @saved_cs_results */ ;;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;;
 DELIMITER ;
 /*!50106 SET TIME_ZONE= @save_time_zone */ ;
 

=== modified file 'mysql-test/r/ddl_i18n_utf8.result'
--- a/mysql-test/r/ddl_i18n_utf8.result	2010-01-15 11:42:15 +0000
+++ b/mysql-test/r/ddl_i18n_utf8.result	2011-02-22 14:02:49 +0000
@@ -724,7 +724,7 @@ utf8_general_ci	utf8_general_ci
 CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER SET cp866 */;
 
 USE `mysqltest1`;
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -757,8 +757,8 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -791,7 +791,7 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;
 
 ---> Dumping mysqltest1 to ddl_i18n_utf8sp.mysqltest1.sql
 
@@ -800,7 +800,7 @@ ALTER DATABASE mysqltest1 CHARACTER SET
 CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest2` /*!40100 DEFAULT CHARACTER SET cp866 */;
 
 USE `mysqltest2`;
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -833,8 +833,8 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -867,7 +867,7 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;
 
 ---> Dumping mysqltest2 to ddl_i18n_utf8sp.mysqltest2.sql
 
@@ -1742,7 +1742,7 @@ CREATE TABLE `t1` (
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 /*!40101 SET character_set_client = @saved_cs_client */;
 INSERT INTO `t1` VALUES (1),(0),(1);
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -1770,8 +1770,8 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -1799,7 +1799,7 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;
 
 ---> Dumping mysqltest1 to ddl_i18n_utf8triggers.mysqltest1.sql
 
@@ -1821,7 +1821,7 @@ CREATE TABLE `t1` (
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 /*!40101 SET character_set_client = @saved_cs_client */;
 INSERT INTO `t1` VALUES (1),(0),(1);
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -1849,8 +1849,8 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;
@@ -1878,7 +1878,7 @@ DELIMITER ;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;
 /*!50003 SET character_set_results = @saved_cs_results */ ;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;
 
 ---> Dumping mysqltest2 to ddl_i18n_utf8triggers.mysqltest2.sql
 
@@ -2486,7 +2486,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/
 USE `mysqltest1`;
 /*!50106 SET @save_time_zone= @@TIME_ZONE */ ;
 DELIMITER ;;
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;;
@@ -2512,9 +2512,9 @@ END */ ;;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;;
 /*!50003 SET character_set_results = @saved_cs_results */ ;;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;;
 DELIMITER ;;
-ALTER DATABASE mysqltest1 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
+ALTER DATABASE `mysqltest1` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;;
@@ -2540,7 +2540,7 @@ END */ ;;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;;
 /*!50003 SET character_set_results = @saved_cs_results */ ;;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;;
-ALTER DATABASE mysqltest1 CHARACTER SET cp866 COLLATE cp866_general_ci ;;
+ALTER DATABASE `mysqltest1` CHARACTER SET cp866 COLLATE cp866_general_ci ;;
 DELIMITER ;
 /*!50106 SET TIME_ZONE= @save_time_zone */ ;
 
@@ -2553,7 +2553,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/
 USE `mysqltest2`;
 /*!50106 SET @save_time_zone= @@TIME_ZONE */ ;
 DELIMITER ;;
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;;
@@ -2579,9 +2579,9 @@ END */ ;;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;;
 /*!50003 SET character_set_results = @saved_cs_results */ ;;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;;
 DELIMITER ;;
-ALTER DATABASE mysqltest2 CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
+ALTER DATABASE `mysqltest2` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;;
 /*!50003 SET @saved_cs_client      = @@character_set_client */ ;;
 /*!50003 SET @saved_cs_results     = @@character_set_results */ ;;
 /*!50003 SET @saved_col_connection = @@collation_connection */ ;;
@@ -2607,7 +2607,7 @@ END */ ;;
 /*!50003 SET character_set_client  = @saved_cs_client */ ;;
 /*!50003 SET character_set_results = @saved_cs_results */ ;;
 /*!50003 SET collation_connection  = @saved_col_connection */ ;;
-ALTER DATABASE mysqltest2 CHARACTER SET cp866 COLLATE cp866_general_ci ;;
+ALTER DATABASE `mysqltest2` CHARACTER SET cp866 COLLATE cp866_general_ci ;;
 DELIMITER ;
 /*!50106 SET TIME_ZONE= @save_time_zone */ ;
 

=== added file 'mysql-test/r/file_contents.result'
--- a/mysql-test/r/file_contents.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/file_contents.result	2011-02-11 14:55:25 +0000
@@ -0,0 +1,6 @@
+
+Checking 'INFO_SRC' and 'INFO_BIN'
+INFO_SRC: Found MySQL version number / Found BZR revision id
+INFO_BIN: Found 'Compiler ... used' line / Found 'Feature flags' line
+
+End of tests

=== modified file 'mysql-test/r/filesort_debug.result'
--- a/mysql-test/r/filesort_debug.result	2011-02-02 11:54:49 +0000
+++ b/mysql-test/r/filesort_debug.result	2011-02-24 07:00:12 +0000
@@ -14,3 +14,20 @@ DELETE FROM t1 ORDER BY (f1(10)) LIMIT 1
 ERROR 42000: Incorrect number of arguments for FUNCTION test.f1; expected 0, got 1
 DROP TABLE t1;
 DROP FUNCTION f1;
+#
+# Bug #11747102
+# 30771: LOG MORE INFO ABOUT THREADS KILL'D AND SORT ABORTED MESSAGES
+#
+# connection 1
+CREATE TABLE t1(f0 int auto_increment primary key, f1 int);
+INSERT INTO t1(f1) VALUES (0),(1),(2),(3),(4),(5);
+SET DEBUG_SYNC='filesort_start SIGNAL filesort_started WAIT_FOR filesort_killed';
+# Sending: (not reaped since connection is killed later)
+SELECT * FROM t1 ORDER BY f1 ASC, f0;
+# connection 2
+SET DEBUG_SYNC='now WAIT_FOR filesort_started';
+KILL @id;
+SET DEBUG_SYNC='now SIGNAL filesort_killed';
+# connection default
+SET DEBUG_SYNC= "RESET";
+DROP TABLE t1;

=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result	2011-02-02 18:16:06 +0000
+++ b/mysql-test/r/func_time.result	2011-02-18 08:10:30 +0000
@@ -136,7 +136,7 @@ dayname("1962-03-03")	dayname("1962-03-0
 Saturday	5
 select monthname("1972-03-04"),monthname("1972-03-04")+0;
 monthname("1972-03-04")	monthname("1972-03-04")+0
-March	3
+March	0
 select time_format(19980131000000,'%H|%I|%k|%l|%i|%p|%r|%S|%T');
 time_format(19980131000000,'%H|%I|%k|%l|%i|%p|%r|%S|%T')
 00|12|0|12|00|AM|12:00:00 AM|00|00:00:00
@@ -1368,3 +1368,11 @@ SELECT SUBDATE(STR_TO_DATE(NULL,0), INTE
 SUBDATE(STR_TO_DATE(NULL,0), INTERVAL 1 HOUR)
 NULL
 #
+# BUG#59895 - setting storage engine to null segfaults mysqld
+#
+SELECT MONTHNAME(0), MONTHNAME(0) IS NULL, MONTHNAME(0) + 1;
+MONTHNAME(0)	MONTHNAME(0) IS NULL	MONTHNAME(0) + 1
+NULL	1	NULL
+SET storage_engine=NULL;
+ERROR 42000: Variable 'storage_engine' can't be set to the value of 'NULL'
+#

=== modified file 'mysql-test/r/gis.result'
--- a/mysql-test/r/gis.result	2011-02-02 13:53:56 +0000
+++ b/mysql-test/r/gis.result	2011-02-24 14:49:38 +0000
@@ -1034,6 +1034,14 @@ p
 NULL
 NULL
 drop table t1;
+#
+# Test for bug #59888 "debug assertion when attempt to create spatial index
+#                      on char > 31 bytes".
+#
+create table t1(a char(32) not null) engine=myisam;
+create spatial index i on t1 (a);
+ERROR 42000: A SPATIAL index may only contain a geometrical type column
+drop table t1;
 End of 5.1 tests
 CREATE TABLE t1(
 col0 BINARY NOT NULL,

=== modified file 'mysql-test/r/group_by.result'
--- a/mysql-test/r/group_by.result	2010-12-17 11:11:34 +0000
+++ b/mysql-test/r/group_by.result	2011-02-18 10:55:24 +0000
@@ -1856,6 +1856,42 @@ ON 1 WHERE t2.f1 > 1 GROUP BY t2.f1;
 COUNT(*)
 2
 DROP TABLE t1;
+#
+# Bug#59839: Aggregation followed by subquery yields wrong result
+#
+CREATE TABLE t1 (
+a INT,
+b INT,
+c INT,
+KEY (a, b)
+);
+INSERT INTO t1 VALUES
+( 1, 1,  1 ),
+( 1, 2,  2 ),
+( 1, 3,  3 ),
+( 1, 4,  6 ),
+( 1, 5,  5 ),
+( 1, 9, 13 ),
+( 2, 1,  6 ),
+( 2, 2,  7 ),
+( 2, 3,  8 );
+EXPLAIN
+SELECT a, AVG(t1.b),
+(SELECT t11.c FROM t1 t11 WHERE t11.a = t1.a AND t11.b = AVG(t1.b)) AS t11c,
+(SELECT t12.c FROM t1 t12 WHERE t12.a = t1.a AND t12.b = AVG(t1.b)) AS t12c
+FROM t1 GROUP BY a;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	t1	index	NULL	a	10	NULL	9	Using index
+3	DEPENDENT SUBQUERY	t12	ref	a	a	10	func,func	2	Using where
+2	DEPENDENT SUBQUERY	t11	ref	a	a	10	func,func	2	Using where
+SELECT a, AVG(t1.b),
+(SELECT t11.c FROM t1 t11 WHERE t11.a = t1.a AND t11.b = AVG(t1.b)) AS t11c,
+(SELECT t12.c FROM t1 t12 WHERE t12.a = t1.a AND t12.b = AVG(t1.b)) AS t12c
+FROM t1 GROUP BY a;
+a	AVG(t1.b)	t11c	t12c
+1	4.0000	6	6
+2	2.0000	7	7
+DROP TABLE t1;
 # End of 5.1 tests
 #
 # Bug#49771: Incorrect MIN (date) when minimum value is 0000-00-00

=== modified file 'mysql-test/r/insert_select.result'
--- a/mysql-test/r/insert_select.result	2010-08-25 19:00:38 +0000
+++ b/mysql-test/r/insert_select.result	2011-02-16 20:45:52 +0000
@@ -842,7 +842,7 @@ SET max_heap_table_size = 16384;
 SET @old_myisam_data_pointer_size = @@myisam_data_pointer_size;
 SET GLOBAL myisam_data_pointer_size = 2;
 INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
-call mtr.add_suppression("mysqld: The table '.*#sql.*' is full");
+call mtr.add_suppression("mysqld.*: The table '.*#sql.*' is full");
 INSERT IGNORE INTO t1 SELECT t1.a FROM t1,t1 t2,t1 t3,t1 t4,t1 t5,t1 t6,t1 t7;
 Got one of the listed errors
 SET GLOBAL myisam_data_pointer_size = @old_myisam_data_pointer_size;

=== modified file 'mysql-test/r/multi_update.result'
--- a/mysql-test/r/multi_update.result	2010-12-14 10:46:00 +0000
+++ b/mysql-test/r/multi_update.result	2011-02-24 14:49:38 +0000
@@ -680,4 +680,21 @@ Warnings:
 Warning	1292	Truncated incorrect datetime value: '1'
 DROP FUNCTION f1;
 DROP TABLE t1;
+#
+# BUG#57373: Multi update+InnoDB reports ER_KEY_NOT_FOUND if a
+#            table is updated twice
+#
+CREATE TABLE t1(
+pk INT,
+a INT,
+PRIMARY KEY (pk)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (0,0);
+UPDATE t1 AS A, t1 AS B SET A.pk = 1, B.a = 2;
+
+# Should be (1,2)
+SELECT * FROM t1;
+pk	a
+1	2
+DROP TABLE t1;
 end of tests

=== added file 'mysql-test/r/multi_update_innodb.result'
--- a/mysql-test/r/multi_update_innodb.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/multi_update_innodb.result	2011-02-21 15:49:03 +0000
@@ -0,0 +1,29 @@
+#
+# BUG#57373: Multi update+InnoDB reports ER_KEY_NOT_FOUND if a
+#            table is updated twice
+#
+CREATE TABLE t1(
+pk INT,
+a INT,
+b INT,
+PRIMARY KEY (pk)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (0,0,0);
+UPDATE t1 AS A, t1 AS B SET A.pk = 1, B.a = 2;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+SELECT * FROM t1;
+pk	a	b
+0	0	0
+CREATE VIEW v1 AS SELECT * FROM t1;
+UPDATE v1 AS A, t1 AS B SET A.pk = 1, B.a = 2;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+SELECT * FROM t1;
+pk	a	b
+0	0	0
+UPDATE t1 AS A, t1 AS B SET A.a = 1, B.b = 2;
+# Should be (0,1,2)
+SELECT * FROM t1;
+pk	a	b
+0	1	2
+DROP VIEW v1;
+DROP TABLE t1;

=== added file 'mysql-test/r/mysqld--defaults-file.result'
--- a/mysql-test/r/mysqld--defaults-file.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/mysqld--defaults-file.result	2011-02-08 10:21:14 +0000
@@ -0,0 +1,12 @@
+Could not open required defaults file: /path/with/no/extension
+Fatal error in defaults handling. Program aborted
+Could not open required defaults file: /path/with.ext
+Fatal error in defaults handling. Program aborted
+Could not open required defaults file: MYSQL_TEST_DIR/relative/path/with.ext
+Fatal error in defaults handling. Program aborted
+Could not open required defaults file: MYSQL_TEST_DIR/relative/path/without/extension
+Fatal error in defaults handling. Program aborted
+Could not open required defaults file: MYSQL_TEST_DIR/with.ext
+Fatal error in defaults handling. Program aborted
+Could not open required defaults file: MYSQL_TEST_DIR/no_extension
+Fatal error in defaults handling. Program aborted

=== modified file 'mysql-test/r/mysqldump.result'
--- a/mysql-test/r/mysqldump.result	2011-01-14 14:41:00 +0000
+++ b/mysql-test/r/mysqldump.result	2011-02-21 07:12:27 +0000
@@ -4591,5 +4591,41 @@ CREATE TABLE `comment_table` (i INT COMM
 </mysqldump>
 DROP TABLE `comment_table`;
 #
+# BUG#11766310 : 59398: MYSQLDUMP 5.1 CAN'T HANDLE A DASH ("-") IN
+#                DATABASE NAMES IN ALTER DATABASE
+#
+CREATE DATABASE `test-database`;
+USE `test-database`;
+CREATE TABLE `test` (`c1` VARCHAR(10)) ENGINE=MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+CREATE TRIGGER `trig` BEFORE INSERT ON `test` FOR EACH ROW BEGIN
+END |
+ALTER DATABASE `test-database` CHARACTER SET latin1 COLLATE latin1_swedish_ci;
+ALTER DATABASE `test-database` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `test` (
+  `c1` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+/*!40101 SET character_set_client = @saved_cs_client */;
+ALTER DATABASE `test-database` CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
+/*!50003 SET @saved_cs_client      = @@character_set_client */ ;
+/*!50003 SET @saved_cs_results     = @@character_set_results */ ;
+/*!50003 SET @saved_col_connection = @@collation_connection */ ;
+/*!50003 SET character_set_client  = latin1 */ ;
+/*!50003 SET character_set_results = latin1 */ ;
+/*!50003 SET collation_connection  = latin1_swedish_ci */ ;
+/*!50003 SET @saved_sql_mode       = @@sql_mode */ ;
+/*!50003 SET sql_mode              = '' */ ;
+DELIMITER ;;
+/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER `trig` BEFORE INSERT ON `test` FOR EACH ROW BEGIN
+END */;;
+DELIMITER ;
+/*!50003 SET sql_mode              = @saved_sql_mode */ ;
+/*!50003 SET character_set_client  = @saved_cs_client */ ;
+/*!50003 SET character_set_results = @saved_cs_results */ ;
+/*!50003 SET collation_connection  = @saved_col_connection */ ;
+ALTER DATABASE `test-database` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+DROP DATABASE `test-database`;
+#
 # End of 5.1 tests
 #

=== modified file 'mysql-test/r/partition.result'
--- a/mysql-test/r/partition.result	2011-01-10 14:08:31 +0000
+++ b/mysql-test/r/partition.result	2011-02-24 14:49:38 +0000
@@ -2264,3 +2264,51 @@ INSERT INTO t1 VALUES(0);
 DROP TABLE t1;
 SET GLOBAL myisam_use_mmap=default;
 End of 5.1 tests
+#
+# BUG#55385: UPDATE statement throws an error, but still updates
+#            the table entries
+CREATE TABLE t1_part (
+partkey int,
+nokey int
+) PARTITION BY LINEAR HASH(partkey) PARTITIONS 3;
+INSERT INTO t1_part VALUES (1, 1) , (10, 10);
+CREATE VIEW v1 AS SELECT * FROM t1_part;
+
+# Should be (1,1),(10,10)
+SELECT * FROM t1_part;
+partkey	nokey
+1	1
+10	10
+
+# Case 1
+# Update is refused because partitioning key is updated
+UPDATE t1_part AS A NATURAL JOIN t1_part B SET A.partkey = 2, B.nokey = 3;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+UPDATE t1_part AS A NATURAL JOIN t1_part B SET A.nokey = 2, B.partkey = 3;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+
+# Case 2
+# Like 1, but partition accessed through a view
+UPDATE t1_part AS A NATURAL JOIN v1 as B SET A.nokey = 2 , B.partkey = 3;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+UPDATE v1 AS A NATURAL JOIN t1_part as B SET A.nokey = 2 , B.partkey = 3;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+
+# Should be (1,1),(10,10)
+SELECT * FROM t1_part;
+partkey	nokey
+1	1
+10	10
+
+# Case 3
+# Update is accepted because partitioning key is not updated
+UPDATE t1_part AS A NATURAL JOIN t1_part B SET A.nokey = 2 , B.nokey = 3;
+
+# Should be (1,3),(10,3)
+SELECT * FROM t1_part;
+partkey	nokey
+1	3
+10	3
+
+DROP VIEW v1;
+DROP TABLE t1_part;

=== modified file 'mysql-test/r/signal_code.result'
--- a/mysql-test/r/signal_code.result	2009-12-01 19:07:18 +0000
+++ b/mysql-test/r/signal_code.result	2011-02-16 16:27:35 +0000
@@ -20,16 +20,16 @@ return 0;
 end $$
 show procedure code signal_proc;
 Pos	Instruction
-0	stmt 131 "SIGNAL foo"
-1	stmt 131 "SIGNAL foo SET MESSAGE_TEXT = "This i..."
-2	stmt 132 "RESIGNAL foo"
-3	stmt 132 "RESIGNAL foo SET MESSAGE_TEXT = "This..."
+0	stmt 130 "SIGNAL foo"
+1	stmt 130 "SIGNAL foo SET MESSAGE_TEXT = "This i..."
+2	stmt 131 "RESIGNAL foo"
+3	stmt 131 "RESIGNAL foo SET MESSAGE_TEXT = "This..."
 drop procedure signal_proc;
 show function code signal_func;
 Pos	Instruction
-0	stmt 131 "SIGNAL foo"
-1	stmt 131 "SIGNAL foo SET MESSAGE_TEXT = "This i..."
-2	stmt 132 "RESIGNAL foo"
-3	stmt 132 "RESIGNAL foo SET MESSAGE_TEXT = "This..."
+0	stmt 130 "SIGNAL foo"
+1	stmt 130 "SIGNAL foo SET MESSAGE_TEXT = "This i..."
+2	stmt 131 "RESIGNAL foo"
+3	stmt 131 "RESIGNAL foo SET MESSAGE_TEXT = "This..."
 4	freturn 3 0
 drop function signal_func;

=== modified file 'mysql-test/r/sp-code.result'
--- a/mysql-test/r/sp-code.result	2010-07-30 15:28:36 +0000
+++ b/mysql-test/r/sp-code.result	2011-02-16 16:27:35 +0000
@@ -155,11 +155,11 @@ Pos	Instruction
 0	stmt 9 "drop temporary table if exists sudoku..."
 1	stmt 1 "create temporary table sudoku_work ( ..."
 2	stmt 1 "create temporary table sudoku_schedul..."
-3	stmt 89 "call sudoku_init()"
+3	stmt 88 "call sudoku_init()"
 4	jump_if_not 7(8) p_naive@0
 5	stmt 4 "update sudoku_work set cnt = 0 where ..."
 6	jump 8
-7	stmt 89 "call sudoku_count()"
+7	stmt 88 "call sudoku_count()"
 8	stmt 6 "insert into sudoku_schedule (row,col)..."
 9	set v_scounter@2 0
 10	set v_i@3 1

=== modified file 'mysql-test/r/variables.result'
--- a/mysql-test/r/variables.result	2010-11-25 03:50:16 +0000
+++ b/mysql-test/r/variables.result	2011-02-10 07:34:22 +0000
@@ -1732,3 +1732,25 @@ set @@session.autocommit=t1_min(), @@ses
 drop table t1;
 drop function t1_min;
 drop function t1_max;
+#
+# Bug #59884: setting charset to 2048 crashes
+#
+set session character_set_results = 2048;
+ERROR 42000: Unknown character set: '2048'
+set session character_set_client=2048;
+ERROR 42000: Unknown character set: '2048'
+set session character_set_connection=2048;
+ERROR 42000: Unknown character set: '2048'
+set session character_set_server=2048;
+ERROR 42000: Unknown character set: '2048'
+set session collation_server=2048;
+ERROR HY000: Unknown collation: '2048'
+set session character_set_filesystem=2048;
+ERROR 42000: Unknown character set: '2048'
+set session character_set_database=2048;
+ERROR 42000: Unknown character set: '2048'
+set session collation_connection=2048;
+ERROR HY000: Unknown collation: '2048'
+set session collation_database=2048;
+ERROR HY000: Unknown collation: '2048'
+End of 5.5 tests

=== modified file 'mysql-test/r/xa.result'
--- a/mysql-test/r/xa.result	2010-09-13 11:31:22 +0000
+++ b/mysql-test/r/xa.result	2011-02-14 13:16:31 +0000
@@ -142,3 +142,27 @@ XA PREPARE 'x';
 XA PREPARE 'x';
 ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the  PREPARED state
 XA ROLLBACK 'x';
+#
+# Bug#59986 Assert in Diagnostics_area::set_ok_status() for XA COMMIT
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a)) engine=InnoDB;
+INSERT INTO t1 VALUES (1, 1), (2, 2);
+# Connection con1
+XA START 'a';
+UPDATE t1 SET b= 3 WHERE a=1;
+# Connection default
+XA START 'b';
+UPDATE t1 SET b=4 WHERE a=2;
+# Sending:
+UPDATE t1 SET b=5 WHERE a=1;
+# Connection con1
+UPDATE t1 SET b=6 WHERE a=2;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+XA COMMIT 'a';
+ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
+# Connection default
+# Reaping: UPDATE t1 SET b=5 WHERE a=1
+XA END 'b';
+XA ROLLBACK 'b';
+DROP TABLE t1;

=== added file 'mysql-test/suite/innodb/r/innodb_bug53756.result'
--- a/mysql-test/suite/innodb/r/innodb_bug53756.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/r/innodb_bug53756.result	2011-02-10 08:58:23 +0000
@@ -0,0 +1,118 @@
+DROP TABLE IF EXISTS bug_53756 ;
+CREATE TABLE bug_53756 (pk INT, c1 INT) ENGINE=InnoDB;
+ALTER TABLE bug_53756 ADD PRIMARY KEY (pk);
+INSERT INTO bug_53756 VALUES(1, 11), (2, 22), (3, 33), (4, 44);
+
+# Select a less restrictive isolation level.
+SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+COMMIT;
+
+# Start a transaction in the default connection for isolation.
+START TRANSACTION;
+SELECT @@tx_isolation;
+@@tx_isolation
+READ-COMMITTED
+SELECT * FROM bug_53756;
+pk	c1
+1	11
+2	22
+3	33
+4	44
+
+# connection con1 deletes row 1
+START TRANSACTION;
+SELECT @@tx_isolation;
+@@tx_isolation
+READ-COMMITTED
+DELETE FROM bug_53756 WHERE pk=1;
+
+# connection con2 deletes row 2
+START TRANSACTION;
+SELECT @@tx_isolation;
+@@tx_isolation
+READ-COMMITTED
+DELETE FROM bug_53756 WHERE pk=2;
+
+# connection con3 updates row 3
+START TRANSACTION;
+SELECT @@tx_isolation;
+@@tx_isolation
+READ-COMMITTED
+UPDATE bug_53756 SET c1=77 WHERE pk=3;
+
+# connection con4 updates row 4
+START TRANSACTION;
+SELECT @@tx_isolation;
+@@tx_isolation
+READ-COMMITTED
+UPDATE bug_53756 SET c1=88 WHERE pk=4;
+
+# connection con5 inserts row 5
+START TRANSACTION;
+SELECT @@tx_isolation;
+@@tx_isolation
+READ-COMMITTED
+INSERT INTO bug_53756 VALUES(5, 55);
+
+# connection con6 inserts row 6
+START TRANSACTION;
+SELECT @@tx_isolation;
+@@tx_isolation
+READ-COMMITTED
+INSERT INTO bug_53756 VALUES(6, 66);
+
+# connection con1 commits.
+COMMIT;
+
+# connection con3 commits.
+COMMIT;
+
+# connection con4 rolls back.
+ROLLBACK;
+
+# connection con6 rolls back.
+ROLLBACK;
+
+# The connections 2 and 5 stay open.
+
+# connection default selects resulting data.
+# Delete of row 1 was committed.
+# Update of row 3 was committed.
+# Due to isolation level read committed, these should be included.
+# All other changes should not be included.
+SELECT * FROM bug_53756;
+pk	c1
+2	22
+3	77
+4	44
+
+# connection default
+#
+# Crash server.
+START TRANSACTION;
+INSERT INTO bug_53756 VALUES (666,666);
+SET SESSION debug="+d,crash_commit_before";
+COMMIT;
+ERROR HY000: Lost connection to MySQL server during query
+
+#
+# disconnect con1, con2, con3, con4, con5, con6.
+#
+# Restart server.
+
+#
+# Select recovered data.
+# Delete of row 1 was committed.
+# Update of row 3 was committed.
+# These should be included.
+# All other changes should not be included.
+# Delete of row 2 and insert of row 5 should be rolled back
+SELECT * FROM bug_53756;
+pk	c1
+2	22
+3	77
+4	44
+
+# Clean up.
+DROP TABLE bug_53756;

=== added file 'mysql-test/suite/innodb/r/innodb_bug59307.result'
--- a/mysql-test/suite/innodb/r/innodb_bug59307.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/r/innodb_bug59307.result	2011-02-15 09:29:56 +0000
@@ -0,0 +1,28 @@
+CREATE TABLE t1 (
+t1_int INT,
+t1_time TIME
+) ENGINE=innodb;
+CREATE TABLE t2 (
+t2_int int PRIMARY KEY,
+t2_int2 INT
+) ENGINE=INNODB;
+INSERT INTO t2 VALUES ();
+Warnings:
+Warning	1364	Field 't2_int' doesn't have a default value
+INSERT INTO t1 VALUES ();
+SELECT *
+FROM t1 AS t1a
+WHERE NOT EXISTS
+(SELECT *
+FROM t1 AS t1b
+WHERE t1b.t1_int NOT IN
+(SELECT t2.t2_int
+FROM t2
+WHERE t1b.t1_time LIKE t1b.t1_int
+OR t1b.t1_time <> t2.t2_int2
+AND 6=7
+)
+)
+;
+t1_int	t1_time
+DROP TABLE t1,t2;

=== added file 'mysql-test/suite/innodb/r/innodb_bug60049.result'
--- a/mysql-test/suite/innodb/r/innodb_bug60049.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/r/innodb_bug60049.result	2011-02-15 10:12:27 +0000
@@ -0,0 +1,8 @@
+CREATE TABLE t(a INT)ENGINE=InnoDB;
+RENAME TABLE t TO u;
+DROP TABLE u;
+SELECT @@innodb_fast_shutdown;
+@@innodb_fast_shutdown
+0
+Last record of ID_IND root page (9):
+1808000018050074000000000000000c5359535f464f524549474e5f434f4c53

=== added file 'mysql-test/suite/innodb/t/innodb_bug53756-master.opt'
--- a/mysql-test/suite/innodb/t/innodb_bug53756-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_bug53756-master.opt	2011-02-10 08:58:23 +0000
@@ -0,0 +1 @@
+--skip-stack-trace --skip-core-file

=== added file 'mysql-test/suite/innodb/t/innodb_bug53756.test'
--- a/mysql-test/suite/innodb/t/innodb_bug53756.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_bug53756.test	2011-02-10 08:58:23 +0000
@@ -0,0 +1,184 @@
+# This is the test case for bug #53756. Alter table operation could
+# leave a deleted record for the temp table (later renamed to the altered
+# table) in the SYS_TABLES secondary index, we should ignore this row and
+# find the first non-deleted row for the specified table_id when load table
+# metadata in the function dict_load_table_on_id() during crash recovery.
+
+#
+# innobackup needs to connect to the server. Not supported in embedded.
+--source include/not_embedded.inc
+#
+# This test case needs to crash the server. Needs a debug server.
+--source include/have_debug.inc
+#
+# Don't test this under valgrind, memory leaks will occur.
+--source include/not_valgrind.inc
+#
+# This test case needs InnoDB.
+-- source include/have_innodb.inc
+
+#
+# Precautionary clean up.
+#
+--disable_warnings
+DROP TABLE IF EXISTS bug_53756 ;
+--enable_warnings
+
+#
+# Create test data.
+#
+CREATE TABLE bug_53756 (pk INT, c1 INT) ENGINE=InnoDB;
+ALTER TABLE bug_53756 ADD PRIMARY KEY (pk);
+INSERT INTO bug_53756 VALUES(1, 11), (2, 22), (3, 33), (4, 44);
+
+--echo
+--echo # Select a less restrictive isolation level.
+# Don't use user variables. They won't survive server crash.
+--let $global_isolation= `SELECT @@global.tx_isolation`
+--let $session_isolation= `SELECT @@session.tx_isolation`
+SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
+SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
+COMMIT;
+
+--echo
+--echo # Start a transaction in the default connection for isolation.
+START TRANSACTION;
+SELECT @@tx_isolation;
+SELECT * FROM bug_53756;
+
+--echo
+--echo # connection con1 deletes row 1
+--connect (con1,localhost,root,,)
+START TRANSACTION;
+SELECT @@tx_isolation;
+DELETE FROM bug_53756 WHERE pk=1;
+
+--echo
+--echo # connection con2 deletes row 2
+--connect (con2,localhost,root,,)
+START TRANSACTION;
+SELECT @@tx_isolation;
+DELETE FROM bug_53756 WHERE pk=2;
+
+--echo
+--echo # connection con3 updates row 3
+--connect (con3,localhost,root,,)
+START TRANSACTION;
+SELECT @@tx_isolation;
+UPDATE bug_53756 SET c1=77 WHERE pk=3;
+
+--echo
+--echo # connection con4 updates row 4
+--connect (con4,localhost,root,,)
+START TRANSACTION;
+SELECT @@tx_isolation;
+UPDATE bug_53756 SET c1=88 WHERE pk=4;
+
+--echo
+--echo # connection con5 inserts row 5
+--connect (con5,localhost,root,,)
+START TRANSACTION;
+SELECT @@tx_isolation;
+INSERT INTO bug_53756 VALUES(5, 55);
+
+--echo
+--echo # connection con6 inserts row 6
+--connect (con6,localhost,root,,)
+START TRANSACTION;
+SELECT @@tx_isolation;
+INSERT INTO bug_53756 VALUES(6, 66);
+
+--echo
+--echo # connection con1 commits.
+--connection con1
+COMMIT;
+
+--echo
+--echo # connection con3 commits.
+--connection con3
+COMMIT;
+
+--echo
+--echo # connection con4 rolls back.
+--connection con4
+ROLLBACK;
+
+--echo
+--echo # connection con6 rolls back.
+--connection con6
+ROLLBACK;
+
+--echo
+--echo # The connections 2 and 5 stay open.
+
+--echo
+--echo # connection default selects resulting data.
+--echo # Delete of row 1 was committed.
+--echo # Update of row 3 was committed.
+--echo # Due to isolation level read committed, these should be included.
+--echo # All other changes should not be included.
+--connection default
+SELECT * FROM bug_53756;
+
+--echo
+--echo # connection default
+--connection default
+--echo #
+--echo # Crash server.
+#
+# Write file to make mysql-test-run.pl expect the "crash", but don't start
+# it until it's told to
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+#
+START TRANSACTION;
+INSERT INTO bug_53756 VALUES (666,666);
+#
+# Request a crash on next execution of commit.
+SET SESSION debug="+d,crash_commit_before";
+#
+# Execute the statement that causes the crash.
+--error 2013
+COMMIT;
+--echo
+--echo #
+--echo # disconnect con1, con2, con3, con4, con5, con6.
+--disconnect con1
+--disconnect con2
+--disconnect con3
+--disconnect con4
+--disconnect con5
+--disconnect con6
+--echo #
+--echo # Restart server.
+#
+# Write file to make mysql-test-run.pl start up the server again
+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+#
+# Turn on reconnect
+--enable_reconnect
+#
+# Call script that will poll the server waiting for it to be back online again
+--source include/wait_until_connected_again.inc
+#
+# Turn off reconnect again
+--disable_reconnect
+--echo
+
+--echo #
+--echo # Select recovered data.
+--echo # Delete of row 1 was committed.
+--echo # Update of row 3 was committed.
+--echo # These should be included.
+--echo # All other changes should not be included.
+--echo # Delete of row 2 and insert of row 5 should be rolled back
+SELECT * FROM bug_53756;
+
+--echo
+--echo # Clean up.
+DROP TABLE bug_53756;
+
+--disable_query_log
+eval SET GLOBAL tx_isolation= '$global_isolation';
+eval SET SESSION tx_isolation= '$session_isolation';
+--enable_query_log
+

=== added file 'mysql-test/suite/innodb/t/innodb_bug59307.test'
--- a/mysql-test/suite/innodb/t/innodb_bug59307.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_bug59307.test	2011-02-15 09:29:56 +0000
@@ -0,0 +1,32 @@
+-- source include/have_innodb.inc
+# Bug #59307 uninitialized value in rw_lock_set_writer_id_and_recursion_flag()
+# when Valgrind instrumentation (UNIV_DEBUG_VALGRIND) is not enabled
+
+CREATE TABLE t1 (
+  t1_int INT,
+  t1_time TIME
+) ENGINE=innodb;
+
+CREATE TABLE t2 (
+  t2_int int PRIMARY KEY,
+  t2_int2 INT
+) ENGINE=INNODB;
+
+INSERT INTO t2 VALUES ();
+INSERT INTO t1 VALUES ();
+
+SELECT *
+FROM t1 AS t1a
+WHERE NOT EXISTS
+  (SELECT *
+   FROM t1 AS t1b
+   WHERE t1b.t1_int NOT IN
+     (SELECT t2.t2_int
+      FROM t2
+      WHERE t1b.t1_time LIKE t1b.t1_int
+      OR t1b.t1_time <> t2.t2_int2
+      AND 6=7
+ )
+)
+;
+DROP TABLE t1,t2;

=== added file 'mysql-test/suite/innodb/t/innodb_bug60049-master.opt'
--- a/mysql-test/suite/innodb/t/innodb_bug60049-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_bug60049-master.opt	2011-02-15 10:12:27 +0000
@@ -0,0 +1 @@
+--innodb_fast_shutdown=0

=== added file 'mysql-test/suite/innodb/t/innodb_bug60049.test'
--- a/mysql-test/suite/innodb/t/innodb_bug60049.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_bug60049.test	2011-02-17 20:25:33 +0000
@@ -0,0 +1,39 @@
+# Bug #60049 Verify that purge leaves no garbage in unique secondary indexes
+# This test requires a fresh server start-up and a slow shutdown.
+# This was a suspected bug (not a bug).
+
+-- source include/not_embedded.inc
+-- source include/have_innodb.inc
+
+CREATE TABLE t(a INT)ENGINE=InnoDB;
+RENAME TABLE t TO u;
+DROP TABLE u;
+SELECT @@innodb_fast_shutdown;
+let $MYSQLD_DATADIR=`select @@datadir`;
+
+# Shut down the server
+-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+-- shutdown_server 30
+-- source include/wait_until_disconnected.inc
+
+# Check the tail of ID_IND (SYS_TABLES.ID)
+let IBDATA1=$MYSQLD_DATADIR/ibdata1;
+perl;
+my $file = $ENV{'IBDATA1'};
+open(FILE, "<$file") || die "Unable to open $file";
+# Read DICT_HDR_TABLE_IDS, the root page number of ID_IND (SYS_TABLES.ID).
+seek(FILE, 7*16384+38+36, 0) || die "Unable to seek $file";
+die unless read(FILE, $_, 4) == 4;
+my $sys_tables_id_root = unpack("N", $_);
+print "Last record of ID_IND root page ($sys_tables_id_root):\n";
+# This should be the last record in ID_IND. Dump it in hexadecimal.
+seek(FILE, $sys_tables_id_root*16384 + 152, 0) || die "Unable to seek $file";
+read(FILE, $_, 32) || die "Unable to read $file";
+close(FILE);
+print unpack("H*", $_), "\n";
+EOF
+
+# Restart the server.
+-- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+-- enable_reconnect
+-- source include/wait_until_connected_again.inc

=== modified file 'mysql-test/suite/innodb/t/innodb_information_schema.test'
--- a/mysql-test/suite/innodb/t/innodb_information_schema.test	2010-06-22 15:58:28 +0000
+++ b/mysql-test/suite/innodb/t/innodb_information_schema.test	2011-02-17 17:14:41 +0000
@@ -118,11 +118,29 @@ SELECT * FROM ```t'\"_str` WHERE c1 = '4
 # executes before some of them, resulting in less than expected number
 # of rows being selected from innodb_locks. If there is a bug and there
 # are no 14 rows in innodb_locks then this test will fail with timeout.
-let $count = 14;
-let $table = INFORMATION_SCHEMA.INNODB_LOCKS;
--- source include/wait_until_rows_count.inc
-# the above enables the query log, re-disable it
--- disable_query_log
+# Notice that if we query INNODB_LOCKS more often than once per 0.1 sec
+# then its contents will never change because the cache from which it is
+# filled is updated only if it has not been read for 0.1 seconds. See
+# CACHE_MIN_IDLE_TIME_US in trx/trx0i_s.c.
+let $cnt=10;
+while ($cnt)
+{
+    let $success=`SELECT COUNT(*) = 14 FROM INFORMATION_SCHEMA.INNODB_LOCKS`;
+    if ($success)
+    {
+        let $cnt=0;
+    }
+    if (!$success)
+    {
+        real_sleep 0.2;
+        dec $cnt;
+    }
+}
+if (!$success)
+{
+    -- echo Timeout waiting for rows in INNODB_LOCKS to appear
+}
+
 SELECT lock_mode, lock_type, lock_table, lock_index, lock_rec, lock_data
 FROM INFORMATION_SCHEMA.INNODB_LOCKS ORDER BY lock_data;
 

=== modified file 'mysql-test/suite/rpl/r/rpl_failed_optimize.result'
--- a/mysql-test/suite/rpl/r/rpl_failed_optimize.result	2010-12-19 17:07:28 +0000
+++ b/mysql-test/suite/rpl/r/rpl_failed_optimize.result	2011-02-15 11:59:12 +0000
@@ -3,13 +3,6 @@ include/master-slave.inc
 CREATE TABLE t1 ( a int ) ENGINE=InnoDB;
 BEGIN;
 INSERT INTO t1 VALUES (1);
-OPTIMIZE TABLE t1;
-Table	Op	Msg_type	Msg_text
-test.t1	optimize	note	Table does not support optimize, doing recreate + analyze instead
-test.t1	optimize	error	Lock wait timeout exceeded; try restarting transaction
-test.t1	optimize	status	Operation failed
-Warnings:
-Error	1205	Lock wait timeout exceeded; try restarting transaction
 OPTIMIZE TABLE non_existing;
 Table	Op	Msg_type	Msg_text
 test.non_existing	optimize	Error	Table 'test.non_existing' doesn't exist

=== modified file 'mysql-test/suite/rpl/r/rpl_read_only.result'
--- a/mysql-test/suite/rpl/r/rpl_read_only.result	2010-12-19 17:15:12 +0000
+++ b/mysql-test/suite/rpl/r/rpl_read_only.result	2011-02-15 12:01:52 +0000
@@ -27,15 +27,26 @@ a
 2001
 set global read_only=0;
 BEGIN;
+BEGIN;
+select @@read_only;
+@@read_only
+0
+set global read_only=1;
+*** On SUPER USER connection ***
 insert into t1 values(1002);
 insert into t2 values(2002);
-BEGIN;
+*** On regular USER connection ***
 insert into t1 values(1003);
+ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement
 insert into t2 values(2003);
-set global read_only=1;
+ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement
+*** SUPER USER COMMIT (must succeed) *** 
 COMMIT;
+*** regular USER COMMIT (must succeed - nothing to commit) *** 
 COMMIT;
-ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement
+select @@read_only;
+@@read_only
+1
 set global read_only=0;
 insert into t1 values(1004);
 insert into t2 values(2004);
@@ -48,7 +59,6 @@ select * from t2;
 a
 2001
 2002
-2003
 2004
 select * from t1;
 a
@@ -59,7 +69,6 @@ select * from t2;
 a
 2001
 2002
-2003
 2004
 set global read_only=1;
 select @@read_only;
@@ -87,7 +96,6 @@ select * from t2;
 a
 2001
 2002
-2003
 2004
 2005
 select * from t1;
@@ -100,7 +108,6 @@ select * from t2;
 a
 2001
 2002
-2003
 2004
 2005
 insert into t1 values(1006);

=== modified file 'mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result'
--- a/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result	2011-02-23 11:54:58 +0000
+++ b/mysql-test/suite/rpl/r/rpl_slave_load_remove_tmpfile.result	2011-02-24 14:48:35 +0000
@@ -13,5 +13,6 @@ include/stop_slave_io.inc
 RESET SLAVE;
 drop table t1;
 call mtr.add_suppression("Slave: Can't get stat of .*");
+call mtr.add_suppression("Slave SQL: Error .Can.t get stat of.* Error_code: 13");
 call mtr.add_suppression("Slave: File.* not found.*");
 include/rpl_end.inc

=== modified file 'mysql-test/suite/rpl/r/rpl_slow_query_log.result'
--- a/mysql-test/suite/rpl/r/rpl_slow_query_log.result	2010-12-19 17:15:12 +0000
+++ b/mysql-test/suite/rpl/r/rpl_slow_query_log.result	2011-02-24 14:48:35 +0000
@@ -1,6 +1,7 @@
 include/master-slave.inc
 [connection master]
 CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression("Slave SQL: slave SQL thread is being stopped in the middle of applying of a group having updated a non-transaction table; waiting for the group completion");
 include/stop_slave.inc
 SET @old_log_output= @@log_output;
 SET GLOBAL log_output= 'TABLE';

=== modified file 'mysql-test/suite/rpl/t/disabled.def'
--- a/mysql-test/suite/rpl/t/disabled.def	2011-01-31 13:11:05 +0000
+++ b/mysql-test/suite/rpl/t/disabled.def	2011-02-15 12:01:52 +0000
@@ -10,8 +10,6 @@
 #
 ##############################################################################
 
-rpl_failed_optimize       : WL#4284: Can't optimize table used by a pending transaction (there is metadata lock on the table).
-rpl_read_only             : WL#4284: Setting Read only won't succeed until all metadata locks are released.
 rpl_row_create_table      : Bug#51574 2010-02-27 andrei failed different way than earlier with bug#45576
 rpl_spec_variables        : BUG#47661 2009-10-27 jasonh rpl_spec_variables fails on PB2 hpux
 rpl_get_master_version_and_clock : Bug#59178 Jan 05 2011 joro Valgrind warnings rpl_get_master_version_and_clock

=== removed file 'mysql-test/suite/rpl/t/rpl_failed_optimize-master.opt'
--- a/mysql-test/suite/rpl/t/rpl_failed_optimize-master.opt	2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/rpl/t/rpl_failed_optimize-master.opt	1970-01-01 00:00:00 +0000
@@ -1 +0,0 @@
---loose-innodb-lock-wait-timeout=1

=== modified file 'mysql-test/suite/rpl/t/rpl_read_only.test'
--- a/mysql-test/suite/rpl/t/rpl_read_only.test	2010-12-19 17:15:12 +0000
+++ b/mysql-test/suite/rpl/t/rpl_read_only.test	2011-02-15 12:01:52 +0000
@@ -41,30 +41,39 @@ set global read_only=0;
 
 connection master1;
 BEGIN;
+
+connection master2;
+BEGIN;
+
+connection master;
+select @@read_only;
+set global read_only=1;
+
+connection master1;
+-- echo *** On SUPER USER connection ***
 insert into t1 values(1002);
 --disable_warnings
 insert into t2 values(2002);
 --enable_warnings
 
 connection master2;
-BEGIN;
+-- echo *** On regular USER connection ***
+--error ER_OPTION_PREVENTS_STATEMENT
 insert into t1 values(1003);
---disable_warnings
+--error ER_OPTION_PREVENTS_STATEMENT
 insert into t2 values(2003);
---enable_warnings
-
-connection master;
-set global read_only=1;
 
 connection master1;
 ## works even with read_only=1, because master1 is root
+-- echo *** SUPER USER COMMIT (must succeed) *** 
 COMMIT;
 
 connection master2;
---error ER_OPTION_PREVENTS_STATEMENT
+-- echo *** regular USER COMMIT (must succeed - nothing to commit) *** 
 COMMIT;
 
 connection master;
+select @@read_only;
 set global read_only=0;
 
 connection master1;

=== modified file 'mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test'
--- a/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test	2011-02-23 11:54:58 +0000
+++ b/mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test	2011-02-24 14:48:35 +0000
@@ -13,6 +13,7 @@
 --source include/have_debug.inc
 --source include/master-slave.inc
 --source include/not_embedded.inc
+--source include/not_var_link.inc
 
 ##########################################################################
 #                            Loading data
@@ -59,6 +60,7 @@ RESET SLAVE;
 drop table t1;
 
 call mtr.add_suppression("Slave: Can't get stat of .*");
+call mtr.add_suppression("Slave SQL: Error .Can.t get stat of.* Error_code: 13");
 call mtr.add_suppression("Slave: File.* not found.*");
 --let $rpl_only_running_threads= 1
 --source include/rpl_end.inc

=== modified file 'mysql-test/suite/rpl/t/rpl_slow_query_log.test'
--- a/mysql-test/suite/rpl/t/rpl_slow_query_log.test	2010-12-19 17:15:12 +0000
+++ b/mysql-test/suite/rpl/t/rpl_slow_query_log.test	2011-02-24 14:48:35 +0000
@@ -29,6 +29,7 @@ source include/master-slave.inc;
 source include/have_binlog_format_statement.inc;
 
 CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+call mtr.add_suppression("Slave SQL: slave SQL thread is being stopped in the middle of applying of a group having updated a non-transaction table; waiting for the group completion");
 
 
 # Prepare slave for different long_query_time we need to stop the slave 

=== modified file 'mysql-test/suite/sys_vars/r/all_vars.result'
--- a/mysql-test/suite/sys_vars/r/all_vars.result	2011-01-15 07:24:47 +0000
+++ b/mysql-test/suite/sys_vars/r/all_vars.result	2011-02-23 14:39:54 +0000
@@ -11,8 +11,10 @@ There should be *no* long test name list
 select variable_name as `There should be *no* variables listed below:` from t2
 left join t1 on variable_name=test_name where test_name is null;
 There should be *no* variables listed below:
+INNODB_ROLLBACK_SEGMENTS
 INNODB_STATS_METHOD
 INNODB_FILE_FORMAT_MAX
+INNODB_ROLLBACK_SEGMENTS
 INNODB_STATS_METHOD
 INNODB_FILE_FORMAT_MAX
 drop table t1;

=== modified file 'mysql-test/t/alter_table.test'
--- a/mysql-test/t/alter_table.test	2010-07-26 09:22:38 +0000
+++ b/mysql-test/t/alter_table.test	2011-02-21 11:30:08 +0000
@@ -1144,3 +1144,18 @@ INSERT INTO t1 VALUES (1, 1), (2, 2);
 ALTER TABLE t1 CHANGE a id INT;
 --disable_info
 DROP TABLE t1;
+
+
+--echo #
+--echo # Bug#11754461 CANNOT ALTER TABLE WHEN KEY PREFIX TOO LONG
+--echo #
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+--enable_warnings
+
+CREATE DATABASE db1 CHARACTER SET utf8;
+CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100)));
+ALTER TABLE db1.t1 ADD baz INT;
+
+DROP DATABASE db1;

=== modified file 'mysql-test/t/ctype_cp1250_ch.test'
--- a/mysql-test/t/ctype_cp1250_ch.test	2008-03-07 11:28:51 +0000
+++ b/mysql-test/t/ctype_cp1250_ch.test	2011-02-17 11:53:09 +0000
@@ -72,3 +72,13 @@ select a from t1 where a like "abcdefgh�
 drop table t1;
 
 # End of 4.1 tests
+
+#
+# Bug #48053 String::c_ptr has a race and/or does an invalid 
+#            memory reference
+#            (triggered by Valgrind tests)
+#  (see also ctype_eucjpms.test, ctype_cp1250.test, ctype_cp1251.test)
+#
+--error 1649
+set global LC_MESSAGES=convert((@@global.log_bin_trust_function_creators) 
+    using cp1250);

=== modified file 'mysql-test/t/ctype_cp1251.test'
--- a/mysql-test/t/ctype_cp1251.test	2010-11-26 14:22:06 +0000
+++ b/mysql-test/t/ctype_cp1251.test	2011-02-18 07:32:40 +0000
@@ -65,6 +65,16 @@ DROP TABLE t1;
 
 --source include/ctype_8bit.inc
 
+#
+# Bug #48053 String::c_ptr has a race and/or does an invalid 
+#            memory reference
+#            (triggered by Valgrind tests)
+#  (see also ctype_eucjpms.test, ctype_cp1250.test, ctype_cp1251.test)
+#
+--error 1649
+set global LC_TIME_NAMES=convert((-8388608) using cp1251);
+
+
 --echo #
 --echo # End of 5.1 tests
 --echo #
@@ -76,5 +86,15 @@ DROP TABLE t1;
 --source include/ctype_numconv.inc
 
 --echo #
+--echo # Bug#60101 COALESCE with cp1251 tables causes [Err] 1267 - Illegal mix of collations
+--echo #
+CREATE TABLE t1 (test1 INT, test2 VARCHAR(255));
+SHOW CREATE TABLE t1;
+SELECT COALESCE(IF(test1=1, 1, NULL), test2) FROM t1;
+SELECT COALESCE(IF(test1=1, NULL, 1), test2) FROM t1;
+DROP TABLE t1;
+
+
+--echo #
 --echo # End of 5.5 tests
 --echo #

=== modified file 'mysql-test/t/ctype_eucjpms.test'
--- a/mysql-test/t/ctype_eucjpms.test	2010-02-15 05:57:24 +0000
+++ b/mysql-test/t/ctype_eucjpms.test	2011-02-17 11:53:09 +0000
@@ -382,6 +382,16 @@ select hex(convert(_eucjpms 0xA5FE41 usi
 select hex(convert(_eucjpms 0x8FABF841 using ucs2));
 
 
+#
+# Bug #48053 String::c_ptr has a race and/or does an invalid 
+#            memory reference
+#            (triggered by Valgrind tests)
+#  (see also ctype_eucjpms.test, ctype_cp1250.test, ctype_cp1251.test)
+#
+--error 1649
+set global LC_TIME_NAMES=convert((convert((0x63) using eucjpms)) using utf8);
+
+
 --echo #
 --echo # Start of 5.5 tests
 --echo #

=== added file 'mysql-test/t/file_contents.test'
--- a/mysql-test/t/file_contents.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/file_contents.test	2011-02-16 12:44:28 +0000
@@ -0,0 +1,56 @@
+#
+# Testing files that were built to be packaged, both for existence and for contents
+#
+
+#
+# Bug #42969: Create MANIFEST files
+#
+# Use a Perl script to verify that files "docs/INFO_BIN" and "docs/INFO_SRC" do exist
+# and have the expected contents.
+
+--perl
+print "\nChecking 'INFO_SRC' and 'INFO_BIN'\n";
+$dir_docs = $ENV{'MYSQL_BINDIR'};
+if($dir_docs =~ m|/usr/|) {
+  # RPM package
+  $dir_docs =~ s|/lib|/share/doc|;
+  if(-d "$dir_docs/packages/MySQL-server") {
+    # SuSE
+    $dir_docs = "$dir_docs/packages/MySQL-server";
+  } else {
+    # RedHat: version number in directory name
+    $dir_docs = glob "$dir_docs/MySQL-server*";
+  }
+} else {
+  # tar.gz package, Windows, or developer work (in BZR)
+  $dir_docs =~ s|/lib||;
+  if(-d "$dir_docs/docs") {
+    $dir_docs = "$dir_docs/docs"; # package
+  } else {
+    $dir_docs = "$dir_docs/Docs"; # development tree
+  }
+}
+$found_version = "No line 'MySQL source #.#.#'";
+$found_revision = "No line 'revision-id: .....'";
+open(I_SRC,"<","$dir_docs/INFO_SRC") or print "Cannot open 'INFO_SRC' in '$dir_docs'\n";
+while(defined ($line = <I_SRC>)) {
+  if ($line =~ m|^MySQL source \d\.\d\.\d+|) {$found_version = "Found MySQL version number";}
+  if ($line =~ m|^revision-id: .*@.*-2\d{13}-\w+$|) {$found_revision = "Found BZR revision id";}
+}
+close I_SRC;
+print "INFO_SRC: $found_version / $found_revision\n";
+$found_compiler = "No line about compiler information";
+$found_features = "No line 'Feature flags'";
+open(I_BIN,"<","$dir_docs/INFO_BIN") or print "Cannot open 'INFO_BIN' in '$dir_docs'\n";
+while(defined ($line = <I_BIN>)) {
+  # "generator" on Windows, "flags" on Unix:
+  if (($line =~ m| Compiler / generator used: |) ||
+      ($line =~ m| Compiler flags used |))   {$found_compiler = "Found 'Compiler ... used' line";}
+  if  ($line =~ m| Feature flags used:|)     {$found_features = "Found 'Feature flags' line";}
+}
+close I_BIN;
+print "INFO_BIN: $found_compiler / $found_features\n";
+EOF
+
+--echo
+--echo End of tests

=== modified file 'mysql-test/t/filesort_debug.test'
--- a/mysql-test/t/filesort_debug.test	2011-02-02 11:54:49 +0000
+++ b/mysql-test/t/filesort_debug.test	2011-02-24 07:00:12 +0000
@@ -1,4 +1,6 @@
 --source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/count_sessions.inc
 
 SET @old_debug= @@session.debug;
 
@@ -21,3 +23,37 @@ DELETE FROM t1 ORDER BY (f1(10)) LIMIT 1
 
 DROP TABLE t1;
 DROP FUNCTION f1;
+
+--echo #
+--echo # Bug #11747102
+--echo # 30771: LOG MORE INFO ABOUT THREADS KILL'D AND SORT ABORTED MESSAGES
+--echo #
+
+connect (con1, localhost, root);
+connect (con2, localhost, root);
+
+--echo # connection 1
+connection con1;
+CREATE TABLE t1(f0 int auto_increment primary key, f1 int);
+INSERT INTO t1(f1) VALUES (0),(1),(2),(3),(4),(5);
+
+let $ID= `SELECT @id := CONNECTION_ID()`;
+
+SET DEBUG_SYNC='filesort_start SIGNAL filesort_started WAIT_FOR filesort_killed';
+--echo # Sending: (not reaped since connection is killed later)
+--send SELECT * FROM t1 ORDER BY f1 ASC, f0
+
+--echo # connection 2
+connection con2;
+let $ignore= `SELECT @id := $ID`;
+SET DEBUG_SYNC='now WAIT_FOR filesort_started';
+KILL @id;
+SET DEBUG_SYNC='now SIGNAL filesort_killed';
+
+--echo # connection default
+connection default;
+disconnect con1;
+disconnect con2;
+--source include/wait_until_count_sessions.inc
+SET DEBUG_SYNC= "RESET";
+DROP TABLE t1;

=== modified file 'mysql-test/t/func_time.test'
--- a/mysql-test/t/func_time.test	2011-02-02 18:16:06 +0000
+++ b/mysql-test/t/func_time.test	2011-02-18 08:10:30 +0000
@@ -881,4 +881,11 @@ SELECT WEEK(STR_TO_DATE(NULL,0));
 SELECT SUBDATE(STR_TO_DATE(NULL,0), INTERVAL 1 HOUR);
 
 --echo #
+--echo # BUG#59895 - setting storage engine to null segfaults mysqld
+--echo #
+SELECT MONTHNAME(0), MONTHNAME(0) IS NULL, MONTHNAME(0) + 1;
+--error ER_WRONG_VALUE_FOR_VAR
+SET storage_engine=NULL;
+
+--echo #
 

=== modified file 'mysql-test/t/gis.test'
--- a/mysql-test/t/gis.test	2011-01-14 21:02:02 +0000
+++ b/mysql-test/t/gis.test	2011-02-24 14:49:38 +0000
@@ -757,6 +757,17 @@ insert into t1 values (geomfromtext("poi
 select * from (select polygon(t1.a) as p from t1 order by t1.a) d;
 drop table t1;
 
+
+--echo #
+--echo # Test for bug #59888 "debug assertion when attempt to create spatial index
+--echo #                      on char > 31 bytes".
+--echo #
+create table t1(a char(32) not null) engine=myisam;
+--error ER_SPATIAL_MUST_HAVE_GEOM_COL
+create spatial index i on t1 (a);
+drop table t1;
+
+
 --echo End of 5.1 tests
 
 #

=== modified file 'mysql-test/t/group_by.test'
--- a/mysql-test/t/group_by.test	2010-12-17 11:11:34 +0000
+++ b/mysql-test/t/group_by.test	2011-02-18 10:55:24 +0000
@@ -1248,6 +1248,43 @@ ON 1 WHERE t2.f1 > 1 GROUP BY t2.f1;
 
 DROP TABLE t1;
 
+--echo #
+--echo # Bug#59839: Aggregation followed by subquery yields wrong result
+--echo #
+
+CREATE TABLE t1 (
+  a INT,
+  b INT,
+  c INT,
+  KEY (a, b)
+);
+
+INSERT INTO t1 VALUES
+  ( 1, 1,  1 ),
+  ( 1, 2,  2 ),
+  ( 1, 3,  3 ),
+  ( 1, 4,  6 ),
+  ( 1, 5,  5 ),
+  ( 1, 9, 13 ),
+
+  ( 2, 1,  6 ),
+  ( 2, 2,  7 ),
+  ( 2, 3,  8 );
+
+EXPLAIN
+SELECT a, AVG(t1.b),
+(SELECT t11.c FROM t1 t11 WHERE t11.a = t1.a AND t11.b = AVG(t1.b)) AS t11c,
+(SELECT t12.c FROM t1 t12 WHERE t12.a = t1.a AND t12.b = AVG(t1.b)) AS t12c
+FROM t1 GROUP BY a;
+
+SELECT a, AVG(t1.b),
+(SELECT t11.c FROM t1 t11 WHERE t11.a = t1.a AND t11.b = AVG(t1.b)) AS t11c,
+(SELECT t12.c FROM t1 t12 WHERE t12.a = t1.a AND t12.b = AVG(t1.b)) AS t12c
+FROM t1 GROUP BY a;
+
+DROP TABLE t1;
+
+
 --echo # End of 5.1 tests
 
 --echo #

=== modified file 'mysql-test/t/insert_select.test'
--- a/mysql-test/t/insert_select.test	2009-09-22 21:41:37 +0000
+++ b/mysql-test/t/insert_select.test	2011-02-16 20:45:52 +0000
@@ -407,7 +407,7 @@ SET GLOBAL myisam_data_pointer_size = 2;
 
 INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
 
-call mtr.add_suppression("mysqld: The table '.*#sql.*' is full");
+call mtr.add_suppression("mysqld.*: The table '.*#sql.*' is full");
 --error ER_RECORD_FILE_FULL,ER_RECORD_FILE_FULL
 INSERT IGNORE INTO t1 SELECT t1.a FROM t1,t1 t2,t1 t3,t1 t4,t1 t5,t1 t6,t1 t7;
 

=== modified file 'mysql-test/t/multi_update.test'
--- a/mysql-test/t/multi_update.test	2010-12-14 10:46:00 +0000
+++ b/mysql-test/t/multi_update.test	2011-02-24 14:49:38 +0000
@@ -683,4 +683,24 @@ UPDATE (SELECT 1 FROM t1 WHERE f1 = (SEL
 DROP FUNCTION f1;
 DROP TABLE t1;
 
+--echo #
+--echo # BUG#57373: Multi update+InnoDB reports ER_KEY_NOT_FOUND if a
+--echo #            table is updated twice
+--echo #
+
+# Results differ between storage engines.
+# See multi_update_innodb.test for the InnoDB variant of this test
+CREATE TABLE t1(
+  pk INT,
+  a INT,
+  PRIMARY KEY (pk)
+) ENGINE=MyISAM;
+
+INSERT INTO t1 VALUES (0,0);
+UPDATE t1 AS A, t1 AS B SET A.pk = 1, B.a = 2;
+--echo
+--echo # Should be (1,2)
+SELECT * FROM t1;
+DROP TABLE t1;
+
 --echo end of tests

=== added file 'mysql-test/t/multi_update_innodb.test'
--- a/mysql-test/t/multi_update_innodb.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/multi_update_innodb.test	2011-02-21 15:49:03 +0000
@@ -0,0 +1,33 @@
+--source include/have_innodb.inc
+
+--echo #
+--echo # BUG#57373: Multi update+InnoDB reports ER_KEY_NOT_FOUND if a
+--echo #            table is updated twice
+--echo #
+
+# Results differ between storage engines.
+# See multi_update.test for the MyISAM variant of this test
+CREATE TABLE t1(
+  pk INT,
+  a INT,
+  b INT,
+  PRIMARY KEY (pk)
+) ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES (0,0,0);
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE t1 AS A, t1 AS B SET A.pk = 1, B.a = 2;
+SELECT * FROM t1;
+
+CREATE VIEW v1 AS SELECT * FROM t1;
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE v1 AS A, t1 AS B SET A.pk = 1, B.a = 2;
+SELECT * FROM t1;
+
+UPDATE t1 AS A, t1 AS B SET A.a = 1, B.b = 2;
+--echo # Should be (0,1,2)
+SELECT * FROM t1;
+
+DROP VIEW v1;
+DROP TABLE t1;
+

=== added file 'mysql-test/t/mysqld--defaults-file.test'
--- a/mysql-test/t/mysqld--defaults-file.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/mysqld--defaults-file.test	2011-02-08 10:21:14 +0000
@@ -0,0 +1,47 @@
+# BUG#58455
+# Starting mysqld with defaults file without extension cause
+# segmentation fault
+
+source include/not_embedded.inc;
+source include/not_windows.inc;
+
+# We need to use a plain "mysqld" without any other options to trigger
+# the bug. In particular, it seems that passing --bootstrap does not
+# trigger the bug. To do that, we extract the "command name" from the
+# MYSQLD_BOOTSTRAP_CMD variable and store that in a file, which we
+# then load into the test case.
+
+perl;
+  my ($mysqld)= split " ", $ENV{MYSQLD_BOOTSTRAP_CMD};
+  open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/mysqld.inc") or die;
+  print FILE "let \$MYSQLD= $mysqld;\n";
+  close FILE;
+EOF
+
+source $MYSQL_TMP_DIR/mysqld.inc;
+
+# All these tests refer to configuration files that do not exist
+
+--error 1
+exec $MYSQLD --defaults-file=/path/with/no/extension --print-defaults 2>&1;
+
+--error 1
+exec $MYSQLD --defaults-file=/path/with.ext --print-defaults 2>&1;
+
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--error 1
+exec $MYSQLD --defaults-file=relative/path/with.ext --print-defaults 2>&1;
+
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--error 1
+exec $MYSQLD --defaults-file=relative/path/without/extension --print-defaults 2>&1;
+
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--error 1
+exec $MYSQLD --defaults-file=with.ext --print-defaults 2>&1;
+
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--error 1
+exec $MYSQLD --defaults-file=no_extension --print-defaults 2>&1;
+
+remove_file $MYSQL_TMP_DIR/mysqld.inc;

=== modified file 'mysql-test/t/mysqldump.test'
--- a/mysql-test/t/mysqldump.test	2011-01-14 14:41:00 +0000
+++ b/mysql-test/t/mysqldump.test	2011-02-21 07:12:27 +0000
@@ -2179,6 +2179,27 @@ CREATE TABLE `comment_table` (i INT COMM
 DROP TABLE `comment_table`;
 
 --echo #
+--echo # BUG#11766310 : 59398: MYSQLDUMP 5.1 CAN'T HANDLE A DASH ("-") IN
+--echo #                DATABASE NAMES IN ALTER DATABASE
+--echo #
+
+CREATE DATABASE `test-database`;
+USE `test-database`;
+CREATE TABLE `test` (`c1` VARCHAR(10)) ENGINE=MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+DELIMITER |;
+CREATE TRIGGER `trig` BEFORE INSERT ON `test` FOR EACH ROW BEGIN
+END |
+DELIMITER ;|
+
+ALTER DATABASE `test-database` CHARACTER SET latin1 COLLATE latin1_swedish_ci;
+ALTER DATABASE `test-database` CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
+
+--exec $MYSQL_DUMP --quote-names --compact test-database
+
+DROP DATABASE `test-database`;
+
+--echo #
 --echo # End of 5.1 tests
 --echo #
 

=== modified file 'mysql-test/t/partition.test'
--- a/mysql-test/t/partition.test	2011-01-10 14:08:31 +0000
+++ b/mysql-test/t/partition.test	2011-02-24 14:49:38 +0000
@@ -2267,3 +2267,53 @@ DROP TABLE t1;
 SET GLOBAL myisam_use_mmap=default;
 
 --echo End of 5.1 tests
+
+--echo #
+--echo # BUG#55385: UPDATE statement throws an error, but still updates
+--echo #            the table entries
+
+CREATE TABLE t1_part (
+  partkey int,
+  nokey int
+) PARTITION BY LINEAR HASH(partkey) PARTITIONS 3;
+
+INSERT INTO t1_part VALUES (1, 1) , (10, 10);
+CREATE VIEW v1 AS SELECT * FROM t1_part;
+
+--echo
+--echo # Should be (1,1),(10,10)
+SELECT * FROM t1_part;
+
+--echo
+--echo # Case 1
+--echo # Update is refused because partitioning key is updated
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE t1_part AS A NATURAL JOIN t1_part B SET A.partkey = 2, B.nokey = 3;
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE t1_part AS A NATURAL JOIN t1_part B SET A.nokey = 2, B.partkey = 3;
+
+--echo
+--echo # Case 2
+--echo # Like 1, but partition accessed through a view
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE t1_part AS A NATURAL JOIN v1 as B SET A.nokey = 2 , B.partkey = 3;
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE v1 AS A NATURAL JOIN t1_part as B SET A.nokey = 2 , B.partkey = 3;
+
+--echo
+--echo # Should be (1,1),(10,10)
+SELECT * FROM t1_part;
+
+--echo
+--echo # Case 3
+--echo # Update is accepted because partitioning key is not updated
+UPDATE t1_part AS A NATURAL JOIN t1_part B SET A.nokey = 2 , B.nokey = 3;
+
+--echo
+--echo # Should be (1,3),(10,3)
+SELECT * FROM t1_part;
+
+--echo
+# Cleanup
+DROP VIEW v1;
+DROP TABLE t1_part;

=== modified file 'mysql-test/t/variables.test'
--- a/mysql-test/t/variables.test	2011-02-02 18:13:28 +0000
+++ b/mysql-test/t/variables.test	2011-02-10 07:34:22 +0000
@@ -1476,3 +1476,29 @@ drop function t1_max;
 
 
 ###########################################################################
+
+
+--echo #
+--echo # Bug #59884: setting charset to 2048 crashes
+--echo #
+
+--error ER_UNKNOWN_CHARACTER_SET
+set session character_set_results = 2048;
+--error ER_UNKNOWN_CHARACTER_SET
+set session character_set_client=2048;
+--error ER_UNKNOWN_CHARACTER_SET
+set session character_set_connection=2048;
+--error ER_UNKNOWN_CHARACTER_SET
+set session character_set_server=2048;
+--error ER_UNKNOWN_COLLATION
+set session collation_server=2048;
+--error ER_UNKNOWN_CHARACTER_SET
+set session character_set_filesystem=2048;
+--error ER_UNKNOWN_CHARACTER_SET
+set session character_set_database=2048;
+--error ER_UNKNOWN_COLLATION
+set session collation_connection=2048;
+--error ER_UNKNOWN_COLLATION
+set session collation_database=2048;
+
+--echo End of 5.5 tests

=== modified file 'mysql-test/t/xa.test'
--- a/mysql-test/t/xa.test	2010-09-13 11:31:22 +0000
+++ b/mysql-test/t/xa.test	2011-02-14 13:16:31 +0000
@@ -245,6 +245,48 @@ XA PREPARE 'x';
 XA ROLLBACK 'x';
 
 
+--echo #
+--echo # Bug#59986 Assert in Diagnostics_area::set_ok_status() for XA COMMIT
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a)) engine=InnoDB;
+INSERT INTO t1 VALUES (1, 1), (2, 2);
+
+--echo # Connection con1
+connect (con1, localhost, root);
+XA START 'a';
+UPDATE t1 SET b= 3 WHERE a=1;
+
+--echo # Connection default
+connection default;
+XA START 'b';
+UPDATE t1 SET b=4 WHERE a=2;
+--echo # Sending:
+--send UPDATE t1 SET b=5 WHERE a=1
+
+--echo # Connection con1
+connection con1;
+--sleep 1
+--error ER_LOCK_DEADLOCK
+UPDATE t1 SET b=6 WHERE a=2;
+# This used to trigger the assert
+--error ER_XA_RBDEADLOCK
+XA COMMIT 'a';
+
+--echo # Connection default
+connection default;
+--echo # Reaping: UPDATE t1 SET b=5 WHERE a=1
+--reap
+XA END 'b';
+XA ROLLBACK 'b';
+DROP TABLE t1;
+disconnect con1;
+
+
 # Wait till all disconnects are completed
 --source include/wait_until_count_sessions.inc
 

=== modified file 'mysql-test/valgrind.supp'
--- a/mysql-test/valgrind.supp	2011-02-08 17:28:00 +0000
+++ b/mysql-test/valgrind.supp	2011-02-17 11:57:26 +0000
@@ -875,5 +875,4 @@
    fun:buf_buddy_relocate
    fun:buf_buddy_free_low
    fun:buf_buddy_free
-   fun:buf_LRU_block_remove_hashed_page
 }

=== modified file 'mysys/charset.c'
--- a/mysys/charset.c	2010-07-08 21:20:08 +0000
+++ b/mysys/charset.c	2011-02-10 07:34:22 +0000
@@ -419,6 +419,7 @@ CHARSET_INFO *default_charset_info = &my
 
 void add_compiled_collation(CHARSET_INFO *cs)
 {
+  DBUG_ASSERT(cs->number < array_elements(all_charsets));
   all_charsets[cs->number]= cs;
   cs->state|= MY_CS_AVAILABLE;
 }
@@ -529,14 +530,17 @@ uint get_charset_number(const char *char
 
 const char *get_charset_name(uint charset_number)
 {
-  CHARSET_INFO *cs;
   my_pthread_once(&charsets_initialized, init_available_charsets);
 
-  cs=all_charsets[charset_number];
-  if (cs && (cs->number == charset_number) && cs->name )
-    return (char*) cs->name;
+  if (charset_number < array_elements(all_charsets))
+  {
+    CHARSET_INFO *cs= all_charsets[charset_number];
+
+    if (cs && (cs->number == charset_number) && cs->name)
+      return (char*) cs->name;
+  }
   
-  return (char*) "?";   /* this mimics find_type() */
+  return "?";   /* this mimics find_type() */
 }
 
 
@@ -545,6 +549,8 @@ static CHARSET_INFO *get_internal_charse
   char  buf[FN_REFLEN];
   CHARSET_INFO *cs;
 
+  DBUG_ASSERT(cs_number < array_elements(all_charsets));
+
   if ((cs= all_charsets[cs_number]))
   {
     if (cs->state & MY_CS_READY)  /* if CS is already initialized */
@@ -589,8 +595,8 @@ CHARSET_INFO *get_charset(uint cs_number
     return default_charset_info;
 
   my_pthread_once(&charsets_initialized, init_available_charsets);
-  
-  if (!cs_number || cs_number > array_elements(all_charsets))
+ 
+  if (cs_number >= array_elements(all_charsets)) 
     return NULL;
   
   cs=get_internal_charset(cs_number, flags);

=== modified file 'mysys/default.c'
--- a/mysys/default.c	2011-01-17 07:44:37 +0000
+++ b/mysys/default.c	2011-02-08 10:21:14 +0000
@@ -179,7 +179,7 @@ fn_expand(const char *filename, char *re
   if (my_getwd(dir, sizeof(dir), MYF(0)))
     DBUG_RETURN(3);
   DBUG_PRINT("debug", ("dir: %s", dir));
-  if (fn_format(result_buf, filename, dir, NULL, flags) == NULL)
+  if (fn_format(result_buf, filename, dir, "", flags) == NULL)
     DBUG_RETURN(2);
   DBUG_PRINT("return", ("result: %s", result_buf));
   DBUG_RETURN(0);

=== modified file 'mysys/mf_format.c'
--- a/mysys/mf_format.c	2009-04-19 01:21:33 +0000
+++ b/mysys/mf_format.c	2011-02-08 10:21:14 +0000
@@ -31,6 +31,8 @@ char * fn_format(char * to, const char *
   reg1 size_t length;
   size_t dev_length;
   DBUG_ENTER("fn_format");
+  DBUG_ASSERT(name != NULL);
+  DBUG_ASSERT(extension != NULL);
   DBUG_PRINT("enter",("name: %s  dir: %s  extension: %s  flag: %d",
 		       name,dir,extension,flag));
 

=== modified file 'mysys/my_bitmap.c'
--- a/mysys/my_bitmap.c	2011-01-11 09:07:37 +0000
+++ b/mysys/my_bitmap.c	2011-02-16 15:33:02 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2000, 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
@@ -86,6 +86,7 @@ static inline void bitmap_lock(MY_BITMAP
     mysql_mutex_lock(map->mutex);
 }
 
+
 static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused)))
 {
   if (map->mutex)
@@ -93,6 +94,46 @@ static inline void bitmap_unlock(MY_BITM
 }
 
 
+static inline uint get_first_set(uint32 value, uint word_pos)
+{
+  uchar *byte_ptr= (uchar*)&value;
+  uchar byte_value;
+  uint byte_pos, bit_pos;
+
+  for (byte_pos=0; byte_pos < 4; byte_pos++, byte_ptr++)
+  {
+    byte_value= *byte_ptr;
+    if (byte_value)
+    {
+      for (bit_pos=0; ; bit_pos++)
+        if (byte_value & (1 << bit_pos))
+          return (word_pos*32) + (byte_pos*8) + bit_pos;
+    }
+  }
+  return MY_BIT_NONE;
+}
+
+
+static inline uint get_first_not_set(uint32 value, uint word_pos)
+{
+  uchar *byte_ptr= (uchar*)&value;
+  uchar byte_value;
+  uint byte_pos, bit_pos;
+
+  for (byte_pos=0; byte_pos < 4; byte_pos++, byte_ptr++)
+  {
+    byte_value= *byte_ptr;
+    if (byte_value != 0xFF)
+    {
+      for (bit_pos=0; ; bit_pos++)
+        if (!(byte_value & (1 << bit_pos)))
+          return (word_pos*32) + (byte_pos*8) + bit_pos;
+    }
+  }
+  return MY_BIT_NONE;
+}
+
+
 my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits,
 		    my_bool thread_safe __attribute__((unused)))
 {
@@ -251,7 +292,7 @@ void bitmap_set_prefix(MY_BITMAP *map, u
     memset(m, 0xff, prefix_bytes);
   m+= prefix_bytes;
   if ((prefix_bits= prefix_size & 7))
-    *m++= (1 << prefix_bits)-1;
+    *(m++)= (1 << prefix_bits)-1;
   if ((d= no_bytes_in_map(map)-prefix_bytes))
     bzero(m, d);
 }
@@ -259,28 +300,43 @@ void bitmap_set_prefix(MY_BITMAP *map, u
 
 my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size)
 {
-  uint prefix_bits= prefix_size & 0x7, res;
-  uchar *m= (uchar*)map->bitmap;
-  uchar *end_prefix= m+prefix_size/8;
-  uchar *end;
-  DBUG_ASSERT(m && prefix_size <= map->n_bits);
-  end= m+no_bytes_in_map(map);
-
-  while (m < end_prefix)
-    if (*m++ != 0xff)
-      return 0;
-
-  *map->last_word_ptr&= ~map->last_word_mask; /*Clear bits*/
-  res= 0;
-  if (prefix_bits && *m++ != (1 << prefix_bits)-1)
-    goto ret;
-
-  while (m < end)
-    if (*m++ != 0)
-      goto ret;
-  res= 1;
-ret:
-  return res; 
+  uint prefix_bits= prefix_size % 32;
+  my_bitmap_map *word_ptr= map->bitmap, last_word;
+  my_bitmap_map *end_prefix= word_ptr + prefix_size / 32;
+  DBUG_ASSERT(word_ptr && prefix_size <= map->n_bits);
+
+  /* 1: Words that should be filled with 1 */
+  for (; word_ptr < end_prefix; word_ptr++)
+    if (*word_ptr != 0xFFFFFFFF)
+      return FALSE;
+
+  last_word= *map->last_word_ptr & ~map->last_word_mask;
+
+  /* 2: Word which contains the end of the prefix (if any) */
+  if (prefix_bits)
+  {
+    if (word_ptr == map->last_word_ptr)
+      return uint4korr((uchar*)&last_word) == (uint32)((1 << prefix_bits) - 1);
+    else if (uint4korr((uchar*)word_ptr) != (uint32)((1 << prefix_bits) - 1))
+      return FALSE;
+    word_ptr++;
+  }
+
+  /* 3: Words that should be filled with 0 */
+  for (; word_ptr < map->last_word_ptr; word_ptr++)
+    if (*word_ptr != 0)
+      return FALSE;
+
+  /*
+    We can end up here in two situations:
+    1) We went through the whole bitmap in step 1. This will happen if the
+       whole bitmap is filled with 1 and prefix_size is a multiple of 32
+       (i.e. the prefix does not end in the middle of a word).
+       In this case word_ptr will be larger than map->last_word_ptr.
+    2) We have gone through steps 1-3 and just need to check that also
+       the last word is 0.
+  */
+  return word_ptr > map->last_word_ptr || last_word == 0;
 }
 
 
@@ -288,10 +344,12 @@ my_bool bitmap_is_set_all(const MY_BITMA
 {
   my_bitmap_map *data_ptr= map->bitmap;
   my_bitmap_map *end= map->last_word_ptr;
-  *map->last_word_ptr |= map->last_word_mask;
-  for (; data_ptr <= end; data_ptr++)
+
+  for (; data_ptr < end; data_ptr++)
     if (*data_ptr != 0xFFFFFFFF)
       return FALSE;
+  if ((*map->last_word_ptr | map->last_word_mask) != 0xFFFFFFFF)
+    return FALSE;
   return TRUE;
 }
 
@@ -299,13 +357,13 @@ my_bool bitmap_is_set_all(const MY_BITMA
 my_bool bitmap_is_clear_all(const MY_BITMAP *map)
 {
   my_bitmap_map *data_ptr= map->bitmap;
-  my_bitmap_map *end;
-  if (*map->last_word_ptr & ~map->last_word_mask)
-    return FALSE;
-  end= map->last_word_ptr;
+  my_bitmap_map *end= map->last_word_ptr;
+
   for (; data_ptr < end; data_ptr++)
     if (*data_ptr)
       return FALSE;
+  if (*map->last_word_ptr & ~map->last_word_mask)
+    return FALSE;
   return TRUE;
 }
 
@@ -319,14 +377,14 @@ my_bool bitmap_is_subset(const MY_BITMAP
               map1->n_bits==map2->n_bits);
 
   end= map1->last_word_ptr;
-  *map1->last_word_ptr &= ~map1->last_word_mask;
-  *map2->last_word_ptr &= ~map2->last_word_mask;
-  while (m1 <= end)
-  {
-    if ((*m1++) & ~(*m2++))
-      return 0;
-  }
-  return 1;
+  for (; m1 < end; m1++, m2++)
+    if (*m1 & ~(*m2))
+      return FALSE;
+
+  if ((*map1->last_word_ptr & ~map1->last_word_mask) &
+      ~(*map2->last_word_ptr & ~map2->last_word_mask))
+    return FALSE;
+  return TRUE;
 }
 
 /* True if bitmaps has any common bits */
@@ -339,14 +397,14 @@ my_bool bitmap_is_overlapping(const MY_B
               map1->n_bits==map2->n_bits);
 
   end= map1->last_word_ptr;
-  *map1->last_word_ptr &= ~map1->last_word_mask;
-  *map2->last_word_ptr &= ~map2->last_word_mask;
-  while (m1 <= end)
-  {
-    if ((*m1++) & (*m2++))
-      return 1;
-  }
-  return 0;
+  for (; m1 < end; m1++, m2++)
+    if (*m1 & *m2)
+      return TRUE;
+
+  if ((*map1->last_word_ptr & ~map1->last_word_mask) &
+      (*map2->last_word_ptr & ~map2->last_word_mask))
+    return TRUE;
+  return FALSE;
 }
 
 
@@ -358,15 +416,17 @@ void bitmap_intersect(MY_BITMAP *map, co
   DBUG_ASSERT(map->bitmap && map2->bitmap);
 
   end= to+min(len,len2);
-  *map2->last_word_ptr&= ~map2->last_word_mask; /*Clear last bits in map2*/
-  while (to < end)
-    *to++ &= *from++;
+  for (; to < end; to++, from++)
+    *to &= *from;
+
+  if (len >= len2)
+    map->bitmap[len2 - 1] &= ~map2->last_word_mask;
 
   if (len2 < len)
   {
     end+=len-len2;
-    while (to < end)
-      *to++=0;
+    for (; to < end; to++)
+      *to= 0;
   }
 }
 
@@ -397,8 +457,8 @@ void bitmap_set_above(MY_BITMAP *map, ui
   uchar *to= (uchar *)map->bitmap + from_byte;
   uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8;
 
-  while (to < end)
-    *to++= use_byte;
+  for (; to < end; to++)
+    *to= use_byte;
 }
 
 
@@ -407,59 +467,60 @@ void bitmap_subtract(MY_BITMAP *map, con
   my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
   DBUG_ASSERT(map->bitmap && map2->bitmap &&
               map->n_bits==map2->n_bits);
-
   end= map->last_word_ptr;
 
-  while (to <= end)
-    *to++ &= ~(*from++);
+  for (; to <= end; to++, from++)
+    *to &= ~(*from);
 }
 
 
 void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
 {
   my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
-
   DBUG_ASSERT(map->bitmap && map2->bitmap &&
               map->n_bits==map2->n_bits);
   end= map->last_word_ptr;
 
-  while (to <= end)
-    *to++ |= *from++;
+  for (; to <= end; to++, from++)
+    *to |= *from;
 }
 
 
 void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2)
 {
-  my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr;
+  my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
   DBUG_ASSERT(map->bitmap && map2->bitmap &&
               map->n_bits==map2->n_bits);
-  while (to <= end)
-    *to++ ^= *from++;
+  end= map->last_word_ptr;
+
+  for (; to <= end; to++, from++)
+    *to ^= *from;
 }
 
 
 void bitmap_invert(MY_BITMAP *map)
 {
   my_bitmap_map *to= map->bitmap, *end;
-
   DBUG_ASSERT(map->bitmap);
   end= map->last_word_ptr;
 
-  while (to <= end)
-    *to++ ^= 0xFFFFFFFF;
+  for (; to <= end; to++)
+    *to ^= 0xFFFFFFFF;
 }
 
 
 uint bitmap_bits_set(const MY_BITMAP *map)
-{  
-  uchar *m= (uchar*)map->bitmap;
-  uchar *end= m + no_bytes_in_map(map);
+{
+  my_bitmap_map *data_ptr= map->bitmap;
+  my_bitmap_map *end= map->last_word_ptr;
   uint res= 0;
-
   DBUG_ASSERT(map->bitmap);
-  *map->last_word_ptr&= ~map->last_word_mask; /*Reset last bits to zero*/
-  while (m < end)
-    res+= my_count_bits_ushort(*m++);
+
+  for (; data_ptr < end; data_ptr++)
+    res+= my_count_bits_uint32(*data_ptr);
+
+  /*Reset last bits to zero*/
+  res+= my_count_bits_uint32(*map->last_word_ptr & ~map->last_word_mask);
   return res;
 }
 
@@ -467,76 +528,44 @@ uint bitmap_bits_set(const MY_BITMAP *ma
 void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2)
 {
   my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
-
   DBUG_ASSERT(map->bitmap && map2->bitmap &&
               map->n_bits==map2->n_bits);
   end= map->last_word_ptr;
-  while (to <= end)
-    *to++ = *from++;
+
+  for (; to <= end; to++, from++)
+    *to = *from;
 }
 
 
 uint bitmap_get_first_set(const MY_BITMAP *map)
 {
-  uchar *byte_ptr;
-  uint i,j,k;
+  uint word_pos;
   my_bitmap_map *data_ptr, *end= map->last_word_ptr;
 
   DBUG_ASSERT(map->bitmap);
   data_ptr= map->bitmap;
-  *map->last_word_ptr &= ~map->last_word_mask;
 
-  for (i=0; data_ptr <= end; data_ptr++, i++)
-  {
+  for (word_pos=0; data_ptr < end; data_ptr++, word_pos++)
     if (*data_ptr)
-    {
-      byte_ptr= (uchar*)data_ptr;
-      for (j=0; ; j++, byte_ptr++)
-      {
-        if (*byte_ptr)
-        {
-          for (k=0; ; k++)
-          {
-            if (*byte_ptr & (1 << k))
-              return (i*32) + (j*8) + k;
-          }
-        }
-      }
-    }
-  }
-  return MY_BIT_NONE;
+      return get_first_set(*data_ptr, word_pos);
+
+  return get_first_set(*map->last_word_ptr & ~map->last_word_mask, word_pos);
 }
 
 
 uint bitmap_get_first(const MY_BITMAP *map)
 {
-  uchar *byte_ptr;
-  uint i,j,k;
+  uint word_pos;
   my_bitmap_map *data_ptr, *end= map->last_word_ptr;
 
   DBUG_ASSERT(map->bitmap);
   data_ptr= map->bitmap;
-  *map->last_word_ptr|= map->last_word_mask;
 
-  for (i=0; data_ptr <= end; data_ptr++, i++)
-  {
+  for (word_pos=0; data_ptr < end; data_ptr++, word_pos++)
     if (*data_ptr != 0xFFFFFFFF)
-    {
-      byte_ptr= (uchar*)data_ptr;
-      for (j=0; ; j++, byte_ptr++)
-      {
-        if (*byte_ptr != 0xFF)
-        {
-          for (k=0; ; k++)
-          {
-            if (!(*byte_ptr & (1 << k)))
-              return (i*32) + (j*8) + k;
-          }
-        }
-      }
-    }
-  }
-  return MY_BIT_NONE;
+      return get_first_not_set(*data_ptr, word_pos);
+
+  return get_first_not_set(*map->last_word_ptr | map->last_word_mask, word_pos);
 }
 
 
@@ -557,376 +586,3 @@ void bitmap_lock_clear_bit(MY_BITMAP *ma
   bitmap_clear_bit(map, bitmap_bit);
   bitmap_unlock(map);
 }
-
-#ifdef MAIN
-
-uint get_rand_bit(uint bitsize)
-{
-  return (rand() % bitsize);
-}
-
-bool test_set_get_clear_bit(MY_BITMAP *map, uint bitsize)
-{
-  uint i, test_bit;
-  uint no_loops= bitsize > 128 ? 128 : bitsize;
-  for (i=0; i < no_loops; i++)
-  {
-    test_bit= get_rand_bit(bitsize);
-    bitmap_set_bit(map, test_bit);
-    if (!bitmap_is_set(map, test_bit))
-      goto error1;
-    bitmap_clear_bit(map, test_bit);
-    if (bitmap_is_set(map, test_bit))
-      goto error2;
-  }
-  return FALSE;
-error1:
-  printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize);
-  return TRUE;
-error2:
-  printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize);
-  return TRUE;
-}
-
-bool test_flip_bit(MY_BITMAP *map, uint bitsize)
-{
-  uint i, test_bit;
-  uint no_loops= bitsize > 128 ? 128 : bitsize;
-  for (i=0; i < no_loops; i++)
-  {
-    test_bit= get_rand_bit(bitsize);
-    bitmap_flip_bit(map, test_bit);
-    if (!bitmap_is_set(map, test_bit))
-      goto error1;
-    bitmap_flip_bit(map, test_bit);
-    if (bitmap_is_set(map, test_bit))
-      goto error2;
-  }
-  return FALSE;
-error1:
-  printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize);
-  return TRUE;
-error2:
-  printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize);
-  return TRUE;
-}
-
-bool test_operators(MY_BITMAP *map __attribute__((unused)),
-                    uint bitsize __attribute__((unused)))
-{
-  return FALSE;
-}
-
-bool test_get_all_bits(MY_BITMAP *map, uint bitsize)
-{
-  uint i;
-  bitmap_set_all(map);
-  if (!bitmap_is_set_all(map))
-    goto error1;
-  if (!bitmap_is_prefix(map, bitsize))
-    goto error5;
-  bitmap_clear_all(map);
-  if (!bitmap_is_clear_all(map))
-    goto error2;
-  if (!bitmap_is_prefix(map, 0))
-    goto error6;
-  for (i=0; i<bitsize;i++)
-    bitmap_set_bit(map, i);
-  if (!bitmap_is_set_all(map))
-    goto error3;
-  for (i=0; i<bitsize;i++)
-    bitmap_clear_bit(map, i);
-  if (!bitmap_is_clear_all(map))
-    goto error4;
-  return FALSE;
-error1:
-  printf("Error in set_all, bitsize = %u", bitsize);
-  return TRUE;
-error2:
-  printf("Error in clear_all, bitsize = %u", bitsize);
-  return TRUE;
-error3:
-  printf("Error in bitmap_is_set_all, bitsize = %u", bitsize);
-  return TRUE;
-error4:
-  printf("Error in bitmap_is_clear_all, bitsize = %u", bitsize);
-  return TRUE;
-error5:
-  printf("Error in set_all through set_prefix, bitsize = %u", bitsize);
-  return TRUE;
-error6:
-  printf("Error in clear_all through set_prefix, bitsize = %u", bitsize);
-  return TRUE;
-}
-
-bool test_compare_operators(MY_BITMAP *map, uint bitsize)
-{
-  uint i, j, test_bit1, test_bit2, test_bit3,test_bit4;
-  uint no_loops= bitsize > 128 ? 128 : bitsize;
-  MY_BITMAP map2_obj, map3_obj;
-  MY_BITMAP *map2= &map2_obj, *map3= &map3_obj;
-  my_bitmap_map map2buf[1024];
-  my_bitmap_map map3buf[1024];
-  bitmap_init(&map2_obj, map2buf, bitsize, FALSE);
-  bitmap_init(&map3_obj, map3buf, bitsize, FALSE);
-  bitmap_clear_all(map2);
-  bitmap_clear_all(map3);
-  for (i=0; i < no_loops; i++)
-  {
-    test_bit1=get_rand_bit(bitsize);
-    bitmap_set_prefix(map, test_bit1);
-    test_bit2=get_rand_bit(bitsize);
-    bitmap_set_prefix(map2, test_bit2);
-    bitmap_intersect(map, map2);
-    test_bit3= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
-    bitmap_set_prefix(map3, test_bit3);
-    if (!bitmap_cmp(map, map3))
-      goto error1;
-    bitmap_clear_all(map);
-    bitmap_clear_all(map2);
-    bitmap_clear_all(map3);
-    test_bit1=get_rand_bit(bitsize);
-    test_bit2=get_rand_bit(bitsize);
-    test_bit3=get_rand_bit(bitsize);
-    bitmap_set_prefix(map, test_bit1);
-    bitmap_set_prefix(map2, test_bit2);
-    test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
-    bitmap_set_prefix(map3, test_bit3);
-    bitmap_union(map, map2);
-    if (!bitmap_cmp(map, map3))
-      goto error2;
-    bitmap_clear_all(map);
-    bitmap_clear_all(map2);
-    bitmap_clear_all(map3);
-    test_bit1=get_rand_bit(bitsize);
-    test_bit2=get_rand_bit(bitsize);
-    test_bit3=get_rand_bit(bitsize);
-    bitmap_set_prefix(map, test_bit1);
-    bitmap_set_prefix(map2, test_bit2);
-    bitmap_xor(map, map2);
-    test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
-    test_bit4= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
-    bitmap_set_prefix(map3, test_bit3);
-    for (j=0; j < test_bit4; j++)
-      bitmap_clear_bit(map3, j);
-    if (!bitmap_cmp(map, map3))
-      goto error3;
-    bitmap_clear_all(map);
-    bitmap_clear_all(map2);
-    bitmap_clear_all(map3);
-    test_bit1=get_rand_bit(bitsize);
-    test_bit2=get_rand_bit(bitsize);
-    test_bit3=get_rand_bit(bitsize);
-    bitmap_set_prefix(map, test_bit1);
-    bitmap_set_prefix(map2, test_bit2);
-    bitmap_subtract(map, map2);
-    if (test_bit2 < test_bit1)
-    {
-      bitmap_set_prefix(map3, test_bit1);
-      for (j=0; j < test_bit2; j++)
-        bitmap_clear_bit(map3, j);
-    }
-    if (!bitmap_cmp(map, map3))
-      goto error4;
-    bitmap_clear_all(map);
-    bitmap_clear_all(map2);
-    bitmap_clear_all(map3);
-    test_bit1=get_rand_bit(bitsize);
-    bitmap_set_prefix(map, test_bit1);
-    bitmap_invert(map);
-    bitmap_set_all(map3);
-    for (j=0; j < test_bit1; j++)
-      bitmap_clear_bit(map3, j);
-    if (!bitmap_cmp(map, map3))
-      goto error5;
-    bitmap_clear_all(map);
-    bitmap_clear_all(map3);
-  }
-  return FALSE;
-error1:
-  printf("intersect error  bitsize=%u,size1=%u,size2=%u", bitsize,
-  test_bit1,test_bit2);
-  return TRUE;
-error2:
-  printf("union error  bitsize=%u,size1=%u,size2=%u", bitsize,
-  test_bit1,test_bit2);
-  return TRUE;
-error3:
-  printf("xor error  bitsize=%u,size1=%u,size2=%u", bitsize,
-  test_bit1,test_bit2);
-  return TRUE;
-error4:
-  printf("subtract error  bitsize=%u,size1=%u,size2=%u", bitsize,
-  test_bit1,test_bit2);
-  return TRUE;
-error5:
-  printf("invert error  bitsize=%u,size=%u", bitsize,
-  test_bit1);
-  return TRUE;
-}
-
-bool test_count_bits_set(MY_BITMAP *map, uint bitsize)
-{
-  uint i, bit_count=0, test_bit;
-  uint no_loops= bitsize > 128 ? 128 : bitsize;
-  for (i=0; i < no_loops; i++)
-  {
-    test_bit=get_rand_bit(bitsize);
-    if (!bitmap_is_set(map, test_bit))
-    {
-      bitmap_set_bit(map, test_bit);
-      bit_count++;
-    }
-  }
-  if (bit_count==0 && bitsize > 0)
-    goto error1;
-  if (bitmap_bits_set(map) != bit_count)
-    goto error2;
-  return FALSE;
-error1:
-  printf("No bits set  bitsize = %u", bitsize);
-  return TRUE;
-error2:
-  printf("Wrong count of bits set, bitsize = %u", bitsize);
-  return TRUE;
-}
-
-bool test_get_first_bit(MY_BITMAP *map, uint bitsize)
-{
-  uint i, test_bit;
-  uint no_loops= bitsize > 128 ? 128 : bitsize;
-  for (i=0; i < no_loops; i++)
-  {
-    test_bit=get_rand_bit(bitsize);
-    bitmap_set_bit(map, test_bit);
-    if (bitmap_get_first_set(map) != test_bit)
-      goto error1;
-    bitmap_set_all(map);
-    bitmap_clear_bit(map, test_bit);
-    if (bitmap_get_first(map) != test_bit)
-      goto error2;
-    bitmap_clear_all(map);
-  }
-  return FALSE;
-error1:
-  printf("get_first_set error bitsize=%u,prefix_size=%u",bitsize,test_bit);
-  return TRUE;
-error2:
-  printf("get_first error bitsize= %u, prefix_size= %u",bitsize,test_bit);
-  return TRUE;
-}
-
-bool test_get_next_bit(MY_BITMAP *map, uint bitsize)
-{
-  uint i, j, test_bit;
-  uint no_loops= bitsize > 128 ? 128 : bitsize;
-  for (i=0; i < no_loops; i++)
-  {
-    test_bit=get_rand_bit(bitsize);
-    for (j=0; j < test_bit; j++)
-      bitmap_set_next(map);
-    if (!bitmap_is_prefix(map, test_bit))
-      goto error1;
-    bitmap_clear_all(map);
-  }
-  return FALSE;
-error1:
-  printf("get_next error  bitsize= %u, prefix_size= %u", bitsize,test_bit);
-  return TRUE;
-}
-
-bool test_prefix(MY_BITMAP *map, uint bitsize)
-{
-  uint i, j, test_bit;
-  uint no_loops= bitsize > 128 ? 128 : bitsize;
-  for (i=0; i < no_loops; i++)
-  {
-    test_bit=get_rand_bit(bitsize);
-    bitmap_set_prefix(map, test_bit);
-    if (!bitmap_is_prefix(map, test_bit))
-      goto error1;
-    bitmap_clear_all(map);
-    for (j=0; j < test_bit; j++)
-      bitmap_set_bit(map, j);
-    if (!bitmap_is_prefix(map, test_bit))
-      goto error2;
-    bitmap_set_all(map);
-    for (j=bitsize - 1; ~(j-test_bit); j--)
-      bitmap_clear_bit(map, j);
-    if (!bitmap_is_prefix(map, test_bit))
-      goto error3;
-    bitmap_clear_all(map);
-  }
-  return FALSE;
-error1:
-  printf("prefix1 error  bitsize = %u, prefix_size = %u", bitsize,test_bit);
-  return TRUE;
-error2:
-  printf("prefix2 error  bitsize = %u, prefix_size = %u", bitsize,test_bit);
-  return TRUE;
-error3:
-  printf("prefix3 error  bitsize = %u, prefix_size = %u", bitsize,test_bit);
-  return TRUE;
-}
-
-
-bool do_test(uint bitsize)
-{
-  MY_BITMAP map;
-  my_bitmap_map buf[1024];
-  if (bitmap_init(&map, buf, bitsize, FALSE))
-  {
-    printf("init error for bitsize %d", bitsize);
-    goto error;
-  }
-  if (test_set_get_clear_bit(&map,bitsize))
-    goto error;
-  bitmap_clear_all(&map);
-  if (test_flip_bit(&map,bitsize))
-    goto error;
-  bitmap_clear_all(&map);
-  if (test_operators(&map,bitsize))
-    goto error;
-  bitmap_clear_all(&map);
-  if (test_get_all_bits(&map, bitsize))
-    goto error;
-  bitmap_clear_all(&map);
-  if (test_compare_operators(&map,bitsize))
-    goto error;
-  bitmap_clear_all(&map);
-  if (test_count_bits_set(&map,bitsize))
-    goto error;
-  bitmap_clear_all(&map);
-  if (test_get_first_bit(&map,bitsize))
-    goto error;
-  bitmap_clear_all(&map);
-  if (test_get_next_bit(&map,bitsize))
-    goto error;
-  if (test_prefix(&map,bitsize))
-    goto error;
-  return FALSE;
-error:
-  printf("\n");
-  return TRUE;
-}
-
-int main()
-{
-  int i;
-  for (i= 1; i < 4096; i++)
-  {
-    printf("Start test for bitsize=%u\n",i);
-    if (do_test(i))
-      return -1;
-  }
-  printf("OK\n");
-  return 0;
-}
-
-/*
-  In directory mysys:
-  make test_bitmap
-  will build the bitmap tests and ./test_bitmap will execute it
-*/
-
-#endif

=== modified file 'plugin/auth/auth_socket.c'
--- a/plugin/auth/auth_socket.c	2010-09-20 16:38:27 +0000
+++ b/plugin/auth/auth_socket.c	2011-01-11 14:53:14 +0000
@@ -79,7 +79,7 @@ mysql_declare_plugin(socket_auth)
 {
   MYSQL_AUTHENTICATION_PLUGIN,
   &socket_auth_handler,
-  "socket_peercred",
+  "auth_socket",
   "Sergei Golubchik",
   "Unix Socket based authentication",
   PLUGIN_LICENSE_GPL,

=== modified file 'sql/filesort.cc'
--- a/sql/filesort.cc	2011-02-02 11:54:49 +0000
+++ b/sql/filesort.cc	2011-02-24 07:00:12 +0000
@@ -32,6 +32,7 @@
 #include "probes_mysql.h"
 #include "sql_test.h"                           // TEST_filesort
 #include "opt_range.h"                          // SQL_SELECT
+#include "debug_sync.h"
 
 /// How to write record_ref.
 #define WRITE_REF(file,from) \
@@ -123,6 +124,7 @@ ha_rows filesort(THD *thd, TABLE *table,
   Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
 
   MYSQL_FILESORT_START(table->s->db.str, table->s->table_name.str);
+  DEBUG_SYNC(thd, "filesort_start");
 
   /*
    Release InnoDB's adaptive hash index latch (if holding) before
@@ -325,12 +327,13 @@ ha_rows filesort(THD *thd, TABLE *table,
   }
   if (error)
   {
-    DBUG_ASSERT(thd->is_error());
+    int kill_errno= thd->killed_errno();
+    DBUG_ASSERT(thd->is_error() || kill_errno);
     my_printf_error(ER_FILSORT_ABORT,
                     "%s: %s",
                     MYF(ME_ERROR + ME_WAITTANG),
                     ER_THD(thd, ER_FILSORT_ABORT),
-                    thd->stmt_da->message());
+                    kill_errno ? ER(kill_errno) : thd->stmt_da->message());
                     
     if (global_system_variables.log_warnings > 1)
     {

=== modified file 'sql/ha_ndbcluster_cond.cc'
--- a/sql/ha_ndbcluster_cond.cc	2010-08-14 09:11:33 +0000
+++ b/sql/ha_ndbcluster_cond.cc	2011-02-21 10:15:29 +0000
@@ -1472,4 +1472,4 @@ int ha_ndbcluster_cond::generate_scan_fi
   DBUG_RETURN(0);
 }
 
-#endif /* HAVE_NDBCLUSTER_DB */
+#endif

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2011-02-08 15:47:33 +0000
+++ b/sql/handler.cc	2011-02-24 14:49:38 +0000
@@ -2700,6 +2700,7 @@ void handler::print_error(int error, myf
     break;
   case HA_ERR_KEY_NOT_FOUND:
   case HA_ERR_NO_ACTIVE_RECORD:
+  case HA_ERR_RECORD_DELETED:
   case HA_ERR_END_OF_FILE:
     textno=ER_KEY_NOT_FOUND;
     break;

=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc	2011-02-08 15:47:33 +0000
+++ b/sql/item_cmpfunc.cc	2011-02-24 14:49:38 +0000
@@ -2640,7 +2640,7 @@ Item_func_if::fix_length_and_dec()
   if (null1)
   {
     cached_result_type= arg2_type;
-    collation.set(args[2]->collation.collation);
+    collation.set(args[2]->collation);
     cached_field_type= args[2]->field_type();
     max_length= args[2]->max_length;
     return;
@@ -2649,7 +2649,7 @@ Item_func_if::fix_length_and_dec()
   if (null2)
   {
     cached_result_type= arg1_type;
-    collation.set(args[1]->collation.collation);
+    collation.set(args[1]->collation);
     cached_field_type= args[1]->field_type();
     max_length= args[1]->max_length;
     return;

=== modified file 'sql/item_strfunc.cc'
--- a/sql/item_strfunc.cc	2011-01-17 12:26:13 +0000
+++ b/sql/item_strfunc.cc	2011-02-10 08:18:08 +0000
@@ -70,7 +70,7 @@ String my_empty_string("",default_charse
   Normally conversion does not happen, and val_str_ascii() is immediately
   returned instead.
 */
-String *Item_str_ascii_func::val_str(String *str)
+String *Item_str_func::val_str_from_val_str_ascii(String *str, String *str2)
 {
   DBUG_ASSERT(fixed == 1);
 
@@ -82,19 +82,19 @@ String *Item_str_ascii_func::val_str(Str
     return res;
   }
   
-  DBUG_ASSERT(str != &ascii_buf);
+  DBUG_ASSERT(str != str2);
   
   uint errors;
-  String *res= val_str_ascii(&ascii_buf);
+  String *res= val_str_ascii(str);
   if (!res)
     return 0;
   
-  if ((null_value= str->copy(res->ptr(), res->length(),
-                             &my_charset_latin1, collation.collation,
-                             &errors)))
+  if ((null_value= str2->copy(res->ptr(), res->length(),
+                              &my_charset_latin1, collation.collation,
+                              &errors)))
     return 0;
   
-  return str;
+  return str2;
 }
 
 

=== modified file 'sql/item_strfunc.h'
--- a/sql/item_strfunc.h	2011-02-07 10:17:46 +0000
+++ b/sql/item_strfunc.h	2011-02-10 08:18:08 +0000
@@ -51,6 +51,7 @@ public:
   enum Item_result result_type () const { return STRING_RESULT; }
   void left_right_max_length();
   bool fix_fields(THD *thd, Item **ref);
+  String *val_str_from_val_str_ascii(String *str, String *str2);
 };
 
 
@@ -66,8 +67,10 @@ public:
   Item_str_ascii_func(Item *a) :Item_str_func(a) {}
   Item_str_ascii_func(Item *a,Item *b) :Item_str_func(a,b) {}
   Item_str_ascii_func(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {}
-  String *val_str_convert_from_ascii(String *str, String *ascii_buf);
-  String *val_str(String *str);
+  String *val_str(String *str)
+  {
+    return val_str_from_val_str_ascii(str, &ascii_buf);
+  }
   virtual String *val_str_ascii(String *)= 0;
 };
 

=== modified file 'sql/item_timefunc.cc'
--- a/sql/item_timefunc.cc	2010-11-25 10:46:18 +0000
+++ b/sql/item_timefunc.cc	2011-02-18 08:10:30 +0000
@@ -1133,16 +1133,13 @@ String* Item_func_monthname::val_str(Str
 {
   DBUG_ASSERT(fixed == 1);
   const char *month_name;
-  uint month= (uint) val_int();
   uint err;
+  MYSQL_TIME ltime;
 
-  if (null_value || !month)
-  {
-    null_value=1;
-    return (String*) 0;
-  }
-  null_value=0;
-  month_name= locale->month_names->type_names[month-1];
+  if ((null_value= (get_arg0_date(&ltime, TIME_FUZZY_DATE) || !ltime.month)))
+    return (String *) 0;
+
+  month_name= locale->month_names->type_names[ltime.month - 1];
   str->copy(month_name, (uint) strlen(month_name), &my_charset_utf8_bin,
 	    collation.collation, &err);
   return str;
@@ -2205,8 +2202,6 @@ void Item_date_add_interval::fix_length_
   enum_field_types arg0_field_type;
 
   maybe_null=1;
-  fix_length_and_charset_datetime(MAX_DATETIME_FULL_WIDTH);
-  value.alloc(max_length);
 
   /*
     The field type for the result of an Item_date function is defined as
@@ -2231,6 +2226,21 @@ void Item_date_add_interval::fix_length_
     else
       cached_field_type= MYSQL_TYPE_DATETIME;
   }
+
+  if (cached_field_type == MYSQL_TYPE_STRING)
+  {
+    /* Behave as a usual string function when return type is VARCHAR. */
+    fix_length_and_charset(MAX_DATETIME_FULL_WIDTH, default_charset());
+  }
+  else
+  {
+    /*
+      Follow the "Number-to-string conversion" rules as in WorkLog 2649
+      when return type is DATE or DATETIME.
+    */
+    fix_length_and_charset_datetime(MAX_DATETIME_FULL_WIDTH);
+  }
+  value.alloc(max_length);
 }
 
 
@@ -2253,7 +2263,7 @@ bool Item_date_add_interval::get_date(MY
 }
 
 
-String *Item_date_add_interval::val_str(String *str)
+String *Item_date_add_interval::val_str_ascii(String *str)
 {
   DBUG_ASSERT(fixed == 1);
   MYSQL_TIME ltime;

=== modified file 'sql/item_timefunc.h'
--- a/sql/item_timefunc.h	2011-01-28 12:39:39 +0000
+++ b/sql/item_timefunc.h	2011-02-24 14:49:38 +0000
@@ -163,16 +163,19 @@ public:
 };
 
 
-class Item_func_monthname :public Item_func_month
+class Item_func_monthname :public Item_str_func
 {
   MY_LOCALE *locale;
 public:
-  Item_func_monthname(Item *a) :Item_func_month(a) {}
+  Item_func_monthname(Item *a) :Item_str_func(a) {}
   const char *func_name() const { return "monthname"; }
   String *val_str(String *str);
-  enum Item_result result_type () const { return STRING_RESULT; }
   void fix_length_and_dec();
   bool check_partition_func_processor(uchar *int_arg) {return TRUE;}
+  bool check_valid_arguments_processor(uchar *int_arg)
+  {
+    return !has_date_args();
+  }
 };
 
 
@@ -773,16 +776,32 @@ class Item_date_add_interval :public Ite
 {
   String value;
   enum_field_types cached_field_type;
-
+  String ascii_buf;
 public:
   const interval_type int_type; // keep it public
   const bool date_sub_interval; // keep it public
   Item_date_add_interval(Item *a,Item *b,interval_type type_arg,bool neg_arg)
     :Item_date_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {}
-  String *val_str(String *);
+  String *val_str_ascii(String *str);
+  String *val_str(String *str)
+  {
+    return val_str_from_val_str_ascii(str, &ascii_buf);
+  }
   const char *func_name() const { return "date_add_interval"; }
   void fix_length_and_dec();
   enum_field_types field_type() const { return cached_field_type; }
+  CHARSET_INFO *charset_for_protocol(void) const
+  {
+    /*
+      DATE_ADD() can return DATE, DATETIME or VARCHAR depending on arguments.
+      Send using "binary" when DATE or DATETIME,
+      or using collation.collation when VARCHAR
+      (which was fixed from @collation_connection in fix_length_and_dec).
+    */
+    DBUG_ASSERT(fixed == 1);
+    return cached_field_type == MYSQL_TYPE_STRING ?
+                                collation.collation : &my_charset_bin;
+  }
   longlong val_int();
   bool get_date(MYSQL_TIME *res, uint fuzzy_date);
   bool eq(const Item *item, bool binary_cmp) const;

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2011-02-04 04:59:55 +0000
+++ b/sql/mysqld.cc	2011-02-16 16:27:35 +0000
@@ -3028,7 +3028,6 @@ SHOW_VAR com_status_vars[]= {
   {"show_grants",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
   {"show_keys",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
   {"show_master_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
-  {"show_new_master",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS},
   {"show_open_tables",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
   {"show_plugins",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]), SHOW_LONG_STATUS},
   {"show_privileges",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS},

=== modified file 'sql/repl_failsafe.cc'
--- a/sql/repl_failsafe.cc	2010-10-11 14:50:14 +0000
+++ b/sql/repl_failsafe.cc	2011-02-16 16:27:35 +0000
@@ -56,10 +56,6 @@ const char* rpl_status_type[]=
   "RECOVERY_CAPTAIN","NULL",NullS
 };
 
-static Slave_log_event* find_slave_event(IO_CACHE* log,
-					 const char* log_file_name,
-					 char* errmsg);
-
 /*
   All of the functions defined in this file which are not used (the ones to
   handle failsafe) are not used; their code has not been updated for more than
@@ -91,13 +87,6 @@ void change_rpl_status(ulong from_status
 }\
 
 
-static inline int cmp_master_pos(Slave_log_event* sev, LEX_MASTER_INFO* mi)
-{
-  return cmp_master_pos(sev->master_log, sev->master_pos, mi->log_file_name,
-			mi->pos);
-}
-
-
 void unregister_slave(THD* thd, bool only_mine, bool need_mutex)
 {
   if (thd->server_id)
@@ -228,361 +217,6 @@ void end_slave_list()
   }
 }
 
-static int find_target_pos(LEX_MASTER_INFO *mi, IO_CACHE *log, char *errmsg)
-{
-  my_off_t log_pos =	    (my_off_t) mi->pos;
-  uint32 target_server_id = mi->server_id;
-
-  for (;;)
-  {
-    Log_event* ev;
-    if (!(ev= Log_event::read_log_event(log, (mysql_mutex_t*) 0, 0)))
-    {
-      if (log->error > 0)
-	strmov(errmsg, "Binary log truncated in the middle of event");
-      else if (log->error < 0)
-	strmov(errmsg, "I/O error reading binary log");
-      else
-	strmov(errmsg, "Could not find target event in the binary log");
-      return 1;
-    }
-
-    if (ev->log_pos >= log_pos && ev->server_id == target_server_id)
-    {
-      delete ev;
-      mi->pos = my_b_tell(log);
-      return 0;
-    }
-    delete ev;
-  }
-  /* Impossible */
-}
-
-/**
-  @details 
-  Before 4.0.15 we had a member of THD called log_pos, it was meant for
-  failsafe replication code in repl_failsafe.cc which is disabled until
-  it is reworked. Event's log_pos used to be preserved through 
-  log-slave-updates to make code in repl_failsafe.cc work (this 
-  function, SHOW NEW MASTER); but on the other side it caused unexpected
-  values in Exec_Master_Log_Pos in A->B->C replication setup, 
-  synchronization problems in master_pos_wait(), ... So we 
-  (Dmitri & Guilhem) removed it.
-  
-  So for now this function is broken. 
-*/
-
-int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg)
-{
-  LOG_INFO linfo;
-  char last_log_name[FN_REFLEN];
-  IO_CACHE log;
-  File file = -1, last_file = -1;
-  mysql_mutex_t *log_lock;
-  const char* errmsg_p;
-  Slave_log_event* sev = 0;
-  my_off_t last_pos = 0;
-  int error = 1;
-  int cmp_res;
-  LINT_INIT(cmp_res);
-  DBUG_ENTER("translate_master");
-
-  if (!mysql_bin_log.is_open())
-  {
-    strmov(errmsg,"Binary log is not open");
-    DBUG_RETURN(1);
-  }
-
-  if (!server_id_supplied)
-  {
-    strmov(errmsg, "Misconfigured master - server id was not set");
-    DBUG_RETURN(1);
-  }
-
-  if (mysql_bin_log.find_log_pos(&linfo, NullS, 1))
-  {
-    strmov(errmsg,"Could not find first log");
-    DBUG_RETURN(1);
-  }
-  thd->current_linfo = &linfo;
-
-  bzero((char*) &log,sizeof(log));
-  log_lock = mysql_bin_log.get_log_lock();
-  mysql_mutex_lock(log_lock);
-
-  for (;;)
-  {
-    if ((file=open_binlog(&log, linfo.log_file_name, &errmsg_p)) < 0)
-    {
-      strmov(errmsg, errmsg_p);
-      goto err;
-    }
-
-    if (!(sev = find_slave_event(&log, linfo.log_file_name, errmsg)))
-      goto err;
-
-    cmp_res = cmp_master_pos(sev, mi);
-    delete sev;
-
-    if (!cmp_res)
-    {
-      /* Copy basename */
-      fn_format(mi->log_file_name, linfo.log_file_name, "","",1);
-      mi->pos = my_b_tell(&log);
-      goto mi_inited;
-    }
-    else if (cmp_res > 0)
-    {
-      if (!last_pos)
-      {
-	strmov(errmsg,
-	       "Slave event in first log points past the target position");
-	goto err;
-      }
-      end_io_cache(&log);
-      mysql_file_close(file, MYF(MY_WME));
-      if (init_io_cache(&log, (file = last_file), IO_SIZE, READ_CACHE, 0, 0,
-			MYF(MY_WME)))
-      {
-	errmsg[0] = 0;
-	goto err;
-      }
-      break;
-    }
-
-    strmov(last_log_name, linfo.log_file_name);
-    last_pos = my_b_tell(&log);
-
-    switch (mysql_bin_log.find_next_log(&linfo, 1)) {
-    case LOG_INFO_EOF:
-      if (last_file >= 0)
-       mysql_file_close(last_file, MYF(MY_WME));
-      last_file = -1;
-      goto found_log;
-    case 0:
-      break;
-    default:
-      strmov(errmsg, "Error reading log index");
-      goto err;
-    }
-
-    end_io_cache(&log);
-    if (last_file >= 0)
-      mysql_file_close(last_file, MYF(MY_WME));
-    last_file = file;
-  }
-
-found_log:
-  my_b_seek(&log, last_pos);
-  if (find_target_pos(mi,&log,errmsg))
-    goto err;
-  fn_format(mi->log_file_name, last_log_name, "","",1);  /* Copy basename */
-
-mi_inited:
-  error = 0;
-err:
-  mysql_mutex_unlock(log_lock);
-  end_io_cache(&log);
-  mysql_mutex_lock(&LOCK_thread_count);
-  thd->current_linfo = 0;
-  mysql_mutex_unlock(&LOCK_thread_count);
-  if (file >= 0)
-    mysql_file_close(file, MYF(MY_WME));
-  if (last_file >= 0 && last_file != file)
-    mysql_file_close(last_file, MYF(MY_WME));
-
-  DBUG_RETURN(error);
-}
-
-
-/**
-  Caller must delete result when done.
-*/
-
-static Slave_log_event* find_slave_event(IO_CACHE* log,
-					 const char* log_file_name,
-					 char* errmsg)
-{
-  Log_event* ev;
-  int i;
-  bool slave_event_found = 0;
-  LINT_INIT(ev);
-
-  for (i = 0; i < 2; i++)
-  {
-    if (!(ev= Log_event::read_log_event(log, (mysql_mutex_t*)0, 0)))
-    {
-      my_snprintf(errmsg, SLAVE_ERRMSG_SIZE,
-		  "Error reading event in log '%s'",
-		  (char*)log_file_name);
-      return 0;
-    }
-    if (ev->get_type_code() == SLAVE_EVENT)
-    {
-      slave_event_found = 1;
-      break;
-    }
-    delete ev;
-  }
-  if (!slave_event_found)
-  {
-    my_snprintf(errmsg, SLAVE_ERRMSG_SIZE,
-		"Could not find slave event in log '%s'",
-		(char*)log_file_name);
-    return 0;
-  }
-
-  return (Slave_log_event*)ev;
-}
-
-/**
-  This function is broken now. 
-
-  @seealso translate_master()
-*/
-
-bool show_new_master(THD* thd)
-{
-  Protocol *protocol= thd->protocol;
-  DBUG_ENTER("show_new_master");
-  List<Item> field_list;
-  char errmsg[SLAVE_ERRMSG_SIZE];
-  LEX_MASTER_INFO* lex_mi= &thd->lex->mi;
-
-  errmsg[0]=0;					// Safety
-  if (translate_master(thd, lex_mi, errmsg))
-  {
-    if (errmsg[0])
-      my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
-               "SHOW NEW MASTER", errmsg);
-    DBUG_RETURN(TRUE);
-  }
-  else
-  {
-    field_list.push_back(new Item_empty_string("Log_name", 20));
-    field_list.push_back(new Item_return_int("Log_pos", 10,
-					     MYSQL_TYPE_LONGLONG));
-    if (protocol->send_result_set_metadata(&field_list,
-                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
-      DBUG_RETURN(TRUE);
-    protocol->prepare_for_resend();
-    protocol->store(lex_mi->log_file_name, &my_charset_bin);
-    protocol->store((ulonglong) lex_mi->pos);
-    if (protocol->write())
-      DBUG_RETURN(TRUE);
-    my_eof(thd);
-    DBUG_RETURN(FALSE);
-  }
-}
-
-/**
-  Asks the master for the list of its other connected slaves.
-
-  This is for failsafe replication:
-  in order for failsafe replication to work, the servers involved in
-  replication must know of each other. We accomplish this by having each
-  slave report to the master how to reach it, and on connection, each
-  slave receives information about where the other slaves are.
-
-  @param mysql           pre-existing connection to the master
-  @param mi              master info
-
-  @note
-    mi is used only to give detailed error messages which include the
-    hostname/port of the master, the username used by the slave to connect to
-    the master.
-    If the user used by the slave to connect to the master does not have the
-    REPLICATION SLAVE privilege, it will pop in this function because
-    SHOW SLAVE HOSTS will fail on the master.
-
-  @retval
-    1           error
-  @retval
-    0           success
-*/
-
-int update_slave_list(MYSQL* mysql, Master_info* mi)
-{
-  MYSQL_RES* res=0;
-  MYSQL_ROW row;
-  const char* error=0;
-  bool have_auth_info;
-  int port_ind;
-  DBUG_ENTER("update_slave_list");
-
-  if (mysql_real_query(mysql, STRING_WITH_LEN("SHOW SLAVE HOSTS")) ||
-      !(res = mysql_store_result(mysql)))
-  {
-    error= mysql_error(mysql);
-    goto err;
-  }
-
-  switch (mysql_num_fields(res)) {
-  case 5:
-    have_auth_info = 0;
-    port_ind=2;
-    break;
-  case 7:
-    have_auth_info = 1;
-    port_ind=4;
-    break;
-  default:
-    error= "the master returned an invalid number of fields for SHOW SLAVE \
-HOSTS";
-    goto err;
-  }
-
-  mysql_mutex_lock(&LOCK_slave_list);
-
-  while ((row= mysql_fetch_row(res)))
-  {
-    uint32 log_server_id;
-    SLAVE_INFO* si, *old_si;
-    log_server_id = atoi(row[0]);
-    if ((old_si= (SLAVE_INFO*)my_hash_search(&slave_list,
-                                             (uchar*)&log_server_id,4)))
-      si = old_si;
-    else
-    {
-      if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME))))
-      {
-	error= "the slave is out of memory";
-        mysql_mutex_unlock(&LOCK_slave_list);
-	goto err;
-      }
-      si->server_id = log_server_id;
-      if (my_hash_insert(&slave_list, (uchar*)si))
-      {
-        error= "the slave is out of memory";
-        mysql_mutex_unlock(&LOCK_slave_list);
-        goto err;
-      }
-    }
-    strmake(si->host, row[1], sizeof(si->host)-1);
-    si->port = atoi(row[port_ind]);
-    si->rpl_recovery_rank = atoi(row[port_ind+1]);
-    si->master_id = atoi(row[port_ind+2]);
-    if (have_auth_info)
-    {
-      strmake(si->user, row[2], sizeof(si->user)-1);
-      strmake(si->password, row[3], sizeof(si->password)-1);
-    }
-  }
-  mysql_mutex_unlock(&LOCK_slave_list);
-
-err:
-  if (res)
-    mysql_free_result(res);
-  if (error)
-  {
-    sql_print_error("While trying to obtain the list of slaves from the master "
-                    "'%s:%d', user '%s' got the following error: '%s'", 
-                    mi->host, mi->port, mi->user, error);
-    DBUG_RETURN(1);
-  }
-  DBUG_RETURN(0);
-}
-
 
 /**
   Execute a SHOW SLAVE HOSTS statement.

=== modified file 'sql/repl_failsafe.h'
--- a/sql/repl_failsafe.h	2010-10-11 14:50:14 +0000
+++ b/sql/repl_failsafe.h	2011-02-16 16:27:35 +0000
@@ -33,19 +33,12 @@ extern mysql_cond_t COND_rpl_status;
 extern TYPELIB rpl_role_typelib;
 extern const char* rpl_role_type[], *rpl_status_type[];
 
-pthread_handler_t handle_failsafe_rpl(void *arg);
 void change_rpl_status(ulong from_status, ulong to_status);
 int find_recovery_captain(THD* thd, MYSQL* mysql);
-int update_slave_list(MYSQL* mysql, Master_info* mi);
 
 extern HASH slave_list;
 
-bool load_master_data(THD* thd);
-int connect_to_master(THD *thd, MYSQL* mysql, Master_info* mi);
-
-bool show_new_master(THD* thd);
 bool show_slave_hosts(THD* thd);
-int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg);
 void init_slave_list();
 void end_slave_list();
 int register_slave(THD* thd, uchar* packet, uint packet_length);

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2011-02-02 18:13:28 +0000
+++ b/sql/set_var.cc	2011-02-18 13:24:03 +0000
@@ -776,7 +776,7 @@ int set_var_password::update(THD *thd)
 int set_var_collation_client::check(THD *thd)
 {
   /* Currently, UCS-2 cannot be used as a client character set */
-  if (character_set_client->mbminlen > 1)
+  if (!is_supported_parser_charset(character_set_client))
   {
     my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
              character_set_client->csname);

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	2011-02-02 11:54:49 +0000
+++ b/sql/share/errmsg-utf8.txt	2011-02-21 15:49:03 +0000
@@ -6394,3 +6394,6 @@ ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MA
 
 ER_STMT_CACHE_FULL  
         eng "Multi-row statements required more than 'max_binlog_stmt_cache_size' bytes of storage; increase this mysqld variable and try again"
+
+ER_MULTI_UPDATE_KEY_CONFLICT
+  eng "Primary key/partition key update is not allowed since the table is updated both as '%-.192s' and '%-.192s'."

=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc	2010-12-17 11:11:34 +0000
+++ b/sql/sp_head.cc	2011-02-16 16:27:35 +0000
@@ -237,7 +237,6 @@ sp_get_flags_for_command(LEX *lex)
   case SQLCOM_SHOW_EVENTS:
   case SQLCOM_SHOW_KEYS:
   case SQLCOM_SHOW_MASTER_STAT:
-  case SQLCOM_SHOW_NEW_MASTER:
   case SQLCOM_SHOW_OPEN_TABLES:
   case SQLCOM_SHOW_PRIVILEGES:
   case SQLCOM_SHOW_PROCESSLIST:

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2011-01-14 15:48:11 +0000
+++ b/sql/sql_acl.cc	2011-02-18 09:46:55 +0000
@@ -7799,7 +7799,8 @@ public:
   Thd_charset_adapter(THD *thd_arg) : thd (thd_arg) {} 
   bool init_client_charset(uint cs_number)
   {
-    thd_init_client_charset(thd, cs_number);
+    if (thd_init_client_charset(thd, cs_number))
+      return true;
     thd->update_charset();
     return thd->is_error();
   }
@@ -8929,9 +8930,8 @@ server_mpvio_initialize(THD *thd, MPVIO_
   mpvio->auth_info.host_or_ip= thd->security_ctx->host_or_ip;
   mpvio->auth_info.host_or_ip_length= 
     (unsigned int) strlen(thd->security_ctx->host_or_ip);
-  mpvio->auth_info.user_name= thd->security_ctx->user;
-  mpvio->auth_info.user_name_length= thd->security_ctx->user ? 
-    (unsigned int) strlen(thd->security_ctx->user) : 0;
+  mpvio->auth_info.user_name= NULL;
+  mpvio->auth_info.user_name_length= 0;
   mpvio->connect_errors= connect_errors;
   mpvio->status= MPVIO_EXT::FAILURE;
 

=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc	2010-12-15 22:59:21 +0000
+++ b/sql/sql_connect.cc	2011-02-18 13:24:03 +0000
@@ -370,8 +370,23 @@ void reset_mqh(LEX_USER *lu, bool get_th
 }
 
 
-void thd_init_client_charset(THD *thd, uint cs_number)
+/**
+  Set thread character set variables from the given ID
+
+  @param  thd         thread handle
+  @param  cs_number   character set and collation ID
+
+  @retval  0  OK; character_set_client, collation_connection and
+              character_set_results are set to the new value,
+              or to the default global values.
+
+  @retval  1  error, e.g. the given ID is not supported by parser.
+              Corresponding SQL error is sent.
+*/
+
+bool thd_init_client_charset(THD *thd, uint cs_number)
 {
+  CHARSET_INFO *cs;
   /*
    Use server character set and collation if
    - opt_character_set_client_handshake is not set
@@ -380,10 +395,10 @@ void thd_init_client_charset(THD *thd, u
    - client character set doesn't exists in server
   */
   if (!opt_character_set_client_handshake ||
-      !(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
+      !(cs= get_charset(cs_number, MYF(0))) ||
       !my_strcasecmp(&my_charset_latin1,
                      global_system_variables.character_set_client->name,
-                     thd->variables.character_set_client->name))
+                     cs->name))
   {
     thd->variables.character_set_client=
       global_system_variables.character_set_client;
@@ -394,10 +409,18 @@ void thd_init_client_charset(THD *thd, u
   }
   else
   {
+    if (!is_supported_parser_charset(cs))
+    {
+      /* Disallow non-supported parser character sets: UCS2, UTF16, UTF32 */
+      my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
+               cs->csname);
+      return true;
+    }    
     thd->variables.character_set_results=
       thd->variables.collation_connection= 
-      thd->variables.character_set_client;
+      thd->variables.character_set_client= cs;
   }
+  return false;
 }
 
 

=== modified file 'sql/sql_connect.h'
--- a/sql/sql_connect.h	2010-09-20 14:17:32 +0000
+++ b/sql/sql_connect.h	2011-02-18 09:46:55 +0000
@@ -33,7 +33,7 @@ void reset_mqh(LEX_USER *lu, bool get_th
 bool check_mqh(THD *thd, uint check_command);
 void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
 void decrease_user_connections(USER_CONN *uc);
-void thd_init_client_charset(THD *thd, uint cs_number);
+bool thd_init_client_charset(THD *thd, uint cs_number);
 bool setup_connection_thread_globals(THD *thd);
 
 int check_user(THD *thd, enum enum_server_command command,

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2011-01-26 07:35:18 +0000
+++ b/sql/sql_lex.h	2011-02-24 14:49:38 +0000
@@ -162,7 +162,7 @@ enum enum_sql_command {
   SQLCOM_SHOW_OPEN_TABLES,
   SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
   SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI,
-  SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
+  SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_DO,
   SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
   SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES,
   SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER,
@@ -269,8 +269,7 @@ typedef struct st_lex_server_options
 
 
 /**
-  Structure to hold parameters for CHANGE MASTER or START/STOP SLAVE
-  or SHOW NEW MASTER.
+  Structure to hold parameters for CHANGE MASTER, START SLAVE, and STOP SLAVE.
 
   Remark: this should not be confused with Master_info (and perhaps
   would better be renamed to st_lex_replication_info).  Some fields,

=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc	2011-01-12 09:31:32 +0000
+++ b/sql/sql_load.cc	2011-02-10 10:50:53 +0000
@@ -402,10 +402,9 @@ int mysql_load(THD *thd,sql_exchange *ex
 
     // if we are not in slave thread, the file must be:
     if (!thd->slave_thread &&
-	      !((stat_info.st_mode & S_IROTH) == S_IROTH &&  // readable by others
-	        (stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
-	        ((stat_info.st_mode & S_IFREG) == S_IFREG ||
-	         (stat_info.st_mode & S_IFIFO) == S_IFIFO)))
+        !((stat_info.st_mode & S_IFLNK) != S_IFLNK &&   // symlink
+          ((stat_info.st_mode & S_IFREG) == S_IFREG ||  // regular file
+           (stat_info.st_mode & S_IFIFO) == S_IFIFO)))  // named pipe
     {
 	    my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
 	    DBUG_RETURN(TRUE);

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2011-01-26 07:35:18 +0000
+++ b/sql/sql_parse.cc	2011-02-24 14:49:38 +0000
@@ -316,7 +316,6 @@ void init_update_queries(void)
   sql_command_flags[SQLCOM_SHOW_VARIABLES]=   CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
   sql_command_flags[SQLCOM_SHOW_CHARSETS]=    CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
   sql_command_flags[SQLCOM_SHOW_COLLATIONS]=  CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
-  sql_command_flags[SQLCOM_SHOW_NEW_MASTER]=  CF_STATUS_COMMAND;
   sql_command_flags[SQLCOM_SHOW_BINLOGS]=     CF_STATUS_COMMAND;
   sql_command_flags[SQLCOM_SHOW_SLAVE_HOSTS]= CF_STATUS_COMMAND;
   sql_command_flags[SQLCOM_SHOW_BINLOG_EVENTS]= CF_STATUS_COMMAND;
@@ -2145,19 +2144,6 @@ case SQLCOM_PREPARE:
 #endif
     break;
   }
-  case SQLCOM_SHOW_NEW_MASTER:
-  {
-    if (check_global_access(thd, REPL_SLAVE_ACL))
-      goto error;
-    /* This query don't work now. See comment in repl_failsafe.cc */
-#ifndef WORKING_NEW_MASTER
-    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "SHOW NEW MASTER");
-    goto error;
-#else
-    res = show_new_master(thd);
-    break;
-#endif
-  }
 
 #ifdef HAVE_REPLICATION
   case SQLCOM_SHOW_SLAVE_HOSTS:

=== modified file 'sql/sql_parse.h'
--- a/sql/sql_parse.h	2010-08-31 09:59:51 +0000
+++ b/sql/sql_parse.h	2011-02-18 09:46:55 +0000
@@ -197,4 +197,10 @@ check_table_access(THD *thd, ulong requi
 
 bool check_global_access(THD *thd, ulong want_access);
 
+inline bool is_supported_parser_charset(CHARSET_INFO *cs)
+{
+  return test(cs->mbminlen == 1);
+}
+
+
 #endif /* SQL_PARSE_INCLUDED */

=== modified file 'sql/sql_repl.cc'
--- a/sql/sql_repl.cc	2011-01-31 13:11:05 +0000
+++ b/sql/sql_repl.cc	2011-02-16 16:27:35 +0000
@@ -1694,23 +1694,6 @@ int reset_master(THD* thd)
   return 0;
 }
 
-int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
-		   const char* log_file_name2, ulonglong log_pos2)
-{
-  int res;
-  size_t log_file_name1_len=  strlen(log_file_name1);
-  size_t log_file_name2_len=  strlen(log_file_name2);
-
-  //  We assume that both log names match up to '.'
-  if (log_file_name1_len == log_file_name2_len)
-  {
-    if ((res= strcmp(log_file_name1, log_file_name2)))
-      return res;
-    return (log_pos1 < log_pos2) ? -1 : (log_pos1 == log_pos2) ? 0 : 1;
-  }
-  return ((log_file_name1_len < log_file_name2_len) ? -1 : 1);
-}
-
 
 /**
   Execute a SHOW BINLOG EVENTS statement.

=== modified file 'sql/sql_repl.h'
--- a/sql/sql_repl.h	2010-03-31 14:05:33 +0000
+++ b/sql/sql_repl.h	2011-02-16 16:27:35 +0000
@@ -43,8 +43,6 @@ int start_slave(THD* thd, Master_info* m
 int stop_slave(THD* thd, Master_info* mi, bool net_report);
 bool change_master(THD* thd, Master_info* mi);
 bool mysql_show_binlog_events(THD* thd);
-int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
-		   const char* log_file_name2, ulonglong log_pos2);
 int reset_slave(THD *thd, Master_info* mi);
 int reset_master(THD* thd);
 bool purge_master_logs(THD* thd, const char* to_log);

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-02-08 15:47:33 +0000
+++ b/sql/sql_select.cc	2011-02-24 14:49:38 +0000
@@ -307,61 +307,65 @@ bool handle_select(THD *thd, LEX *lex, s
 }
 
 
-/*
+/**
   Fix fields referenced from inner selects.
 
-  SYNOPSIS
-    fix_inner_refs()
-    thd               Thread handle
-    all_fields        List of all fields used in select
-    select            Current select
-    ref_pointer_array Array of references to Items used in current select
-    group_list        GROUP BY list (is NULL by default)
-
-  DESCRIPTION
-    The function serves 3 purposes - adds fields referenced from inner
-    selects to the current select list, resolves which class to use
-    to access referenced item (Item_ref of Item_direct_ref) and fixes
-    references (Item_ref objects) to these fields.
+  @param thd               Thread handle
+  @param all_fields        List of all fields used in select
+  @param select            Current select
+  @param ref_pointer_array Array of references to Items used in current select
+  @param group_list        GROUP BY list (is NULL by default)
+
+  @details
+    The function serves 3 purposes
+
+    - adds fields referenced from inner query blocks to the current select list
+
+    - Decides which class to use to reference the items (Item_ref or
+      Item_direct_ref)
+
+    - fixes references (Item_ref objects) to these fields.
 
-    If a field isn't already in the select list and the ref_pointer_array
+    If a field isn't already on the select list and the ref_pointer_array
     is provided then it is added to the all_fields list and the pointer to
     it is saved in the ref_pointer_array.
 
     The class to access the outer field is determined by the following rules:
-    1. If the outer field isn't used under an aggregate function
-      then the Item_ref class should be used.
-    2. If the outer field is used under an aggregate function and this
-      function is aggregated in the select where the outer field was
-      resolved or in some more inner select then the Item_direct_ref
-      class should be used.
-      Also it should be used if we are grouping by a subquery containing
-      the outer field.
+
+    -#. If the outer field isn't used under an aggregate function then the
+        Item_ref class should be used.
+
+    -#. If the outer field is used under an aggregate function and this
+        function is, in turn, aggregated in the query block where the outer
+        field was resolved or some query nested therein, then the
+        Item_direct_ref class should be used. Also it should be used if we are
+        grouping by a subquery containing the outer field.
+
     The resolution is done here and not at the fix_fields() stage as
-    it can be done only after sum functions are fixed and pulled up to
-    selects where they are have to be aggregated.
+    it can be done only after aggregate functions are fixed and pulled up to
+    selects where they are to be aggregated.
+
     When the class is chosen it substitutes the original field in the
     Item_outer_ref object.
 
     After this we proceed with fixing references (Item_outer_ref objects) to
     this field from inner subqueries.
 
-  RETURN
-    TRUE  an error occured
-    FALSE ok
-*/
+  @return Status
+  @retval true An error occured.
+  @retval false OK.
+ */
 
 bool
 fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
                  Item **ref_pointer_array, ORDER *group_list)
 {
   Item_outer_ref *ref;
-  bool res= FALSE;
-  bool direct_ref= FALSE;
 
   List_iterator<Item_outer_ref> ref_it(select->inner_refs_list);
   while ((ref= ref_it++))
   {
+    bool direct_ref= false;
     Item *item= ref->outer_ref;
     Item **item_ref= ref->ref;
     Item_ref *new_ref;
@@ -433,7 +437,7 @@ fix_inner_refs(THD *thd, List<Item> &all
       return TRUE;
     thd->used_tables|= item->used_tables();
   }
-  return res;
+  return false;
 }
 
 /**

=== modified file 'sql/sql_string.h'
--- a/sql/sql_string.h	2011-01-13 08:07:21 +0000
+++ b/sql/sql_string.h	2011-02-17 11:53:09 +0000
@@ -113,6 +113,9 @@ public:
   inline const char *ptr() const { return Ptr; }
   inline char *c_ptr()
   {
+    DBUG_ASSERT(!alloced || !Ptr || !Alloced_length || 
+                (Alloced_length >= (str_length + 1)));
+
     if (!Ptr || Ptr[str_length])		/* Should be safe */
       (void) realloc(str_length);
     return Ptr;

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2010-12-29 00:26:31 +0000
+++ b/sql/sql_update.cc	2011-02-21 15:49:03 +0000
@@ -998,6 +998,98 @@ static table_map get_table_map(List<Item
   return map;
 }
 
+/**
+  If one row is updated through two different aliases and the first
+  update physically moves the row, the second update will error
+  because the row is no longer located where expected. This function
+  checks if the multiple-table update is about to do that and if so
+  returns with an error.
+
+  The following update operations physically moves rows:
+    1) Update of a column in a clustered primary key
+    2) Update of a column used to calculate which partition the row belongs to
+
+  This function returns with an error if both of the following are
+  true:
+
+    a) A table in the multiple-table update statement is updated
+       through multiple aliases (including views)
+    b) At least one of the updates on the table from a) may physically
+       moves the row. Note: Updating a column used to calculate which
+       partition a row belongs to does not necessarily mean that the
+       row is moved. The new value may or may not belong to the same
+       partition.
+
+  @param leaves               First leaf table
+  @param tables_for_update    Map of tables that are updated
+
+  @return
+    true   if the update is unsafe, in which case an error message is also set,
+    false  otherwise.
+*/
+static
+bool unsafe_key_update(TABLE_LIST *leaves, table_map tables_for_update)
+{
+  TABLE_LIST *tl= leaves;
+
+  for (tl= leaves; tl ; tl= tl->next_leaf)
+  {
+    if (tl->table->map & tables_for_update)
+    {
+      TABLE *table1= tl->table;
+      bool primkey_clustered= (table1->file->primary_key_is_clustered() &&
+                               table1->s->primary_key != MAX_KEY);
+
+      bool table_partitioned= false;
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+      table_partitioned= (table1->part_info != NULL);
+#endif
+
+      if (!table_partitioned && !primkey_clustered)
+        continue;
+
+      for (TABLE_LIST* tl2= tl->next_leaf; tl2 ; tl2= tl2->next_leaf)
+      {
+        /*
+          Look at "next" tables only since all previous tables have
+          already been checked
+        */
+        TABLE *table2= tl2->table;
+        if (table2->map & tables_for_update && table1->s == table2->s)
+        {
+          // A table is updated through two aliases
+          if (table_partitioned &&
+              (partition_key_modified(table1, table1->write_set) ||
+               partition_key_modified(table2, table2->write_set)))
+          {
+            // Partitioned key is updated
+            my_error(ER_MULTI_UPDATE_KEY_CONFLICT, MYF(0),
+                     tl->belong_to_view ? tl->belong_to_view->alias
+                                        : tl->alias,
+                     tl2->belong_to_view ? tl2->belong_to_view->alias
+                                         : tl2->alias);
+            return true;
+          }
+
+          if (primkey_clustered &&
+              (bitmap_is_set(table1->write_set, table1->s->primary_key) ||
+               bitmap_is_set(table2->write_set, table2->s->primary_key)))
+          {
+            // Clustered primary key is updated
+            my_error(ER_MULTI_UPDATE_KEY_CONFLICT, MYF(0),
+                     tl->belong_to_view ? tl->belong_to_view->alias
+                                        : tl->alias,
+                     tl2->belong_to_view ? tl2->belong_to_view->alias
+                                         : tl2->alias);
+            return true;
+          }
+        }
+      }
+    }
+  }
+  return false;
+}
+
 
 /*
   make update specific preparation and checks after opening tables
@@ -1077,10 +1169,14 @@ int mysql_multi_update_prepare(THD *thd)
 
   thd->table_map_for_update= tables_for_update= get_table_map(fields);
 
+  leaves= lex->select_lex.leaf_tables;
+
+  if (unsafe_key_update(leaves, tables_for_update))
+    DBUG_RETURN(true);
+
   /*
     Setup timestamp handling and locking mode
   */
-  leaves= lex->select_lex.leaf_tables;
   for (tl= leaves; tl; tl= tl->next_leaf)
   {
     TABLE *table= tl->table;

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2011-01-10 12:43:12 +0000
+++ b/sql/sql_yacc.yy	2011-02-16 16:27:35 +0000
@@ -10921,19 +10921,6 @@ show_param:
             if (prepare_schema_table(YYTHD, lex, $4, SCH_COLUMNS))
               MYSQL_YYABORT;
           }
-        | NEW_SYM MASTER_SYM FOR_SYM SLAVE
-          WITH MASTER_LOG_FILE_SYM EQ
-          TEXT_STRING_sys /* $8 */
-          AND_SYM MASTER_LOG_POS_SYM EQ
-          ulonglong_num /* $12 */
-          AND_SYM MASTER_SERVER_ID_SYM EQ
-          ulong_num /* $16 */
-          {
-            Lex->sql_command = SQLCOM_SHOW_NEW_MASTER;
-            Lex->mi.log_file_name = $8.str;
-            Lex->mi.pos = $12;
-            Lex->mi.server_id = $16;
-          }
         | master_or_binary LOGS_SYM
           {
             Lex->sql_command = SQLCOM_SHOW_BINLOGS;

=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc	2011-02-02 18:13:28 +0000
+++ b/sql/sys_vars.cc	2011-02-17 11:53:09 +0000
@@ -3082,7 +3082,7 @@ static bool check_locale(sys_var *self,
     String str(buff, sizeof(buff), system_charset_info), *res;
     if (!(res=var->value->val_str(&str)))
       return true;
-    else if (!(locale= my_locale_by_name(res->c_ptr())))
+    else if (!(locale= my_locale_by_name(res->c_ptr_safe())))
     {
       ErrConvString err(res);
       my_error(ER_UNKNOWN_LOCALE, MYF(0), err.ptr());

=== modified file 'sql/transaction.cc'
--- a/sql/transaction.cc	2010-11-11 17:11:05 +0000
+++ b/sql/transaction.cc	2011-02-14 13:16:31 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008 Sun/MySQL
+/* Copyright (c) 2000, 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
@@ -635,8 +635,9 @@ bool trans_xa_commit(THD *thd)
 
   if (xa_trans_rolled_back(&thd->transaction.xid_state))
   {
-    if ((res= test(ha_rollback_trans(thd, TRUE))))
+    if (ha_rollback_trans(thd, TRUE))
       my_error(ER_XAER_RMERR, MYF(0));
+    res= thd->is_error();
   }
   else if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
   {

=== modified file 'storage/innobase/CMakeLists.txt'
--- a/storage/innobase/CMakeLists.txt	2010-12-02 10:04:10 +0000
+++ b/storage/innobase/CMakeLists.txt	2011-02-22 05:04:08 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 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
@@ -246,7 +246,7 @@ SET(INNOBASE_SOURCES	btr/btr0btr.c btr/b
 			trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
 			usr/usr0sess.c
 			ut/ut0byte.c ut/ut0dbg.c ut/ut0list.c ut/ut0mem.c ut/ut0rbt.c ut/ut0rnd.c
-			ut/ut0ut.c ut/ut0vec.c ut/ut0wqueue.c)
+			ut/ut0ut.c ut/ut0vec.c ut/ut0wqueue.c ut/ut0bh.c)
 
 IF(WITH_INNODB)
   # Legacy option

=== modified file 'storage/innobase/btr/btr0btr.c'
--- a/storage/innobase/btr/btr0btr.c	2011-01-25 08:51:13 +0000
+++ b/storage/innobase/btr/btr0btr.c	2011-02-08 11:39:24 +0000
@@ -42,6 +42,560 @@ Created 6/2/1994 Heikki Tuuri
 #include "ibuf0ibuf.h"
 #include "trx0trx.h"
 
+#ifdef UNIV_BLOB_DEBUG
+# include "srv0srv.h"
+# include "ut0rbt.h"
+
+/** TRUE when messages about index->blobs modification are enabled. */
+static ibool btr_blob_dbg_msg;
+
+/** Issue a message about an operation on index->blobs.
+@param op	operation
+@param b	the entry being subjected to the operation
+@param ctx	the context of the operation */
+#define btr_blob_dbg_msg_issue(op, b, ctx)			\
+	fprintf(stderr, op " %u:%u:%u->%u %s(%u,%u,%u)\n",	\
+		(b)->ref_page_no, (b)->ref_heap_no,		\
+		(b)->ref_field_no, (b)->blob_page_no, ctx,	\
+		(b)->owner, (b)->always_owner, (b)->del)
+
+/** Insert to index->blobs a reference to an off-page column.
+@param index	the index tree
+@param b	the reference
+@param ctx	context (for logging) */
+UNIV_INTERN
+void
+btr_blob_dbg_rbt_insert(
+/*====================*/
+	dict_index_t*		index,	/*!< in/out: index tree */
+	const btr_blob_dbg_t*	b,	/*!< in: the reference */
+	const char*		ctx)	/*!< in: context (for logging) */
+{
+	if (btr_blob_dbg_msg) {
+		btr_blob_dbg_msg_issue("insert", b, ctx);
+	}
+	mutex_enter(&index->blobs_mutex);
+	rbt_insert(index->blobs, b, b);
+	mutex_exit(&index->blobs_mutex);
+}
+
+/** Remove from index->blobs a reference to an off-page column.
+@param index	the index tree
+@param b	the reference
+@param ctx	context (for logging) */
+UNIV_INTERN
+void
+btr_blob_dbg_rbt_delete(
+/*====================*/
+	dict_index_t*		index,	/*!< in/out: index tree */
+	const btr_blob_dbg_t*	b,	/*!< in: the reference */
+	const char*		ctx)	/*!< in: context (for logging) */
+{
+	if (btr_blob_dbg_msg) {
+		btr_blob_dbg_msg_issue("delete", b, ctx);
+	}
+	mutex_enter(&index->blobs_mutex);
+	ut_a(rbt_delete(index->blobs, b));
+	mutex_exit(&index->blobs_mutex);
+}
+
+/**************************************************************//**
+Comparator for items (btr_blob_dbg_t) in index->blobs.
+The key in index->blobs is (ref_page_no, ref_heap_no, ref_field_no).
+@return negative, 0 or positive if *a<*b, *a=*b, *a>*b */
+static
+int
+btr_blob_dbg_cmp(
+/*=============*/
+	const void*	a,	/*!< in: first btr_blob_dbg_t to compare */
+	const void*	b)	/*!< in: second btr_blob_dbg_t to compare */
+{
+	const btr_blob_dbg_t*	aa	= a;
+	const btr_blob_dbg_t*	bb	= b;
+
+	ut_ad(aa != NULL);
+	ut_ad(bb != NULL);
+
+	if (aa->ref_page_no != bb->ref_page_no) {
+		return(aa->ref_page_no < bb->ref_page_no ? -1 : 1);
+	}
+	if (aa->ref_heap_no != bb->ref_heap_no) {
+		return(aa->ref_heap_no < bb->ref_heap_no ? -1 : 1);
+	}
+	if (aa->ref_field_no != bb->ref_field_no) {
+		return(aa->ref_field_no < bb->ref_field_no ? -1 : 1);
+	}
+	return(0);
+}
+
+/**************************************************************//**
+Add a reference to an off-page column to the index->blobs map. */
+UNIV_INTERN
+void
+btr_blob_dbg_add_blob(
+/*==================*/
+	const rec_t*	rec,		/*!< in: clustered index record */
+	ulint		field_no,	/*!< in: off-page column number */
+	ulint		page_no,	/*!< in: start page of the column */
+	dict_index_t*	index,		/*!< in/out: index tree */
+	const char*	ctx)		/*!< in: context (for logging) */
+{
+	btr_blob_dbg_t	b;
+	const page_t*	page	= page_align(rec);
+
+	ut_a(index->blobs);
+
+	b.blob_page_no = page_no;
+	b.ref_page_no = page_get_page_no(page);
+	b.ref_heap_no = page_rec_get_heap_no(rec);
+	b.ref_field_no = field_no;
+	ut_a(b.ref_field_no >= index->n_uniq);
+	b.always_owner = b.owner = TRUE;
+	b.del = FALSE;
+	ut_a(!rec_get_deleted_flag(rec, page_is_comp(page)));
+	btr_blob_dbg_rbt_insert(index, &b, ctx);
+}
+
+/**************************************************************//**
+Add to index->blobs any references to off-page columns from a record.
+@return number of references added */
+UNIV_INTERN
+ulint
+btr_blob_dbg_add_rec(
+/*=================*/
+	const rec_t*	rec,	/*!< in: record */
+	dict_index_t*	index,	/*!< in/out: index */
+	const ulint*	offsets,/*!< in: offsets */
+	const char*	ctx)	/*!< in: context (for logging) */
+{
+	ulint		count	= 0;
+	ulint		i;
+	btr_blob_dbg_t	b;
+	ibool		del;
+
+	ut_ad(rec_offs_validate(rec, index, offsets));
+
+	if (!rec_offs_any_extern(offsets)) {
+		return(0);
+	}
+
+	b.ref_page_no = page_get_page_no(page_align(rec));
+	b.ref_heap_no = page_rec_get_heap_no(rec);
+	del = (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) != 0);
+
+	for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+		if (rec_offs_nth_extern(offsets, i)) {
+			ulint		len;
+			const byte*	field_ref = rec_get_nth_field(
+				rec, offsets, i, &len);
+
+			ut_a(len != UNIV_SQL_NULL);
+			ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+			field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+			if (!memcmp(field_ref, field_ref_zero,
+				    BTR_EXTERN_FIELD_REF_SIZE)) {
+				/* the column has not been stored yet */
+				continue;
+			}
+
+			b.ref_field_no = i;
+			b.blob_page_no = mach_read_from_4(
+				field_ref + BTR_EXTERN_PAGE_NO);
+			ut_a(b.ref_field_no >= index->n_uniq);
+			b.always_owner = b.owner
+				= !(field_ref[BTR_EXTERN_LEN]
+				    & BTR_EXTERN_OWNER_FLAG);
+			b.del = del;
+
+			btr_blob_dbg_rbt_insert(index, &b, ctx);
+			count++;
+		}
+	}
+
+	return(count);
+}
+
+/**************************************************************//**
+Display the references to off-page columns.
+This function is to be called from a debugger,
+for example when a breakpoint on ut_dbg_assertion_failed is hit. */
+UNIV_INTERN
+void
+btr_blob_dbg_print(
+/*===============*/
+	const dict_index_t*	index)	/*!< in: index tree */
+{
+	const ib_rbt_node_t*	node;
+
+	if (!index->blobs) {
+		return;
+	}
+
+	/* We intentionally do not acquire index->blobs_mutex here.
+	This function is to be called from a debugger, and the caller
+	should make sure that the index->blobs_mutex is held. */
+
+	for (node = rbt_first(index->blobs);
+	     node != NULL; node = rbt_next(index->blobs, node)) {
+		const btr_blob_dbg_t*	b
+			= rbt_value(btr_blob_dbg_t, node);
+		fprintf(stderr, "%u:%u:%u->%u%s%s%s\n",
+			b->ref_page_no, b->ref_heap_no, b->ref_field_no,
+			b->blob_page_no,
+			b->owner ? "" : "(disowned)",
+			b->always_owner ? "" : "(has disowned)",
+			b->del ? "(deleted)" : "");
+	}
+}
+
+/**************************************************************//**
+Remove from index->blobs any references to off-page columns from a record.
+@return number of references removed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_remove_rec(
+/*====================*/
+	const rec_t*	rec,	/*!< in: record */
+	dict_index_t*	index,	/*!< in/out: index */
+	const ulint*	offsets,/*!< in: offsets */
+	const char*	ctx)	/*!< in: context (for logging) */
+{
+	ulint		i;
+	ulint		count	= 0;
+	btr_blob_dbg_t	b;
+
+	ut_ad(rec_offs_validate(rec, index, offsets));
+
+	if (!rec_offs_any_extern(offsets)) {
+		return(0);
+	}
+
+	b.ref_page_no = page_get_page_no(page_align(rec));
+	b.ref_heap_no = page_rec_get_heap_no(rec);
+
+	for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+		if (rec_offs_nth_extern(offsets, i)) {
+			ulint		len;
+			const byte*	field_ref = rec_get_nth_field(
+				rec, offsets, i, &len);
+
+			ut_a(len != UNIV_SQL_NULL);
+			ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+			field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+			b.ref_field_no = i;
+			b.blob_page_no = mach_read_from_4(
+				field_ref + BTR_EXTERN_PAGE_NO);
+
+			switch (b.blob_page_no) {
+			case 0:
+				/* The column has not been stored yet.
+				The BLOB pointer must be all zero.
+				There cannot be a BLOB starting at
+				page 0, because page 0 is reserved for
+				the tablespace header. */
+				ut_a(!memcmp(field_ref, field_ref_zero,
+					     BTR_EXTERN_FIELD_REF_SIZE));
+				/* fall through */
+			case FIL_NULL:
+				/* the column has been freed already */
+				continue;
+			}
+
+			btr_blob_dbg_rbt_delete(index, &b, ctx);
+			count++;
+		}
+	}
+
+	return(count);
+}
+
+/**************************************************************//**
+Check that there are no references to off-page columns from or to
+the given page. Invoked when freeing or clearing a page.
+@return TRUE when no orphan references exist */
+UNIV_INTERN
+ibool
+btr_blob_dbg_is_empty(
+/*==================*/
+	dict_index_t*	index,		/*!< in: index */
+	ulint		page_no)	/*!< in: page number */
+{
+	const ib_rbt_node_t*	node;
+	ibool			success	= TRUE;
+
+	if (!index->blobs) {
+		return(success);
+	}
+
+	mutex_enter(&index->blobs_mutex);
+
+	for (node = rbt_first(index->blobs);
+	     node != NULL; node = rbt_next(index->blobs, node)) {
+		const btr_blob_dbg_t*	b
+			= rbt_value(btr_blob_dbg_t, node);
+
+		if (b->ref_page_no != page_no && b->blob_page_no != page_no) {
+			continue;
+		}
+
+		fprintf(stderr,
+			"InnoDB: orphan BLOB ref%s%s%s %u:%u:%u->%u\n",
+			b->owner ? "" : "(disowned)",
+			b->always_owner ? "" : "(has disowned)",
+			b->del ? "(deleted)" : "",
+			b->ref_page_no, b->ref_heap_no, b->ref_field_no,
+			b->blob_page_no);
+
+		if (b->blob_page_no != page_no || b->owner || !b->del) {
+			success = FALSE;
+		}
+	}
+
+	mutex_exit(&index->blobs_mutex);
+	return(success);
+}
+
+/**************************************************************//**
+Count and process all references to off-page columns on a page.
+@return number of references processed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_op(
+/*============*/
+	const page_t*		page,	/*!< in: B-tree leaf page */
+	const rec_t*		rec,	/*!< in: record to start from
+					(NULL to process the whole page) */
+	dict_index_t*		index,	/*!< in/out: index */
+	const char*		ctx,	/*!< in: context (for logging) */
+	const btr_blob_dbg_op_f	op)	/*!< in: operation on records */
+{
+	ulint		count	= 0;
+	mem_heap_t*	heap	= NULL;
+	ulint		offsets_[REC_OFFS_NORMAL_SIZE];
+	ulint*		offsets	= offsets_;
+	rec_offs_init(offsets_);
+
+	ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
+	ut_a(!rec || page_align(rec) == page);
+
+	if (!index->blobs || !page_is_leaf(page)
+	    || !dict_index_is_clust(index)) {
+		return(0);
+	}
+
+	if (rec == NULL) {
+		rec = page_get_infimum_rec(page);
+	}
+
+	do {
+		offsets = rec_get_offsets(rec, index, offsets,
+					  ULINT_UNDEFINED, &heap);
+		count += op(rec, index, offsets, ctx);
+		rec = page_rec_get_next_const(rec);
+	} while (!page_rec_is_supremum(rec));
+
+	if (UNIV_LIKELY_NULL(heap)) {
+		mem_heap_free(heap);
+	}
+
+	return(count);
+}
+
+/**************************************************************//**
+Count and add to index->blobs any references to off-page columns
+from records on a page.
+@return number of references added */
+UNIV_INTERN
+ulint
+btr_blob_dbg_add(
+/*=============*/
+	const page_t*	page,	/*!< in: rewritten page */
+	dict_index_t*	index,	/*!< in/out: index */
+	const char*	ctx)	/*!< in: context (for logging) */
+{
+	btr_blob_dbg_assert_empty(index, page_get_page_no(page));
+
+	return(btr_blob_dbg_op(page, NULL, index, ctx, btr_blob_dbg_add_rec));
+}
+
+/**************************************************************//**
+Count and remove from index->blobs any references to off-page columns
+from records on a page.
+Used when reorganizing a page, before copying the records.
+@return number of references removed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_remove(
+/*================*/
+	const page_t*	page,	/*!< in: b-tree page */
+	dict_index_t*	index,	/*!< in/out: index */
+	const char*	ctx)	/*!< in: context (for logging) */
+{
+	ulint	count;
+
+	count = btr_blob_dbg_op(page, NULL, index, ctx,
+				btr_blob_dbg_remove_rec);
+
+	/* Check that no references exist. */
+	btr_blob_dbg_assert_empty(index, page_get_page_no(page));
+
+	return(count);
+}
+
+/**************************************************************//**
+Restore in index->blobs any references to off-page columns
+Used when page reorganize fails due to compressed page overflow. */
+UNIV_INTERN
+void
+btr_blob_dbg_restore(
+/*=================*/
+	const page_t*	npage,	/*!< in: page that failed to compress  */
+	const page_t*	page,	/*!< in: copy of original page */
+	dict_index_t*	index,	/*!< in/out: index */
+	const char*	ctx)	/*!< in: context (for logging) */
+{
+	ulint	removed;
+	ulint	added;
+
+	ut_a(page_get_page_no(npage) == page_get_page_no(page));
+	ut_a(page_get_space_id(npage) == page_get_space_id(page));
+
+	removed = btr_blob_dbg_remove(npage, index, ctx);
+	added = btr_blob_dbg_add(page, index, ctx);
+	ut_a(added == removed);
+}
+
+/**************************************************************//**
+Modify the 'deleted' flag of a record. */
+UNIV_INTERN
+void
+btr_blob_dbg_set_deleted_flag(
+/*==========================*/
+	const rec_t*		rec,	/*!< in: record */
+	dict_index_t*		index,	/*!< in/out: index */
+	const ulint*		offsets,/*!< in: rec_get_offs(rec, index) */
+	ibool			del)	/*!< in: TRUE=deleted, FALSE=exists */
+{
+	const ib_rbt_node_t*	node;
+	btr_blob_dbg_t		b;
+	btr_blob_dbg_t*		c;
+	ulint			i;
+
+	ut_ad(rec_offs_validate(rec, index, offsets));
+	ut_a(dict_index_is_clust(index));
+	ut_a(del == !!del);/* must be FALSE==0 or TRUE==1 */
+
+	if (!rec_offs_any_extern(offsets) || !index->blobs) {
+
+		return;
+	}
+
+	b.ref_page_no = page_get_page_no(page_align(rec));
+	b.ref_heap_no = page_rec_get_heap_no(rec);
+
+	for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+		if (rec_offs_nth_extern(offsets, i)) {
+			ulint		len;
+			const byte*	field_ref = rec_get_nth_field(
+				rec, offsets, i, &len);
+
+			ut_a(len != UNIV_SQL_NULL);
+			ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+			field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+			b.ref_field_no = i;
+			b.blob_page_no = mach_read_from_4(
+				field_ref + BTR_EXTERN_PAGE_NO);
+
+			switch (b.blob_page_no) {
+			case 0:
+				ut_a(memcmp(field_ref, field_ref_zero,
+					    BTR_EXTERN_FIELD_REF_SIZE));
+				/* page number 0 is for the
+				page allocation bitmap */
+			case FIL_NULL:
+				/* the column has been freed already */
+				ut_error;
+			}
+
+			mutex_enter(&index->blobs_mutex);
+			node = rbt_lookup(index->blobs, &b);
+			ut_a(node);
+
+			c = rbt_value(btr_blob_dbg_t, node);
+			/* The flag should be modified. */
+			c->del = del;
+			if (btr_blob_dbg_msg) {
+				b = *c;
+				mutex_exit(&index->blobs_mutex);
+				btr_blob_dbg_msg_issue("del_mk", &b, "");
+			} else {
+				mutex_exit(&index->blobs_mutex);
+			}
+		}
+	}
+}
+
+/**************************************************************//**
+Change the ownership of an off-page column. */
+UNIV_INTERN
+void
+btr_blob_dbg_owner(
+/*===============*/
+	const rec_t*		rec,	/*!< in: record */
+	dict_index_t*		index,	/*!< in/out: index */
+	const ulint*		offsets,/*!< in: rec_get_offs(rec, index) */
+	ulint			i,	/*!< in: ith field in rec */
+	ibool			own)	/*!< in: TRUE=owned, FALSE=disowned */
+{
+	const ib_rbt_node_t*	node;
+	btr_blob_dbg_t		b;
+	const byte*		field_ref;
+	ulint			len;
+
+	ut_ad(rec_offs_validate(rec, index, offsets));
+	ut_a(rec_offs_nth_extern(offsets, i));
+
+	field_ref = rec_get_nth_field(rec, offsets, i, &len);
+	ut_a(len != UNIV_SQL_NULL);
+	ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+	field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+	b.ref_page_no = page_get_page_no(page_align(rec));
+	b.ref_heap_no = page_rec_get_heap_no(rec);
+	b.ref_field_no = i;
+	b.owner = !(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG);
+	b.blob_page_no = mach_read_from_4(field_ref + BTR_EXTERN_PAGE_NO);
+
+	ut_a(b.owner == own);
+
+	mutex_enter(&index->blobs_mutex);
+	node = rbt_lookup(index->blobs, &b);
+	/* row_ins_clust_index_entry_by_modify() invokes
+	btr_cur_unmark_extern_fields() also for the newly inserted
+	references, which are all zero bytes until the columns are stored.
+	The node lookup must fail if and only if that is the case. */
+	ut_a(!memcmp(field_ref, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE)
+	     == !node);
+
+	if (node) {
+		btr_blob_dbg_t*	c = rbt_value(btr_blob_dbg_t, node);
+		/* Some code sets ownership from TRUE to TRUE.
+		We do not allow changing ownership from FALSE to FALSE. */
+		ut_a(own || c->owner);
+
+		c->owner = own;
+		if (!own) {
+			c->always_owner = FALSE;
+		}
+	}
+
+	mutex_exit(&index->blobs_mutex);
+}
+#endif /* UNIV_BLOB_DEBUG */
+
 /*
 Latching strategy of the InnoDB B-tree
 --------------------------------------
@@ -296,6 +850,7 @@ btr_page_create(
 	page_t*		page = buf_block_get_frame(block);
 
 	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+	btr_blob_dbg_assert_empty(index, buf_block_get_page_no(block));
 
 	if (UNIV_LIKELY_NULL(page_zip)) {
 		page_create_zip(block, index, level, mtr);
@@ -489,6 +1044,7 @@ btr_page_free_low(
 	modify clock */
 
 	buf_block_modify_clock_inc(block);
+	btr_blob_dbg_assert_empty(index, buf_block_get_page_no(block));
 
 	if (dict_index_is_ibuf(index)) {
 
@@ -774,6 +1330,14 @@ btr_create(
 		block = buf_page_get(space, zip_size, page_no,
 				     RW_X_LATCH, mtr);
 	} else {
+#ifdef UNIV_BLOB_DEBUG
+		if ((type & DICT_CLUSTERED) && !index->blobs) {
+			mutex_create(PFS_NOT_INSTRUMENTED,
+				     &index->blobs_mutex, SYNC_ANY_LATCH);
+			index->blobs = rbt_create(sizeof(btr_blob_dbg_t),
+						  btr_blob_dbg_cmp);
+		}
+#endif /* UNIV_BLOB_DEBUG */
 		block = fseg_create(space, 0,
 				    PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
 	}
@@ -998,6 +1562,7 @@ btr_page_reorganize_low(
 
 	block->check_index_page_at_flush = TRUE;
 #endif /* !UNIV_HOTBACKUP */
+	btr_blob_dbg_remove(page, index, "btr_page_reorganize");
 
 	/* Recreate the page: note that global data on page (possible
 	segment headers, next page-field, etc.) is preserved intact */
@@ -1026,6 +1591,8 @@ btr_page_reorganize_low(
 	    (!page_zip_compress(page_zip, page, index, NULL))) {
 
 		/* Restore the old page and exit. */
+		btr_blob_dbg_restore(page, temp_page, index,
+				     "btr_page_reorganize_compress_fail");
 
 #if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
 		/* Check that the bytes that we skip are identical. */
@@ -1159,6 +1726,7 @@ btr_page_empty(
 #endif /* UNIV_ZIP_DEBUG */
 
 	btr_search_drop_page_hash_index(block);
+	btr_blob_dbg_remove(page, index, "btr_page_empty");
 
 	/* Recreate the page: note that global data on page (possible
 	segment headers, next page-field, etc.) is preserved intact */
@@ -2499,6 +3067,7 @@ btr_lift_page_up(
 						       index);
 	}
 
+	btr_blob_dbg_remove(page, index, "btr_lift_page_up");
 	lock_update_copy_and_discard(father_block, block);
 
 	/* Go upward to root page, decrementing levels by one. */
@@ -2760,6 +3329,7 @@ err_exit:
 		lock_update_merge_right(merge_block, orig_succ, block);
 	}
 
+	btr_blob_dbg_remove(page, index, "btr_compress");
 	mem_heap_free(heap);
 
 	if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
@@ -2990,6 +3560,8 @@ btr_discard_page(
 				    block);
 	}
 
+	btr_blob_dbg_remove(page, index, "btr_discard_page");
+
 	/* Free the file page */
 	btr_page_free(index, block, mtr);
 

=== modified file 'storage/innobase/btr/btr0cur.c'
--- a/storage/innobase/btr/btr0cur.c	2011-02-02 13:58:01 +0000
+++ b/storage/innobase/btr/btr0cur.c	2011-02-08 11:39:24 +0000
@@ -2690,6 +2690,7 @@ btr_cur_del_mark_set_clust_rec(
 
 	page_zip = buf_block_get_page_zip(block);
 
+	btr_blob_dbg_set_deleted_flag(rec, index, offsets, val);
 	btr_rec_set_deleted_flag(rec, page_zip, val);
 
 	trx = thr_get_trx(thr);
@@ -3873,6 +3874,8 @@ btr_cur_set_ownership_of_extern_field(
 	} else {
 		mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
 	}
+
+	btr_blob_dbg_owner(rec, index, offsets, i, val);
 }
 
 /*******************************************************************//**
@@ -4373,6 +4376,11 @@ btr_store_big_rec_extern_fields_func(
 				}
 
 				if (prev_page_no == FIL_NULL) {
+					btr_blob_dbg_add_blob(
+						rec, big_rec_vec->fields[i]
+						.field_no, page_no, index,
+						"store");
+
 					mach_write_to_4(field_ref
 							+ BTR_EXTERN_SPACE_ID,
 							space_id);
@@ -4448,6 +4456,11 @@ next_zip_page:
 						 MLOG_4BYTES, &mtr);
 
 				if (prev_page_no == FIL_NULL) {
+					btr_blob_dbg_add_blob(
+						rec, big_rec_vec->fields[i]
+						.field_no, page_no, index,
+						"store");
+
 					mlog_write_ulint(field_ref
 							 + BTR_EXTERN_SPACE_ID,
 							 space_id,
@@ -4616,6 +4629,37 @@ btr_free_externally_stored_field(
 		rec_zip_size = 0;
 	}
 
+#ifdef UNIV_BLOB_DEBUG
+	if (!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG)
+	    && !((field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
+		 && (rb_ctx == RB_NORMAL || rb_ctx == RB_RECOVERY))) {
+		/* This off-page column will be freed.
+		Check that no references remain. */
+
+		btr_blob_dbg_t	b;
+
+		b.blob_page_no = mach_read_from_4(
+			field_ref + BTR_EXTERN_PAGE_NO);
+
+		if (rec) {
+			/* Remove the reference from the record to the
+			BLOB. If the BLOB were not freed, the
+			reference would be removed when the record is
+			removed. Freeing the BLOB will overwrite the
+			BTR_EXTERN_PAGE_NO in the field_ref of the
+			record with FIL_NULL, which would make the
+			btr_blob_dbg information inconsistent with the
+			record. */
+			b.ref_page_no = page_get_page_no(page_align(rec));
+			b.ref_heap_no = page_rec_get_heap_no(rec);
+			b.ref_field_no = i;
+			btr_blob_dbg_rbt_delete(index, &b, "free");
+		}
+
+		btr_blob_dbg_assert_empty(index, b.blob_page_no);
+	}
+#endif /* UNIV_BLOB_DEBUG */
+
 	for (;;) {
 #ifdef UNIV_SYNC_DEBUG
 		buf_block_t*	rec_block;

=== modified file 'storage/innobase/buf/buf0rea.c'
--- a/storage/innobase/buf/buf0rea.c	2010-08-16 12:50:27 +0000
+++ b/storage/innobase/buf/buf0rea.c	2011-02-10 12:07:58 +0000
@@ -530,7 +530,7 @@ buf_read_ibuf_merge_pages(
 		buf_pool_t*	buf_pool;
 		ulint		zip_size = fil_space_get_zip_size(space_ids[i]);
 
-		buf_pool = buf_pool_get(space_ids[i], space_versions[i]);
+		buf_pool = buf_pool_get(space_ids[i], page_nos[i]);
 
 		while (buf_pool->n_pend_reads
 		       > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {

=== modified file 'storage/innobase/dict/dict0load.c'
--- a/storage/innobase/dict/dict0load.c	2011-02-04 14:59:30 +0000
+++ b/storage/innobase/dict/dict0load.c	2011-02-10 08:58:23 +0000
@@ -1323,7 +1323,10 @@ ulint
 dict_load_indexes(
 /*==============*/
 	dict_table_t*	table,	/*!< in/out: table */
-	mem_heap_t*	heap)	/*!< in: memory heap for temporary storage */
+	mem_heap_t*	heap,	/*!< in: memory heap for temporary storage */
+	dict_err_ignore_t ignore_err)
+				/*!< in: error to be ignored when
+				loading the index definition */
 {
 	dict_table_t*	sys_indexes;
 	dict_index_t*	sys_index;
@@ -1406,10 +1409,22 @@ dict_load_indexes(
 				"InnoDB: but the index tree has been freed!\n",
 				index->name, table->name);
 
+			if (ignore_err & DICT_ERR_IGNORE_INDEX_ROOT) {
+				/* If caller can tolerate this error,
+				we will continue to load the index and
+				let caller deal with this error. However
+				mark the index and table corrupted */
+				index->corrupted = TRUE;
+				table->corrupted = TRUE;
+				fprintf(stderr,
+					"InnoDB: Index is corrupt but forcing"
+					" load into data dictionary\n");
+			} else {
 corrupted:
-			dict_mem_index_free(index);
-			error = DB_CORRUPTION;
-			goto func_exit;
+				dict_mem_index_free(index);
+				error = DB_CORRUPTION;
+				goto func_exit;
+			}
 		} else if (!dict_index_is_clust(index)
 			   && NULL == dict_table_get_first_index(table)) {
 
@@ -1618,7 +1633,10 @@ dict_load_table(
 /*============*/
 	const char*	name,	/*!< in: table name in the
 				databasename/tablename format */
-	ibool		cached)	/*!< in: TRUE=add to cache, FALSE=do not */
+	ibool		cached,	/*!< in: TRUE=add to cache, FALSE=do not */
+	dict_err_ignore_t ignore_err)
+				/*!< in: error to be ignored when loading
+				table and its indexes' definition */
 {
 	dict_table_t*	table;
 	dict_table_t*	sys_tables;
@@ -1733,7 +1751,7 @@ err_exit:
 
 	mem_heap_empty(heap);
 
-	err = dict_load_indexes(table, heap);
+	err = dict_load_indexes(table, heap, ignore_err);
 
 	/* Initialize table foreign_child value. Its value could be
 	changed when dict_load_foreigns() is called below */
@@ -1810,6 +1828,8 @@ dict_load_table_on_id(
 
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 
+	table = NULL;
+
 	/* NOTE that the operation of this function is protected by
 	the dictionary mutex, and therefore no deadlocks can occur
 	with other dictionary operations. */
@@ -1836,15 +1856,17 @@ dict_load_table_on_id(
 				  BTR_SEARCH_LEAF, &pcur, &mtr);
 	rec = btr_pcur_get_rec(&pcur);
 
-	if (!btr_pcur_is_on_user_rec(&pcur)
-	    || rec_get_deleted_flag(rec, 0)) {
+	if (!btr_pcur_is_on_user_rec(&pcur)) {
 		/* Not found */
+		goto func_exit;
+	}
 
-		btr_pcur_close(&pcur);
-		mtr_commit(&mtr);
-		mem_heap_free(heap);
-
-		return(NULL);
+	/* Find the first record that is not delete marked */
+	while (rec_get_deleted_flag(rec, 0)) {
+		if (!btr_pcur_move_to_next_user_rec(&pcur, &mtr)) {
+			goto func_exit;
+		}
+		rec = btr_pcur_get_rec(&pcur);
 	}
 
 	/*---------------------------------------------------*/
@@ -1857,20 +1879,15 @@ dict_load_table_on_id(
 
 	/* Check if the table id in record is the one searched for */
 	if (table_id != mach_read_from_8(field)) {
-
-		btr_pcur_close(&pcur);
-		mtr_commit(&mtr);
-		mem_heap_free(heap);
-
-		return(NULL);
+		goto func_exit;
 	}
 
 	/* Now we get the table name from the record */
 	field = rec_get_nth_field_old(rec, 1, &len);
 	/* Load the table definition to memory */
 	table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len),
-				TRUE);
-
+				TRUE, DICT_ERR_IGNORE_NONE);
+func_exit:
 	btr_pcur_close(&pcur);
 	mtr_commit(&mtr);
 	mem_heap_free(heap);
@@ -1894,7 +1911,7 @@ dict_load_sys_table(
 
 	heap = mem_heap_create(1000);
 
-	dict_load_indexes(table, heap);
+	dict_load_indexes(table, heap, DICT_ERR_IGNORE_NONE);
 
 	mem_heap_free(heap);
 }

=== modified file 'storage/innobase/dict/dict0mem.c'
--- a/storage/innobase/dict/dict0mem.c	2010-12-01 08:36:54 +0000
+++ b/storage/innobase/dict/dict0mem.c	2011-02-08 11:39:24 +0000
@@ -38,6 +38,9 @@ Created 1/8/1996 Heikki Tuuri
 #ifndef UNIV_HOTBACKUP
 # include "lock0lock.h"
 #endif /* !UNIV_HOTBACKUP */
+#ifdef UNIV_BLOB_DEBUG
+# include "ut0rbt.h"
+#endif /* UNIV_BLOB_DEBUG */
 
 #define	DICT_HEAP_SIZE		100	/*!< initial memory heap size when
 					creating a table or index object */
@@ -380,6 +383,12 @@ dict_mem_index_free(
 {
 	ut_ad(index);
 	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
+#ifdef UNIV_BLOB_DEBUG
+	if (index->blobs) {
+		mutex_free(&index->blobs_mutex);
+		rbt_free(index->blobs);
+	}
+#endif /* UNIV_BLOB_DEBUG */
 
 	mem_heap_free(index->heap);
 }

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2011-02-08 15:47:33 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2011-02-24 14:49:38 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 2000, 2010, MySQL AB & Innobase Oy. All Rights Reserved.
+Copyright (c) 2000, 2011, MySQL AB & Innobase Oy. All Rights Reserved.
 Copyright (c) 2008, 2009 Google Inc.
 Copyright (c) 2009, Percona Inc.
 
@@ -262,7 +262,7 @@ static PSI_mutex_info all_innodb_mutexes
 #  endif /* UNIV_MEM_DEBUG */
 	{&mem_pool_mutex_key, "mem_pool_mutex", 0},
 	{&mutex_list_mutex_key, "mutex_list_mutex", 0},
-	{&purge_sys_mutex_key, "purge_sys_mutex", 0},
+	{&purge_sys_bh_mutex_key, "purge_sys_bh_mutex", 0},
 	{&recv_sys_mutex_key, "recv_sys_mutex", 0},
 	{&rseg_mutex_key, "rseg_mutex", 0},
 #  ifdef UNIV_SYNC_DEBUG
@@ -10982,16 +10982,23 @@ static MYSQL_SYSVAR_ULONG(io_capacity, s
 
 static MYSQL_SYSVAR_ULONG(purge_batch_size, srv_purge_batch_size,
   PLUGIN_VAR_OPCMDARG,
-  "Number of UNDO logs to purge in one batch from the history list. "
-  "Default is 20",
+  "Number of UNDO log pages to purge in one batch from the history list.",
   NULL, NULL,
   20,			/* Default setting */
   1,			/* Minimum value */
   5000, 0);		/* Maximum value */
 
+static MYSQL_SYSVAR_ULONG(rollback_segments, srv_rollback_segments,
+  PLUGIN_VAR_OPCMDARG,
+  "Number of UNDO logs to use.",
+  NULL, NULL,
+  128,			/* Default setting */
+  1,			/* Minimum value */
+  TRX_SYS_N_RSEGS, 0);	/* Maximum value */
+
 static MYSQL_SYSVAR_ULONG(purge_threads, srv_n_purge_threads,
   PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
-  "Purge threads can be either 0 or 1. Default is 0.",
+  "Purge threads can be either 0 or 1.",
   NULL, NULL,
   0,			/* Default setting */
   0,			/* Minimum value */
@@ -11342,6 +11349,7 @@ static struct st_mysql_sys_var* innobase
   MYSQL_SYSVAR(io_capacity),
   MYSQL_SYSVAR(purge_threads),
   MYSQL_SYSVAR(purge_batch_size),
+  MYSQL_SYSVAR(rollback_segments),
   NULL
 };
 

=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc	2010-11-11 05:51:00 +0000
+++ b/storage/innobase/handler/handler0alter.cc	2011-02-14 10:17:51 +0000
@@ -786,10 +786,6 @@ err_exit:
 
 	ut_ad(error == DB_SUCCESS);
 
-	/* We will need to rebuild index translation table. Set
-	valid index entry count in the translation table to zero */
-	share->idx_trans_tbl.index_count = 0;
-
 	/* Commit the data dictionary transaction in order to release
 	the table locks on the system tables.  This means that if
 	MySQL crashes while creating a new primary key inside
@@ -915,6 +911,14 @@ error:
 		}
 
 convert_error:
+		if (error == DB_SUCCESS) {
+			/* Build index is successful. We will need to
+			rebuild index translation table.  Reset the
+			index entry count in the translation table
+			to zero, so that translation table will be rebuilt */
+			share->idx_trans_tbl.index_count = 0;
+		}
+
 		error = convert_error_code_to_mysql(error,
 						    innodb_table->flags,
 						    user_thd);

=== modified file 'storage/innobase/include/btr0btr.h'
--- a/storage/innobase/include/btr0btr.h	2010-11-03 09:25:14 +0000
+++ b/storage/innobase/include/btr0btr.h	2011-02-08 11:39:24 +0000
@@ -92,6 +92,91 @@ insert/delete buffer when the record is
 buffer when the record is not in the buffer pool. */
 #define BTR_DELETE		8192
 
+#ifdef UNIV_BLOB_DEBUG
+# include "ut0rbt.h"
+/** An index->blobs entry for keeping track of off-page column references */
+struct btr_blob_dbg_struct
+{
+	unsigned	blob_page_no:32;	/*!< first BLOB page number */
+	unsigned	ref_page_no:32;		/*!< referring page number */
+	unsigned	ref_heap_no:16;		/*!< referring heap number */
+	unsigned	ref_field_no:10;	/*!< referring field number */
+	unsigned	owner:1;		/*!< TRUE if BLOB owner */
+	unsigned	always_owner:1;		/*!< TRUE if always
+						has been the BLOB owner;
+						reset to TRUE on B-tree
+						page splits and merges */
+	unsigned	del:1;			/*!< TRUE if currently
+						delete-marked */
+};
+
+/**************************************************************//**
+Add a reference to an off-page column to the index->blobs map. */
+UNIV_INTERN
+void
+btr_blob_dbg_add_blob(
+/*==================*/
+	const rec_t*	rec,		/*!< in: clustered index record */
+	ulint		field_no,	/*!< in: number of off-page column */
+	ulint		page_no,	/*!< in: start page of the column */
+	dict_index_t*	index,		/*!< in/out: index tree */
+	const char*	ctx)		/*!< in: context (for logging) */
+	__attribute__((nonnull));
+/**************************************************************//**
+Display the references to off-page columns.
+This function is to be called from a debugger,
+for example when a breakpoint on ut_dbg_assertion_failed is hit. */
+UNIV_INTERN
+void
+btr_blob_dbg_print(
+/*===============*/
+	const dict_index_t*	index)	/*!< in: index tree */
+	__attribute__((nonnull));
+/**************************************************************//**
+Check that there are no references to off-page columns from or to
+the given page. Invoked when freeing or clearing a page.
+@return TRUE when no orphan references exist */
+UNIV_INTERN
+ibool
+btr_blob_dbg_is_empty(
+/*==================*/
+	dict_index_t*	index,		/*!< in: index */
+	ulint		page_no)	/*!< in: page number */
+	__attribute__((nonnull, warn_unused_result));
+
+/**************************************************************//**
+Modify the 'deleted' flag of a record. */
+UNIV_INTERN
+void
+btr_blob_dbg_set_deleted_flag(
+/*==========================*/
+	const rec_t*		rec,	/*!< in: record */
+	dict_index_t*		index,	/*!< in/out: index */
+	const ulint*		offsets,/*!< in: rec_get_offs(rec, index) */
+	ibool			del)	/*!< in: TRUE=deleted, FALSE=exists */
+	__attribute__((nonnull));
+/**************************************************************//**
+Change the ownership of an off-page column. */
+UNIV_INTERN
+void
+btr_blob_dbg_owner(
+/*===============*/
+	const rec_t*		rec,	/*!< in: record */
+	dict_index_t*		index,	/*!< in/out: index */
+	const ulint*		offsets,/*!< in: rec_get_offs(rec, index) */
+	ulint			i,	/*!< in: ith field in rec */
+	ibool			own)	/*!< in: TRUE=owned, FALSE=disowned */
+	__attribute__((nonnull));
+/** Assert that there are no BLOB references to or from the given page. */
+# define btr_blob_dbg_assert_empty(index, page_no)	\
+	ut_a(btr_blob_dbg_is_empty(index, page_no))
+#else /* UNIV_BLOB_DEBUG */
+# define btr_blob_dbg_add_blob(rec, field_no, page, index, ctx)	((void) 0)
+# define btr_blob_dbg_set_deleted_flag(rec, index, offsets, del)((void) 0)
+# define btr_blob_dbg_owner(rec, index, offsets, i, val)	((void) 0)
+# define btr_blob_dbg_assert_empty(index, page_no)		((void) 0)
+#endif /* UNIV_BLOB_DEBUG */
+
 /**************************************************************//**
 Gets the root node of a tree and x-latches it.
 @return	root page, x-latched */

=== modified file 'storage/innobase/include/btr0types.h'
--- a/storage/innobase/include/btr0types.h	2010-06-22 15:58:28 +0000
+++ b/storage/innobase/include/btr0types.h	2011-02-08 11:39:24 +0000
@@ -38,6 +38,131 @@ typedef struct btr_cur_struct		btr_cur_t
 /** B-tree search information for the adaptive hash index */
 typedef struct btr_search_struct	btr_search_t;
 
+#ifdef UNIV_BLOB_DEBUG
+# include "buf0types.h"
+/** An index->blobs entry for keeping track of off-page column references */
+typedef struct btr_blob_dbg_struct btr_blob_dbg_t;
+
+/** Insert to index->blobs a reference to an off-page column.
+@param index	the index tree
+@param b	the reference
+@param ctx	context (for logging) */
+UNIV_INTERN
+void
+btr_blob_dbg_rbt_insert(
+/*====================*/
+	dict_index_t*		index,	/*!< in/out: index tree */
+	const btr_blob_dbg_t*	b,	/*!< in: the reference */
+	const char*		ctx)	/*!< in: context (for logging) */
+	__attribute__((nonnull));
+
+/** Remove from index->blobs a reference to an off-page column.
+@param index	the index tree
+@param b	the reference
+@param ctx	context (for logging) */
+UNIV_INTERN
+void
+btr_blob_dbg_rbt_delete(
+/*====================*/
+	dict_index_t*		index,	/*!< in/out: index tree */
+	const btr_blob_dbg_t*	b,	/*!< in: the reference */
+	const char*		ctx)	/*!< in: context (for logging) */
+	__attribute__((nonnull));
+
+/**************************************************************//**
+Add to index->blobs any references to off-page columns from a record.
+@return number of references added */
+UNIV_INTERN
+ulint
+btr_blob_dbg_add_rec(
+/*=================*/
+	const rec_t*	rec,	/*!< in: record */
+	dict_index_t*	index,	/*!< in/out: index */
+	const ulint*	offsets,/*!< in: offsets */
+	const char*	ctx)	/*!< in: context (for logging) */
+	__attribute__((nonnull));
+/**************************************************************//**
+Remove from index->blobs any references to off-page columns from a record.
+@return number of references removed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_remove_rec(
+/*====================*/
+	const rec_t*	rec,	/*!< in: record */
+	dict_index_t*	index,	/*!< in/out: index */
+	const ulint*	offsets,/*!< in: offsets */
+	const char*	ctx)	/*!< in: context (for logging) */
+	__attribute__((nonnull));
+/**************************************************************//**
+Count and add to index->blobs any references to off-page columns
+from records on a page.
+@return number of references added */
+UNIV_INTERN
+ulint
+btr_blob_dbg_add(
+/*=============*/
+	const page_t*	page,	/*!< in: rewritten page */
+	dict_index_t*	index,	/*!< in/out: index */
+	const char*	ctx)	/*!< in: context (for logging) */
+	__attribute__((nonnull));
+/**************************************************************//**
+Count and remove from index->blobs any references to off-page columns
+from records on a page.
+Used when reorganizing a page, before copying the records.
+@return number of references removed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_remove(
+/*================*/
+	const page_t*	page,	/*!< in: b-tree page */
+	dict_index_t*	index,	/*!< in/out: index */
+	const char*	ctx)	/*!< in: context (for logging) */
+	__attribute__((nonnull));
+/**************************************************************//**
+Restore in index->blobs any references to off-page columns
+Used when page reorganize fails due to compressed page overflow. */
+UNIV_INTERN
+void
+btr_blob_dbg_restore(
+/*=================*/
+	const page_t*	npage,	/*!< in: page that failed to compress */
+	const page_t*	page,	/*!< in: copy of original page */
+	dict_index_t*	index,	/*!< in/out: index */
+	const char*	ctx)	/*!< in: context (for logging) */
+	__attribute__((nonnull));
+
+/** Operation that processes the BLOB references of an index record
+@param[in]	rec	record on index page
+@param[in/out]	index	the index tree of the record
+@param[in]	offsets	rec_get_offsets(rec,index)
+@param[in]	ctx	context (for logging)
+@return			number of BLOB references processed */
+typedef ulint (*btr_blob_dbg_op_f)
+(const rec_t* rec,dict_index_t* index,const ulint* offsets,const char* ctx);
+
+/**************************************************************//**
+Count and process all references to off-page columns on a page.
+@return number of references processed */
+UNIV_INTERN
+ulint
+btr_blob_dbg_op(
+/*============*/
+	const page_t*		page,	/*!< in: B-tree leaf page */
+	const rec_t*		rec,	/*!< in: record to start from
+					(NULL to process the whole page) */
+	dict_index_t*		index,	/*!< in/out: index */
+	const char*		ctx,	/*!< in: context (for logging) */
+	const btr_blob_dbg_op_f	op)	/*!< in: operation on records */
+	__attribute__((nonnull(1,3,4,5)));
+#else /* UNIV_BLOB_DEBUG */
+# define btr_blob_dbg_add_rec(rec, index, offsets, ctx)		((void) 0)
+# define btr_blob_dbg_add(page, index, ctx)			((void) 0)
+# define btr_blob_dbg_remove_rec(rec, index, offsets, ctx)	((void) 0)
+# define btr_blob_dbg_remove(page, index, ctx)			((void) 0)
+# define btr_blob_dbg_restore(npage, page, index, ctx)		((void) 0)
+# define btr_blob_dbg_op(page, rec, index, ctx, op)		((void) 0)
+#endif /* UNIV_BLOB_DEBUG */
+
 /** The size of a reference to data stored on a different page.
 The reference is stored at the end of the prefix of the field
 in the index record. */

=== modified file 'storage/innobase/include/buf0flu.h'
--- a/storage/innobase/include/buf0flu.h	2010-10-20 11:46:28 +0000
+++ b/storage/innobase/include/buf0flu.h	2011-02-22 05:04:08 +0000
@@ -138,7 +138,18 @@ UNIV_INTERN
 void
 buf_flush_wait_batch_end(
 /*=====================*/
-	buf_pool_t*	buf_pool,	/*!< buffer pool instance */
+	buf_pool_t*	buf_pool,	/*!< in: buffer pool instance */
+	enum buf_flush	type);		/*!< in: BUF_FLUSH_LRU
+					or BUF_FLUSH_LIST */
+/******************************************************************//**
+Waits until a flush batch of the given type ends. This is called by
+a thread that only wants to wait for a flush to end but doesn't do
+any flushing itself. */
+UNIV_INTERN
+void
+buf_flush_wait_batch_end_wait_only(
+/*===============================*/
+	buf_pool_t*	buf_pool,	/*!< in: buffer pool instance */
 	enum buf_flush	type);		/*!< in: BUF_FLUSH_LRU
 					or BUF_FLUSH_LIST */
 /********************************************************************//**

=== modified file 'storage/innobase/include/dict0dict.h'
--- a/storage/innobase/include/dict0dict.h	2010-11-11 11:25:35 +0000
+++ b/storage/innobase/include/dict0dict.h	2011-02-09 09:15:06 +0000
@@ -441,6 +441,18 @@ function.
 @return	table, NULL if not found */
 UNIV_INLINE
 dict_table_t*
+dict_table_get_low_ignore_err(
+/*===========================*/
+	const char*	table_name,	/*!< in: table name */
+	dict_err_ignore_t
+			ignore_err);	/*!< in: error to be ignored when
+					loading a table definition */
+/**********************************************************************//**
+Gets a table; loads it to the dictionary cache if necessary. A low-level
+function.
+@return	table, NULL if not found */
+UNIV_INLINE
+dict_table_t*
 dict_table_get_low(
 /*===============*/
 	const char*	table_name);	/*!< in: table name */

=== modified file 'storage/innobase/include/dict0dict.ic'
--- a/storage/innobase/include/dict0dict.ic	2010-08-13 12:52:11 +0000
+++ b/storage/innobase/include/dict0dict.ic	2011-02-09 09:15:06 +0000
@@ -828,6 +828,34 @@ dict_table_check_if_in_cache_low(
 }
 
 /**********************************************************************//**
+load a table into dictionary cache, ignore any error specified during load; 
+@return	table, NULL if not found */
+UNIV_INLINE
+dict_table_t*
+dict_table_get_low_ignore_err(
+/*==========================*/
+	const char*	table_name,	/*!< in: table name */
+	dict_err_ignore_t
+			ignore_err)	/*!< in: error to be ignored when
+					loading a table definition */
+{
+	dict_table_t*	table;
+
+	ut_ad(table_name);
+	ut_ad(mutex_own(&(dict_sys->mutex)));
+
+	table = dict_table_check_if_in_cache_low(table_name);
+
+	if (table == NULL) {
+		table = dict_load_table(table_name, TRUE, ignore_err);
+	}
+
+	ut_ad(!table || table->cached);
+
+	return(table);
+}
+
+/**********************************************************************//**
 Gets a table; loads it to the dictionary cache if necessary. A low-level
 function.
 @return	table, NULL if not found */
@@ -845,7 +873,7 @@ dict_table_get_low(
 	table = dict_table_check_if_in_cache_low(table_name);
 
 	if (table == NULL) {
-		table = dict_load_table(table_name, TRUE);
+		table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
 	}
 
 	ut_ad(!table || table->cached);

=== modified file 'storage/innobase/include/dict0load.h'
--- a/storage/innobase/include/dict0load.h	2010-10-06 13:55:34 +0000
+++ b/storage/innobase/include/dict0load.h	2011-02-09 09:15:06 +0000
@@ -170,7 +170,10 @@ dict_load_table(
 /*============*/
 	const char*	name,	/*!< in: table name in the
 				databasename/tablename format */
-	ibool		cached);/*!< in: TRUE=add to cache, FALSE=do not */
+	ibool		cached,	/*!< in: TRUE=add to cache, FALSE=do not */
+	dict_err_ignore_t ignore_err);
+				/*!< in: error to be ignored when loading
+				table and its indexes' definition */
 /***********************************************************************//**
 Loads a table object based on the table id.
 @return	table; NULL if table does not exist */

=== modified file 'storage/innobase/include/dict0mem.h'
--- a/storage/innobase/include/dict0mem.h	2011-01-15 07:24:47 +0000
+++ b/storage/innobase/include/dict0mem.h	2011-02-09 09:15:06 +0000
@@ -361,6 +361,8 @@ struct dict_index_struct{
 				/*!< TRUE if this index is marked to be
 				dropped in ha_innobase::prepare_drop_index(),
 				otherwise FALSE */
+	unsigned	corrupted:1;
+				/*!< TRUE if the index object is corrupted */
 	dict_field_t*	fields;	/*!< array of field descriptions */
 #ifndef UNIV_HOTBACKUP
 	UT_LIST_NODE_T(dict_index_t)
@@ -395,6 +397,13 @@ struct dict_index_struct{
 				index, or 0 if the index existed
 				when InnoDB was started up */
 #endif /* !UNIV_HOTBACKUP */
+#ifdef UNIV_BLOB_DEBUG
+	mutex_t		blobs_mutex;
+				/*!< mutex protecting blobs */
+	void*		blobs;	/*!< map of (page_no,heap_no,field_no)
+				to first_blob_page_no; protected by
+				blobs_mutex; @see btr_blob_dbg_t */
+#endif /* UNIV_BLOB_DEBUG */
 #ifdef UNIV_DEBUG
 	ulint		magic_n;/*!< magic number */
 /** Value of dict_index_struct::magic_n */
@@ -487,6 +496,8 @@ struct dict_table_struct{
 				to the dictionary cache */
 	unsigned	n_def:10;/*!< number of columns defined so far */
 	unsigned	n_cols:10;/*!< number of columns */
+	unsigned	corrupted:1;
+				/*!< TRUE if table is corrupted */
 	dict_col_t*	cols;	/*!< array of column descriptions */
 	const char*	col_names;
 				/*!< Column names packed in a character string

=== modified file 'storage/innobase/include/dict0types.h'
--- a/storage/innobase/include/dict0types.h	2011-01-17 12:11:43 +0000
+++ b/storage/innobase/include/dict0types.h	2011-02-09 09:15:06 +0000
@@ -43,4 +43,18 @@ typedef struct tab_node_struct		tab_node
 typedef ib_id_t		table_id_t;
 typedef ib_id_t		index_id_t;
 
+/** Error to ignore when we load table dictionary into memory. However,
+the table and index will be marked as "corrupted", and caller will
+be responsible to deal with corrupted table or index.
+Note: please define the IGNORE_ERR_* as bits, so their value can
+be or-ed together */
+enum dict_err_ignore {
+        DICT_ERR_IGNORE_NONE = 0,        /*!< no error to ignore */
+        DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root
+					page is FIL_NUL or incorrect value */
+        DICT_ERR_IGNORE_ALL = 0xFFFF	/*!< ignore all errors */
+};
+
+typedef enum dict_err_ignore		dict_err_ignore_t;
+
 #endif

=== modified file 'storage/innobase/include/page0zip.h'
--- a/storage/innobase/include/page0zip.h	2010-06-22 15:58:28 +0000
+++ b/storage/innobase/include/page0zip.h	2011-02-08 11:39:24 +0000
@@ -420,7 +420,7 @@ page_zip_copy_recs(
 	const page_t*		src,		/*!< in: page */
 	dict_index_t*		index,		/*!< in: index of the B-tree */
 	mtr_t*			mtr)		/*!< in: mini-transaction */
-	__attribute__((nonnull(1,2,3,4)));
+	__attribute__((nonnull));
 #endif /* !UNIV_HOTBACKUP */
 
 /**********************************************************************//**

=== modified file 'storage/innobase/include/srv0srv.h'
--- a/storage/innobase/include/srv0srv.h	2011-01-15 07:24:47 +0000
+++ b/storage/innobase/include/srv0srv.h	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
 Copyright (c) 2008, 2009, Google Inc.
 Copyright (c) 2009, Percona Inc.
 
@@ -294,9 +294,12 @@ extern ulint srv_log_waits;
 /* the number of purge threads to use from the worker pool (currently 0 or 1) */
 extern ulong srv_n_purge_threads;
 
-/* the number of records to purge in one batch */
+/* the number of pages to purge in one batch */
 extern ulong srv_purge_batch_size;
 
+/* the number of rollback segments to use */
+extern ulong srv_rollback_segments;
+
 /* variable that counts amount of data read in total (in bytes) */
 extern ulint srv_data_read;
 

=== modified file 'storage/innobase/include/sync0sync.h'
--- a/storage/innobase/include/sync0sync.h	2010-10-22 06:34:57 +0000
+++ b/storage/innobase/include/sync0sync.h	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
 Copyright (c) 2008, Google Inc.
 
 Portions of this file contain modifications contributed and copyrighted by
@@ -93,7 +93,7 @@ extern mysql_pfs_key_t	mem_hash_mutex_ke
 # endif /* UNIV_MEM_DEBUG */
 extern mysql_pfs_key_t	mem_pool_mutex_key;
 extern mysql_pfs_key_t	mutex_list_mutex_key;
-extern mysql_pfs_key_t	purge_sys_mutex_key;
+extern mysql_pfs_key_t	purge_sys_bh_mutex_key;
 extern mysql_pfs_key_t	recv_sys_mutex_key;
 extern mysql_pfs_key_t	rseg_mutex_key;
 # ifdef UNIV_SYNC_DEBUG
@@ -637,7 +637,6 @@ or row lock! */
 #define SYNC_TREE_NODE_NEW	892
 #define SYNC_TREE_NODE_FROM_HASH 891
 #define SYNC_TREE_NODE		890
-#define	SYNC_PURGE_SYS		810
 #define	SYNC_PURGE_LATCH	800
 #define	SYNC_TRX_UNDO		700
 #define SYNC_RSEG		600
@@ -659,6 +658,7 @@ or row lock! */
 #define SYNC_REC_LOCK		299
 #define	SYNC_TRX_LOCK_HEAP	298
 #define SYNC_TRX_SYS_HEADER	290
+#define	SYNC_PURGE_QUEUE	200
 #define SYNC_LOG		170
 #define SYNC_LOG_FLUSH_ORDER	147
 #define SYNC_RECV		168

=== modified file 'storage/innobase/include/trx0purge.h'
--- a/storage/innobase/include/trx0purge.h	2010-06-22 15:58:28 +0000
+++ b/storage/innobase/include/trx0purge.h	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. 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
@@ -68,8 +68,9 @@ Creates the global purge system control
 mutex. */
 UNIV_INTERN
 void
-trx_purge_sys_create(void);
-/*======================*/
+trx_purge_sys_create(
+/*=================*/
+	ib_bh_t*	ib_bh);	/*!< in/own: UNDO log min binary heap*/
 /********************************************************************//**
 Frees the global purge system control structure. */
 UNIV_INTERN
@@ -128,20 +129,20 @@ struct trx_purge_struct{
 	ulint		state;		/*!< Purge system state */
 	sess_t*		sess;		/*!< System session running the purge
 					query */
-	trx_t*		trx;		/*!< System transaction running the purge
+	trx_t*		trx;		/*!< System transaction running the
+					purge
 					query: this trx is not in the trx list
 					of the trx system and it never ends */
 	que_t*		query;		/*!< The query graph which will do the
 					parallelized purge operation */
-	rw_lock_t	latch;		/*!< The latch protecting the purge view.
-					A purge operation must acquire an
-					x-latch here for the instant at which
+	rw_lock_t	latch;		/*!< The latch protecting the purge
+					view.  A purge operation must acquire
+					an x-latch here for the instant at which
 					it changes the purge view: an undo
 					log operation can prevent this by
 					obtaining an s-latch here. */
 	read_view_t*	view;		/*!< The purge will not remove undo logs
 					which are >= this view (purge view) */
-	mutex_t		mutex;		/*!< Mutex protecting the fields below */
 	ulint		n_pages_handled;/*!< Approximate number of undo log
 					pages processed in purge */
 	ulint		handle_limit;	/*!< Target of how many pages to get
@@ -179,6 +180,11 @@ struct trx_purge_struct{
 	mem_heap_t*	heap;		/*!< Temporary storage used during a
 					purge: can be emptied after purge
 					completes */
+	/*-----------------------------*/
+	ib_bh_t*	ib_bh;		/*!< Binary min-heap, ordered on
+					rseg_queue_t::trx_no. It is protected
+					by the bh_mutex */
+	mutex_t		bh_mutex;	/*!< Mutex protecting ib_bh */
 };
 
 #define TRX_PURGE_ON		1	/* purge operation is running */

=== modified file 'storage/innobase/include/trx0rseg.h'
--- a/storage/innobase/include/trx0rseg.h	2011-01-17 12:11:43 +0000
+++ b/storage/innobase/include/trx0rseg.h	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. 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
@@ -113,7 +113,9 @@ void
 trx_rseg_list_and_array_init(
 /*=========================*/
 	trx_sysf_t*	sys_header,	/*!< in: trx system header */
+	ib_bh_t*	ib_bh,		/*!< in: rseg queue */
 	mtr_t*		mtr);		/*!< in: mtr */
+
 /***************************************************************************
 Free's an instance of the rollback segment in memory. */
 UNIV_INTERN
@@ -180,6 +182,14 @@ struct trx_rseg_struct{
 					memory objects */
 };
 
+/** For prioritising the rollback segments for purge. */
+struct rseg_queue_struct {
+	trx_id_t	trx_no;		/*!< trx_rseg_t::last_trx_no */
+	trx_rseg_t*	rseg;		/*!< Rollback segment */
+};
+
+typedef struct rseg_queue_struct rseg_queue_t;
+
 /* Undo log segment slot in a rollback segment header */
 /*-------------------------------------------------------------*/
 #define	TRX_RSEG_SLOT_PAGE_NO	0	/* Page number of the header page of

=== modified file 'storage/innobase/include/trx0sys.h'
--- a/storage/innobase/include/trx0sys.h	2010-07-21 14:22:29 +0000
+++ b/storage/innobase/include/trx0sys.h	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. 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
@@ -38,6 +38,7 @@ Created 3/26/1996 Heikki Tuuri
 #include "mem0mem.h"
 #include "sync0sync.h"
 #include "ut0lst.h"
+#include "ut0bh.h"
 #include "read0types.h"
 #include "page0types.h"
 
@@ -221,13 +222,6 @@ UNIV_INLINE
 trx_id_t
 trx_sys_get_new_trx_id(void);
 /*========================*/
-/*****************************************************************//**
-Allocates a new transaction number.
-@return	new, allocated trx number */
-UNIV_INLINE
-trx_id_t
-trx_sys_get_new_trx_no(void);
-/*========================*/
 #endif /* !UNIV_HOTBACKUP */
 /*****************************************************************//**
 Writes a trx id to an index page. In case that the id size changes in

=== modified file 'storage/innobase/include/trx0sys.ic'
--- a/storage/innobase/include/trx0sys.ic	2010-07-21 14:22:29 +0000
+++ b/storage/innobase/include/trx0sys.ic	2011-02-22 05:04:08 +0000
@@ -369,16 +369,4 @@ trx_sys_get_new_trx_id(void)
 	return(id);
 }
 
-/*****************************************************************//**
-Allocates a new transaction number.
-@return	new, allocated trx number */
-UNIV_INLINE
-trx_id_t
-trx_sys_get_new_trx_no(void)
-/*========================*/
-{
-	ut_ad(mutex_own(&kernel_mutex));
-
-	return(trx_sys_get_new_trx_id());
-}
 #endif /* !UNIV_HOTBACKUP */

=== modified file 'storage/innobase/include/univ.i'
--- a/storage/innobase/include/univ.i	2011-02-08 17:30:46 +0000
+++ b/storage/innobase/include/univ.i	2011-02-17 12:00:27 +0000
@@ -51,7 +51,7 @@ Created 1/20/1994 Heikki Tuuri
 
 #define INNODB_VERSION_MAJOR	1
 #define INNODB_VERSION_MINOR	1
-#define INNODB_VERSION_BUGFIX	5
+#define INNODB_VERSION_BUGFIX	6
 
 /* The following is the InnoDB version as shown in
 SELECT plugin_version FROM information_schema.plugins;
@@ -201,6 +201,8 @@ this will break redo log file compatibil
 debugging redo log application problems. */
 #define UNIV_MEM_DEBUG				/* detect memory leaks etc */
 #define UNIV_IBUF_DEBUG				/* debug the insert buffer */
+#define UNIV_BLOB_DEBUG				/* track BLOB ownership;
+assumes that no BLOBs survive server restart */
 #define UNIV_IBUF_COUNT_DEBUG			/* debug the insert buffer;
 this limits the database to IBUF_COUNT_N_SPACES and IBUF_COUNT_N_PAGES,
 and the insert buffer must be empty when the database is started */

=== added file 'storage/innobase/include/ut0bh.h'
--- a/storage/innobase/include/ut0bh.h	1970-01-01 00:00:00 +0000
+++ b/storage/innobase/include/ut0bh.h	2011-02-23 06:48:15 +0000
@@ -0,0 +1,152 @@
+/***************************************************************************//**
+
+Copyright (c) 2011, Oracle Corpn. 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
+
+*****************************************************************************/
+
+/******************************************************************//**
+@file include/ut0bh.h
+Binary min-heap interface.
+
+Created 2010-05-28 by Sunny Bains
+*******************************************************/
+
+#ifndef INNOBASE_UT0BH_H
+#define INNOBASE_UT0BH_H
+
+#include "univ.i"
+
+/** Comparison function for objects in the binary heap. */
+typedef int (*ib_bh_cmp_t)(const void* p1, const void* p2);
+
+typedef struct ib_bh_struct ib_bh_t;
+
+/**********************************************************************//**
+Get the number of elements in the binary heap.
+@return number of elements */
+UNIV_INLINE
+ulint
+ib_bh_size(
+/*=======*/
+	const ib_bh_t*	ib_bh);			/*!< in: instance */
+
+/**********************************************************************//**
+Test if binary heap is empty.
+@return TRUE if empty. */
+UNIV_INLINE
+ibool
+ib_bh_is_empty(
+/*===========*/
+	const ib_bh_t*	ib_bh);			/*!< in: instance */
+
+/**********************************************************************//**
+Test if binary heap is full.
+@return TRUE if full. */
+UNIV_INLINE
+ibool
+ib_bh_is_full(
+/*===========*/
+	const ib_bh_t*	ib_bh);			/*!< in: instance */
+
+/**********************************************************************//**
+Get a pointer to the element.
+@return pointer to element */
+UNIV_INLINE
+void*
+ib_bh_get(
+/*=======*/
+	ib_bh_t*	ib_bh,			/*!< in: instance */
+	ulint		i);			/*!< in: index */
+
+/**********************************************************************//**
+Copy an element to the binary heap.
+@return pointer to copied element */
+UNIV_INLINE
+void*
+ib_bh_set(
+/*======*/
+	ib_bh_t*	ib_bh,			/*!< in/out: instance */
+	ulint		i,			/*!< in: index */
+	const void*	elem);			/*!< in: element to add */
+
+/**********************************************************************//**
+Return the first element from the binary heap.
+@return pointer to first element or NULL if empty. */
+UNIV_INLINE
+void*
+ib_bh_first(
+/*========*/
+	ib_bh_t*	ib_bh);			/*!< in: instance */
+
+/**********************************************************************//**
+Return the last element from the binary heap.
+@return pointer to last element or NULL if empty. */
+UNIV_INLINE
+void*
+ib_bh_last(
+/*========*/
+	ib_bh_t*	ib_bh);			/*!< in/out: instance */
+
+/**********************************************************************//**
+Create a binary heap.
+@return a new binary heap */
+UNIV_INTERN
+ib_bh_t*
+ib_bh_create(
+/*=========*/
+	ib_bh_cmp_t	compare,		/*!< in: comparator */
+	ulint		sizeof_elem,		/*!< in: size of one element */
+	ulint		max_elems);		/*!< in: max elements allowed */
+
+/**********************************************************************//**
+Free a binary heap.
+@return a new binary heap */
+UNIV_INTERN
+void
+ib_bh_free(
+/*=======*/
+	ib_bh_t*	ib_bh);			/*!< in,own: instance */
+
+/**********************************************************************//**
+Add an element to the binary heap. Note: The element is copied.
+@return pointer to added element or NULL if full. */
+UNIV_INTERN
+void*
+ib_bh_push(
+/*=======*/
+	ib_bh_t*	ib_bh,			/*!< in/out: instance */
+	const void*	elem);			/*!< in: element to add */
+
+/**********************************************************************//**
+Remove the first element from the binary heap. */
+UNIV_INTERN
+void
+ib_bh_pop(
+/*======*/
+	ib_bh_t*	ib_bh);			/*!< in/out: instance */
+
+/** Binary heap data structure */
+struct ib_bh_struct {
+	ulint		max_elems;		/*!< max elements allowed */
+	ulint		n_elems;		/*!< current size */
+	ulint		sizeof_elem;		/*!< sizeof element */
+	ib_bh_cmp_t	compare;		/*!< comparator */
+};
+
+#ifndef UNIV_NONINL
+#include "ut0bh.ic"
+#endif
+
+#endif /* INNOBASE_UT0BH_H */

=== added file 'storage/innobase/include/ut0bh.ic'
--- a/storage/innobase/include/ut0bh.ic	1970-01-01 00:00:00 +0000
+++ b/storage/innobase/include/ut0bh.ic	2011-02-22 20:24:34 +0000
@@ -0,0 +1,125 @@
+/***************************************************************************//**
+Copyright (c) 2011, Oracle Corpn. 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
+
+*****************************************************************************/
+
+/******************************************************************//**
+@file include/ut0bh.ic
+Binary min-heap implementation.
+
+Created 2011-01-15 by Sunny Bains
+*******************************************************/
+
+#include "ut0bh.h"
+#include "ut0mem.h"	/* For ut_memcpy() */
+
+/**********************************************************************//**
+Get the number of elements in the binary heap.
+@return number of elements */
+UNIV_INLINE
+ulint
+ib_bh_size(
+/*=======*/
+	const ib_bh_t*	ib_bh)			/*!< in: instance */
+{
+	return(ib_bh->n_elems);
+}
+
+/**********************************************************************//**
+Test if binary heap is empty.
+@return TRUE if empty. */
+UNIV_INLINE
+ibool
+ib_bh_is_empty(
+/*===========*/
+	const ib_bh_t*	ib_bh)			/*!< in: instance */
+{
+	return(ib_bh_size(ib_bh) == 0);
+}
+
+/**********************************************************************//**
+Test if binary heap is full.
+@return TRUE if full. */
+UNIV_INLINE
+ibool
+ib_bh_is_full(
+/*===========*/
+	const ib_bh_t*	ib_bh)			/*!< in: instance */
+{
+	return(ib_bh_size(ib_bh) >= ib_bh->max_elems);
+}
+
+/**********************************************************************//**
+Get a pointer to the element.
+@return pointer to element */
+UNIV_INLINE
+void*
+ib_bh_get(
+/*=======*/
+	ib_bh_t*	ib_bh,			/*!< in: instance */
+	ulint		i)			/*!< in: index */
+{
+	byte*		ptr = (byte*) (ib_bh + 1);
+
+	ut_a(i < ib_bh_size(ib_bh));
+
+	return(ptr + (ib_bh->sizeof_elem * i));
+}
+
+/**********************************************************************//**
+Copy an element to the binary heap.
+@return pointer to copied element */
+UNIV_INLINE
+void*
+ib_bh_set(
+/*======*/
+	ib_bh_t*	ib_bh,			/*!< in/out: instance */
+	ulint		i,			/*!< in: index */
+	const void*	elem)			/*!< in: element to add */
+{
+	void*		ptr = ib_bh_get(ib_bh, i);
+
+	ut_memcpy(ptr, elem, ib_bh->sizeof_elem);
+
+	return(ptr);
+}
+
+/**********************************************************************//**
+Return the first element from the binary heap.
+@return pointer to first element or NULL if empty. */
+UNIV_INLINE
+void*
+ib_bh_first(
+/*========*/
+	ib_bh_t*	ib_bh)			/*!< in: instance */
+{
+	return(ib_bh_is_empty(ib_bh) ? NULL : ib_bh_get(ib_bh, 0));
+}
+
+/**********************************************************************//**
+Return the last element from the binary heap.
+@return pointer to last element or NULL if empty. */
+UNIV_INLINE
+void*
+ib_bh_last(
+/*========*/
+	ib_bh_t*	ib_bh)			/*!< in/out: instance */
+{
+	return(ib_bh_is_empty(ib_bh)
+		? NULL
+		: ib_bh_get(ib_bh, ib_bh_size(ib_bh) - 1));
+}
+
+

=== modified file 'storage/innobase/page/page0cur.c'
--- a/storage/innobase/page/page0cur.c	2010-06-22 15:58:28 +0000
+++ b/storage/innobase/page/page0cur.c	2011-02-08 11:39:24 +0000
@@ -1149,6 +1149,8 @@ use_heap:
 					      current_rec, index, mtr);
 	}
 
+	btr_blob_dbg_add_rec(insert_rec, index, offsets, "insert");
+
 	return(insert_rec);
 }
 
@@ -1195,10 +1197,12 @@ page_cur_insert_rec_zip_reorg(
 	}
 
 	/* Out of space: restore the page */
+	btr_blob_dbg_remove(page, index, "insert_zip_fail");
 	if (!page_zip_decompress(page_zip, page, FALSE)) {
 		ut_error; /* Memory corrupted? */
 	}
 	ut_ad(page_validate(page, index));
+	btr_blob_dbg_add(page, index, "insert_zip_fail");
 	return(NULL);
 }
 
@@ -1490,6 +1494,8 @@ use_heap:
 
 	page_zip_write_rec(page_zip, insert_rec, index, offsets, 1);
 
+	btr_blob_dbg_add_rec(insert_rec, index, offsets, "insert_zip_ok");
+
 	/* 9. Write log record of the insert */
 	if (UNIV_LIKELY(mtr != NULL)) {
 		page_cur_insert_rec_write_log(insert_rec, rec_size,
@@ -1697,6 +1703,9 @@ page_copy_rec_list_end_to_created_page(
 
 		heap_top += rec_size;
 
+		rec_offs_make_valid(insert_rec, index, offsets);
+		btr_blob_dbg_add_rec(insert_rec, index, offsets, "copy_end");
+
 		page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
 					      index, mtr);
 		prev_rec = insert_rec;
@@ -1944,6 +1953,7 @@ page_cur_delete_rec(
 	page_dir_slot_set_n_owned(cur_dir_slot, page_zip, cur_n_owned - 1);
 
 	/* 6. Free the memory occupied by the record */
+	btr_blob_dbg_remove_rec(current_rec, index, offsets, "delete");
 	page_mem_free(page, page_zip, current_rec, index, offsets);
 
 	/* 7. Now we have decremented the number of owned records of the slot.

=== modified file 'storage/innobase/page/page0page.c'
--- a/storage/innobase/page/page0page.c	2010-07-21 14:22:29 +0000
+++ b/storage/innobase/page/page0page.c	2011-02-08 11:39:24 +0000
@@ -685,12 +685,16 @@ page_copy_rec_list_end(
 			if (UNIV_UNLIKELY
 			    (!page_zip_reorganize(new_block, index, mtr))) {
 
+				btr_blob_dbg_remove(new_page, index,
+						    "copy_end_reorg_fail");
 				if (UNIV_UNLIKELY
 				    (!page_zip_decompress(new_page_zip,
 							  new_page, FALSE))) {
 					ut_error;
 				}
 				ut_ad(page_validate(new_page, index));
+				btr_blob_dbg_add(new_page, index,
+						 "copy_end_reorg_fail");
 				return(NULL);
 			} else {
 				/* The page was reorganized:
@@ -803,12 +807,16 @@ page_copy_rec_list_start(
 			if (UNIV_UNLIKELY
 			    (!page_zip_reorganize(new_block, index, mtr))) {
 
+				btr_blob_dbg_remove(new_page, index,
+						    "copy_start_reorg_fail");
 				if (UNIV_UNLIKELY
 				    (!page_zip_decompress(new_page_zip,
 							  new_page, FALSE))) {
 					ut_error;
 				}
 				ut_ad(page_validate(new_page, index));
+				btr_blob_dbg_add(new_page, index,
+						 "copy_start_reorg_fail");
 				return(NULL);
 			} else {
 				/* The page was reorganized:
@@ -1080,6 +1088,9 @@ page_delete_rec_list_end(
 	/* Remove the record chain segment from the record chain */
 	page_rec_set_next(prev_rec, page_get_supremum_rec(page));
 
+	btr_blob_dbg_op(page, rec, index, "delete_end",
+			btr_blob_dbg_remove_rec);
+
 	/* Catenate the deleted chain segment to the page free list */
 
 	page_rec_set_next(last_rec, page_header_get_ptr(page, PAGE_FREE));

=== modified file 'storage/innobase/page/page0zip.c'
--- a/storage/innobase/page/page0zip.c	2011-01-25 08:51:13 +0000
+++ b/storage/innobase/page/page0zip.c	2011-02-08 11:39:24 +0000
@@ -4452,6 +4452,8 @@ page_zip_reorganize(
 	/* Copy the old page to temporary space */
 	buf_frame_copy(temp_page, page);
 
+	btr_blob_dbg_remove(page, index, "zip_reorg");
+
 	/* Recreate the page: note that global data on page (possible
 	segment headers, next page-field, etc.) is preserved intact */
 
@@ -4510,7 +4512,7 @@ page_zip_copy_recs(
 	mtr_t*			mtr)		/*!< in: mini-transaction */
 {
 	ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
-	ut_ad(mtr_memo_contains_page(mtr, (page_t*) src, MTR_MEMO_PAGE_X_FIX));
+	ut_ad(mtr_memo_contains_page(mtr, src, MTR_MEMO_PAGE_X_FIX));
 	ut_ad(!dict_index_is_ibuf(index));
 #ifdef UNIV_ZIP_DEBUG
 	/* The B-tree operations that call this function may set
@@ -4580,6 +4582,7 @@ page_zip_copy_recs(
 #ifdef UNIV_ZIP_DEBUG
 	ut_a(page_zip_validate(page_zip, page));
 #endif /* UNIV_ZIP_DEBUG */
+	btr_blob_dbg_add(page, index, "page_zip_copy_recs");
 
 	page_zip_compress_write_log(page_zip, page, index, mtr);
 }

=== modified file 'storage/innobase/row/row0mysql.c'
--- a/storage/innobase/row/row0mysql.c	2011-02-01 16:28:41 +0000
+++ b/storage/innobase/row/row0mysql.c	2011-02-09 09:15:06 +0000
@@ -3132,7 +3132,7 @@ row_drop_table_for_mysql(
 	ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
 #endif /* UNIV_SYNC_DEBUG */
 
-	table = dict_table_get_low(name);
+	table = dict_table_get_low_ignore_err(name, DICT_ERR_IGNORE_INDEX_ROOT);
 
 	if (!table) {
 		err = DB_TABLE_NOT_FOUND;
@@ -3367,7 +3367,7 @@ check_next_foreign:
 
 		dict_table_remove_from_cache(table);
 
-		if (dict_load_table(name, TRUE) != NULL) {
+		if (dict_load_table(name, TRUE, DICT_ERR_IGNORE_NONE) != NULL) {
 			ut_print_timestamp(stderr);
 			fputs("  InnoDB: Error: not able to remove table ",
 			      stderr);
@@ -3513,7 +3513,7 @@ row_mysql_drop_temp_tables(void)
 		btr_pcur_store_position(&pcur, &mtr);
 		btr_pcur_commit_specify_mtr(&pcur, &mtr);
 
-		table = dict_load_table(table_name, TRUE);
+		table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
 
 		if (table) {
 			row_drop_table_for_mysql(table_name, trx, FALSE);

=== modified file 'storage/innobase/row/row0upd.c'
--- a/storage/innobase/row/row0upd.c	2011-02-02 13:58:01 +0000
+++ b/storage/innobase/row/row0upd.c	2011-02-08 11:39:24 +0000
@@ -498,14 +498,49 @@ row_upd_rec_in_place(
 	n_fields = upd_get_n_fields(update);
 
 	for (i = 0; i < n_fields; i++) {
+#ifdef UNIV_BLOB_DEBUG
+		btr_blob_dbg_t	b;
+		const byte*	field_ref	= NULL;
+#endif /* UNIV_BLOB_DEBUG */
+
 		upd_field = upd_get_nth_field(update, i);
 		new_val = &(upd_field->new_val);
 		ut_ad(!dfield_is_ext(new_val) ==
 		      !rec_offs_nth_extern(offsets, upd_field->field_no));
+#ifdef UNIV_BLOB_DEBUG
+		if (dfield_is_ext(new_val)) {
+			ulint	len;
+			field_ref = rec_get_nth_field(rec, offsets, i, &len);
+			ut_a(len != UNIV_SQL_NULL);
+			ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+			field_ref += len - BTR_EXTERN_FIELD_REF_SIZE;
+
+			b.ref_page_no = page_get_page_no(page_align(rec));
+			b.ref_heap_no = page_rec_get_heap_no(rec);
+			b.ref_field_no = i;
+			b.blob_page_no = mach_read_from_4(
+				field_ref + BTR_EXTERN_PAGE_NO);
+			ut_a(b.ref_field_no >= index->n_uniq);
+			btr_blob_dbg_rbt_delete(index, &b, "upd_in_place");
+		}
+#endif /* UNIV_BLOB_DEBUG */
 
 		rec_set_nth_field(rec, offsets, upd_field->field_no,
 				  dfield_get_data(new_val),
 				  dfield_get_len(new_val));
+
+#ifdef UNIV_BLOB_DEBUG
+		if (dfield_is_ext(new_val)) {
+			b.blob_page_no = mach_read_from_4(
+				field_ref + BTR_EXTERN_PAGE_NO);
+			b.always_owner = b.owner = !(field_ref[BTR_EXTERN_LEN]
+						     & BTR_EXTERN_OWNER_FLAG);
+			b.del = rec_get_deleted_flag(
+				rec, rec_offs_comp(offsets));
+
+			btr_blob_dbg_rbt_insert(index, &b, "upd_in_place");
+		}
+#endif /* UNIV_BLOB_DEBUG */
 	}
 
 	if (UNIV_LIKELY_NULL(page_zip)) {

=== modified file 'storage/innobase/srv/srv0srv.c'
--- a/storage/innobase/srv/srv0srv.c	2011-01-15 07:24:47 +0000
+++ b/storage/innobase/srv/srv0srv.c	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, 2009 Google Inc.
 Copyright (c) 2009, Percona Inc.
 
@@ -269,9 +269,12 @@ UNIV_INTERN ulong	srv_max_buf_pool_modif
 /* the number of purge threads to use from the worker pool (currently 0 or 1).*/
 UNIV_INTERN ulong srv_n_purge_threads = 0;
 
-/* the number of records to purge in one batch */
+/* the number of pages to purge in one batch */
 UNIV_INTERN ulong srv_purge_batch_size = 20;
 
+/* the number of rollback segments to use */
+UNIV_INTERN ulong srv_rollback_segments = TRX_SYS_N_RSEGS;
+
 /* variable counts amount of data read in total (in bytes) */
 UNIV_INTERN ulint srv_data_read = 0;
 
@@ -3096,6 +3099,7 @@ srv_purge_thread(
 						required by os_thread_create */
 {
 	srv_slot_t*	slot;
+	ulint		retries = 0;
 	ulint		slot_no = ULINT_UNDEFINED;
 	ulint		n_total_purged = ULINT_UNDEFINED;
 
@@ -3122,7 +3126,7 @@ srv_purge_thread(
 
 	while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
 
-		ulint	n_pages_purged;
+		ulint	n_pages_purged = 0;
 
 		/* If there are very few records to purge or the last
 		purge didn't purge any records then wait for activity.
@@ -3130,7 +3134,8 @@ srv_purge_thread(
 		because in the worst case we will end up waiting for
 		the next purge event. */
 		if (trx_sys->rseg_history_len < srv_purge_batch_size
-		    || n_total_purged == 0) {
+		    || (n_total_purged == 0
+			&& retries >= TRX_SYS_N_RSEGS)) {
 
 			os_event_t	event;
 
@@ -3141,6 +3146,8 @@ srv_purge_thread(
 			mutex_exit(&kernel_mutex);
 
 			os_event_wait(event);
+
+			retries = 0;
 		}
 
 		/* Check for shutdown and whether we should do purge at all. */
@@ -3151,7 +3158,12 @@ srv_purge_thread(
 			break;
 		}
 
-		n_total_purged = 0;
+		if (n_total_purged == 0 && retries <= TRX_SYS_N_RSEGS) {
+			++retries;
+		} else if (n_total_purged > 0) {
+			retries = 0;
+			n_total_purged = 0;
+		}
 
 		/* Purge until there are no more records to purge and there is
 		no change in configuration or server state. */

=== modified file 'storage/innobase/srv/srv0start.c'
--- a/storage/innobase/srv/srv0start.c	2011-02-07 23:43:00 +0000
+++ b/storage/innobase/srv/srv0start.c	2011-02-08 11:39:24 +0000
@@ -1083,6 +1083,12 @@ innobase_start_or_create_for_mysql(void)
 # endif
 #endif
 
+#ifdef UNIV_BLOB_DEBUG
+	fprintf(stderr,
+		"InnoDB: !!!!!!!! UNIV_BLOB_DEBUG switched on !!!!!!!!!\n"
+		"InnoDB: Server restart may fail with UNIV_BLOB_DEBUG\n");
+#endif /* UNIV_BLOB_DEBUG */
+
 #ifdef UNIV_SYNC_DEBUG
 	ut_print_timestamp(stderr);
 	fprintf(stderr,

=== modified file 'storage/innobase/sync/sync0rw.c'
--- a/storage/innobase/sync/sync0rw.c	2011-01-18 10:30:33 +0000
+++ b/storage/innobase/sync/sync0rw.c	2011-02-15 09:29:56 +0000
@@ -271,6 +271,9 @@ rw_lock_create_func(
 	contains garbage at initialization and cannot be used for
 	recursive x-locking. */
 	lock->recursive = FALSE;
+	/* Silence Valgrind when UNIV_DEBUG_VALGRIND is not enabled. */
+	memset((void*) &lock->writer_thread, 0, sizeof lock->writer_thread);
+	UNIV_MEM_INVALID(&lock->writer_thread, sizeof lock->writer_thread);
 
 #ifdef UNIV_SYNC_DEBUG
 	UT_LIST_INIT(lock->debug_list);

=== modified file 'storage/innobase/sync/sync0sync.c'
--- a/storage/innobase/sync/sync0sync.c	2011-01-25 22:33:59 +0000
+++ b/storage/innobase/sync/sync0sync.c	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
 Copyright (c) 2008, Google Inc.
 
 Portions of this file contain modifications contributed and copyrighted by
@@ -1172,7 +1172,7 @@ sync_thread_add_level(
 	case SYNC_RSEG:
 	case SYNC_TRX_UNDO:
 	case SYNC_PURGE_LATCH:
-	case SYNC_PURGE_SYS:
+	case SYNC_PURGE_QUEUE:
 	case SYNC_DICT_AUTOINC_MUTEX:
 	case SYNC_DICT_OPERATION:
 	case SYNC_DICT_HEADER:
@@ -1239,10 +1239,16 @@ sync_thread_add_level(
 		     || sync_thread_levels_g(array, SYNC_FSP, TRUE));
 		break;
 	case SYNC_TRX_UNDO_PAGE:
+		/* Purge is allowed to read in as many UNDO pages as it likes,
+		there was a bogus rule here earlier that forced the caller to
+		acquire the purge_sys_t::mutex. The purge mutex did not really
+		protect anything because it was only ever acquired by the
+		single purge thread. The purge thread can read the UNDO pages
+		without any covering mutex. */
+
 		ut_a(sync_thread_levels_contain(array, SYNC_TRX_UNDO)
 		     || sync_thread_levels_contain(array, SYNC_RSEG)
-		     || sync_thread_levels_contain(array, SYNC_PURGE_SYS)
-		     || sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE, TRUE));
+		     || sync_thread_levels_g(array, level - 1, TRUE));
 		break;
 	case SYNC_RSEG_HEADER:
 		ut_a(sync_thread_levels_contain(array, SYNC_RSEG));

=== modified file 'storage/innobase/trx/trx0purge.c'
--- a/storage/innobase/trx/trx0purge.c	2010-10-01 13:36:35 +0000
+++ b/storage/innobase/trx/trx0purge.c	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. 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
@@ -57,8 +57,8 @@ UNIV_INTERN mysql_pfs_key_t	trx_purge_la
 #endif /* UNIV_PFS_RWLOCK */
 
 #ifdef UNIV_PFS_MUTEX
-/* Key to register purge_sys_mutex with performance schema */
-UNIV_INTERN mysql_pfs_key_t	purge_sys_mutex_key;
+/* Key to register purge_sys_bh_mutex with performance schema */
+UNIV_INTERN mysql_pfs_key_t	purge_sys_bh_mutex_key;
 #endif /* UNIV_PFS_MUTEX */
 
 /*****************************************************************//**
@@ -219,13 +219,16 @@ Creates the global purge system control
 mutex. */
 UNIV_INTERN
 void
-trx_purge_sys_create(void)
-/*======================*/
+trx_purge_sys_create(
+/*=================*/
+	ib_bh_t*	ib_bh)	/*!< in, own: UNDO log min binary heap */
 {
 	ut_ad(mutex_own(&kernel_mutex));
 
-	purge_sys = mem_alloc(sizeof(trx_purge_t));
+	purge_sys = mem_zalloc(sizeof(trx_purge_t));
 
+	/* Take ownership of ib_bh, we are responsible for freeing it. */
+	purge_sys->ib_bh = ib_bh;
 	purge_sys->state = TRX_STOP_PURGE;
 
 	purge_sys->n_pages_handled = 0;
@@ -237,8 +240,9 @@ trx_purge_sys_create(void)
 	rw_lock_create(trx_purge_latch_key,
 		       &purge_sys->latch, SYNC_PURGE_LATCH);
 
-	mutex_create(purge_sys_mutex_key,
-		     &purge_sys->mutex, SYNC_PURGE_SYS);
+	mutex_create(
+		purge_sys_bh_mutex_key, &purge_sys->bh_mutex,
+		SYNC_PURGE_QUEUE);
 
 	purge_sys->heap = mem_heap_create(256);
 
@@ -288,9 +292,12 @@ trx_purge_sys_close(void)
 	trx_undo_arr_free(purge_sys->arr);
 
 	rw_lock_free(&purge_sys->latch);
-	mutex_free(&purge_sys->mutex);
+	mutex_free(&purge_sys->bh_mutex);
 
 	mem_heap_free(purge_sys->heap);
+
+	ib_bh_free(purge_sys->ib_bh);
+
 	mem_free(purge_sys);
 
 	purge_sys = NULL;
@@ -311,34 +318,31 @@ trx_purge_add_update_undo_to_history(
 	mtr_t*	mtr)		/*!< in: mtr */
 {
 	trx_undo_t*	undo;
-	trx_rseg_t*	rseg;
 	trx_rsegf_t*	rseg_header;
-#ifdef UNIV_DEBUG
-	trx_usegf_t*	seg_header;
-#endif /* UNIV_DEBUG */
 	trx_ulogf_t*	undo_header;
-	ulint		hist_size;
 
 	undo = trx->update_undo;
 
 	ut_ad(undo);
 
-	rseg = undo->rseg;
+	ut_ad(mutex_own(&undo->rseg->mutex));
 
-	ut_ad(mutex_own(&(rseg->mutex)));
-
-	rseg_header = trx_rsegf_get(rseg->space, rseg->zip_size,
-				    rseg->page_no, mtr);
+	rseg_header = trx_rsegf_get(
+		undo->rseg->space, undo->rseg->zip_size, undo->rseg->page_no,
+		mtr);
 
 	undo_header = undo_page + undo->hdr_offset;
+	/* Add the log as the first in the history list */
+
+	if (undo->state != TRX_UNDO_CACHED) {
+		ulint		hist_size;
 #ifdef UNIV_DEBUG
-	seg_header  = undo_page + TRX_UNDO_SEG_HDR;
+		trx_usegf_t*	seg_header = undo_page + TRX_UNDO_SEG_HDR;
 #endif /* UNIV_DEBUG */
 
-	if (undo->state != TRX_UNDO_CACHED) {
 		/* The undo log segment will not be reused */
 
-		if (undo->id >= TRX_RSEG_N_SLOTS) {
+		if (UNIV_UNLIKELY(undo->id >= TRX_RSEG_N_SLOTS)) {
 			fprintf(stderr,
 				"InnoDB: Error: undo->id is %lu\n",
 				(ulong) undo->id);
@@ -347,42 +351,50 @@ trx_purge_add_update_undo_to_history(
 
 		trx_rsegf_set_nth_undo(rseg_header, undo->id, FIL_NULL, mtr);
 
-		hist_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
-					   MLOG_4BYTES, mtr);
+		hist_size = mtr_read_ulint(
+			rseg_header + TRX_RSEG_HISTORY_SIZE, MLOG_4BYTES, mtr);
+
 		ut_ad(undo->size == flst_get_len(
 			      seg_header + TRX_UNDO_PAGE_LIST, mtr));
 
-		mlog_write_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
-				 hist_size + undo->size, MLOG_4BYTES, mtr);
+		mlog_write_ulint(
+			rseg_header + TRX_RSEG_HISTORY_SIZE,
+			hist_size + undo->size, MLOG_4BYTES, mtr);
 	}
 
-	/* Add the log as the first in the history list */
-	flst_add_first(rseg_header + TRX_RSEG_HISTORY,
-		       undo_header + TRX_UNDO_HISTORY_NODE, mtr);
-	mutex_enter(&kernel_mutex);
-	trx_sys->rseg_history_len++;
-	mutex_exit(&kernel_mutex);
-
-	if (!(trx_sys->rseg_history_len % srv_purge_batch_size)) {
-		/* Inform the purge thread that there is work to do. */
-		srv_wake_purge_thread_if_not_active();
-	}
+	flst_add_first(
+		rseg_header + TRX_RSEG_HISTORY,
+		undo_header + TRX_UNDO_HISTORY_NODE, mtr);
 
 	/* Write the trx number to the undo log header */
+
 	mlog_write_ull(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr);
+
 	/* Write information about delete markings to the undo log header */
 
 	if (!undo->del_marks) {
-		mlog_write_ulint(undo_header + TRX_UNDO_DEL_MARKS, FALSE,
-				 MLOG_2BYTES, mtr);
+		mlog_write_ulint(
+			undo_header + TRX_UNDO_DEL_MARKS, FALSE,
+			MLOG_2BYTES, mtr);
 	}
 
-	if (rseg->last_page_no == FIL_NULL) {
+	if (undo->rseg->last_page_no == FIL_NULL) {
+		undo->rseg->last_trx_no = trx->no;
+		undo->rseg->last_offset = undo->hdr_offset;
+		undo->rseg->last_page_no = undo->hdr_page_no;
+		undo->rseg->last_del_marks = undo->del_marks;
 
-		rseg->last_page_no = undo->hdr_page_no;
-		rseg->last_offset = undo->hdr_offset;
-		rseg->last_trx_no = trx->no;
-		rseg->last_del_marks = undo->del_marks;
+		/* FIXME: Add a bin heap validate function to check that
+		the rseg exists. */
+	}
+
+	mutex_enter(&kernel_mutex);
+	trx_sys->rseg_history_len++;
+	mutex_exit(&kernel_mutex);
+
+	if (!(trx_sys->rseg_history_len % srv_purge_batch_size)) {
+		/* Inform the purge thread that there is work to do. */
+		srv_wake_purge_thread_if_not_active();
 	}
 }
 
@@ -411,7 +423,6 @@ trx_purge_free_segment(
 
 	/*	fputs("Freeing an update undo log segment\n", stderr); */
 
-	ut_ad(mutex_own(&(purge_sys->mutex)));
 loop:
 	mtr_start(&mtr);
 	mutex_enter(&(rseg->mutex));
@@ -515,8 +526,6 @@ trx_purge_truncate_rseg_history(
 	mtr_t		mtr;
 	trx_id_t	undo_trx_no;
 
-	ut_ad(mutex_own(&(purge_sys->mutex)));
-
 	mtr_start(&mtr);
 	mutex_enter(&(rseg->mutex));
 
@@ -609,10 +618,8 @@ trx_purge_truncate_history(void)
 	trx_id_t	limit_trx_no;
 	undo_no_t	limit_undo_no;
 
-	ut_ad(mutex_own(&(purge_sys->mutex)));
-
-	trx_purge_arr_get_biggest(purge_sys->arr, &limit_trx_no,
-				  &limit_undo_no);
+	trx_purge_arr_get_biggest(
+		purge_sys->arr, &limit_trx_no, &limit_undo_no);
 
 	if (limit_trx_no == 0) {
 
@@ -630,34 +637,29 @@ trx_purge_truncate_history(void)
 
 	ut_ad(limit_trx_no <= purge_sys->view->low_limit_no);
 
-	rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
+	for (rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
+	     rseg != NULL;
+	     rseg = UT_LIST_GET_NEXT(rseg_list, rseg)) {
 
-	while (rseg) {
-		trx_purge_truncate_rseg_history(rseg, limit_trx_no,
-						limit_undo_no);
-		rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
+		trx_purge_truncate_rseg_history(
+			rseg, limit_trx_no, limit_undo_no);
 	}
 }
 
 /********************************************************************//**
 Does a truncate if the purge array is empty. NOTE that when this function is
-called, the caller must not have any latches on undo log pages!
-@return	TRUE if array empty */
+called, the caller must not have any latches on undo log pages! */
 UNIV_INLINE
-ibool
+void
 trx_purge_truncate_if_arr_empty(void)
 /*=================================*/
 {
-	ut_ad(mutex_own(&(purge_sys->mutex)));
+	static ulint	count;
 
-	if (purge_sys->arr->n_used == 0) {
+	if (!(++count % TRX_SYS_N_RSEGS) && purge_sys->arr->n_used == 0) {
 
 		trx_purge_truncate_history();
-
-		return(TRUE);
 	}
-
-	return(FALSE);
 }
 
 /***********************************************************************//**
@@ -675,8 +677,8 @@ trx_purge_rseg_get_next_history_log(
 	trx_id_t	trx_no;
 	ibool		del_marks;
 	mtr_t		mtr;
-
-	ut_ad(mutex_own(&(purge_sys->mutex)));
+	rseg_queue_t	rseg_queue;
+	const void*	ptr;
 
 	mutex_enter(&(rseg->mutex));
 
@@ -688,8 +690,9 @@ trx_purge_rseg_get_next_history_log(
 
 	mtr_start(&mtr);
 
-	undo_page = trx_undo_page_get_s_latched(rseg->space, rseg->zip_size,
-						rseg->last_page_no, &mtr);
+	undo_page = trx_undo_page_get_s_latched(
+		rseg->space, rseg->zip_size, rseg->last_page_no, &mtr);
+
 	log_hdr = undo_page + rseg->last_offset;
 
 	/* Increase the purge page count by one for every handled log */
@@ -698,6 +701,7 @@ trx_purge_rseg_get_next_history_log(
 
 	prev_log_addr = trx_purge_get_log_from_hist(
 		flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE, &mtr));
+
 	if (prev_log_addr.page == FIL_NULL) {
 		/* No logs left in the history list */
 
@@ -712,11 +716,11 @@ trx_purge_rseg_get_next_history_log(
 		on the MySQL mailing list on Nov 9, 2004. The fut0lst.c
 		file-based list was corrupt. The prev node pointer was
 		FIL_NULL, even though the list length was over 8 million nodes!
-		We assume that purge truncates the history list in moderate
+		We assume that purge truncates the history list in large
 		size pieces, and if we here reach the head of the list, the
-		list cannot be longer than 20 000 undo logs now. */
+		list cannot be longer than 2000 000 undo logs now. */
 
-		if (trx_sys->rseg_history_len > 20000) {
+		if (trx_sys->rseg_history_len > 2000000) {
 			ut_print_timestamp(stderr);
 			fprintf(stderr,
 				"  InnoDB: Warning: purge reached the"
@@ -756,105 +760,150 @@ trx_purge_rseg_get_next_history_log(
 	rseg->last_trx_no = trx_no;
 	rseg->last_del_marks = del_marks;
 
+	rseg_queue.rseg = rseg;
+	rseg_queue.trx_no = rseg->last_trx_no;
+
+	/* Purge can also produce events, however these are already ordered
+	in the rollback segment and any user generated event will be greater
+	than the events that Purge produces. ie. Purge can never produce
+	events from an empty rollback segment. */
+
+	mutex_enter(&purge_sys->bh_mutex);
+
+	ptr = ib_bh_push(purge_sys->ib_bh, &rseg_queue);
+	ut_a(ptr != NULL);
+
+	mutex_exit(&purge_sys->bh_mutex);
+
 	mutex_exit(&(rseg->mutex));
 }
 
 /***********************************************************************//**
-Chooses the next undo log to purge and updates the info in purge_sys. This
-function is used to initialize purge_sys when the next record to purge is
-not known, and also to update the purge system info on the next record when
-purge has handled the whole undo log for a transaction. */
+Chooses the rollback segment with the smallest trx_id.
+@return zip_size if log is for a compressed table, ULINT_UNDEFINED if
+	no rollback segments to purge, 0 for non compressed tables. */
 static
-void
-trx_purge_choose_next_log(void)
-/*===========================*/
+ulint
+trx_purge_get_rseg_with_min_trx_id(
+/*===============================*/
+	trx_purge_t*	purge_sys)		/*!< in/out: purge instance */
+
 {
-	trx_undo_rec_t*	rec;
-	trx_rseg_t*	rseg;
-	trx_rseg_t*	min_rseg;
-	trx_id_t	min_trx_no;
-	ulint		space = 0;   /* remove warning (??? bug ???) */
 	ulint		zip_size = 0;
-	ulint		page_no = 0; /* remove warning (??? bug ???) */
-	ulint		offset = 0;  /* remove warning (??? bug ???) */
-	mtr_t		mtr;
 
-	ut_ad(mutex_own(&(purge_sys->mutex)));
-	ut_ad(purge_sys->next_stored == FALSE);
+	mutex_enter(&purge_sys->bh_mutex);
 
-	rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
+	/* Only purge consumes events from the binary heap, user
+	threads only produce the events. */
 
-	min_trx_no = IB_ULONGLONG_MAX;
+	if (!ib_bh_is_empty(purge_sys->ib_bh)) {
+		trx_rseg_t*	rseg;
 
-	min_rseg = NULL;
+		rseg = ((rseg_queue_t*) ib_bh_first(purge_sys->ib_bh))->rseg;
+		ib_bh_pop(purge_sys->ib_bh);
 
-	while (rseg) {
-		mutex_enter(&(rseg->mutex));
+		mutex_exit(&purge_sys->bh_mutex);
 
-		if (rseg->last_page_no != FIL_NULL) {
+		purge_sys->rseg = rseg;
+	} else {
+		mutex_exit(&purge_sys->bh_mutex);
 
-			if (min_rseg == NULL
-			    || min_trx_no > rseg->last_trx_no) {
+		purge_sys->rseg = NULL;
 
-				min_rseg = rseg;
-				min_trx_no = rseg->last_trx_no;
-				space = rseg->space;
-				zip_size = rseg->zip_size;
-				ut_a(space == 0); /* We assume in purge of
-						  externally stored fields
-						  that space id == 0 */
-				page_no = rseg->last_page_no;
-				offset = rseg->last_offset;
-			}
-		}
+		return(ULINT_UNDEFINED);
+	}
 
-		mutex_exit(&(rseg->mutex));
+	ut_a(purge_sys->rseg != NULL);
 
-		rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
-	}
+	mutex_enter(&purge_sys->rseg->mutex);
 
-	if (min_rseg == NULL) {
+	ut_a(purge_sys->rseg->last_page_no != FIL_NULL);
 
-		return;
-	}
+	/* We assume in purge of externally stored fields
+	that space id == 0 */
+	ut_a(purge_sys->rseg->space == 0);
 
-	mtr_start(&mtr);
+	zip_size = purge_sys->rseg->zip_size;
 
-	if (!min_rseg->last_del_marks) {
-		/* No need to purge this log */
+	ut_a(purge_sys->purge_trx_no <= purge_sys->rseg->last_trx_no);
 
-		rec = &trx_purge_dummy_rec;
-	} else {
-		rec = trx_undo_get_first_rec(space, zip_size, page_no, offset,
-					     RW_S_LATCH, &mtr);
-		if (rec == NULL) {
-			/* Undo log empty */
+	purge_sys->purge_trx_no = purge_sys->rseg->last_trx_no;
+
+	purge_sys->hdr_offset = purge_sys->rseg->last_offset;
+
+	purge_sys->hdr_page_no = purge_sys->rseg->last_page_no;
+
+	mutex_exit(&purge_sys->rseg->mutex);
+
+	return(zip_size);
+}
+
+/***********************************************************************//**
+Position the purge sys "iterator" on the undo record to use for purging. */
+static
+void
+trx_purge_read_undo_rec(
+/*====================*/
+	trx_purge_t*	purge_sys,		/*!< in/out: purge instance */
+	ulint		zip_size)		/*!< in: block size or 0 */
+{
+	ulint		page_no;
+	ulint		offset = 0;
+	ib_uint64_t	undo_no = 0;
+
+	purge_sys->hdr_offset = purge_sys->rseg->last_offset;
+	page_no = purge_sys->hdr_page_no = purge_sys->rseg->last_page_no;
 
-			rec = &trx_purge_dummy_rec;
+	if (purge_sys->rseg->last_del_marks) {
+		mtr_t		mtr;
+		trx_undo_rec_t*	undo_rec;
+
+		mtr_start(&mtr);
+
+		undo_rec = trx_undo_get_first_rec(
+			0 /* System space id */, zip_size,
+			purge_sys->hdr_page_no,
+			purge_sys->hdr_offset, RW_S_LATCH, &mtr);
+
+		if (undo_rec != NULL) {
+			offset = page_offset(undo_rec);
+			undo_no = trx_undo_rec_get_undo_no(undo_rec);
+			page_no = page_get_page_no(page_align(undo_rec));
 		}
+
+		mtr_commit(&mtr);
 	}
 
+	purge_sys->offset = offset;
+	purge_sys->page_no = page_no;
+	purge_sys->purge_undo_no = undo_no;
+
 	purge_sys->next_stored = TRUE;
-	purge_sys->rseg = min_rseg;
+}
+
+/***********************************************************************//**
+Chooses the next undo log to purge and updates the info in purge_sys. This
+function is used to initialize purge_sys when the next record to purge is
+not known, and also to update the purge system info on the next record when
+purge has handled the whole undo log for a transaction. */
+static
+void
+trx_purge_choose_next_log(void)
+/*===========================*/
+{
+	ulint		zip_size;
 
-	purge_sys->hdr_page_no = page_no;
-	purge_sys->hdr_offset = offset;
+	ut_ad(purge_sys->next_stored == FALSE);
 
-	purge_sys->purge_trx_no = min_trx_no;
+	zip_size = trx_purge_get_rseg_with_min_trx_id(purge_sys);
 
-	if (rec == &trx_purge_dummy_rec) {
+	if (purge_sys->rseg != NULL) {
 
-		purge_sys->purge_undo_no = 0;
-		purge_sys->page_no = page_no;
-		purge_sys->offset = 0;
+		trx_purge_read_undo_rec(purge_sys, zip_size);
 	} else {
-		purge_sys->purge_undo_no = trx_undo_rec_get_undo_no(rec);
-
-		purge_sys->page_no = page_get_page_no(page_align(rec));
-		purge_sys->offset = page_offset(rec);
+		/* There is nothing to do yet. */
+		os_thread_yield();
 	}
-
-	mtr_commit(&mtr);
 }
 
 /***********************************************************************//**
@@ -880,7 +929,6 @@ trx_purge_get_next_rec(
 	ulint		cmpl_info;
 	mtr_t		mtr;
 
-	ut_ad(mutex_own(&(purge_sys->mutex)));
 	ut_ad(purge_sys->next_stored);
 
 	space = purge_sys->rseg->space;
@@ -903,8 +951,8 @@ trx_purge_get_next_rec(
 
 	mtr_start(&mtr);
 
-	undo_page = trx_undo_page_get_s_latched(space, zip_size,
-						page_no, &mtr);
+	undo_page = trx_undo_page_get_s_latched(space, zip_size, page_no, &mtr);
+
 	rec = undo_page + offset;
 
 	rec2 = rec;
@@ -913,9 +961,9 @@ trx_purge_get_next_rec(
 		/* Try first to find the next record which requires a purge
 		operation from the same page of the same undo log */
 
-		next_rec = trx_undo_page_get_next_rec(rec2,
-						      purge_sys->hdr_page_no,
-						      purge_sys->hdr_offset);
+		next_rec = trx_undo_page_get_next_rec(
+			rec2, purge_sys->hdr_page_no, purge_sys->hdr_offset);
+
 		if (next_rec == NULL) {
 			rec2 = trx_undo_get_next_rec(
 				rec2, purge_sys->hdr_page_no,
@@ -995,17 +1043,12 @@ trx_purge_fetch_next_rec(
 {
 	trx_undo_rec_t*	undo_rec;
 
-	mutex_enter(&(purge_sys->mutex));
 
 	if (purge_sys->state == TRX_STOP_PURGE) {
 		trx_purge_truncate_if_arr_empty();
 
-		mutex_exit(&(purge_sys->mutex));
-
 		return(NULL);
-	}
-
-	if (!purge_sys->next_stored) {
+	} else if (!purge_sys->next_stored) {
 		trx_purge_choose_next_log();
 
 		if (!purge_sys->next_stored) {
@@ -1020,8 +1063,6 @@ trx_purge_fetch_next_rec(
 					(ulong) purge_sys->n_pages_handled);
 			}
 
-			mutex_exit(&(purge_sys->mutex));
-
 			return(NULL);
 		}
 	}
@@ -1032,18 +1073,12 @@ trx_purge_fetch_next_rec(
 
 		trx_purge_truncate_if_arr_empty();
 
-		mutex_exit(&(purge_sys->mutex));
-
 		return(NULL);
-	}
-
-	if (purge_sys->purge_trx_no >= purge_sys->view->low_limit_no) {
+	} else if (purge_sys->purge_trx_no >= purge_sys->view->low_limit_no) {
 		purge_sys->state = TRX_STOP_PURGE;
 
 		trx_purge_truncate_if_arr_empty();
 
-		mutex_exit(&(purge_sys->mutex));
-
 		return(NULL);
 	}
 
@@ -1052,12 +1087,13 @@ trx_purge_fetch_next_rec(
 	(ullint) purge_sys->purge_trx_no,
 	(ullint) purge_sys->purge_undo_no); */
 
-	*roll_ptr = trx_undo_build_roll_ptr(FALSE, (purge_sys->rseg)->id,
-					    purge_sys->page_no,
-					    purge_sys->offset);
 
-	*cell = trx_purge_arr_store_info(purge_sys->purge_trx_no,
-					 purge_sys->purge_undo_no);
+	*roll_ptr = trx_undo_build_roll_ptr(
+		FALSE, (purge_sys->rseg)->id, purge_sys->page_no,
+		purge_sys->offset);
+
+	*cell = trx_purge_arr_store_info(
+		purge_sys->purge_trx_no, purge_sys->purge_undo_no);
 
 	ut_ad(purge_sys->purge_trx_no < purge_sys->view->low_limit_no);
 
@@ -1066,8 +1102,6 @@ trx_purge_fetch_next_rec(
 
 	undo_rec = trx_purge_get_next_rec(heap);
 
-	mutex_exit(&(purge_sys->mutex));
-
 	return(undo_rec);
 }
 
@@ -1079,11 +1113,7 @@ trx_purge_rec_release(
 /*==================*/
 	trx_undo_inf_t*	cell)	/*!< in: storage cell */
 {
-	mutex_enter(&(purge_sys->mutex));
-
 	trx_purge_arr_remove_info(cell);
-
-	mutex_exit(&(purge_sys->mutex));
 }
 
 /*******************************************************************//**
@@ -1097,23 +1127,11 @@ trx_purge(
 				purge in one batch */
 {
 	que_thr_t*	thr;
-	/*	que_thr_t*	thr2; */
 	ulint		old_pages_handled;
 
-	mutex_enter(&(purge_sys->mutex));
-
-	if (purge_sys->trx->n_active_thrs > 0) {
+	ut_a(purge_sys->trx->n_active_thrs == 0);
 
-		mutex_exit(&(purge_sys->mutex));
-
-		/* Should not happen */
-
-		ut_error;
-
-		return(0);
-	}
-
-	rw_lock_x_lock(&(purge_sys->latch));
+	rw_lock_x_lock(&purge_sys->latch);
 
 	mutex_enter(&kernel_mutex);
 
@@ -1147,8 +1165,9 @@ trx_purge(
 		}
 	}
 
-	purge_sys->view = read_view_oldest_copy_or_open_new(0,
-							    purge_sys->heap);
+	purge_sys->view = read_view_oldest_copy_or_open_new(
+		0, purge_sys->heap);
+
 	mutex_exit(&kernel_mutex);
 
 	rw_lock_x_unlock(&(purge_sys->latch));
@@ -1159,7 +1178,6 @@ trx_purge(
 
 	old_pages_handled = purge_sys->n_pages_handled;
 
-	mutex_exit(&(purge_sys->mutex));
 
 	mutex_enter(&kernel_mutex);
 
@@ -1167,15 +1185,8 @@ trx_purge(
 
 	ut_ad(thr);
 
-	/*	thr2 = que_fork_start_command(purge_sys->query);
-
-	ut_ad(thr2); */
-
-
 	mutex_exit(&kernel_mutex);
 
-	/*	srv_que_task_enqueue(thr2); */
-
 	if (srv_print_thread_releases) {
 
 		fputs("Starting purge\n", stderr);

=== modified file 'storage/innobase/trx/trx0rseg.c'
--- a/storage/innobase/trx/trx0rseg.c	2010-07-21 14:22:29 +0000
+++ b/storage/innobase/trx/trx0rseg.c	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Oracle Corpn. 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
@@ -50,11 +50,11 @@ trx_rseg_get_on_id(
 {
 	trx_rseg_t*	rseg;
 
-	rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
+	ut_a(id < TRX_SYS_N_RSEGS);
 
-	while (rseg && rseg->id != id) {
-		rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
-	}
+	rseg = trx_sys->rseg_array[id];
+
+	ut_a(rseg == NULL || id == rseg->id);
 
 	return(rseg);
 }
@@ -181,12 +181,15 @@ static
 trx_rseg_t*
 trx_rseg_mem_create(
 /*================*/
-	ulint	id,		/*!< in: rollback segment id */
-	ulint	space,		/*!< in: space where the segment placed */
-	ulint	zip_size,	/*!< in: compressed page size in bytes
-				or 0 for uncompressed pages */
-	ulint	page_no,	/*!< in: page number of the segment header */
-	mtr_t*	mtr)		/*!< in: mtr */
+	ulint		id,		/*!< in: rollback segment id */
+	ulint		space,		/*!< in: space where the segment
+					placed */
+	ulint		zip_size,	/*!< in: compressed page size in bytes
+					or 0 for uncompressed pages */
+	ulint		page_no,	/*!< in: page number of the segment
+					header */
+	ib_bh_t*	ib_bh,		/*!< in/out: rseg queue */
+	mtr_t*		mtr)		/*!< in: mtr */
 {
 	ulint		len;
 	trx_rseg_t*	rseg;
@@ -225,6 +228,9 @@ trx_rseg_mem_create(
 
 	len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr);
 	if (len > 0) {
+		const void*	ptr;
+		rseg_queue_t	rseg_queue;
+
 		trx_sys->rseg_history_len += len;
 
 		node_addr = trx_purge_get_log_from_hist(
@@ -240,6 +246,17 @@ trx_rseg_mem_create(
 			undo_log_hdr + TRX_UNDO_TRX_NO);
 		rseg->last_del_marks = mtr_read_ulint(
 			undo_log_hdr + TRX_UNDO_DEL_MARKS, MLOG_2BYTES, mtr);
+
+		rseg_queue.rseg = rseg;
+		rseg_queue.trx_no = rseg->last_trx_no;
+
+		if (rseg->last_page_no != FIL_NULL) {
+			/* There is no need to cover this operation by the purge
+			mutex because we are still bootstrapping. */
+
+			ptr = ib_bh_push(ib_bh, &rseg_queue);
+			ut_a(ptr != NULL);
+		}
 	} else {
 		rseg->last_page_no = FIL_NULL;
 	}
@@ -255,6 +272,7 @@ void
 trx_rseg_create_instance(
 /*=====================*/
 	trx_sysf_t*	sys_header,	/*!< in: trx system header */
+	ib_bh_t*	ib_bh,		/*!< in/out: rseg queue */
 	mtr_t*		mtr)		/*!< in: mtr */
 {
 	ulint		i;
@@ -278,7 +296,7 @@ trx_rseg_create_instance(
 			zip_size = space ? fil_space_get_zip_size(space) : 0;
 
 			rseg = trx_rseg_mem_create(
-				i, space, zip_size, page_no, mtr);
+				i, space, zip_size, page_no, ib_bh, mtr);
 
 			ut_a(rseg->id == i);
 		}
@@ -327,7 +345,8 @@ trx_rseg_create(void)
 		zip_size = space ? fil_space_get_zip_size(space) : 0;
 
 		rseg = trx_rseg_mem_create(
-			slot_no, space, zip_size, page_no, &mtr);
+			slot_no, space, zip_size, page_no,
+			purge_sys->ib_bh, &mtr);
 	}
 
 	mutex_exit(&kernel_mutex);
@@ -342,13 +361,14 @@ UNIV_INTERN
 void
 trx_rseg_list_and_array_init(
 /*=========================*/
-	trx_sysf_t*	sys_header,	/* in: trx system header */
-	mtr_t*		mtr)		/* in: mtr */
+	trx_sysf_t*	sys_header,	/*!< in: trx system header */
+	ib_bh_t*	ib_bh,		/*!< in: rseg queue */
+	mtr_t*		mtr)		/*!< in: mtr */
 {
 	UT_LIST_INIT(trx_sys->rseg_list);
 
 	trx_sys->rseg_history_len = 0;
 
-	trx_rseg_create_instance(sys_header, mtr);
+	trx_rseg_create_instance(sys_header, ib_bh, mtr);
 }
 

=== modified file 'storage/innobase/trx/trx0sys.c'
--- a/storage/innobase/trx/trx0sys.c	2010-11-29 12:53:09 +0000
+++ b/storage/innobase/trx/trx0sys.c	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. 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
@@ -946,6 +946,31 @@ trx_sysf_create(
 }
 
 /*****************************************************************//**
+Compare two trx_rseg_t instances on last_trx_no. */
+static
+int
+trx_rseg_compare_last_trx_no(
+/*=========================*/
+	const void*	p1,		/*!< in: elem to compare */
+	const void*	p2)		/*!< in: elem to compare */
+{
+	ib_int64_t	cmp;
+
+	const rseg_queue_t*	rseg_q1 = (const rseg_queue_t*) p1;
+	const rseg_queue_t*	rseg_q2 = (const rseg_queue_t*) p2;
+
+	cmp = rseg_q1->trx_no - rseg_q2->trx_no;
+
+	if (cmp < 0) {
+		return(-1);
+	} else if (cmp > 0) {
+		return(1);
+	}
+
+	return(0);
+}
+
+/*****************************************************************//**
 Creates and initializes the central memory structures for the transaction
 system. This is called when the database is started. */
 UNIV_INTERN
@@ -958,6 +983,7 @@ trx_sys_init_at_db_start(void)
 	const char*	unit		= "";
 	trx_t*		trx;
 	mtr_t		mtr;
+	ib_bh_t*	ib_bh;
 
 	mtr_start(&mtr);
 
@@ -965,11 +991,19 @@ trx_sys_init_at_db_start(void)
 
 	mutex_enter(&kernel_mutex);
 
-	trx_sys = mem_alloc(sizeof(trx_sys_t));
+	/* We create the min binary heap here and pass ownership to
+	purge when we init the purge sub-system. Purge is responsible
+	for freeing the binary heap. */
+
+	ib_bh = ib_bh_create(
+		trx_rseg_compare_last_trx_no,
+		sizeof(rseg_queue_t), TRX_SYS_N_RSEGS);
+
+	trx_sys = mem_zalloc(sizeof(*trx_sys));
 
 	sys_header = trx_sysf_get(&mtr);
 
-	trx_rseg_list_and_array_init(sys_header, &mtr);
+	trx_rseg_list_and_array_init(sys_header, ib_bh, &mtr);
 
 	trx_sys->latest_rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
 
@@ -1023,7 +1057,8 @@ trx_sys_init_at_db_start(void)
 
 	UT_LIST_INIT(trx_sys->view_list);
 
-	trx_purge_sys_create();
+	/* Transfer ownership to purge. */
+	trx_purge_sys_create(ib_bh);
 
 	mutex_exit(&kernel_mutex);
 

=== modified file 'storage/innobase/trx/trx0trx.c'
--- a/storage/innobase/trx/trx0trx.c	2011-01-27 11:30:59 +0000
+++ b/storage/innobase/trx/trx0trx.c	2011-02-22 05:04:08 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 2011, Innobase Oy. 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
@@ -42,6 +42,7 @@ Created 3/26/1996 Heikki Tuuri
 #include "btr0sea.h"
 #include "os0proc.h"
 #include "trx0xa.h"
+#include "trx0purge.h"
 #include "ha_prototypes.h"
 
 /** Dummy session used currently in MySQL interface */
@@ -604,36 +605,26 @@ trx_lists_init_at_db_start(void)
 
 /******************************************************************//**
 Assigns a rollback segment to a transaction in a round-robin fashion.
-Skips the SYSTEM rollback segment if another is available.
-@return	assigned rollback segment id */
+@return	assigned rollback segment instance */
 UNIV_INLINE
-ulint
-trx_assign_rseg(void)
-/*=================*/
+trx_rseg_t*
+trx_assign_rseg(
+/*============*/
+	ulint	max_undo_logs)	/*!< in: maximum number of UNDO logs to use */
 {
-	trx_rseg_t*	rseg	= trx_sys->latest_rseg;
+	trx_rseg_t*	rseg = trx_sys->latest_rseg;
 
 	ut_ad(mutex_own(&kernel_mutex));
-loop:
-	/* Get next rseg in a round-robin fashion */
 
 	rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
 
-	if (rseg == NULL) {
+	if (rseg == NULL || rseg->id == max_undo_logs - 1) {
 		rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
 	}
 
-	/* If it is the SYSTEM rollback segment, and there exist others, skip
-	it */
-
-	if ((rseg->id == TRX_SYS_SYSTEM_RSEG_ID)
-	    && (UT_LIST_GET_LEN(trx_sys->rseg_list) > 1)) {
-		goto loop;
-	}
-
 	trx_sys->latest_rseg = rseg;
 
-	return(rseg->id);
+	return(rseg);
 }
 
 /****************************************************************//**
@@ -663,12 +654,9 @@ trx_start_low(
 
 	ut_ad(trx->conc_state != TRX_ACTIVE);
 
-	if (rseg_id == ULINT_UNDEFINED) {
-
-		rseg_id = trx_assign_rseg();
-	}
+	ut_a(rseg_id == ULINT_UNDEFINED);
 
-	rseg = trx_sys_get_nth_rseg(trx_sys, rseg_id);
+	rseg = trx_assign_rseg(srv_rollback_segments);
 
 	trx->id = trx_sys_get_new_trx_id();
 
@@ -719,107 +707,179 @@ trx_start(
 }
 
 /****************************************************************//**
-Commits a transaction. */
-UNIV_INTERN
+Set the transaction serialisation number. */
+static
 void
-trx_commit_off_kernel(
-/*==================*/
-	trx_t*	trx)	/*!< in: transaction */
+trx_serialisation_number_get(
+/*=========================*/
+	trx_t*		trx)	/*!< in: transaction */
 {
-	page_t*		update_hdr_page;
-	ib_uint64_t	lsn		= 0;
 	trx_rseg_t*	rseg;
-	trx_undo_t*	undo;
-	mtr_t		mtr;
 
-	ut_ad(mutex_own(&kernel_mutex));
+	rseg = trx->rseg;
 
-	trx->must_flush_log_later = FALSE;
+	ut_ad(mutex_own(&rseg->mutex));
 
-	rseg = trx->rseg;
+	mutex_enter(&kernel_mutex);
 
-	if (trx->insert_undo != NULL || trx->update_undo != NULL) {
+	trx->no = trx_sys_get_new_trx_id();
 
+	/* If the rollack segment is not empty then the
+	new trx_t::no can't be less than any trx_t::no
+	already in the rollback segment. User threads only
+	produce events when a rollback segment is empty. */
+
+	if (rseg->last_page_no == FIL_NULL) {
+		void*		ptr;
+		rseg_queue_t	rseg_queue;
+
+		rseg_queue.rseg = rseg;
+		rseg_queue.trx_no = trx->no;
+
+		mutex_enter(&purge_sys->bh_mutex);
+
+		/* This is to reduce the pressure on the kernel mutex,
+		though in reality it should make very little (read no)
+		difference because this code path is only taken when the
+		rbs is empty. */
+
+		mutex_exit(&kernel_mutex);
+
+		ptr = ib_bh_push(purge_sys->ib_bh, &rseg_queue);
+		ut_a(ptr);
+
+		mutex_exit(&purge_sys->bh_mutex);
+	} else {
 		mutex_exit(&kernel_mutex);
+	}
+}
+
+/****************************************************************//**
+Assign the transaction its history serialisation number and write the
+update UNDO log record to the assigned rollback segment.
+@return the LSN of the UNDO log write. */
+static
+ib_uint64_t
+trx_write_serialisation_history(
+/*============================*/
+	trx_t*		trx)	/*!< in: transaction */
+{
+	mtr_t		mtr;
+	trx_rseg_t*	rseg;
 
-		mtr_start(&mtr);
+	ut_ad(!mutex_own(&kernel_mutex));
 
-		/* Change the undo log segment states from TRX_UNDO_ACTIVE
-		to some other state: these modifications to the file data
-		structure define the transaction as committed in the file
-		based world, at the serialization point of the log sequence
-		number lsn obtained below. */
+	rseg = trx->rseg;
 
-		mutex_enter(&(rseg->mutex));
+	mtr_start(&mtr);
 
-		if (trx->insert_undo != NULL) {
-			trx_undo_set_state_at_finish(trx->insert_undo, &mtr);
-		}
+	/* Change the undo log segment states from TRX_UNDO_ACTIVE
+	to some other state: these modifications to the file data
+	structure define the transaction as committed in the file
+	based domain, at the serialization point of the log sequence
+	number lsn obtained below. */
 
-		undo = trx->update_undo;
+	if (trx->update_undo != NULL) {
+		page_t*		undo_hdr_page;
+		trx_undo_t*	undo = trx->update_undo;
 
-		if (undo) {
-			mutex_enter(&kernel_mutex);
-			trx->no = trx_sys_get_new_trx_no();
-			mutex_exit(&kernel_mutex);
-
-			/* It is not necessary to obtain trx->undo_mutex here
-			because only a single OS thread is allowed to do the
-			transaction commit for this transaction. */
-
-			update_hdr_page = trx_undo_set_state_at_finish(
-				undo, &mtr);
-
-			/* We have to do the cleanup for the update log while
-			holding the rseg mutex because update log headers
-			have to be put to the history list in the order of
-			the trx number. */
+		/* We have to hold the rseg mutex because update
+		log headers have to be put to the history list in the
+		(serialisation) order of the UNDO trx number. This is
+		required for the purge in-memory data structures too. */
 
-			trx_undo_update_cleanup(trx, update_hdr_page, &mtr);
-		}
+		mutex_enter(&rseg->mutex);
 
-		mutex_exit(&(rseg->mutex));
+		/* Assign the transaction serialisation number and also
+		update the purge min binary heap if this is the first
+		UNDO log being written to the assigned rollback segment. */
 
-		/* Update the latest MySQL binlog name and offset info
-		in trx sys header if MySQL binlogging is on or the database
-		server is a MySQL replication slave */
-
-		if (trx->mysql_log_file_name
-		    && trx->mysql_log_file_name[0] != '\0') {
-			trx_sys_update_mysql_binlog_offset(
-				trx->mysql_log_file_name,
-				trx->mysql_log_offset,
-				TRX_SYS_MYSQL_LOG_INFO, &mtr);
-			trx->mysql_log_file_name = NULL;
-		}
+		trx_serialisation_number_get(trx);
 
-		/* The following call commits the mini-transaction, making the
-		whole transaction committed in the file-based world, at this
-		log sequence number. The transaction becomes 'durable' when
-		we write the log to disk, but in the logical sense the commit
-		in the file-based data structures (undo logs etc.) happens
-		here.
-
-		NOTE that transaction numbers, which are assigned only to
-		transactions with an update undo log, do not necessarily come
-		in exactly the same order as commit lsn's, if the transactions
-		have different rollback segments. To get exactly the same
-		order we should hold the kernel mutex up to this point,
-		adding to the contention of the kernel mutex. However, if
-		a transaction T2 is able to see modifications made by
-		a transaction T1, T2 will always get a bigger transaction
-		number and a bigger commit lsn than T1. */
-
-		/*--------------*/
-		mtr_commit(&mtr);
-		/*--------------*/
-		lsn = mtr.end_lsn;
+		/* It is not necessary to obtain trx->undo_mutex here
+		because only a single OS thread is allowed to do the
+		transaction commit for this transaction. */
+
+		undo_hdr_page = trx_undo_set_state_at_finish(undo, &mtr);
+
+		trx_undo_update_cleanup(trx, undo_hdr_page, &mtr);
+	} else {
+		mutex_enter(&rseg->mutex);
+	}
+
+	if (trx->insert_undo != NULL) {
+		trx_undo_set_state_at_finish(trx->insert_undo, &mtr);
+	}
+
+	mutex_exit(&rseg->mutex);
+
+	/* Update the latest MySQL binlog name and offset info
+	in trx sys header if MySQL binlogging is on or the database
+	server is a MySQL replication slave */
+
+	if (trx->mysql_log_file_name
+	    && trx->mysql_log_file_name[0] != '\0') {
+
+		trx_sys_update_mysql_binlog_offset(
+			trx->mysql_log_file_name,
+			trx->mysql_log_offset,
+			TRX_SYS_MYSQL_LOG_INFO, &mtr);
+
+		trx->mysql_log_file_name = NULL;
+	}
+
+	/* The following call commits the mini-transaction, making the
+	whole transaction committed in the file-based world, at this
+	log sequence number. The transaction becomes 'durable' when
+	we write the log to disk, but in the logical sense the commit
+	in the file-based data structures (undo logs etc.) happens
+	here.
+
+	NOTE that transaction numbers, which are assigned only to
+	transactions with an update undo log, do not necessarily come
+	in exactly the same order as commit lsn's, if the transactions
+	have different rollback segments. To get exactly the same
+	order we should hold the kernel mutex up to this point,
+	adding to the contention of the kernel mutex. However, if
+	a transaction T2 is able to see modifications made by
+	a transaction T1, T2 will always get a bigger transaction
+	number and a bigger commit lsn than T1. */
+
+	/*--------------*/
+	mtr_commit(&mtr);
+	/*--------------*/
+
+	return(mtr.end_lsn);
+}
+
+/****************************************************************//**
+Commits a transaction. */
+UNIV_INTERN
+void
+trx_commit_off_kernel(
+/*==================*/
+	trx_t*	trx)	/*!< in: transaction */
+{
+	ib_uint64_t	lsn;
+
+	ut_ad(mutex_own(&kernel_mutex));
+
+	trx->must_flush_log_later = FALSE;
+
+	/* If the transaction made any updates then we need to write the
+	UNDO logs for the updates to the assigned rollback segment. */
+
+	if (trx->insert_undo != NULL || trx->update_undo != NULL) {
+		mutex_exit(&kernel_mutex);
+
+		lsn = trx_write_serialisation_history(trx);
 
 		mutex_enter(&kernel_mutex);
+	} else {
+		lsn = 0;
 	}
 
-	ut_ad(trx->conc_state == TRX_ACTIVE
-	      || trx->conc_state == TRX_PREPARED);
+	ut_ad(trx->conc_state == TRX_ACTIVE || trx->conc_state == TRX_PREPARED);
 	ut_ad(mutex_own(&kernel_mutex));
 
 	/* The following assignment makes the transaction committed in memory

=== added file 'storage/innobase/ut/ut0bh.c'
--- a/storage/innobase/ut/ut0bh.c	1970-01-01 00:00:00 +0000
+++ b/storage/innobase/ut/ut0bh.c	2011-02-23 06:48:15 +0000
@@ -0,0 +1,164 @@
+/***************************************************************************//**
+Copyright (c) 2010, 2011, Oracle Corpn. All Rights Reserved.
+
+Portions of this file contain modifications contributed and copyrighted by
+Sun Microsystems, Inc. Those modifications are gratefully acknowledged and
+are described briefly in the InnoDB documentation. The contributions by
+Sun Microsystems are incorporated with their permission, and subject to the
+conditions contained in the file COPYING.Sun_Microsystems.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/******************************************************************//**
+@file ut/ut0bh.c
+Binary min-heap implementation.
+
+Created 2010-05-28 by Sunny Bains
+*******************************************************/
+
+#include "ut0bh.h"
+#include "ut0mem.h"
+
+#ifdef UNIV_NONINL
+#include "ut0bh.ic"
+#endif
+
+#include <string.h>
+
+/**********************************************************************//**
+Create a binary heap.
+@return a new binary heap */
+UNIV_INTERN
+ib_bh_t*
+ib_bh_create(
+/*=========*/
+	ib_bh_cmp_t	compare,		/*!< in: comparator */
+	ulint		sizeof_elem,		/*!< in: size of one element */
+	ulint		max_elems)		/*!< in: max elements allowed */
+{
+	ulint		sz;
+	ib_bh_t*	ib_bh;
+
+	sz = sizeof(*ib_bh) + (sizeof_elem * max_elems);
+
+	ib_bh = (ib_bh_t*) ut_malloc(sz);
+	memset(ib_bh, 0x0, sz);
+
+	ib_bh->compare = compare;
+	ib_bh->max_elems = max_elems;
+	ib_bh->sizeof_elem = sizeof_elem;
+
+	return(ib_bh);
+}
+
+/**********************************************************************//**
+Free a binary heap.
+@return a new binary heap */
+UNIV_INTERN
+void
+ib_bh_free(
+/*=======*/
+	ib_bh_t*	ib_bh)			/*!< in/own: instance */
+{
+	ut_free(ib_bh);
+}
+
+/**********************************************************************//**
+Add an element to the binary heap. Note: The element is copied.
+@return pointer to added element or NULL if full. */
+UNIV_INTERN
+void*
+ib_bh_push(
+/*=======*/
+	ib_bh_t*	ib_bh,			/*!< in/out: instance */
+	const void*	elem)			/*!< in: element to add */
+{
+	void*		ptr;
+
+	if (ib_bh_is_full(ib_bh)) {
+		return(NULL);
+	} else if (ib_bh_is_empty(ib_bh)) {
+		++ib_bh->n_elems;
+		return(ib_bh_set(ib_bh, 0, elem));
+	} else {
+		ulint	i;
+
+		i = ib_bh->n_elems;
+
+		++ib_bh->n_elems;
+
+		for (ptr = ib_bh_get(ib_bh, i >> 1);
+		     i > 0 && ib_bh->compare(ptr, elem) > 0;
+		     i >>= 1, ptr = ib_bh_get(ib_bh, i >> 1)) {
+
+			ib_bh_set(ib_bh, i, ptr);
+		}
+
+		ptr = ib_bh_set(ib_bh, i, elem);
+	}
+
+	return(ptr);
+}
+
+/**********************************************************************//**
+Remove the first element from the binary heap. */
+UNIV_INTERN
+void
+ib_bh_pop(
+/*======*/
+	ib_bh_t*	ib_bh)			/*!< in/out: instance */
+{
+	byte*		ptr;
+	byte*		last;
+	ulint		parent = 0;
+
+	if (ib_bh_is_empty(ib_bh)) {
+		return;
+	} else if (ib_bh_size(ib_bh) == 1) {
+		--ib_bh->n_elems;
+		return;
+	}
+
+	last = (byte*) ib_bh_last(ib_bh);
+
+	/* Start from the child node */
+	ptr = (byte*) ib_bh_get(ib_bh, 1);
+
+	while (ptr < last) {
+		/* If the "right" child node is < "left" child node */
+		if (ib_bh->compare(ptr + ib_bh->sizeof_elem, ptr) < 0) {
+			ptr += ib_bh->sizeof_elem;
+		}
+
+		if (ib_bh->compare(last, ptr) <= 0) {
+			break;
+		}
+
+		ib_bh_set(ib_bh, parent, ptr);
+
+		parent = (ptr - (byte*) ib_bh_first(ib_bh))
+		       / ib_bh->sizeof_elem;
+
+		if ((parent << 1) >= ib_bh_size(ib_bh)) {
+			break;
+		}
+
+		ptr = (byte*) ib_bh_get(ib_bh, parent << 1);
+	}
+
+	--ib_bh->n_elems;
+
+	ib_bh_set(ib_bh, parent, last);
+}

=== modified file 'storage/innobase/ut/ut0ut.c'
--- a/storage/innobase/ut/ut0ut.c	2010-11-15 07:08:04 +0000
+++ b/storage/innobase/ut/ut0ut.c	2011-02-22 05:04:08 +0000
@@ -1,13 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
-Copyright (c) 2009, Sun Microsystems, Inc.
-
-Portions of this file contain modifications contributed and copyrighted by
-Sun Microsystems, Inc. Those modifications are gratefully acknowledged and
-are described briefly in the InnoDB documentation. The contributions by
-Sun Microsystems are incorporated with their permission, and subject to the
-conditions contained in the file COPYING.Sun_Microsystems.
+Copyright (c) 2011, Oracle Corpn. 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

=== modified file 'storage/myisam/mi_create.c'
--- a/storage/myisam/mi_create.c	2010-11-16 09:45:07 +0000
+++ b/storage/myisam/mi_create.c	2011-02-15 12:04:52 +0000
@@ -269,7 +269,7 @@ int mi_create(const char *name,uint keys
             keyseg->type != HA_KEYTYPE_VARBINARY2)
         {
           my_errno=HA_WRONG_CREATE_OPTION;
-          goto err;
+          goto err_no_lock;
         }
       }
       keydef->keysegs+=sp_segs;
@@ -278,7 +278,7 @@ int mi_create(const char *name,uint keys
       min_key_length_skip+=SPLEN*2*SPDIMS;
 #else
       my_errno= HA_ERR_UNSUPPORTED;
-      goto err;
+      goto err_no_lock;
 #endif /*HAVE_SPATIAL*/
     }
     else if (keydef->flag & HA_FULLTEXT)
@@ -294,7 +294,7 @@ int mi_create(const char *name,uint keys
             keyseg->type != HA_KEYTYPE_VARTEXT2)
         {
           my_errno=HA_WRONG_CREATE_OPTION;
-          goto err;
+          goto err_no_lock;
         }
         if (!(keyseg->flag & HA_BLOB_PART) &&
 	    (keyseg->type == HA_KEYTYPE_VARTEXT1 ||
@@ -419,7 +419,7 @@ int mi_create(const char *name,uint keys
     if (keydef->keysegs > MI_MAX_KEY_SEG)
     {
       my_errno=HA_WRONG_CREATE_OPTION;
-      goto err;
+      goto err_no_lock;
     }
     /*
       key_segs may be 0 in the case when we only want to be able to
@@ -444,7 +444,7 @@ int mi_create(const char *name,uint keys
         length >= MI_MAX_KEY_BUFF)
     {
       my_errno=HA_WRONG_CREATE_OPTION;
-      goto err;
+      goto err_no_lock;
     }
     set_if_bigger(max_key_block_length,keydef->block_length);
     keydef->keylength= (uint16) key_length;
@@ -491,7 +491,7 @@ int mi_create(const char *name,uint keys
                     "indexes and/or unique constraints.",
                     MYF(0), name + dirname_length(name));
     my_errno= HA_WRONG_CREATE_OPTION;
-    goto err;
+    goto err_no_lock;
   }
 
   bmove(share.state.header.file_version,(uchar*) myisam_file_magic,4);
@@ -810,12 +810,14 @@ int mi_create(const char *name,uint keys
   errpos=0;
   mysql_mutex_unlock(&THR_LOCK_myisam);
   if (mysql_file_close(file, MYF(0)))
-    goto err;
+    goto err_no_lock;
   my_free(rec_per_key_part);
   DBUG_RETURN(0);
 
 err:
   mysql_mutex_unlock(&THR_LOCK_myisam);
+
+err_no_lock:
   save_errno=my_errno;
   switch (errpos) {
   case 3:

=== modified file 'support-files/mysql.spec.sh'
--- a/support-files/mysql.spec.sh	2010-12-29 00:26:31 +0000
+++ b/support-files/mysql.spec.sh	2011-02-14 14:53:51 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 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
@@ -523,10 +523,27 @@ rm -f $RBR%{_mandir}/man1/make_win_bin_d
 ##############################################################################
 
 %pre -n MySQL-server%{product_suffix}
+# This is the code running at the beginning of a RPM upgrade action,
+# before replacing the old files with the new ones.
 
 # ATTENTION: Parts of this are duplicated in the "triggerpostun" !
 
-mysql_datadir=%{mysqldatadir}
+# There are users who deviate from the default file system layout.
+# Check local settings to support them.
+if [ -x %{_bindir}/my_print_defaults ]
+then
+  mysql_datadir=`%{_bindir}/my_print_defaults server mysqld | grep '^--datadir=' | sed -n 's/--datadir=//p'`
+  PID_FILE_PATT=`%{_bindir}/my_print_defaults server mysqld | grep '^--pid-file=' | sed -n 's/--pid-file=//p'`
+fi
+if [ -z "$mysql_datadir" ]
+then
+  mysql_datadir=%{mysqldatadir}
+fi
+if [ -z "$PID_FILE_PATT" ]
+then
+  PID_FILE_PATT="$mysql_datadir/*.pid"
+fi
+
 # Check if we can safely upgrade.  An upgrade is only safe if it's from one
 # of our RPMs in the same version family.
 
@@ -601,7 +618,7 @@ fi
 
 # We assume that if there is exactly one ".pid" file,
 # it contains the valid PID of a running MySQL server.
-NR_PID_FILES=`ls $mysql_datadir/*.pid 2>/dev/null | wc -l`
+NR_PID_FILES=`ls $PID_FILE_PATT 2>/dev/null | wc -l`
 case $NR_PID_FILES in
 	0 ) SERVER_TO_START=''  ;;  # No "*.pid" file == no running server
 	1 ) SERVER_TO_START='true' ;;
@@ -623,8 +640,8 @@ if [ -f $STATUS_FILE ]; then
 	echo "before repeating the MySQL upgrade."
 	exit 1
 elif [ -n "$SEVERAL_PID_FILES" ] ; then
-	echo "Your MySQL directory '$mysql_datadir' has more than one PID file:"
-	ls -ld $mysql_datadir/*.pid
+	echo "You have more than one PID file:"
+	ls -ld $PID_FILE_PATT
 	echo "Please check which one (if any) corresponds to a running server"
 	echo "and delete all others before repeating the MySQL upgrade."
 	exit 1
@@ -649,17 +666,17 @@ if [ -d $mysql_datadir ] ; then
 	if [ -n "$SERVER_TO_START" ] ; then
 		# There is only one PID file, race possibility ignored
 		echo "PID file:"                           >> $STATUS_FILE
-		ls -l   $mysql_datadir/*.pid               >> $STATUS_FILE
-		cat     $mysql_datadir/*.pid               >> $STATUS_FILE
+		ls -l   $PID_FILE_PATT                     >> $STATUS_FILE
+		cat     $PID_FILE_PATT                     >> $STATUS_FILE
 		echo                                       >> $STATUS_FILE
 		echo "Server process:"                     >> $STATUS_FILE
-		ps -fp `cat $mysql_datadir/*.pid`          >> $STATUS_FILE
+		ps -fp `cat $PID_FILE_PATT`                >> $STATUS_FILE
 		echo                                       >> $STATUS_FILE
 		echo "SERVER_TO_START=$SERVER_TO_START"    >> $STATUS_FILE
 	else
 		# Take a note we checked it ...
 		echo "PID file:"                           >> $STATUS_FILE
-		ls -l   $mysql_datadir/*.pid               >> $STATUS_FILE 2>&1
+		ls -l   $PID_FILE_PATT                     >> $STATUS_FILE 2>&1
 	fi
 fi
 
@@ -674,10 +691,22 @@ if [ -x %{_sysconfdir}/init.d/mysql ] ;
 fi
 
 %post -n MySQL-server%{product_suffix}
+# This is the code running at the end of a RPM install or upgrade action,
+# after the (new) files have been written.
 
 # ATTENTION: Parts of this are duplicated in the "triggerpostun" !
 
-mysql_datadir=%{mysqldatadir}
+# There are users who deviate from the default file system layout.
+# Check local settings to support them.
+if [ -x %{_bindir}/my_print_defaults ]
+then
+  mysql_datadir=`%{_bindir}/my_print_defaults server mysqld | grep '^--datadir=' | sed -n 's/--datadir=//p'`
+fi
+if [ -z "$mysql_datadir" ]
+then
+  mysql_datadir=%{mysqldatadir}
+fi
+
 NEW_VERSION=%{mysql_version}-%{release}
 STATUS_FILE=$mysql_datadir/RPM_UPGRADE_MARKER
 
@@ -855,7 +884,17 @@ fi
 #   http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch10s02.html
 # For all details of this code, see the "pre" and "post" sections.
 
-mysql_datadir=%{mysqldatadir}
+# There are users who deviate from the default file system layout.
+# Check local settings to support them.
+if [ -x %{_bindir}/my_print_defaults ]
+then
+  mysql_datadir=`%{_bindir}/my_print_defaults server mysqld | grep '^--datadir=' | sed -n 's/--datadir=//p'`
+fi
+if [ -z "$mysql_datadir" ]
+then
+  mysql_datadir=%{mysqldatadir}
+fi
+
 NEW_VERSION=%{mysql_version}-%{release}
 STATUS_FILE=$mysql_datadir/RPM_UPGRADE_MARKER-LAST  # Note the difference!
 STATUS_HISTORY=$mysql_datadir/RPM_UPGRADE_HISTORY
@@ -908,6 +947,8 @@ echo "====="
 %doc %{license_files_server}
 %endif
 %doc %{src_dir}/Docs/ChangeLog
+%doc %{src_dir}/Docs/INFO_SRC*
+%doc release/Docs/INFO_BIN*
 %doc release/support-files/my-*.cnf
 
 %doc %attr(644, root, root) %{_infodir}/mysql.info*
@@ -1085,6 +1126,17 @@ echo "====="
 # merging BK trees)
 ##############################################################################
 %changelog
+* Thu Feb 09 2011 Joerg Bruehe <joerg.bruehe@stripped>
+
+- Fix bug#56581: If an installation deviates from the default file locations
+  ("datadir" and "pid-file"), the mechanism to detect a running server (on upgrade)
+  should still work, and use these locations.
+  The problem was that the fix for bug#27072 did not check for local settings.
+  
+* Mon Jan 31 2011 Joerg Bruehe <joerg.bruehe@stripped>
+
+- Install the new "manifest" files: "INFO_SRC" and "INFO_BIN".
+
 * Tue Nov 23 2010 Jonathan Perkin <jonathan.perkin@strippedom>
 
 - EXCEPTIONS-CLIENT has been deleted, remove it from here too

=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c	2010-12-29 00:26:31 +0000
+++ b/tests/mysql_client_test.c	2011-02-18 14:19:55 +0000
@@ -19289,6 +19289,72 @@ static void test_bug47485()
 
 
 /*
+  Bug#58036 client utf32, utf16, ucs2 should be disallowed, they crash server
+*/
+static void test_bug58036()
+{
+  MYSQL *conn;
+  DBUG_ENTER("test_bug47485");
+  myheader("test_bug58036");
+
+  /* Part1: try to connect with ucs2 client character set */
+  conn= mysql_client_init(NULL);
+  mysql_options(conn, MYSQL_SET_CHARSET_NAME, "ucs2");
+  if (mysql_real_connect(conn, opt_host, opt_user,
+                         opt_password,  opt_db ? opt_db : "test",
+                         opt_port, opt_unix_socket, 0))
+  {
+    if (!opt_silent)
+      printf("mysql_real_connect() succeeded (failure expected)\n");
+    mysql_close(conn);
+    DIE("");
+  }
+
+  if (!opt_silent)
+    printf("Got mysql_real_connect() error (expected): %s (%d)\n",
+           mysql_error(conn), mysql_errno(conn));  
+  DIE_UNLESS(mysql_errno(conn) == ER_WRONG_VALUE_FOR_VAR);
+  mysql_close(conn);
+
+
+  /*
+    Part2:
+    - connect with latin1
+    - then change client character set to ucs2
+    - then try mysql_change_user()
+  */
+  conn= mysql_client_init(NULL);
+  mysql_options(conn, MYSQL_SET_CHARSET_NAME, "latin1");
+  if (!mysql_real_connect(conn, opt_host, opt_user,
+                         opt_password, opt_db ? opt_db : "test",
+                         opt_port, opt_unix_socket, 0))
+  {
+    if (!opt_silent)
+      printf("mysql_real_connect() failed: %s (%d)\n",
+             mysql_error(conn), mysql_errno(conn));
+    mysql_close(conn);
+    DIE("");
+  }
+
+  mysql_options(conn, MYSQL_SET_CHARSET_NAME, "ucs2");
+  if (!mysql_change_user(conn, opt_user, opt_password, NULL))
+  {
+    if (!opt_silent)
+      printf("mysql_change_user() succedded, error expected!");
+    mysql_close(conn);
+    DIE("");
+  }
+
+  if (!opt_silent)
+    printf("Got mysql_change_user() error (expected): %s (%d)\n",
+           mysql_error(conn), mysql_errno(conn));
+  mysql_close(conn);
+
+  DBUG_VOID_RETURN;
+}
+
+
+/*
   Bug#49972: Crash in prepared statements.
 
   The following case lead to a server crash:
@@ -19770,6 +19836,7 @@ static struct my_tests_st my_tests[]= {
   { "test_bug42373", test_bug42373 },
   { "test_bug54041", test_bug54041 },
   { "test_bug47485", test_bug47485 },
+  { "test_bug58036", test_bug58036 },
   { "test_bug57058", test_bug57058 },
   { 0, 0 }
 };

=== modified file 'unittest/mysys/bitmap-t.c'
--- a/unittest/mysys/bitmap-t.c	2008-02-18 22:29:39 +0000
+++ b/unittest/mysys/bitmap-t.c	2011-02-23 13:50:59 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006 MySQL AB
+/* Copyright (c) 2000, 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
@@ -24,6 +24,8 @@
 #include <tap.h>
 #include <m_string.h>
 
+#define MAX_TESTED_BITMAP_SIZE 1024
+
 uint get_rand_bit(uint bitsize)
 {
   return (rand() % bitsize);
@@ -75,12 +77,6 @@ error2:
   return TRUE;
 }
 
-my_bool test_operators(MY_BITMAP *map __attribute__((unused)),
-                       uint bitsize __attribute__((unused)))
-{
-  return FALSE;
-}
-
 my_bool test_get_all_bits(MY_BITMAP *map, uint bitsize)
 {
   uint i;
@@ -129,8 +125,8 @@ my_bool test_compare_operators(MY_BITMAP
   uint no_loops= bitsize > 128 ? 128 : bitsize;
   MY_BITMAP map2_obj, map3_obj;
   MY_BITMAP *map2= &map2_obj, *map3= &map3_obj;
-  uint32 map2buf[1024];
-  uint32 map3buf[1024];
+  uint32 map2buf[MAX_TESTED_BITMAP_SIZE];
+  uint32 map3buf[MAX_TESTED_BITMAP_SIZE];
   bitmap_init(&map2_obj, map2buf, bitsize, FALSE);
   bitmap_init(&map3_obj, map3buf, bitsize, FALSE);
   bitmap_clear_all(map2);
@@ -257,8 +253,21 @@ error2:
 
 my_bool test_get_first_bit(MY_BITMAP *map, uint bitsize)
 {
-  uint i, test_bit;
+  uint i, test_bit= 0;
   uint no_loops= bitsize > 128 ? 128 : bitsize;
+
+  bitmap_set_all(map);
+  for (i=0; i < bitsize; i++)
+    bitmap_clear_bit(map, i);
+  if (bitmap_get_first_set(map) != MY_BIT_NONE)
+    goto error1;
+  bitmap_clear_all(map);
+  for (i=0; i < bitsize; i++)
+    bitmap_set_bit(map, i);
+  if (bitmap_get_first(map) != MY_BIT_NONE)
+    goto error2;
+  bitmap_clear_all(map);
+
   for (i=0; i < no_loops; i++)
   {
     test_bit=get_rand_bit(bitsize);
@@ -321,6 +330,24 @@ my_bool test_prefix(MY_BITMAP *map, uint
       goto error3;
     bitmap_clear_all(map);
   }
+  for (i=0; i < bitsize; i++)
+  {
+    if (bitmap_is_prefix(map, i + 1))
+      goto error4;
+    bitmap_set_bit(map, i);
+    if (!bitmap_is_prefix(map, i + 1))
+      goto error5;
+    test_bit=get_rand_bit(bitsize);
+    bitmap_set_bit(map, test_bit);
+    if (test_bit <= i && !bitmap_is_prefix(map, i + 1))
+      goto error5;
+    else if (test_bit > i)
+    {
+      if (bitmap_is_prefix(map, i + 1))
+        goto error4;
+      bitmap_clear_bit(map, test_bit);
+    }
+  }
   return FALSE;
 error1:
   diag("prefix1 error  bitsize = %u, prefix_size = %u", bitsize,test_bit);
@@ -331,13 +358,127 @@ error2:
 error3:
   diag("prefix3 error  bitsize = %u, prefix_size = %u", bitsize,test_bit);
   return TRUE;
+error4:
+  diag("prefix4 error  bitsize = %u, i = %u", bitsize,i);
+  return TRUE;
+error5:
+  diag("prefix5 error  bitsize = %u, i = %u", bitsize,i);
+  return TRUE;
 }
 
+my_bool test_compare(MY_BITMAP *map, uint bitsize)
+{
+  MY_BITMAP map2;
+  uint32 map2buf[MAX_TESTED_BITMAP_SIZE];
+  uint i, test_bit;
+  uint no_loops= bitsize > 128 ? 128 : bitsize;
+  if (bitmap_init(&map2, map2buf, bitsize, FALSE))
+  {
+    diag("init error for bitsize %d", bitsize);
+    return TRUE;
+  }
+  /* Test all 4 possible combinations of set/unset bits. */
+  for (i=0; i < no_loops; i++)
+  {
+    test_bit=get_rand_bit(bitsize);
+    bitmap_clear_bit(map, test_bit);
+    bitmap_clear_bit(&map2, test_bit);
+    if (!bitmap_is_subset(map, &map2))
+      goto error_is_subset;
+    bitmap_set_bit(map, test_bit);
+    if (bitmap_is_subset(map, &map2))
+      goto error_is_subset;
+    bitmap_set_bit(&map2, test_bit);
+    if (!bitmap_is_subset(map, &map2))
+      goto error_is_subset;
+    bitmap_clear_bit(map, test_bit);
+    if (!bitmap_is_subset(map, &map2))
+      goto error_is_subset;
+    /* Note that test_bit is not cleared i map2. */
+  }
+  bitmap_clear_all(map);
+  bitmap_clear_all(&map2);
+  /* Test all 4 possible combinations of set/unset bits. */
+  for (i=0; i < no_loops; i++)
+  {
+    test_bit=get_rand_bit(bitsize);
+    if (bitmap_is_overlapping(map, &map2))
+      goto error_is_overlapping;
+    bitmap_set_bit(map, test_bit);
+    if (bitmap_is_overlapping(map, &map2))
+      goto error_is_overlapping;
+    bitmap_set_bit(&map2, test_bit);
+    if (!bitmap_is_overlapping(map, &map2))
+      goto error_is_overlapping;
+    bitmap_clear_bit(map, test_bit);
+    if (bitmap_is_overlapping(map, &map2))
+      goto error_is_overlapping;
+    bitmap_clear_bit(&map2, test_bit);
+    /* Note that test_bit is not cleared i map2. */
+  }
+  return FALSE;
+error_is_subset:
+  diag("is_subset error  bitsize = %u", bitsize);
+  return TRUE;
+error_is_overlapping:
+  diag("is_overlapping error  bitsize = %u", bitsize);
+  return TRUE;
+}
+
+my_bool test_intersect(MY_BITMAP *map, uint bitsize)
+{
+  uint bitsize2 = 1 + get_rand_bit(MAX_TESTED_BITMAP_SIZE - 1);
+  MY_BITMAP map2;
+  uint32 map2buf[MAX_TESTED_BITMAP_SIZE];
+  uint i, test_bit1, test_bit2, test_bit3;
+  if (bitmap_init(&map2, map2buf, bitsize2, FALSE))
+  {
+    diag("init error for bitsize %d", bitsize2);
+    return TRUE;
+  }
+  test_bit1= get_rand_bit(bitsize);
+  test_bit2= get_rand_bit(bitsize);
+  bitmap_set_bit(map, test_bit1);
+  bitmap_set_bit(map, test_bit2);
+  test_bit3= get_rand_bit(bitsize2);
+  bitmap_set_bit(&map2, test_bit3);
+  if (test_bit2 < bitsize2)
+    bitmap_set_bit(&map2, test_bit2);
+
+  bitmap_intersect(map, &map2);
+  if (test_bit2 < bitsize2)
+  {
+    if (!bitmap_is_set(map, test_bit2))
+      goto error;
+    bitmap_clear_bit(map, test_bit2);
+  }
+  if (test_bit1 == test_bit3)
+  {
+    if (!bitmap_is_set(map, test_bit1))
+      goto error;
+    bitmap_clear_bit(map, test_bit1);
+  }
+  if (!bitmap_is_clear_all(map))
+    goto error;
+
+  bitmap_set_all(map);
+  bitmap_set_all(&map2);
+  for (i=0; i < bitsize2; i++)
+    bitmap_clear_bit(&map2, i);
+  bitmap_intersect(map, &map2);
+  if (!bitmap_is_clear_all(map))
+    goto error;
+  return FALSE;
+error:
+  diag("intersect error  bitsize = %u, bit1 = %u, bit2 = %u, bit3 = %u",
+       bitsize, test_bit1, test_bit2, test_bit3);
+  return TRUE;
+}
 
 my_bool do_test(uint bitsize)
 {
   MY_BITMAP map;
-  uint32 buf[1024];
+  uint32 buf[MAX_TESTED_BITMAP_SIZE];
   if (bitmap_init(&map, buf, bitsize, FALSE))
   {
     diag("init error for bitsize %d", bitsize);
@@ -349,9 +490,6 @@ my_bool do_test(uint bitsize)
   if (test_flip_bit(&map,bitsize))
     goto error;
   bitmap_clear_all(&map);
-  if (test_operators(&map,bitsize))
-    goto error;
-  bitmap_clear_all(&map);
   if (test_get_all_bits(&map, bitsize))
     goto error;
   bitmap_clear_all(&map);
@@ -366,8 +504,15 @@ my_bool do_test(uint bitsize)
   bitmap_clear_all(&map);
   if (test_get_next_bit(&map,bitsize))
     goto error;
+  bitmap_clear_all(&map);
   if (test_prefix(&map,bitsize))
     goto error;
+  bitmap_clear_all(&map);
+  if (test_compare(&map,bitsize))
+    goto error;
+  bitmap_clear_all(&map);
+  if (test_intersect(&map,bitsize))
+    goto error;
   return FALSE;
 error:
   return TRUE;
@@ -377,7 +522,7 @@ int main()
 {
   int i;
   int const min_size = 1;
-  int const max_size = 1024;
+  int const max_size = MAX_TESTED_BITMAP_SIZE;
   MY_INIT("bitmap-t");
 
   plan(max_size - min_size);

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.5-mtr branch (bjorn.munch:3169 to 3174) Bjorn Munch24 Feb