List:Commits« Previous MessageNext Message »
From:Bjorn Munch Date:February 24 2011 3:57pm
Subject:bzr push into mysql-5.1-mtr branch (bjorn.munch:2982 to 2983)
View as plain text  
 2983 Bjorn Munch	2011-02-24 [merge]
      merge from 5.1 main

    added:
      mysql-test/suite/innodb/r/innodb_bug60049.result
      mysql-test/suite/innodb/t/innodb_bug60049-master.opt
      mysql-test/suite/innodb/t/innodb_bug60049.test
      mysql-test/suite/innodb_plugin/r/innodb_bug59307.result
      mysql-test/suite/innodb_plugin/r/innodb_bug60049.result
      mysql-test/suite/innodb_plugin/t/innodb_bug59307.test
      mysql-test/suite/innodb_plugin/t/innodb_bug60049-master.opt
      mysql-test/suite/innodb_plugin/t/innodb_bug60049.test
    modified:
      README
      client/mysql.cc
      client/mysqldump.c
      client/readline.cc
      configure.in
      include/my_bit.h
      include/my_bitmap.h
      mysql-test/r/ctype_cp1250_ch.result
      mysql-test/r/ctype_cp1251.result
      mysql-test/r/ctype_eucjpms.result*
      mysql-test/r/ddl_i18n_koi8r.result
      mysql-test/r/ddl_i18n_utf8.result
      mysql-test/r/gis.result
      mysql-test/r/group_by.result
      mysql-test/r/insert_select.result
      mysql-test/r/mysqldump.result
      mysql-test/suite/innodb_plugin/t/innodb_information_schema.test
      mysql-test/t/ctype_cp1250_ch.test
      mysql-test/t/ctype_cp1251.test
      mysql-test/t/ctype_eucjpms.test
      mysql-test/t/gis.test
      mysql-test/t/group_by.test
      mysql-test/t/insert_select.test
      mysql-test/t/mysqldump.test
      mysys/my_bitmap.c
      sql/mysql_priv.h
      sql/set_var.cc
      sql/sql_connect.cc
      sql/sql_parse.cc
      sql/sql_select.cc
      sql/sql_string.h
      storage/innodb_plugin/ChangeLog
      storage/innodb_plugin/btr/btr0btr.c
      storage/innodb_plugin/btr/btr0cur.c
      storage/innodb_plugin/dict/dict0mem.c
      storage/innodb_plugin/handler/handler0alter.cc
      storage/innodb_plugin/include/btr0btr.h
      storage/innodb_plugin/include/btr0types.h
      storage/innodb_plugin/include/dict0mem.h
      storage/innodb_plugin/include/page0zip.h
      storage/innodb_plugin/include/univ.i
      storage/innodb_plugin/page/page0cur.c
      storage/innodb_plugin/page/page0page.c
      storage/innodb_plugin/page/page0zip.c
      storage/innodb_plugin/row/row0upd.c
      storage/innodb_plugin/srv/srv0start.c
      storage/innodb_plugin/sync/sync0rw.c
      storage/myisam/mi_create.c
      support-files/mysql.spec.sh
      tests/mysql_client_test.c
      unittest/mysys/bitmap-t.c
 2982 Bjorn Munch	2011-02-23
      Bug #11762407 54999: MTR GLOBAL SUPPRESSION HIDES SQL THREAD EXECUTION UNEXPECTED ERRORS
      Removed the global suppression, added lots of local ones to affected tests
      Re-commit, now kept "Slave SQL" at start of patterns.

    modified:
      mysql-test/extra/binlog_tests/binlog.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/include/mtr_warnings.sql
      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_binlog_max_cache_size.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_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_concurrent.result
      mysql-test/suite/rpl/r/rpl_loaddata_fatal.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_colSize.result
      mysql-test/suite/rpl/r/rpl_row_conflicts.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_remove_tmpfile.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_conflicts.result
      mysql-test/suite/rpl/r/rpl_temporary_errors.result
      mysql-test/suite/rpl/t/rpl_binlog_corruption.test
      mysql-test/suite/rpl/t/rpl_binlog_max_cache_size.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_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_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_remove_tmpfile.test
      mysql-test/suite/rpl/t/rpl_slave_load_tmpdir_not_exist.test
      mysql-test/suite/rpl/t/rpl_temporary_errors.test
