List:Commits« Previous MessageNext Message »
From:Christopher Powers Date:June 24 2011 7:31pm
Subject:bzr commit into mysql-trunk branch (chris.powers:3309)
View as plain text  
#At file:///home/cpowers/work/dev/mysql-trunk-wl4896/ based on revid:chris.powers@stripped

 3309 Christopher Powers	2011-06-24 [merge]
      Merge with mysql-trunk to pick up QA bug fixes

    added:
      mysql-test/suite/innodb/r/innodb_buffer_pool_load.result
      mysql-test/suite/innodb/t/innodb_buffer_pool_load-master.opt
      mysql-test/suite/innodb/t/innodb_buffer_pool_load.test
      mysql-test/suite/sys_vars/r/innodb_buffer_pool_dump_at_shutdown_basic.result
      mysql-test/suite/sys_vars/r/innodb_buffer_pool_dump_now_basic.result
      mysql-test/suite/sys_vars/r/innodb_buffer_pool_filename_basic.result
      mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_abort_basic.result
      mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_at_startup_basic.result
      mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_now_basic.result
      mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_at_shutdown_basic.test
      mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_now_basic.test
      mysql-test/suite/sys_vars/t/innodb_buffer_pool_filename_basic.test
      mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_abort_basic.test
      mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_at_startup_basic.test
      mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test
      storage/innobase/buf/buf0dump.c
      storage/innobase/include/buf0dump.h
      unittest/gunit/bounds_checked_array-t.cc
    modified:
      cmake/os/WindowsCache.cmake
      config.h.cmake
      configure.cmake
      extra/perror.c
      mysql-test/r/mysql_embedded.result
      mysql-test/r/ps.result
      mysql-test/r/sp_sync.result
      mysql-test/suite/innodb/r/innodb-index.result
      mysql-test/suite/innodb/t/innodb-index.test
      mysql-test/suite/perfschema/r/all_tests.result
      mysql-test/suite/perfschema/t/all_tests.test
      mysql-test/t/mysql_embedded.test
      mysql-test/t/ps.test
      mysql-test/t/sp_sync.test
      sql/item.cc
      sql/item.h
      sql/item_cmpfunc.cc
      sql/item_cmpfunc.h
      sql/item_func.cc
      sql/item_func.h
      sql/item_row.cc
      sql/item_row.h
      sql/item_strfunc.cc
      sql/item_strfunc.h
      sql/item_subselect.cc
      sql/item_sum.cc
      sql/sp.cc
      sql/sql_array.h
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_class.h
      sql/sql_db.cc
      sql/sql_derived.cc
      sql/sql_do.cc
      sql/sql_insert.cc
      sql/sql_lex.cc
      sql/sql_lex.h
      sql/sql_load.cc
      sql/sql_parse.cc
      sql/sql_prepare.cc
      sql/sql_select.cc
      sql/sql_select.h
      sql/sql_table.cc
      sql/sql_union.cc
      sql/sql_update.cc
      sql/sql_yacc.yy
      storage/innobase/CMakeLists.txt
      storage/innobase/buf/buf0buddy.c
      storage/innobase/buf/buf0buf.c
      storage/innobase/buf/buf0lru.c
      storage/innobase/buf/buf0rea.c
      storage/innobase/fil/fil0fil.c
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/include/buf0buddy.h
      storage/innobase/include/buf0buddy.ic
      storage/innobase/include/buf0buf.h
      storage/innobase/include/buf0rea.h
      storage/innobase/include/srv0srv.h
      storage/innobase/include/srv0start.h
      storage/innobase/include/ut0ut.h
      storage/innobase/srv/srv0srv.c
      storage/innobase/srv/srv0start.c
      storage/innobase/trx/trx0sys.c
      storage/innobase/ut/ut0ut.c
      unittest/gunit/CMakeLists.txt
=== modified file 'cmake/os/WindowsCache.cmake'
--- a/cmake/os/WindowsCache.cmake	2011-05-26 15:20:09 +0000
+++ b/cmake/os/WindowsCache.cmake	2011-06-17 13:29:25 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 Sun Microsystems, Inc
+# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 # 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -266,7 +266,6 @@ SET(HAVE_SYNCH_H CACHE  INTERNAL "")
 SET(HAVE_SYSENT_H CACHE  INTERNAL "")
 SET(HAVE_SYS_CDEFS_H CACHE  INTERNAL "")
 SET(HAVE_SYS_DIR_H CACHE  INTERNAL "")
-SET(HAVE_SYS_ERRLIST CACHE  INTERNAL "")
 SET(HAVE_SYS_FILE_H CACHE  INTERNAL "")
 SET(HAVE_SYS_FPU_H CACHE  INTERNAL "")
 SET(HAVE_SYS_IOCTL_H CACHE  INTERNAL "")

=== modified file 'config.h.cmake'
--- a/config.h.cmake	2011-05-27 15:46:36 +0000
+++ b/config.h.cmake	2011-06-24 19:30:01 +0000
@@ -287,7 +287,6 @@
 #cmakedefine HAVE_TZNAME 1
 #cmakedefine HAVE_AIO_READ 1
 /* Symbols we may use */
-#cmakedefine HAVE_SYS_ERRLIST 1
 /* used by stacktrace functions */
 #cmakedefine HAVE_BSS_START 1
 #cmakedefine HAVE_BACKTRACE 1

=== modified file 'configure.cmake'
--- a/configure.cmake	2011-06-06 10:29:45 +0000
+++ b/configure.cmake	2011-06-17 13:29:25 +0000
@@ -477,7 +477,6 @@ CHECK_FUNCTION_EXISTS(rdtscll HAVE_RDTSC
 # Tests for symbols
 #
 
-CHECK_SYMBOL_EXISTS(sys_errlist "stdio.h" HAVE_SYS_ERRLIST)
 CHECK_SYMBOL_EXISTS(madvise "sys/mman.h" HAVE_DECL_MADVISE)
 CHECK_SYMBOL_EXISTS(tzname "time.h" HAVE_TZNAME)
 CHECK_SYMBOL_EXISTS(lrand48 "stdlib.h" HAVE_LRAND48)

=== modified file 'extra/perror.c'
--- a/extra/perror.c	2011-03-29 12:43:49 +0000
+++ b/extra/perror.c	2011-06-23 09:51:41 +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
@@ -11,7 +11,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
 /* Return error-text for system error messages and handler messages */
 
@@ -27,8 +27,9 @@
 #include "../storage/ndb/src/kernel/error/ndbd_exit_codes.c"
 #include "../storage/ndb/include/mgmapi/mgmapi_error.h"
 #endif
+#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
 
-static my_bool verbose, print_all_codes;
+static my_bool verbose;
 
 #include "../include/my_base.h"
 #include "../mysys/my_handler_errors.h"
@@ -63,11 +64,6 @@ static struct my_option my_long_options[
   {"ndb", 257, "Ndbcluster storage engine specific error codes.", &ndb_code,
    &ndb_code, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
 #endif
-#ifdef HAVE_SYS_ERRLIST
-  {"all", 'a', "Print all the error messages and the number.",
-   &print_all_codes, &print_all_codes, 0, GET_BOOL, NO_ARG,
-   0, 0, 0, 0, 0, 0},
-#endif
   {"silent", 's', "Only print the error message.", 0, 0, 0, GET_NO_ARG, NO_ARG,
    0, 0, 0, 0, 0, 0},
   {"verbose", 'v', "Print error code and message (default).", &verbose,
@@ -78,30 +74,6 @@ static struct my_option my_long_options[
 };
 
 
-typedef struct ha_errors {
-  int errcode;
-  const char *msg;
-} HA_ERRORS;
-
-
-static HA_ERRORS ha_errlist[]=
-{
-  { -30999, "DB_INCOMPLETE: Sync didn't finish"},
-  { -30998, "DB_KEYEMPTY: Key/data deleted or never created"},
-  { -30997, "DB_KEYEXIST: The key/data pair already exists"},
-  { -30996, "DB_LOCK_DEADLOCK: Deadlock"},
-  { -30995, "DB_LOCK_NOTGRANTED: Lock unavailable"},
-  { -30994, "DB_NOSERVER: Server panic return"},
-  { -30993, "DB_NOSERVER_HOME: Bad home sent to server"},
-  { -30992, "DB_NOSERVER_ID: Bad ID sent to server"},
-  { -30991, "DB_NOTFOUND: Key/data pair not found (EOF)"},
-  { -30990, "DB_OLD_VERSION: Out-of-date version"},
-  { -30989, "DB_RUNRECOVERY: Panic return"},
-  { -30988, "DB_VERIFY_BAD: Verify failed; bad format"},
-  { 0,NullS },
-};
-
-
 static void print_version(void)
 {
   printf("%s Ver %s, for %s (%s)\n",my_progname,PERROR_VERSION,
@@ -112,7 +84,7 @@ static void print_version(void)
 static void usage(void)
 {
   print_version();
-  puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
+  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011"));
   printf("Print a description for a system error code or a MySQL error code.\n");
   printf("If you want to get the error for a negative error code, you should use\n-- before the first error code to tell perror that there was no more options.\n\n");
   printf("Usage: %s [OPTIONS] [ERRORCODE [ERRORCODE...]]\n",my_progname);
@@ -150,7 +122,7 @@ static int get_options(int *argc,char **
   if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
     exit(ho_error);
 
-  if (!*argc && !print_all_codes)
+  if (!*argc)
   {
     usage();
     return 1;
@@ -161,8 +133,6 @@ static int get_options(int *argc,char **
 
 static const char *get_ha_error_msg(int code)
 {
-  HA_ERRORS *ha_err_ptr;
-
   /*
     If you got compilation error here about compile_time_assert array, check
     that every HA_ERR_xxx constant has a corresponding error message in
@@ -174,9 +144,6 @@ static const char *get_ha_error_msg(int
   if (code >= HA_ERR_FIRST && code <= HA_ERR_LAST)
     return handler_error_messages[code - HA_ERR_FIRST];
 
-  for (ha_err_ptr=ha_errlist ; ha_err_ptr->errcode ;ha_err_ptr++)
-    if (ha_err_ptr->errcode == code)
-      return ha_err_ptr->msg;
   return NullS;
 }
 
@@ -291,22 +258,6 @@ int main(int argc,char *argv[])
   my_handler_error_register();
 
   error=0;
-#ifdef HAVE_SYS_ERRLIST
-  if (print_all_codes)
-  {
-    HA_ERRORS *ha_err_ptr;
-    for (code=1 ; code < sys_nerr ; code++)
-    {
-      if (sys_errlist[code] && sys_errlist[code][0])
-      {						/* Skip if no error-text */
-	printf("%3d = %s\n",code,sys_errlist[code]);
-      }
-    }
-    for (ha_err_ptr=ha_errlist ; ha_err_ptr->errcode ;ha_err_ptr++)
-      printf("%3d = %s\n",ha_err_ptr->errcode,ha_err_ptr->msg);
-  }
-  else
-#endif
   {
     /*
       On some system, like Linux, strerror(unknown_error) returns a

=== modified file 'mysql-test/r/mysql_embedded.result'
--- a/mysql-test/r/mysql_embedded.result	2011-06-13 18:41:24 +0000
+++ b/mysql-test/r/mysql_embedded.result	2011-06-22 11:46:29 +0000
@@ -3,3 +3,7 @@
 #
 1
 1
+#
+# Bug#11764633 : 57491: THD->MAIN_DA.IS_OK() ASSERT IN EMBEDDED
+#
+Error logging to file 'foo/bar'

=== modified file 'mysql-test/r/ps.result'
--- a/mysql-test/r/ps.result	2011-03-22 12:06:52 +0000
+++ b/mysql-test/r/ps.result	2011-06-21 07:57:31 +0000
@@ -3721,3 +3721,17 @@ FROM (SELECT 1 UNION SELECT 2) t;
 2
 #
 # End of 5.5 tests.
+#
+# Bug#12661349 assert in protocol::end_statement
+#
+# Note: This test case should be run with --ps-protocol
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (col1 INT);
+# Connection con1
+# Connection default
+KILL QUERY <con1_id>;
+# Connection con1
+SELECT * FROM t1;
+ERROR 70100: Query execution was interrupted
+# Connection default
+DROP TABLE t1;

=== modified file 'mysql-test/r/sp_sync.result'
--- a/mysql-test/r/sp_sync.result	2010-06-07 07:06:55 +0000
+++ b/mysql-test/r/sp_sync.result	2011-06-23 17:02:58 +0000
@@ -1,4 +1,4 @@
-Tests of syncronization of stored procedure execution.
+Tests of synchronization of stored procedure execution.
 SET DEBUG_SYNC= 'RESET';
 #
 # Bug #30977 Concurrent statement using stored function and
@@ -92,4 +92,16 @@ COUNT(f1(a))
 DROP PROCEDURE p1;
 DROP FUNCTION f1;
 DROP TABLES t0, t1;
-SET DEBUG_SYNC= 'RESET';
+#
+# test for bug#11756013
+#
+DROP SCHEMA IF EXISTS s1;
+CREATE SCHEMA s1;
+CREATE PROCEDURE s1.p1() BEGIN END;
+SET DEBUG_SYNC='before_db_dir_check SIGNAL check_db WAIT_FOR dropped_schema';
+CALL s1.p1;
+SET DEBUG_SYNC='now WAIT_FOR check_db';
+DROP SCHEMA s1;
+SET DEBUG_SYNC='now SIGNAL dropped_schema';
+ERROR 42000: Unknown database 's1'
+SET DEBUG_SYNC = 'RESET';

=== modified file 'mysql-test/suite/innodb/r/innodb-index.result'
--- a/mysql-test/suite/innodb/r/innodb-index.result	2011-05-31 09:30:59 +0000
+++ b/mysql-test/suite/innodb/r/innodb-index.result	2011-06-23 09:51:41 +0000
@@ -1084,3 +1084,44 @@ t2	CREATE TABLE `t2` (
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 DROP TABLE t2;
 DROP TABLE t1;
+CREATE TABLE t1 (a INT, b CHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (3,'a'),(3,'b'),(1,'c'),(0,'d'),(1,'e');
+CREATE TABLE t2 (a INT, b CHAR(1)) ENGINE=InnoDB;
+INSERT INTO t2 SELECT * FROM t1;
+BEGIN;
+SELECT * FROM t1;
+a	b
+3	a
+3	b
+1	c
+0	d
+1	e
+SET lock_wait_timeout=1;
+CREATE INDEX t1a ON t1(a);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+CREATE INDEX t2a ON t2(a);
+SELECT * FROM t2;
+a	b
+3	a
+3	b
+1	c
+0	d
+1	e
+SELECT * FROM t2 FORCE INDEX(t2a) ORDER BY a;
+ERROR HY000: Table definition has changed, please retry transaction
+SELECT * FROM t2;
+a	b
+3	a
+3	b
+1	c
+0	d
+1	e
+COMMIT;
+SELECT * FROM t2 FORCE INDEX(t2a) ORDER BY a;
+a	b
+0	d
+1	c
+1	e
+3	a
+3	b
+DROP TABLE t1,t2;

=== added file 'mysql-test/suite/innodb/r/innodb_buffer_pool_load.result'
--- a/mysql-test/suite/innodb/r/innodb_buffer_pool_load.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_load.result	2011-06-23 13:29:26 +0000
@@ -0,0 +1,28 @@
+CREATE TABLE ib_bp_test
+(a INT AUTO_INCREMENT, b VARCHAR(64), c TEXT, PRIMARY KEY (a), KEY (b, c(128)))
+ENGINE=INNODB;
+SELECT COUNT(*) FROM information_schema.innodb_buffer_page_lru
+WHERE table_name LIKE '%ib_bp_test';
+COUNT(*)
+2
+SELECT COUNT(*) FROM information_schema.innodb_buffer_page_lru
+WHERE table_name LIKE '%ib_bp_test';
+COUNT(*)
+329
+SET GLOBAL innodb_buffer_pool_dump_now = ON;
+select count(*) from ib_bp_test where a = 1;
+count(*)
+1
+SET GLOBAL innodb_buffer_pool_load_now = ON;
+SELECT variable_value
+FROM information_schema.global_status
+WHERE variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS';
+variable_value
+Buffer pool(s) load completed at TIMESTAMP_NOW
+SELECT COUNT(*) FROM information_schema.innodb_buffer_page_lru
+WHERE table_name LIKE '%ib_bp_test';
+COUNT(*)
+329
+call mtr.add_suppression("InnoDB: Error parsing");
+SET GLOBAL innodb_buffer_pool_load_now = ON;
+DROP TABLE ib_bp_test;

=== modified file 'mysql-test/suite/innodb/t/innodb-index.test'
--- a/mysql-test/suite/innodb/t/innodb-index.test	2011-05-31 09:30:59 +0000
+++ b/mysql-test/suite/innodb/t/innodb-index.test	2011-06-23 09:51:41 +0000
@@ -514,34 +514,35 @@ SHOW CREATE TABLE t2;
 DROP TABLE t2;
 DROP TABLE t1;
 
-# The following tests are disabled because of the introduced timeouts for
-# metadata locks at the MySQL level as part of the fix for
-# Bug#45225 Locking: hang if drop table with no timeout
-# The following CREATE INDEX t1a ON t1(a); causes a lock wait timeout
-# start disabled45225_2
-#connect (a,localhost,root,,);
-#connect (b,localhost,root,,);
-#connection a;
-#CREATE TABLE t1 (a INT, b CHAR(1)) ENGINE=InnoDB;
-#INSERT INTO t1 VALUES (3,'a'),(3,'b'),(1,'c'),(0,'d'),(1,'e');
-#connection b;
-#BEGIN;
-#SELECT * FROM t1;
-#connection a;
-#CREATE INDEX t1a ON t1(a);
-#connection b;
-#SELECT * FROM t1;
-#--error ER_TABLE_DEF_CHANGED
-#SELECT * FROM t1 FORCE INDEX(t1a) ORDER BY a;
-#SELECT * FROM t1;
-#COMMIT;
-#SELECT * FROM t1 FORCE INDEX(t1a) ORDER BY a;
-#connection default;
-#disconnect a;
-#disconnect b;
-#
-#DROP TABLE t1;
-# end disabled45225_2
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+connection a;
+CREATE TABLE t1 (a INT, b CHAR(1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (3,'a'),(3,'b'),(1,'c'),(0,'d'),(1,'e');
+CREATE TABLE t2 (a INT, b CHAR(1)) ENGINE=InnoDB;
+INSERT INTO t2 SELECT * FROM t1;
+connection b;
+BEGIN;
+# This acquires a MDL lock on t1 until commit.
+SELECT * FROM t1;
+connection a;
+# This times out before of the MDL lock held by connection b.
+SET lock_wait_timeout=1;
+--error ER_LOCK_WAIT_TIMEOUT
+CREATE INDEX t1a ON t1(a);
+CREATE INDEX t2a ON t2(a);
+connection b;
+SELECT * FROM t2;
+--error ER_TABLE_DEF_CHANGED
+SELECT * FROM t2 FORCE INDEX(t2a) ORDER BY a;
+SELECT * FROM t2;
+COMMIT;
+SELECT * FROM t2 FORCE INDEX(t2a) ORDER BY a;
+connection default;
+disconnect a;
+disconnect b;
+
+DROP TABLE t1,t2;
 
 #
 # restore environment to the state it was before this test execution

=== added file 'mysql-test/suite/innodb/t/innodb_buffer_pool_load-master.opt'
--- a/mysql-test/suite/innodb/t/innodb_buffer_pool_load-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_load-master.opt	2011-06-23 06:48:48 +0000
@@ -0,0 +1 @@
+--innodb-buffer-pool-size=16M

=== added file 'mysql-test/suite/innodb/t/innodb_buffer_pool_load.test'
--- a/mysql-test/suite/innodb/t/innodb_buffer_pool_load.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_load.test	2011-06-23 13:29:26 +0000
@@ -0,0 +1,109 @@
+#
+# Test for the functionality of InnoDB Buffer Pool dump/load.
+#
+
+-- source include/have_innodb.inc
+# include/restart_mysqld.inc does not work in embedded mode
+-- source include/not_embedded.inc
+
+-- let $file = `SELECT CONCAT(@@datadir, @@global.innodb_buffer_pool_filename)`
+
+-- error 0,1
+-- remove_file $file
+
+# Create a table and populate it with some data
+CREATE TABLE ib_bp_test
+(a INT AUTO_INCREMENT, b VARCHAR(64), c TEXT, PRIMARY KEY (a), KEY (b, c(128)))
+ENGINE=INNODB;
+
+let $check_cnt =
+SELECT COUNT(*) FROM information_schema.innodb_buffer_page_lru
+WHERE table_name LIKE '%ib_bp_test';
+
+# See that we have a small number of pages in the LRU
+-- eval $check_cnt
+
+# Here we end up with 16382 rows in the table
+-- disable_query_log
+INSERT INTO ib_bp_test (b, c) VALUES (REPEAT('b', 64), REPEAT('c', 256));
+INSERT INTO ib_bp_test (b, c) VALUES (REPEAT('B', 64), REPEAT('C', 256));
+let $i=12;
+while ($i)
+{
+  -- eval INSERT INTO ib_bp_test (b, c) VALUES ($i, $i * $i);
+  INSERT INTO ib_bp_test (b, c) SELECT b, c FROM ib_bp_test;
+  dec $i;
+}
+-- enable_query_log
+
+-- eval $check_cnt
+
+# Dump
+SET GLOBAL innodb_buffer_pool_dump_now = ON;
+
+# Wait for the dump to complete
+let $wait_condition =
+  SELECT SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) dump completed at '
+  FROM information_schema.global_status
+  WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS';
+-- source include/wait_condition.inc
+
+# Confirm the file has been created
+-- file_exists $file
+
+# Add some garbage records to the dump file
+-- let IBDUMPFILE = $file
+perl;
+my $fn = $ENV{'IBDUMPFILE'};
+open(my $fh, '>>', $fn) || die "perl open($fn): $!";
+print $fh "123456,0\n";
+print $fh "0,123456\n";
+print $fh "123456,123456\n";
+close($fh);
+EOF
+
+-- source include/restart_mysqld.inc
+
+# Load the table so that entries in the I_S table do not appear as NULL
+select count(*) from ib_bp_test where a = 1;
+
+# Load
+SET GLOBAL innodb_buffer_pool_load_now = ON;
+
+# Wait for the load to complete
+let $wait_condition =
+  SELECT SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) load completed at '
+  FROM information_schema.global_status
+  WHERE variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS';
+-- source include/wait_condition.inc
+
+# Show the status, interesting if the above timed out
+-- replace_regex /[0-9]{6}[[:space:]]+[0-9]{1,2}:[0-9]{2}:[0-9]{2}/TIMESTAMP_NOW/
+SELECT variable_value
+FROM information_schema.global_status
+WHERE variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS';
+
+-- eval $check_cnt
+
+# Add some total garbage to the dump file
+-- let IBDUMPFILE = $file
+perl;
+my $fn = $ENV{'IBDUMPFILE'};
+open(my $fh, '>>', $fn) || die "perl open($fn): $!";
+print $fh "abcdefg\n";
+close($fh);
+EOF
+
+call mtr.add_suppression("InnoDB: Error parsing");
+
+# Load
+SET GLOBAL innodb_buffer_pool_load_now = ON;
+
+# Wait for the load to fail
+let $wait_condition =
+  SELECT SUBSTR(variable_value, 1, 13) = 'Error parsing'
+  FROM information_schema.global_status
+  WHERE variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS';
+-- source include/wait_condition.inc
+
+DROP TABLE ib_bp_test;

=== modified file 'mysql-test/suite/perfschema/r/all_tests.result'
--- a/mysql-test/suite/perfschema/r/all_tests.result	2011-02-27 02:46:11 +0000
+++ b/mysql-test/suite/perfschema/r/all_tests.result	2011-06-24 19:30:01 +0000
@@ -2,7 +2,7 @@ drop table if exists t1;
 drop table if exists t2;
 create table t1 (test_name text);
 create table t2 (test_name text);
-load data infile "MYSQLTEST_VARDIR/tmp/perfschema-all_tests.txt" into table t1;
+load data infile "<MYSQLTEST_VARDIR>/tmp/perfschema-all_tests.txt" into table t1;
 insert into t2 select concat('ddl_', table_name, '.test') from information_schema.tables
 where table_schema='performance_schema';
 insert into t2 select concat('dml_', table_name, '.test') from information_schema.tables

=== modified file 'mysql-test/suite/perfschema/t/all_tests.test'
--- a/mysql-test/suite/perfschema/t/all_tests.test	2011-02-09 15:22:04 +0000
+++ b/mysql-test/suite/perfschema/t/all_tests.test	2011-06-21 13:38:03 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
 --source include/not_embedded.inc
 
 #
-# Test based on mysql-test/suite/sys_vars/all_vars.test,
+# Test based on mysql-test/suite/sys_vars/t/all_vars.test
 # and adapted for the performance schema tables.
 #
 # This test verifies that *all* performance schema tables are tested
@@ -46,7 +46,7 @@ drop table if exists t2;
 
 create table t1 (test_name text);
 create table t2 (test_name text);
---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--replace_result $MYSQLTEST_VARDIR <MYSQLTEST_VARDIR>
 eval load data infile "$MYSQLTEST_VARDIR/tmp/perfschema-all_tests.txt" into table t1;
 
 insert into t2 select concat('ddl_', table_name, '.test') from information_schema.tables
@@ -76,3 +76,4 @@ select test_name as `MISSING DDL/DML TES
 drop table t1;
 drop table t2;
 
+--remove_file $MYSQLTEST_VARDIR/tmp/perfschema-all_tests.txt

=== added file 'mysql-test/suite/sys_vars/r/innodb_buffer_pool_dump_at_shutdown_basic.result'
--- a/mysql-test/suite/sys_vars/r/innodb_buffer_pool_dump_at_shutdown_basic.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/innodb_buffer_pool_dump_at_shutdown_basic.result	2011-06-23 06:48:48 +0000
@@ -0,0 +1,18 @@
+SET @orig = @@global.innodb_buffer_pool_dump_at_shutdown;
+SELECT @orig;
+@orig
+0
+SET GLOBAL innodb_buffer_pool_dump_at_shutdown = OFF;
+SELECT @@global.innodb_buffer_pool_dump_at_shutdown;
+@@global.innodb_buffer_pool_dump_at_shutdown
+0
+SET GLOBAL innodb_buffer_pool_dump_at_shutdown = ON;
+SELECT @@global.innodb_buffer_pool_dump_at_shutdown;
+@@global.innodb_buffer_pool_dump_at_shutdown
+1
+SET GLOBAL innodb_buffer_pool_dump_at_shutdown = 12.34;
+Got one of the listed errors
+SET GLOBAL innodb_buffer_pool_dump_at_shutdown = "string";
+Got one of the listed errors
+SET GLOBAL innodb_buffer_pool_dump_at_shutdown = 5;
+Got one of the listed errors

=== added file 'mysql-test/suite/sys_vars/r/innodb_buffer_pool_dump_now_basic.result'
--- a/mysql-test/suite/sys_vars/r/innodb_buffer_pool_dump_now_basic.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/innodb_buffer_pool_dump_now_basic.result	2011-06-23 06:48:48 +0000
@@ -0,0 +1,8 @@
+SET @orig = @@global.innodb_buffer_pool_dump_now;
+SELECT @orig;
+@orig
+0
+SET GLOBAL innodb_buffer_pool_dump_now = ON;
+SELECT @@global.innodb_buffer_pool_dump_now;
+@@global.innodb_buffer_pool_dump_now
+0

=== added file 'mysql-test/suite/sys_vars/r/innodb_buffer_pool_filename_basic.result'
--- a/mysql-test/suite/sys_vars/r/innodb_buffer_pool_filename_basic.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/innodb_buffer_pool_filename_basic.result	2011-06-23 06:48:48 +0000
@@ -0,0 +1,8 @@
+SET @orig = @@global.innodb_buffer_pool_filename;
+SELECT @orig;
+@orig
+ib_buffer_pool
+SET GLOBAL innodb_buffer_pool_dump_now = ON;
+SET GLOBAL innodb_buffer_pool_filename = 'innodb_foobar_dump';
+SET GLOBAL innodb_buffer_pool_dump_now = ON;
+SET GLOBAL innodb_buffer_pool_filename = @orig;

=== added file 'mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_abort_basic.result'
--- a/mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_abort_basic.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_abort_basic.result	2011-06-23 06:48:48 +0000
@@ -0,0 +1,8 @@
+SET @orig = @@global.innodb_buffer_pool_load_abort;
+SELECT @orig;
+@orig
+0
+SET GLOBAL innodb_buffer_pool_load_abort = ON;
+SELECT @@global.innodb_buffer_pool_load_abort;
+@@global.innodb_buffer_pool_load_abort
+0

=== added file 'mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_at_startup_basic.result'
--- a/mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_at_startup_basic.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_at_startup_basic.result	2011-06-23 06:48:48 +0000
@@ -0,0 +1,8 @@
+SET @orig = @@global.innodb_buffer_pool_load_at_startup;
+SELECT @orig;
+@orig
+0
+SET GLOBAL innodb_buffer_pool_load_at_startup = OFF;
+ERROR HY000: Variable 'innodb_buffer_pool_load_at_startup' is a read only variable
+SET GLOBAL innodb_buffer_pool_load_at_startup = ON;
+ERROR HY000: Variable 'innodb_buffer_pool_load_at_startup' is a read only variable

=== added file 'mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_now_basic.result'
--- a/mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_now_basic.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/innodb_buffer_pool_load_now_basic.result	2011-06-23 06:48:48 +0000
@@ -0,0 +1,11 @@
+SET @orig = @@global.innodb_buffer_pool_load_now;
+SELECT @orig;
+@orig
+0
+SET GLOBAL innodb_buffer_pool_dump_now = ON;
+SET GLOBAL innodb_buffer_pool_load_now = ON;
+SELECT variable_value
+FROM information_schema.global_status
+WHERE variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS';
+variable_value
+Buffer pool(s) load completed at TIMESTAMP_NOW

=== added file 'mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_at_shutdown_basic.test'
--- a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_at_shutdown_basic.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_at_shutdown_basic.test	2011-06-23 06:48:48 +0000
@@ -0,0 +1,42 @@
+#
+# Basic test for innodb_buffer_pool_dump_at_shutdown
+#
+
+-- source include/have_innodb.inc
+# include/restart_mysqld.inc does not work in embedded mode
+-- source include/not_embedded.inc
+
+# Check the default value
+SET @orig = @@global.innodb_buffer_pool_dump_at_shutdown;
+SELECT @orig;
+
+# Confirm that we can change the value
+SET GLOBAL innodb_buffer_pool_dump_at_shutdown = OFF;
+SELECT @@global.innodb_buffer_pool_dump_at_shutdown;
+SET GLOBAL innodb_buffer_pool_dump_at_shutdown = ON;
+SELECT @@global.innodb_buffer_pool_dump_at_shutdown;
+
+# Check the type
+
+-- error ER_WRONG_TYPE_FOR_VAR, ER_WRONG_VALUE_FOR_VAR
+SET GLOBAL innodb_buffer_pool_dump_at_shutdown = 12.34;
+
+-- error ER_WRONG_TYPE_FOR_VAR, ER_WRONG_VALUE_FOR_VAR
+SET GLOBAL innodb_buffer_pool_dump_at_shutdown = "string";
+
+-- error ER_WRONG_TYPE_FOR_VAR, ER_WRONG_VALUE_FOR_VAR
+SET GLOBAL innodb_buffer_pool_dump_at_shutdown = 5;
+
+# Confirm that the dump file is created at shutdown
+
+-- let $file = `SELECT CONCAT(@@datadir, @@global.innodb_buffer_pool_filename)`
+
+-- error 0,1
+-- remove_file $file
+
+-- error 1
+-- file_exists $file
+
+-- source include/restart_mysqld.inc
+
+-- file_exists $file

=== added file 'mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_now_basic.test'
--- a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_now_basic.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_dump_now_basic.test	2011-06-23 06:48:48 +0000
@@ -0,0 +1,25 @@
+#
+# Basic test for innodb_buffer_pool_dump_now
+#
+
+-- source include/have_innodb.inc
+
+# Check the default value
+SET @orig = @@global.innodb_buffer_pool_dump_now;
+SELECT @orig;
+
+# Do the dump
+SET GLOBAL innodb_buffer_pool_dump_now = ON;
+# Should always be OFF
+SELECT @@global.innodb_buffer_pool_dump_now;
+
+# Wait for the dump to complete
+let $wait_condition =
+  SELECT SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) dump completed at '
+  FROM information_schema.global_status
+  WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS';
+-- source include/wait_condition.inc
+
+# Confirm that the dump file has been created
+-- let $file = `SELECT CONCAT(@@datadir, @@global.innodb_buffer_pool_filename)`
+-- file_exists $file

=== added file 'mysql-test/suite/sys_vars/t/innodb_buffer_pool_filename_basic.test'
--- a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_filename_basic.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_filename_basic.test	2011-06-23 06:48:48 +0000
@@ -0,0 +1,42 @@
+#
+# Basic test for innodb_buffer_pool_filename
+#
+
+-- source include/have_innodb.inc
+
+# Check the default value and save for later restoration
+SET @orig = @@global.innodb_buffer_pool_filename;
+SELECT @orig;
+
+# Do a dump and check that the file has been created
+
+SET GLOBAL innodb_buffer_pool_dump_now = ON;
+-- let $file = `SELECT CONCAT(@@datadir, @@global.innodb_buffer_pool_filename)`
+
+# Wait for the dump to complete
+let $wait_condition =
+  SELECT SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) dump completed at '
+  FROM information_schema.global_status
+  WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS';
+-- source include/wait_condition.inc
+
+-- file_exists $file
+
+# Try with a non-default filename
+
+SET GLOBAL innodb_buffer_pool_filename = 'innodb_foobar_dump';
+
+SET GLOBAL innodb_buffer_pool_dump_now = ON;
+-- let $file = `SELECT CONCAT(@@datadir, @@global.innodb_buffer_pool_filename)`
+
+# Wait for the dump to complete
+let $wait_condition =
+  SELECT SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) dump completed at '
+  FROM information_schema.global_status
+  WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS';
+-- source include/wait_condition.inc
+
+-- file_exists $file
+
+# Restore the env
+SET GLOBAL innodb_buffer_pool_filename = @orig;

=== added file 'mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_abort_basic.test'
--- a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_abort_basic.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_abort_basic.test	2011-06-23 06:48:48 +0000
@@ -0,0 +1,15 @@
+#
+# Basic test for innodb_buffer_pool_load_abort
+#
+
+-- source include/have_innodb.inc
+
+# Check the default value
+SET @orig = @@global.innodb_buffer_pool_load_abort;
+SELECT @orig;
+
+# Confirm that the value remains OFF after being set to ON
+
+SET GLOBAL innodb_buffer_pool_load_abort = ON;
+
+SELECT @@global.innodb_buffer_pool_load_abort;

=== added file 'mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_at_startup_basic.test'
--- a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_at_startup_basic.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_at_startup_basic.test	2011-06-23 06:48:48 +0000
@@ -0,0 +1,15 @@
+#
+# Basic test for innodb_buffer_pool_load_at_startup
+#
+
+-- source include/have_innodb.inc
+
+# Check the default value
+SET @orig = @@global.innodb_buffer_pool_load_at_startup;
+SELECT @orig;
+
+# Confirm that we can not change the value
+-- error 1238
+SET GLOBAL innodb_buffer_pool_load_at_startup = OFF;
+-- error 1238
+SET GLOBAL innodb_buffer_pool_load_at_startup = ON;

=== added file 'mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test'
--- a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test	2011-06-23 06:48:48 +0000
@@ -0,0 +1,39 @@
+#
+# Basic test for innodb_buffer_pool_load_now
+#
+
+-- source include/have_innodb.inc
+
+# Check the default value
+SET @orig = @@global.innodb_buffer_pool_load_now;
+SELECT @orig;
+
+# Do the dump
+SET GLOBAL innodb_buffer_pool_dump_now = ON;
+
+# Wait for the dump to complete
+let $wait_condition =
+  SELECT SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) dump completed at '
+  FROM information_schema.global_status
+  WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS';
+-- source include/wait_condition.inc
+
+# Confirm the file is really created
+-- let $file = `SELECT CONCAT(@@datadir, @@global.innodb_buffer_pool_filename)`
+-- file_exists $file
+
+# Load the dump
+SET GLOBAL innodb_buffer_pool_load_now = ON;
+
+# Wait for the load to complete
+let $wait_condition =
+  SELECT SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) load completed at '
+  FROM information_schema.global_status
+  WHERE variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS';
+-- source include/wait_condition.inc
+
+# Show the status, interesting if the above timed out
+-- replace_regex /[0-9]{6}[[:space:]]+[0-9]{1,2}:[0-9]{2}:[0-9]{2}/TIMESTAMP_NOW/
+SELECT variable_value
+FROM information_schema.global_status
+WHERE variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS';

=== modified file 'mysql-test/t/mysql_embedded.test'
--- a/mysql-test/t/mysql_embedded.test	2011-06-16 13:55:11 +0000
+++ b/mysql-test/t/mysql_embedded.test	2011-06-22 11:46:29 +0000
@@ -1,12 +1,18 @@
+--source include/is_embedded.inc
+
 --echo #
 --echo # Bug#12561297 : LIBMYSQLD/EXAMPLE/MYSQL_EMBEDDED IS ABORTING.
 --echo #
 
---source include/is_embedded.inc
-
 # Test case require mysql_embedded to be present
 if(!$MYSQL_EMBEDDED)
 {
   --skip Test requires mysql_embedded executable
 }
 --exec $MYSQL_EMBEDDED -e 'select 1'
+
+--echo #
+--echo # Bug#11764633 : 57491: THD->MAIN_DA.IS_OK() ASSERT IN EMBEDDED
+--echo #
+
+--exec $MYSQL_EMBEDDED -e '\T foo/bar'

=== modified file 'mysql-test/t/ps.test'
--- a/mysql-test/t/ps.test	2011-03-22 12:06:52 +0000
+++ b/mysql-test/t/ps.test	2011-06-21 07:57:31 +0000
@@ -3328,3 +3328,37 @@ FROM (SELECT 1 UNION SELECT 2) t;
 --echo # End of 5.5 tests.
 
 ###########################################################################
+
+
+--echo #
+--echo # Bug#12661349 assert in protocol::end_statement
+--echo #
+
+--echo # Note: This test case should be run with --ps-protocol
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (col1 INT);
+
+--echo # Connection con1
+connect(con1, localhost, root);
+let $con1_id= `SELECT CONNECTION_ID()`;
+
+--echo # Connection default
+connection default;
+--replace_result $con1_id <con1_id>
+eval KILL QUERY $con1_id;
+
+--echo # Connection con1
+connection con1;
+# Here the server asserts when running with "--ps-protocol"
+--error ER_QUERY_INTERRUPTED
+SELECT * FROM t1;
+disconnect con1;
+--source include/wait_until_disconnected.inc
+
+--echo # Connection default
+connection default;
+DROP TABLE t1;

=== modified file 'mysql-test/t/sp_sync.test'
--- a/mysql-test/t/sp_sync.test	2010-08-06 11:29:37 +0000
+++ b/mysql-test/t/sp_sync.test	2011-06-23 17:02:58 +0000
@@ -1,7 +1,7 @@
 # This test should work in embedded server after mysqltest is fixed
 -- source include/not_embedded.inc
 
---echo Tests of syncronization of stored procedure execution.
+--echo Tests of synchronization of stored procedure execution.
 
 --source include/have_debug_sync.inc
 
@@ -149,9 +149,34 @@ disconnect con2;
 DROP PROCEDURE p1;
 DROP FUNCTION f1;
 DROP TABLES t0, t1;
-SET DEBUG_SYNC= 'RESET';
 
 
+--echo #
+--echo # test for bug#11756013
+--echo #
+--disable_warnings
+DROP SCHEMA IF EXISTS s1;
+--enable_warnings
+CREATE SCHEMA s1;
+CREATE PROCEDURE s1.p1() BEGIN END;
+
+connect (con3, localhost, root);
+SET DEBUG_SYNC='before_db_dir_check SIGNAL check_db WAIT_FOR dropped_schema';
+--send CALL s1.p1
+
+connection default;
+SET DEBUG_SYNC='now WAIT_FOR check_db';
+DROP SCHEMA s1;
+SET DEBUG_SYNC='now SIGNAL dropped_schema';
+
+connection con3;
+--error ER_BAD_DB_ERROR
+--reap
+connection default;
+disconnect con3;
+
+SET DEBUG_SYNC = 'RESET';
+
 # Check that all connections opened by test cases in this file are really
 # gone so execution of other tests won't be affected by their presence.
 --source include/wait_until_count_sessions.inc

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2011-06-06 12:49:55 +0000
+++ b/sql/item.cc	2011-06-24 09:29:07 +0000
@@ -1489,7 +1489,7 @@ public:
     thd->fatal_error() may be called if we are out of memory
 */
 
-void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
+void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
                            List<Item> &fields, Item **ref, 
                            bool skip_registered)
 {
@@ -1526,7 +1526,7 @@ void Item::split_sum_func2(THD *thd, Ite
 
     ref_pointer_array[el]= real_itm;
     if (!(item_ref= new Item_aggregate_ref(&thd->lex->current_select->context,
-                                           ref_pointer_array + el, 0, name)))
+                                           &ref_pointer_array[el], 0, name)))
       return;                                   // fatal_error is set
     if (type() == SUM_FUNC_ITEM)
       item_ref->depended_from= ((Item_sum *) this)->depended_from(); 
@@ -4345,7 +4345,7 @@ resolve_ref_in_select_and_group(THD *thd
         return NULL;
       }
       DBUG_ASSERT((*select_ref)->fixed);
-      return (select->ref_pointer_array + counter);
+      return &select->ref_pointer_array[counter];
     }
     if (group_by_ref)
       return group_by_ref;
@@ -6233,13 +6233,13 @@ Item *Item_field::update_value_transform
       type() != Item::TRIGGER_FIELD_ITEM)
   {
     List<Item> *all_fields= &select->join->all_fields;
-    Item **ref_pointer_array= select->ref_pointer_array;
+    Ref_ptr_array &ref_pointer_array= select->ref_pointer_array;
     int el= all_fields->elements;
     Item_ref *ref;
 
     ref_pointer_array[el]= (Item*)this;
     all_fields->push_front((Item*)this);
-    ref= new Item_ref(&select->context, ref_pointer_array + el,
+    ref= new Item_ref(&select->context, &ref_pointer_array[el],
                       table_name, field_name);
     return ref;
   }

=== modified file 'sql/item.h'
--- a/sql/item.h	2011-06-10 15:29:04 +0000
+++ b/sql/item.h	2011-06-24 09:29:07 +0000
@@ -23,6 +23,7 @@
 #include "unireg.h"                    // REQUIRED: for other includes
 #include "thr_malloc.h"                         /* sql_calloc */
 #include "field.h"                              /* Derivation */
+#include "sql_array.h"
 
 class Protocol;
 struct TABLE_LIST;
@@ -30,6 +31,7 @@ void item_init(void);			/* Init item fun
 class Item_field;
 class user_var_entry;
 
+typedef Bounds_checked_array<Item*> Ref_ptr_array;
 
 static inline uint32
 char_to_byte_length_safe(uint32 char_length_arg, uint32 mbmaxlen_arg)
@@ -932,10 +934,11 @@ public:
 
   void print_item_w_name(String *, enum_query_type query_type);
   virtual void update_used_tables() {}
-  virtual void split_sum_func(THD *thd, Item **ref_pointer_array,
+  virtual void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
                               List<Item> &fields) {}
   /* Called for items that really have to be split */
-  void split_sum_func2(THD *thd, Item **ref_pointer_array, List<Item> &fields,
+  void split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
+                       List<Item> &fields,
                        Item **ref, bool skip_registered);
   virtual bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
   virtual bool get_time(MYSQL_TIME *ltime);

=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc	2011-06-09 06:22:39 +0000
+++ b/sql/item_cmpfunc.cc	2011-06-24 09:29:07 +0000
@@ -4591,7 +4591,7 @@ void Item_cond::traverse_cond(Cond_trave
     that have or refer (HAVING) to a SUM expression.
 */
 
-void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array,
+void Item_cond::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
                                List<Item> &fields)
 {
   List_iterator<Item> li(list);

=== modified file 'sql/item_cmpfunc.h'
--- a/sql/item_cmpfunc.h	2011-06-09 06:22:39 +0000
+++ b/sql/item_cmpfunc.h	2011-06-24 09:29:07 +0000
@@ -1540,7 +1540,8 @@ public:
   table_map used_tables() const;
   void update_used_tables();
   virtual void print(String *str, enum_query_type query_type);
-  void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
+  void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
+                      List<Item> &fields);
   friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
                          Item **conds);
   void top_level_item() { abort_on_null=1; }

=== modified file 'sql/item_func.cc'
--- a/sql/item_func.cc	2011-06-09 06:22:39 +0000
+++ b/sql/item_func.cc	2011-06-24 09:29:07 +0000
@@ -392,7 +392,7 @@ Item *Item_func::compile(Item_analyzer a
   See comments in Item_cmp_func::split_sum_func()
 */
 
-void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
+void Item_func::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
                                List<Item> &fields)
 {
   Item **arg, **arg_end;

=== modified file 'sql/item_func.h'
--- a/sql/item_func.h	2011-05-05 07:41:53 +0000
+++ b/sql/item_func.h	2011-06-24 09:29:07 +0000
@@ -135,7 +135,8 @@ public:
   void set_arguments(List<Item> &list);
   inline uint argument_count() const { return arg_count; }
   inline void remove_arguments() { arg_count=0; }
-  void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
+  void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
+                      List<Item> &fields);
   virtual void print(String *str, enum_query_type query_type);
   void print_op(String *str, enum_query_type query_type);
   void print_args(String *str, uint from, enum_query_type query_type);

=== modified file 'sql/item_row.cc'
--- a/sql/item_row.cc	2011-06-09 06:22:39 +0000
+++ b/sql/item_row.cc	2011-06-24 09:29:07 +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
@@ -113,7 +113,7 @@ void Item_row::cleanup()
 }
 
 
-void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array,
+void Item_row::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
                               List<Item> &fields)
 {
   Item **arg, **arg_end;

=== modified file 'sql/item_row.h'
--- a/sql/item_row.h	2010-10-15 10:32:50 +0000
+++ b/sql/item_row.h	2011-06-24 09:29:07 +0000
@@ -66,7 +66,8 @@ public:
   void fix_after_pullout(st_select_lex *parent_select,
                          st_select_lex *removed_select, Item **ref);
   void cleanup();
-  void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
+  void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
+                      List<Item> &fields);
   table_map used_tables() const { return used_tables_cache; };
   bool const_item() const { return const_item_cache; };
   enum Item_result result_type() const { return ROW_RESULT; }

=== modified file 'sql/item_strfunc.cc'
--- a/sql/item_strfunc.cc	2011-06-09 06:22:39 +0000
+++ b/sql/item_strfunc.cc	2011-06-24 09:29:07 +0000
@@ -2540,7 +2540,8 @@ String *Item_func_elt::val_str(String *s
 }
 
 
-void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array,
+void Item_func_make_set::split_sum_func(THD *thd,
+                                        Ref_ptr_array ref_pointer_array,
 					List<Item> &fields)
 {
   item->split_sum_func2(thd, ref_pointer_array, fields, &item, TRUE);

=== modified file 'sql/item_strfunc.h'
--- a/sql/item_strfunc.h	2011-04-15 09:04:21 +0000
+++ b/sql/item_strfunc.h	2011-06-24 09:29:07 +0000
@@ -556,7 +556,8 @@ public:
 	    item->check_cols(1) ||
 	    Item_func::fix_fields(thd, ref));
   }
-  void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
+  void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
+                      List<Item> &fields);
   void fix_length_and_dec();
   void update_used_tables();
   const char *func_name() const { return "make_set"; }

=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc	2011-05-24 09:36:11 +0000
+++ b/sql/item_subselect.cc	2011-06-24 09:29:07 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2002, 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
@@ -1126,7 +1126,7 @@ Item_in_subselect::single_value_transfor
 	  (ALL && (> || =>)) || (ANY && (< || =<))
 	  for ALL condition is inverted
 	*/
-	item= new Item_sum_max(*select_lex->ref_pointer_array);
+	item= new Item_sum_max(join->ref_ptrs[0]);
       }
       else
       {
@@ -1134,11 +1134,11 @@ Item_in_subselect::single_value_transfor
 	  (ALL && (< || =<)) || (ANY && (> || =>))
 	  for ALL condition is inverted
 	*/
-	item= new Item_sum_min(*select_lex->ref_pointer_array);
+	item= new Item_sum_min(join->ref_ptrs[0]);
       }
       if (upper_item)
         upper_item->set_sum_test(item);