=== modified file 'README'
--- a/README	2011-01-25 14:42:40 +0000
+++ b/README	2011-02-22 21:03:32 +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 'client/mysql.cc'
--- a/client/mysql.cc	2011-02-05 05:02:00 +0000
+++ b/client/mysql.cc	2011-02-09 06:46:12 +0000
@@ -1131,6 +1131,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-14 14:20:34 +0000
+++ b/client/mysqldump.c	2011-02-21 07:07:24 +0000
@@ -1134,6 +1134,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)
@@ -1141,7 +1144,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);
@@ -1162,6 +1165,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)
@@ -1169,7 +1175,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:02:00 +0000
+++ b/client/readline.cc	2011-02-09 11:13:17 +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;

=== modified file 'configure.in'
--- a/configure.in	2011-02-08 11:52:33 +0000
+++ b/configure.in	2011-02-22 21:03:32 +0000
@@ -12,7 +12,7 @@ dnl
 dnl When changing the major version number please also check the switch
 dnl statement in mysqlbinlog::check_master_version().  You may also need
 dnl to update version.c in ndb.
-AC_INIT([MySQL Server], [5.1.56], [], [mysql])
+AC_INIT([MySQL Server], [5.1.57], [], [mysql])
 
 AC_CONFIG_SRCDIR([sql/mysqld.cc])
 AC_CANONICAL_SYSTEM

=== modified file 'include/my_bit.h'
--- a/include/my_bit.h	2007-10-16 15:03:13 +0000
+++ b/include/my_bit.h	2011-02-16 15:26:19 +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 */
+
 /*
   Some useful bit functions
 */
@@ -42,9 +57,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)]);
 }
 
 
@@ -104,6 +122,6 @@ extern uint32 my_round_up_to_next_power(
 uint32 my_clear_highest_bit(uint32 v);
 uint32 my_reverse_bits(uint32 key);
 extern uint my_count_bits(ulonglong v);
-extern uint my_count_bits_ushort(ushort v);
+extern uint my_count_bits_uint32(uint32 v);
 #endif /* HAVE_INLINE */
 C_MODE_END

=== modified file 'include/my_bitmap.h'
--- a/include/my_bitmap.h	2010-07-02 18:30:47 +0000
+++ b/include/my_bitmap.h	2011-02-16 15:26:19 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 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
@@ -149,9 +149,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 '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:43:53 +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 system variable 'LC_MESSAGES'

=== modified file 'mysql-test/r/ctype_cp1251.result'
--- a/mysql-test/r/ctype_cp1251.result	2010-11-26 13:58:54 +0000
+++ b/mysql-test/r/ctype_cp1251.result	2011-02-17 11:43:53 +0000
@@ -375,6 +375,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
 #

=== modified file 'mysql-test/r/ctype_eucjpms.result' (properties changed: +x to -x)
--- a/mysql-test/r/ctype_eucjpms.result	2008-02-04 07:10:40 +0000
+++ b/mysql-test/r/ctype_eucjpms.result	2011-02-17 11:43:53 +0000
@@ -9859,3 +9859,5 @@ 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'

=== modified file 'mysql-test/r/ddl_i18n_koi8r.result'
--- a/mysql-test/r/ddl_i18n_koi8r.result	2009-05-15 10:15:56 +0000
+++ b/mysql-test/r/ddl_i18n_koi8r.result	2011-02-22 13:58:50 +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	2009-05-15 10:15:56 +0000
+++ b/mysql-test/r/ddl_i18n_utf8.result	2011-02-22 13:58:50 +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 */ ;
 

=== modified file 'mysql-test/r/gis.result'
--- a/mysql-test/r/gis.result	2011-02-02 13:17:48 +0000
+++ b/mysql-test/r/gis.result	2011-02-22 21:03:32 +0000
@@ -1034,4 +1034,12 @@ 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 HY000: Can't create table '#sql-temporary' (errno: 140)
+drop table t1;
 End of 5.1 tests

=== modified file 'mysql-test/r/group_by.result'
--- a/mysql-test/r/group_by.result	2010-10-29 08:23:06 +0000
+++ b/mysql-test/r/group_by.result	2011-02-18 10:50:06 +0000
@@ -1855,4 +1855,40 @@ 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

=== modified file 'mysql-test/r/insert_select.result'
--- a/mysql-test/r/insert_select.result	2009-09-02 16:58:17 +0000
+++ b/mysql-test/r/insert_select.result	2011-02-16 20:43:12 +0000
@@ -841,7 +841,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/mysqldump.result'
--- a/mysql-test/r/mysqldump.result	2011-01-14 14:20:34 +0000
+++ b/mysql-test/r/mysqldump.result	2011-02-21 07:07:24 +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
 #

=== 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_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

=== added file 'mysql-test/suite/innodb_plugin/r/innodb_bug59307.result'
--- a/mysql-test/suite/innodb_plugin/r/innodb_bug59307.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb_plugin/r/innodb_bug59307.result	2011-02-15 08:51:33 +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_plugin/r/innodb_bug60049.result'
--- a/mysql-test/suite/innodb_plugin/r/innodb_bug60049.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb_plugin/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_plugin/t/innodb_bug59307.test'
--- a/mysql-test/suite/innodb_plugin/t/innodb_bug59307.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb_plugin/t/innodb_bug59307.test	2011-02-15 08:51:33 +0000
@@ -0,0 +1,32 @@
+-- source include/have_innodb_plugin.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_plugin/t/innodb_bug60049-master.opt'
--- a/mysql-test/suite/innodb_plugin/t/innodb_bug60049-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb_plugin/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_plugin/t/innodb_bug60049.test'
--- a/mysql-test/suite/innodb_plugin/t/innodb_bug60049.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb_plugin/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_plugin.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_plugin/t/innodb_information_schema.test'
--- a/mysql-test/suite/innodb_plugin/t/innodb_information_schema.test	2010-04-09 12:56:51 +0000
+++ b/mysql-test/suite/innodb_plugin/t/innodb_information_schema.test	2011-02-17 17:09:53 +0000
@@ -116,11 +116,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/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:43:53 +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 1193
+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 13:58:54 +0000
+++ b/mysql-test/t/ctype_cp1251.test	2011-02-17 11:43:53 +0000
@@ -55,6 +55,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 1105
+set global LC_TIME_NAMES=convert((-8388608) using cp1251);
+
+
 --echo #
 --echo # End of 5.1 tests
 --echo #

=== modified file 'mysql-test/t/ctype_eucjpms.test'
--- a/mysql-test/t/ctype_eucjpms.test	2008-02-04 07:10:40 +0000
+++ b/mysql-test/t/ctype_eucjpms.test	2011-02-17 11:43:53 +0000
@@ -381,3 +381,11 @@ select hex(convert(_eucjpms 0xA5FE41 usi
 # the next character, which is a single byte character 0x41.
 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 1105
+set global LC_TIME_NAMES=convert((convert((0x63) using eucjpms)) using utf8);

=== modified file 'mysql-test/t/gis.test'
--- a/mysql-test/t/gis.test	2011-01-14 20:56:09 +0000
+++ b/mysql-test/t/gis.test	2011-02-22 21:03:32 +0000
@@ -754,4 +754,16 @@ 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;
+--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
+--error ER_CANT_CREATE_TABLE
+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-10-29 08:23:06 +0000
+++ b/mysql-test/t/group_by.test	2011-02-18 10:50:06 +0000
@@ -1247,4 +1247,41 @@ 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

=== modified file 'mysql-test/t/insert_select.test'
--- a/mysql-test/t/insert_select.test	2009-09-02 16:58:17 +0000
+++ b/mysql-test/t/insert_select.test	2011-02-16 20:43:12 +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/mysqldump.test'
--- a/mysql-test/t/mysqldump.test	2011-01-14 14:20:34 +0000
+++ b/mysql-test/t/mysqldump.test	2011-02-21 07:07:24 +0000
@@ -2174,6 +2174,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 'mysys/my_bitmap.c'
--- a/mysys/my_bitmap.c	2010-07-02 18:30:47 +0000
+++ b/mysys/my_bitmap.c	2011-02-16 15:26:19 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 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
@@ -91,6 +91,7 @@ static inline void bitmap_lock(MY_BITMAP
 #endif
 }
 
+
 static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused)))
 {
 #ifdef THREAD
@@ -100,6 +101,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)))
 {
@@ -259,7 +300,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);
 }
@@ -267,28 +308,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;
 }
 
 
@@ -296,10 +352,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;
 }
 
@@ -307,13 +365,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;
 }
 
@@ -327,14 +385,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 */
@@ -347,14 +405,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;
 }
 
 
@@ -366,15 +424,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;
   }
 }
 
@@ -405,8 +465,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;
 }
 
 