-      *select_lex->ref_pointer_array= item;
+      join->ref_ptrs[0]= item;
       {
 	List_iterator<Item> it(select_lex->item_list);
 	it++;
@@ -1220,7 +1220,8 @@ Item_in_subselect::single_value_transfor
     DBUG_RETURN(RES_OK);
 
   /* Perform the IN=>EXISTS transformation. */
-  DBUG_RETURN(single_value_in_to_exists_transformer(join, func));
+  const trans_res retval= single_value_in_to_exists_transformer(join, func);
+  DBUG_RETURN(retval);
 }
 
 
@@ -1274,8 +1275,7 @@ Item_in_subselect::single_value_in_to_ex
     Item *item= func->create(expr,
                              new Item_ref_null_helper(&select_lex->context,
                                                       this,
-                                                      select_lex->
-                                                      ref_pointer_array,
+                                                      &join->ref_ptrs[0],
                                                       (char *)"<ref>",
                                                       this->full_name()));
     if (!abort_on_null && left_expr->maybe_null)
@@ -1318,7 +1318,7 @@ Item_in_subselect::single_value_in_to_ex
       select_lex->item_list.push_back(new Item_int("Not_used",
                                                    (longlong) 1,
                                                    MY_INT64_NUM_DECIMAL_DIGITS));
-      select_lex->ref_pointer_array[0]= select_lex->item_list.head();
+      join->ref_ptrs[0]= select_lex->item_list.head();
        
       item= func->create(expr, item);
       if (!abort_on_null && orig_item->maybe_null)
@@ -1393,7 +1393,7 @@ Item_in_subselect::single_value_in_to_ex
         Item *new_having=
           func->create(expr,
                        new Item_ref_null_helper(&select_lex->context, this,
-                                            select_lex->ref_pointer_array,
+                                            &join->ref_ptrs[0],
                                             (char *)"<no matter>",
                                             (char *)"<result>"));
         if (!abort_on_null && left_expr->maybe_null)
@@ -1553,13 +1553,12 @@ Item_in_subselect::row_value_in_to_exist
     Item *item_having_part2= 0;
     for (uint i= 0; i < cols_num; i++)
     {
-      DBUG_ASSERT((left_expr->fixed &&
-                  select_lex->ref_pointer_array[i]->fixed) ||
-                  (select_lex->ref_pointer_array[i]->type() == REF_ITEM &&
-                   ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() ==
-                    Item_ref::OUTER_REF));
-      if (select_lex->ref_pointer_array[i]->
-          check_cols(left_expr->element_index(i)->cols()))
+      Item *item_i= join->ref_ptrs[i];
+      Item **pitem_i= &join->ref_ptrs[i];
+      DBUG_ASSERT((left_expr->fixed && item_i->fixed) ||
+                  (item_i->type() == REF_ITEM &&
+                   ((Item_ref*)(item_i))->ref_type() == Item_ref::OUTER_REF));
+      if (item_i-> check_cols(left_expr->element_index(i)->cols()))
         DBUG_RETURN(RES_ERROR);
       Item *item_eq=
         new Item_func_eq(new
@@ -1570,14 +1569,14 @@ Item_in_subselect::row_value_in_to_exist
                                   (char *)in_left_expr_name),
                          new
                          Item_ref(&select_lex->context,
-                                  select_lex->ref_pointer_array + i,
+                                  pitem_i,
                                   (char *)"<no matter>",
                                   (char *)"<list ref>")
                         );
       Item *item_isnull=
         new Item_func_isnull(new
                              Item_ref(&select_lex->context,
-                                      select_lex->ref_pointer_array+i,
+                                      pitem_i,
                                       (char *)"<no matter>",
                                       (char *)"<list ref>")
                             );
@@ -1592,8 +1591,7 @@ Item_in_subselect::row_value_in_to_exist
       Item *item_nnull_test= 
          new Item_is_not_null_test(this,
                                    new Item_ref(&select_lex->context,
-                                                select_lex->
-                                                ref_pointer_array + i,
+                                                pitem_i,
                                                 (char *)"<no matter>",
                                                 (char *)"<list ref>"));
       if (!abort_on_null && left_expr->element_index(i)->maybe_null)