@@ -415,59 +475,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;
 }
 
@@ -475,76 +536,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);
 }
 
 
@@ -752,375 +781,3 @@ void bitmap_lock_flip_bit(MY_BITMAP *map
   bitmap_unlock(map);
 }
 #endif
-#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 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2011-01-26 07:32:41 +0000
+++ b/sql/mysql_priv.h	2011-02-22 21:03:32 +0000
@@ -1019,7 +1019,11 @@ 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);
+inline bool is_supported_parser_charset(CHARSET_INFO *cs)
+{
+  return test(cs->mbminlen == 1);
+}
 bool setup_connection_thread_globals(THD *thd);
 
 int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2011-02-02 17:05:28 +0000
+++ b/sql/set_var.cc	2011-02-18 13:12:36 +0000
@@ -1828,7 +1828,7 @@ bool sys_var::check_set(THD *thd, set_va
     }
 
     var->save_result.ulong_value= ((ulong)
-				   find_set(enum_names, res->c_ptr(),
+				   find_set(enum_names, res->c_ptr_safe(),
 					    res->length(),
                                             NULL,
                                             &error, &error_len,
@@ -2187,7 +2187,7 @@ bool sys_var_character_set_client::check
   if (sys_var_character_set_sv::check(thd, var))
     return 1;
   /* Currently, UCS-2 cannot be used as a client character set */
-  if (var->save_result.charset->mbminlen > 1)
+  if (!is_supported_parser_charset(var->save_result.charset))
   {
     my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, 
              var->save_result.charset->csname);
@@ -2941,7 +2941,7 @@ bool sys_var_thd_lc_time_names::check(TH
       my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
       return 1;
     }
-    const char *locale_str= res->c_ptr();
+    const char *locale_str= res->c_ptr_safe();
     if (!(locale_match= my_locale_by_name(locale_str)))
     {
       my_printf_error(ER_UNKNOWN_ERROR,

=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc	2010-11-11 07:34:14 +0000
+++ b/sql/sql_connect.cc	2011-02-18 13:12:36 +0000
@@ -582,8 +582,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
@@ -592,10 +607,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;
@@ -606,10 +621,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;
 }
 
 
@@ -782,7 +805,8 @@ static int check_connection(THD *thd)
     thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
     thd->max_client_packet_length= uint4korr(net->read_pos+4);
     DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
-    thd_init_client_charset(thd, (uint) net->read_pos[8]);
+    if (thd_init_client_charset(thd, (uint) net->read_pos[8]))
+      return 1;
     thd->update_charset();
     end= (char*) net->read_pos+32;
   }

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2011-01-26 07:32:41 +0000
+++ b/sql/sql_parse.cc	2011-02-22 21:03:32 +0000
@@ -1153,13 +1153,22 @@ bool dispatch_command(enum enum_server_c
 
     if (ptr < packet_end)
     {
+      CHARSET_INFO *cs;
       if (ptr + 2 > packet_end)
       {
         my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
         break;
       }
 
-      cs_number= uint2korr(ptr);
+      if ((cs_number= uint2korr(ptr)) &&
+          (cs= get_charset(cs_number, MYF(0))) &&
+          !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);
+        break;
+      }        
     }
 
     /* Convert database name to utf8 */
@@ -1205,7 +1214,11 @@ bool dispatch_command(enum enum_server_c
 
       if (cs_number)
       {
-        thd_init_client_charset(thd, cs_number);
+        /*
+          We have checked charset earlier,
+          so thd_init_client_charset cannot fail.
+        */
+        DBUG_ASSERT(!thd_init_client_charset(thd, cs_number));
         thd->update_charset();
       }
     }

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-02-08 11:52:33 +0000
+++ b/sql/sql_select.cc	2011-02-22 21:03:32 +0000
@@ -278,61 +278,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;
@@ -404,7 +408,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 07:57:15 +0000
+++ b/sql/sql_string.h	2011-02-17 11:43:53 +0000
@@ -106,6 +106,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 'storage/innodb_plugin/ChangeLog'
--- a/storage/innodb_plugin/ChangeLog	2011-02-08 17:26:42 +0000
+++ b/storage/innodb_plugin/ChangeLog	2011-02-17 11:56:05 +0000
@@ -1,3 +1,15 @@
+2011-02-15	The InnoDB Team
+
+	* sync/sync0rw.c, innodb_bug59307.test:
+	Bug#59307 Valgrind: uninitialized value in
+	rw_lock_set_writer_id_and_recursion_flag()
+
+2011-02-14	The InnoDB Team
+
+	* handler/handler0alter.cc:
+	Bug#59749 Enabling concurrent reads while creating non-primary
+	unique index gives failures
+
 2011-01-31	The InnoDB Team
 
 	* btr/btr0cur.c, include/row0upd.h,

=== modified file 'storage/innodb_plugin/btr/btr0btr.c'
--- a/storage/innodb_plugin/btr/btr0btr.c	2011-01-25 07:56:18 +0000
+++ b/storage/innodb_plugin/btr/btr0btr.c	2011-02-08 10:56:23 +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)) {
 
@@ -773,6 +1329,13 @@ 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(&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);
 	}
@@ -996,6 +1559,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 */
@@ -1024,6 +1588,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. */
@@ -1157,6 +1723,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 */
@@ -2497,6 +3064,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. */
@@ -2758,6 +3326,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)) {
@@ -2988,6 +3557,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/innodb_plugin/btr/btr0cur.c'
--- a/storage/innodb_plugin/btr/btr0cur.c	2011-02-02 13:51:08 +0000
+++ b/storage/innodb_plugin/btr/btr0cur.c	2011-02-08 10:56:23 +0000
@@ -2572,6 +2572,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);
@@ -3595,6 +3596,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);
 }
 
 /*******************************************************************//**
@@ -4094,6 +4097,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);
@@ -4169,6 +4177,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,
@@ -4337,6 +4350,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/innodb_plugin/dict/dict0mem.c'
--- a/storage/innodb_plugin/dict/dict0mem.c	2010-06-22 16:30:43 +0000
+++ b/storage/innodb_plugin/dict/dict0mem.c	2011-02-08 10:56:23 +0000
@@ -36,6 +36,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 */
@@ -316,6 +319,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/innodb_plugin/handler/handler0alter.cc'
--- a/storage/innodb_plugin/handler/handler0alter.cc	2010-11-11 05:32:12 +0000
+++ b/storage/innodb_plugin/handler/handler0alter.cc	2011-02-14 10:07:59 +0000
@@ -782,10 +782,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
@@ -911,6 +907,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/innodb_plugin/include/btr0btr.h'
--- a/storage/innodb_plugin/include/btr0btr.h	2010-11-03 09:19:12 +0000
+++ b/storage/innodb_plugin/include/btr0btr.h	2011-02-08 10:56:23 +0000
@@ -81,6 +81,91 @@ UNIQUE definition on secondary indexes w
 the insert buffer to speed up inserts */
 #define BTR_IGNORE_SEC_UNIQUE	2048
 
+#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/innodb_plugin/include/btr0types.h'
--- a/storage/innodb_plugin/include/btr0types.h	2009-05-26 12:28:49 +0000
+++ b/storage/innodb_plugin/include/btr0types.h	2011-02-08 10:56:23 +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/innodb_plugin/include/dict0mem.h'
--- a/storage/innodb_plugin/include/dict0mem.h	2011-01-14 17:02:28 +0000
+++ b/storage/innodb_plugin/include/dict0mem.h	2011-02-08 10:56:23 +0000
@@ -340,6 +340,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 */

=== modified file 'storage/innodb_plugin/include/page0zip.h'
--- a/storage/innodb_plugin/include/page0zip.h	2009-09-28 07:52:25 +0000
+++ b/storage/innodb_plugin/include/page0zip.h	2011-02-08 10:56:23 +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/innodb_plugin/include/univ.i'
--- a/storage/innodb_plugin/include/univ.i	2011-02-08 17:26:42 +0000
+++ b/storage/innodb_plugin/include/univ.i	2011-02-17 11:56:05 +0000
@@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri
 
 #define INNODB_VERSION_MAJOR	1
 #define INNODB_VERSION_MINOR	0
-#define INNODB_VERSION_BUGFIX	15
+#define INNODB_VERSION_BUGFIX	16
 
 /* The following is the InnoDB version as shown in
 SELECT plugin_version FROM information_schema.plugins;
@@ -194,6 +194,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 */