@@ -1630,16 +1628,14 @@ Item_in_subselect::row_value_in_to_exist
     Item *where_item= 0;
     for (uint i= 0; i < cols_num; i++)
     {
-      Item *item, *item_isnull;
-      DBUG_ASSERT((left_expr->fixed &&
-                  select_lex->ref_pointer_array[i]->fixed) ||
-                  (select_lex->ref_pointer_array[i]->type() == REF_ITEM &&
-                   ((Item_ref*)(select_lex->ref_pointer_array[i]))->ref_type() ==
-                    Item_ref::OUTER_REF));
-      if (select_lex->ref_pointer_array[i]->
-          check_cols(left_expr->element_index(i)->cols()))
+      Item *item_i= join->ref_ptrs[i];
+      Item **pitem_i= &join->ref_ptrs[i];
+      DBUG_ASSERT((left_expr->fixed && item_i->fixed) ||
+                  (item_i->type() == REF_ITEM &&
+                   ((Item_ref*)(item_i))->ref_type() == Item_ref::OUTER_REF));
+      if (item_i->check_cols(left_expr->element_index(i)->cols()))
         DBUG_RETURN(RES_ERROR);
-      item=
+      Item *item=
         new Item_func_eq(new
                          Item_direct_ref(&select_lex->context,
                                          (*optimizer->get_cache())->
@@ -1648,8 +1644,7 @@ Item_in_subselect::row_value_in_to_exist
                                          (char *)in_left_expr_name),
                          new
                          Item_direct_ref(&select_lex->context,
-                                         select_lex->
-                                         ref_pointer_array+i,
+                                         pitem_i,
                                          (char *)"<no matter>",
                                          (char *)"<list ref>")
                         );
@@ -1659,16 +1654,15 @@ Item_in_subselect::row_value_in_to_exist
           new Item_is_not_null_test(this,
                                     new
                                     Item_ref(&select_lex->context, 
-                                             select_lex->ref_pointer_array + i,
+                                             pitem_i,
                                              (char *)"<no matter>",
                                              (char *)"<list ref>"));
         
         
-        item_isnull= new
+        Item *item_isnull= new
           Item_func_isnull(new
                            Item_direct_ref(&select_lex->context,
-                                           select_lex->
-                                           ref_pointer_array+i,
+                                           pitem_i,
                                            (char *)"<no matter>",
                                            (char *)"<list ref>")
                           );
@@ -2155,8 +2149,7 @@ bool subselect_single_select_engine::pre
   prepared= 1;
   SELECT_LEX *save_select= thd->lex->current_select;
   thd->lex->current_select= select_lex;
-  if (join->prepare(&select_lex->ref_pointer_array,
-		    select_lex->table_list.first,
+  if (join->prepare(select_lex->table_list.first,
 		    select_lex->with_wild,
 		    select_lex->where,
 		    select_lex->order_list.elements +

=== modified file 'sql/item_sum.cc'
--- a/sql/item_sum.cc	2011-06-09 06:22:39 +0000
+++ b/sql/item_sum.cc	2011-06-24 09:29:07 +0000
@@ -3308,7 +3308,8 @@ bool Item_func_group_concat::setup(THD *
     tmp table columns.
   */
   if (arg_count_order &&
-      setup_order(thd, args, context->table_list, list, all_fields, *order))
+      setup_order(thd, Ref_ptr_array(args, arg_count),
+                  context->table_list, list, all_fields, *order))
     DBUG_RETURN(TRUE);
 
   count_field_types(select_lex, tmp_table_param, all_fields, 0);

=== modified file 'sql/sp.cc'
--- a/sql/sp.cc	2011-06-10 16:57:01 +0000
+++ b/sql/sp.cc	2011-06-23 17:34:08 +0000
@@ -756,6 +756,43 @@ static sp_head *sp_compile(THD *thd, Str
 }
 
 
+class Bad_db_error_handler : public Internal_error_handler
+{
+public:
+  Bad_db_error_handler()
+    :m_error_caught(false)
+  {}
+
+  virtual bool handle_condition(THD *thd,
+                                uint sql_errno,
+                                const char* sqlstate,
+                                MYSQL_ERROR::enum_warning_level level,
+                                const char* message,
+                                MYSQL_ERROR ** cond_hdl);
+
+  bool error_caught() const { return m_error_caught; }
+
+private:
+  bool m_error_caught;
+};
+
+bool
+Bad_db_error_handler::handle_condition(THD *thd,
+                                       uint sql_errno,
+                                       const char* sqlstate,
+                                       MYSQL_ERROR::enum_warning_level level,
+                                       const char* message,
+                                       MYSQL_ERROR ** cond_hdl)
+{
+  if (sql_errno == ER_BAD_DB_ERROR)
+  {
+    m_error_caught= true;
+    return true;
+  }
+  return false;
+}
+
+
 static int
 db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
                 sql_mode_t sql_mode, const char *params, const char *returns,
@@ -769,7 +806,7 @@ db_load_routine(THD *thd, int type, sp_n
   LEX_STRING saved_cur_db_name=
     { saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
   bool cur_db_changed;
-  
+  Bad_db_error_handler db_not_exists_handler;
   char definer_user_name_holder[USERNAME_LENGTH + 1];
   LEX_STRING definer_user_name= { definer_user_name_holder,
                                   USERNAME_LENGTH };
@@ -808,6 +845,7 @@ db_load_routine(THD *thd, int type, sp_n
     goto end;
   }
 
+  thd->push_internal_handler(&db_not_exists_handler);
   /*
     Change the current database (if needed).
 
@@ -818,6 +856,15 @@ db_load_routine(THD *thd, int type, sp_n
                           &cur_db_changed))
   {
     ret= SP_INTERNAL_ERROR;
+    thd->pop_internal_handler();
+    goto end;
+  }
+  thd->pop_internal_handler();
+  if (db_not_exists_handler.error_caught())
+  {
+    ret= SP_INTERNAL_ERROR;
+    my_error(ER_BAD_DB_ERROR, MYF(0), name->m_db.str);
+
     goto end;
   }
 

=== modified file 'sql/sql_array.h'
--- a/sql/sql_array.h	2011-05-18 13:12:02 +0000
+++ b/sql/sql_array.h	2011-06-24 09:29:07 +0000
@@ -1,7 +1,7 @@
 #ifndef SQL_ARRAY_INCLUDED
 #define SQL_ARRAY_INCLUDED
 
-/* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2003, 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
@@ -18,6 +18,60 @@
 
 #include <my_sys.h>
 
+/**
+   A wrapper class which provides array bounds checking.
+   We do *not* own the array, we simply have a pointer to the first element,
+   and a length.
+
+   @remark
+   We want the compiler-generated versions of:
+   - the copy CTOR (memberwise initialization)
+   - the assignment operator (memberwise assignment)
+
+   @param Element_type The type of the elements of the container.
+ */
+template <typename Element_type> class Bounds_checked_array
+{
+public:
+  Bounds_checked_array() : m_array(NULL), m_size(0) {}
+
+  Bounds_checked_array(Element_type *el, size_t size)
+    : m_array(el), m_size(size)
+  {}
+
+  void reset() { m_array= NULL; m_size= 0; }
+
+  Element_type &operator[](size_t n)
+  {
+    DBUG_ASSERT(n < m_size);
+    return m_array[n];
+  }
+
+  const Element_type &operator[](size_t n) const
+  {
+    DBUG_ASSERT(n < m_size);
+    return m_array[n];
+  }
+
+  size_t element_size() const { return sizeof(Element_type); }
+  size_t size() const         { return m_size; }
+
+  bool is_null() const { return m_array == NULL; }
+
+  void pop_front()
+  {
+    DBUG_ASSERT(m_size > 0);
+    m_array+= 1;
+    m_size-= 1;
+  }
+
+  Element_type *array() const { return m_array; }
+
+private:
+  Element_type *m_array;
+  size_t        m_size;
+};
+
 /*
   A typesafe wrapper around DYNAMIC_ARRAY
 */

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2011-06-15 22:31:43 +0000
+++ b/sql/sql_base.cc	2011-06-24 09:29:07 +0000
@@ -8025,7 +8025,7 @@ int setup_wild(THD *thd, TABLE_LIST *tab
 ** Check that all given fields exists and fill struct with current data
 ****************************************************************************/
 
-bool setup_fields(THD *thd, Item **ref_pointer_array,
+bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
                   List<Item> &fields, enum_mark_columns mark_used_columns,
                   List<Item> *sum_func_list, bool allow_sum_func)
 {
@@ -8055,8 +8055,11 @@ bool setup_fields(THD *thd, Item **ref_p
     TODO: remove it when (if) we made one list for allfields and
     ref_pointer_array
   */
-  if (ref_pointer_array)
-    memset(ref_pointer_array, 0, sizeof(Item *) * fields.elements);
+  if (!ref_pointer_array.is_null())
+  {
+    DBUG_ASSERT(ref_pointer_array.size() >= fields.elements);
+    memset(ref_pointer_array.array(), 0, sizeof(Item *) * fields.elements);
+  }
 
   /*
     We call set_entry() there (before fix_fields() of the whole list of field
@@ -8074,7 +8077,7 @@ bool setup_fields(THD *thd, Item **ref_p
   while ((var= li++))
     var->set_entry(thd, FALSE);
 
-  Item **ref= ref_pointer_array;
+  Ref_ptr_array ref= ref_pointer_array;
   thd->lex->current_select->cur_pos_in_select_list= 0;
   while ((item= it++))
   {
@@ -8087,8 +8090,11 @@ bool setup_fields(THD *thd, Item **ref_p
       DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns));
       DBUG_RETURN(TRUE); /* purecov: inspected */
     }
-    if (ref)
-      *(ref++)= item;
+    if (!ref.is_null())
+    {
+      ref[0]= item;
+      ref.pop_front();
+    }
     if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
 	sum_func_list)
       item->split_sum_func(thd, ref_pointer_array, *sum_func_list);

=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h	2011-05-04 07:51:15 +0000
+++ b/sql/sql_base.h	2011-06-24 09:29:07 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -184,7 +184,7 @@ bool insert_fields(THD *thd, Name_resolu
                    List_iterator<Item> *it, bool any_privileges);
 int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
 	       List<Item> *sum_func_list, uint wild_num);
-bool setup_fields(THD *thd, Item** ref_pointer_array,
+bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
                   List<Item> &item, enum_mark_columns mark_used_columns,
                   List<Item> *sum_func_list, bool allow_sum_func);
 bool fill_record(THD *thd, Field **field, List<Item> &values,
@@ -350,7 +350,7 @@ inline TABLE_LIST *find_table_in_local_l
 }
 
 
-inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
+inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array,
                                       List<Item> &item,
                                       enum_mark_columns mark_used_columns,
                                       List<Item> *sum_func_list,

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2011-06-16 16:06:32 +0000
+++ b/sql/sql_class.h	2011-06-21 07:57:31 +0000
@@ -2891,7 +2891,7 @@ public:
   inline void send_kill_message() const
   {
     int err= killed_errno();
-    if (err)
+    if (err && !get_stmt_da()->is_set())
     {
       if ((err == KILL_CONNECTION) && !shutdown_in_progress)
         err = KILL_QUERY;

=== modified file 'sql/sql_db.cc'
--- a/sql/sql_db.cc	2011-05-26 15:20:09 +0000
+++ b/sql/sql_db.cc	2011-06-23 17:34:08 +0000
@@ -40,6 +40,7 @@
 #ifdef __WIN__
 #include <direct.h>
 #endif
+#include "debug_sync.h"
 
 #define MAX_DROP_TABLE_Q_LEN      1024
 
@@ -1533,6 +1534,8 @@ bool mysql_change_db(THD *thd, const LEX
   }
 #endif
 
+  DEBUG_SYNC(thd, "before_db_dir_check");
+
   if (check_db_dir_existence(new_db_file_name.str))
   {
     if (force_switch)

=== modified file 'sql/sql_derived.cc'
--- a/sql/sql_derived.cc	2011-06-09 08:58:41 +0000
+++ b/sql/sql_derived.cc	2011-06-24 09:29:07 +0000
@@ -286,7 +286,7 @@ bool mysql_derived_filling(THD *thd, LEX
 	first_select->options&= ~OPTION_FOUND_ROWS;
 
       lex->current_select= first_select;
-      res= mysql_select(thd, &first_select->ref_pointer_array,
+      res= mysql_select(thd,
 			first_select->table_list.first,
 			first_select->with_wild,
 			first_select->item_list, first_select->where,

=== modified file 'sql/sql_do.cc'
--- a/sql/sql_do.cc	2010-07-27 15:01:56 +0000
+++ b/sql/sql_do.cc	2011-06-24 09:29:07 +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
@@ -28,7 +28,7 @@ bool mysql_do(THD *thd, List<Item> &valu
   List_iterator<Item> li(values);
   Item *value;
   DBUG_ENTER("mysql_do");
-  if (setup_fields(thd, 0, values, MARK_COLUMNS_NONE, 0, 0))
+  if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_NONE, 0, 0))
     DBUG_RETURN(TRUE);
   while ((value = li++))
     value->val_int();

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2011-06-10 16:57:01 +0000
+++ b/sql/sql_insert.cc	2011-06-24 09:29:07 +0000
@@ -256,7 +256,7 @@ static int check_insert_fields(THD *thd,
     */
     table_list->next_local= 0;
     context->resolve_in_table_list_only(table_list);
-    res= setup_fields(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0);
+    res= setup_fields(thd, Ref_ptr_array(), fields, MARK_COLUMNS_WRITE, 0, 0);
 
     /* Restore the current context. */
     ctx_state.restore_state(context, table_list);
@@ -347,7 +347,8 @@ static int check_update_fields(THD *thd,
   }
 
   /* Check the fields we are going to modify */
-  if (setup_fields(thd, 0, update_fields, MARK_COLUMNS_WRITE, 0, 0))
+  if (setup_fields(thd, Ref_ptr_array(),
+                   update_fields, MARK_COLUMNS_WRITE, 0, 0))
     return -1;
 
   if (insert_table_list->effective_algorithm == VIEW_ALGORITHM_MERGE &&
@@ -762,7 +763,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
       my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
       goto abort;
     }
-    if (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0))
+    if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_READ, 0, 0))
       goto abort;
   }
   its.rewind ();
@@ -1377,7 +1378,8 @@ bool mysql_prepare_insert(THD *thd, TABL
     table_list->next_local= 0;
     context->resolve_in_table_list_only(table_list);
 
-    res= (setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0) ||
+    res= (setup_fields(thd, Ref_ptr_array(),
+                       *values, MARK_COLUMNS_READ, 0, 0) ||
           check_insert_fields(thd, context->table_list, fields, *values,
                               !insert_into_view, 0, &map));
 
@@ -1393,7 +1395,8 @@ bool mysql_prepare_insert(THD *thd, TABL
     }
 
    if (!res)
-     res= setup_fields(thd, 0, update_values, MARK_COLUMNS_READ, 0, 0);
+     res= setup_fields(thd, Ref_ptr_array(),
+                       update_values, MARK_COLUMNS_READ, 0, 0);
 
     if (!res && duplic == DUP_UPDATE)
     {
@@ -3234,7 +3237,7 @@ select_insert::prepare(List<Item> &value
 
   /* Errors during check_insert_fields() should not be ignored. */
   lex->current_select->no_error= FALSE;
-  res= (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0) ||
+  res= (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0) ||
         check_insert_fields(thd, table_list, *fields, values,
                             !insert_into_view, 1, &map));
 
@@ -3282,7 +3285,7 @@ select_insert::prepare(List<Item> &value
       table_list->next_name_resolution_table= 
         ctx_state.get_first_name_resolution_table();
 
-    res= res || setup_fields(thd, 0, *info.update_values,
+    res= res || setup_fields(thd, Ref_ptr_array(), *info.update_values,
                              MARK_COLUMNS_READ, 0, 0);
     if (!res)
     {

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2011-06-10 09:52:57 +0000
+++ b/sql/sql_lex.cc	2011-06-24 09:29:07 +0000
@@ -1759,7 +1759,7 @@ void st_select_lex::init_query()
   parent_lex->push_context(&context);
   cond_count= between_count= with_wild= 0;
   max_equal_elems= 0;
-  ref_pointer_array= 0;
+  ref_pointer_array.reset();
   select_n_where_fields= 0;
   select_n_having_items= 0;
   subquery_in_having= explicit_limit= 0;
@@ -2136,20 +2136,42 @@ ulong st_select_lex::get_table_join_opti
 
 bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
 {
-  if (ref_pointer_array)
-    return 0;
+#ifdef DBUG_OFF
+  if (!ref_pointer_array.is_null())
+    return false;
+#endif
+
+  // find_order_in_list() may need some extra space, so multiply by two.
+  order_group_num*= 2;
 
   /*
     We have to create array in prepared statement memory if it is
     prepared statement
   */
   Query_arena *arena= thd->stmt_arena;
-  return (ref_pointer_array=
-          (Item **)arena->alloc(sizeof(Item*) * (n_child_sum_items +
-                                                 item_list.elements +
-                                                 select_n_having_items +
-                                                 select_n_where_fields +
-                                                 order_group_num)*5)) == 0;
+  const uint n_elems= (n_child_sum_items +
+                       item_list.elements +
+                       select_n_having_items +
+                       select_n_where_fields +
+                       order_group_num) * 5;
+  DBUG_PRINT("info", ("setup_ref_array this %p %4u : %4u %4u %4u %4u %4u %4u",
+                      this,
+                      n_elems, // :
+                      n_sum_items,
+                      n_child_sum_items,
+                      item_list.elements,
+                      select_n_having_items,
+                      select_n_where_fields,
+                      order_group_num));
+  if (!ref_pointer_array.is_null())
+  {
+    DBUG_ASSERT(ref_pointer_array.size() == n_elems);
+    return false;
+  }
+  Item **array= static_cast<Item**>(arena->alloc(sizeof(Item*) * n_elems));
+  ref_pointer_array= Ref_ptr_array(array, n_elems);
+
+  return array == NULL;
 }
 
 

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2011-06-10 09:52:57 +0000
+++ b/sql/sql_lex.h	2011-06-24 09:29:07 +0000
@@ -24,6 +24,7 @@
 #include "sql_trigger.h"
 #include "item.h"               /* From item_subselect.h: subselect_union_engine */
 #include "thr_lock.h"                  /* thr_lock_type, TL_UNLOCK */
+#include "sql_array.h"
 #include "mem_root_array.h"
 
 /* YACC and LEX Definitions */
@@ -604,6 +605,7 @@ public:
 };
 
 typedef class st_select_lex_unit SELECT_LEX_UNIT;
+typedef Bounds_checked_array<Item*> Ref_ptr_array;
 
 /*
   SELECT_LEX - store information of parsed SELECT statment
@@ -666,8 +668,9 @@ public:
   SQL_I_List<ORDER> order_list;   /* ORDER clause */
   SQL_I_List<ORDER> *gorder_list;
   Item *select_limit, *offset_limit;  /* LIMIT clause parameters */
-  // Arrays of pointers to top elements of all_fields list
-  Item **ref_pointer_array;
+
+  /// Array of pointers to top elements of all_fields list
+  Ref_ptr_array ref_pointer_array;
 
   /*
     number of items in select_list and HAVING clause used to get number
@@ -677,7 +680,7 @@ public:
   uint select_n_having_items;
   uint cond_count;    /* number of arguments of and/or/xor in where/having/on */
   uint between_count; /* number of between predicates in where/having/on      */
-  uint max_equal_elems; /* maximal number of elements in multiple equalities  */   
+  uint max_equal_elems; /* maximal number of elements in multiple equalities  */
   /*
     Number of fields used in select list or where clause of current select
     and all inner subselects.

=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc	2011-06-10 16:57:01 +0000
+++ b/sql/sql_load.cc	2011-06-24 09:29:07 +0000
@@ -268,15 +268,18 @@ int mysql_load(THD *thd,sql_exchange *ex
       Let us also prepare SET clause, altough it is probably empty
       in this case.
     */
-    if (setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
-        setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
+    if (setup_fields(thd, Ref_ptr_array(),
+                     set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
+        setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0))
       DBUG_RETURN(TRUE);
   }
   else
   {						// Part field list
     /* TODO: use this conds for 'WITH CHECK OPTIONS' */
-    if (setup_fields(thd, 0, fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
-        setup_fields(thd, 0, set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
+    if (setup_fields(thd, Ref_ptr_array(),
+                     fields_vars, MARK_COLUMNS_WRITE, 0, 0) ||
+        setup_fields(thd, Ref_ptr_array(),
+                     set_fields, MARK_COLUMNS_WRITE, 0, 0) ||
         check_that_all_fields_are_given_values(thd, table, table_list))
       DBUG_RETURN(TRUE);
     /*
@@ -295,7 +298,7 @@ int mysql_load(THD *thd,sql_exchange *ex
       }
     }
     /* Fix the expressions in SET clause */
-    if (setup_fields(thd, 0, set_values, MARK_COLUMNS_READ, 0, 0))
+    if (setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0))
       DBUG_RETURN(TRUE);
   }
 

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2011-06-18 20:34:45 +0000
+++ b/sql/sql_parse.cc	2011-06-24 19:30:01 +0000
@@ -1543,6 +1543,8 @@ bool dispatch_command(enum enum_server_c
 
   /* Finalize server status flags after executing a command. */
   thd->update_server_status();
+  if (thd->killed)
+    thd->send_kill_message();
   thd->protocol->end_statement();
   query_cache_end_of_result(thd);
 
@@ -3165,7 +3167,7 @@ end_with_restore_list:
     if (!thd->is_fatal_error &&
         (del_result= new multi_delete(aux_tables, lex->table_count)))
     {
-      res= mysql_select(thd, &select_lex->ref_pointer_array,
+      res= mysql_select(thd,
 			select_lex->get_table_list(),
 			select_lex->with_wild,
 			select_lex->item_list,
@@ -4547,10 +4549,7 @@ finish:
   {
     /* report error issued during command execution */
     if (thd->killed_errno())
-    {
-      if (! thd->get_stmt_da()->is_set())
-        thd->send_kill_message();
-    }
+      thd->send_kill_message();
     if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
     {
       thd->killed= THD::NOT_KILLED;

=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc	2011-06-10 16:57:01 +0000
+++ b/sql/sql_prepare.cc	2011-06-24 09:29:07 +0000
@@ -1294,7 +1294,7 @@ static bool mysql_test_insert(Prepared_s
         my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
         goto error;
       }
-      if (setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0))
+      if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_NONE, 0, 0))
         goto error;
     }
   }
@@ -1373,7 +1373,8 @@ static int mysql_test_update(Prepared_st
   table_list->register_want_access(want_privilege);
 #endif
   thd->lex->select_lex.no_wrap_view_item= TRUE;
-  res= setup_fields(thd, 0, select->item_list, MARK_COLUMNS_READ, 0, 0);
+  res= setup_fields(thd, Ref_ptr_array(),
+                    select->item_list, MARK_COLUMNS_READ, 0, 0);
   thd->lex->select_lex.no_wrap_view_item= FALSE;
   if (res)
     goto error;
@@ -1384,7 +1385,8 @@ static int mysql_test_update(Prepared_st
     (SELECT_ACL & ~table_list->table->grant.privilege);
   table_list->register_want_access(SELECT_ACL);
 #endif
-  if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0))
+  if (setup_fields(thd, Ref_ptr_array(),
+                   stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0))
     goto error;
   /* TODO: here we should send types of placeholders to the client. */
   DBUG_RETURN(0);
@@ -1530,7 +1532,8 @@ static bool mysql_test_do_fields(Prepare
 
   if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL))
     DBUG_RETURN(TRUE);
-  DBUG_RETURN(setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0));
+  DBUG_RETURN(setup_fields(thd, Ref_ptr_array(),
+                           *values, MARK_COLUMNS_NONE, 0, 0));
 }
 
 

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-06-10 16:57:01 +0000
+++ b/sql/sql_select.cc	2011-06-24 09:29:07 +0000
@@ -203,7 +203,7 @@ static int remove_dup_with_hash_index(TH
 static bool cmp_buffer_with_ref(THD *thd, TABLE *table, TABLE_REF *tab_ref);
 static bool setup_new_fields(THD *thd, List<Item> &fields,
 			     List<Item> &all_fields, ORDER *new_order);
-static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array,
+static ORDER *create_distinct_group(THD *thd, Ref_ptr_array ref_pointer_array,
                                     ORDER *order, List<Item> &fields,
                                     List<Item> &all_fields,
 				    bool *all_order_by_fields_used);
@@ -213,12 +213,12 @@ static void calc_group_buffer(JOIN *join
 static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
 static bool alloc_group_fields(JOIN *join,ORDER *group);
 // Create list for using with tempory table
-static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
+static bool change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
 				     List<Item> &new_list1,
 				     List<Item> &new_list2,
 				     uint elements, List<Item> &items);
 // Create list for using with tempory table
-static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
+static bool change_refs_to_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
 				      List<Item> &new_list1,
 				      List<Item> &new_list2,
 				      uint elements, List<Item> &items);
@@ -384,7 +384,7 @@ bool handle_select(THD *thd, LEX *lex, s
       every PS/SP execution new, we will not need reset this flag if 
       setup_tables_done_option changed for next rexecution
     */
-    res= mysql_select(thd, &select_lex->ref_pointer_array,
+    res= mysql_select(thd,
 		      select_lex->table_list.first,
 		      select_lex->with_wild, select_lex->item_list,
 		      select_lex->where,
@@ -460,7 +460,7 @@ bool handle_select(THD *thd, LEX *lex, s
 
 bool
 fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
-                 Item **ref_pointer_array, ORDER *group_list)
+               Ref_ptr_array ref_pointer_array, ORDER *group_list)
 {
   Item_outer_ref *ref;
 
@@ -477,7 +477,7 @@ fix_inner_refs(THD *thd, List<Item> &all
       existing one. The change will lead to less operations for copying fields,
       smaller temporary tables and less data passed through filesort.
     */
-    if (ref_pointer_array && !ref->found_in_select_list)
+    if (!ref_pointer_array.is_null() && !ref->found_in_select_list)
     {
       int el= all_fields.elements;
       ref_pointer_array[el]= item;
@@ -487,7 +487,7 @@ fix_inner_refs(THD *thd, List<Item> &all
         If it's needed reset each Item_ref item that refers this field with
         a new reference taken from ref_pointer_array.
       */
-      item_ref= ref_pointer_array + el;
+      item_ref= &ref_pointer_array[el];
     }
 
     if (ref->in_sum_func)
@@ -546,7 +546,7 @@ fix_inner_refs(THD *thd, List<Item> &all
 /**
   Function to setup clauses without sum functions.
 */
-inline int setup_without_group(THD *thd, Item **ref_pointer_array,
+inline int setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
 			       TABLE_LIST *tables,
 			       TABLE_LIST *leaves,
 			       List<Item> &fields,
@@ -600,8 +600,7 @@ inline int setup_without_group(THD *thd,
     0   on success
 */
 int
-JOIN::prepare(Item ***rref_pointer_array,
-	      TABLE_LIST *tables_init,
+JOIN::prepare(TABLE_LIST *tables_init,
 	      uint wild_num, Item *conds_init, uint og_num,
 	      ORDER *order_init, ORDER *group_init,
 	      Item *having_init,
@@ -647,18 +646,31 @@ JOIN::prepare(Item ***rref_pointer_array
        table_ptr= table_ptr->next_leaf)
     tables++;
 
-  if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
-      select_lex->setup_ref_array(thd, og_num) ||
-      setup_fields(thd, (*rref_pointer_array), fields_list, MARK_COLUMNS_READ,
-		   &all_fields, 1) ||
-      setup_without_group(thd, (*rref_pointer_array), tables_list,
+  /*
+    Item and Item_field CTORs will both increment some counters
+    in current_select, based on the current parsing context.
+    We are not parsing anymore: any new Items created now are due to
+    query rewriting, so stop incrementing counters.
+   */
+  DBUG_ASSERT(select_lex->parsing_place == NO_MATTER);
+  select_lex->parsing_place= NO_MATTER;
+
+  if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num))
+    DBUG_RETURN(-1);
+  if (select_lex->setup_ref_array(thd, og_num))
+    DBUG_RETURN(-1);
+
+  ref_ptrs= ref_ptr_array_slice(0);
+  
+  if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ,
+		   &all_fields, 1))
+    DBUG_RETURN(-1);
+  if (setup_without_group(thd, ref_ptrs, tables_list,
 			  select_lex->leaf_tables, fields_list,
 			  all_fields, &conds, order, group_list,
 			  &hidden_group_fields))
-    DBUG_RETURN(-1);				/* purecov: inspected */
+    DBUG_RETURN(-1);
 
-  ref_pointer_array= *rref_pointer_array;
-  
   if (having)
   {
     nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
@@ -712,15 +724,15 @@ JOIN::prepare(Item ***rref_pointer_array
         real_order= TRUE;
 
       if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
-        item->split_sum_func(thd, ref_pointer_array, all_fields);
+        item->split_sum_func(thd, ref_ptrs, all_fields);
     }
     if (!real_order)
       order= NULL;
   }
 
   if (having && having->with_sum_func)
-    having->split_sum_func2(thd, ref_pointer_array, all_fields,
-                            &having, TRUE);
+    having->split_sum_func2(thd, ref_ptrs,
+                            all_fields, &having, TRUE);
   if (select_lex->inner_sum_func_list)
   {
     Item_sum *end=select_lex->inner_sum_func_list;
@@ -728,13 +740,13 @@ JOIN::prepare(Item ***rref_pointer_array
     do
     { 
       item_sum= item_sum->next;
-      item_sum->split_sum_func2(thd, ref_pointer_array,
+      item_sum->split_sum_func2(thd, ref_ptrs,
                                 all_fields, item_sum->ref_by, FALSE);
     } while (item_sum != end);
   }
 
   if (select_lex->inner_refs_list.elements &&
-      fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array,
+      fix_inner_refs(thd, all_fields, select_lex, ref_ptrs,
                      group_list))
     DBUG_RETURN(-1);
 
@@ -753,9 +765,9 @@ JOIN::prepare(Item ***rref_pointer_array
       {
         Item_field *field= new Item_field(thd, *(Item_field**)ord->item);
         int el= all_fields.elements;
-        ref_pointer_array[el]= field;
+        ref_ptrs[el]= field;
         all_fields.push_front(field);
-        ord->item= ref_pointer_array + el;
+        ord->item= &ref_ptrs[el];
       }
     }
   }
@@ -824,7 +836,6 @@ JOIN::prepare(Item ***rref_pointer_array
 
   /* Init join struct */
   count_field_types(select_lex, &tmp_table_param, all_fields, 0);
-  ref_pointer_array_size= all_fields.elements*sizeof(Item*);
   this->group= group_list != 0;
   unit= unit_arg;
 
@@ -2247,7 +2258,7 @@ JOIN::optimize()
     if (order)
       skip_sort_order= test_if_skip_sort_order(tab, order, m_select_limit, 1, 
         &tab->table->keys_in_use_for_order_by);
-    if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array,
+    if ((group_list=create_distinct_group(thd, ref_ptrs,
                                           order, fields_list, all_fields,
 				          &all_order_fields_used)))
     {
@@ -2750,7 +2761,7 @@ void JOIN::reset()
     filesort_free_buffers(exec_tmp_table2,0);
   }
   clear_sj_tmp_tables(this);
-  if (items0)
+  if (!items0.is_null())
     set_items_ref_array(items0);
 
   if (join_tab_save)
@@ -3032,9 +3043,9 @@ JOIN::exec()
     /* Change sum_fields reference to calculated fields in tmp_table */
     if (curr_join != this)
       curr_join->all_fields= *curr_all_fields;
-    if (!items1)
+    if (items1.is_null())
     {
-      items1= items0 + all_fields.elements;
+      items1= ref_ptr_array_slice(2);
       if (sort_and_group || curr_tmp_table->group ||
           tmp_table_param.precomputed_group_by)
       {
@@ -3197,9 +3208,9 @@ JOIN::exec()
       curr_join->join_tab[0].table= 0;           // Table is freed
       
       // No sum funcs anymore
-      if (!items2)
+      if (items2.is_null())
       {
-	items2= items1 + all_fields.elements;
+        items2= ref_ptr_array_slice(3);
 	if (change_to_use_tmp_fields(thd, items2,
 				     tmp_fields_list2, tmp_all_fields2, 
 				     fields_list.elements, tmp_all_fields1))
@@ -3252,11 +3263,11 @@ JOIN::exec()
     {
       DBUG_VOID_RETURN;
     }
-    if (!items3)
+    if (items3.is_null())
     {
-      if (!items0)
+      if (items0.is_null())
 	init_items_ref_array();
-      items3= ref_pointer_array + (all_fields.elements*4);
+      items3= ref_ptr_array_slice(4);
       setup_copy_fields(thd, &curr_join->tmp_table_param,
 			items3, tmp_fields_list3, tmp_all_fields3,
 			curr_fields_list->elements, *curr_all_fields);
@@ -3486,7 +3497,7 @@ JOIN::exec()
     We also need to do this when we have temp table(s).
     Otherwise we would not be able to print the query correctly.
   */ 
-  if (items0 && (thd->lex->describe & DESCRIBE_EXTENDED) &&
+  if (!items0.is_null() && (thd->lex->describe & DESCRIBE_EXTENDED) &&
       (select_lex->linkage == DERIVED_TABLE_TYPE ||
        exec_tmp_table1 || exec_tmp_table2))
     set_items_ref_array(items0);
@@ -3568,7 +3579,6 @@ void JOIN::cleanup_item_list(List<Item>
   An entry point to single-unit select (a select without UNION).
 
   @param thd                  thread handler
-  @param rref_pointer_array   a reference to ref_pointer_array of
                               the top-level select_lex for this query
   @param tables               list of all tables used in this query.
                               The tables have been pre-opened.
@@ -3609,7 +3619,7 @@ void JOIN::cleanup_item_list(List<Item>
 */
 
 bool
-mysql_select(THD *thd, Item ***rref_pointer_array,
+mysql_select(THD *thd, 
 	     TABLE_LIST *tables, uint wild_num, List<Item> &fields,
 	     Item *conds, uint og_num,  ORDER *order, ORDER *group,
 	     Item *having, ORDER *proc_param, ulonglong select_options,
@@ -3649,7 +3659,7 @@ mysql_select(THD *thd, Item ***rref_poin
       }
       else
       {
-        err= join->prepare(rref_pointer_array, tables, wild_num,
+        err= join->prepare(tables, wild_num,
                            conds, og_num, order, group, having, proc_param,
                            select_lex, unit);
         if (err)
@@ -3667,7 +3677,7 @@ mysql_select(THD *thd, Item ***rref_poin
 	DBUG_RETURN(TRUE); /* purecov: inspected */
     THD_STAGE_INFO(thd, stage_init);
     thd->used_tables=0;                         // Updated by setup_fields
-    err= join->prepare(rref_pointer_array, tables, wild_num,
+    err= join->prepare(tables, wild_num,
                        conds, og_num, order, group, having, proc_param,
                        select_lex, unit);
     if (err)
@@ -21129,7 +21139,7 @@ cp_buffer_from_ref(THD *thd, TABLE *tabl
 */
 
 static bool
-find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
                    ORDER *order, List<Item> &fields, List<Item> &all_fields,
                    bool is_group_field)
 {
@@ -21153,7 +21163,7 @@ find_order_in_list(THD *thd, Item **ref_
                order_item->full_name(), thd->where);
       return TRUE;
     }
-    order->item= ref_pointer_array + count - 1;
+    order->item= &ref_pointer_array[count - 1];
     order->in_field_list= 1;
     order->counter= count;
     order->counter_used= 1;
@@ -21214,7 +21224,7 @@ find_order_in_list(THD *thd, Item **ref_
         'shadowed' a table field with the same name, the table field will be
         chosen over the derived field.
       */
-      order->item= ref_pointer_array + counter;
+      order->item= &ref_pointer_array[counter];
       order->in_field_list=1;
       return FALSE;
     }
@@ -21272,7 +21282,7 @@ find_order_in_list(THD *thd, Item **ref_
   uint el= all_fields.elements;
   all_fields.push_front(order_item); /* Add new field to field list. */
   ref_pointer_array[el]= order_item;
-  order->item= ref_pointer_array + el;
+  order->item= &ref_pointer_array[el];
   return FALSE;
 }
 
@@ -21284,7 +21294,7 @@ find_order_in_list(THD *thd, Item **ref_
   the field list.
 */
 
-int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
 		List<Item> &fields, List<Item> &all_fields, ORDER *order)
 {
   thd->where="order clause";
@@ -21325,7 +21335,7 @@ int setup_order(THD *thd, Item **ref_poi
 */
 
 int
-setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
 	    List<Item> &fields, List<Item> &all_fields, ORDER *order,
 	    bool *hidden_group_fields)
 {
@@ -21456,13 +21466,14 @@ setup_new_fields(THD *thd, List<Item> &f
 */
 
 ORDER *
-create_distinct_group(THD *thd, Item **ref_pointer_array,
+create_distinct_group(THD *thd, Ref_ptr_array ref_pointer_array,
                       ORDER *order_list, List<Item> &fields,
                       List<Item> &all_fields,
 		      bool *all_order_by_fields_used)
 {
   List_iterator<Item> li(fields);
-  Item *item, **orig_ref_pointer_array= ref_pointer_array;
+  Item *item;
+  Ref_ptr_array orig_ref_pointer_array= ref_pointer_array;
   ORDER *order,*group,**prev;
 
   *all_order_by_fields_used= 1;
@@ -21516,7 +21527,7 @@ create_distinct_group(THD *thd, Item **r
         int el= all_fields.elements;
         orig_ref_pointer_array[el]= new_item;
         all_fields.push_front(new_item);
-        ord->item= orig_ref_pointer_array + el;
+        ord->item= &orig_ref_pointer_array[el];
       }
       else
       {
@@ -21525,14 +21536,14 @@ create_distinct_group(THD *thd, Item **r
           simple indexing of ref_pointer_array (order in the array and in the
           list are same)
         */
-        ord->item= ref_pointer_array;
+        ord->item= &ref_pointer_array[0];
       }
       ord->direction= ORDER::ORDER_ASC;
       *prev=ord;
       prev= &ord->next;
     }
 next_item:
-    ref_pointer_array++;
+    ref_pointer_array.pop_front();
   }
   *prev=0;
   return group;
@@ -21847,7 +21858,7 @@ int test_if_item_cache_changed(List<Cach
 
 bool
 setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
-		  Item **ref_pointer_array,
+		  Ref_ptr_array ref_pointer_array,
 		  List<Item> &res_selected_fields, List<Item> &res_all_fields,
 		  uint elements, List<Item> &all_fields)
 {
@@ -22128,7 +22139,7 @@ bool JOIN::make_sum_func_list(List<Item>
 */
 
 static bool
-change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
+change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
 			 List<Item> &res_selected_fields,
 			 List<Item> &res_all_fields,
 			 uint elements, List<Item> &all_fields)
@@ -22219,7 +22230,7 @@ change_to_use_tmp_fields(THD *thd, Item
 */
 
 static bool
-change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
+change_refs_to_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array,
 			  List<Item> &res_selected_fields,
 			  List<Item> &res_all_fields, uint elements,
 			  List<Item> &all_fields)
@@ -22594,15 +22605,20 @@ bool JOIN::rollup_init()
   */
   tmp_table_param.group_parts= send_group_parts;
 
-  if (!(rollup.null_items= (Item_null_result**) thd->alloc((sizeof(Item*) +
-                                                sizeof(Item**) +
-                                                sizeof(List<Item>) +
-				                ref_pointer_array_size)
-				                * send_group_parts )))
-    return 1;
-  
-  rollup.fields= (List<Item>*) (rollup.null_items + send_group_parts);
-  rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
+  Item_null_result **null_items=
+    static_cast<Item_null_result**>(thd->alloc(sizeof(Item*)*send_group_parts));
+
+  rollup.null_items= Item_null_array(null_items, send_group_parts);
+  rollup.ref_pointer_arrays=
+    static_cast<Ref_ptr_array*>
+    (thd->alloc((sizeof(Ref_ptr_array) +
+                 all_fields.elements * sizeof(Item*)) * send_group_parts));
+  rollup.fields=
+    static_cast<List<Item>*>(thd->alloc(sizeof(List<Item>) * send_group_parts));
+
+  if (!null_items || !rollup.ref_pointer_arrays || !rollup.fields)
+    return true;
+
   ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
 
   /*
@@ -22614,7 +22630,7 @@ bool JOIN::rollup_init()
     rollup.null_items[i]= new (thd->mem_root) Item_null_result();
     List<Item> *rollup_fields= &rollup.fields[i];
     rollup_fields->empty();
-    rollup.ref_pointer_arrays[i]= ref_array;
+    rollup.ref_pointer_arrays[i]= Ref_ptr_array(ref_array, all_fields.elements);
     ref_array+= all_fields.elements;
   }
   for (i= 0 ; i < send_group_parts; i++)
@@ -22760,11 +22776,11 @@ bool JOIN::rollup_make_fields(List<Item>
     bool real_fields= 0;
     Item *item;
     List_iterator<Item> new_it(rollup.fields[pos]);
-    Item **ref_array_start= rollup.ref_pointer_arrays[pos];
+    Ref_ptr_array ref_array_start= rollup.ref_pointer_arrays[pos];
     ORDER *start_group;
 
     /* Point to first hidden field */
-    Item **ref_array= ref_array_start + fields_arg.elements-1;
+    uint ref_array_ix= fields_arg.elements-1;
 
     /* Remember where the sum functions ends for the previous level */
     sum_funcs_end[pos+1]= *func;
@@ -22781,7 +22797,7 @@ bool JOIN::rollup_make_fields(List<Item>
       if (item == first_field)
       {
 	real_fields= 1;				// End of hidden fields
-	ref_array= ref_array_start;
+        ref_array_ix= 0;
       }
 
       if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item() &&
@@ -22825,15 +22841,15 @@ bool JOIN::rollup_make_fields(List<Item>
 	  }
 	}
       }
-      *ref_array= item;
+      ref_array_start[ref_array_ix]= item;
       if (real_fields)
       {
 	(void) new_it++;			// Point to next item
 	new_it.replace(item);			// Replace previous
-	ref_array++;
+	ref_array_ix++;
       }
       else
-	ref_array--;
+	ref_array_ix--;
     }
   }
   sum_funcs_end[0]= *func;			// Point to last function
@@ -22865,9 +22881,7 @@ int JOIN::rollup_send_data(uint idx)
   for (i= send_group_parts ; i-- > idx ; )
   {
     /* Get reference pointers to sum functions in place */
-    memcpy((char*) ref_pointer_array,
-	   (char*) rollup.ref_pointer_arrays[i],
-	   ref_pointer_array_size);
+    copy_ref_ptr_array(ref_ptrs, rollup.ref_pointer_arrays[i]);
     if ((!having || having->val_int()))
     {
       if (send_records < unit->select_limit_cnt && do_send_rows &&
@@ -22877,7 +22891,7 @@ int JOIN::rollup_send_data(uint idx)
     }
   }
   /* Restore ref_pointer_array */
-  set_items_ref_array(current_ref_pointer_array);
+  set_items_ref_array(current_ref_ptrs);
   return 0;
 }
 
@@ -22907,9 +22921,7 @@ int JOIN::rollup_write_data(uint idx, TA
   for (i= send_group_parts ; i-- > idx ; )
   {
     /* Get reference pointers to sum functions in place */
-    memcpy((char*) ref_pointer_array,
-	   (char*) rollup.ref_pointer_arrays[i],
-	   ref_pointer_array_size);
+    copy_ref_ptr_array(ref_ptrs, rollup.ref_pointer_arrays[i]);
     if ((!having || having->val_int()))
     {
       int write_error;
@@ -22932,7 +22944,7 @@ int JOIN::rollup_write_data(uint idx, TA
     }
   }
   /* Restore ref_pointer_array */
-  set_items_ref_array(current_ref_pointer_array);
+  set_items_ref_array(current_ref_ptrs);
   return 0;
 }
 
@@ -23573,7 +23585,7 @@ bool mysql_explain_union(THD *thd, SELEC
   {
     thd->lex->current_select= first;
     unit->set_limit(unit->global_parameters);
-    res= mysql_select(thd, &first->ref_pointer_array,
+    res= mysql_select(thd,
 			first->table_list.first,
 			first->with_wild, first->item_list,
 			first->where,

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2011-05-26 15:20:09 +0000
+++ b/sql/sql_select.h	2011-06-24 09:29:07 +0000
@@ -1598,12 +1598,14 @@ typedef struct st_position : public Sql_
 } POSITION;
 
 
+typedef Bounds_checked_array<Item_null_result*> Item_null_array;
+
 typedef struct st_rollup
 {
   enum State { STATE_NONE, STATE_INITED, STATE_READY };
   State state;
-  Item_null_result **null_items;
-  Item ***ref_pointer_arrays;
+  Item_null_array null_items;
+  Ref_ptr_array *ref_pointer_arrays;
   List<Item> *fields;
 } ROLLUP;
 
@@ -1879,10 +1881,19 @@ public:
     FirstMatch strategy.
   */
   JOIN_TAB *return_tab;
-  Item **ref_pointer_array; ///<used pointer reference for this select
-  // Copy of above to be used with different lists
-  Item **items0, **items1, **items2, **items3, **current_ref_pointer_array;
-  uint ref_pointer_array_size; ///< size of above in bytes
+
+  /*
+    Used pointer reference for this select.
+    select_lex->ref_pointer_array contains five "slices" of the same length:
+    |========|========|========|========|========|
+     ref_ptrs items0   items1   items2   items3
+   */
+  Ref_ptr_array ref_ptrs;
+  // Copy of the initial slice above, to be used with different lists
+  Ref_ptr_array items0, items1, items2, items3;
+  // Used by rollup, to restore ref_ptrs after overwriting it.
+  Ref_ptr_array current_ref_ptrs;
+
   const char *zero_result_cause; ///< not 0 if exec must return zero result
   
   bool union_part; ///< this subselect is part of union 
@@ -1958,8 +1969,11 @@ public:
     hidden_group_fields= 0; /*safety*/
     error= 0;
     return_tab= 0;
-    ref_pointer_array= items0= items1= items2= items3= 0;
-    ref_pointer_array_size= 0;
+    ref_ptrs.reset();
+    items0.reset();
+    items1.reset();
+    items2.reset();
+    items3.reset();
     zero_result_cause= 0;
     optimized= 0;
     cond_equal= 0;
@@ -1979,7 +1993,7 @@ public:
     first_select= sub_select;
   }
 
-  int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
+  int prepare(TABLE_LIST *tables, uint wind_num,
 	      Item *conds, uint og_num, ORDER *order, ORDER *group,
 	      Item *having, ORDER *proc_param, SELECT_LEX *select,
 	      SELECT_LEX_UNIT *unit);
@@ -1994,16 +2008,42 @@ public:
   bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
 			  bool before_group_by, bool recompute= FALSE);
 
-  inline void set_items_ref_array(Item **ptr)
+  /// Initialzes a slice, see comments for ref_ptrs above.
+  Ref_ptr_array ref_ptr_array_slice(size_t slice_num)
+  {
+    size_t slice_sz= select_lex->ref_pointer_array.size() / 5U;
+    DBUG_ASSERT(select_lex->ref_pointer_array.size() % 5 == 0);
+    DBUG_ASSERT(slice_num < 5U);
+    return Ref_ptr_array(&select_lex->ref_pointer_array[slice_num * slice_sz],
+                         slice_sz);
+  }
+
+  /**
+     Overwrites one slice with the contents of another slice.
+     In the normal case, dst and src have the same size().
+     However: the rollup slices may have smaller size than slice_sz.
+   */
+  void copy_ref_ptr_array(Ref_ptr_array dst_arr, Ref_ptr_array src_arr)
+  {
+    DBUG_ASSERT(dst_arr.size() >= src_arr.size());
+    void *dest= dst_arr.array();
+    const void *src= src_arr.array();
+    memcpy(dest, src, src_arr.size() * src_arr.element_size());
+  }
+
+  /// Overwrites 'ref_ptrs' and remembers the the source as 'current'.
+  void set_items_ref_array(Ref_ptr_array src_arr)
   {
-    memcpy((char*) ref_pointer_array, (char*) ptr, ref_pointer_array_size);
-    current_ref_pointer_array= ptr;
+    copy_ref_ptr_array(ref_ptrs, src_arr);
+    current_ref_ptrs= src_arr;
   }
-  inline void init_items_ref_array()
+
+  /// Initializes 'items0' and remembers that it is 'current'.
+  void init_items_ref_array()
   {
-    items0= ref_pointer_array + all_fields.elements;
-    memcpy(items0, ref_pointer_array, ref_pointer_array_size);
-    current_ref_pointer_array= items0;
+    items0= ref_ptr_array_slice(1);
+    copy_ref_ptr_array(items0, ref_ptrs);
+    current_ref_ptrs= items0;
   }
 
   bool rollup_init();
@@ -2074,7 +2114,7 @@ void free_tmp_table(THD *thd, TABLE *ent
 void count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param, 
                        List<Item> &fields, bool reset_with_sum_func);
 bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
-		       Item **ref_pointer_array,
+		       Ref_ptr_array ref_pointer_array,
 		       List<Item> &new_list1, List<Item> &new_list2,
 		       uint elements, List<Item> &fields);
 void copy_fields(TMP_TABLE_PARAM *param);
@@ -2263,17 +2303,17 @@ Item *remove_eq_conds(THD *thd, Item *co
 int get_quick_record(SQL_SELECT *select);
 SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length,
                                   SORT_FIELD *sortorder);
-int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
 		List<Item> &fields, List <Item> &all_fields, ORDER *order);
-int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+int setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
 		List<Item> &fields, List<Item> &all_fields, ORDER *order,
 		bool *hidden_group_fields);
 bool fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
-                   Item **ref_pointer_array, ORDER *group_list= NULL);
+                   Ref_ptr_array ref_pointer_array, ORDER *group_list= NULL);
 
 bool handle_select(THD *thd, LEX *lex, select_result *result,
                    ulong setup_tables_done_option);
-bool mysql_select(THD *thd, Item ***rref_pointer_array,
+bool mysql_select(THD *thd,
                   TABLE_LIST *tables, uint wild_num,  List<Item> &list,
                   Item *conds, uint og_num, ORDER *order, ORDER *group,
                   Item *having, ORDER *proc_param, ulonglong select_type, 

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2011-06-16 23:45:58 +0000
+++ b/sql/sql_table.cc	2011-06-20 12:07:06 +0000
@@ -4978,6 +4978,35 @@ err:
   DBUG_RETURN(-1);
 }
 
+
+/**
+  Check if ALTER TABLE statement changes position of any column
+  in the table or adds new columns.
+
+  @param alter_info  Alter_info object describing structure of new
+                     version of table.
+
+  @retval True  - some column is added or changes its position.
+  @retval False - no columns are added nor their positions change.
+*/
+
+static bool has_new_or_reordered_columns(Alter_info *alter_info)
+{
+  List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
+  Create_field *new_field;
+  uint new_field_idx;
+
+  for (new_field_idx= 0, new_field= new_field_it++; new_field;
+       new_field_idx++, new_field= new_field_it++)
+  {
+    if (! new_field->field ||
+        new_field->field->field_index != new_field_idx)
+      return true;
+  }
+  return false;
+}
+
+
 /**
   @brief Check if both DROP and CREATE are present for an index in ALTER TABLE
 
@@ -5577,12 +5606,6 @@ mysql_prepare_alter_table(THD *thd, TABL
     if (drop)
     {
       drop_it.remove();
-      /*
-        ALTER TABLE DROP COLUMN always changes table data even in cases
-        when new version of the table has the same structure as the old
-        one.
-      */
-      alter_info->change_level= ALTER_TABLE_DATA_CHANGED;
       continue;
     }
     /* Check if field is changed */
@@ -5662,11 +5685,6 @@ mysql_prepare_alter_table(THD *thd, TABL
     else if (def->after == first_keyword)
     {
       new_create_list.push_front(def);
-      /*
-        Re-ordering columns in table can't be done using in-place algorithm
-        as it always changes table data.
-      */
-      alter_info->change_level= ALTER_TABLE_DATA_CHANGED;
     }
     else
     {
@@ -5683,11 +5701,6 @@ mysql_prepare_alter_table(THD *thd, TABL
         goto err;
       }
       find_it.after(def);			// Put element after this
-      /*
-        Re-ordering columns in table can't be done using in-place algorithm
-        as it always changes table data.
-      */
-      alter_info->change_level= ALTER_TABLE_DATA_CHANGED;
     }
   }
   if (alter_info->alter_list.elements)
@@ -6368,6 +6381,17 @@ bool mysql_alter_table(THD *thd,char *ne
     if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
       need_copy_table= need_copy_table_res;
 
+    if (need_copy_table != ALTER_TABLE_DATA_CHANGED &&
+        has_new_or_reordered_columns(alter_info))
+    {
+      /*
+        ALTER TABLE which adds new columns (e.g. replacing columns being
+        removed) or changes their order can't be executed using in-place
+        algorithm even if table structure stays the same.
+      */
+      need_copy_table= ALTER_TABLE_DATA_CHANGED;
+    }
+
     if (need_copy_table == ALTER_TABLE_INDEX_CHANGED)
     {
       if (is_index_maintenance_unique(table, key_info_buffer,

=== modified file 'sql/sql_union.cc'
--- a/sql/sql_union.cc	2011-05-26 15:20:09 +0000
+++ b/sql/sql_union.cc	2011-06-24 09:29:07 +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
@@ -10,9 +10,8 @@
    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,
-   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
-
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA */
 
 /*
   UNION  of select's
@@ -270,8 +269,7 @@ bool st_select_lex_unit::prepare(THD *th
 
     can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
 
-    saved_error= join->prepare(&sl->ref_pointer_array,
-                               sl->table_list.first,
+    saved_error= join->prepare(sl->table_list.first,
                                sl->with_wild,
                                sl->where,
                                (can_skip_order_by ? 0 :
@@ -419,23 +417,38 @@ bool st_select_lex_unit::prepare(THD *th
 	init_prepare_fake_select_lex(thd);
         /* Should be done only once (the only item_list per statement) */
         DBUG_ASSERT(fake_select_lex->join == 0);
-	if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->variables.option_bits,
-					      result)))
+	if (!(fake_select_lex->join=
+              new JOIN(thd, item_list, thd->variables.option_bits, result)))
 	{
 	  fake_select_lex->table_list.empty();
 	  DBUG_RETURN(TRUE);
 	}
+
+        /*
+          Fake st_select_lex should have item list for correct ref_array
+          allocation.
+        */
 	fake_select_lex->item_list= item_list;
 
-	thd_arg->lex->current_select= fake_select_lex;
+        thd_arg->lex->current_select= fake_select_lex;
+
+        /*
+          We need to add up n_sum_items in order to make the correct
+          allocation in setup_ref_array().
+        */
+        fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
+
 	saved_error= fake_select_lex->join->
-	  prepare(&fake_select_lex->ref_pointer_array,
-		  fake_select_lex->table_list.first,
-		  0, 0,
-		  fake_select_lex->order_list.elements,
-		  fake_select_lex->order_list.first,
-		  NULL, NULL, NULL,
-		  fake_select_lex, this);
+	  prepare(fake_select_lex->table_list.first, // tables_init
+                  0,                                 // wild_num
+                  0,                                 // conds_init
+                  global_parameters->order_list.elements, // og_num
+                  global_parameters->order_list.first,    // order
+                  NULL,                                // group_init
+                  NULL,                                // having_init
+                  NULL,                                // proc_param_init
+                  fake_select_lex,                     // select_lex_arg
+                  this);                               // unit_arg
 	fake_select_lex->table_list.empty();
       }
     }
@@ -607,18 +620,35 @@ bool st_select_lex_unit::exec()
         fake_select_lex->join->no_const_tables= true;
 
         /*
-          Fake st_select_lex should have item list for correctref_array
+          Fake st_select_lex should have item list for correct ref_array
           allocation.
         */
         fake_select_lex->item_list= item_list;
-        saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
-                              &result_table_list,
-                              0, item_list, NULL,
-                              global_parameters->order_list.elements,
-                              global_parameters->order_list.first,
-                              NULL, NULL, NULL,
-                              fake_select_lex->options | SELECT_NO_UNLOCK,
-                              result, this, fake_select_lex);
+
+        /*
+          We need to add up n_sum_items in order to make the correct
+          allocation in setup_ref_array().
+          Don't add more sum_items if we have already done JOIN::prepare
+          for this (with a different join object)
+        */
+        if (fake_select_lex->ref_pointer_array.is_null())
+          fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
+
+        saved_error=
+          mysql_select(thd,
+                       &result_table_list,      // tables
+                       0,                       // wild_num
+                       item_list,               // fields
+                       NULL,                    // conds
+                       global_parameters->order_list.elements, // og_num
+                       global_parameters->order_list.first,    // order
+                       NULL,                    // group
+                       NULL,                    // having
+                       NULL,                    // proc_param
+                       fake_select_lex->options | SELECT_NO_UNLOCK,
+                       result,                  // result
+                       this,                    // unit
+                       fake_select_lex);        // select_lex
       }
       else
       {
@@ -634,7 +664,7 @@ bool st_select_lex_unit::exec()
             to reset them back, we re-do all of the actions (yes it is ugly):
           */
           join->init(thd, item_list, fake_select_lex->options, result);
-          saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
+          saved_error= mysql_select(thd,
                                 &result_table_list,
                                 0, item_list, NULL,
                                 global_parameters->order_list.elements,

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2011-06-16 06:30:16 +0000
+++ b/sql/sql_update.cc	2011-06-24 09:29:07 +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
@@ -328,7 +328,8 @@ int mysql_update(THD *thd,
   table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
   table_list->register_want_access(want_privilege);
 #endif
-  if (setup_fields_with_no_wrap(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
+  if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
+                                fields, MARK_COLUMNS_WRITE, 0, 0))
     DBUG_RETURN(1);                     /* purecov: inspected */
   if (table_list->view && check_fields(thd, fields))
   {
@@ -359,7 +360,7 @@ int mysql_update(THD *thd,
   table_list->grant.want_privilege= table->grant.want_privilege=
     (SELECT_ACL & ~table->grant.privilege);
 #endif
-  if (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0))
+  if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0))
   {
     free_underlaid_joins(thd, select_lex);
     DBUG_RETURN(1);				/* purecov: inspected */
@@ -1158,7 +1159,8 @@ int mysql_multi_update_prepare(THD *thd)
                                     UPDATE_ACL, SELECT_ACL))
     DBUG_RETURN(TRUE);
 
-  if (setup_fields_with_no_wrap(thd, 0, *fields, MARK_COLUMNS_WRITE, 0, 0))
+  if (setup_fields_with_no_wrap(thd, Ref_ptr_array(),
+                                *fields, MARK_COLUMNS_WRITE, 0, 0))
     DBUG_RETURN(TRUE);
 
   for (tl= table_list; tl ; tl= tl->next_local)
@@ -1347,7 +1349,7 @@ bool mysql_multi_update(THD *thd,
 
   List<Item> total_list;
 
-  res= mysql_select(thd, &select_lex->ref_pointer_array,
+  res= mysql_select(thd,
                     table_list, select_lex->with_wild,
                     total_list,
                     conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
@@ -1432,7 +1434,8 @@ int multi_update::prepare(List<Item> &no
     reference tables
   */
 
-  int error= setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0);
+  int error= setup_fields(thd, Ref_ptr_array(),
+                          *values, MARK_COLUMNS_READ, 0, 0);
 
   for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
   {

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2011-06-09 18:18:22 +0000
+++ b/sql/sql_yacc.yy	2011-06-24 09:29:07 +0000
@@ -11033,7 +11033,9 @@ show:
             memset(&lex->create_info, 0, sizeof(lex->create_info));
           }
           show_param
-          {}
+          {
+            Select->parsing_place= NO_MATTER;
+          }
         ;
 
 show_param:
@@ -11375,7 +11377,10 @@ describe:
             if (prepare_schema_table(YYTHD, lex, $2, SCH_COLUMNS))
               MYSQL_YYABORT;
           }
-          opt_describe_column {}
+          opt_describe_column
+          {
+            Select->parsing_place= NO_MATTER;
+          }
         | describe_command opt_extended_describe
           { Lex->describe|= DESCRIBE_NORMAL; }
           select

=== modified file 'storage/innobase/CMakeLists.txt'
--- a/storage/innobase/CMakeLists.txt	2011-04-18 02:17:16 +0000
+++ b/storage/innobase/CMakeLists.txt	2011-06-23 06:48:48 +0000
@@ -227,6 +227,7 @@ SET(INNOBASE_SOURCES
 	btr/btr0sea.c
 	buf/buf0buddy.c
 	buf/buf0buf.c
+	buf/buf0dump.c
 	buf/buf0flu.c
 	buf/buf0lru.c
 	buf/buf0rea.c

=== modified file 'storage/innobase/buf/buf0buddy.c'
--- a/storage/innobase/buf/buf0buddy.c	2011-06-17 20:32:42 +0000
+++ b/storage/innobase/buf/buf0buddy.c	2011-06-23 13:03:09 +0000
@@ -79,7 +79,6 @@ buf_buddy_add_to_free(
 	ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
 	ut_ad(buf_pool->zip_free[i].start != bpage);
 	UT_LIST_ADD_FIRST(list, buf_pool->zip_free[i], bpage);
-
 }
 
 /**********************************************************************//**
@@ -104,7 +103,6 @@ buf_buddy_remove_from_free(
 	ut_ad(buf_pool_mutex_own(buf_pool));
 	ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
 	UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage);
-
 }
 
 /**********************************************************************//**
@@ -262,19 +260,19 @@ buf_buddy_alloc_from(
 Allocate a block.  The thread calling this function must hold
 buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex.
 The buf_pool_mutex may be released and reacquired.
-@return        allocated block, never NULL */
+@return	allocated block, never NULL */
 UNIV_INTERN
 void*
 buf_buddy_alloc_low(
 /*================*/
-	buf_pool_t*	buf_pool,	/*!< in: buffer pool instance */
+	buf_pool_t*	buf_pool,	/*!< in/out: buffer pool instance */
 	ulint		i,		/*!< in: index of buf_pool->zip_free[],
 					or BUF_BUDDY_SIZES */
 	ibool*		lru)		/*!< in: pointer to a variable that
 					will be assigned TRUE if storage was
 					allocated from the LRU list and
 					buf_pool->mutex was temporarily
-					released, */
+					released */
 {
 	buf_block_t*	block;
 
@@ -353,7 +351,6 @@ buf_buddy_relocate(
 	header. Should the fields be invalid, we will be unable to
 	relocate the block. */
 
-
 	/* The src block may be split into smaller blocks,
 	some of which may be free.  Thus, the
 	mach_read_from_4() calls below may attempt to read
@@ -362,10 +359,10 @@ buf_buddy_relocate(
 	pool), so there is nothing wrong about this.  The
 	mach_read_from_4() calls here will only trigger bogus
 	Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
-	space	= mach_read_from_4((const byte*) src +
-			FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
-	page_no	= mach_read_from_4((const byte*) src +
-			FIL_PAGE_OFFSET);
+	space	= mach_read_from_4((const byte *) src
+				   + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
+	page_no	= mach_read_from_4((const byte *) src
+				   + FIL_PAGE_OFFSET);
 	/* Suppress Valgrind warnings about conditional jump
 	on uninitialized value. */
 	UNIV_MEM_VALID(&space, sizeof space);
@@ -460,21 +457,21 @@ recombine:
 	if (UT_LIST_GET_LEN(buf_pool->zip_free[i]) < 16) {
 		goto func_exit;
 	}
- 
+
 	/* Try to combine adjacent blocks. */
- 	buddy = (buf_page_t*) buf_buddy_get(((byte*) buf), BUF_BUDDY_LOW << i);
- 
- #ifndef UNIV_DEBUG_VALGRIND
+	buddy = (buf_page_t*) buf_buddy_get(((byte*) buf), BUF_BUDDY_LOW << i);
+
+#ifndef UNIV_DEBUG_VALGRIND
 	/* When Valgrind instrumentation is not enabled, we can read
 	buddy->state to quickly determine that a block is not free.
 	When the block is not free, buddy->state belongs to a compressed
 	page frame that may be flagged uninitialized in our Valgrind
 	instrumentation.  */
- 
- 	if (buddy->state != BUF_BLOCK_ZIP_FREE) {
- 
- 		goto buddy_nonfree;
- 	}
+
+	if (buddy->state != BUF_BLOCK_ZIP_FREE) {
+
+		goto buddy_nonfree;
+	}
 #endif /* !UNIV_DEBUG_VALGRIND */
 
 	for (bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); bpage; ) {
@@ -501,12 +498,13 @@ buddy_is_free:
 buddy_nonfree:
 #endif /* !UNIV_DEBUG_VALGRIND */
 
-	 ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
+	ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
 
 	/* The buddy is not free. Is there a free block of this size? */
 	bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
 
 	if (bpage) {
+
 		/* Remove the block from the free list, because a successful
 		buf_buddy_relocate() will overwrite bpage->list. */
 		buf_buddy_remove_from_free(buf_pool, bpage, i);

=== modified file 'storage/innobase/buf/buf0buf.c'
--- a/storage/innobase/buf/buf0buf.c	2011-06-17 20:32:42 +0000
+++ b/storage/innobase/buf/buf0buf.c	2011-06-23 13:03:09 +0000
@@ -3451,9 +3451,6 @@ err_exit:
 		uninitialized data. */
 		data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
-		/* Initialize the buf_pool pointer. */
-		bpage->buf_pool_index = buf_pool_index(buf_pool);
-
 		rw_lock_x_lock(hash_lock);
 
 		/* If buf_buddy_alloc() allocated storage from the LRU list,
@@ -3480,6 +3477,9 @@ err_exit:
 
 		bpage = buf_page_alloc_descriptor();
 
+		/* Initialize the buf_pool pointer. */
+		bpage->buf_pool_index = buf_pool_index(buf_pool);
+
 		page_zip_des_init(&bpage->zip);
 		page_zip_set_size(&bpage->zip, zip_size);
 		bpage->zip.data = data;
@@ -3494,7 +3494,6 @@ err_exit:
 		bpage->space	= space;
 		bpage->offset	= offset;
 
-
 #ifdef UNIV_DEBUG
 		bpage->in_page_hash = FALSE;
 		bpage->in_zip_hash = FALSE;

=== added file 'storage/innobase/buf/buf0dump.c'
--- a/storage/innobase/buf/buf0dump.c	1970-01-01 00:00:00 +0000
+++ b/storage/innobase/buf/buf0dump.c	2011-06-23 06:48:48 +0000
@@ -0,0 +1,614 @@
+/*****************************************************************************
+
+Copyright (c) 2011, 2011, Oracle and/or its affiliates. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/**************************************************//**
+@file buf/buf0dump.c
+Implements a buffer pool dump/load.
+
+Created April 08, 2011 Vasil Dimov
+*******************************************************/
+
+#include <stdarg.h> /* va_* */
+#include <string.h> /* strerror() */
+
+#include "univ.i"
+
+#include "buf0buf.h" /* buf_pool_mutex_enter(), srv_buf_pool_instances */
+#include "buf0dump.h"
+#include "db0err.h" /* enum db_err */
+#include "dict0dict.h" /* dict_operation_lock */
+#include "os0file.h" /* OS_FILE_MAX_PATH */
+#include "os0sync.h" /* os_event* */
+#include "os0thread.h" /* os_thread_* */
+#include "srv0srv.h" /* srv_fast_shutdown, srv_buf_dump* */
+#include "srv0start.h" /* srv_shutdown_state */
+#include "sync0rw.h" /* rw_lock_s_lock() */
+#include "ut0byte.h" /* ut_ull_create() */
+#include "ut0sort.h" /* UT_SORT_FUNCTION_BODY */
+
+enum status_severity {
+	STATUS_INFO,
+	STATUS_NOTICE,
+	STATUS_ERR,
+};
+
+#define SHUTTING_DOWN()	(UNIV_UNLIKELY(srv_shutdown_state \
+				       != SRV_SHUTDOWN_NONE))
+
+/* Flags that tell the buffer pool dump/load thread which action should it
+take after being waked up. */
+static ibool	buf_dump_should_start = FALSE;
+static ibool	buf_load_should_start = FALSE;
+
+static ibool	buf_load_abort_flag = FALSE;
+
+/* Used to temporary store dump info in order to avoid IO while holding
+buffer pool mutex during dump and also to sort the contents of the dump
+before reading the pages from disk during load.
+We store the space id in the high 32 bits and page no in low 32 bits. */
+typedef ib_uint64_t	buf_dump_t;
+
+/* Aux macros to create buf_dump_t and to extract space and page from it */
+#define BUF_DUMP_CREATE(space, page)	ut_ull_create(space, page)
+#define BUF_DUMP_SPACE(a)		((ulint) ((a) >> 32))
+#define BUF_DUMP_PAGE(a)		((ulint) ((a) & 0xFFFFFFFFUL))
+
+/*****************************************************************//**
+Wakes up the buffer pool dump/load thread and instructs it to start
+a dump. This function is called by MySQL code via buffer_pool_dump_now()
+and it should return immediately because the whole MySQL is frozen during
+its execution. */
+UNIV_INTERN
+void
+buf_dump_start()
+/*============*/
+{
+	buf_dump_should_start = TRUE;
+	os_event_set(srv_buf_dump_event);
+}
+
+/*****************************************************************//**
+Wakes up the buffer pool dump/load thread and instructs it to start
+a load. This function is called by MySQL code via buffer_pool_load_now()
+and it should return immediately because the whole MySQL is frozen during
+its execution. */
+UNIV_INTERN
+void
+buf_load_start()
+/*============*/
+{
+	buf_load_should_start = TRUE;
+	os_event_set(srv_buf_dump_event);
+}
+
+/*****************************************************************//**
+Sets the global variable that feeds MySQL's innodb_buffer_pool_dump_status
+to the specified string. The format and the following parameters are the
+same as the ones used for printf(3). The value of this variable can be
+retrieved by:
+SELECT variable_value FROM information_schema.global_status WHERE
+variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS';
+or by:
+SHOW STATUS LIKE 'innodb_buffer_pool_dump_status'; */
+static __attribute__((nonnull, format(printf, 2, 3)))
+void
+buf_dump_status(
+/*============*/
+	enum status_severity	severity,/*!< in: status severity */
+	const char*		fmt,	/*!< in: format */
+	...)				/*!< in: extra parameters according
+					to fmt */
+{
+	va_list	ap;
+
+	va_start(ap, fmt);
+
+	ut_vsnprintf(
+		export_vars.innodb_buffer_pool_dump_status,
+		sizeof(export_vars.innodb_buffer_pool_dump_status),
+		fmt, ap);
+
+	if (severity == STATUS_NOTICE || severity == STATUS_ERR) {
+		ut_print_timestamp(stderr);
+		fprintf(stderr, " InnoDB: %s\n",
+			export_vars.innodb_buffer_pool_dump_status);
+	}
+
+	va_end(ap);
+}
+
+/*****************************************************************//**
+Sets the global variable that feeds MySQL's innodb_buffer_pool_load_status
+to the specified string. The format and the following parameters are the
+same as the ones used for printf(3). The value of this variable can be
+retrieved by:
+SELECT variable_value FROM information_schema.global_status WHERE
+variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS';
+or by:
+SHOW STATUS LIKE 'innodb_buffer_pool_load_status'; */
+static __attribute__((nonnull, format(printf, 2, 3)))
+void
+buf_load_status(
+/*============*/
+	enum status_severity	severity,/*!< in: status severity */
+	const char*	fmt,	/*!< in: format */
+	...)			/*!< in: extra parameters according to fmt */
+{
+	va_list	ap;
+
+	va_start(ap, fmt);
+
+	ut_vsnprintf(
+		export_vars.innodb_buffer_pool_load_status,
+		sizeof(export_vars.innodb_buffer_pool_load_status),
+		fmt, ap);
+
+	if (severity == STATUS_NOTICE || severity == STATUS_ERR) {
+		ut_print_timestamp(stderr);
+		fprintf(stderr, " InnoDB: %s\n",
+			export_vars.innodb_buffer_pool_load_status);
+	}
+
+	va_end(ap);
+}
+
+/*****************************************************************//**
+Perform a buffer pool dump into the file specified by
+innodb_buffer_pool_filename. If any errors occur then the value of
+innodb_buffer_pool_dump_status will be set accordingly, see buf_dump_status().
+The dump filename can be specified by (relative to srv_data_home):
+SET GLOBAL innodb_buffer_pool_filename='filename'; */
+static
+void
+buf_dump(
+/*=====*/
+	ibool	obey_shutdown)	/*!< in: quit if we are in a shutting down
+				state */
+{
+#define SHOULD_QUIT()	(SHUTTING_DOWN() && obey_shutdown)
+
+	char	full_filename[OS_FILE_MAX_PATH];
+	char	tmp_filename[OS_FILE_MAX_PATH];
+	char	now[32];
+	FILE*	f;
+	ulint	i;
+	int	ret;
+
+	ut_snprintf(full_filename, sizeof(full_filename),
+		    "%s%c%s", srv_data_home, SRV_PATH_SEPARATOR,
+		    srv_buf_dump_filename);
+
+	ut_snprintf(tmp_filename, sizeof(tmp_filename),
+		    "%s.incomplete", full_filename);
+
+	buf_dump_status(STATUS_NOTICE, "Dumping buffer pool(s) to %s",
+			full_filename);
+
+	f = fopen(tmp_filename, "w");
+	if (f == NULL) {
+		buf_dump_status(STATUS_ERR,
+				"Cannot open '%s' for writing: %s",
+				tmp_filename, strerror(errno));
+		return;
+	}
+	/* else */
+
+	/* walk through each buffer pool */
+	for (i = 0; i < srv_buf_pool_instances && !SHOULD_QUIT(); i++) {
+		buf_pool_t*		buf_pool;
+		const buf_page_t*	bpage;
+		buf_dump_t*		dump;
+		ulint			n_pages;
+		ulint			j;
+
+		buf_pool = buf_pool_from_array(i);
+
+		/* obtain buf_pool mutex before allocate, since
+		UT_LIST_GET_LEN(buf_pool->LRU) could change */
+		buf_pool_mutex_enter(buf_pool);
+
+		n_pages = UT_LIST_GET_LEN(buf_pool->LRU);
+
+		/* skip empty buffer pools */
+		if (n_pages == 0) {
+			buf_pool_mutex_exit(buf_pool);
+			continue;
+		}
+
+		dump = ut_malloc(n_pages * sizeof(*dump));
+		if (dump == NULL) {
+			buf_pool_mutex_exit(buf_pool);
+			fclose(f);
+			buf_dump_status(STATUS_ERR,
+					"Cannot allocate " ULINTPF " bytes: %s",
+					(ulint) (n_pages * sizeof(*dump)),
+					strerror(errno));
+			/* leave tmp_filename to exist */
+			return;
+		}
+
+		for (bpage = UT_LIST_GET_LAST(buf_pool->LRU), j = 0;
+		     bpage != NULL;
+		     bpage = UT_LIST_GET_PREV(LRU, bpage), j++) {
+
+			ut_a(buf_page_in_file(bpage));
+
+			dump[j] = BUF_DUMP_CREATE(buf_page_get_space(bpage),
+						  buf_page_get_page_no(bpage));
+		}
+
+		ut_a(j == n_pages);
+
+		buf_pool_mutex_exit(buf_pool);
+
+		for (j = 0; j < n_pages && !SHOULD_QUIT(); j++) {
+			ret = fprintf(f, ULINTPF "," ULINTPF "\n",
+				      BUF_DUMP_SPACE(dump[j]),
+				      BUF_DUMP_PAGE(dump[j]));
+			if (ret < 0) {
+				ut_free(dump);
+				fclose(f);
+				buf_dump_status(STATUS_ERR,
+						"Cannot write to '%s': %s",
+						tmp_filename, strerror(errno));
+				/* leave tmp_filename to exist */
+				return;
+			}
+
+			if (j % 128 == 0) {
+				buf_dump_status(
+					STATUS_INFO,
+					"Dumping buffer pool "
+					ULINTPF "/" ULINTPF ", "
+					"page " ULINTPF "/" ULINTPF,
+					i + 1, srv_buf_pool_instances,
+					j + 1, n_pages);
+			}
+		}
+
+		ut_free(dump);
+	}
+
+	ret = fclose(f);
+	if (ret != 0) {
+		buf_dump_status(STATUS_ERR,
+				"Cannot close '%s': %s",
+				tmp_filename, strerror(errno));
+		return;
+	}
+	/* else */
+
+	ret = unlink(full_filename);
+	if (ret != 0 && errno != ENOENT) {
+		buf_dump_status(STATUS_ERR,
+				"Cannot delete '%s': %s",
+				full_filename, strerror(errno));
+		/* leave tmp_filename to exist */
+		return;
+	}
+	/* else */
+
+	ret = rename(tmp_filename, full_filename);
+	if (ret != 0) {
+		buf_dump_status(STATUS_ERR,
+				"Cannot rename '%s' to '%s': %s",
+				tmp_filename, full_filename,
+				strerror(errno));
+		/* leave tmp_filename to exist */
+		return;
+	}
+	/* else */
+
+	/* success */
+
+	ut_sprintf_timestamp(now);
+
+	buf_dump_status(STATUS_NOTICE,
+			"Buffer pool(s) dump completed at %s", now);
+}
+
+/*****************************************************************//**
+Compare two buffer pool dump entries, used to sort the dump on
+space_no,page_no before loading in order to increase the chance for
+sequential IO.
+@return -1/0/1 if entry 1 is smaller/equal/bigger than entry 2 */
+static
+lint
+buf_dump_cmp(
+/*=========*/
+	const buf_dump_t	d1,	/*!< in: buffer pool dump entry 1 */
+	const buf_dump_t	d2)	/*!< in: buffer pool dump entry 2 */
+{
+	if (d1 < d2) {
+		return(-1);
+	} else if (d1 == d2) {
+		return(0);
+	} else {
+		return(1);
+	}
+}
+
+/*****************************************************************//**
+Sort a buffer pool dump on space_no, page_no. */
+static
+void
+buf_dump_sort(
+/*==========*/
+	buf_dump_t*	dump,	/*!< in/out: buffer pool dump to sort */
+	buf_dump_t*	tmp,	/*!< in/out: temp storage */
+	ulint		low,	/*!< in: lowest index (inclusive) */
+	ulint		high)	/*!< in: highest index (non-inclusive) */
+{
+	UT_SORT_FUNCTION_BODY(buf_dump_sort, dump, tmp, low, high,
+			      buf_dump_cmp);
+}
+
+/*****************************************************************//**
+Perform a buffer pool load from the file specified by
+innodb_buffer_pool_filename. If any errors occur then the value of
+innodb_buffer_pool_load_status will be set accordingly, see buf_load_status().
+The dump filename can be specified by (relative to srv_data_home):
+SET GLOBAL innodb_buffer_pool_filename='filename'; */
+static
+void
+buf_load()
+/*======*/
+{
+	char		full_filename[OS_FILE_MAX_PATH];
+	char		now[32];
+	FILE*		f;
+	buf_dump_t*	dump;
+	buf_dump_t*	dump_tmp;
+	ulint		dump_n;
+	ulint		total_buffer_pools_pages;
+	ulint		i;
+	ulint		space_id;
+	ulint		page_no;
+	int		fscanf_ret;
+
+	/* Ignore any leftovers from before */
+	buf_load_abort_flag = FALSE;
+
+	ut_snprintf(full_filename, sizeof(full_filename),
+		    "%s%c%s", srv_data_home, SRV_PATH_SEPARATOR,
+		    srv_buf_dump_filename);
+
+	buf_load_status(STATUS_NOTICE,
+			"Loading buffer pool(s) from %s", full_filename);
+
+	f = fopen(full_filename, "r");
+	if (f == NULL) {
+		buf_load_status(STATUS_ERR,
+				"Cannot open '%s' for reading: %s",
+				full_filename, strerror(errno));
+		return;
+	}
+	/* else */
+
+	/* First scan the file to estimate how many entries are in it.
+	This file is tiny (approx 500KB per 1GB buffer pool), reading it
+	two times is fine. */
+	dump_n = 0;
+	while (fscanf(f, ULINTPF "," ULINTPF, &space_id, &page_no) == 2
+	       && !SHUTTING_DOWN()) {
+		dump_n++;
+	}
+
+	if (!SHUTTING_DOWN() && !feof(f)) {
+		/* fscanf() returned != 2 */
+		const char*	what;
+		if (ferror(f)) {
+			what = "reading";
+		} else {
+			what = "parsing";
+		}
+		fclose(f);
+		buf_load_status(STATUS_ERR, "Error %s '%s', "
+				"unable to load buffer pool (stage 1)",
+				what, full_filename);
+		return;
+	}
+
+	/* If dump is larger than the buffer pool(s), then we ignore the
+	extra trailing. This could happen if a dump is made, then buffer
+	pool is shrunk and then load it attempted. */
+	total_buffer_pools_pages = buf_pool_get_n_pages()
+		* srv_buf_pool_instances;
+	if (dump_n > total_buffer_pools_pages) {
+		dump_n = total_buffer_pools_pages;
+	}
+
+	dump = ut_malloc(dump_n * sizeof(*dump));
+	if (dump == NULL) {
+		fclose(f);
+		buf_load_status(STATUS_ERR,
+				"Cannot allocate " ULINTPF " bytes: %s",
+				(ulint) (dump_n * sizeof(*dump)),
+				strerror(errno));
+		return;
+	}
+
+	dump_tmp = ut_malloc(dump_n * sizeof(*dump_tmp));
+	if (dump_tmp == NULL) {
+		ut_free(dump);
+		fclose(f);
+		buf_load_status(STATUS_ERR,
+				"Cannot allocate " ULINTPF " bytes: %s",
+				(ulint) (dump_n * sizeof(*dump_tmp)),
+				strerror(errno));
+		return;
+	}
+
+	rewind(f);
+
+	for (i = 0; i < dump_n && !SHUTTING_DOWN(); i++) {
+		fscanf_ret = fscanf(f, ULINTPF "," ULINTPF,
+				    &space_id, &page_no);
+
+		if (fscanf_ret != 2) {
+			if (feof(f)) {
+				break;
+			}
+			/* else */
+
+			ut_free(dump);
+			ut_free(dump_tmp);
+			fclose(f);
+			buf_load_status(STATUS_ERR,
+					"Error parsing '%s', unable "
+					"to load buffer pool (stage 2)",
+					full_filename);
+			return;
+		}
+
+		if (space_id > ULINT32_MASK || page_no > ULINT32_MASK) {
+			ut_free(dump);
+			ut_free(dump_tmp);
+			fclose(f);
+			buf_load_status(STATUS_ERR,
+					"Error parsing '%s': bogus "
+					"space,page " ULINTPF "," ULINTPF
+					" at line " ULINTPF ", "
+					"unable to load buffer pool",
+					full_filename,
+					space_id, page_no,
+					i);
+			return;
+		}
+
+		dump[i] = BUF_DUMP_CREATE(space_id, page_no);
+	}
+
+	/* Set dump_n to the actual number of initialized elements,
+	i could be smaller than dump_n here if the file got truncated after
+	we read it the first time. */
+	dump_n = i;
+
+	fclose(f);
+
+	if (dump_n == 0) {
+		ut_free(dump);
+		ut_sprintf_timestamp(now);
+		buf_load_status(STATUS_NOTICE,
+				"Buffer pool(s) load completed at %s "
+				"(%s was empty)", now, full_filename);
+		return;
+	}
+
+	if (!SHUTTING_DOWN()) {
+		buf_dump_sort(dump, dump_tmp, 0, dump_n);
+	}
+
+	ut_free(dump_tmp);
+
+	for (i = 0; i < dump_n && !SHUTTING_DOWN(); i++) {
+
+		buf_read_page_async(BUF_DUMP_SPACE(dump[i]),
+				    BUF_DUMP_PAGE(dump[i]));
+
+		if (i % 64 == 63) {
+			os_aio_simulated_wake_handler_threads();
+		}
+
+		if (i % 128 == 0) {
+			buf_load_status(STATUS_INFO,
+					"Loaded " ULINTPF "/" ULINTPF " pages",
+					i + 1, dump_n);
+		}
+
+		if (buf_load_abort_flag) {
+			buf_load_abort_flag = FALSE;
+			ut_free(dump);
+			buf_load_status(
+				STATUS_NOTICE,
+				"Buffer pool(s) load aborted on request");
+			return;
+		}
+	}
+
+	ut_free(dump);
+
+	ut_sprintf_timestamp(now);
+
+	buf_load_status(STATUS_NOTICE,
+			"Buffer pool(s) load completed at %s", now);
+}
+
+/*****************************************************************//**
+Aborts a currently running buffer pool load. This function is called by
+MySQL code via buffer_pool_load_abort() and it should return immediately
+because the whole MySQL is frozen during its execution. */
+UNIV_INTERN
+void
+buf_load_abort()
+/*============*/
+{
+	buf_load_abort_flag = TRUE;
+}
+
+/*****************************************************************//**
+This is the main thread for buffer pool dump/load. It waits for an
+event and when waked up either performs a dump or load and sleeps
+again.
+@return this function does not return, it calls os_thread_exit() */
+UNIV_INTERN
+os_thread_ret_t
+buf_dump_thread(
+/*============*/
+	void*	arg __attribute__((unused)))	/*!< in: a dummy parameter
+						required by os_thread_create */
+{
+	srv_buf_dump_thread_active = TRUE;
+
+	buf_dump_status(STATUS_INFO, "not started");
+	buf_load_status(STATUS_INFO, "not started");
+
+	if (srv_buffer_pool_load_at_startup) {
+		buf_load();
+	}
+
+	while (!SHUTTING_DOWN()) {
+
+		os_event_wait(srv_buf_dump_event);
+
+		if (buf_dump_should_start) {
+			buf_dump_should_start = FALSE;
+			buf_dump(TRUE /* quit on shutdown */);
+		}
+
+		if (buf_load_should_start) {
+			buf_load_should_start = FALSE;
+			buf_load();
+		}
+
+		os_event_reset(srv_buf_dump_event);
+	}
+
+	if (srv_buffer_pool_dump_at_shutdown && srv_fast_shutdown != 2) {
+		buf_dump(FALSE /* ignore shutdown down flag,
+		keep going even if we are in a shutdown state */);
+	}
+
+	srv_buf_dump_thread_active = FALSE;
+
+	/* We count the number of threads in os_thread_exit(). A created
+	thread should always use that to exit and not use return() to exit. */
+	os_thread_exit(NULL);
+
+	OS_THREAD_DUMMY_RETURN;
+}

=== modified file 'storage/innobase/buf/buf0lru.c'
--- a/storage/innobase/buf/buf0lru.c	2011-06-17 20:32:42 +0000
+++ b/storage/innobase/buf/buf0lru.c	2011-06-23 13:03:09 +0000
@@ -1876,7 +1876,6 @@ buf_LRU_block_remove_hashed_page(
 
 		buf_pool_mutex_exit_allow(buf_pool);
 		buf_page_free_descriptor(bpage);
-
 		return(BUF_BLOCK_ZIP_FREE);
 
 	case BUF_BLOCK_FILE_PAGE:

=== modified file 'storage/innobase/buf/buf0rea.c'
--- a/storage/innobase/buf/buf0rea.c	2011-05-04 09:54:04 +0000
+++ b/storage/innobase/buf/buf0rea.c	2011-06-23 06:48:48 +0000
@@ -81,12 +81,16 @@ buf_read_page_low(
 {
 	buf_page_t*	bpage;
 	ulint		wake_later;
+	ibool		ignore_nonexistent_pages;
 
 	*err = DB_SUCCESS;
 
 	wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
 	mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER;
 
+	ignore_nonexistent_pages = mode & BUF_READ_IGNORE_NONEXISTENT_PAGES;
+	mode &= ~BUF_READ_IGNORE_NONEXISTENT_PAGES;
+
 	if (trx_doublewrite && space == TRX_SYS_SPACE
 	    && (   (offset >= trx_doublewrite->block1
 		    && offset < trx_doublewrite->block1
@@ -139,18 +143,27 @@ buf_read_page_low(
 
 	thd_wait_begin(NULL, THD_WAIT_DISKIO);
 	if (zip_size) {
-		*err = fil_io(OS_FILE_READ | wake_later,
+		*err = fil_io(OS_FILE_READ | wake_later
+			      | ignore_nonexistent_pages,
 			      sync, space, zip_size, offset, 0, zip_size,
 			      bpage->zip.data, bpage);
 	} else {
 		ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
 
-		*err = fil_io(OS_FILE_READ | wake_later,
+		*err = fil_io(OS_FILE_READ | wake_later
+			      | ignore_nonexistent_pages,
 			      sync, space, 0, offset, 0, UNIV_PAGE_SIZE,
 			      ((buf_block_t*) bpage)->frame, bpage);
 	}
 	thd_wait_end(NULL);
-	ut_a(*err == DB_SUCCESS);
+
+	if (*err != DB_SUCCESS) {
+		if (ignore_nonexistent_pages) {
+			return(0);
+		}
+		/* else */
+		ut_error;
+	}
 
 	if (sync) {
 		/* The i/o is already completed when we arrive from
@@ -207,6 +220,53 @@ buf_read_page(
 
 	return(count > 0);
 }
+
+/********************************************************************//**
+High-level function which reads a page asynchronously from a file to the
+buffer buf_pool if it is not already there. Sets the io_fix flag and sets
+an exclusive lock on the buffer frame. The flag is cleared and the x-lock
+released by the i/o-handler thread.
+@return TRUE if page has been read in, FALSE in case of failure */
+UNIV_INTERN
+ibool
+buf_read_page_async(
+/*================*/
+	ulint	space,	/*!< in: space id */
+	ulint	offset)	/*!< in: page number */
+{
+	buf_pool_t*	buf_pool = buf_pool_get(space, offset);
+	ulint		zip_size;
+	ib_int64_t	tablespace_version;
+	ulint		count;
+	ulint		err;
+
+	zip_size = fil_space_get_zip_size(space);
+
+	if (zip_size == ULINT_UNDEFINED) {
+		return(FALSE);
+	}
+
+	tablespace_version = fil_space_get_version(space);
+
+	count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE
+				  | OS_AIO_SIMULATED_WAKE_LATER
+				  | BUF_READ_IGNORE_NONEXISTENT_PAGES,
+				  space, zip_size, FALSE,
+				  tablespace_version, offset);
+	srv_buf_pool_reads += count;
+
+	/* Flush pages from the end of the LRU list if necessary */
+	buf_flush_free_margin(buf_pool);
+
+	/* We do not increment number of I/O operations used for LRU policy
+	here (buf_LRU_stat_inc_io()). We use this in heuristics to decide
+	about evicting uncompressed version of compressed pages from the
+	buffer pool. Since this function is called from buffer pool load
+	these IOs are deliberate and are not part of normal workload we can
+	ignore these in our heuristics. */
+
+	return(count > 0);
+}
 
 /********************************************************************//**
 Applies linear read-ahead if in the buf_pool the page is a border page of

=== modified file 'storage/innobase/fil/fil0fil.c'
--- a/storage/innobase/fil/fil0fil.c	2011-05-22 20:19:06 +0000
+++ b/storage/innobase/fil/fil0fil.c	2011-06-23 06:48:48 +0000
@@ -4340,6 +4340,7 @@ fil_io(
 	ulint		is_log;
 	ulint		wake_later;
 	os_offset_t	offset;
+	ibool		ignore_nonexistent_pages;
 
 	is_log = type & OS_FILE_LOG;
 	type = type & ~OS_FILE_LOG;
@@ -4347,6 +4348,9 @@ fil_io(
 	wake_later = type & OS_AIO_SIMULATED_WAKE_LATER;
 	type = type & ~OS_AIO_SIMULATED_WAKE_LATER;
 
+	ignore_nonexistent_pages = type & BUF_READ_IGNORE_NONEXISTENT_PAGES;
+	type &= ~BUF_READ_IGNORE_NONEXISTENT_PAGES;
+
 	ut_ad(byte_offset < UNIV_PAGE_SIZE);
 	ut_ad(!zip_size || !byte_offset);
 	ut_ad(ut_is_2pow(zip_size));
@@ -4413,6 +4417,12 @@ fil_io(
 
 	for (;;) {
 		if (UNIV_UNLIKELY(node == NULL)) {
+			if (ignore_nonexistent_pages) {
+				mutex_exit(&fil_system->mutex);
+				return(DB_ERROR);
+			}
+			/* else */
+
 			fil_report_invalid_page_access(
 				block_offset, space_id, space->name,
 				byte_offset, len, type);

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2011-06-02 07:05:42 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2011-06-23 06:48:48 +0000
@@ -47,6 +47,7 @@ this program; if not, write to the Free
 /* Include necessary InnoDB headers */
 extern "C" {
 #include "univ.i"
+#include "buf0dump.h"
 #include "buf0lru.h"
 #include "buf0flu.h"
 #include "btr0sea.h"
@@ -388,6 +389,10 @@ static MYSQL_THDVAR_ULONG(lock_wait_time
   NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
 
 static SHOW_VAR innodb_status_variables[]= {
+  {"buffer_pool_dump_status",
+  (char*) &export_vars.innodb_buffer_pool_dump_status,	  SHOW_CHAR},
+  {"buffer_pool_load_status",
+  (char*) &export_vars.innodb_buffer_pool_load_status,	  SHOW_CHAR},
   {"buffer_pool_pages_data",
   (char*) &export_vars.innodb_buffer_pool_pages_data,	  SHOW_LONG},
   {"buffer_pool_pages_dirty",
@@ -12054,6 +12059,91 @@ innobase_index_name_is_reserved(
 	return(false);
 }
 
+/* These variables are never read by InnoDB or changed. They are a kind of
+dummies that are needed by the MySQL infrastructure to call
+buffer_pool_dump_now(), buffer_pool_load_now() and buffer_pool_load_abort()
+by the user by doing:
+  SET GLOBAL innodb_buffer_pool_dump_now=ON;
+  SET GLOBAL innodb_buffer_pool_load_now=ON;
+  SET GLOBAL innodb_buffer_pool_load_abort=ON;
+Their values are read by MySQL and displayed to the user when the variables
+are queried, e.g.:
+  SELECT @@innodb_buffer_pool_dump_now;
+  SELECT @@innodb_buffer_pool_load_now;
+  SELECT @@innodb_buffer_pool_load_abort; */
+static my_bool	innodb_buffer_pool_dump_now = FALSE;
+static my_bool	innodb_buffer_pool_load_now = FALSE;
+static my_bool	innodb_buffer_pool_load_abort = FALSE;
+
+/****************************************************************//**
+Trigger a dump of the buffer pool if innodb_buffer_pool_dump_now is set
+to ON. This function is registered as a callback with MySQL. */
+static
+void
+buffer_pool_dump_now(
+/*=================*/
+	THD*				thd	/*!< in: thread handle */
+					__attribute__((unused)),
+	struct st_mysql_sys_var*	var	/*!< in: pointer to system
+						variable */
+					__attribute__((unused)),
+	void*				var_ptr	/*!< out: where the formal
+						string goes */
+					__attribute__((unused)),
+	const void*			save)	/*!< in: immediate result from
+						check function */
+{
+	if (*(my_bool*) save) {
+		buf_dump_start();
+	}
+}
+
+/****************************************************************//**
+Trigger a load of the buffer pool if innodb_buffer_pool_load_now is set
+to ON. This function is registered as a callback with MySQL. */
+static
+void
+buffer_pool_load_now(
+/*=================*/
+	THD*				thd	/*!< in: thread handle */
+					__attribute__((unused)),
+	struct st_mysql_sys_var*	var	/*!< in: pointer to system
+						variable */
+					__attribute__((unused)),
+	void*				var_ptr	/*!< out: where the formal
+						string goes */
+					__attribute__((unused)),
+	const void*			save)	/*!< in: immediate result from
+						check function */
+{
+	if (*(my_bool*) save) {
+		buf_load_start();
+	}
+}
+
+/****************************************************************//**
+Abort a load of the buffer pool if innodb_buffer_pool_load_abort
+is set to ON. This function is registered as a callback with MySQL. */
+static
+void
+buffer_pool_load_abort(
+/*===================*/
+	THD*				thd	/*!< in: thread handle */
+					__attribute__((unused)),
+	struct st_mysql_sys_var*	var	/*!< in: pointer to system
+						variable */
+					__attribute__((unused)),
+	void*				var_ptr	/*!< out: where the formal
+						string goes */
+					__attribute__((unused)),
+	const void*			save)	/*!< in: immediate result from
+						check function */
+{
+	if (*(my_bool*) save) {
+		buf_load_abort();
+	}
+}
+
 static SHOW_VAR innodb_status_variables_export[]= {
   {"Innodb",                   (char*) &show_innodb_vars, SHOW_FUNC},
   {NullS, NullS, SHOW_LONG}
@@ -12278,6 +12368,37 @@ static MYSQL_SYSVAR_LONG(buffer_pool_ins
   "Number of buffer pool instances, set to higher value on high-end machines to increase scalability",
   NULL, NULL, 1L, 1L, MAX_BUFFER_POOLS, 1L);
 
+static MYSQL_SYSVAR_STR(buffer_pool_filename, srv_buf_dump_filename,
+  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
+  "Filename to/from which to dump/load the InnoDB buffer pool",
+  NULL, NULL, SRV_BUF_DUMP_FILENAME_DEFAULT);
+
+static MYSQL_SYSVAR_BOOL(buffer_pool_dump_now, innodb_buffer_pool_dump_now,
+  PLUGIN_VAR_RQCMDARG,
+  "Trigger an immediate dump of the buffer pool into a file named @@innodb_buffer_pool_filename",
+  NULL, buffer_pool_dump_now, FALSE);
+
+static MYSQL_SYSVAR_BOOL(buffer_pool_dump_at_shutdown, srv_buffer_pool_dump_at_shutdown,
+  PLUGIN_VAR_RQCMDARG,
+  "Dump the buffer pool into a file named @@innodb_buffer_pool_filename",
+  NULL, NULL, FALSE);
+
+static MYSQL_SYSVAR_BOOL(buffer_pool_load_now, innodb_buffer_pool_load_now,
+  PLUGIN_VAR_RQCMDARG,
+  "Trigger an immediate load of the buffer pool from a file named @@innodb_buffer_pool_filename",
+  NULL, buffer_pool_load_now, FALSE);
+
+static MYSQL_SYSVAR_BOOL(buffer_pool_load_abort, innodb_buffer_pool_load_abort,
+  PLUGIN_VAR_RQCMDARG,
+  "Abort a currently running load of the buffer pool",
+  NULL, buffer_pool_load_abort, FALSE);
+
+/* there is no point in changing this during runtime, thus readonly */
+static MYSQL_SYSVAR_BOOL(buffer_pool_load_at_startup, srv_buffer_pool_load_at_startup,
+  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
+  "Load the buffer pool from a file named @@innodb_buffer_pool_filename",
+  NULL, NULL, FALSE);
+
 static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
   PLUGIN_VAR_RQCMDARG,
   "Helps in performance tuning in heavily concurrent environments.",
@@ -12465,6 +12586,12 @@ static struct st_mysql_sys_var* innobase
   MYSQL_SYSVAR(autoextend_increment),
   MYSQL_SYSVAR(buffer_pool_size),
   MYSQL_SYSVAR(buffer_pool_instances),
+  MYSQL_SYSVAR(buffer_pool_filename),
+  MYSQL_SYSVAR(buffer_pool_dump_now),
+  MYSQL_SYSVAR(buffer_pool_dump_at_shutdown),
+  MYSQL_SYSVAR(buffer_pool_load_now),
+  MYSQL_SYSVAR(buffer_pool_load_abort),
+  MYSQL_SYSVAR(buffer_pool_load_at_startup),
   MYSQL_SYSVAR(checksums),
   MYSQL_SYSVAR(commit_concurrency),
   MYSQL_SYSVAR(concurrency_tickets),

=== modified file 'storage/innobase/include/buf0buddy.h'
--- a/storage/innobase/include/buf0buddy.h	2011-06-17 20:32:42 +0000
+++ b/storage/innobase/include/buf0buddy.h	2011-06-23 13:03:09 +0000
@@ -37,14 +37,14 @@ Created December 2006 by Marko Makela
 /**********************************************************************//**
 Allocate a block.  The thread calling this function must hold
 buf_pool->mutex and must not hold buf_pool->zip_mutex or any
-block->mutex.  The buf_pool_mutex may be released and reacquired.
+block->mutex.  The buf_pool->mutex may be released and reacquired.
 This function should only be used for allocating compressed page frames.
 @return	allocated block, never NULL */
 UNIV_INLINE
-void*
+byte*
 buf_buddy_alloc(
 /*============*/
-	buf_pool_t*	buf_pool,	/*!< in: buffer pool in which
+	buf_pool_t*	buf_pool,	/*!< in/out: buffer pool in which
 					the page resides */
 	ulint		size,		/*!< in: compressed page size
 					(between UNIV_ZIP_SIZE_MIN and
@@ -57,16 +57,17 @@ buf_buddy_alloc(
 	__attribute__((malloc, nonnull));
 
 /**********************************************************************//**
-Release a block. */
+Deallocate a block. */
 UNIV_INLINE
 void
 buf_buddy_free(
 /*===========*/
-	buf_pool_t*	buf_pool,
-			/*!< buffer pool in which the block resides */
-	void*	buf,	/*!< in: block to be freed, must not be
-			pointed to by the buffer pool */
-	ulint	size)	/*!< in: block size, up to UNIV_PAGE_SIZE */
+	buf_pool_t*	buf_pool,	/*!< in/out: buffer pool in which
+					the block resides */
+	void*		buf,		/*!< in: block to be freed, must not
+					be pointed to by the buffer pool */
+	ulint		size)		/*!< in: block size,
+					up to UNIV_PAGE_SIZE */
 	__attribute__((nonnull));
 
 #ifndef UNIV_NONINL

=== modified file 'storage/innobase/include/buf0buddy.ic'
--- a/storage/innobase/include/buf0buddy.ic	2011-06-17 20:32:42 +0000
+++ b/storage/innobase/include/buf0buddy.ic	2011-06-23 13:03:09 +0000
@@ -42,13 +42,14 @@ UNIV_INTERN
 void*
 buf_buddy_alloc_low(
 /*================*/
-	buf_pool_t*	buf_pool,
-			/*!< in: buffer pool in which the page resides */
-	ulint	i,	/*!< in: index of buf_pool->zip_free[],
-			or BUF_BUDDY_SIZES */
-	ibool*	lru)	/*!< in: pointer to a variable that will be assigned
-			TRUE if storage was allocated from the LRU list
-			and buf_pool_mutex was temporarily released */
+	buf_pool_t*	buf_pool,	/*!< in/out: buffer pool instance */
+	ulint		i,		/*!< in: index of buf_pool->zip_free[],
+					or BUF_BUDDY_SIZES */
+	ibool*		lru)		/*!< in: pointer to a variable that
+					will be assigned TRUE if storage was
+					allocated from the LRU list and
+					buf_pool->mutex was temporarily
+					released */
 	__attribute__((malloc, nonnull));
 
 /**********************************************************************//**
@@ -88,14 +89,14 @@ buf_buddy_get_slot(
 /**********************************************************************//**
 Allocate a block.  The thread calling this function must hold
 buf_pool->mutex and must not hold buf_pool->zip_mutex or any
-block->mutex.  The buf_pool_mutex may be released and reacquired.
+block->mutex.  The buf_pool->mutex may be released and reacquired.
 This function should only be used for allocating compressed page frames.
 @return	allocated block, never NULL */
 UNIV_INLINE
-void*
+byte*
 buf_buddy_alloc(
 /*============*/
-	buf_pool_t*	buf_pool,	/*!< in: buffer pool in which
+	buf_pool_t*	buf_pool,	/*!< in/out: buffer pool in which
 					the page resides */
 	ulint		size,		/*!< in: compressed page size
 					(between UNIV_ZIP_SIZE_MIN and
@@ -111,7 +112,8 @@ buf_buddy_alloc(
 	ut_ad(size >= UNIV_ZIP_SIZE_MIN);
 	ut_ad(size <= UNIV_PAGE_SIZE);
 
-	return(buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), lru));
+	return((byte*) buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size),
+					   lru));
 }
 
 /**********************************************************************//**
@@ -120,11 +122,12 @@ UNIV_INLINE
 void
 buf_buddy_free(
 /*===========*/
-	buf_pool_t*	buf_pool,	/*!< in: buffer pool instance */
-	void*		buf,		/*!< in: block to be freed, must not be
-					pointed to by the buffer pool */
-	ulint		size)		/*!< in: block size, up to
-					UNIV_PAGE_SIZE */
+	buf_pool_t*	buf_pool,	/*!< in/out: buffer pool in which
+					the block resides */
+	void*		buf,		/*!< in: block to be freed, must not
+					be pointed to by the buffer pool */
+	ulint		size)		/*!< in: block size,
+					up to UNIV_PAGE_SIZE */
 {
 	ut_ad(buf_pool_mutex_own(buf_pool));
 	ut_ad(ut_is_2pow(size));

=== modified file 'storage/innobase/include/buf0buf.h'
--- a/storage/innobase/include/buf0buf.h	2011-06-17 20:32:42 +0000
+++ b/storage/innobase/include/buf0buf.h	2011-06-23 13:03:09 +0000
@@ -290,6 +290,7 @@ buf_page_free_descriptor(
 /*=====================*/
 	buf_page_t*	bpage)	/*!< in: bpage descriptor to free. */
 	__attribute__((nonnull));
+
 /********************************************************************//**
 Allocates a buffer block.
 @return	own: the allocated block, in state BUF_BLOCK_MEMORY */

=== added file 'storage/innobase/include/buf0dump.h'
--- a/storage/innobase/include/buf0dump.h	1970-01-01 00:00:00 +0000
+++ b/storage/innobase/include/buf0dump.h	2011-06-23 06:48:48 +0000
@@ -0,0 +1,72 @@
+/*****************************************************************************
+
+Copyright (c) 2011, 2011, Oracle and/or its affiliates. All Rights Reserved.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+*****************************************************************************/
+
+/**************************************************//**
+@file buf/buf0dump.c
+Implements a buffer pool dump/load.
+
+Created April 08, 2011 Vasil Dimov
+*******************************************************/
+
+#ifndef buf0dump_h
+#define buf0dump_h
+
+#include "univ.i"
+
+/*****************************************************************//**
+Wakes up the buffer pool dump/load thread and instructs it to start
+a dump. This function is called by MySQL code via buffer_pool_dump_now()
+and it should return immediately because the whole MySQL is frozen during
+its execution. */
+UNIV_INTERN
+void
+buf_dump_start();
+/*============*/
+
+/*****************************************************************//**
+Wakes up the buffer pool dump/load thread and instructs it to start
+a load. This function is called by MySQL code via buffer_pool_load_now()
+and it should return immediately because the whole MySQL is frozen during
+its execution. */
+UNIV_INTERN
+void
+buf_load_start();
+/*============*/
+
+/*****************************************************************//**
+Aborts a currently running buffer pool load. This function is called by
+MySQL code via buffer_pool_load_abort() and it should return immediately
+because the whole MySQL is frozen during its execution. */
+UNIV_INTERN
+void
+buf_load_abort();
+/*============*/
+
+/*****************************************************************//**
+This is the main thread for buffer pool dump/load. It waits for an
+event and when waked up either performs a dump or load and sleeps
+again.
+@return this function does not return, it calls os_thread_exit() */
+UNIV_INTERN
+os_thread_ret_t
+buf_dump_thread(
+/*============*/
+	void*	arg __attribute__((unused)));	/*!< in: a dummy parameter
+						required by os_thread_create */
+
+#endif /* buf0dump_h */

=== modified file 'storage/innobase/include/buf0rea.h'
--- a/storage/innobase/include/buf0rea.h	2011-05-04 09:54:04 +0000
+++ b/storage/innobase/include/buf0rea.h	2011-06-23 06:48:48 +0000
@@ -43,6 +43,18 @@ buf_read_page(
 	ulint	zip_size,/*!< in: compressed page size in bytes, or 0 */
 	ulint	offset);/*!< in: page number */
 /********************************************************************//**
+High-level function which reads a page asynchronously from a file to the
+buffer buf_pool if it is not already there. Sets the io_fix flag and sets
+an exclusive lock on the buffer frame. The flag is cleared and the x-lock
+released by the i/o-handler thread.
+@return TRUE if page has been read in, FALSE in case of failure */
+UNIV_INTERN
+ibool
+buf_read_page_async(
+/*================*/
+	ulint	space,	/*!< in: space id */
+	ulint	offset);/*!< in: page number */
+/********************************************************************//**
 Applies linear read-ahead if in the buf_pool the page is a border page of
 a linear read-ahead area and all the pages in the area have been accessed.
 Does not read any page if the read-ahead mechanism is not activated. Note
@@ -132,6 +144,9 @@ invoked */
 #define BUF_READ_IBUF_PAGES_ONLY	131
 /** read any page */
 #define BUF_READ_ANY_PAGE		132
+/** read any page, but ignore (return an error) if a page does not exist
+instead of crashing like BUF_READ_ANY_PAGE does */
+#define BUF_READ_IGNORE_NONEXISTENT_PAGES 1024
 /* @} */
 
 #endif

=== modified file 'storage/innobase/include/srv0srv.h'
--- a/storage/innobase/include/srv0srv.h	2011-04-26 18:59:22 +0000
+++ b/storage/innobase/include/srv0srv.h	2011-06-23 06:48:48 +0000
@@ -68,6 +68,18 @@ extern os_event_t	srv_timeout_event;
 /* The error monitor thread waits on this event. */
 extern os_event_t	srv_error_event;
 
+/** The buffer pool dump/load thread waits on this event. */
+extern os_event_t	srv_buf_dump_event;
+
+/** The buffer pool dump/load file name */
+#define SRV_BUF_DUMP_FILENAME_DEFAULT	"ib_buffer_pool"
+extern char*		srv_buf_dump_filename;
+
+/** Boolean config knobs that tell InnoDB to dump the buffer pool at shutdown
+and/or load it during startup. */
+extern char		srv_buffer_pool_dump_at_shutdown;
+extern char		srv_buffer_pool_load_at_startup;
+
 /* If the last data file is auto-extended, we add this many pages to it
 at a time */
 #define SRV_AUTO_EXTEND_INCREMENT	\
@@ -230,6 +242,9 @@ extern ibool	srv_lock_timeout_active;
 extern ibool	srv_monitor_active;
 extern ibool	srv_error_monitor_active;
 
+/* TRUE during the lifetime of the buffer pool dump/load thread */
+extern ibool	srv_buf_dump_thread_active;
+
 extern ulong	srv_n_spin_wait_rounds;
 extern ulong	srv_n_free_tickets_to_enter;
 extern ulong	srv_thread_sleep_delay;
@@ -697,6 +712,8 @@ struct export_var_struct{
 	ulint innodb_data_writes;		/*!< I/O write requests */
 	ulint innodb_data_written;		/*!< Data bytes written */
 	ulint innodb_data_reads;		/*!< I/O read requests */
+	char  innodb_buffer_pool_dump_status[512];/*!< Buf pool dump status */
+	char  innodb_buffer_pool_load_status[512];/*!< Buf pool load status */
 	ulint innodb_buffer_pool_pages_total;	/*!< Buffer pool size */
 	ulint innodb_buffer_pool_pages_data;	/*!< Data pages */
 	ulint innodb_buffer_pool_pages_dirty;	/*!< Dirty data pages */

=== modified file 'storage/innobase/include/srv0start.h'
--- a/storage/innobase/include/srv0start.h	2011-03-09 07:32:36 +0000
+++ b/storage/innobase/include/srv0start.h	2011-06-23 06:48:48 +0000
@@ -30,6 +30,12 @@ Created 10/10/1995 Heikki Tuuri
 #include "log0log.h"
 #include "ut0byte.h"
 
+#ifdef __WIN__
+#define SRV_PATH_SEPARATOR	'\\'
+#else
+#define SRV_PATH_SEPARATOR	'/'
+#endif
+
 /*********************************************************************//**
 Normalizes a directory path for Windows: converts slashes to backslashes. */
 UNIV_INTERN

=== modified file 'storage/innobase/include/ut0ut.h'
--- a/storage/innobase/include/ut0ut.h	2011-05-17 11:42:10 +0000
+++ b/storage/innobase/include/ut0ut.h	2011-06-23 06:48:48 +0000
@@ -46,6 +46,8 @@ Created 1/20/1994 Heikki Tuuri
 #include <ctype.h>
 #endif
 
+#include <stdarg.h> /* for va_list */
+
 /** Index name prefix in fast index creation */
 #define	TEMP_INDEX_PREFIX	'\377'
 /** Index name prefix in fast index creation, as a string constant */
@@ -373,6 +375,22 @@ ut_copy_file(
 
 #ifdef __WIN__
 /**********************************************************************//**
+A substitute for vsnprintf(3), formatted output conversion into
+a limited buffer. Note: this function DOES NOT return the number of
+characters that would have been printed if the buffer was unlimited because
+VC's _vsnprintf() returns -1 in this case and we would need to call
+_vscprintf() in addition to estimate that but we would need another copy
+of "ap" for that and VC does not provide va_copy(). */
+UNIV_INTERN
+void
+ut_vsnprintf(
+/*=========*/
+	char*		str,	/*!< out: string */
+	size_t		size,	/*!< in: str size */
+	const char*	fmt,	/*!< in: format */
+	va_list		ap);	/*!< in: format values */
+
+/**********************************************************************//**
 A substitute for snprintf(3), formatted output conversion into
 a limited buffer.
 @return number of characters that would have been printed if the size
@@ -387,6 +405,15 @@ ut_snprintf(
 	...);			/*!< in: format values */
 #else
 /**********************************************************************//**
+A wrapper for vsnprintf(3), formatted output conversion into
+a limited buffer. Note: this function DOES NOT return the number of
+characters that would have been printed if the buffer was unlimited because
+VC's _vsnprintf() returns -1 in this case and we would need to call
+_vscprintf() in addition to estimate that but we would need another copy
+of "ap" for that and VC does not provide va_copy(). */
+# define ut_vsnprintf(buf, size, fmt, ap)	\
+	((void) vsnprintf(buf, size, fmt, ap))
+/**********************************************************************//**
 A wrapper for snprintf(3), formatted output conversion into
 a limited buffer. */
 # define ut_snprintf	snprintf

=== modified file 'storage/innobase/srv/srv0srv.c'
--- a/storage/innobase/srv/srv0srv.c	2011-06-02 07:11:45 +0000
+++ b/storage/innobase/srv/srv0srv.c	2011-06-23 06:48:48 +0000
@@ -82,6 +82,8 @@ UNIV_INTERN ulint	srv_dml_needed_delay =
 UNIV_INTERN ibool	srv_monitor_active = FALSE;
 UNIV_INTERN ibool	srv_error_monitor_active = FALSE;
 
+UNIV_INTERN ibool	srv_buf_dump_thread_active = FALSE;
+
 UNIV_INTERN const char*	srv_main_thread_op_info = "";
 
 /** Prefix used by MySQL to indicate pre-5.1 table name encoding */
@@ -584,6 +586,17 @@ UNIV_INTERN os_event_t	srv_monitor_event
 /** Event to signal the error thread */
 UNIV_INTERN os_event_t	srv_error_event;
 
+/** Event to signal the buffer pool dump/load thread */
+UNIV_INTERN os_event_t	srv_buf_dump_event;
+
+/** The buffer pool dump/load file name */
+UNIV_INTERN char*	srv_buf_dump_filename;
+
+/** Boolean config knobs that tell InnoDB to dump the buffer pool at shutdown
+and/or load it during startup. */
+UNIV_INTERN char	srv_buffer_pool_dump_at_shutdown = FALSE;
+UNIV_INTERN char	srv_buffer_pool_load_at_startup = FALSE;
+
 /***********************************************************************
 Prints counters for work done by srv_master_thread. */
 static
@@ -901,6 +914,8 @@ srv_init(void)
 
 	srv_monitor_event = os_event_create(NULL);
 
+	srv_buf_dump_event = os_event_create("buf_dump_event");
+
 	UT_LIST_INIT(srv_sys->tasks);
 
 	/* Create dummy indexes for infimum and supremum records */
@@ -928,6 +943,9 @@ srv_free(void)
 	srv_sys = NULL;
 
 	trx_i_s_cache_free(trx_i_s_cache);
+
+	os_event_free(srv_buf_dump_event);
+	srv_buf_dump_event = NULL;
 }
 
 /*********************************************************************//**
@@ -1666,11 +1684,14 @@ srv_any_background_threads_are_active(vo
 		thread_active = "srv_lock_timeout thread";
 	} else if (srv_monitor_active) {
 		thread_active = "srv_monitor_thread";
+	} else if (srv_buf_dump_thread_active) {
+		thread_active = "buf_dump_thread";
 	}
 
 	os_event_set(srv_error_event);
 	os_event_set(srv_monitor_event);
 	os_event_set(srv_timeout_event);
+	os_event_set(srv_buf_dump_event);
 
 	return(thread_active);
 }

=== modified file 'storage/innobase/srv/srv0start.c'
--- a/storage/innobase/srv/srv0start.c	2011-05-26 06:29:48 +0000
+++ b/storage/innobase/srv/srv0start.c	2011-06-23 06:48:48 +0000
@@ -44,6 +44,7 @@ Created 2/16/1996 Heikki Tuuri
 #include "data0type.h"
 #include "dict0dict.h"
 #include "buf0buf.h"
+#include "buf0dump.h"
 #include "os0file.h"
 #include "os0thread.h"
 #include "fil0fil.h"
@@ -493,12 +494,6 @@ io_handler_thread(
 }
 #endif /* !UNIV_HOTBACKUP */
 
-#ifdef __WIN__
-#define SRV_PATH_SEPARATOR	'\\'
-#else
-#define SRV_PATH_SEPARATOR	'/'
-#endif
-
 /*********************************************************************//**
 Normalizes a directory path for Windows: converts slashes to backslashes. */
 UNIV_INTERN
@@ -2078,6 +2073,9 @@ innobase_start_or_create_for_mysql(void)
 
 	srv_file_per_table = srv_file_per_table_original_value;
 
+	/* Create the buffer pool dump/load thread */
+	os_thread_create(buf_dump_thread, NULL, NULL);
+
 	srv_was_started = TRUE;
 
 	return((int) DB_SUCCESS);

=== modified file 'storage/innobase/trx/trx0sys.c'
--- a/storage/innobase/trx/trx0sys.c	2011-04-13 08:34:16 +0000
+++ b/storage/innobase/trx/trx0sys.c	2011-06-23 06:48:48 +0000
@@ -413,6 +413,9 @@ start_again:
 		/* Flush the modified pages to disk and make a checkpoint */
 		log_make_checkpoint_at(LSN_MAX, TRUE);
 
+		/* Remove doublewrite pages from LRU */
+		buf_pool_invalidate();
+
 		fprintf(stderr, "InnoDB: Doublewrite buffer created\n");
 
 		trx_sys_multiple_tablespace_format = TRUE;

=== modified file 'storage/innobase/ut/ut0ut.c'
--- a/storage/innobase/ut/ut0ut.c	2011-05-31 09:30:59 +0000
+++ b/storage/innobase/ut/ut0ut.c	2011-06-23 06:48:48 +0000
@@ -559,6 +559,26 @@ ut_copy_file(
 #ifdef __WIN__
 # include <stdarg.h>
 /**********************************************************************//**
+A substitute for vsnprintf(3), formatted output conversion into
+a limited buffer. Note: this function DOES NOT return the number of
+characters that would have been printed if the buffer was unlimited because
+VC's _vsnprintf() returns -1 in this case and we would need to call
+_vscprintf() in addition to estimate that but we would need another copy
+of "ap" for that and VC does not provide va_copy(). */
+UNIV_INTERN
+void
+ut_vsnprintf(
+/*=========*/
+	char*		str,	/*!< out: string */
+	size_t		size,	/*!< in: str size */
+	const char*	fmt,	/*!< in: format */
+	va_list		ap)	/*!< in: format values */
+{
+	_vsnprintf(str, size, fmt, ap);
+	str[size - 1] = '\0';
+}
+
+/**********************************************************************//**
 A substitute for snprintf(3), formatted output conversion into
 a limited buffer.
 @return number of characters that would have been printed if the size

=== modified file 'unittest/gunit/CMakeLists.txt'
--- a/unittest/gunit/CMakeLists.txt	2011-05-18 08:29:46 +0000
+++ b/unittest/gunit/CMakeLists.txt	2011-06-24 09:29:07 +0000
@@ -205,6 +205,7 @@ ENDIF()
 # Add tests (link them with gunit library) 
 SET(TESTS
   bounded_queue
+  bounds_checked_array
   dbug
   dynarray
   mdl

=== added file 'unittest/gunit/bounds_checked_array-t.cc'
--- a/unittest/gunit/bounds_checked_array-t.cc	1970-01-01 00:00:00 +0000
+++ b/unittest/gunit/bounds_checked_array-t.cc	2011-06-24 09:29:07 +0000
@@ -0,0 +1,117 @@
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+// First include (the generated) my_config.h, to get correct platform defines,
+// then gtest.h (before any other MySQL headers), to avoid min() macros etc ...
+#include "my_config.h"
+#include <gtest/gtest.h>
+
+#include "sql_array.h"
+
+namespace {
+
+typedef Bounds_checked_array<int> Int_array;
+
+class BoundsCheckedArray : public ::testing::Test
+{
+public:
+  BoundsCheckedArray() : some_integer(0) {}
+
+  virtual void SetUp()
+  {
+    for (int ix= 0; ix < c_array_size; ++ix)
+      c_array[ix]= ix;
+  }
+
+  static const int c_array_size= 5;
+  int c_array[c_array_size];
+
+  int some_integer;
+  Int_array int_array;
+};
+
+TEST_F(BoundsCheckedArray, Empty)
+{
+  EXPECT_EQ(sizeof(int), int_array.element_size());
+  EXPECT_EQ(0U, int_array.size());
+  EXPECT_TRUE(int_array.is_null());
+  int *pi= NULL;
+  EXPECT_EQ(pi, int_array.array());
+}
+
+#if !defined(DBUG_OFF)
+
+// Google Test recommends DeathTest suffix for classes used in death tests.
+typedef BoundsCheckedArray BoundsCheckedArrayDeathTest;
+
+TEST_F(BoundsCheckedArrayDeathTest, BoundsCheckRead)
+{
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  int_array= Int_array(c_array, 2);
+  EXPECT_DEATH_IF_SUPPORTED(some_integer= int_array[5],
+                            ".*Assertion .*n < m_size.*");
+}
+
+TEST_F(BoundsCheckedArrayDeathTest, BoundsCheckAssign)
+{
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  int_array= Int_array(c_array, 2);
+  EXPECT_DEATH_IF_SUPPORTED(int_array[5]= some_integer,
+                            ".*Assertion .*n < m_size.*");
+}
+
+TEST_F(BoundsCheckedArrayDeathTest, BoundsCheckPopFront)
+{
+  ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+  int_array= Int_array(c_array, 1);
+  int_array.pop_front();
+  EXPECT_DEATH_IF_SUPPORTED(int_array.pop_front(),
+                            ".*Assertion .*m_size > 0.*");
+}
+
+#endif  // !defined(DBUG_OFF)
+
+TEST_F(BoundsCheckedArray, Indexing)
+{
+  int_array= Int_array(c_array, c_array_size);
+  EXPECT_EQ(0, int_array[0]);
+  int_array[0]= 42;
+  EXPECT_EQ(42, int_array[0]);
+}
+
+
+TEST_F(BoundsCheckedArray, Reset)
+{
+  int_array= Int_array(c_array, c_array_size);
+  EXPECT_EQ(c_array, int_array.array());
+  EXPECT_FALSE(int_array.is_null());
+  int_array.reset();
+  int *pi= NULL;
+  EXPECT_EQ(pi, int_array.array());
+  EXPECT_TRUE(int_array.is_null());
+}
+
+
+TEST_F(BoundsCheckedArray, PopFront)
+{
+  int_array= Int_array(c_array, c_array_size);
+  for (int ix= 0; ix < c_array_size; ++ix)
+  {
+    EXPECT_EQ(ix, int_array[0]);
+    int_array.pop_front();
+  }
+}
+
+}  // namespace


Attachment: [text/bzr-bundle] bzr/chris.powers@oracle.com-20110624193001-eqn02w4a67tvorul.bundle
Thread
bzr commit into mysql-trunk branch (chris.powers:3309) Christopher Powers25 Jun