=== modified file 'storage/innodb_plugin/page/page0cur.c'
--- a/storage/innodb_plugin/page/page0cur.c	2009-09-28 07:52:25 +0000
+++ b/storage/innodb_plugin/page/page0cur.c	2011-02-08 10:56:23 +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/innodb_plugin/page/page0page.c'
--- a/storage/innodb_plugin/page/page0page.c	2010-03-25 11:03:08 +0000
+++ b/storage/innodb_plugin/page/page0page.c	2011-02-08 10:56:23 +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/innodb_plugin/page/page0zip.c'
--- a/storage/innodb_plugin/page/page0zip.c	2011-01-25 07:56:18 +0000
+++ b/storage/innodb_plugin/page/page0zip.c	2011-02-08 10:56:23 +0000
@@ -4451,6 +4451,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 */
 
@@ -4509,7 +4511,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
@@ -4579,6 +4581,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/innodb_plugin/row/row0upd.c'
--- a/storage/innodb_plugin/row/row0upd.c	2011-02-02 13:51:08 +0000
+++ b/storage/innodb_plugin/row/row0upd.c	2011-02-08 10:56:23 +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/innodb_plugin/srv/srv0start.c'
--- a/storage/innodb_plugin/srv/srv0start.c	2010-11-11 05:27:10 +0000
+++ b/storage/innodb_plugin/srv/srv0start.c	2011-02-08 10:56:23 +0000
@@ -1061,6 +1061,12 @@ innobase_start_or_create_for_mysql(void)
 		);
 #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
 	fprintf(stderr,
 		"InnoDB: !!!!!!!! UNIV_SYNC_DEBUG switched on !!!!!!!!!\n");

=== modified file 'storage/innodb_plugin/sync/sync0rw.c'
--- a/storage/innodb_plugin/sync/sync0rw.c	2011-01-18 10:25:13 +0000
+++ b/storage/innodb_plugin/sync/sync0rw.c	2011-02-15 08:51:33 +0000
@@ -260,6 +260,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/myisam/mi_create.c'
--- a/storage/myisam/mi_create.c	2010-11-10 21:14:47 +0000
+++ b/storage/myisam/mi_create.c	2011-02-15 11:03:05 +0000
@@ -272,7 +272,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;
@@ -281,7 +281,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)
@@ -297,7 +297,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 ||
@@ -422,7 +422,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
@@ -447,7 +447,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;
@@ -494,7 +494,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);
@@ -827,12 +827,14 @@ int mi_create(const char *name,uint keys
   errpos=0;
   pthread_mutex_unlock(&THR_LOCK_myisam);
   if (my_close(file,MYF(0)))
-    goto err;
+    goto err_no_lock;
   my_free((char*) rec_per_key_part,MYF(0));
   DBUG_RETURN(0);
 
 err:
   pthread_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-28 23:47:05 +0000
+++ b/support-files/mysql.spec.sh	2011-02-03 17:16:22 +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
@@ -610,7 +610,25 @@ touch $RBR%{_sysconfdir}/mysqlmanager.pa
 ##############################################################################
 
 %pre server
-mysql_datadir=%{mysqldatadir}
+# This is the code running at the beginning of a RPM upgrade action,
+# before replacing the old files with the new ones.
+
+# 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.
 
@@ -681,7 +699,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' ;;
@@ -703,8 +721,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
@@ -729,17 +747,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
 
@@ -754,7 +772,20 @@ if [ -x %{_sysconfdir}/init.d/mysql ] ;
 fi
 
 %post server
-mysql_datadir=%{mysqldatadir}
+# This is the code running at the end of a RPM install or upgrade action,
+# after the (new) files have been written.
+
+# 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
 
@@ -1133,6 +1164,13 @@ fi
 ##############################################################################
 %changelog
 
+* Thu Feb 03 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.
+
 * Wed Nov 24 2010 Alexander Nozdrin <alexander.nozdrin@oracle.com>
 
 - 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-28 23:47:05 +0000
+++ b/tests/mysql_client_test.c	2011-02-18 14:17:37 +0000
@@ -18399,6 +18399,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;
+}
+
+
+/*
   Read and parse arguments and MySQL options from my.cnf
 */
 
@@ -18724,6 +18790,7 @@ static struct my_tests_st my_tests[]= {
   { "test_bug42373", test_bug42373 },
   { "test_bug54041", test_bug54041 },
   { "test_bug47485", test_bug47485 },
+  { "test_bug58036", test_bug58036 },
   { 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-16 17:19:10 +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[bitsize2];
+  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.1-mtr branch (bjorn.munch:2982 to 2983) Bjorn Munch24 Feb