List:Commits« Previous MessageNext Message »
From:Horst.Hunger Date:July 4 2011 5:41pm
Subject:bzr commit into mysql-5.5 branch (horst.hunger:3421) WL#5710
View as plain text  
#At file:///home/horst/bzr/mysql-5.5-wl-5710/ based on revid:bjorn.munch@stripped

 3421 Horst.Hunger	2011-07-04 [merge]
      WL#5710 : mysql_plugin - enable or disable plugins
      
      This patch adds a new client utility that enables or disables plugin
      features. The utility disables or enables a plugin using values (name,
      soname, and symbols) provided via a configuration file by the same name.
      For example, to ENABLE the daemon_example plugin, the utility will read
      the daemon_example.ini configuration file and use the values contained to
      enable or disable the plugin.
      
      ******
      WL#5710 : Enable and disable plugins (mysql_plugin)
      
      Local merge with latest mysql-5.5 tree.
      
      ******
      WL#5710 : Enable and disable plugins (mysql_plugin)
      
      This patch changes the plugin configuration file format to make it
      easier to add new plugins and remove complexity. It also adds more
      information when plugin configuration file reads fail.
      
      ******
      Merge of BUG#12707948 and BUG#12664302 for testing.

    added:
      client/mysql_plugin.c
      mysql-test/include/daemon_example_bad_format.ini
      mysql-test/include/daemon_example_bad_soname.ini
      mysql-test/r/archive_debug.result
      mysql-test/r/mysql_embedded.result
      mysql-test/r/mysql_plugin.result
      mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result
      mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test
      mysql-test/t/archive_debug.test
      mysql-test/t/mysql_embedded.test
      mysql-test/t/mysql_plugin-master.opt
      mysql-test/t/mysql_plugin.test
      plugin/daemon_example/daemon_example.ini
    modified:
      .bzrignore
      VERSION
      client/CMakeLists.txt
      client/mysql.cc
      client/mysql_upgrade.c
      client/mysqladmin.cc
      client/mysqlbinlog.cc
      client/mysqlcheck.c
      client/mysqldump.c
      client/mysqlimport.c
      client/mysqlshow.c
      client/mysqlslap.c
      client/mysqltest.cc
      cmake/make_dist.cmake.in
      cmake/plugin.cmake
      configure.cmake
      extra/perror.c
      extra/yassl/src/yassl_error.cpp
      include/my_global.h
      include/mysql/plugin_audit.h
      include/mysql/plugin_audit.h.pp
      libmysql/authentication_win/plugin_client.cc
      libmysqld/lib_sql.cc
      mysql-test/collections/default.experimental
      mysql-test/include/plugin.defs
      mysql-test/mysql-test-run.pl
      mysql-test/r/alter_table.result
      mysql-test/r/events_bugs.result
      mysql-test/r/flush.result
      mysql-test/r/gis-rtree.result
      mysql-test/r/multi_update.result
      mysql-test/r/multi_update_innodb.result
      mysql-test/r/partition.result
      mysql-test/r/partition_datatype.result
      mysql-test/r/query_cache_28249.result
      mysql-test/r/sp_notembedded.result
      mysql-test/r/symlink.result
      mysql-test/r/trigger-compat.result
      mysql-test/r/trigger.result
      mysql-test/r/type_datetime.result
      mysql-test/suite/innodb/r/innodb-index.result
      mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result
      mysql-test/suite/innodb/t/innodb-index.test
      mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test
      mysql-test/suite/perfschema/include/cleanup_helper.inc
      mysql-test/suite/perfschema/include/upgrade_check.inc
      mysql-test/suite/perfschema/r/selects.result
      mysql-test/suite/perfschema/t/selects.test
      mysql-test/t/alter_table.test
      mysql-test/t/disabled.def
      mysql-test/t/events_bugs.test
      mysql-test/t/flush.test
      mysql-test/t/gis-rtree.test
      mysql-test/t/multi_update.test
      mysql-test/t/multi_update_innodb.test
      mysql-test/t/partition.test
      mysql-test/t/partition_datatype.test
      mysql-test/t/query_cache_28249.test
      mysql-test/t/sp_notembedded.test
      mysql-test/t/symlink.test
      mysql-test/t/trigger-compat.test
      mysql-test/t/type_datetime.test
      mysys/mf_pack.c
      plugin/audit_null/audit_null.c
      plugin/daemon_example/CMakeLists.txt
      sql/event_db_repository.cc
      sql/event_parse_data.cc
      sql/event_parse_data.h
      sql/ha_partition.cc
      sql/item.h
      sql/item_timefunc.cc
      sql/item_timefunc.h
      sql/mdl.h
      sql/mysqld.cc
      sql/share/errmsg-utf8.txt
      sql/sp_head.cc
      sql/sql_audit.cc
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_parse.cc
      sql/sql_select.cc
      sql/sql_table.cc
      sql/sql_trigger.cc
      sql/sql_trigger.h
      sql/sql_update.cc
      sql/sql_yacc.yy
      sql/table.h
      storage/archive/azio.c
      storage/archive/ha_archive.cc
      storage/innobase/btr/btr0btr.c
      storage/innobase/btr/btr0cur.c
      storage/innobase/buf/buf0buddy.c
      storage/innobase/buf/buf0buf.c
      storage/innobase/buf/buf0flu.c
      storage/innobase/buf/buf0lru.c
      storage/innobase/include/btr0btr.h
      storage/innobase/include/btr0cur.h
      storage/innobase/include/btr0cur.ic
      storage/innobase/include/buf0buddy.h
      storage/innobase/include/buf0buddy.ic
      storage/innobase/include/buf0buf.h
      storage/innobase/include/buf0buf.ic
      storage/innobase/include/buf0lru.h
      storage/innobase/include/buf0types.h
      storage/innobase/include/page0cur.ic
      storage/innobase/include/page0page.h
      storage/innobase/include/page0page.ic
      storage/innobase/include/rem0rec.h
      storage/innobase/include/rem0rec.ic
      storage/innobase/include/sync0rw.ic
      storage/innobase/include/sync0sync.h
      storage/innobase/include/univ.i
      storage/innobase/page/page0cur.c
      storage/innobase/page/page0page.c
      storage/innobase/page/page0zip.c
      storage/innobase/rem/rem0rec.c
      storage/innobase/row/row0ins.c
      storage/innobase/row/row0row.c
      storage/innobase/row/row0upd.c
      storage/innobase/row/row0vers.c
      storage/innobase/sync/sync0rw.c
      storage/innobase/sync/sync0sync.c
      storage/innobase/trx/trx0rec.c
      storage/myisam/mi_update.c
      storage/myisam/mi_write.c
      tests/mysql_client_test.c
=== modified file '.bzrignore'
--- a/.bzrignore	2011-05-16 08:51:14 +0000
+++ b/.bzrignore	2011-06-07 13:06:26 +0000
@@ -3133,3 +3133,4 @@ info_macros.cmake
 Docs/INFO_BIN
 Docs/INFO_SRC
 Testing
+source_downloads

=== modified file 'VERSION'
--- a/VERSION	2011-05-13 05:00:09 +0000
+++ b/VERSION	2011-06-10 08:38:27 +0000
@@ -1,4 +1,4 @@
 MYSQL_VERSION_MAJOR=5
 MYSQL_VERSION_MINOR=5
-MYSQL_VERSION_PATCH=14
+MYSQL_VERSION_PATCH=15
 MYSQL_VERSION_EXTRA=

=== modified file 'client/CMakeLists.txt'
--- a/client/CMakeLists.txt	2010-09-20 14:17:32 +0000
+++ b/client/CMakeLists.txt	2011-06-14 20:00:51 +0000
@@ -54,6 +54,9 @@ ADD_DEPENDENCIES(mysql_upgrade GenFixPri
 MYSQL_ADD_EXECUTABLE(mysqlshow mysqlshow.c)
 TARGET_LINK_LIBRARIES(mysqlshow mysqlclient)
 
+MYSQL_ADD_EXECUTABLE(mysql_plugin mysql_plugin.c)
+TARGET_LINK_LIBRARIES(mysql_plugin mysqlclient)
+
 MYSQL_ADD_EXECUTABLE(mysqlbinlog mysqlbinlog.cc)
 TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient)
 
@@ -69,7 +72,7 @@ IF(WIN32)
   MYSQL_ADD_EXECUTABLE(echo echo.c)
 ENDIF(WIN32)
 
-SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap 
+SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap mysql_plugin 
 PROPERTIES HAS_CXX TRUE)
 
 ADD_DEFINITIONS(-DHAVE_DLOPEN)

=== modified file 'client/mysql.cc'
--- a/client/mysql.cc	2011-02-09 06:50:11 +0000
+++ b/client/mysql.cc	2011-06-06 10:27:05 +0000
@@ -1564,11 +1564,11 @@ static struct my_option my_long_options[
     &show_warnings, &show_warnings, 0, GET_BOOL, NO_ARG,
     0, 0, 0, 0, 0, 0},
   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+    &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"default_auth", OPT_DEFAULT_AUTH,
     "Default authentication client-side plugin to use.",
-   (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+    &opt_default_auth, &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };

=== added file 'client/mysql_plugin.c'
--- a/client/mysql_plugin.c	1970-01-01 00:00:00 +0000
+++ b/client/mysql_plugin.c	2011-07-04 17:41:07 +0000
@@ -0,0 +1,1151 @@
+/* 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
+*/
+
+#include <m_string.h>
+#include <mysql.h>
+#include <my_getopt.h>
+#include <sys/stat.h>
+#include <my_global.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#define SHOW_VERSION "1.0.0"
+#define PRINT_VERSION do { printf("%s  Ver %s Distrib %s\n",    \
+                        my_progname, SHOW_VERSION, MYSQL_SERVER_VERSION);    \
+                      } while(0)
+
+/* Global variables. */
+static uint my_end_arg= 0;
+static uint opt_verbose=0;
+static uint opt_no_defaults= 0;
+static uint opt_print_defaults= 0;
+static char *opt_datadir=0, *opt_basedir=0,
+            *opt_plugin_dir=0, *opt_plugin_ini=0;
+static char bootstrap[FN_REFLEN];
+
+
+/* plugin struct */
+struct st_plugin
+{
+  const char *name;           /* plugin name */
+  const char *so_name;        /* plugin so (library) name */
+  const char *components[16]; /* components to load */
+} plugin_data;
+
+
+/* Options */
+static struct my_option my_long_options[] =
+{
+  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
+    0, 0, 0, 0, 0, 0},
+  {"basedir", 'b', "The basedir for the server.",
+    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"datadir", 'd', "The datadir for the server.",
+    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"plugin-dir", 'p', "The plugin dir for the server.",
+    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"plugin-ini", 'i', "Read plugin information from configuration file "
+   "specified instead of from <plugin-dir>/<plugin_name>.ini.",
+    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"no-defaults", 'n', "Do not read values from configuration file.",
+    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+  {"print-defaults", 'P', "Show default values from configuration file.",
+    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+  {"verbose", 'v',
+    "More verbose output; you can use this multiple times to get even more "
+    "verbose output.",
+    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
+    NO_ARG, 0, 0, 0, 0, 0, 0},
+  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+
+/* Methods */
+static int process_options(int argc, char *argv[], char *operation);
+static int check_access();
+static int find_tool(const char *tool_name, char *tool_path);
+static int find_plugin(char *tp_path);
+static int build_bootstrap_file(char *operation, char *bootstrap);
+static int dump_bootstrap_file(char *bootstrap_file);
+static int bootstrap_server(char *server_path, char *bootstrap_file);
+
+
+int main(int argc,char *argv[])
+{
+  int error= 0;
+  char tp_path[FN_REFLEN];
+  char server_path[FN_REFLEN];
+  char operation[16];
+
+  MY_INIT(argv[0]);
+  plugin_data.name= 0; // initialize name
+  
+  /*
+    The following operations comprise the method for enabling or disabling
+    a plugin. We begin by processing the command options then check the
+    directories specified for --datadir, --basedir, --plugin-dir, and
+    --plugin-ini (if specified). If the directories are Ok, we then look
+    for the mysqld executable and the plugin soname. Finally, we build a
+    bootstrap command file for use in bootstraping the server.
+    
+    If any step fails, the method issues an error message and the tool exits.
+    
+      1) Parse, execute, and verify command options.
+      2) Check access to directories.
+      3) Look for mysqld executable.
+      4) Look for the plugin.
+      5) Build a bootstrap file with commands to enable or disable plugin.
+      
+  */
+  if ((error= process_options(argc, argv, operation)) ||
+      (error= check_access()) ||
+      (error= find_tool("mysqld" FN_EXEEXT, server_path)) ||
+      (error= find_plugin(tp_path)) ||
+      (error= build_bootstrap_file(operation, bootstrap)))
+    goto exit;
+  
+  /* Dump the bootstrap file if --verbose specified. */
+  if (opt_verbose && ((error= dump_bootstrap_file(bootstrap))))
+    goto exit;
+  
+  /* Start the server in bootstrap mode and execute bootstrap commands */
+  error= bootstrap_server(server_path, bootstrap);
+
+exit:
+  /* Remove file */
+  my_delete(bootstrap, MYF(0));
+  if (opt_verbose && error == 0)
+  {
+    printf("# Operation succeeded.\n");
+  }
+
+  my_end(my_end_arg);
+  exit(error ? 1 : 0);
+  return 0;        /* No compiler warnings */
+}
+
+
+/**
+  Get a temporary file name.
+
+  @param[out]  filename   The file name of the temporary file
+  @param[in]   ext        An extension for the file (optional)
+
+  @retval int error = 1, success = 0
+*/
+
+static int make_tempfile(char *filename, const char *ext)
+{
+  int fd= 0;
+
+  if ((fd=create_temp_file(filename, NullS, ext, O_CREAT | O_WRONLY,
+         MYF(MY_WME))) < 0)
+  {
+    fprintf(stderr, "ERROR: Cannot generate temporary file. Error code: %d.\n",
+            fd);
+    return 1;
+  }
+  my_close(fd, MYF(0));
+  return 0;
+}
+
+
+/**
+  Get the value of an option from a string read from my_print_defaults output.
+
+  @param[in]  line   The line (string) read from the file
+  @param[in]  item   The option to search for (e.g. --datadir)
+
+  @returns NULL if not found, string containing value if found
+*/
+
+static char *get_value(char *line, const char *item)
+{
+  char *destination= 0;
+  int item_len= (int)strlen(item);
+  int line_len = (int)strlen(line);
+
+  if ((strncasecmp(line, item, item_len) == 0))
+  {
+    int start= 0;
+    char *s= 0;
+
+    s = line + item_len + 1;
+    destination= my_strndup(s, line_len - start, MYF(MY_FAE));
+    destination[line_len - item_len - 2]= 0;
+  }
+  return destination;
+}
+
+
+/**
+  Run a command in a shell.
+
+  This function will attempt to execute the command specified by using the
+  popen() method to open a shell and execute the command passed and store the
+  output in a result file. If the --verbose option was specified, it will open
+  the result file and print the contents to stdout.
+
+  @param[in]  cmd   The command to execute.
+  @param[in]  mode  The mode for popen() (e.g. "r", "w", "rw")
+
+  @return int error code or 0 for success.
+*/
+
+static int run_command(char* cmd, const char *mode)
+{
+  char buf[512]= {0};
+  FILE *res_file;
+  int error;
+
+  if (!(res_file= popen(cmd, mode)))
+    return -1;
+
+  if (opt_verbose)
+  {
+    while (fgets(buf, sizeof(buf), res_file))
+    {
+      fprintf(stdout, "%s", buf);
+    }
+  }
+  error= pclose(res_file);
+  return error;
+}
+
+
+#ifdef __WIN__
+/**
+  Check to see if there are spaces in a path.
+  
+  @param[in]  path  The Windows path to examine.
+
+  @retval int spaces found = 1, no spaces = 0
+*/
+static int has_spaces(const char *path)
+{
+  if (strchr(path, ' ') != NULL)
+    return 1;
+  return 0;
+}
+
+
+/**
+  Convert a Unix path to a Windows path.
+ 
+  @param[in]  path  The Windows path to examine.
+
+  @returns string containing path with / changed to \\
+*/
+static char *convert_path(const char *argument)
+{
+  /* Convert / to \\ to make Windows paths */
+  char *winfilename= my_strdup(argument, MYF(MY_FAE));
+  char *pos, *end;
+  int length= strlen(argument);
+
+  for (pos= winfilename, end= pos+length ; pos < end ; pos++)
+  {
+    if (*pos == '/')
+    {
+      *pos= '\\';
+    }
+  }
+  return winfilename;
+}
+
+
+/**
+  Add quotes if the path has spaces in it.
+
+  @param[in]  path  The Windows path to examine.
+
+  @returns string containing excaped quotes if spaces found in path
+*/
+static char *add_quotes(const char *path)
+{
+  char windows_cmd_friendly[FN_REFLEN];
+
+  if (has_spaces(path))
+    snprintf(windows_cmd_friendly, sizeof(windows_cmd_friendly),
+             "\"%s\"", path);
+  else
+    snprintf(windows_cmd_friendly, sizeof(windows_cmd_friendly),
+             "%s", path);
+  return my_strdup(windows_cmd_friendly, MYF(MY_FAE));
+}
+#endif
+
+
+/**
+  Get the default values from the my.cnf file.
+
+  This method gets the default values for the following parameters:
+
+  --datadir
+  --basedir
+  --plugin-dir
+  --plugin-ini
+
+  These values are used if the user has not specified a value.
+
+  @retval int error = 1, success = 0
+*/
+
+static int get_default_values()
+{
+  char tool_path[FN_REFLEN];
+  char defaults_cmd[FN_REFLEN];
+  char defaults_file[FN_REFLEN];
+  char line[FN_REFLEN];
+  int error= 0;
+  int ret= 0;
+  FILE *file= 0;
+
+  if ((error= find_tool("my_print_defaults" FN_EXEEXT, tool_path)))
+    goto exit;
+  else
+  {
+    if ((error= make_tempfile(defaults_file, "txt")))
+      goto exit;
+
+#ifdef __WIN__
+    {
+      char *format_str= 0;
+  
+      if (has_spaces(tool_path) || has_spaces(defaults_file))
+        format_str = "\"%s mysqld > %s\"";
+      else
+        format_str = "%s mysqld > %s";
+  
+      snprintf(defaults_cmd, sizeof(defaults_cmd), format_str,
+               add_quotes(tool_path), add_quotes(defaults_file));
+    }
+#else
+    snprintf(defaults_cmd, sizeof(defaults_cmd),
+             "%s mysqld > %s", tool_path, defaults_file);
+#endif
+
+    /* Execute the command */
+    if (opt_verbose)
+    {
+      printf("# Command: %s\n", defaults_cmd);
+    }
+    error= run_command(defaults_cmd, "r");
+    if (error)
+    {
+      fprintf(stderr, "ERROR: my_print_defaults failed. Error code: %d.\n",
+              ret);
+      goto exit;
+    }
+    /* Now open the file and read the defaults we want. */
+    file= fopen(defaults_file, "r");
+    while (fgets(line, FN_REFLEN, file) != NULL)
+    {
+      char *value= 0;
+
+      if ((opt_datadir == 0) && ((value= get_value(line, "--datadir"))))
+      {
+        opt_datadir= my_strdup(value, MYF(MY_FAE));
+      }
+      if ((opt_basedir == 0) && ((value= get_value(line, "--basedir"))))
+      {
+        opt_basedir= my_strdup(value, MYF(MY_FAE));
+      }
+      if ((opt_plugin_dir == 0) && ((value= get_value(line, "--plugin_dir"))))
+      {
+        opt_plugin_dir= my_strdup(value, MYF(MY_FAE));
+      }
+      if ((opt_plugin_ini == 0) && ((value= get_value(line, "--plugin_ini"))))
+      {
+        opt_plugin_ini= my_strdup(value, MYF(MY_FAE));
+      }
+    }
+  }
+exit:
+  if (file)
+  {
+    fclose(file);
+    /* Remove file */
+    my_delete(defaults_file, MYF(0));
+  }
+  return error;
+}
+
+
+/**
+  Print usage.
+*/
+
+static void usage(void)
+{
+  PRINT_VERSION;
+  puts("Copyright (c) 2011, Oracle and/or its affiliates. "
+       "All rights reserved.\n");
+  puts("Enable or disable plugins.");
+  printf("\nUsage: %s [options] <plugin> ENABLE|DISABLE\n\nOptions:\n",
+     my_progname);
+  my_print_help(my_long_options);
+  puts("\n");
+}
+
+
+/**
+  Print the default values as read from the my.cnf file.
+
+  This method displays the default values for the following parameters:
+
+  --datadir
+  --basedir
+  --plugin-dir
+  --plugin-ini
+
+*/
+
+static void print_default_values(void)
+{
+  printf("%s would have been started with the following arguments:\n",
+         my_progname);
+  get_default_values();
+  if (opt_datadir)
+  {
+    printf("--datadir=%s ", opt_datadir);
+  }
+  if (opt_basedir)
+  {
+    printf("--basedir=%s ", opt_basedir);
+  }
+  if (opt_plugin_dir)
+  {
+    printf("--plugin_dir=%s ", opt_plugin_dir);
+  }
+  if (opt_plugin_ini)
+  {
+    printf("--plugin_ini=%s ", opt_plugin_ini);
+  }
+  printf("\n");
+}
+
+
+/**
+  Process the arguments and identify an option and store its value.
+
+  @param[in]  optid      The single character shortcut for the argument.
+  @param[in]  my_option  Structure of legal options.
+  @param[in]  argument   The argument value to process.
+*/
+
+static my_bool
+get_one_option(int optid,
+               const struct my_option *opt __attribute__((unused)),
+               char *argument)
+{
+  switch(optid) {
+  case 'n':
+    opt_no_defaults++;
+    break;
+  case 'P':
+    opt_print_defaults++;
+    print_default_values();
+    break;
+  case 'v':
+    opt_verbose++;
+    break;
+  case 'V':
+    PRINT_VERSION;
+    exit(0);
+    break;
+  case '?':
+  case 'I':          /* Info */
+    usage();
+    exit(0);
+  case 'd':
+    opt_datadir= my_strdup(argument, MYF(MY_FAE));
+    break;
+  case 'b':
+    opt_basedir= my_strdup(argument, MYF(MY_FAE));
+    break;
+  case 'p':
+    opt_plugin_dir= my_strdup(argument, MYF(MY_FAE));
+    break;
+  case 'i':
+    opt_plugin_ini= my_strdup(argument, MYF(MY_FAE));
+    break;
+  }
+  return 0;
+}
+
+
+/**
+  Check to see if a file exists.
+
+  @param[in]  filename  File to locate.
+
+  @retval int file not found = 1, file found = 0
+*/
+
+static int file_exists(char * filename)
+{
+  struct stat buf;
+  int i = stat (filename, &buf);
+  /* File found */
+  if (i == 0)
+  {
+    return 1;
+  }
+  return 0;
+}
+
+
+/**
+  Search a specific path and sub directory for a file name.
+
+  @param[in]  base_path  Original path to use.
+  @param[in]  tool_name  Name of the tool to locate.
+  @param[in]  subdir     The sub directory to search.
+  @param[out] tool_path  If tool found, return complete path.
+
+  @retval int error = 1, success = 0
+*/
+
+static int search_dir(const char * base_path, const char *tool_name,
+                      const char *subdir, char *tool_path)
+{
+  char new_path[FN_REFLEN];
+
+  strcpy(new_path, base_path);
+  strcat(new_path, subdir);
+  fn_format(new_path, new_path, "", tool_name, MY_UNPACK_FILENAME);
+  if (file_exists(new_path))
+  {
+    strcpy(tool_path, new_path);
+    return 1;
+  }
+  return 0;
+}
+
+
+/**
+  Search known common paths and sub directories for a file name.
+
+  @param[in]  base_path  Original path to use.
+  @param[in]  tool_name  Name of the tool to locate.
+  @param[out] tool_path  If tool found, return complete path.
+
+  @retval int error = 1, success = 0
+*/
+
+static int search_paths(const char *base_path, const char *tool_name,
+                        char *tool_path)
+{
+  int i= 0;
+
+  static const char *paths[]= {
+    "", "/share/",  "/scripts/", "/bin/", "/sbin/", "/libexec/",
+    "/mysql/", "/sql/",
+  };
+  for (i = 0 ; i < (int)array_elements(paths); i++)
+  {
+    if (search_dir(base_path, tool_name, paths[i], tool_path))
+    {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+
+/**
+  Read the plugin ini file.
+
+  This function attempts to read the plugin config file from the plugin_dir
+  path saving the data in the the st_plugin structure. If the file is not
+  found or the file cannot be read, an error is generated.
+
+  @retval int error = 1, success = 0
+*/
+
+static int load_plugin_data(char *plugin_name, char *config_file)
+{
+  FILE *file_ptr;
+  char path[FN_REFLEN];
+  char line[1024];
+  char *reason= 0;
+  char *res;
+  int i= -1;
+
+  if (opt_plugin_ini == 0)
+  {
+    fn_format(path, config_file, opt_plugin_dir, "", MYF(0));
+    opt_plugin_ini= my_strdup(path, MYF(MY_FAE));
+  }
+  if (!file_exists(opt_plugin_ini))
+  {
+    reason= (char *)"File does not exist.";
+    goto error;
+  }
+
+  file_ptr= fopen(opt_plugin_ini, "r");
+  if (file_ptr == NULL)
+  {
+    reason= (char *)"Cannot open file.";
+    goto error;
+  }
+
+  /* save name */
+  plugin_data.name= my_strdup(plugin_name, MYF(MY_WME));
+
+  /* Read plugin components */
+  while (i < 16)
+  {
+    res= fgets(line, sizeof(line), file_ptr);
+    /* strip /n */
+    if (line[strlen(line)-1] == '\n')
+    {
+      line[strlen(line)-1]= '\0';
+    }
+    if (res == NULL)
+    {
+      if (i < 1)
+      {
+        reason= (char *)"Bad format in plugin configuration file.";
+        fclose(file_ptr);
+        goto error;        
+      }
+      break;
+    }
+    if ((line[0] == '#') || (line[0] == '\n')) // skip comment and blank lines
+    {
+      continue;
+    }
+    if (i == -1) // if first pass, read this line as so_name
+    {
+      /* save so_name */
+      plugin_data.so_name= my_strdup(line, MYF(MY_WME));
+      /* Add proper file extension for soname */
+      strcat((char *)plugin_data.so_name, FN_SOEXT);
+      i++;
+    }
+    else
+    {
+      if (strlen(line) > 0)
+      {
+        plugin_data.components[i]= my_strdup(line, MYF(MY_WME));
+        i++;
+      }
+      else
+      {
+        plugin_data.components[i]= NULL;
+      }
+    }
+  }
+  
+  fclose(file_ptr);
+  return 0;
+
+error:
+  fprintf(stderr, "ERROR: Cannot read plugin config file %s. %s\n",
+          plugin_name, reason);
+  return 1;
+}
+
+
+/**
+  Check the options for validity.
+
+  This function checks the arguments for validity issuing the appropriate
+  error message if arguments are missing or invalid. On success, @operation
+  is set to either "ENABLE" or "DISABLE".
+
+  @param[in]  argc       The number of arguments.
+  @param[in]  argv       The arguments.
+  @param[out] operation  The operation chosen (enable|disable)
+
+  @retval int error = 1, success = 0
+*/
+
+static int check_options(int argc, char **argv, char *operation)
+{
+  int i= 0;                    // loop counter
+  int num_found= 0;            // number of options found (shortcut loop)
+  char config_file[FN_REFLEN]; // configuration file name
+  char plugin_name[FN_REFLEN]; // plugin name
+  
+  /* Form prefix strings for the options. */
+  const char *basedir_prefix = "--basedir=";
+  int basedir_len= strlen(basedir_prefix);
+  const char *datadir_prefix = "--datadir=";
+  int datadir_len= strlen(datadir_prefix);
+  const char *plugin_dir_prefix = "--plugin_dir=";
+  int plugin_dir_len= strlen(plugin_dir_prefix);
+
+  strcpy(plugin_name, "");
+  for (i = 0; i < argc && num_found < 5; i++)
+  {
+
+    if (!argv[i])
+    {
+      continue;
+    }
+    if ((strcasecmp(argv[i], "ENABLE") == 0) ||
+        (strcasecmp(argv[i], "DISABLE") == 0))
+    {
+      strcpy(operation, argv[i]);
+      num_found++;
+    }
+    else if ((strncasecmp(argv[i], basedir_prefix, basedir_len) == 0) &&
+             !opt_basedir)
+    {
+      opt_basedir= my_strndup(argv[i]+basedir_len,
+                              strlen(argv[i])-basedir_len, MYF(MY_FAE));
+      num_found++;
+    }
+    else if ((strncasecmp(argv[i], datadir_prefix, datadir_len) == 0) &&
+             !opt_datadir)
+    {
+      opt_datadir= my_strndup(argv[i]+datadir_len,
+                              strlen(argv[i])-datadir_len, MYF(MY_FAE));
+      num_found++;
+    }
+    else if ((strncasecmp(argv[i], plugin_dir_prefix, plugin_dir_len) == 0) &&
+             !opt_plugin_dir)
+    {
+      opt_plugin_dir= my_strndup(argv[i]+plugin_dir_len,
+                                 strlen(argv[i])-plugin_dir_len, MYF(MY_FAE));
+      num_found++;
+    }
+    /* read the plugin config file and check for match against argument */
+    else
+    {
+      strcpy(plugin_name, argv[i]);
+      strcpy(config_file, argv[i]);
+      strcat(config_file, ".ini");
+    }
+  }
+
+  if (!opt_basedir)
+  {
+    fprintf(stderr, "ERROR: Missing --basedir option.\n");
+    return 1;
+  }
+
+  if (!opt_datadir)
+  {
+    fprintf(stderr, "ERROR: Missing --datadir option.\n");
+    return 1;
+  }
+
+  if (!opt_plugin_dir)
+  {
+    fprintf(stderr, "ERROR: Missing --plugin_dir option.\n");
+    return 1;
+  }
+  /* If a plugin was specified, read the config file. */
+  else if (strlen(plugin_name) > 0) 
+  {
+    if (load_plugin_data(plugin_name, config_file))
+    {
+      return 1;
+    }
+    if (strcasecmp(plugin_data.name, plugin_name) != 0)
+    {
+      fprintf(stderr, "ERROR: plugin name requested does not match config "
+              "file data.\n");
+      return 1;
+    }
+  }
+  else
+  {
+    fprintf(stderr, "ERROR: No plugin specified.\n");
+    return 1;
+  }
+
+  if ((strlen(operation) == 0))
+  {
+    fprintf(stderr, "ERROR: missing operation. Please specify either "
+            "'<plugin> ENABLE' or '<plugin> DISABLE'.\n");
+    return 1;
+  }
+
+  return 0;
+}
+
+
+/**
+  Parse, execute, and verify command options.
+  
+  This method handles all of the option processing including the optional
+  features for displaying data (--print-defaults, --help ,etc.) that do not
+  result in an attempt to ENABLE or DISABLE of a plugin.
+  
+  @param[in]   arc        Count of arguments
+  @param[in]   argv       Array of arguments
+  @param[out]  operation  Operation (ENABLE or DISABLE)
+  
+  @retval int error = 1, success = 0, exit program = -1
+*/
+
+static int process_options(int argc, char *argv[], char *operation)
+{
+  int error= 0;
+  int i= 0;
+  
+  /* Parse and execute command-line options */
+  if ((error= handle_options(&argc, &argv, my_long_options, get_one_option)))
+    goto exit;
+
+  /* If the print defaults option used, exit. */
+  if (opt_print_defaults)
+  {
+    error= -1;
+    goto exit;
+  }
+
+  /* Add a trailing directory separator if not present */
+  if (opt_basedir)
+  {
+    i= (int)strlength(opt_basedir);
+    if (opt_basedir[i-1] != FN_LIBCHAR || opt_basedir[i-1] != FN_LIBCHAR2)
+#ifdef __WIN__
+      strcat(opt_basedir, "//");
+#else
+      strcat(opt_basedir, FN_DIRSEP);
+#endif
+  }
+  
+  /*
+    If the user did not specify the option to skip loading defaults from a
+    config file and the required options are not present or there was an error
+    generated when the defaults were read from the file, exit.
+  */
+  if (!opt_no_defaults && ((error= get_default_values())))
+  {
+    error= -1;
+    goto exit;
+  }
+
+  /*
+   Check to ensure required options are present and validate the operation.
+   Note: this method also validates the plugin specified by attempting to
+   read a configuration file named <plugin_name>.ini from the --plugin-dir
+   or --plugin-ini location if the --plugin-ini option presented.
+  */
+  strcpy(operation, "");
+  if ((error = check_options(argc, argv, operation)))
+  {
+    goto exit;
+  }
+
+  if (opt_verbose)
+  {
+    printf("#    basedir = %s\n", opt_basedir);
+    printf("# plugin_dir = %s\n", opt_plugin_dir);
+    printf("#    datadir = %s\n", opt_datadir);
+    printf("# plugin_ini = %s\n", opt_plugin_ini);
+  }
+
+exit:
+  return error;
+}
+
+
+/**
+  Check access
+  
+  This method checks to ensure all of the directories (opt_basedir,
+  opt_plugin_dir, opt_datadir, and opt_plugin_ini) are accessible by
+  the user.
+  
+  @retval int error = 1, success = 0
+*/
+
+static int check_access()
+{
+  int error= 0;
+  
+  if ((error= my_access(opt_basedir, F_OK)))
+  {
+    fprintf(stderr, "ERROR: Cannot access basedir at '%s'.\n",
+            opt_basedir);
+    goto exit;
+  }
+  if ((error= my_access(opt_plugin_dir, F_OK)))
+  {
+    fprintf(stderr, "ERROR: Cannot access plugin_dir at '%s'.\n",
+            opt_plugin_dir);
+    goto exit;
+  }
+  if ((error= my_access(opt_datadir, F_OK)))
+  {
+    fprintf(stderr, "ERROR: Cannot access datadir at '%s'.\n",
+            opt_datadir);
+    goto exit;
+  }
+  if ((error= my_access(opt_plugin_ini, F_OK)))
+  {
+    fprintf(stderr, "ERROR: Cannot access plugin config file at '%s'.\n",
+            opt_plugin_ini);
+    goto exit;
+  }
+
+exit:
+  return error;
+}
+
+
+/**
+  Locate the tool and form tool path.
+
+  @param[in]  tool_name  Name of the tool to locate.
+  @param[out] tool_path  If tool found, return complete path.
+
+  @retval int error = 1, success = 0
+*/
+
+static int find_tool(const char *tool_name, char *tool_path)
+{
+  int i= 0;
+
+  const char *paths[]= {
+    opt_basedir, "/usr", "/usr/local/mysql", "/usr/sbin", "/usr/share",
+  };
+  for (i= 0; i < (int)array_elements(paths); i++)
+  {
+    if (paths[i] && (search_paths(paths[i], tool_name, tool_path)))
+      goto found;
+  }
+  fprintf(stderr, "WARNING: Cannot find %s.\n", tool_name);
+  return 1;
+found:
+  if (opt_verbose)
+    printf("# Found tool '%s' as '%s'.\n", tool_name, tool_path);
+  return 0;
+}
+
+
+/**
+  Find the plugin library.
+
+  This function attempts to use the @c plugin_dir option passed on the
+  command line to locate the plugin.
+
+  @param[out] tp_path   The actual path to plugin with FN_SOEXT applied.
+
+  @retval int error = 1, success = 0
+*/
+
+static int find_plugin(char *tp_path)
+{
+  /* Check for existance of plugin */
+  fn_format(tp_path, plugin_data.so_name, opt_plugin_dir, "", MYF(0));
+  if (!file_exists(tp_path))
+  {
+    fprintf(stderr, "ERROR: The plugin library is missing or in a different"
+            " location.\n");
+    return 1;
+  }
+  else if (opt_verbose)
+  {
+    printf("# Found plugin '%s' as '%s'\n", plugin_data.name, tp_path);
+  }
+  return 0;
+}
+
+
+/**
+  Build the boostrap file.
+  
+  Create a new file and populate it with SQL commands to ENABLE or DISABLE
+  the plugin via INSERT and DELETE operations on the mysql.plugin table.
+
+  param[in]  operation  The type of operation (ENABLE or DISABLE)
+  param[out] bootstrap  A FILE* pointer
+  
+  @retval int error = 1, success = 0
+*/
+
+static int build_bootstrap_file(char *operation, char *bootstrap)
+{
+  int error= 0;
+  FILE *file= 0;
+  
+  /*
+    Perform plugin operation : ENABLE or DISABLE
+
+    The following creates a temporary bootstrap file and populates it with
+    the appropriate SQL commands for the operation. For ENABLE, INSERT
+    statements are created. For DISABLE, DELETE statements are created. The
+    values for these statements are derived from the plugin_data read from the
+    <plugin_name>.ini configuration file. Once the file is built, a call to
+    mysqld is made in read only, bootstrap modes to read the SQL statements
+    and execute them.
+  */
+  if ((error= make_tempfile(bootstrap, "sql")))
+  {
+    /* Fail if we cannot create a temporary file for the bootstrap commands. */
+    fprintf(stderr, "ERROR: Cannot create bootstrap file.\n");
+    goto exit;
+  }
+  if ((file= fopen(bootstrap, "w+")) == NULL)
+  {
+    fprintf(stderr, "ERROR: Cannot open bootstrap file for writing.\n");
+    error= 1;
+    goto exit;
+  }
+  if (strcasecmp(operation, "enable") == 0)
+  {
+    int i= 0;
+    fprintf(file, "INSERT IGNORE INTO mysql.plugin VALUES ");
+    for (i= 0; i < (int)array_elements(plugin_data.components); i++)
+    {
+      /* stop when we read the end of the symbol list - marked with NULL */
+      if (plugin_data.components[i] == NULL)
+      {
+        break;
+      }
+      if (i > 0)
+      {
+        fprintf(file, ", ");
+      }
+      fprintf(file, "('%s','%s')",
+              plugin_data.components[i], plugin_data.so_name);
+    }
+    fprintf(file, ";\n");
+    if (opt_verbose)
+    {
+      printf("# Enabling %s...\n", plugin_data.name);
+    }
+  }
+  else
+  {
+    fprintf(file,
+            "DELETE FROM mysql.plugin WHERE name = '%s';", plugin_data.name);
+    if (opt_verbose)
+    {
+      printf("# Disabling %s...\n", plugin_data.name);
+    }
+  }
+  
+exit:
+  fclose(file);
+  return error;
+}
+
+
+/**
+  Dump bootstrap file.
+  
+  Read the contents of the bootstrap file and print it out.
+  
+  @param[in]  bootstrap_file  Name of bootstrap file to read
+  
+  @retval int error = 1, success = 0
+*/
+
+static int dump_bootstrap_file(char *bootstrap_file)
+{
+  char *ret= 0;
+  int error= 0;
+  char query_str[512];
+  FILE *file= 0;
+
+  if ((file= fopen(bootstrap_file, "r")) == NULL)
+  {
+    fprintf(stderr, "ERROR: Cannot open bootstrap file for reading.\n");
+    error= 1;
+    goto exit;
+  }
+  ret= fgets(query_str, 512, file);
+  if (ret == 0)
+  {
+    fprintf(stderr, "ERROR: Cannot read bootstrap file.\n");
+    error= 1;
+    goto exit;
+  }
+  printf("# Query: %s", query_str);
+
+exit:
+  if (file)
+  {
+    fclose(file);
+  }
+  return error;
+}
+
+
+/**
+  Bootstrap the server
+  
+  Create a command line sequence to launch mysqld in bootstrap mode. This
+  will allow mysqld to launch a minimal server instance to read and
+  execute SQL commands from a file piped in (the boostrap file). We use
+  the --no-defaults option to skip reading values from the config file.
+
+  The bootstrap mode skips loading of plugins and many other subsystems.
+  This allows the mysql_plugin tool to insert the correct rows into the
+  mysql.plugin table (for ENABLE) or delete the rows (for DISABLE). Once
+  the server is launched in normal mode, the plugin will be loaded
+  (for ENABLE) or not loaded (for DISABLE). In this way, we avoid the
+  (sometimes) complicated LOAD PLUGIN commands.
+
+  @param[in]  server_path     Path to server executable
+  @param[in]  bootstrap_file  Name of bootstrap file to read
+
+  @retval int error = 1, success = 0
+*/
+
+static int bootstrap_server(char *server_path, char *bootstrap_file)
+{
+  char bootstrap_cmd[FN_REFLEN];
+  int error= 0;
+  int ret= 0;
+
+#ifdef __WIN__
+  char *format_str= 0;
+  char *verbose_str= "";
+  
+  if (opt_verbose)
+    strcat(verbose_str, "--console");
+  if (has_spaces(opt_datadir) || has_spaces(opt_basedir) ||
+      has_spaces(bootstrap_file))
+    format_str= "\"%s %s --bootstrap --datadir=%s --basedir=%s < %s\"";
+  else 
+    format_str= "%s %s --bootstrap --datadir=%s --basedir=%s < %s";
+
+  snprintf(bootstrap_cmd, sizeof(bootstrap_cmd), format_str,
+           add_quotes(convert_path(server_path)), verbose_str,
+           add_quotes(opt_datadir), add_quotes(opt_basedir),
+           add_quotes(bootstrap_file));
+#else
+  snprintf(bootstrap_cmd, sizeof(bootstrap_cmd),
+           "%s --no-defaults --bootstrap --datadir=%s --basedir=%s"
+           " < %s", server_path, opt_datadir, opt_basedir, bootstrap_file);
+#endif
+
+  /* Execute the command */
+  if (opt_verbose)
+  {
+    printf("# Command: %s\n", bootstrap_cmd);
+  }
+  error= run_command(bootstrap_cmd, "r");
+  if (error)
+    fprintf(stderr,
+            "ERROR: Unexpected result from bootstrap. Error code: %d.\n",
+            ret);
+  
+  return error;
+}

=== modified file 'client/mysql_upgrade.c'
--- a/client/mysql_upgrade.c	2011-01-16 03:59:05 +0000
+++ b/client/mysql_upgrade.c	2011-06-06 10:27:05 +0000
@@ -92,7 +92,7 @@ static struct my_option my_long_options[
    0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"default_auth", OPT_DEFAULT_AUTH,
    "Default authentication client-side plugin to use.",
-   (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+   &opt_default_auth, &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade "
    "has already been executed for the current version of MySQL.",
@@ -109,7 +109,7 @@ static struct my_option my_long_options[
    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 #endif
   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+   &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"port", 'P', "Port number to use for connection or 0 for default to, in "
    "order of preference, my.cnf, $MYSQL_TCP_PORT, "

=== modified file 'client/mysqladmin.cc'
--- a/client/mysqladmin.cc	2011-02-11 14:00:09 +0000
+++ b/client/mysqladmin.cc	2011-06-06 10:27:05 +0000
@@ -206,11 +206,11 @@ static struct my_option my_long_options[
    &opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG,
    SHUTDOWN_DEF_TIMEOUT, 0, 3600*12, 0, 1, 0},
   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+    &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"default_auth", OPT_DEFAULT_AUTH,
    "Default authentication client-side plugin to use.",
-   (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+   &opt_default_auth, &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };

=== modified file 'client/mysqlbinlog.cc'
--- a/client/mysqlbinlog.cc	2011-05-05 23:55:44 +0000
+++ b/client/mysqlbinlog.cc	2011-06-06 10:27:05 +0000
@@ -1052,7 +1052,7 @@ static struct my_option my_long_options[
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"default_auth", OPT_DEFAULT_AUTH,
    "Default authentication client-side plugin to use.",
-   (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+   &opt_default_auth, &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"disable-log-bin", 'D', "Disable binary log. This is useful, if you "
     "enabled --to-last-log and are sending the output to the same MySQL server. "
@@ -1080,7 +1080,7 @@ static struct my_option my_long_options[
   {"password", 'p', "Password to connect to remote server.",
    0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+    &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"port", 'P', "Port number to use for connection or 0 for default to, in "
    "order of preference, my.cnf, $MYSQL_TCP_PORT, "

=== modified file 'client/mysqlcheck.c'
--- a/client/mysqlcheck.c	2011-03-08 08:41:57 +0000
+++ b/client/mysqlcheck.c	2011-06-06 10:27:05 +0000
@@ -102,7 +102,7 @@ static struct my_option my_long_options[
    &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"default_auth", OPT_DEFAULT_AUTH,
    "Default authentication client-side plugin to use.",
-   (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+   &opt_default_auth, &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"fast",'F', "Check only tables that haven't been closed properly.",
    &opt_fast, &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
@@ -142,7 +142,7 @@ static struct my_option my_long_options[
    NO_ARG, 0, 0, 0, 0, 0, 0},
 #endif
   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+   &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"port", 'P', "Port number to use for connection or 0 for default to, in "
    "order of preference, my.cnf, $MYSQL_TCP_PORT, "

=== modified file 'client/mysqldump.c'
--- a/client/mysqldump.c	2011-03-16 14:11:20 +0000
+++ b/client/mysqldump.c	2011-06-06 10:27:05 +0000
@@ -501,11 +501,11 @@ static struct my_option my_long_options[
   {"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
    NO_ARG, 0, 0, 0, 0, 0, 0},
   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+   &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"default_auth", OPT_DEFAULT_AUTH,
    "Default authentication client-side plugin to use.",
-   (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+   &opt_default_auth, &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };

=== modified file 'client/mysqlimport.c'
--- a/client/mysqlimport.c	2011-01-16 03:59:05 +0000
+++ b/client/mysqlimport.c	2011-06-06 10:27:05 +0000
@@ -93,7 +93,7 @@ static struct my_option my_long_options[
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"default_auth", OPT_DEFAULT_AUTH,
    "Default authentication client-side plugin to use.",
-   (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+   &opt_default_auth, &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"delete", 'd', "First delete all rows from table.", &opt_delete,
    &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -145,7 +145,7 @@ static struct my_option my_long_options[
    NO_ARG, 0, 0, 0, 0, 0, 0},
 #endif
   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+   &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"port", 'P', "Port number to use for connection or 0 for default to, in "
    "order of preference, my.cnf, $MYSQL_TCP_PORT, "

=== modified file 'client/mysqlshow.c'
--- a/client/mysqlshow.c	2011-01-16 03:59:05 +0000
+++ b/client/mysqlshow.c	2011-06-06 10:27:05 +0000
@@ -191,7 +191,7 @@ static struct my_option my_long_options[
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"default_auth", OPT_DEFAULT_AUTH,
    "Default authentication client-side plugin to use.",
-   (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+   &opt_default_auth, &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
    0, 0, 0, 0, 0, 0},
@@ -207,7 +207,7 @@ static struct my_option my_long_options[
    "solicited on the tty.",
    0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+   &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"port", 'P', "Port number to use for connection or 0 for default to, in "
    "order of preference, my.cnf, $MYSQL_TCP_PORT, "

=== modified file 'client/mysqlslap.c'
--- a/client/mysqlslap.c	2011-04-08 06:55:59 +0000
+++ b/client/mysqlslap.c	2011-06-06 10:27:05 +0000
@@ -590,7 +590,7 @@ static struct my_option my_long_options[
    &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"default_auth", OPT_DEFAULT_AUTH,
    "Default authentication client-side plugin to use.",
-   (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+   &opt_default_auth, &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"delimiter", 'F',
     "Delimiter to use in SQL statements supplied in file or command line.",
@@ -634,7 +634,7 @@ static struct my_option my_long_options[
     NO_ARG, 0, 0, 0, 0, 0, 0},
 #endif
   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+   &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"port", 'P', "Port number to use for connection.", &opt_mysql_port,
     &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,

=== modified file 'client/mysqltest.cc'
--- a/client/mysqltest.cc	2011-05-05 23:50:31 +0000
+++ b/client/mysqltest.cc	2011-06-06 10:27:05 +0000
@@ -6423,7 +6423,7 @@ static struct my_option my_long_options[
    &opt_connect_timeout, &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG,
    120, 0, 3600 * 12, 0, 0, 0},
   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+    &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };

=== modified file 'cmake/make_dist.cmake.in'
--- a/cmake/make_dist.cmake.in	2011-03-03 21:46:12 +0000
+++ b/cmake/make_dist.cmake.in	2011-06-10 07:12:10 +0000
@@ -28,6 +28,7 @@ SET(TAR_EXECUTABLE "@TAR_EXECUTABLE@")
 SET(CMAKE_GENERATOR "@CMAKE_GENERATOR@")
 SET(CMAKE_MAKE_PROGRAM "@CMAKE_MAKE_PROGRAM@")
 SET(CMAKE_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@")
+SET(PLUGIN_REPOS "@PLUGIN_REPOS@")
 
 SET(VERSION "@VERSION@")
 
@@ -53,6 +54,22 @@ IF(BZR_EXECUTABLE)
   ENDIF()
 ENDIF()
 
+IF(BZR_EXECUTABLE)
+  FOREACH(REPO ${PLUGIN_REPOS})
+    GET_FILENAME_COMPONENT(PLUGIN_NAME ${REPO} NAME)
+    SET(DEST ${PACKAGE_DIR}/plugin/${PLUGIN_NAME})
+    MESSAGE(STATUS "Running bzr export for plugin/${PLUGIN_NAME}")
+    EXECUTE_PROCESS(
+      COMMAND "${BZR_EXECUTABLE}" export ${DEST}
+      WORKING_DIRECTORY ${REPO}
+      RESULT_VARIABLE RESULT
+    )
+    IF(NOT RESULT EQUAL 0)
+      MESSAGE(STATUS "bzr export failed")
+    ENDIF()
+  ENDFOREACH()
+ENDIF()
+
 IF(NOT BZR_EXECUTABLE)
   MESSAGE(STATUS "bzr not found or source dir is not a repo, use CPack")
   

=== modified file 'cmake/plugin.cmake'
--- a/cmake/plugin.cmake	2011-05-27 12:43:15 +0000
+++ b/cmake/plugin.cmake	2011-06-10 12:57:42 +0000
@@ -32,16 +32,15 @@ INCLUDE(${MYSQL_CMAKE_SCRIPT_DIR}/cmake_
 
 MACRO(PLUGIN_APPEND_COLLECTIONS plugin)
   SET(fcopied "${CMAKE_CURRENT_SOURCE_DIR}/tests/collections/FilesCopied")
-  IF(EXISTS ${fcopied})
-    RETURN()
+  IF(NOT EXISTS ${fcopied})
+    FILE(GLOB collections ${CMAKE_CURRENT_SOURCE_DIR}/tests/collections/*)
+    FOREACH(cfile ${collections})
+      FILE(READ ${cfile} contents)
+      GET_FILENAME_COMPONENT(fname ${cfile} NAME)
+      FILE(APPEND ${CMAKE_SOURCE_DIR}/mysql-test/collections/${fname} "${contents}")
+      FILE(APPEND ${fcopied} "${fname}\n")
+    ENDFOREACH()
   ENDIF()
-  FILE(GLOB collections ${CMAKE_CURRENT_SOURCE_DIR}/tests/collections/*)
-  FOREACH(cfile ${collections})
-    FILE(READ ${cfile} contents)
-    GET_FILENAME_COMPONENT(fname ${cfile} NAME)
-    FILE(APPEND ${CMAKE_SOURCE_DIR}/mysql-test/collections/${fname} "${contents}")
-    FILE(APPEND ${fcopied} "${fname}\n")
-  ENDFOREACH()
 ENDMACRO()
 
 MACRO(MYSQL_ADD_PLUGIN)
@@ -228,4 +227,11 @@ MACRO(CONFIGURE_PLUGINS)
       ADD_SUBDIRECTORY(${dir})
     ENDIF()
   ENDFOREACH()
+  FOREACH(dir ${dirs_plugin})
+    IF (EXISTS ${dir}/.bzr)
+      MESSAGE(STATUS "Found repo ${dir}/.bzr")
+      LIST(APPEND PLUGIN_BZR_REPOS "${dir}")
+    ENDIF()
+  ENDFOREACH()
+  SET(PLUGIN_REPOS "${PLUGIN_BZR_REPOS}" CACHE INTERNAL "")
 ENDMACRO()

=== modified file 'configure.cmake'
--- a/configure.cmake	2011-04-30 05:24:38 +0000
+++ b/configure.cmake	2011-06-06 10:24:28 +0000
@@ -345,6 +345,7 @@ CHECK_FUNCTION_EXISTS (fconvert HAVE_FCO
 CHECK_FUNCTION_EXISTS (fdatasync HAVE_FDATASYNC)
 CHECK_SYMBOL_EXISTS(fdatasync "unistd.h" HAVE_DECL_FDATASYNC)
 CHECK_FUNCTION_EXISTS (fesetround HAVE_FESETROUND)
+CHECK_FUNCTION_EXISTS (fedisableexcept HAVE_FEDISABLEEXCEPT)
 CHECK_FUNCTION_EXISTS (fpsetmask HAVE_FPSETMASK)
 CHECK_FUNCTION_EXISTS (fseeko HAVE_FSEEKO)
 CHECK_FUNCTION_EXISTS (fsync HAVE_FSYNC)

=== modified file 'extra/perror.c'
--- a/extra/perror.c	2011-03-29 12:43:49 +0000
+++ b/extra/perror.c	2011-06-07 07:53:37 +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 */
 
@@ -64,7 +64,8 @@ static struct my_option my_long_options[
    &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.",
+  {"all", 'a', "Print all the error messages and the number. Deprecated,"
+   " will be removed in a future release.",
    &print_all_codes, &print_all_codes, 0, GET_BOOL, NO_ARG,
    0, 0, 0, 0, 0, 0},
 #endif
@@ -295,6 +296,8 @@ int main(int argc,char *argv[])
   if (print_all_codes)
   {
     HA_ERRORS *ha_err_ptr;
+    printf("WARNING: option '-a/--all' is deprecated and will be removed in a"
+           " future release.\n");
     for (code=1 ; code < sys_nerr ; code++)
     {
       if (sys_errlist[code] && sys_errlist[code][0])

=== modified file 'extra/yassl/src/yassl_error.cpp'
--- a/extra/yassl/src/yassl_error.cpp	2010-02-22 13:23:47 +0000
+++ b/extra/yassl/src/yassl_error.cpp	2011-06-17 07:51:34 +0000
@@ -128,7 +128,7 @@ void SetErrorString(unsigned long error,
         break;
 
     case badVersion_error :
-        strncpy(buffer, "protocl version mismatch", max);
+        strncpy(buffer, "protocol version mismatch", max);
         break;
         
     case compress_error :

=== modified file 'include/my_global.h'
--- a/include/my_global.h	2011-04-13 19:05:26 +0000
+++ b/include/my_global.h	2011-06-14 20:00:51 +0000
@@ -602,6 +602,8 @@ typedef SOCKET_SIZE_TYPE size_socket;
 #define FN_LIBCHAR	'\\'
 #define FN_LIBCHAR2	'/'
 #define FN_DIRSEP       "/\\"               /* Valid directory separators */
+#define FN_EXEEXT   ".exe"
+#define FN_SOEXT    ".dll"
 #define FN_ROOTDIR	"\\"
 #define FN_DEVCHAR	':'
 #define FN_NETWORK_DRIVES	/* Uses \\ to indicate network drives */
@@ -610,6 +612,8 @@ typedef SOCKET_SIZE_TYPE size_socket;
 #define FN_LIBCHAR	'/'
 #define FN_LIBCHAR2	'/'
 #define FN_DIRSEP       "/"     /* Valid directory separators */
+#define FN_EXEEXT   ""
+#define FN_SOEXT    ".so"
 #define FN_ROOTDIR	"/"
 #endif
 

=== modified file 'include/mysql/plugin_audit.h'
--- a/include/mysql/plugin_audit.h	2010-12-14 14:34:23 +0000
+++ b/include/mysql/plugin_audit.h	2011-06-03 07:27:11 +0000
@@ -24,16 +24,7 @@
 
 #define MYSQL_AUDIT_CLASS_MASK_SIZE 1
 
-#define MYSQL_AUDIT_INTERFACE_VERSION 0x0200
-
-/*
-  The first word in every event class struct indicates the specific
-  class of the event.
-*/
-struct mysql_event
-{
-  unsigned int event_class;
-};
+#define MYSQL_AUDIT_INTERFACE_VERSION 0x0300
 
 
 /*************************************************************************
@@ -55,7 +46,6 @@ struct mysql_event
 
 struct mysql_event_general
 {
-  unsigned int event_class;
   unsigned int event_subclass;
   int general_error_code;
   unsigned long general_thread_id;
@@ -87,7 +77,6 @@ struct mysql_event_general
 
 struct mysql_event_connection
 {
-  unsigned int event_class;
   unsigned int event_subclass;
   int status;
   unsigned long thread_id;
@@ -118,9 +107,9 @@ struct mysql_event_connection
   waiting for the next query from the client.
   
   event_notify() is invoked whenever an event occurs which is of any
-  class for which the plugin has interest. The first word of the
-  mysql_event argument indicates the specific event class and the
-  remainder of the structure is as required for that class.
+  class for which the plugin has interest. The second argument
+  indicates the specific event class and the third argument is data
+  as required for that class.
   
   class_mask is an array of bits used to indicate what event classes
   that this plugin wants to receive.
@@ -130,7 +119,7 @@ struct st_mysql_audit
 {
   int interface_version;
   void (*release_thd)(MYSQL_THD);
-  void (*event_notify)(MYSQL_THD, const struct mysql_event *);
+  void (*event_notify)(MYSQL_THD, unsigned int, const void *);
   unsigned long class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
 };
 

=== modified file 'include/mysql/plugin_audit.h.pp'
--- a/include/mysql/plugin_audit.h.pp	2011-03-04 12:12:31 +0000
+++ b/include/mysql/plugin_audit.h.pp	2011-06-03 07:27:11 +0000
@@ -43,7 +43,7 @@ typedef enum _thd_wait_type_e {
   THD_WAIT_BINLOG= 8,
   THD_WAIT_GROUP_COMMIT= 9,
   THD_WAIT_SYNC= 10,
-  THD_WAIT_LAST= 11 
+  THD_WAIT_LAST= 11
 } thd_wait_type;
 extern struct thd_wait_service_st {
   void (*thd_wait_begin_func)(void*, int);
@@ -195,13 +195,8 @@ void mysql_query_cache_invalidate4(void*
 void *thd_get_ha_data(const void* thd, const struct handlerton *hton);
 void thd_set_ha_data(void* thd, const struct handlerton *hton,
                      const void *ha_data);
-struct mysql_event
-{
-  unsigned int event_class;
-};
 struct mysql_event_general
 {
-  unsigned int event_class;
   unsigned int event_subclass;
   int general_error_code;
   unsigned long general_thread_id;
@@ -217,7 +212,6 @@ struct mysql_event_general
 };
 struct mysql_event_connection
 {
-  unsigned int event_class;
   unsigned int event_subclass;
   int status;
   unsigned long thread_id;
@@ -240,6 +234,6 @@ struct st_mysql_audit
 {
   int interface_version;
   void (*release_thd)(void*);
-  void (*event_notify)(void*, const struct mysql_event *);
+  void (*event_notify)(void*, unsigned int, const void *);
   unsigned long class_mask[1];
 };

=== modified file 'libmysql/authentication_win/plugin_client.cc'
--- a/libmysql/authentication_win/plugin_client.cc	2011-04-28 19:17:29 +0000
+++ b/libmysql/authentication_win/plugin_client.cc	2011-06-03 11:44:33 +0000
@@ -20,6 +20,16 @@
 
 #include "common.h"
 
+/*
+  The following MS C++ specific pragma embeds a comment in the resulting
+  object file. A "lib" comment tells the linker to use the specified 
+  library, thus the dependency is handled automagically.
+*/
+
+#ifdef _MSC_VER
+#pragma comment(lib, "Secur32")
+#endif
+
 static int win_auth_client_plugin_init(char*, size_t, int, va_list)
 {
   return 0;

=== modified file 'libmysqld/lib_sql.cc'
--- a/libmysqld/lib_sql.cc	2011-05-20 09:18:36 +0000
+++ b/libmysqld/lib_sql.cc	2011-06-13 18:41:24 +0000
@@ -531,8 +531,8 @@ int init_embedded_server(int argc, char
     return 1;
   defaults_argc= *argcp;
   defaults_argv= *argvp;
-  remaining_argc= argc;
-  remaining_argv= argv;
+  remaining_argc= *argcp;
+  remaining_argv= *argvp;
 
   /* Must be initialized early for comparison of options name */
   system_charset_info= &my_charset_utf8_general_ci;

=== modified file 'mysql-test/collections/default.experimental'
--- a/mysql-test/collections/default.experimental	2011-05-26 07:05:46 +0000
+++ b/mysql-test/collections/default.experimental	2011-06-06 10:24:28 +0000
@@ -6,13 +6,10 @@ binlog.binlog_multi_engine
 funcs_1.charset_collation_1              # depends on compile-time decisions
 
 main.func_math @freebsd                  # Bug#11751977 2010-05-04 alik main.func_math fails on FreeBSD in PB2
-main.gis-rtree @freebsd                  # Bug#11749418 2010-05-04 alik test cases gis-rtree, type_float, type_newdecimal fail in embedded server
 main.lock_multi_bug38499                 # Bug#11755645 2009-09-19 alik main.lock_multi_bug38499 times out sporadically
 main.outfile_loaddata @solaris           # Bug#11755168 2010-01-20 alik Test "outfile_loaddata" fails (reproducible)
 main.signal_demo3 @solaris               # Bug#11755949 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun
 main.sp @solaris                         # Bug#11755949 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun
-main.log_tables-big                      # Bug#11756699 2010-11-15 mattiasj report already exists
-main.type_float @freebsd                 # Bug#11749418 2010-05-04 alik test cases gis-rtree, type_float, type_newdecimal fail in embedded server
 main.wait_timeout @solaris               # Bug#11758972 2010-04-26 alik wait_timeout fails on OpenSolaris
 
 rpl.rpl_innodb_bug28430                  # Bug#11754425
@@ -29,7 +26,3 @@ sys_vars.ndb_log_update_as_write_basic
 sys_vars.have_ndbcluster_basic
 sys_vars.ndb_log_updated_only_basic
 sys_vars.rpl_init_slave_func		 # Bug#12535301 2011-05-09 andrei sys_vars.rpl_init_slave_func mismatches in daily-5.5
-
-main.gis-rtree                           # svoj: due to BUG#11749418
-main.type_float                          # svoj: due to BUG#11749418
-main.type_newdecimal                     # svoj: due to BUG#11749418

=== added file 'mysql-test/include/daemon_example_bad_format.ini'
--- a/mysql-test/include/daemon_example_bad_format.ini	1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/daemon_example_bad_format.ini	2011-06-30 12:12:58 +0000
@@ -0,0 +1,8 @@
+#
+# Plugin configuration file. Place the following on a separate line:
+#
+# library binary file name (without .so or .dll)
+# component_name
+# [component_name] - additional components in plugin
+#
+libdaemon_example   

=== added file 'mysql-test/include/daemon_example_bad_soname.ini'
--- a/mysql-test/include/daemon_example_bad_soname.ini	1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/daemon_example_bad_soname.ini	2011-06-30 12:12:58 +0000
@@ -0,0 +1,9 @@
+#
+# Plugin configuration file. Place the following on a separate line:
+#
+# library binary file name (without .so or .dll)
+# component_name
+# [component_name] - additional components in plugin
+#
+libdaemon_BADNAME
+daemon_BADNAME

=== modified file 'mysql-test/include/plugin.defs'
--- a/mysql-test/include/plugin.defs	2011-05-30 13:55:44 +0000
+++ b/mysql-test/include/plugin.defs	2011-06-14 20:00:51 +0000
@@ -39,3 +39,4 @@ ha_archive         storage/archive    AR
 ha_blackhole       storage/blackhole  BLACKHOLE_PLUGIN
 ha_federated       storage/federated  FEDERATED_PLUGIN
 mypluglib          plugin/fulltext    SIMPLE_PARSER
+libdaemon_example  plugin/daemon_example DAEMONEXAMPLE

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2011-05-30 13:55:44 +0000
+++ b/mysql-test/mysql-test-run.pl	2011-06-23 12:03:03 +0000
@@ -168,9 +168,11 @@ my $opt_suites;
 
 our $opt_verbose= 0;  # Verbose output, enable with --verbose
 our $exe_mysql;
+our $exe_mysql_plugin;
 our $exe_mysqladmin;
 our $exe_mysqltest;
 our $exe_libtool;
+our $exe_mysql_embedded;
 
 our $opt_big_test= 0;
 
@@ -1949,6 +1951,9 @@ sub executable_setup () {
   # Look for the client binaries
   $exe_mysqladmin=     mtr_exe_exists("$path_client_bindir/mysqladmin");
   $exe_mysql=          mtr_exe_exists("$path_client_bindir/mysql");
+  $exe_mysql_plugin=   mtr_exe_exists("$path_client_bindir/mysql_plugin");
+
+  $exe_mysql_embedded= mtr_exe_maybe_exists("$basedir/libmysqld/examples/mysql_embedded");
 
   if ( ! $opt_skip_ndbcluster )
   {
@@ -2354,6 +2359,8 @@ sub environment_setup {
   $ENV{'MYSQLADMIN'}=               native_path($exe_mysqladmin);
   $ENV{'MYSQL_CLIENT_TEST'}=        mysql_client_test_arguments();
   $ENV{'EXE_MYSQL'}=                $exe_mysql;
+  $ENV{'MYSQL_PLUGIN'}=             $exe_mysql_plugin;
+  $ENV{'MYSQL_EMBEDDED'}=           $exe_mysql_embedded;
 
   # ----------------------------------------------------
   # bug25714 executable may _not_ exist in

=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result	2011-04-13 06:16:40 +0000
+++ b/mysql-test/r/alter_table.result	2011-06-16 22:50:07 +0000
@@ -1345,6 +1345,35 @@ DROP TABLE t1;
 CREATE TABLE t1 (a TEXT, id INT, b INT);
 ALTER TABLE t1 DROP COLUMN a, ADD COLUMN c TEXT FIRST;
 DROP TABLE t1;
+#
+# Test for bug #12652385 - "61493: REORDERING COLUMNS TO POSITION
+#                           FIRST CAN CAUSE DATA TO BE CORRUPTED".
+#
+drop table if exists t1;
+# Use MyISAM engine as the fact that InnoDB doesn't support
+# in-place ALTER TABLE in cases when columns are being renamed
+# hides some bugs.
+create table t1 (i int, j int) engine=myisam;
+insert into t1 value (1, 2);
+# First, test for original problem described in the bug report.
+select * from t1;
+i	j
+1	2
+# Change of column order by the below ALTER TABLE statement should
+# affect both column names and column contents.
+alter table t1 modify column j int first;
+select * from t1;
+j	i
+2	1
+# Now test for similar problem with the same root.
+# The below ALTER TABLE should change not only the name but
+# also the value for the last column of the table.
+alter table t1 drop column i, add column k int default 0;
+select * from t1;
+j	k
+2	0
+# Clean-up.
+drop table t1;
 End of 5.1 tests
 CREATE TABLE t1(c CHAR(10), 
 i INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY);

=== added file 'mysql-test/r/archive_debug.result'
--- a/mysql-test/r/archive_debug.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/archive_debug.result	2011-05-18 10:01:43 +0000
@@ -0,0 +1,12 @@
+#
+# BUG#12402794 - 60976: CRASH, VALGRIND WARNING AND MEMORY LEAK
+#                       WITH PARTITIONED ARCHIVE TABLES
+#
+CREATE TABLE t1(a INT) ENGINE=ARCHIVE;
+INSERT INTO t1 VALUES(1);
+SET SESSION debug='d,simulate_archive_open_failure';
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	error	Corrupt
+SET SESSION debug=DEFAULT;
+DROP TABLE t1;

=== modified file 'mysql-test/r/events_bugs.result'
--- a/mysql-test/r/events_bugs.result	2011-05-27 11:42:28 +0000
+++ b/mysql-test/r/events_bugs.result	2011-06-09 18:08:38 +0000
@@ -419,7 +419,7 @@ SET TIME_ZONE= '+04:00';
 ALTER EVENT e1 DO SELECT 2;
 SHOW EVENTS;
 Db	Name	Definer	Time zone	Type	Execute at	Interval value	Interval field	Starts	Ends	Status	Originator	character_set_client	collation_connection	Database Collation
-events_test	e1	root@localhost	-03:00	RECURRING	NULL	1	DAY	2005-12-31 20:58:59	2030-01-03 00:00:00	ENABLED	1	latin1	latin1_swedish_ci	latin1_swedish_ci
+events_test	e1	root@localhost	-03:00	RECURRING	NULL	1	DAY	2005-12-31 20:58:59	2030-01-03 00:00:00	DISABLED	1	latin1	latin1_swedish_ci	latin1_swedish_ci
 DROP EVENT e1;
 SET TIME_ZONE='+05:00';
 CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY STARTS '2006-01-01 00:00:00' DO
@@ -796,6 +796,20 @@ COUNT(*)
 DROP EVENT IF EXISTS event_Bug12546938;
 DROP TABLE table_bug12546938;
 SET GLOBAL EVENT_SCHEDULER = OFF;
+DROP DATABASE IF EXISTS event_test11764334;
+CREATE DATABASE event_test11764334;
+USE event_test11764334;
+CREATE EVENT ev1 ON SCHEDULE EVERY 3 SECOND DISABLE DO SELECT 1;
+SHOW EVENTS IN event_test11764334 WHERE NAME='ev1';
+Db	Name	Definer	Time zone	Type	Execute at	Interval value	Interval field	Starts	Ends	Status	Originator	character_set_client	collation_connection	Database Collation
+event_test11764334	ev1	root@localhost	SYSTEM	RECURRING	NULL	3	SECOND	#	#	DISABLED	1	latin1	latin1_swedish_ci	latin1_swedish_ci
+ALTER EVENT ev1 ON SCHEDULE EVERY 4 SECOND;
+SHOW EVENTS IN event_test11764334 WHERE NAME='ev1';
+Db	Name	Definer	Time zone	Type	Execute at	Interval value	Interval field	Starts	Ends	Status	Originator	character_set_client	collation_connection	Database Collation
+event_test11764334	ev1	root@localhost	SYSTEM	RECURRING	NULL	4	SECOND	#	#	DISABLED	1	latin1	latin1_swedish_ci	latin1_swedish_ci
+DROP EVENT ev1;
+DROP DATABASE event_test11764334;
+USE test;
 DROP DATABASE events_test;
 SET GLOBAL event_scheduler= 'ON';
 SET @@global.concurrent_insert= @concurrent_insert;

=== modified file 'mysql-test/r/flush.result'
--- a/mysql-test/r/flush.result	2011-03-07 09:08:10 +0000
+++ b/mysql-test/r/flush.result	2011-06-16 15:18:16 +0000
@@ -466,3 +466,26 @@ ALTER TABLE t1 COMMENT 'test';
 ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
 UNLOCK TABLES;
 DROP TABLE t1;
+#
+# Test for bug #12641342 - "61401: UPDATE PERFORMANCE DEGRADES
+#                           GRADUALLY IF A TRIGGER EXISTS".
+#
+# One of side-effects of this bug was that a transaction which
+# involved DML statements requiring prelocking blocked concurrent
+# FLUSH TABLES WITH READ LOCK for the whole its duration, while
+# correct behavior in this case is to block FTWRL only for duration
+# of individual DML statements.
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (id INT PRIMARY KEY, value INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW SET @var = "a";
+BEGIN;
+UPDATE t1 SET value= value + 1 WHERE id = 1;
+# Switching to connection 'con1'.
+# The below FLUSH TABLES WITH READ LOCK should succeed and
+# should not be blocked by the transaction in default connection.
+FLUSH TABLES WITH READ LOCK;
+UNLOCK TABLES;
+# Switching to connection 'default'.
+COMMIT;
+DROP TABLE t1;

=== modified file 'mysql-test/r/gis-rtree.result'
--- a/mysql-test/r/gis-rtree.result	2010-03-25 11:49:01 +0000
+++ b/mysql-test/r/gis-rtree.result	2011-06-07 15:30:43 +0000
@@ -1549,3 +1549,30 @@ HANDLER t1 READ a NEXT;
 HANDLER t1 CLOSE;
 DROP TABLE t1;
 End of 5.0 tests.
+#
+# Bug #57323/11764487: myisam corruption with insert ignore 
+# and invalid spatial data
+#
+CREATE TABLE t1(a LINESTRING NOT NULL, b GEOMETRY NOT NULL,
+SPATIAL KEY(a), SPATIAL KEY(b)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(GEOMFROMTEXT("point (0 0)"), GEOMFROMTEXT("point (1 1)"));
+INSERT IGNORE INTO t1 SET a=GEOMFROMTEXT("point (-6 0)"), b=GEOMFROMTEXT("error");
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+INSERT IGNORE INTO t1 SET a=GEOMFROMTEXT("point (-6 0)"), b=NULL;
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+SELECT ASTEXT(a), ASTEXT(b) FROM t1;
+ASTEXT(a)	ASTEXT(b)
+POINT(0 0)	POINT(1 1)
+DROP TABLE t1;
+CREATE TABLE t1(a INT NOT NULL, b GEOMETRY NOT NULL,
+KEY(a), SPATIAL KEY(b)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(0, GEOMFROMTEXT("point (1 1)"));
+INSERT IGNORE INTO t1 SET a=0, b=GEOMFROMTEXT("error");
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+INSERT IGNORE INTO t1 SET a=1, b=NULL;
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+SELECT a, ASTEXT(b) FROM t1;
+a	ASTEXT(b)
+0	POINT(1 1)
+DROP TABLE t1;
+End of 5.1 tests

=== modified file 'mysql-test/r/multi_update.result'
--- a/mysql-test/r/multi_update.result	2011-03-08 17:39:25 +0000
+++ b/mysql-test/r/multi_update.result	2011-06-16 06:24:00 +0000
@@ -697,4 +697,40 @@ SELECT * FROM t1;
 pk	a
 1	2
 DROP TABLE t1;
-end of tests
+#
+# BUG#11882110: UPDATE REPORTS ER_KEY_NOT_FOUND IF TABLE IS 
+#               UPDATED TWICE
+#
+CREATE TABLE t1 ( 
+col_int_key int, 
+pk int, 
+col_int int, 
+key(col_int_key), 
+primary key (pk)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,2,3);
+
+CREATE TABLE t2 ( 
+col_int_key int, 
+pk_1 int, 
+pk_2 int, 
+col_int int, 
+key(col_int_key), 
+primary key (pk_1,pk_2)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,2,3,4);
+
+UPDATE t1 AS A NATURAL JOIN t1 B SET A.pk=5,B.pk=7;
+
+SELECT * FROM t1;
+col_int_key	pk	col_int
+1	7	3
+
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_1=5,B.pk_1=7;
+
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_2=10,B.pk_2=11;
+
+SELECT * FROM t2;
+col_int_key	pk_1	pk_2	col_int
+1	7	11	4
+DROP TABLE t1,t2;

=== modified file 'mysql-test/r/multi_update_innodb.result'
--- a/mysql-test/r/multi_update_innodb.result	2011-02-21 15:49:03 +0000
+++ b/mysql-test/r/multi_update_innodb.result	2011-06-16 06:24:00 +0000
@@ -27,3 +27,43 @@ pk	a	b
 0	1	2
 DROP VIEW v1;
 DROP TABLE t1;
+#
+# BUG#11882110: UPDATE REPORTS ER_KEY_NOT_FOUND IF TABLE IS 
+#               UPDATED TWICE
+#
+CREATE TABLE t1 ( 
+col_int_key int, 
+pk int, 
+col_int int, 
+key(col_int_key), 
+primary key (pk)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,2,3);
+
+CREATE TABLE t2 ( 
+col_int_key int, 
+pk_1 int, 
+pk_2 int, 
+col_int int, 
+key(col_int_key), 
+primary key (pk_1,pk_2)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1,2,3,4);
+
+UPDATE t1 AS A NATURAL JOIN t1 B SET A.pk=5,B.pk=7;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+
+SELECT * FROM t1;
+col_int_key	pk	col_int
+1	2	3
+
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_1=5,B.pk_1=7;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_2=10,B.pk_2=11;
+ERROR HY000: Primary key/partition key update is not allowed since the table is updated both as 'A' and 'B'.
+
+SELECT * FROM t2;
+col_int_key	pk_1	pk_2	col_int
+1	2	3	4
+DROP TABLE t1,t2;

=== added file 'mysql-test/r/mysql_embedded.result'
--- a/mysql-test/r/mysql_embedded.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/mysql_embedded.result	2011-06-13 18:41:24 +0000
@@ -0,0 +1,5 @@
+#
+# Bug#12561297 : LIBMYSQLD/EXAMPLE/MYSQL_EMBEDDED IS ABORTING.
+#
+1
+1

=== added file 'mysql-test/r/mysql_plugin.result'
--- a/mysql-test/r/mysql_plugin.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/mysql_plugin.result	2011-06-30 12:12:58 +0000
@@ -0,0 +1,97 @@
+#
+# Ensure the plugin isn't loaded.
+#
+SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name;
+name	dl
+#
+# Enable the plugin...
+#
+#
+# Ensure the plugin is now loaded.
+#
+SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name;
+name	dl
+daemon_example	libdaemon_example.so
+#
+# Disable the plugin...
+#
+#
+# Ensure the plugin isn't loaded.
+#
+SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name;
+name	dl
+#
+# Attempt to load non-existant plugin
+#
+ERROR: Cannot read plugin config file NOT_THERE_AT_ALL. File does not exist.
+#
+# Attempt to use non-existant plugin.ini file
+#
+ERROR: Cannot read plugin config file daemon_example. File does not exist.
+# 
+# Attempt to omit the plugin
+#
+ERROR: No plugin specified.
+# 
+# Attempt to omit DISABLE|ENABLE
+#
+ERROR: missing operation. Please specify either '<plugin> ENABLE' or '<plugin> DISABLE'.
+# 
+# Attempt to use bad paths - datadir
+#
+ERROR: Cannot access datadir at '/data_not_there/'.
+# 
+# Attempt to use bad paths - basedir
+#
+ERROR: Cannot access basedir at '/basedir_not_there/'.
+# 
+# Attempt to use bad paths - plugin_dir
+#
+ERROR: Cannot read plugin config file daemon_example. File does not exist.
+# 
+# Missing library
+#
+ERROR: The plugin library is missing or in a different location.
+# 
+# Bad format for config file
+#
+ERROR: Cannot read plugin config file daemon_example. Bad format in plugin configuration file.
+# 
+# Missing base_dir option
+#
+ERROR: Missing --basedir option.
+# 
+# Missing data_dir option
+#
+ERROR: Missing --datadir option.
+# 
+# Missing plugin_dir option
+#
+ERROR: Missing --plugin_dir option.
+#
+# Show the help.
+#
+mysql_plugin  Ver 1.0.0 Distrib XX.XX.XX
+Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+Enable or disable plugins.
+
+Usage: mysql_plugin [options] <plugin> ENABLE|DISABLE
+
+Options:
+  -?, --help          Display this help and exit.
+  -b, --basedir=name  The basedir for the server.
+  -d, --datadir=name  The datadir for the server.
+  -p, --plugin-dir=name 
+                      The plugin dir for the server.
+  -i, --plugin-ini=name 
+                      Read plugin information from configuration file specified
+                      instead of from <plugin-dir>/<plugin_name>.ini.
+  -n, --no-defaults   Do not read values from configuration file.
+  -P, --print-defaults 
+                      Show default values from configuration file.
+  -v, --verbose       More verbose output; you can use this multiple times to
+                      get even more verbose output.
+  -V, --version       Output version information and exit.
+
+

=== modified file 'mysql-test/r/partition.result'
--- a/mysql-test/r/partition.result	2011-03-11 09:12:58 +0000
+++ b/mysql-test/r/partition.result	2011-06-13 09:57:47 +0000
@@ -1,5 +1,34 @@
 drop table if exists t1, t2;
 #
+# Bug#11765667: bug#58655: ASSERTION FAILED,
+#                          SERVER CRASHES WITH MYSQLD GOT SIGNAL 6
+#
+CREATE TABLE t1 (
+id MEDIUMINT NOT NULL AUTO_INCREMENT,
+dt DATE, st VARCHAR(255), uid INT,
+id2nd LONGBLOB, filler VARCHAR(255), PRIMARY KEY(id, dt)
+);
+INSERT INTO t1 (dt, st, uid, id2nd, filler) VALUES
+('1991-03-14', 'Initial Insert', 200, 1234567, 'No Data'),
+('1991-02-26', 'Initial Insert', 201, 1234567, 'No Data'),
+('1992-03-16', 'Initial Insert', 234, 1234567, 'No Data'),
+('1992-07-02', 'Initial Insert', 287, 1234567, 'No Data'),
+('1991-05-26', 'Initial Insert', 256, 1234567, 'No Data'),
+('1991-04-25', 'Initial Insert', 222, 1234567, 'No Data'),
+('1993-03-12', 'Initial Insert', 267, 1234567, 'No Data'),
+('1993-03-14', 'Initial Insert', 291, 1234567, 'No Data'),
+('1991-12-20', 'Initial Insert', 298, 1234567, 'No Data'),
+('1994-10-31', 'Initial Insert', 220, 1234567, 'No Data');
+ALTER TABLE t1 PARTITION BY LIST (YEAR(dt)) (
+PARTITION d1 VALUES IN (1991, 1994),
+PARTITION d2 VALUES IN (1993),
+PARTITION d3 VALUES IN (1992, 1995, 1996)
+);
+INSERT INTO t1 (dt, st, uid, id2nd, filler) VALUES
+('1991-07-14', 'After Partitioning Insert', 299, 1234567, 'Insert row');
+UPDATE t1 SET filler='Updating the row' WHERE uid=298;
+DROP TABLE t1;
+#
 # Bug#59297: Can't find record in 'tablename' on update inner join
 #
 CREATE TABLE t1 (
@@ -189,6 +218,15 @@ a	b
 2007-07-30 17:35:48	p1
 2009-07-14 17:35:55	pmax
 2009-09-21 17:31:42	pmax
+SELECT * FROM t1 where a between '2007-01-01' and '2007-08-01';
+a	b
+2007-07-30 17:35:48	p1
+EXPLAIN PARTITIONS SELECT * FROM t1 where a between '2007-01-01' and '2007-08-01';
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	p1	system	PRIMARY	NULL	NULL	NULL	1	
+EXPLAIN PARTITIONS SELECT * FROM t1 where a = '2007-07-30 17:35:48';
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	p1	system	PRIMARY	NULL	NULL	NULL	1	
 ALTER TABLE t1 REORGANIZE PARTITION pmax INTO (
 PARTITION p3 VALUES LESS THAN (1247688000),
 PARTITION pmax VALUES LESS THAN MAXVALUE);
@@ -197,6 +235,15 @@ a	b
 2007-07-30 17:35:48	p1
 2009-07-14 17:35:55	pmax
 2009-09-21 17:31:42	pmax
+SELECT * FROM t1 where a between '2007-01-01' and '2007-08-01';
+a	b
+2007-07-30 17:35:48	p1
+EXPLAIN PARTITIONS SELECT * FROM t1 where a between '2007-01-01' and '2007-08-01';
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	p1	system	PRIMARY	NULL	NULL	NULL	1	
+EXPLAIN PARTITIONS SELECT * FROM t1 where a = '2007-07-30 17:35:48';
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	p1	system	PRIMARY	NULL	NULL	NULL	1	
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (

=== modified file 'mysql-test/r/partition_datatype.result'
--- a/mysql-test/r/partition_datatype.result	2009-10-28 00:11:17 +0000
+++ b/mysql-test/r/partition_datatype.result	2011-06-13 09:57:47 +0000
@@ -338,3 +338,1003 @@ select hex(a) from t1 where a = 7;
 hex(a)
 7
 drop table t1;
+#
+# Bug#28928: UNIX_TIMESTAMP() should be considered unary monotonic
+#            by partition pruning
+SET @old_time_zone= @@session.time_zone;
+SET @@session.time_zone = 'UTC';
+# Using MyISAM to get stable values on TABLE_ROWS in I_S.PARTITIONS
+CREATE TABLE t1
+(a TIMESTAMP NULL,
+tz varchar(16))
+ENGINE = MyISAM;
+CREATE TABLE t2 LIKE t1;
+ALTER TABLE t2 PARTITION BY RANGE (UNIX_TIMESTAMP(a))
+(PARTITION `p0` VALUES LESS THAN (0),
+PARTITION `p-2000` VALUES LESS THAN (UNIX_TIMESTAMP('2000-01-01')),
+PARTITION `p-2011-MSK` VALUES LESS THAN (UNIX_TIMESTAMP('2011-03-26 23:00:00')),
+PARTITION `p-2011-MSD-1` VALUES LESS THAN (UNIX_TIMESTAMP('2011-10-29 22:00:00')),
+PARTITION `p-2011-MSD-2` VALUES LESS THAN (UNIX_TIMESTAMP('2011-10-29 23:00:00')),
+PARTITION `p-2012-MSK-1` VALUES LESS THAN (UNIX_TIMESTAMP('2011-10-30 00:00:00')),
+PARTITION `p-2012-MSK-2` VALUES LESS THAN (UNIX_TIMESTAMP('2012-03-24 23:00:00')),
+PARTITION `pEnd` VALUES LESS THAN (UNIX_TIMESTAMP('2038-01-19 03:14:07')),
+PARTITION `pMax` VALUES LESS THAN MAXVALUE);
+# Test 'odd' values
+INSERT INTO t1 VALUES (NULL, 'UTC');
+INSERT INTO t1 VALUES ('0000-00-00 00:00:00', 'UTC');
+# Test invalid values
+INSERT INTO t1 VALUES ('1901-01-01 00:00:00', 'UTCI');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+INSERT INTO t1 VALUES ('1969-12-31 23:59:59', 'UTCI');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+INSERT INTO t1 VALUES ('2038-01-19 03:14:08', 'UTCI');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+INSERT INTO t1 VALUES ('1970-01-01 00:00:00', 'UTCI');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+# Test start range
+INSERT INTO t1 VALUES ('1970-01-01 00:00:01', 'UTC');
+INSERT INTO t1 VALUES ('1974-02-05 21:28:16', 'UTC');
+# Test end range
+INSERT INTO t1 VALUES ('2038-01-19 03:14:06', 'UTC');
+INSERT INTO t1 VALUES ('2038-01-19 03:14:07', 'UTC');
+# Test Daylight saving shift
+INSERT INTO t1 VALUES ('2011-03-26 22:59:59', 'UTC');
+INSERT INTO t1 VALUES ('2011-03-26 23:00:00', 'UTC');
+INSERT INTO t1 VALUES ('2011-03-26 23:00:01', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 21:59:59', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 22:00:00', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 22:00:01', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 22:59:59', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 23:00:00', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 23:00:01', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 23:59:59', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-30 00:00:00', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-30 00:00:01', 'UTC');
+SET @@session.time_zone = 'Europe/Moscow';
+# Test 'odd' values
+INSERT INTO t1 VALUES (NULL, 'Moscow');
+INSERT INTO t1 VALUES ('0000-00-00 00:00:00', 'Moscow');
+# Test invalid values
+INSERT INTO t1 VALUES ('0000-00-00 03:00:00', 'MoscowI');
+Warnings:
+Warning	1265	Data truncated for column 'a' at row 1
+INSERT INTO t1 VALUES ('1901-01-01 00:00:00', 'MoscowI');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+INSERT INTO t1 VALUES ('1969-12-31 23:59:59', 'MoscowI');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+INSERT INTO t1 VALUES ('1970-01-01 02:29:29', 'MoscowI');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+INSERT INTO t1 VALUES ('2038-01-19 06:14:08', 'MoscowI');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+INSERT INTO t1 VALUES ('1970-01-01 03:00:00', 'MoscowI');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+# values truncated to 03:00:00 due to daylight saving shift
+INSERT INTO t1 VALUES ('2011-03-27 02:00:00', 'MoscowI');
+Warnings:
+Warning	1299	Invalid TIMESTAMP value in column 'a' at row 1
+INSERT INTO t1 VALUES ('2011-03-27 02:00:01', 'MoscowI');
+Warnings:
+Warning	1299	Invalid TIMESTAMP value in column 'a' at row 1
+INSERT INTO t1 VALUES ('2011-03-27 02:59:59', 'MoscowI');
+Warnings:
+Warning	1299	Invalid TIMESTAMP value in column 'a' at row 1
+# Test start range
+INSERT INTO t1 VALUES ('1970-01-01 03:00:01', 'Moscow');
+INSERT INTO t1 VALUES ('1974-02-05 21:28:16', 'Moscow');
+# Test end range
+INSERT INTO t1 VALUES ('2038-01-19 06:14:06', 'Moscow');
+INSERT INTO t1 VALUES ('2038-01-19 06:14:07', 'Moscow');
+# Test Daylight saving shift
+INSERT INTO t1 VALUES ('2011-03-27 01:59:59', 'Moscow');
+INSERT INTO t1 VALUES ('2011-03-27 03:00:00', 'Moscow');
+INSERT INTO t1 VALUES ('2011-03-27 03:00:01', 'Moscow');
+INSERT INTO t1 VALUES ('2011-10-30 01:59:59', 'Moscow');
+# All values between 02:00 and 02:59:59 will be interpretated as DST
+INSERT INTO t1 VALUES ('2011-10-30 02:00:00', 'MoscowD');
+INSERT INTO t1 VALUES ('2011-10-30 02:00:01', 'MoscowD');
+INSERT INTO t1 VALUES ('2011-10-30 02:59:59', 'MoscowD');
+INSERT INTO t1 VALUES ('2011-10-30 03:00:00', 'Moscow');
+INSERT INTO t1 VALUES ('2011-10-30 03:00:01', 'Moscow');
+SET @@session.time_zone = 'UTC';
+INSERT INTO t2 SELECT * FROM t1;
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+PARTITION_NAME	TABLE_ROWS
+p0	2
+p-2000	16
+p-2011-MSK	2
+p-2011-MSD-1	9
+p-2011-MSD-2	6
+p-2012-MSK-1	3
+p-2012-MSK-2	4
+pEnd	2
+pMax	2
+SELECT * FROM t1 ORDER BY a, tz;
+a	tz
+NULL	Moscow
+NULL	UTC
+0000-00-00 00:00:00	Moscow
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	UTC
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+1970-01-01 00:00:01	Moscow
+1970-01-01 00:00:01	UTC
+1974-02-05 18:28:16	Moscow
+1974-02-05 21:28:16	UTC
+2011-03-26 22:59:59	Moscow
+2011-03-26 22:59:59	UTC
+2011-03-26 23:00:00	Moscow
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	UTC
+2011-03-26 23:00:01	Moscow
+2011-03-26 23:00:01	UTC
+2011-10-29 21:59:59	Moscow
+2011-10-29 21:59:59	UTC
+2011-10-29 22:00:00	MoscowD
+2011-10-29 22:00:00	UTC
+2011-10-29 22:00:01	MoscowD
+2011-10-29 22:00:01	UTC
+2011-10-29 22:59:59	MoscowD
+2011-10-29 22:59:59	UTC
+2011-10-29 23:00:00	UTC
+2011-10-29 23:00:01	UTC
+2011-10-29 23:59:59	UTC
+2011-10-30 00:00:00	Moscow
+2011-10-30 00:00:00	UTC
+2011-10-30 00:00:01	Moscow
+2011-10-30 00:00:01	UTC
+2038-01-19 03:14:06	Moscow
+2038-01-19 03:14:06	UTC
+2038-01-19 03:14:07	Moscow
+2038-01-19 03:14:07	UTC
+SELECT * FROM t2 ORDER BY a, tz;
+a	tz
+NULL	Moscow
+NULL	UTC
+0000-00-00 00:00:00	Moscow
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	UTC
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+1970-01-01 00:00:01	Moscow
+1970-01-01 00:00:01	UTC
+1974-02-05 18:28:16	Moscow
+1974-02-05 21:28:16	UTC
+2011-03-26 22:59:59	Moscow
+2011-03-26 22:59:59	UTC
+2011-03-26 23:00:00	Moscow
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	UTC
+2011-03-26 23:00:01	Moscow
+2011-03-26 23:00:01	UTC
+2011-10-29 21:59:59	Moscow
+2011-10-29 21:59:59	UTC
+2011-10-29 22:00:00	MoscowD
+2011-10-29 22:00:00	UTC
+2011-10-29 22:00:01	MoscowD
+2011-10-29 22:00:01	UTC
+2011-10-29 22:59:59	MoscowD
+2011-10-29 22:59:59	UTC
+2011-10-29 23:00:00	UTC
+2011-10-29 23:00:01	UTC
+2011-10-29 23:59:59	UTC
+2011-10-30 00:00:00	Moscow
+2011-10-30 00:00:00	UTC
+2011-10-30 00:00:01	Moscow
+2011-10-30 00:00:01	UTC
+2038-01-19 03:14:06	Moscow
+2038-01-19 03:14:06	UTC
+2038-01-19 03:14:07	Moscow
+2038-01-19 03:14:07	UTC
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-26 23:00:00' ORDER BY a, tz;
+a	tz
+2011-03-26 22:59:59	Moscow
+2011-03-26 22:59:59	UTC
+2011-03-26 23:00:00	Moscow
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-26 23:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSK,p-2011-MSD-1	ALL	NULL	NULL	NULL	NULL	11	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-26 22:59:59' ORDER BY a, tz;
+a	tz
+2011-03-26 22:59:59	Moscow
+2011-03-26 22:59:59	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-26 22:59:59' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSK	ALL	NULL	NULL	NULL	NULL	2	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 22:59:59' and '2011-03-28 00:00:00' ORDER BY a, tz;
+a	tz
+2011-03-26 22:59:59	Moscow
+2011-03-26 22:59:59	UTC
+2011-03-26 23:00:00	Moscow
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	UTC
+2011-03-26 23:00:01	Moscow
+2011-03-26 23:00:01	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 22:59:59' and '2011-03-28 00:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSK,p-2011-MSD-1	ALL	NULL	NULL	NULL	NULL	11	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 23:00:00' and '2011-03-28 00:00:00' ORDER BY a, tz;
+a	tz
+2011-03-26 23:00:00	Moscow
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	UTC
+2011-03-26 23:00:01	Moscow
+2011-03-26 23:00:01	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 23:00:00' and '2011-03-28 00:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1	ALL	NULL	NULL	NULL	NULL	9	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 23:00:00' ORDER BY a, tz;
+a	tz
+2011-10-29 21:59:59	Moscow
+2011-10-29 21:59:59	UTC
+2011-10-29 22:00:00	MoscowD
+2011-10-29 22:00:00	UTC
+2011-10-29 22:00:01	MoscowD
+2011-10-29 22:00:01	UTC
+2011-10-29 22:59:59	MoscowD
+2011-10-29 22:59:59	UTC
+2011-10-29 23:00:00	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 23:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1,p-2011-MSD-2,p-2012-MSK-1	ALL	NULL	NULL	NULL	NULL	18	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 22:59:59' ORDER BY a, tz;
+a	tz
+2011-10-29 21:59:59	Moscow
+2011-10-29 21:59:59	UTC
+2011-10-29 22:00:00	MoscowD
+2011-10-29 22:00:00	UTC
+2011-10-29 22:00:01	MoscowD
+2011-10-29 22:00:01	UTC
+2011-10-29 22:59:59	MoscowD
+2011-10-29 22:59:59	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 22:59:59' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1,p-2011-MSD-2	ALL	NULL	NULL	NULL	NULL	15	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 22:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+a	tz
+2011-10-29 22:59:59	MoscowD
+2011-10-29 22:59:59	UTC
+2011-10-29 23:00:00	UTC
+2011-10-29 23:00:01	UTC
+2011-10-29 23:59:59	UTC
+2011-10-30 00:00:00	Moscow
+2011-10-30 00:00:00	UTC
+2011-10-30 00:00:01	Moscow
+2011-10-30 00:00:01	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 22:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-2,p-2012-MSK-1,p-2012-MSK-2	ALL	NULL	NULL	NULL	NULL	13	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 23:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+a	tz
+2011-10-29 23:00:00	UTC
+2011-10-29 23:00:01	UTC
+2011-10-29 23:59:59	UTC
+2011-10-30 00:00:00	Moscow
+2011-10-30 00:00:00	UTC
+2011-10-30 00:00:01	Moscow
+2011-10-30 00:00:01	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 23:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2012-MSK-1,p-2012-MSK-2	ALL	NULL	NULL	NULL	NULL	7	Using where; Using filesort
+# Test end range changes
+DELETE FROM t2 WHERE a = 0;
+INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'UTC');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+35
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+COUNT(*)
+1
+SELECT * FROM t2 ORDER BY a, tz LIMIT 3;
+a	tz
+NULL	Moscow
+NULL	UTC
+0000-00-00 00:00:00	UTC
+SELECT * FROM t2 ORDER BY a DESC, tz LIMIT 3;
+a	tz
+2038-01-19 03:14:07	Moscow
+2038-01-19 03:14:07	UTC
+2038-01-19 03:14:06	Moscow
+UPDATE t2 SET a = TIMESTAMPADD(SECOND, 1, a);
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 34
+Warning	1264	Out of range value for column 'a' at row 35
+SELECT MIN(a), MAX(a) FROM t2;
+MIN(a)	MAX(a)
+0000-00-00 00:00:00	2038-01-19 03:14:07
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+35
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+COUNT(*)
+2
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+PARTITION_NAME	TABLE_ROWS
+p0	3
+p-2000	6
+p-2011-MSK	0
+p-2011-MSD-1	9
+p-2011-MSD-2	6
+p-2012-MSK-1	4
+p-2012-MSK-2	5
+pEnd	0
+pMax	2
+SELECT * FROM t2 ORDER BY a, tz;
+a	tz
+NULL	Moscow
+NULL	UTC
+NULL	UTC
+0000-00-00 00:00:00	Moscow
+0000-00-00 00:00:00	UTC
+1970-01-01 00:00:02	Moscow
+1970-01-01 00:00:02	UTC
+1974-02-05 18:28:17	Moscow
+1974-02-05 21:28:17	UTC
+2011-03-26 23:00:00	Moscow
+2011-03-26 23:00:00	UTC
+2011-03-26 23:00:01	Moscow
+2011-03-26 23:00:01	MoscowI
+2011-03-26 23:00:01	MoscowI
+2011-03-26 23:00:01	MoscowI
+2011-03-26 23:00:01	UTC
+2011-03-26 23:00:02	Moscow
+2011-03-26 23:00:02	UTC
+2011-10-29 22:00:00	Moscow
+2011-10-29 22:00:00	UTC
+2011-10-29 22:00:01	MoscowD
+2011-10-29 22:00:01	UTC
+2011-10-29 22:00:02	MoscowD
+2011-10-29 22:00:02	UTC
+2011-10-29 23:00:00	MoscowD
+2011-10-29 23:00:00	UTC
+2011-10-29 23:00:01	UTC
+2011-10-29 23:00:02	UTC
+2011-10-30 00:00:00	UTC
+2011-10-30 00:00:01	Moscow
+2011-10-30 00:00:01	UTC
+2011-10-30 00:00:02	Moscow
+2011-10-30 00:00:02	UTC
+2038-01-19 03:14:07	Moscow
+2038-01-19 03:14:07	UTC
+# Test start range changes
+INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'UTC');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+36
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+COUNT(*)
+3
+SELECT * FROM t2 ORDER BY a, tz LIMIT 3;
+a	tz
+NULL	Moscow
+NULL	UTC
+NULL	UTC
+SELECT * FROM t2 ORDER BY a DESC, tz LIMIT 3;
+a	tz
+2038-01-19 03:14:07	Moscow
+2038-01-19 03:14:07	UTC
+2011-10-30 00:00:02	Moscow
+UPDATE t2 SET a = TIMESTAMPADD(SECOND, -1, a);
+SELECT MIN(a), MAX(a) FROM t2;
+MIN(a)	MAX(a)
+1970-01-01 00:00:01	2038-01-19 03:14:06
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+36
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+COUNT(*)
+0
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+PARTITION_NAME	TABLE_ROWS
+p0	6
+p-2000	4
+p-2011-MSK	2
+p-2011-MSD-1	9
+p-2011-MSD-2	6
+p-2012-MSK-1	3
+p-2012-MSK-2	4
+pEnd	2
+pMax	0
+SELECT * FROM t2 ORDER BY a, tz;
+a	tz
+NULL	Moscow
+NULL	Moscow
+NULL	UTC
+NULL	UTC
+NULL	UTC
+NULL	UTC
+1970-01-01 00:00:01	Moscow
+1970-01-01 00:00:01	UTC
+1974-02-05 18:28:16	Moscow
+1974-02-05 21:28:16	UTC
+2011-03-26 22:59:59	Moscow
+2011-03-26 22:59:59	UTC
+2011-03-26 23:00:00	Moscow
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	MoscowI
+2011-03-26 23:00:00	UTC
+2011-03-26 23:00:01	Moscow
+2011-03-26 23:00:01	UTC
+2011-10-29 21:59:59	Moscow
+2011-10-29 21:59:59	UTC
+2011-10-29 22:00:00	MoscowD
+2011-10-29 22:00:00	UTC
+2011-10-29 22:00:01	MoscowD
+2011-10-29 22:00:01	UTC
+2011-10-29 22:59:59	MoscowD
+2011-10-29 22:59:59	UTC
+2011-10-29 23:00:00	UTC
+2011-10-29 23:00:01	UTC
+2011-10-29 23:59:59	UTC
+2011-10-30 00:00:00	Moscow
+2011-10-30 00:00:00	UTC
+2011-10-30 00:00:01	Moscow
+2011-10-30 00:00:01	UTC
+2038-01-19 03:14:06	Moscow
+2038-01-19 03:14:06	UTC
+SHOW CREATE TABLE t2;
+Table	Create Table
+t2	CREATE TABLE `t2` (
+  `a` timestamp NULL DEFAULT NULL,
+  `tz` varchar(16) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (UNIX_TIMESTAMP(a))
+(PARTITION p0 VALUES LESS THAN (0) ENGINE = MyISAM,
+ PARTITION `p-2000` VALUES LESS THAN (946684800) ENGINE = MyISAM,
+ PARTITION `p-2011-MSK` VALUES LESS THAN (1301180400) ENGINE = MyISAM,
+ PARTITION `p-2011-MSD-1` VALUES LESS THAN (1319925600) ENGINE = MyISAM,
+ PARTITION `p-2011-MSD-2` VALUES LESS THAN (1319929200) ENGINE = MyISAM,
+ PARTITION `p-2012-MSK-1` VALUES LESS THAN (1319932800) ENGINE = MyISAM,
+ PARTITION `p-2012-MSK-2` VALUES LESS THAN (1332630000) ENGINE = MyISAM,
+ PARTITION pEnd VALUES LESS THAN (2147483647) ENGINE = MyISAM,
+ PARTITION pMax VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
+TRUNCATE TABLE t2;
+SET @@session.time_zone = 'Europe/Moscow';
+INSERT INTO t2 SELECT * FROM t1;
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+PARTITION_NAME	TABLE_ROWS
+p0	2
+p-2000	16
+p-2011-MSK	2
+p-2011-MSD-1	9
+p-2011-MSD-2	6
+p-2012-MSK-1	3
+p-2012-MSK-2	4
+pEnd	2
+pMax	2
+SELECT * FROM t1 ORDER BY a, tz;
+a	tz
+NULL	Moscow
+NULL	UTC
+0000-00-00 00:00:00	Moscow
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	UTC
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+1970-01-01 03:00:01	Moscow
+1970-01-01 03:00:01	UTC
+1974-02-05 21:28:16	Moscow
+1974-02-06 00:28:16	UTC
+2011-03-27 01:59:59	Moscow
+2011-03-27 01:59:59	UTC
+2011-03-27 03:00:00	Moscow
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	UTC
+2011-03-27 03:00:01	Moscow
+2011-03-27 03:00:01	UTC
+2011-10-30 01:59:59	Moscow
+2011-10-30 01:59:59	UTC
+2011-10-30 02:00:00	MoscowD
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	MoscowD
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	MoscowD
+2011-10-30 02:59:59	UTC
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	UTC
+2011-10-30 03:00:00	Moscow
+2011-10-30 03:00:00	UTC
+2011-10-30 03:00:01	Moscow
+2011-10-30 03:00:01	UTC
+2038-01-19 06:14:06	Moscow
+2038-01-19 06:14:06	UTC
+2038-01-19 06:14:07	Moscow
+2038-01-19 06:14:07	UTC
+SELECT * FROM t2 ORDER BY a, tz;
+a	tz
+NULL	Moscow
+NULL	UTC
+0000-00-00 00:00:00	Moscow
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	MoscowI
+0000-00-00 00:00:00	UTC
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+0000-00-00 00:00:00	UTCI
+1970-01-01 03:00:01	Moscow
+1970-01-01 03:00:01	UTC
+1974-02-05 21:28:16	Moscow
+1974-02-06 00:28:16	UTC
+2011-03-27 01:59:59	Moscow
+2011-03-27 01:59:59	UTC
+2011-03-27 03:00:00	Moscow
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	UTC
+2011-03-27 03:00:01	Moscow
+2011-03-27 03:00:01	UTC
+2011-10-30 01:59:59	Moscow
+2011-10-30 01:59:59	UTC
+2011-10-30 02:00:00	MoscowD
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	MoscowD
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	MoscowD
+2011-10-30 02:59:59	UTC
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	UTC
+2011-10-30 03:00:00	Moscow
+2011-10-30 03:00:00	UTC
+2011-10-30 03:00:01	Moscow
+2011-10-30 03:00:01	UTC
+2038-01-19 06:14:06	Moscow
+2038-01-19 06:14:06	UTC
+2038-01-19 06:14:07	Moscow
+2038-01-19 06:14:07	UTC
+# Testing the leap from 01:59:59 to 03:00:00
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-27 03:00:00' ORDER BY a, tz;
+a	tz
+2011-03-27 01:59:59	Moscow
+2011-03-27 01:59:59	UTC
+2011-03-27 03:00:00	Moscow
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-27 03:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSK,p-2011-MSD-1	ALL	NULL	NULL	NULL	NULL	11	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-27 01:59:59' ORDER BY a, tz;
+a	tz
+2011-03-27 01:59:59	Moscow
+2011-03-27 01:59:59	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-27 01:59:59' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSK	ALL	NULL	NULL	NULL	NULL	2	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 01:59:59' and '2011-03-28 00:00:00' ORDER BY a, tz;
+a	tz
+2011-03-27 01:59:59	Moscow
+2011-03-27 01:59:59	UTC
+2011-03-27 03:00:00	Moscow
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	UTC
+2011-03-27 03:00:01	Moscow
+2011-03-27 03:00:01	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 01:59:59' and '2011-03-28 00:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSK,p-2011-MSD-1	ALL	NULL	NULL	NULL	NULL	11	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 03:00:00' and '2011-03-28 00:00:00' ORDER BY a, tz;
+a	tz
+2011-03-27 01:59:59	Moscow
+2011-03-27 01:59:59	UTC
+2011-03-27 03:00:00	Moscow
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	UTC
+2011-03-27 03:00:01	Moscow
+2011-03-27 03:00:01	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 03:00:00' and '2011-03-28 00:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSK,p-2011-MSD-1	ALL	NULL	NULL	NULL	NULL	11	Using where; Using filesort
+# Testing the leap from 02:59:59 to 02:00:00
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 02:00:00' ORDER BY a, tz;
+a	tz
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 02:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1	ALL	NULL	NULL	NULL	NULL	9	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 02:59:59' ORDER BY a, tz;
+a	tz
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 02:59:59' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1	ALL	NULL	NULL	NULL	NULL	9	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 03:00:00' ORDER BY a, tz;
+a	tz
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 03:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1	ALL	NULL	NULL	NULL	NULL	9	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 01:59:59' ORDER BY a, tz;
+a	tz
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 01:59:59' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1	ALL	NULL	NULL	NULL	NULL	9	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 02:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+a	tz
+2011-10-30 01:59:59	Moscow
+2011-10-30 01:59:59	UTC
+2011-10-30 02:00:00	MoscowD
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	MoscowD
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	MoscowD
+2011-10-30 02:59:59	UTC
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	UTC
+2011-10-30 03:00:00	Moscow
+2011-10-30 03:00:00	UTC
+2011-10-30 03:00:01	Moscow
+2011-10-30 03:00:01	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 02:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1,p-2011-MSD-2,p-2012-MSK-1,p-2012-MSK-2	ALL	NULL	NULL	NULL	NULL	22	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 02:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+a	tz
+2011-10-30 01:59:59	Moscow
+2011-10-30 01:59:59	UTC
+2011-10-30 02:00:00	MoscowD
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	MoscowD
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	MoscowD
+2011-10-30 02:59:59	UTC
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	UTC
+2011-10-30 03:00:00	Moscow
+2011-10-30 03:00:00	UTC
+2011-10-30 03:00:01	Moscow
+2011-10-30 03:00:01	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 02:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1,p-2011-MSD-2,p-2012-MSK-1,p-2012-MSK-2	ALL	NULL	NULL	NULL	NULL	22	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 03:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+a	tz
+2011-10-30 01:59:59	Moscow
+2011-10-30 01:59:59	UTC
+2011-10-30 02:00:00	MoscowD
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	MoscowD
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	MoscowD
+2011-10-30 02:59:59	UTC
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	UTC
+2011-10-30 03:00:00	Moscow
+2011-10-30 03:00:00	UTC
+2011-10-30 03:00:01	Moscow
+2011-10-30 03:00:01	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 03:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1,p-2011-MSD-2,p-2012-MSK-1,p-2012-MSK-2	ALL	NULL	NULL	NULL	NULL	22	Using where; Using filesort
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 01:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+a	tz
+2011-10-30 01:59:59	Moscow
+2011-10-30 01:59:59	UTC
+2011-10-30 02:00:00	MoscowD
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	MoscowD
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	MoscowD
+2011-10-30 02:59:59	UTC
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	UTC
+2011-10-30 03:00:00	Moscow
+2011-10-30 03:00:00	UTC
+2011-10-30 03:00:01	Moscow
+2011-10-30 03:00:01	UTC
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 01:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t2	p-2011-MSD-1,p-2011-MSD-2,p-2012-MSK-1,p-2012-MSK-2	ALL	NULL	NULL	NULL	NULL	22	Using where; Using filesort
+# Test end range changes
+DELETE FROM t2 WHERE a = 0;
+INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'Moscow');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+35
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+COUNT(*)
+1
+SELECT * FROM t2 ORDER BY a, tz LIMIT 3;
+a	tz
+NULL	Moscow
+NULL	UTC
+0000-00-00 00:00:00	Moscow
+SELECT * FROM t2 ORDER BY a DESC, tz LIMIT 3;
+a	tz
+2038-01-19 06:14:07	Moscow
+2038-01-19 06:14:07	UTC
+2038-01-19 06:14:06	Moscow
+UPDATE t2 SET a = TIMESTAMPADD(SECOND, 1, a);
+Warnings:
+Warning	1299	Invalid TIMESTAMP value in column 'a' at row 8
+Warning	1299	Invalid TIMESTAMP value in column 'a' at row 9
+Warning	1264	Out of range value for column 'a' at row 34
+Warning	1264	Out of range value for column 'a' at row 35
+SELECT MIN(a), MAX(a) FROM t2;
+MIN(a)	MAX(a)
+0000-00-00 00:00:00	2038-01-19 06:14:07
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+35
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+COUNT(*)
+2
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+PARTITION_NAME	TABLE_ROWS
+p0	3
+p-2000	6
+p-2011-MSK	0
+p-2011-MSD-1	9
+p-2011-MSD-2	8
+p-2012-MSK-1	0
+p-2012-MSK-2	7
+pEnd	0
+pMax	2
+SELECT * FROM t2 ORDER BY a, tz;
+a	tz
+NULL	Moscow
+NULL	Moscow
+NULL	UTC
+0000-00-00 00:00:00	Moscow
+0000-00-00 00:00:00	UTC
+1970-01-01 03:00:02	Moscow
+1970-01-01 03:00:02	UTC
+1974-02-05 21:28:17	Moscow
+1974-02-06 00:28:17	UTC
+2011-03-27 03:00:00	Moscow
+2011-03-27 03:00:00	UTC
+2011-03-27 03:00:01	Moscow
+2011-03-27 03:00:01	MoscowI
+2011-03-27 03:00:01	MoscowI
+2011-03-27 03:00:01	MoscowI
+2011-03-27 03:00:01	UTC
+2011-03-27 03:00:02	Moscow
+2011-03-27 03:00:02	UTC
+2011-10-30 02:00:00	Moscow
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	MoscowD
+2011-10-30 02:00:01	UTC
+2011-10-30 02:00:01	UTC
+2011-10-30 02:00:02	MoscowD
+2011-10-30 02:00:02	UTC
+2011-10-30 02:00:02	UTC
+2011-10-30 03:00:00	MoscowD
+2011-10-30 03:00:00	UTC
+2011-10-30 03:00:00	UTC
+2011-10-30 03:00:01	Moscow
+2011-10-30 03:00:01	UTC
+2011-10-30 03:00:02	Moscow
+2011-10-30 03:00:02	UTC
+2038-01-19 06:14:07	Moscow
+2038-01-19 06:14:07	UTC
+# Test start range changes
+INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'Moscow');
+Warnings:
+Warning	1264	Out of range value for column 'a' at row 1
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+36
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+COUNT(*)
+3
+SELECT * FROM t2 ORDER BY a, tz LIMIT 3;
+a	tz
+NULL	Moscow
+NULL	Moscow
+NULL	UTC
+SELECT * FROM t2 ORDER BY a DESC, tz LIMIT 3;
+a	tz
+2038-01-19 06:14:07	Moscow
+2038-01-19 06:14:07	UTC
+2011-10-30 03:00:02	Moscow
+UPDATE t2 SET a = TIMESTAMPADD(SECOND, -1, a);
+Warnings:
+Warning	1299	Invalid TIMESTAMP value in column 'a' at row 18
+Warning	1299	Invalid TIMESTAMP value in column 'a' at row 19
+SELECT MIN(a), MAX(a) FROM t2;
+MIN(a)	MAX(a)
+1970-01-01 03:00:01	2038-01-19 06:14:06
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+36
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+COUNT(*)
+0
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+PARTITION_NAME	TABLE_ROWS
+p0	6
+p-2000	4
+p-2011-MSK	0
+p-2011-MSD-1	11
+p-2011-MSD-2	9
+p-2012-MSK-1	0
+p-2012-MSK-2	4
+pEnd	2
+pMax	0
+SELECT * FROM t2 ORDER BY a, tz;
+a	tz
+NULL	Moscow
+NULL	Moscow
+NULL	Moscow
+NULL	Moscow
+NULL	UTC
+NULL	UTC
+1970-01-01 03:00:01	Moscow
+1970-01-01 03:00:01	UTC
+1974-02-05 21:28:16	Moscow
+1974-02-06 00:28:16	UTC
+2011-03-27 03:00:00	Moscow
+2011-03-27 03:00:00	Moscow
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	MoscowI
+2011-03-27 03:00:00	UTC
+2011-03-27 03:00:00	UTC
+2011-03-27 03:00:01	Moscow
+2011-03-27 03:00:01	UTC
+2011-10-30 01:59:59	Moscow
+2011-10-30 01:59:59	UTC
+2011-10-30 02:00:00	MoscowD
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:00	UTC
+2011-10-30 02:00:01	MoscowD
+2011-10-30 02:00:01	UTC
+2011-10-30 02:00:01	UTC
+2011-10-30 02:59:59	MoscowD
+2011-10-30 02:59:59	UTC
+2011-10-30 02:59:59	UTC
+2011-10-30 03:00:00	Moscow
+2011-10-30 03:00:00	UTC
+2011-10-30 03:00:01	Moscow
+2011-10-30 03:00:01	UTC
+2038-01-19 06:14:06	Moscow
+2038-01-19 06:14:06	UTC
+SHOW CREATE TABLE t2;
+Table	Create Table
+t2	CREATE TABLE `t2` (
+  `a` timestamp NULL DEFAULT NULL,
+  `tz` varchar(16) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (UNIX_TIMESTAMP(a))
+(PARTITION p0 VALUES LESS THAN (0) ENGINE = MyISAM,
+ PARTITION `p-2000` VALUES LESS THAN (946684800) ENGINE = MyISAM,
+ PARTITION `p-2011-MSK` VALUES LESS THAN (1301180400) ENGINE = MyISAM,
+ PARTITION `p-2011-MSD-1` VALUES LESS THAN (1319925600) ENGINE = MyISAM,
+ PARTITION `p-2011-MSD-2` VALUES LESS THAN (1319929200) ENGINE = MyISAM,
+ PARTITION `p-2012-MSK-1` VALUES LESS THAN (1319932800) ENGINE = MyISAM,
+ PARTITION `p-2012-MSK-2` VALUES LESS THAN (1332630000) ENGINE = MyISAM,
+ PARTITION pEnd VALUES LESS THAN (2147483647) ENGINE = MyISAM,
+ PARTITION pMax VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
+TRUNCATE TABLE t2;
+DROP TABLE t1, t2;
+SET @@session.time_zone= @old_time_zone;

=== modified file 'mysql-test/r/query_cache_28249.result'
--- a/mysql-test/r/query_cache_28249.result	2008-11-28 15:45:34 +0000
+++ b/mysql-test/r/query_cache_28249.result	2011-06-10 09:40:57 +0000
@@ -8,7 +8,7 @@ SET @query_cache_size=         @@global.
 SET GLOBAL query_cache_type=1;
 SET GLOBAL query_cache_limit=10000;
 SET GLOBAL query_cache_min_res_unit=0;
-SET GLOBAL query_cache_size= 100000;
+SET GLOBAL query_cache_size= 102400;
 FLUSH TABLES;
 DROP TABLE IF EXISTS t1, t2;
 CREATE TABLE t1 (a INT);
@@ -23,10 +23,10 @@ SELECT *, (SELECT COUNT(*) FROM t2) FROM
 # Switch to connection user3
 # Poll till the select of connection user1 is blocked by the write lock on t1.
 SELECT user,command,state,info FROM information_schema.processlist
-WHERE state = 'Locked'
+WHERE state = 'Waiting for table metadata lock'
   AND info = 'SELECT *, (SELECT COUNT(*) FROM t2) FROM t1';
 user	command	state	info
-root	Query	Locked	SELECT *, (SELECT COUNT(*) FROM t2) FROM t1
+root	Query	Waiting for table metadata lock	SELECT *, (SELECT COUNT(*) FROM t2) FROM t1
 INSERT INTO t1 VALUES (4);
 # Switch to connection user2
 UNLOCK TABLES;

=== modified file 'mysql-test/r/sp_notembedded.result'
--- a/mysql-test/r/sp_notembedded.result	2011-03-18 14:16:17 +0000
+++ b/mysql-test/r/sp_notembedded.result	2011-06-08 13:44:50 +0000
@@ -254,7 +254,6 @@ CREATE PROCEDURE p1(i INT) BEGIN END;
 DROP PROCEDURE p1;
 DELETE FROM mysql.user WHERE User='mysqltest_1';
 FLUSH PRIVILEGES;
-set @@global.concurrent_insert= @old_concurrent_insert;
 #
 # Bug#44521 Prepared Statement: CALL p() - crashes: `! thd->main_da.is_sent' failed et.al.
 #
@@ -288,3 +287,25 @@ DROP FUNCTION f1;
 # ------------------------------------------------------------------
 # -- End of 5.1 tests
 # ------------------------------------------------------------------
+#
+# Test for bug#11763757 "56510: ERROR 42000: FUNCTION DOES NOT EXIST
+# IF NOT-PRIV USER RECONNECTS ".
+#
+# The real problem was that server was unable handle properly stored
+# functions in databases which names contained dot.
+#
+DROP DATABASE IF EXISTS `my.db`;
+create database `my.db`;
+use `my.db`;
+CREATE FUNCTION f1(a int) RETURNS INT RETURN a;
+# Create new connection.
+USE `my.db`;
+SELECT f1(1);
+f1(1)
+1
+SELECT `my.db`.f1(2);
+`my.db`.f1(2)
+2
+# Switching to default connection.
+DROP DATABASE `my.db`;
+set @@global.concurrent_insert= @old_concurrent_insert;

=== modified file 'mysql-test/r/symlink.result'
--- a/mysql-test/r/symlink.result	2011-01-31 09:34:39 +0000
+++ b/mysql-test/r/symlink.result	2011-06-09 12:54:12 +0000
@@ -188,3 +188,28 @@ DROP TABLE user;
 FLUSH TABLE mysql.user;
 SELECT * FROM mysql.user;
 End of 5.1 tests
+#
+# Test for bug #11759990 - "52354: 'CREATE TABLE .. LIKE ... '
+#                           STATEMENTS FAIL".
+#
+drop table if exists t1, t2;
+create table t1 (a int primary key) engine=myisam
+data directory="MYSQLTEST_VARDIR/tmp"
+      index directory="MYSQLTEST_VARDIR/run";
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) NOT NULL,
+  PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/'
+# CREATE TABLE LIKE statement on table with INDEX/DATA DIRECTORY
+# options should not fail. Per documentation newly created table
+# should not inherit value of these options from the original table.
+create table t2 like t1;
+show create table t2;
+Table	Create Table
+t2	CREATE TABLE `t2` (
+  `a` int(11) NOT NULL,
+  PRIMARY KEY (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop tables t1, t2;

=== modified file 'mysql-test/r/trigger-compat.result'
--- a/mysql-test/r/trigger-compat.result	2010-02-03 21:48:40 +0000
+++ b/mysql-test/r/trigger-compat.result	2011-06-10 07:20:15 +0000
@@ -41,3 +41,98 @@ DROP TABLE t2;
 DROP USER mysqltest_dfn@localhost;
 DROP USER mysqltest_inv@localhost;
 DROP DATABASE mysqltest_db1;
+USE test;
+#
+# Bug#45235: 5.1 does not support 5.0-only syntax triggers in any way
+#
+DROP TABLE IF EXISTS t1, t2, t3;
+CREATE TABLE t1 ( a INT );
+CREATE TABLE t2 ( a INT );
+CREATE TABLE t3 ( a INT );
+INSERT INTO t1 VALUES (1), (2), (3);
+INSERT INTO t2 VALUES (1), (2), (3);
+INSERT INTO t3 VALUES (1), (2), (3);
+# We simulate importing a trigger from 5.0 by writing a .TRN file for
+# each trigger plus a .TRG file the way MySQL 5.0 would have done it, 
+# with syntax allowed in 5.0 only.
+#
+# Note that in 5.0 the following lines are missing from t1.TRG:
+#
+# client_cs_names='latin1'
+# connection_cl_names='latin1_swedish_ci'
+# db_cl_names='latin1_swedish_ci'
+FLUSH TABLE t1;
+FLUSH TABLE t2;
+# We will get parse errors for most DDL and DML statements when the table
+# has broken triggers. The parse error refers to the first broken 
+# trigger.
+CREATE TRIGGER tr16 AFTER UPDATE ON t1 FOR EACH ROW INSERT INTO t1 VALUES (1);
+ERROR 42000: Trigger 'tr13' has an error in its body: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a USING t1 a' at line 1'
+CREATE TRIGGER tr22 BEFORE INSERT ON t2 FOR EACH ROW DELETE FROM non_existing_table;
+ERROR 42000: Unknown trigger has an error in its body: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Not allowed syntax here, and trigger name cant be extracted either.' at line 1'
+SHOW TRIGGERS;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer	character_set_client	collation_connection	Database Collation
+tr11	INSERT	t1	DELETE FROM t3	BEFORE	NULL		root@localhost	latin1	latin1_swedish_ci	latin1_swedish_ci
+tr12	INSERT	t1	DELETE FROM t3	AFTER	NULL		root@localhost	latin1	latin1_swedish_ci	latin1_swedish_ci
+tr14	DELETE	t1	DELETE FROM non_existing_table	AFTER	NULL		root@localhost	latin1	latin1_swedish_ci	latin1_swedish_ci
+INSERT INTO t1 VALUES (1);
+ERROR 42000: Trigger 'tr13' has an error in its body: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a USING t1 a' at line 1'
+INSERT INTO t2 VALUES (1);
+ERROR 42000: Unknown trigger has an error in its body: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Not allowed syntax here, and trigger name cant be extracted either.' at line 1'
+DELETE FROM t1;
+ERROR 42000: Trigger 'tr13' has an error in its body: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a USING t1 a' at line 1'
+UPDATE t1 SET a = 1 WHERE a = 1;
+ERROR 42000: Trigger 'tr13' has an error in its body: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a USING t1 a' at line 1'
+SELECT * FROM t1;
+a
+1
+2
+3
+RENAME TABLE t1 TO t1_2;
+ERROR 42000: Trigger 'tr13' has an error in its body: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a USING t1 a' at line 1'
+SHOW TRIGGERS;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer	character_set_client	collation_connection	Database Collation
+tr11	INSERT	t1	DELETE FROM t3	BEFORE	NULL		root@localhost	latin1	latin1_swedish_ci	latin1_swedish_ci
+tr12	INSERT	t1	DELETE FROM t3	AFTER	NULL		root@localhost	latin1	latin1_swedish_ci	latin1_swedish_ci
+tr14	DELETE	t1	DELETE FROM non_existing_table	AFTER	NULL		root@localhost	latin1	latin1_swedish_ci	latin1_swedish_ci
+DROP TRIGGER tr11;
+Warnings:
+Warning	1603	Triggers for table `test`.`t1` have no creation context
+DROP TRIGGER tr12;
+DROP TRIGGER tr13;
+DROP TRIGGER tr14;
+DROP TRIGGER tr15;
+SHOW TRIGGERS;
+Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer	character_set_client	collation_connection	Database Collation
+# Make sure there is no trigger file left.
+# We write the same trigger files one more time to test DROP TABLE.
+FLUSH TABLE t1;
+FLUSH TABLE t2;
+DROP TABLE t1;
+Warnings:
+Warning	1603	Triggers for table `test`.`t1` have no creation context
+DROP TABLE t2;
+Warnings:
+Warning	1603	Triggers for table `test`.`t2` have no creation context
+DROP TABLE t3;
+# Make sure there is no trigger file left.
+CREATE TABLE t1 ( a INT );
+CREATE TABLE t2 ( a INT );
+INSERT INTO t1 VALUES (1), (2), (3);
+INSERT INTO t2 VALUES (1), (2), (3);
+# We write three trigger files. First trigger is syntaxically incorrect, next trigger is correct
+# and last trigger is broken.
+# Next we try to execute SHOW CREATE TRGGIR command for broken trigger and then try to drop one.
+FLUSH TABLE t1;
+SHOW CREATE TRIGGER tr12;
+Trigger	sql_mode	SQL Original Statement	character_set_client	collation_connection	Database Collation
+tr12		CREATE DEFINER=`root`@`localhost` TRIGGER tr12 BEFORE INSERT ON t1 FOR EACH ROW DELETE FROM t2	latin1	latin1_swedish_ci	latin1_swedish_ci
+Warnings:
+Warning	1603	Triggers for table `test`.`t1` have no creation context
+SHOW CREATE TRIGGER tr11;
+Trigger	sql_mode	SQL Original Statement	character_set_client	collation_connection	Database Collation
+tr11		CREATE DEFINER=`root`@`localhost` TRIGGER tr11 BEFORE DELETE ON t1 FOR EACH ROW DELETE FROM t1 a USING t1 a	latin1	latin1_swedish_ci	latin1_swedish_ci
+DROP TRIGGER tr12;
+DROP TRIGGER tr11;
+DROP TABLE t1;
+DROP TABLE t2;

=== modified file 'mysql-test/r/trigger.result'
--- a/mysql-test/r/trigger.result	2011-05-09 08:29:23 +0000
+++ b/mysql-test/r/trigger.result	2011-06-10 07:20:15 +0000
@@ -2118,7 +2118,7 @@ CREATE TRIGGER trg1 BEFORE INSERT ON t2
 SHOW TRIGGERS IN db1;
 Trigger	Event	Table	Statement	Timing	Created	sql_mode	Definer	character_set_client	collation_connection	Database Collation
 INSERT INTO t2 VALUES (1);
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VALUES (1)' at line 1
+ERROR 42000: Trigger 'trg1' has an error in its body: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VALUES (1)' at line 1'
 SELECT * FROM t1;
 b
 # Work around Bug#45235

=== modified file 'mysql-test/r/type_datetime.result'
--- a/mysql-test/r/type_datetime.result	2011-01-19 14:12:43 +0000
+++ b/mysql-test/r/type_datetime.result	2011-06-10 08:22:45 +0000
@@ -703,5 +703,51 @@ b
 DROP TABLE t1;
 #
 #
+# BUG#12561818: RERUN OF STORED FUNCTION GIVES ERROR 1172: 
+#               RESULT CONSISTED OF MORE THAN ONE ROW
+#
+CREATE TABLE t1 (a DATE NOT NULL, b INT);
+INSERT INTO t1 VALUES ('0000-00-00',1), ('1999-05-10',2);
+CREATE TABLE t2 (a DATETIME NOT NULL, b INT);
+INSERT INTO t2 VALUES ('0000-00-00 00:00:00',1), ('1999-05-10 00:00:00',2);
+
+SELECT * FROM t1 WHERE a IS NULL;
+a	b
+0000-00-00	1
+SELECT * FROM t2 WHERE a IS NULL;
+a	b
+0000-00-00 00:00:00	1
+SELECT * FROM t1 LEFT JOIN t1 AS t1_2 ON 1 WHERE t1_2.a IS NULL;
+a	b	a	b
+0000-00-00	1	0000-00-00	1
+1999-05-10	2	0000-00-00	1
+SELECT * FROM t2 LEFT JOIN t2 AS t2_2 ON 1 WHERE t2_2.a IS NULL;
+a	b	a	b
+0000-00-00 00:00:00	1	0000-00-00 00:00:00	1
+1999-05-10 00:00:00	2	0000-00-00 00:00:00	1
+SELECT * FROM t1 JOIN t1 AS t1_2 ON 1 WHERE t1_2.a IS NULL;
+a	b	a	b
+0000-00-00	1	0000-00-00	1
+1999-05-10	2	0000-00-00	1
+SELECT * FROM t2 JOIN t2 AS t2_2 ON 1 WHERE t2_2.a IS NULL;
+a	b	a	b
+0000-00-00 00:00:00	1	0000-00-00 00:00:00	1
+1999-05-10 00:00:00	2	0000-00-00 00:00:00	1
+
+PREPARE stmt1 FROM 
+'SELECT *
+   FROM t1 LEFT JOIN t1 AS t1_2 ON 1
+   WHERE t1_2.a IS NULL AND t1_2.b < 2';
+EXECUTE stmt1;
+a	b	a	b
+0000-00-00	1	0000-00-00	1
+1999-05-10	2	0000-00-00	1
+EXECUTE stmt1;
+a	b	a	b
+0000-00-00	1	0000-00-00	1
+1999-05-10	2	0000-00-00	1
+DEALLOCATE PREPARE stmt1;
+DROP TABLE t1,t2;
+#
 # End of 5.5 tests
 #

=== modified file 'mysql-test/suite/innodb/r/innodb-index.result'
--- a/mysql-test/suite/innodb/r/innodb-index.result	2011-05-31 09:12:32 +0000
+++ b/mysql-test/suite/innodb/r/innodb-index.result	2011-06-23 09:40:19 +0000
@@ -1085,3 +1085,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;

=== modified file 'mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result'
--- a/mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result	2011-06-01 09:55:08 +0000
+++ b/mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result	2011-06-02 09:42:55 +0000
@@ -1,6 +1,7 @@
 set global innodb_file_format="Barracuda";
 set global innodb_file_per_table=1;
 set global innodb_large_prefix=1;
+DROP TABLE IF EXISTS worklog5743;
 CREATE TABLE worklog5743 (
 col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
 PRIMARY KEY (col_1_varchar(3072))
@@ -874,92 +875,6 @@ COUNT(*)
 COMMIT;
 DROP TABLE worklog5743;
 CREATE TABLE worklog5743 (
-col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
-PRIMARY KEY (col_1_text(3072))
-) ROW_FORMAT=DYNAMIC, engine = innodb;
-INSERT INTO worklog5743 VALUES(REPEAT("a", 3500) , REPEAT("o", 3500));
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
-worklog5743;
-col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
-1	1
-"In connection 1"
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
-1	1
-SELECT COUNT(*) FROM worklog5743;
-COUNT(*)
-1
-"In connection 2"
-START TRANSACTION;
-INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
-"In connection 1"
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
-1	1
-SELECT COUNT(*) FROM worklog5743;
-COUNT(*)
-1
-START TRANSACTION;
-"In connection default ....restarting the server"
-SELECT COUNT(*) FROM worklog5743;
-COUNT(*)
-1
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
-worklog5743;
-col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
-1	1
-"In connection 1"
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
-1	1
-SELECT COUNT(*) FROM worklog5743;
-COUNT(*)
-1
-START TRANSACTION;
-INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
-DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 3500);
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
-1	1
-"In connection default ....restarting the server"
-SELECT COUNT(*) FROM worklog5743;
-COUNT(*)
-1
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
-worklog5743;
-col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
-1	1
-"In connection 1"
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
-1	1
-SELECT COUNT(*) FROM worklog5743;
-COUNT(*)
-1
-START TRANSACTION;
-UPDATE worklog5743 SET col_1_text = REPEAT("b", 3500) WHERE col_1_text = REPEAT("a", 3500);
-SELECT col_1_text = REPEAT("b", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-col_1_text = REPEAT("b", 3500)	col_2_text = REPEAT("o", 3500)
-1	1
-"In connection default ....restarting the server"
-SELECT COUNT(*) FROM worklog5743;
-COUNT(*)
-1
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
-worklog5743;
-col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
-1	1
-DROP TABLE worklog5743;
-set global innodb_file_format="Barracuda";
-set global innodb_file_per_table=1;
-set global innodb_large_prefix=1;
-CREATE TABLE worklog5743 (
 col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
 PRIMARY KEY (col_1_varchar(3072))
 ) ROW_FORMAT=DYNAMIC, engine = innodb;

=== added file 'mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result'
--- a/mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result	2011-06-02 09:42:55 +0000
@@ -0,0 +1,91 @@
+set global innodb_file_format="Barracuda";
+set global innodb_file_per_table=1;
+set global innodb_large_prefix=1;
+DROP TABLE IF EXISTS worklog5743;
+CREATE TABLE worklog5743 (
+col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 3500) , REPEAT("o", 3500));
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
+1	1
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+"In connection 2"
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+START TRANSACTION;
+"In connection default ....restarting the server"
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
+1	1
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 3500);
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+"In connection default ....restarting the server"
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
+1	1
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+START TRANSACTION;
+UPDATE worklog5743 SET col_1_text = REPEAT("b", 3500) WHERE col_1_text = REPEAT("a", 3500);
+SELECT col_1_text = REPEAT("b", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("b", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+"In connection default ....restarting the server"
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
+1	1
+DROP TABLE worklog5743;
+SET GLOBAL innodb_file_format=Antelope;
+SET GLOBAL innodb_file_per_table=0;
+SET GLOBAL innodb_file_format_max=Antelope;
+SET GLOBAL innodb_large_prefix=0;

=== modified file 'mysql-test/suite/innodb/t/innodb-index.test'
--- a/mysql-test/suite/innodb/t/innodb-index.test	2011-05-31 09:12:32 +0000
+++ b/mysql-test/suite/innodb/t/innodb-index.test	2011-06-23 09:40:19 +0000
@@ -516,34 +516,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

=== modified file 'mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test'
--- a/mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test	2011-06-01 09:55:08 +0000
+++ b/mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test	2011-06-02 09:42:55 +0000
@@ -26,7 +26,9 @@ set global innodb_file_format="Barracuda
 set global innodb_file_per_table=1;
 set global innodb_large_prefix=1;
 
-
+-- disable_warnings
+DROP TABLE IF EXISTS worklog5743;
+-- enable_warnings
 #------------------------------------------------------------------------------
 # Prefix index with VARCHAR data type , primary/secondary index and DML ops
 CREATE TABLE worklog5743 (
@@ -849,97 +851,6 @@ DROP TABLE worklog5743;
 
 
 #------------------------------------------------------------------------------
-# Stop the server in between when prefix index are created and see if state is
-# correct when server is restarted.
-# Server is restarted at differnt points.
-
-CREATE TABLE worklog5743 (
-col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
-PRIMARY KEY (col_1_text(3072))
-) ROW_FORMAT=DYNAMIC, engine = innodb;
-INSERT INTO worklog5743 VALUES(REPEAT("a", 3500) , REPEAT("o", 3500));
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
-worklog5743;
-
---echo "In connection 1"
---connect (con1,localhost,root,,)
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-SELECT COUNT(*) FROM worklog5743;
-
-
---echo "In connection 2"
---connect (con2,localhost,root,,)
-START TRANSACTION;
-INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
-
-
---echo "In connection 1"
---connection con1
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-SELECT COUNT(*) FROM worklog5743;
-START TRANSACTION;
-
-
---echo "In connection default ....restarting the server"
---connection default
-# Restart the server
--- source include/restart_mysqld.inc
-SELECT COUNT(*) FROM worklog5743;
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
-worklog5743;
-
---disconnect con1
---disconnect con2
-
---echo "In connection 1"
---connect (con1,localhost,root,,)
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-SELECT COUNT(*) FROM worklog5743;
-START TRANSACTION;
-INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
-DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 3500);
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-
---echo "In connection default ....restarting the server"
---connection default
-# Restart the server
--- source include/restart_mysqld.inc
-SELECT COUNT(*) FROM worklog5743;
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
-worklog5743;
-
---disconnect con1
-
---echo "In connection 1"
---connect (con2,localhost,root,,)
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-SELECT COUNT(*) FROM worklog5743;
-START TRANSACTION;
-UPDATE worklog5743 SET col_1_text = REPEAT("b", 3500) WHERE col_1_text = REPEAT("a", 3500);
-SELECT col_1_text = REPEAT("b", 3500) , col_2_text = REPEAT("o", 3500) FROM
-worklog5743;
-
---echo "In connection default ....restarting the server"
---connection default
-# Restart the server
--- source include/restart_mysqld.inc
-SELECT COUNT(*) FROM worklog5743;
-SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
-worklog5743;
-
-DROP TABLE worklog5743;
-
-#------------------------------------------------------------------------------
-# Reset variables at server was restarted in previous case
-set global innodb_file_format="Barracuda";
-set global innodb_file_per_table=1;
-set global innodb_large_prefix=1;
-#------------------------------------------------------------------------------
 # Select queries on prefix index column as index will be used in queries.
 # Use few select functions , join condition , subqueries.
 

=== added file 'mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test'
--- a/mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test	2011-06-16 04:30:51 +0000
@@ -0,0 +1,127 @@
+######## suite/innodb/t/innodb_prefix_iindex_restart_server.test #####
+#                                                                    #
+# Testcase for worklog WL#5743: Lift the limit of index key prefixes #
+# Test scenario : Stop the server in between when prefix index are   #
+# created and see if state is preserved after restart                #
+#                                                                    #
+# Creation:                                                          #
+# 2011-06-02 Implemented this test as part of WL#5743                #
+#                                                                    #
+######################################################################
+
+# Don't test this under valgrind, memory leaks will occur due restart
+--source include/not_valgrind.inc
+# Test restart the server and "shutdown_server" looks for pid file
+# which is not there with embedded mode
+--source include/not_embedded.inc
+--source include/have_innodb.inc
+# Save innodb variables
+let $innodb_file_format_orig=`select @@innodb_file_format`;
+let $innodb_file_per_table_orig=`select @@innodb_file_per_table`;
+let $innodb_file_format_max_orig=`select @@innodb_file_format_max`;
+let $innodb_large_prefix_orig=`select @@innodb_large_prefix`;
+
+# Set Innodb file format as feature works for Barracuda file format
+set global innodb_file_format="Barracuda";
+set global innodb_file_per_table=1;
+set global innodb_large_prefix=1;
+
+-- disable_warnings
+DROP TABLE IF EXISTS worklog5743;
+-- enable_warnings
+
+
+#------------------------------------------------------------------------------
+# Stop the server in between when prefix index are created and see if state is
+# correct when server is restarted.
+# Server is restarted at differnt points.
+
+CREATE TABLE worklog5743 (
+col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 3500) , REPEAT("o", 3500));
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+
+--echo "In connection 1"
+--connect (con1,localhost,root,,)
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+
+
+--echo "In connection 2"
+--connect (con2,localhost,root,,)
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
+
+
+--echo "In connection 1"
+--connection con1
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+START TRANSACTION;
+
+
+--echo "In connection default ....restarting the server"
+--connection default
+# Restart the server
+-- source include/restart_mysqld.inc
+SELECT COUNT(*) FROM worklog5743;
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+
+--disconnect con1
+--disconnect con2
+
+--echo "In connection 1"
+--connect (con1,localhost,root,,)
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 3500);
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+
+--echo "In connection default ....restarting the server"
+--connection default
+# Restart the server
+-- source include/restart_mysqld.inc
+SELECT COUNT(*) FROM worklog5743;
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+
+--disconnect con1
+
+--echo "In connection 1"
+--connect (con2,localhost,root,,)
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+START TRANSACTION;
+UPDATE worklog5743 SET col_1_text = REPEAT("b", 3500) WHERE col_1_text = REPEAT("a", 3500);
+SELECT col_1_text = REPEAT("b", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+
+--echo "In connection default ....restarting the server"
+--connection default
+# Restart the server
+-- source include/restart_mysqld.inc
+SELECT COUNT(*) FROM worklog5743;
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+
+DROP TABLE worklog5743;
+
+
+#------------------------------------------------------------------------------
+
+eval SET GLOBAL innodb_file_format=$innodb_file_format_orig;
+eval SET GLOBAL innodb_file_per_table=$innodb_file_per_table_orig;
+eval SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig;
+eval SET GLOBAL innodb_large_prefix=$innodb_large_prefix_orig;
+

=== modified file 'mysql-test/suite/perfschema/include/cleanup_helper.inc'
--- a/mysql-test/suite/perfschema/include/cleanup_helper.inc	2010-11-03 15:42:33 +0000
+++ b/mysql-test/suite/perfschema/include/cleanup_helper.inc	2011-06-16 20:35:01 +0000
@@ -1,25 +1,33 @@
-# Copyright (C) 2009 Sun Microsystems, Inc
+# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 #
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2 of
+# the License.
 #
 # This 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
+# 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
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301  USA
 
 # Tests for PERFORMANCE_SCHEMA
 
 update performance_schema.setup_instruments set enabled='YES';
 
+connection con1;
 disconnect con1;
+--source include/wait_until_disconnected.inc
+connection con2;
 disconnect con2;
+--source include/wait_until_disconnected.inc
+connection con3;
 disconnect con3;
+--source include/wait_until_disconnected.inc
 
 connection default;
 

=== modified file 'mysql-test/suite/perfschema/include/upgrade_check.inc'
--- a/mysql-test/suite/perfschema/include/upgrade_check.inc	2010-09-13 23:19:39 +0000
+++ b/mysql-test/suite/perfschema/include/upgrade_check.inc	2011-06-16 20:35:01 +0000
@@ -17,8 +17,10 @@
 # $out_file and $err_file must be set within pfs_upgrade.test.
 #
 
+--source include/count_sessions.inc
 --error 1
 --exec $MYSQL_UPGRADE --skip-verbose --force > $out_file 2> $err_file
+--source include/wait_until_count_sessions.inc
 
 # Verify that mysql_upgrade complained about the performance_schema
 --cat_file $err_file

=== modified file 'mysql-test/suite/perfschema/r/selects.result'
--- a/mysql-test/suite/perfschema/r/selects.result	2010-11-03 15:42:33 +0000
+++ b/mysql-test/suite/perfschema/r/selects.result	2011-06-16 20:35:01 +0000
@@ -62,6 +62,7 @@ SELECT EVENT_ID FROM performance_schema.
 WHERE 1 = 2;
 CREATE EVENT t_ps_event
 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 SECOND
+ON COMPLETION PRESERVE
 DO INSERT INTO t_event
 SELECT DISTINCT EVENT_ID
 FROM performance_schema.events_waits_current
@@ -106,5 +107,6 @@ EVENT_ID
 [EVENT_ID]
 DROP PROCEDURE t_ps_proc;
 DROP FUNCTION t_ps_func;
+DROP EVENT t_ps_event;
 DROP TABLE t1;
 DROP TABLE t_event;

=== modified file 'mysql-test/suite/perfschema/t/selects.test'
--- a/mysql-test/suite/perfschema/t/selects.test	2010-11-03 15:42:33 +0000
+++ b/mysql-test/suite/perfschema/t/selects.test	2011-06-16 20:35:01 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 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
@@ -97,6 +97,7 @@ SELECT EVENT_ID FROM performance_schema.
 WHERE 1 = 2;
 CREATE EVENT t_ps_event
 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 SECOND
+ON COMPLETION PRESERVE
 DO INSERT INTO t_event
    SELECT DISTINCT EVENT_ID
    FROM performance_schema.events_waits_current
@@ -168,7 +169,7 @@ delimiter ;|
 SELECT t_ps_func(connection_id()) = @p_id;
 
 # We might reach this point too early which means the event scheduler has not
-# execute our "t_ps_event". Therefore we poll till the record was inserted
+# executed our "t_ps_event". Therefore we poll till the record was inserted
 # and run our test statement afterwards.
 let $wait_timeout= 20;
 let $wait_condition= SELECT COUNT(*) = 1 FROM t_event;
@@ -179,5 +180,6 @@ SELECT * FROM t_event;
 # Clean up
 DROP PROCEDURE t_ps_proc;
 DROP FUNCTION t_ps_func;
+DROP EVENT t_ps_event;
 DROP TABLE t1;
 DROP TABLE t_event;

=== modified file 'mysql-test/t/alter_table.test'
--- a/mysql-test/t/alter_table.test	2011-04-13 06:16:40 +0000
+++ b/mysql-test/t/alter_table.test	2011-06-16 22:50:07 +0000
@@ -1073,6 +1073,33 @@ ALTER TABLE t1 DROP COLUMN a, ADD COLUMN
 DROP TABLE t1;
 
 
+--echo #
+--echo # Test for bug #12652385 - "61493: REORDERING COLUMNS TO POSITION
+--echo #                           FIRST CAN CAUSE DATA TO BE CORRUPTED".
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+--echo # Use MyISAM engine as the fact that InnoDB doesn't support
+--echo # in-place ALTER TABLE in cases when columns are being renamed
+--echo # hides some bugs.
+create table t1 (i int, j int) engine=myisam;
+insert into t1 value (1, 2);
+--echo # First, test for original problem described in the bug report.
+select * from t1;
+--echo # Change of column order by the below ALTER TABLE statement should
+--echo # affect both column names and column contents.
+alter table t1 modify column j int first;
+select * from t1;
+--echo # Now test for similar problem with the same root.
+--echo # The below ALTER TABLE should change not only the name but
+--echo # also the value for the last column of the table.
+alter table t1 drop column i, add column k int default 0;
+select * from t1;
+--echo # Clean-up.
+drop table t1;
+
+
 --echo End of 5.1 tests
 
 #

=== added file 'mysql-test/t/archive_debug.test'
--- a/mysql-test/t/archive_debug.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/archive_debug.test	2011-05-18 10:01:43 +0000
@@ -0,0 +1,13 @@
+--source include/have_archive.inc
+--source include/have_debug.inc
+
+--echo #
+--echo # BUG#12402794 - 60976: CRASH, VALGRIND WARNING AND MEMORY LEAK
+--echo #                       WITH PARTITIONED ARCHIVE TABLES
+--echo #
+CREATE TABLE t1(a INT) ENGINE=ARCHIVE;
+INSERT INTO t1 VALUES(1);
+SET SESSION debug='d,simulate_archive_open_failure';
+CHECK TABLE t1;
+SET SESSION debug=DEFAULT;
+DROP TABLE t1;

=== modified file 'mysql-test/t/disabled.def'
--- a/mysql-test/t/disabled.def	2011-05-25 14:09:24 +0000
+++ b/mysql-test/t/disabled.def	2011-06-16 13:55:11 +0000
@@ -15,4 +15,4 @@ sum_distinct-big         : Bug#11764126
 alter_table-big          : Bug#11748731 2010-11-15 mattiasj was not tested
 create-big               : Bug#11748731 2010-11-15 mattiasj was not tested
 archive-big              : Bug#11817185 2011-03-10 Anitha Disabled since this leads to timeout on Solaris Sparc
-main.query_cache_28249   : Bug#12584161 2009-03-25 main.query_cache_28249 fails sporadically
+log_tables-big           : Bug#11756699 2010-11-15 mattiasj report already exists

=== modified file 'mysql-test/t/events_bugs.test'
--- a/mysql-test/t/events_bugs.test	2011-05-27 11:42:28 +0000
+++ b/mysql-test/t/events_bugs.test	2011-06-09 18:08:38 +0000
@@ -1286,6 +1286,23 @@ DROP EVENT IF EXISTS event_Bug12546938;
 DROP TABLE table_bug12546938;
 SET GLOBAL EVENT_SCHEDULER = OFF;
 
+#
+# Bug#11764334 - 57156: ALTER EVENT CHANGES THE EVENT STATUS
+#
+--disable_warnings
+DROP DATABASE IF EXISTS event_test11764334;
+--enable_warnings
+CREATE DATABASE event_test11764334;
+USE event_test11764334;
+CREATE EVENT ev1 ON SCHEDULE EVERY 3 SECOND DISABLE DO SELECT 1;
+--replace_column 9 # 10 #
+SHOW EVENTS IN event_test11764334 WHERE NAME='ev1';
+ALTER EVENT ev1 ON SCHEDULE EVERY 4 SECOND;
+--replace_column 9 # 10 #
+SHOW EVENTS IN event_test11764334 WHERE NAME='ev1';
+DROP EVENT ev1;
+DROP DATABASE event_test11764334;
+USE test; 
 ###########################################################################
 #
 # End of tests

=== modified file 'mysql-test/t/flush.test'
--- a/mysql-test/t/flush.test	2011-03-07 09:08:10 +0000
+++ b/mysql-test/t/flush.test	2011-06-16 15:18:16 +0000
@@ -668,3 +668,36 @@ ALTER TABLE t1 COMMENT 'test';
 
 UNLOCK TABLES;
 DROP TABLE t1;
+
+
+--echo #
+--echo # Test for bug #12641342 - "61401: UPDATE PERFORMANCE DEGRADES
+--echo #                           GRADUALLY IF A TRIGGER EXISTS".
+--echo #
+--echo # One of side-effects of this bug was that a transaction which
+--echo # involved DML statements requiring prelocking blocked concurrent
+--echo # FLUSH TABLES WITH READ LOCK for the whole its duration, while
+--echo # correct behavior in this case is to block FTWRL only for duration
+--echo # of individual DML statements.
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+CREATE TABLE t1 (id INT PRIMARY KEY, value INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW SET @var = "a";
+BEGIN;
+UPDATE t1 SET value= value + 1 WHERE id = 1;
+
+--echo # Switching to connection 'con1'.
+connect(con1, localhost, root);
+--echo # The below FLUSH TABLES WITH READ LOCK should succeed and
+--echo # should not be blocked by the transaction in default connection.
+FLUSH TABLES WITH READ LOCK;
+UNLOCK TABLES;
+disconnect con1;
+--source include/wait_until_disconnected.inc
+
+--echo # Switching to connection 'default'.
+connection default;
+COMMIT;
+DROP TABLE t1;

=== modified file 'mysql-test/t/gis-rtree.test'
--- a/mysql-test/t/gis-rtree.test	2010-03-25 11:49:01 +0000
+++ b/mysql-test/t/gis-rtree.test	2011-06-07 15:30:43 +0000
@@ -928,3 +928,31 @@ DROP TABLE t1;
 
 
 --echo End of 5.0 tests.
+
+
+--echo #
+--echo # Bug #57323/11764487: myisam corruption with insert ignore 
+--echo # and invalid spatial data
+--echo #
+
+CREATE TABLE t1(a LINESTRING NOT NULL, b GEOMETRY NOT NULL,
+  SPATIAL KEY(a), SPATIAL KEY(b)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(GEOMFROMTEXT("point (0 0)"), GEOMFROMTEXT("point (1 1)"));
+--error ER_CANT_CREATE_GEOMETRY_OBJECT
+INSERT IGNORE INTO t1 SET a=GEOMFROMTEXT("point (-6 0)"), b=GEOMFROMTEXT("error");
+--error ER_CANT_CREATE_GEOMETRY_OBJECT
+INSERT IGNORE INTO t1 SET a=GEOMFROMTEXT("point (-6 0)"), b=NULL;
+SELECT ASTEXT(a), ASTEXT(b) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1(a INT NOT NULL, b GEOMETRY NOT NULL,
+  KEY(a), SPATIAL KEY(b)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(0, GEOMFROMTEXT("point (1 1)"));
+--error ER_CANT_CREATE_GEOMETRY_OBJECT
+INSERT IGNORE INTO t1 SET a=0, b=GEOMFROMTEXT("error");
+--error ER_CANT_CREATE_GEOMETRY_OBJECT
+INSERT IGNORE INTO t1 SET a=1, b=NULL;
+SELECT a, ASTEXT(b) FROM t1;
+DROP TABLE t1;
+
+--echo End of 5.1 tests

=== modified file 'mysql-test/t/multi_update.test'
--- a/mysql-test/t/multi_update.test	2011-03-08 17:39:25 +0000
+++ b/mysql-test/t/multi_update.test	2011-06-16 06:24:00 +0000
@@ -703,4 +703,50 @@ UPDATE t1 AS A, t1 AS B SET A.pk = 1, B.
 SELECT * FROM t1;
 DROP TABLE t1;
 
---echo end of tests
+--echo #
+--echo # BUG#11882110: UPDATE REPORTS ER_KEY_NOT_FOUND IF TABLE IS 
+--echo #               UPDATED TWICE
+--echo #
+
+# Results differ between storage engines. This test is to verify that
+# the bugfix did NOT change behavior for MyISAM.
+# See multi_update_innodb.test for the InnoDB variant of this test
+CREATE TABLE t1 ( 
+  col_int_key int, 
+  pk int, 
+  col_int int, 
+  key(col_int_key), 
+  primary key (pk)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,2,3);
+
+--echo
+CREATE TABLE t2 ( 
+  col_int_key int, 
+  pk_1 int, 
+  pk_2 int, 
+  col_int int, 
+  key(col_int_key), 
+  primary key (pk_1,pk_2)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,2,3,4);
+
+--echo
+UPDATE t1 AS A NATURAL JOIN t1 B SET A.pk=5,B.pk=7;
+
+--echo
+SELECT * FROM t1;
+
+--echo
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_1=5,B.pk_1=7;
+--echo
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_2=10,B.pk_2=11;
+
+--echo
+SELECT * FROM t2;
+
+DROP TABLE t1,t2;
+
+
+
+

=== modified file 'mysql-test/t/multi_update_innodb.test'
--- a/mysql-test/t/multi_update_innodb.test	2011-02-21 15:49:03 +0000
+++ b/mysql-test/t/multi_update_innodb.test	2011-06-16 06:24:00 +0000
@@ -31,3 +31,47 @@ SELECT * FROM t1;
 DROP VIEW v1;
 DROP TABLE t1;
 
+--echo #
+--echo # BUG#11882110: UPDATE REPORTS ER_KEY_NOT_FOUND IF TABLE IS 
+--echo #               UPDATED TWICE
+--echo #
+
+# Results differ between storage engines.
+# See multi_update.test for the MyISAM variant of this test
+CREATE TABLE t1 ( 
+  col_int_key int, 
+  pk int, 
+  col_int int, 
+  key(col_int_key), 
+  primary key (pk)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1,2,3);
+
+--echo
+CREATE TABLE t2 ( 
+  col_int_key int, 
+  pk_1 int, 
+  pk_2 int, 
+  col_int int, 
+  key(col_int_key), 
+  primary key (pk_1,pk_2)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1,2,3,4);
+
+--echo
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE t1 AS A NATURAL JOIN t1 B SET A.pk=5,B.pk=7;
+--echo
+SELECT * FROM t1;
+
+--echo
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_1=5,B.pk_1=7;
+--echo
+--error ER_MULTI_UPDATE_KEY_CONFLICT
+UPDATE t2 AS A NATURAL JOIN t2 B SET A.pk_2=10,B.pk_2=11;
+
+--echo
+SELECT * FROM t2;
+
+DROP TABLE t1,t2;

=== added file 'mysql-test/t/mysql_embedded.test'
--- a/mysql-test/t/mysql_embedded.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/mysql_embedded.test	2011-06-16 13:55:11 +0000
@@ -0,0 +1,12 @@
+--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'

=== added file 'mysql-test/t/mysql_plugin-master.opt'
--- a/mysql-test/t/mysql_plugin-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/mysql_plugin-master.opt	2011-06-14 20:00:51 +0000
@@ -0,0 +1 @@
+--plugin-dir=$DAEMONEXAMPLE_DIR

=== added file 'mysql-test/t/mysql_plugin.test'
--- a/mysql-test/t/mysql_plugin.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/mysql_plugin.test	2011-06-30 12:12:58 +0000
@@ -0,0 +1,205 @@
+#
+# Test mysql_plugin tool
+#
+
+#
+# Test currently does not run on Windows because in Windows build trees,
+# mysqld.exe is not placed in the ./sql folder - it is placed either
+# in ./sql/Debug or ./sql/release. If this behaviour is changed, this test
+# can run on Windows.
+#
+--source include/not_windows.inc
+
+# Add the datadir, basedir, plugin_dir to the bootstrap command
+let $MYSQLD_DATADIR= `select @@datadir`;
+let $MYSQLD_BASEDIR= `select @@basedir`;
+let $MYSQLD_BOOTSTRAP_CMD= $MYSQL_PLUGIN --datadir=$MYSQLD_DATADIR --basedir=$MYSQLD_BASEDIR/sql --plugin-dir=$DAEMONEXAMPLE_DIR;
+
+--echo #
+--echo # Ensure the plugin isn't loaded.
+--echo #
+SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name;
+
+--echo #
+--echo # Enable the plugin...
+--echo #
+let $expect_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect;
+# MTR will remove this file later, but this might be too late.
+--error 0,1
+--remove_file $expect_file
+--write_file $expect_file
+wait
+EOF
+--shutdown_server 10
+--source include/wait_until_disconnected.inc
+
+#
+# Enable the plugin
+#
+--exec $MYSQLD_BOOTSTRAP_CMD ENABLE daemon_example
+
+#
+# Ensure enabling an enabled plugin doesn't fail
+--exec $MYSQLD_BOOTSTRAP_CMD ENABLE daemon_example
+
+#
+# Restart the server
+#
+--append_file $expect_file
+restart
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--echo #
+--echo # Ensure the plugin is now loaded.
+--echo #
+--replace_regex /\.dll/.so/
+SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name;
+
+--echo #
+--echo # Disable the plugin...
+--echo #
+# MTR will remove this file later, but this might be too late.
+--error 0,1
+--remove_file $expect_file
+--write_file $expect_file
+wait
+EOF
+--shutdown_server 10
+--source include/wait_until_disconnected.inc
+
+#
+# Disable the plugin
+#
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE daemon_example
+
+#
+# Restart the server
+#
+--append_file $expect_file
+restart
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--echo #
+--echo # Ensure the plugin isn't loaded.
+--echo #
+SELECT * FROM mysql.plugin WHERE name = 'daemon_example' ORDER BY name;
+
+#
+# Stop the server for error conditions
+#
+let $expect_file= $MYSQLTEST_VARDIR/tmp/mysqld.1.expect;
+# MTR will remove this file later, but this might be too late.
+--error 0,1
+--remove_file $expect_file
+--write_file $expect_file
+wait
+EOF
+--shutdown_server 10
+--source include/wait_until_disconnected.inc
+
+--echo #
+--echo # Attempt to load non-existant plugin
+--echo #
+--error 1,2,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE NOT_THERE_AT_ALL 2>&1
+
+--echo #
+--echo # Attempt to use non-existant plugin.ini file
+--echo #
+--error 1,2,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE daemon_example --plugin-ini=/NOT/THERE/pi.ini 2>&1
+
+--echo # 
+--echo # Attempt to omit the plugin
+--echo #
+--error 1,2,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE 2>&1
+
+--echo # 
+--echo # Attempt to omit DISABLE|ENABLE
+--echo #
+--error 1,2,256
+--exec $MYSQLD_BOOTSTRAP_CMD daemon_example 2>&1
+
+--echo # 
+--echo # Attempt to use bad paths - datadir
+--echo #
+let $MYSQLD_BOOTSTRAP_CMD= $MYSQL_PLUGIN -n --datadir=/data_not_there/ --basedir=$MYSQLD_BASEDIR/sql --plugin-dir=$DAEMONEXAMPLE_DIR;
+--error 1,2,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE daemon_example 2>&1
+
+--echo # 
+--echo # Attempt to use bad paths - basedir
+--echo #
+let $MYSQLD_BOOTSTRAP_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=/basedir_not_there/ --plugin-dir=$DAEMONEXAMPLE_DIR;
+--error 1,2,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE daemon_example 2>&1
+
+--echo # 
+--echo # Attempt to use bad paths - plugin_dir
+--echo #
+let $MYSQLD_BOOTSTRAP_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=$MYSQLD_BASEDIR/sql --plugin-dir=/plugin_not_there/;
+--error 1,2,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE daemon_example 2>&1
+
+--echo # 
+--echo # Missing library
+--echo #
+let $MYSQLD_BOOTSTRAP_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=$MYSQLD_BASEDIR/sql --plugin-dir=$DAEMONEXAMPLE_DIR --plugin-ini=$MYSQL_TEST_DIR/include/daemon_example_bad_soname.ini;
+--error 1,2,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE daemon_example 2>&1
+
+--echo # 
+--echo # Bad format for config file
+--echo #
+let $MYSQLD_BOOTSTRAP_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=$MYSQLD_BASEDIR/sql --plugin-dir=$DAEMONEXAMPLE_DIR --plugin-ini=$MYSQL_TEST_DIR/include/daemon_example_bad_format.ini;
+--error 1,2,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE daemon_example 2>&1
+
+--echo # 
+--echo # Missing base_dir option
+--echo #
+let $MYSQLD_BOOTSTRAP_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --plugin-dir=$DAEMONEXAMPLE_DIR;
+--error 1,2,139,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE daemon_example 2>&1
+
+--echo # 
+--echo # Missing data_dir option
+--echo #
+let $MYSQLD_BOOTSTRAP_CMD= $MYSQL_PLUGIN -n --basedir=$MYSQLD_BASEDIR/sql --plugin-dir=$DAEMONEXAMPLE_DIR;
+--error 1,2,139,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE daemon_example 2>&1
+
+--echo # 
+--echo # Missing plugin_dir option
+--echo #
+let $MYSQLD_BOOTSTRAP_CMD= $MYSQL_PLUGIN -n --datadir=$MYSQLD_DATADIR --basedir=$MYSQLD_BASEDIR/sql;
+--error 1,2,139,256
+--exec $MYSQLD_BOOTSTRAP_CMD DISABLE daemon_example 2>&1
+
+--echo #
+--echo # Show the help.
+--echo #
+replace_result $MYSQL_PLUGIN mysql_plugin;
+--replace_regex /Distrib [0-9.]+/Distrib XX.XX.XX/
+--exec $MYSQL_PLUGIN --help
+
+#
+# Restart the server
+#
+--append_file $expect_file
+restart
+EOF
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+#
+# Cleanup
+# MTR will remove this file later, but this might be too late.
+--error 0,1
+--remove_file $expect_file
+

=== modified file 'mysql-test/t/partition.test'
--- a/mysql-test/t/partition.test	2011-03-11 09:12:58 +0000
+++ b/mysql-test/t/partition.test	2011-06-13 09:57:47 +0000
@@ -15,6 +15,37 @@ drop table if exists t1, t2;
 --enable_warnings
 
 --echo #
+--echo # Bug#11765667: bug#58655: ASSERTION FAILED,
+--echo #                          SERVER CRASHES WITH MYSQLD GOT SIGNAL 6
+--echo #
+CREATE TABLE t1 (
+       id MEDIUMINT NOT NULL AUTO_INCREMENT,
+       dt DATE, st VARCHAR(255), uid INT,
+       id2nd LONGBLOB, filler VARCHAR(255), PRIMARY KEY(id, dt)
+);
+INSERT INTO t1 (dt, st, uid, id2nd, filler) VALUES
+   ('1991-03-14', 'Initial Insert', 200, 1234567, 'No Data'),
+   ('1991-02-26', 'Initial Insert', 201, 1234567, 'No Data'),
+   ('1992-03-16', 'Initial Insert', 234, 1234567, 'No Data'),
+   ('1992-07-02', 'Initial Insert', 287, 1234567, 'No Data'),
+   ('1991-05-26', 'Initial Insert', 256, 1234567, 'No Data'),
+   ('1991-04-25', 'Initial Insert', 222, 1234567, 'No Data'),
+   ('1993-03-12', 'Initial Insert', 267, 1234567, 'No Data'),
+   ('1993-03-14', 'Initial Insert', 291, 1234567, 'No Data'),
+   ('1991-12-20', 'Initial Insert', 298, 1234567, 'No Data'),
+   ('1994-10-31', 'Initial Insert', 220, 1234567, 'No Data');
+ALTER TABLE t1 PARTITION BY LIST (YEAR(dt)) (
+    PARTITION d1 VALUES IN (1991, 1994),
+    PARTITION d2 VALUES IN (1993),
+    PARTITION d3 VALUES IN (1992, 1995, 1996)
+);
+INSERT INTO t1 (dt, st, uid, id2nd, filler) VALUES
+   ('1991-07-14', 'After Partitioning Insert', 299, 1234567, 'Insert row');
+UPDATE t1 SET filler='Updating the row' WHERE uid=298;
+
+DROP TABLE t1;
+
+--echo #
 --echo # Bug#59297: Can't find record in 'tablename' on update inner join
 --echo #
 
@@ -196,10 +227,16 @@ INSERT INTO t1 VALUES ('2009-07-14 17:35
 INSERT INTO t1 VALUES ('2009-09-21 17:31:42', 'pmax');
 
 SELECT * FROM t1;
+SELECT * FROM t1 where a between '2007-01-01' and '2007-08-01';
+EXPLAIN PARTITIONS SELECT * FROM t1 where a between '2007-01-01' and '2007-08-01';
+EXPLAIN PARTITIONS SELECT * FROM t1 where a = '2007-07-30 17:35:48';
 ALTER TABLE t1 REORGANIZE PARTITION pmax INTO (
  PARTITION p3 VALUES LESS THAN (1247688000),
  PARTITION pmax VALUES LESS THAN MAXVALUE);
 SELECT * FROM t1;
+SELECT * FROM t1 where a between '2007-01-01' and '2007-08-01';
+EXPLAIN PARTITIONS SELECT * FROM t1 where a between '2007-01-01' and '2007-08-01';
+EXPLAIN PARTITIONS SELECT * FROM t1 where a = '2007-07-30 17:35:48';
 SHOW CREATE TABLE t1;
 DROP TABLE t1;
 

=== modified file 'mysql-test/t/partition_datatype.test'
--- a/mysql-test/t/partition_datatype.test	2009-10-28 00:11:17 +0000
+++ b/mysql-test/t/partition_datatype.test	2011-06-13 09:57:47 +0000
@@ -7,6 +7,7 @@
 # BUG#48164 limited size to 3072 bytes
 #
 -- source include/have_partition.inc
+-- source include/have_innodb.inc
 
 --disable_warnings
 drop table if exists t1;
@@ -233,3 +234,312 @@ show create table t1;
 insert into t1 values (1),(4),(7),(10),(13),(16),(19),(22),(25),(28),(31),(34);
 select hex(a) from t1 where a = 7;
 drop table t1;
+
+--echo #
+--echo # Bug#28928: UNIX_TIMESTAMP() should be considered unary monotonic
+--echo #            by partition pruning
+SET @old_time_zone= @@session.time_zone;
+SET @@session.time_zone = 'UTC';
+--echo # Using MyISAM to get stable values on TABLE_ROWS in I_S.PARTITIONS
+CREATE TABLE t1
+(a TIMESTAMP NULL,
+ tz varchar(16))
+ENGINE = MyISAM;
+CREATE TABLE t2 LIKE t1;
+ALTER TABLE t2 PARTITION BY RANGE (UNIX_TIMESTAMP(a))
+(PARTITION `p0` VALUES LESS THAN (0),
+ PARTITION `p-2000` VALUES LESS THAN (UNIX_TIMESTAMP('2000-01-01')),
+ PARTITION `p-2011-MSK` VALUES LESS THAN (UNIX_TIMESTAMP('2011-03-26 23:00:00')),
+ PARTITION `p-2011-MSD-1` VALUES LESS THAN (UNIX_TIMESTAMP('2011-10-29 22:00:00')),
+ PARTITION `p-2011-MSD-2` VALUES LESS THAN (UNIX_TIMESTAMP('2011-10-29 23:00:00')),
+ PARTITION `p-2012-MSK-1` VALUES LESS THAN (UNIX_TIMESTAMP('2011-10-30 00:00:00')),
+ PARTITION `p-2012-MSK-2` VALUES LESS THAN (UNIX_TIMESTAMP('2012-03-24 23:00:00')),
+ PARTITION `pEnd` VALUES LESS THAN (UNIX_TIMESTAMP('2038-01-19 03:14:07')),
+ PARTITION `pMax` VALUES LESS THAN MAXVALUE);
+
+
+--echo # Test 'odd' values
+INSERT INTO t1 VALUES (NULL, 'UTC');
+INSERT INTO t1 VALUES ('0000-00-00 00:00:00', 'UTC');
+--echo # Test invalid values
+INSERT INTO t1 VALUES ('1901-01-01 00:00:00', 'UTCI');
+INSERT INTO t1 VALUES ('1969-12-31 23:59:59', 'UTCI');
+INSERT INTO t1 VALUES ('2038-01-19 03:14:08', 'UTCI');
+INSERT INTO t1 VALUES ('1970-01-01 00:00:00', 'UTCI');
+--echo # Test start range
+INSERT INTO t1 VALUES ('1970-01-01 00:00:01', 'UTC');
+INSERT INTO t1 VALUES ('1974-02-05 21:28:16', 'UTC');
+--echo # Test end range
+INSERT INTO t1 VALUES ('2038-01-19 03:14:06', 'UTC');
+INSERT INTO t1 VALUES ('2038-01-19 03:14:07', 'UTC');
+--echo # Test Daylight saving shift
+INSERT INTO t1 VALUES ('2011-03-26 22:59:59', 'UTC');
+INSERT INTO t1 VALUES ('2011-03-26 23:00:00', 'UTC');
+INSERT INTO t1 VALUES ('2011-03-26 23:00:01', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 21:59:59', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 22:00:00', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 22:00:01', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 22:59:59', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 23:00:00', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 23:00:01', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-29 23:59:59', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-30 00:00:00', 'UTC');
+INSERT INTO t1 VALUES ('2011-10-30 00:00:01', 'UTC');
+
+SET @@session.time_zone = 'Europe/Moscow';
+
+--echo # Test 'odd' values
+INSERT INTO t1 VALUES (NULL, 'Moscow');
+INSERT INTO t1 VALUES ('0000-00-00 00:00:00', 'Moscow');
+--echo # Test invalid values
+INSERT INTO t1 VALUES ('0000-00-00 03:00:00', 'MoscowI');
+INSERT INTO t1 VALUES ('1901-01-01 00:00:00', 'MoscowI');
+INSERT INTO t1 VALUES ('1969-12-31 23:59:59', 'MoscowI');
+INSERT INTO t1 VALUES ('1970-01-01 02:29:29', 'MoscowI');
+INSERT INTO t1 VALUES ('2038-01-19 06:14:08', 'MoscowI');
+INSERT INTO t1 VALUES ('1970-01-01 03:00:00', 'MoscowI');
+--echo # values truncated to 03:00:00 due to daylight saving shift
+INSERT INTO t1 VALUES ('2011-03-27 02:00:00', 'MoscowI');
+INSERT INTO t1 VALUES ('2011-03-27 02:00:01', 'MoscowI');
+INSERT INTO t1 VALUES ('2011-03-27 02:59:59', 'MoscowI');
+--echo # Test start range
+INSERT INTO t1 VALUES ('1970-01-01 03:00:01', 'Moscow');
+INSERT INTO t1 VALUES ('1974-02-05 21:28:16', 'Moscow');
+--echo # Test end range
+INSERT INTO t1 VALUES ('2038-01-19 06:14:06', 'Moscow');
+INSERT INTO t1 VALUES ('2038-01-19 06:14:07', 'Moscow');
+--echo # Test Daylight saving shift
+INSERT INTO t1 VALUES ('2011-03-27 01:59:59', 'Moscow');
+INSERT INTO t1 VALUES ('2011-03-27 03:00:00', 'Moscow');
+INSERT INTO t1 VALUES ('2011-03-27 03:00:01', 'Moscow');
+INSERT INTO t1 VALUES ('2011-10-30 01:59:59', 'Moscow');
+--echo # All values between 02:00 and 02:59:59 will be interpretated as DST
+INSERT INTO t1 VALUES ('2011-10-30 02:00:00', 'MoscowD');
+INSERT INTO t1 VALUES ('2011-10-30 02:00:01', 'MoscowD');
+INSERT INTO t1 VALUES ('2011-10-30 02:59:59', 'MoscowD');
+INSERT INTO t1 VALUES ('2011-10-30 03:00:00', 'Moscow');
+INSERT INTO t1 VALUES ('2011-10-30 03:00:01', 'Moscow');
+
+
+SET @@session.time_zone = 'UTC';
+
+INSERT INTO t2 SELECT * FROM t1;
+
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+
+SELECT * FROM t1 ORDER BY a, tz;
+SELECT * FROM t2 ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-26 23:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-26 23:00:00' ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-26 22:59:59' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-26 22:59:59' ORDER BY a, tz;
+
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 22:59:59' and '2011-03-28 00:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 22:59:59' and '2011-03-28 00:00:00' ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 23:00:00' and '2011-03-28 00:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 23:00:00' and '2011-03-28 00:00:00' ORDER BY a, tz;
+
+
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 23:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 23:00:00' ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 22:59:59' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 22:59:59' ORDER BY a, tz;
+
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 22:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 22:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 23:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 23:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+
+
+--echo # Test end range changes
+DELETE FROM t2 WHERE a = 0;
+INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'UTC');
+SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+SELECT * FROM t2 ORDER BY a, tz LIMIT 3;
+SELECT * FROM t2 ORDER BY a DESC, tz LIMIT 3;
+UPDATE t2 SET a = TIMESTAMPADD(SECOND, 1, a);
+SELECT MIN(a), MAX(a) FROM t2;
+SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+SELECT * FROM t2 ORDER BY a, tz;
+
+--echo # Test start range changes
+INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'UTC');
+SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+SELECT * FROM t2 ORDER BY a, tz LIMIT 3;
+SELECT * FROM t2 ORDER BY a DESC, tz LIMIT 3;
+UPDATE t2 SET a = TIMESTAMPADD(SECOND, -1, a);
+SELECT MIN(a), MAX(a) FROM t2;
+SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+SELECT * FROM t2 ORDER BY a, tz;
+
+SHOW CREATE TABLE t2;
+TRUNCATE TABLE t2;
+
+SET @@session.time_zone = 'Europe/Moscow';
+
+INSERT INTO t2 SELECT * FROM t1;
+
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+
+SELECT * FROM t1 ORDER BY a, tz;
+SELECT * FROM t2 ORDER BY a, tz;
+
+--echo # Testing the leap from 01:59:59 to 03:00:00
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-27 03:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-27 03:00:00' ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-27 01:59:59' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-01 00:00:00' and '2011-03-27 01:59:59' ORDER BY a, tz;
+
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 01:59:59' and '2011-03-28 00:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 01:59:59' and '2011-03-28 00:00:00' ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 03:00:00' and '2011-03-28 00:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-03-26 03:00:00' and '2011-03-28 00:00:00' ORDER BY a, tz;
+
+
+
+--echo # Testing the leap from 02:59:59 to 02:00:00
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 02:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 02:00:00' ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 02:59:59' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 02:59:59' ORDER BY a, tz;
+
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 03:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 03:00:00' ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 01:59:59' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-01 00:00:00' and '2011-10-29 01:59:59' ORDER BY a, tz;
+
+
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 02:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 02:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 02:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 02:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 03:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 03:00:00' and '2011-10-31 00:00:00' ORDER BY a, tz;
+
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 01:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+EXPLAIN PARTITIONS
+SELECT * FROM t2
+WHERE a BETWEEN '2011-10-29 01:59:59' and '2011-10-31 00:00:00' ORDER BY a, tz;
+
+
+
+--echo # Test end range changes
+DELETE FROM t2 WHERE a = 0;
+INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'Moscow');
+SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+SELECT * FROM t2 ORDER BY a, tz LIMIT 3;
+SELECT * FROM t2 ORDER BY a DESC, tz LIMIT 3;
+UPDATE t2 SET a = TIMESTAMPADD(SECOND, 1, a);
+SELECT MIN(a), MAX(a) FROM t2;
+SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+SELECT * FROM t2 ORDER BY a, tz;
+
+--echo # Test start range changes
+INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'Moscow');
+SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+SELECT * FROM t2 ORDER BY a, tz LIMIT 3;
+SELECT * FROM t2 ORDER BY a DESC, tz LIMIT 3;
+UPDATE t2 SET a = TIMESTAMPADD(SECOND, -1, a);
+SELECT MIN(a), MAX(a) FROM t2;
+SELECT COUNT(*) FROM t2;
+SELECT COUNT(*) FROM t2 WHERE a = 0;
+SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS
+WHERE TABLE_NAME = 't2';
+SELECT * FROM t2 ORDER BY a, tz;
+
+SHOW CREATE TABLE t2;
+TRUNCATE TABLE t2;
+
+DROP TABLE t1, t2;
+SET @@session.time_zone= @old_time_zone;

=== modified file 'mysql-test/t/query_cache_28249.test'
--- a/mysql-test/t/query_cache_28249.test	2010-08-06 11:29:37 +0000
+++ b/mysql-test/t/query_cache_28249.test	2011-06-10 09:40:57 +0000
@@ -30,7 +30,7 @@ connection user1;
 SET GLOBAL query_cache_type=1;
 SET GLOBAL query_cache_limit=10000;
 SET GLOBAL query_cache_min_res_unit=0;
-SET GLOBAL query_cache_size= 100000;
+SET GLOBAL query_cache_size= 102400;
 
 FLUSH TABLES;
 --disable_warnings
@@ -58,18 +58,18 @@ connection user3;
 # Typical information_schema.processlist content after sufficient sleep time
 #   ID  USER  COMMAND  TIME  STATE   INFO
 #   ....
-#   2   root  Query       5  Waiting for table level lock  SELECT *, (SELECT COUNT(*) FROM t2) FROM t1
+#   2   root  Query       5  Waiting for table metadata lock  SELECT *, (SELECT COUNT(*) FROM t2) FROM t1
 #   ....
 #                            XXXXXX  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 # The values marked with 'X' must be reached.
 --echo # Poll till the select of connection user1 is blocked by the write lock on t1.
 let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist
-WHERE state = 'Waiting for table level lock'
+WHERE state = 'Waiting for table metadata lock'
   AND info = '$select_for_qc';
 --source include/wait_condition.inc
 eval
 SELECT user,command,state,info FROM information_schema.processlist
-WHERE state = 'Waiting for table level lock'
+WHERE state = 'Waiting for table metadata lock'
   AND info = '$select_for_qc';
 INSERT INTO t1 VALUES (4);
 

=== modified file 'mysql-test/t/sp_notembedded.test'
--- a/mysql-test/t/sp_notembedded.test	2010-08-06 11:29:37 +0000
+++ b/mysql-test/t/sp_notembedded.test	2011-06-08 13:44:50 +0000
@@ -371,16 +371,6 @@ DELETE FROM mysql.user WHERE User='mysql
 FLUSH PRIVILEGES;
 
 
-#
-# Restore global concurrent_insert value. Keep in the end of the test file.
-#
-
-set @@global.concurrent_insert= @old_concurrent_insert;
-
-# Wait till all disconnects are completed
---source include/wait_until_count_sessions.inc
-
-
 --echo #
 --echo # Bug#44521 Prepared Statement: CALL p() - crashes: `! thd->main_da.is_sent' failed et.al.
 --echo #
@@ -449,7 +439,47 @@ DROP FUNCTION f1;
 --disconnect con1
 --disconnect con2
 
-
 --echo # ------------------------------------------------------------------
 --echo # -- End of 5.1 tests
 --echo # ------------------------------------------------------------------
+
+--echo #
+--echo # Test for bug#11763757 "56510: ERROR 42000: FUNCTION DOES NOT EXIST
+--echo # IF NOT-PRIV USER RECONNECTS ".
+--echo #
+--echo # The real problem was that server was unable handle properly stored
+--echo # functions in databases which names contained dot.
+--echo #
+
+connection default;
+
+--disable_warnings
+DROP DATABASE IF EXISTS `my.db`;
+--enable_warnings
+
+create database `my.db`;
+use `my.db`;
+
+CREATE FUNCTION f1(a int) RETURNS INT RETURN a;
+
+--echo # Create new connection.
+connect (addcon, localhost, root,,);
+connection addcon;
+USE `my.db`;
+SELECT f1(1);
+SELECT `my.db`.f1(2);
+
+--echo # Switching to default connection.
+connection default;
+disconnect addcon;
+DROP DATABASE `my.db`;
+
+#
+# Restore global concurrent_insert value. Keep in the end of the test file.
+#
+
+set @@global.concurrent_insert= @old_concurrent_insert;
+
+# Wait till all disconnects are completed
+--source include/wait_until_count_sessions.inc
+

=== modified file 'mysql-test/t/symlink.test'
--- a/mysql-test/t/symlink.test	2011-01-31 09:34:39 +0000
+++ b/mysql-test/t/symlink.test	2011-06-09 12:54:12 +0000
@@ -277,3 +277,24 @@ SELECT * FROM mysql.user;
 --remove_file $MYSQL_TMP_DIR/mysql
 
 --echo End of 5.1 tests
+
+
+--echo #
+--echo # Test for bug #11759990 - "52354: 'CREATE TABLE .. LIKE ... '
+--echo #                           STATEMENTS FAIL".
+--echo #
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval create table t1 (a int primary key) engine=myisam
+      data directory="$MYSQLTEST_VARDIR/tmp"
+      index directory="$MYSQLTEST_VARDIR/run";
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+show create table t1;
+--echo # CREATE TABLE LIKE statement on table with INDEX/DATA DIRECTORY
+--echo # options should not fail. Per documentation newly created table
+--echo # should not inherit value of these options from the original table.
+create table t2 like t1;
+show create table t2;
+drop tables t1, t2;

=== modified file 'mysql-test/t/trigger-compat.test'
--- a/mysql-test/t/trigger-compat.test	2009-02-19 23:24:25 +0000
+++ b/mysql-test/t/trigger-compat.test	2011-06-10 07:20:15 +0000
@@ -106,4 +106,184 @@ DROP TABLE t2;
 DROP USER mysqltest_dfn@localhost;
 DROP USER mysqltest_inv@localhost;
 DROP DATABASE mysqltest_db1;
+USE test;
 
+
+--echo #
+--echo # Bug#45235: 5.1 does not support 5.0-only syntax triggers in any way
+--echo #
+let $MYSQLD_DATADIR=`SELECT @@datadir`;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2, t3;
+--enable_warnings
+
+CREATE TABLE t1 ( a INT );
+CREATE TABLE t2 ( a INT );
+CREATE TABLE t3 ( a INT );
+INSERT INTO t1 VALUES (1), (2), (3);
+INSERT INTO t2 VALUES (1), (2), (3);
+INSERT INTO t3 VALUES (1), (2), (3);
+
+--echo # We simulate importing a trigger from 5.0 by writing a .TRN file for
+--echo # each trigger plus a .TRG file the way MySQL 5.0 would have done it, 
+--echo # with syntax allowed in 5.0 only.
+--echo #
+--echo # Note that in 5.0 the following lines are missing from t1.TRG:
+--echo #
+--echo # client_cs_names='latin1'
+--echo # connection_cl_names='latin1_swedish_ci'
+--echo # db_cl_names='latin1_swedish_ci'
+
+--write_file $MYSQLD_DATADIR/test/tr11.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/tr12.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/tr13.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/tr14.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/tr15.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/t1.TRG
+TYPE=TRIGGERS
+triggers='CREATE DEFINER=`root`@`localhost` TRIGGER tr11 BEFORE INSERT ON t1 FOR EACH ROW DELETE FROM t3' 'CREATE DEFINER=`root`@`localhost` TRIGGER tr12 AFTER INSERT ON t1 FOR EACH ROW DELETE FROM t3' 'CREATE DEFINER=`root`@`localhost` TRIGGER tr13 BEFORE DELETE ON t1 FOR EACH ROW DELETE FROM t1 a USING t1 a' 'CREATE DEFINER=`root`@`localhost` TRIGGER tr14 AFTER DELETE ON t1 FOR EACH ROW DELETE FROM non_existing_table' 'CREATE DEFINER=`root`@`localhost` TRIGGER tr15 BEFORE UPDATE ON t1 FOR EACH ROW DELETE FROM non_existing_table a USING non_existing_table a'
+sql_modes=0 0 0 0 0
+definers='root@localhost' 'root@localhost' 'root@localhost' 'root@localhost' 'root@localhost'
+EOF
+
+--write_file $MYSQLD_DATADIR/test/t2.TRG
+TYPE=TRIGGERS
+triggers='Not allowed syntax here, and trigger name cant be extracted either.'
+sql_modes=0
+definers='root@localhost'
+EOF
+
+FLUSH TABLE t1;
+FLUSH TABLE t2;
+
+--echo # We will get parse errors for most DDL and DML statements when the table
+--echo # has broken triggers. The parse error refers to the first broken 
+--echo # trigger.
+--error ER_PARSE_ERROR
+CREATE TRIGGER tr16 AFTER UPDATE ON t1 FOR EACH ROW INSERT INTO t1 VALUES (1);
+--error ER_PARSE_ERROR
+CREATE TRIGGER tr22 BEFORE INSERT ON t2 FOR EACH ROW DELETE FROM non_existing_table;
+SHOW TRIGGERS;
+--error ER_PARSE_ERROR
+INSERT INTO t1 VALUES (1);
+--error ER_PARSE_ERROR
+INSERT INTO t2 VALUES (1);
+--error ER_PARSE_ERROR
+DELETE FROM t1;
+--error ER_PARSE_ERROR
+UPDATE t1 SET a = 1 WHERE a = 1;
+SELECT * FROM t1;
+--error ER_PARSE_ERROR
+RENAME TABLE t1 TO t1_2;
+SHOW TRIGGERS;
+
+DROP TRIGGER tr11;
+DROP TRIGGER tr12;
+DROP TRIGGER tr13;
+DROP TRIGGER tr14;
+DROP TRIGGER tr15;
+
+SHOW TRIGGERS;
+
+--echo # Make sure there is no trigger file left.
+--list_files $MYSQLD_DATADIR/test/ tr*
+
+--echo # We write the same trigger files one more time to test DROP TABLE.
+--write_file $MYSQLD_DATADIR/test/tr11.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/tr12.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/tr13.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/tr14.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/tr15.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/t1.TRG
+TYPE=TRIGGERS
+triggers='CREATE DEFINER=`root`@`localhost` TRIGGER tr11 BEFORE INSERT ON t1 FOR EACH ROW DELETE FROM t3' 'CREATE DEFINER=`root`@`localhost` TRIGGER tr12 AFTER INSERT ON t1 FOR EACH ROW DELETE FROM t3' 'CREATE DEFINER=`root`@`localhost` TRIGGER tr13 BEFORE DELETE ON t1 FOR EACH ROW DELETE FROM t1 a USING t1 a' 'CREATE DEFINER=`root`@`localhost` TRIGGER tr14 AFTER DELETE ON t1 FOR EACH ROW DELETE FROM non_existing_table' 'CREATE DEFINER=`root`@`localhost` TRIGGER tr15 BEFORE UPDATE ON t1 FOR EACH ROW DELETE FROM non_existing_table a USING non_existing_table a'
+sql_modes=0 0 0 0 0
+definers='root@localhost' 'root@localhost' 'root@localhost' 'root@localhost' 'root@localhost'
+EOF
+
+FLUSH TABLE t1;
+FLUSH TABLE t2;
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+
+--echo # Make sure there is no trigger file left.
+
+--list_files $MYSQLD_DATADIR/test/ tr*
+
+CREATE TABLE t1 ( a INT );
+CREATE TABLE t2 ( a INT );
+INSERT INTO t1 VALUES (1), (2), (3);
+INSERT INTO t2 VALUES (1), (2), (3);
+
+--echo # We write three trigger files. First trigger is syntaxically incorrect, next trigger is correct
+--echo # and last trigger is broken.
+--echo # Next we try to execute SHOW CREATE TRGGIR command for broken trigger and then try to drop one.
+--write_file $MYSQLD_DATADIR/test/tr11.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/tr12.TRN
+TYPE=TRIGGERNAME
+trigger_table=t1
+EOF
+
+--write_file $MYSQLD_DATADIR/test/t1.TRG
+TYPE=TRIGGERS
+triggers='CREATE the wrongest trigger_in_the_world' 'CREATE DEFINER=`root`@`localhost` TRIGGER tr11 BEFORE DELETE ON t1 FOR EACH ROW DELETE FROM t1 a USING t1 a' 'CREATE DEFINER=`root`@`localhost` TRIGGER tr12 BEFORE INSERT ON t1 FOR EACH ROW DELETE FROM t2'
+sql_modes=0 0 0
+definers='root@localhost' 'root@localhost' 'root@localhost'
+EOF
+
+FLUSH TABLE t1;
+
+SHOW CREATE TRIGGER tr12;
+SHOW CREATE TRIGGER tr11;
+DROP TRIGGER tr12;
+DROP TRIGGER tr11;
+
+DROP TABLE t1;
+DROP TABLE t2;

=== modified file 'mysql-test/t/type_datetime.test'
--- a/mysql-test/t/type_datetime.test	2011-01-19 14:12:43 +0000
+++ b/mysql-test/t/type_datetime.test	2011-06-10 08:22:45 +0000
@@ -506,5 +506,35 @@ DROP TABLE t1;
 --echo #
 
 --echo #
+--echo # BUG#12561818: RERUN OF STORED FUNCTION GIVES ERROR 1172: 
+--echo #               RESULT CONSISTED OF MORE THAN ONE ROW
+--echo #
+
+CREATE TABLE t1 (a DATE NOT NULL, b INT);
+INSERT INTO t1 VALUES ('0000-00-00',1), ('1999-05-10',2);
+
+CREATE TABLE t2 (a DATETIME NOT NULL, b INT);
+INSERT INTO t2 VALUES ('0000-00-00 00:00:00',1), ('1999-05-10 00:00:00',2);
+
+--echo
+SELECT * FROM t1 WHERE a IS NULL;
+SELECT * FROM t2 WHERE a IS NULL;
+SELECT * FROM t1 LEFT JOIN t1 AS t1_2 ON 1 WHERE t1_2.a IS NULL;
+SELECT * FROM t2 LEFT JOIN t2 AS t2_2 ON 1 WHERE t2_2.a IS NULL;
+SELECT * FROM t1 JOIN t1 AS t1_2 ON 1 WHERE t1_2.a IS NULL;
+SELECT * FROM t2 JOIN t2 AS t2_2 ON 1 WHERE t2_2.a IS NULL;
+
+--echo
+PREPARE stmt1 FROM 
+  'SELECT *
+   FROM t1 LEFT JOIN t1 AS t1_2 ON 1
+   WHERE t1_2.a IS NULL AND t1_2.b < 2';
+EXECUTE stmt1;
+EXECUTE stmt1;
+
+DEALLOCATE PREPARE stmt1;
+DROP TABLE t1,t2;
+
+--echo #
 --echo # End of 5.5 tests
 --echo #

=== modified file 'mysys/mf_pack.c'
--- a/mysys/mf_pack.c	2010-12-29 00:26:31 +0000
+++ b/mysys/mf_pack.c	2011-06-15 09:18:08 +0000
@@ -193,7 +193,7 @@ size_t cleanup_dirname(register char *to
 	  while (pos >= start && *pos != FN_LIBCHAR)	/* remove prev dir */
 	    pos--;
           if (pos[1] == FN_HOMELIB ||
-              (pos > start && memcmp(pos, parent, length) == 0))
+              (pos >= start && memcmp(pos, parent, length) == 0))
 	  {					/* Don't remove ~user/ */
 	    pos=strmov(end_parentdir+1,parent);
 	    *pos=FN_LIBCHAR;

=== modified file 'plugin/audit_null/audit_null.c'
--- a/plugin/audit_null/audit_null.c	2010-08-12 15:19:57 +0000
+++ b/plugin/audit_null/audit_null.c	2011-06-03 07:27:11 +0000
@@ -81,11 +81,12 @@ static int audit_null_plugin_deinit(void
 */
 
 static void audit_null_notify(MYSQL_THD thd __attribute__((unused)),
-                              const struct mysql_event *event)
+                              unsigned int event_class,
+                              const void *event)
 {
   /* prone to races, oh well */
   number_of_calls++;
-  if (event->event_class == MYSQL_AUDIT_GENERAL_CLASS)
+  if (event_class == MYSQL_AUDIT_GENERAL_CLASS)
   {
     const struct mysql_event_general *event_general=
       (const struct mysql_event_general *) event;

=== modified file 'plugin/daemon_example/CMakeLists.txt'
--- a/plugin/daemon_example/CMakeLists.txt	2010-08-12 15:19:57 +0000
+++ b/plugin/daemon_example/CMakeLists.txt	2011-06-14 20:00:51 +0000
@@ -15,3 +15,5 @@
 
 MYSQL_ADD_PLUGIN(daemon_example daemon_example.cc
   MODULE_ONLY MODULE_OUTPUT_NAME "libdaemon_example")
+
+INSTALL(FILES daemon_example.ini DESTINATION ${INSTALL_PLUGINDIR})

=== added file 'plugin/daemon_example/daemon_example.ini'
--- a/plugin/daemon_example/daemon_example.ini	1970-01-01 00:00:00 +0000
+++ b/plugin/daemon_example/daemon_example.ini	2011-06-30 12:12:58 +0000
@@ -0,0 +1,9 @@
+#
+# Plugin configuration file. Place the following on a separate line:
+#
+# library binary file name (without .so or .dll)
+# component_name
+# [component_name] - additional components in plugin
+#
+libdaemon_example
+daemon_example

=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc	2011-05-27 11:42:28 +0000
+++ b/sql/event_db_repository.cc	2011-06-09 17:07:03 +0000
@@ -235,9 +235,16 @@ mysql_event_fill_row(THD *thd,
   if (fields[f_num= ET_FIELD_NAME]->store(et->name.str, et->name.length, scs))
     goto err_truncate;
 
-  /* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull()*/
+  /* ON_COMPLETION field is NOT NULL thus not calling set_notnull()*/
   rs|= fields[ET_FIELD_ON_COMPLETION]->store((longlong)et->on_completion, TRUE);
-  rs|= fields[ET_FIELD_STATUS]->store((longlong)et->status, TRUE);
+
+  /*
+    Set STATUS value unconditionally in case of CREATE EVENT.
+    For ALTER EVENT set it only if value of this field was changed.
+    Since STATUS field is NOT NULL call to set_notnull() is not needed.
+  */
+  if (!is_update || et->status_changed)
+    rs|= fields[ET_FIELD_STATUS]->store((longlong)et->status, TRUE);
   rs|= fields[ET_FIELD_ORIGINATOR]->store((longlong)et->originator, TRUE);
 
   /*
@@ -716,8 +723,6 @@ Event_db_repository::create_event(THD *t
   if (mysql_event_fill_row(thd, table, parse_data, sp, saved_mode, FALSE))
     goto end;
 
-  table->field[ET_FIELD_STATUS]->store((longlong)parse_data->status, TRUE);
-
   if ((ret= table->file->ha_write_row(table->record[0])))
   {
     table->file->print_error(ret, MYF(0));

=== modified file 'sql/event_parse_data.cc'
--- a/sql/event_parse_data.cc	2010-03-31 14:05:33 +0000
+++ b/sql/event_parse_data.cc	2011-06-09 17:07:03 +0000
@@ -48,9 +48,8 @@ Event_parse_data::new_instance(THD *thd)
 
 Event_parse_data::Event_parse_data()
   :on_completion(Event_parse_data::ON_COMPLETION_DEFAULT),
-  status(Event_parse_data::ENABLED),
-  do_not_create(FALSE),
-  body_changed(FALSE),
+  status(Event_parse_data::ENABLED), status_changed(false),
+  do_not_create(FALSE), body_changed(FALSE),
   item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
   starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
   item_expression(NULL), expression(0)
@@ -142,6 +141,7 @@ Event_parse_data::check_if_in_the_past(T
   else if (status == Event_parse_data::ENABLED)
   {
     status= Event_parse_data::DISABLED;
+    status_changed= true;
     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
                  ER_EVENT_EXEC_TIME_IN_THE_PAST,
                  ER(ER_EVENT_EXEC_TIME_IN_THE_PAST));
@@ -571,7 +571,10 @@ void Event_parse_data::check_originator_
     DBUG_PRINT("info", ("Invoked object status set to SLAVESIDE_DISABLED."));
     if ((status == Event_parse_data::ENABLED) ||
         (status == Event_parse_data::DISABLED))
-      status = Event_parse_data::SLAVESIDE_DISABLED;
+    {
+      status= Event_parse_data::SLAVESIDE_DISABLED;
+      status_changed= true;
+    }
     originator = thd->server_id;
   }
   else

=== modified file 'sql/event_parse_data.h'
--- a/sql/event_parse_data.h	2010-03-31 14:05:33 +0000
+++ b/sql/event_parse_data.h	2011-06-09 17:07:03 +0000
@@ -55,6 +55,7 @@ public:
 
   int on_completion;
   int status;
+  bool status_changed;
   longlong originator;
   /*
     do_not_create will be set if STARTS time is in the past and

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2011-06-01 08:06:55 +0000
+++ b/sql/ha_partition.cc	2011-06-13 09:21:54 +0000
@@ -3456,9 +3456,13 @@ exit:
     index)
     mysql_update does not set table->next_number_field, so we use
     table->found_next_number_field instead.
+    Also checking that the field is marked in the write set.
   */
-  if (table->found_next_number_field && new_data == table->record[0] &&
-      !table->s->next_number_keypart)
+  if (table->found_next_number_field &&
+      new_data == table->record[0] &&
+      !table->s->next_number_keypart &&
+      bitmap_is_set(table->write_set,
+                    table->found_next_number_field->field_index))
   {
     if (!table_share->ha_part_data->auto_inc_initialized)
       info(HA_STATUS_AUTO);
@@ -4110,6 +4114,7 @@ void ha_partition::position(const uchar
 void ha_partition::column_bitmaps_signal()
 {
     handler::column_bitmaps_signal();
+    /* Must read all partition fields to make position() call possible */
     bitmap_union(table->read_set, &m_part_info->full_part_field_set);
 }
  

=== modified file 'sql/item.h'
--- a/sql/item.h	2011-04-08 13:15:23 +0000
+++ b/sql/item.h	2011-06-10 14:26:35 +0000
@@ -1672,6 +1672,8 @@ public:
   String *val_str(String *str) { return field->val_str(str); }
   my_decimal *val_decimal(my_decimal *dec) { return field->val_decimal(dec); }
   void make_field(Send_field *tmp_field);
+  CHARSET_INFO *charset_for_protocol(void) const
+  { return field->charset_for_protocol(); }
 };
 
 

=== modified file 'sql/item_timefunc.cc'
--- a/sql/item_timefunc.cc	2011-05-18 06:59:04 +0000
+++ b/sql/item_timefunc.cc	2011-06-13 09:57:47 +0000
@@ -1388,6 +1388,26 @@ longlong Item_func_unix_timestamp::val_i
   return (longlong) TIME_to_timestamp(current_thd, &ltime, &not_used);
 }
 
+enum_monotonicity_info Item_func_unix_timestamp::get_monotonicity_info() const
+{
+  if (args[0]->type() == Item::FIELD_ITEM &&
+      (args[0]->field_type() == MYSQL_TYPE_TIMESTAMP))
+    return MONOTONIC_INCREASING;
+  return NON_MONOTONIC;
+}
+
+
+longlong Item_func_unix_timestamp::val_int_endpoint(bool left_endp, bool *incl_endp)
+{
+  DBUG_ASSERT(fixed == 1);
+  DBUG_ASSERT(arg_count == 1 &&
+              args[0]->type() == Item::FIELD_ITEM &&
+              args[0]->field_type() == MYSQL_TYPE_TIMESTAMP);
+  Field *field=((Item_field*) args[0])->field;
+  /* Leave the incl_endp intact */
+  return ((Field_timestamp*) field)->get_timestamp(&null_value);
+}
+
 
 longlong Item_func_time_to_sec::val_int()
 {

=== modified file 'sql/item_timefunc.h'
--- a/sql/item_timefunc.h	2011-03-30 07:25:49 +0000
+++ b/sql/item_timefunc.h	2011-06-13 09:57:47 +0000
@@ -391,6 +391,8 @@ public:
   Item_func_unix_timestamp(Item *a) :Item_int_func(a) {}
   longlong val_int();
   const char *func_name() const { return "unix_timestamp"; }
+  enum_monotonicity_info get_monotonicity_info() const;
+  longlong val_int_endpoint(bool left_endp, bool *incl_endp);
   bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
   /*
     UNIX_TIMESTAMP() depends on the current timezone

=== modified file 'sql/mdl.h'
--- a/sql/mdl.h	2011-04-11 11:39:15 +0000
+++ b/sql/mdl.h	2011-06-16 15:18:16 +0000
@@ -152,11 +152,24 @@ enum enum_mdl_type {
 
 /** Duration of metadata lock. */
 
-enum enum_mdl_duration { MDL_STATEMENT= 0,
-                         MDL_TRANSACTION,
-                         MDL_EXPLICIT,
-                         /* This should be the last ! */
-                         MDL_DURATION_END };
+enum enum_mdl_duration {
+  /**
+    Locks with statement duration are automatically released at the end
+    of statement or transaction.
+  */
+  MDL_STATEMENT= 0,
+  /**
+    Locks with transaction duration are automatically released at the end
+    of transaction.
+  */
+  MDL_TRANSACTION,
+  /**
+    Locks with explicit duration survive the end of statement and transaction.
+    They have to be released explicitly by calling MDL_context::release_lock().
+  */
+  MDL_EXPLICIT,
+  /* This should be the last ! */
+  MDL_DURATION_END };
 
 
 /** Maximal length of key for metadata locking subsystem. */

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2011-05-26 10:56:17 +0000
+++ b/sql/mysqld.cc	2011-06-06 10:24:28 +0000
@@ -163,12 +163,12 @@ extern int memcntl(caddr_t, size_t, int,
 int initgroups(const char *,unsigned int);
 #endif
 
-#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
+#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
 #include <ieeefp.h>
 #ifdef HAVE_FP_EXCEPT				// Fix type conflict
 typedef fp_except fp_except_t;
 #endif
-#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
+#endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */
 #ifdef HAVE_SYS_FPU_H
 /* for IRIX to use set_fpc_csr() */
 #include <sys/fpu.h>
@@ -194,19 +194,24 @@ extern "C" my_bool reopen_fstreams(const
 
 inline void setup_fpu()
 {
-#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
+#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
   /* We can't handle floating point exceptions with threads, so disable
      this on freebsd
-     Don't fall for overflow, underflow,divide-by-zero or loss of precision
+     Don't fall for overflow, underflow,divide-by-zero or loss of precision.
+     fpsetmask() is deprecated in favor of fedisableexcept() in C99.
   */
-#if defined(__i386__)
+#if defined(FP_X_DNML)
   fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
 	      FP_X_IMP));
 #else
   fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
               FP_X_IMP));
-#endif /* __i386__ */
-#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
+#endif /* FP_X_DNML */
+#endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */
+
+#ifdef HAVE_FEDISABLEEXCEPT
+  fedisableexcept(FE_ALL_EXCEPT);
+#endif
 
 #ifdef HAVE_FESETROUND
     /* Set FPU rounding mode to "round-to-nearest" */

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	2011-05-31 09:12:32 +0000
+++ b/sql/share/errmsg-utf8.txt	2011-06-10 07:20:15 +0000
@@ -6408,3 +6408,10 @@ WARN_OPTION_BELOW_LIMIT
 
 ER_INDEX_COLUMN_TOO_LONG
   eng "Index column size too large. The maximum column size is %lu bytes."
+
+ER_ERROR_IN_TRIGGER_BODY
+  eng "Trigger '%-.64s' has an error in its body: '%-.256s'"
+
+ER_ERROR_IN_UNKNOWN_TRIGGER_BODY
+  eng "Unknown trigger has an error in its body: '%-.256s'"
+

=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc	2011-05-21 08:59:32 +0000
+++ b/sql/sp_head.cc	2011-06-10 07:20:15 +0000
@@ -2543,7 +2543,22 @@ void
 sp_head::restore_thd_mem_root(THD *thd)
 {
   DBUG_ENTER("sp_head::restore_thd_mem_root");
-  Item *flist= free_list;       // The old list
+
+  /*
+   In some cases our parser detects a syntax error and calls
+   LEX::cleanup_lex_after_parse_error() method only after
+   finishing parsing the whole routine. In such a situation
+   sp_head::restore_thd_mem_root() will be called twice - the
+   first time as part of normal parsing process and the second
+   time by cleanup_lex_after_parse_error().
+   To avoid ruining active arena/mem_root state in this case we
+   skip restoration of old arena/mem_root if this method has been
+   already called for this routine.
+  */
+  if (!m_thd)
+    DBUG_VOID_RETURN;
+
+  Item *flist= free_list;	// The old list
   set_query_arena(thd);         // Get new free_list and mem_root
   state= STMT_INITIALIZED_FOR_SP;
 

=== modified file 'sql/sql_audit.cc'
--- a/sql/sql_audit.cc	2010-12-14 14:34:23 +0000
+++ b/sql/sql_audit.cc	2011-06-03 07:27:11 +0000
@@ -21,11 +21,18 @@ extern int finalize_audit_plugin(st_plug
 
 #ifndef EMBEDDED_LIBRARY
 
+struct st_mysql_event_generic
+{
+  unsigned int event_class;
+  const void *event;
+};
+
 unsigned long mysql_global_audit_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
 
 static mysql_mutex_t LOCK_audit_mask;
 
-static void event_class_dispatch(THD *thd, const struct mysql_event *event);
+static void event_class_dispatch(THD *thd, unsigned int event_class,
+                                 const void *event);
 
 
 static inline
@@ -64,7 +71,6 @@ typedef void (*audit_handler_t)(THD *thd
 static void general_class_handler(THD *thd, uint event_subtype, va_list ap)
 {
   mysql_event_general event;
-  event.event_class= MYSQL_AUDIT_GENERAL_CLASS;
   event.event_subclass= event_subtype;
   event.general_error_code= va_arg(ap, int);
   event.general_thread_id= thd ? thd->thread_id : 0;
@@ -77,14 +83,13 @@ static void general_class_handler(THD *t
   event.general_query_length= va_arg(ap, unsigned int);
   event.general_charset= va_arg(ap, struct charset_info_st *);
   event.general_rows= (unsigned long long) va_arg(ap, ha_rows);
-  event_class_dispatch(thd, (const mysql_event*) &event);
+  event_class_dispatch(thd, MYSQL_AUDIT_GENERAL_CLASS, &event);
 }
 
 
 static void connection_class_handler(THD *thd, uint event_subclass, va_list ap)
 {
   mysql_event_connection event;
-  event.event_class= MYSQL_AUDIT_CONNECTION_CLASS;
   event.event_subclass= event_subclass;
   event.status= va_arg(ap, int);
   event.thread_id= va_arg(ap, unsigned long);
@@ -102,7 +107,7 @@ static void connection_class_handler(THD
   event.ip_length= va_arg(ap, unsigned int);
   event.database= va_arg(ap, const char *);
   event.database_length= va_arg(ap, unsigned int);
-  event_class_dispatch(thd, (const mysql_event *) &event);
+  event_class_dispatch(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event);
 }
 
 
@@ -433,18 +438,19 @@ int finalize_audit_plugin(st_plugin_int
 
 static my_bool plugins_dispatch(THD *thd, plugin_ref plugin, void *arg)
 {
-  const struct mysql_event *event= (const struct mysql_event *) arg;
+  const struct st_mysql_event_generic *event_generic=
+    (const struct st_mysql_event_generic *) arg;
   unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
   st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *);
 
-  set_audit_mask(event_class_mask, event->event_class);
+  set_audit_mask(event_class_mask, event_generic->event_class);
 
   /* Check to see if the plugin is interested in this event */
   if (check_audit_mask(data->class_mask, event_class_mask))
     return 0;
 
   /* Actually notify the plugin */
-  data->event_notify(thd, event);
+  data->event_notify(thd, event_generic->event_class, event_generic->event);
 
   return 0;
 }
@@ -457,15 +463,19 @@ static my_bool plugins_dispatch(THD *thd
   @param[in] event
 */
 
-static void event_class_dispatch(THD *thd, const struct mysql_event *event)
+static void event_class_dispatch(THD *thd, unsigned int event_class,
+                                 const void *event)
 {
+  struct st_mysql_event_generic event_generic;
+  event_generic.event_class= event_class;
+  event_generic.event= event;
   /*
     Check if we are doing a slow global dispatch. This event occurs when
     thd == NULL as it is not associated with any particular thread.
   */
   if (unlikely(!thd))
   {
-    plugin_foreach(thd, plugins_dispatch, MYSQL_AUDIT_PLUGIN, (void*) event);
+    plugin_foreach(thd, plugins_dispatch, MYSQL_AUDIT_PLUGIN, &event_generic);
   }
   else
   {
@@ -476,7 +486,7 @@ static void event_class_dispatch(THD *th
     plugins_last= plugins + thd->audit_class_plugins.elements;
 
     for (; plugins < plugins_last; plugins++)
-      plugins_dispatch(thd, *plugins, (void*) event);
+      plugins_dispatch(thd, *plugins, &event_generic);
   }
 }
 

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2011-05-21 09:29:10 +0000
+++ b/sql/sql_class.cc	2011-06-16 15:18:16 +0000
@@ -3790,16 +3790,24 @@ void THD::set_mysys_var(struct st_my_thr
 
 void THD::leave_locked_tables_mode()
 {
+  if (locked_tables_mode == LTM_LOCK_TABLES)
+  {
+    /*
+      When leaving LOCK TABLES mode we have to change the duration of most
+      of the metadata locks being held, except for HANDLER and GRL locks,
+      to transactional for them to be properly released at UNLOCK TABLES.
+    */
+    mdl_context.set_transaction_duration_for_all_locks();
+    /*
+      Make sure we don't release the global read lock and commit blocker
+      when leaving LTM.
+    */
+    global_read_lock.set_explicit_lock_duration(this);
+    /* Also ensure that we don't release metadata locks for open HANDLERs. */
+    if (handler_tables_hash.records)
+      mysql_ha_set_explicit_lock_duration(this);
+  }
   locked_tables_mode= LTM_NONE;
-  mdl_context.set_transaction_duration_for_all_locks();
-  /*
-    Make sure we don't release the global read lock and commit blocker
-    when leaving LTM.
-  */
-  global_read_lock.set_explicit_lock_duration(this);
-  /* Also ensure that we don't release metadata locks for open HANDLERs. */
-  if (handler_tables_hash.records)
-    mysql_ha_set_explicit_lock_duration(this);
 }
 
 void THD::get_definer(LEX_USER *definer)

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2011-05-20 09:18:36 +0000
+++ b/sql/sql_class.h	2011-06-16 15:18:16 +0000
@@ -2795,7 +2795,19 @@ public:
   {
     DBUG_ASSERT(locked_tables_mode == LTM_NONE);
 
-    mdl_context.set_explicit_duration_for_all_locks();
+    if (mode_arg == LTM_LOCK_TABLES)
+    {
+      /*
+        When entering LOCK TABLES mode we should set explicit duration
+        for all metadata locks acquired so far in order to avoid releasing
+        them till UNLOCK TABLES statement.
+        We don't do this when entering prelocked mode since sub-statements
+        don't release metadata locks and restoring status-quo after leaving
+        prelocking mode gets complicated.
+      */
+      mdl_context.set_explicit_duration_for_all_locks();
+    }
+
     locked_tables_mode= mode_arg;
   }
   void leave_locked_tables_mode();

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2011-05-26 15:50:06 +0000
+++ b/sql/sql_parse.cc	2011-06-16 15:18:16 +0000
@@ -2027,6 +2027,11 @@ mysql_execute_command(THD *thd)
   */
   if (stmt_causes_implicit_commit(thd, CF_IMPLICT_COMMIT_BEGIN))
   {
+    /*
+      Note that this should never happen inside of stored functions
+      or triggers as all such statements prohibited there.
+    */
+    DBUG_ASSERT(! thd->in_sub_stmt);
     /* Commit or rollback the statement transaction. */
     thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
     /* Commit the normal transaction if one is active. */

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-05-06 08:27:04 +0000
+++ b/sql/sql_select.cc	2011-06-10 08:22:45 +0000
@@ -9519,24 +9519,41 @@ internal_remove_eq_conds(THD *thd, COND
       Field *field=((Item_field*) args[0])->field;
       /* fix to replace 'NULL' dates with '0' (shreeve@stripped) */
       /*
-        datetime_field IS NULL has to be modified to
-        datetime_field == 0
+        See BUG#12594011
+        Documentation says that
+        SELECT datetime_notnull d FROM t1 WHERE d IS NULL
+        shall return rows where d=='0000-00-00'
+
+        Thus, for DATE and DATETIME columns defined as NOT NULL,
+        "date_notnull IS NULL" has to be modified to
+        "date_notnull IS NULL OR date_notnull == 0" (if outer join)
+        "date_notnull == 0"                         (otherwise)
+
       */
       if (((field->type() == MYSQL_TYPE_DATE) ||
            (field->type() == MYSQL_TYPE_DATETIME)) &&
-          (field->flags & NOT_NULL_FLAG) && !field->table->maybe_null)
+          (field->flags & NOT_NULL_FLAG))
       {
-	COND *new_cond;
-	if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2))))
-	{
-	  cond=new_cond;
-          /*
-            Item_func_eq can't be fixed after creation so we do not check
-            cond->fixed, also it do not need tables so we use 0 as second
-            argument.
-          */
-	  cond->fix_fields(thd, &cond);
-	}
+        Item *item0= new(thd->mem_root) Item_int((longlong)0, 1);
+        Item *eq_cond= new(thd->mem_root) Item_func_eq(args[0], item0);
+        if (!eq_cond)
+          return cond;
+
+        if (field->table->pos_in_table_list->outer_join)
+        {
+          // outer join: transform "col IS NULL" to "col IS NULL or col=0"
+          Item *or_cond= new(thd->mem_root) Item_cond_or(eq_cond, cond);
+          if (!or_cond)
+            return cond;
+          cond= or_cond;
+        }
+        else
+        {
+          // not outer join: transform "col IS NULL" to "col=0"
+          cond= eq_cond;
+        }
+
+        cond->fix_fields(thd, &cond);
       }
     }
     if (cond->const_item())

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2011-06-01 08:06:55 +0000
+++ b/sql/sql_table.cc	2011-06-16 22:50:07 +0000
@@ -4582,6 +4582,11 @@ bool mysql_create_like_table(THD* thd, T
   local_create_info.options|= create_info->options & HA_LEX_CREATE_TMP_TABLE;
   /* Reset auto-increment counter for the new table. */
   local_create_info.auto_increment_value= 0;
+  /*
+    Do not inherit values of DATA and INDEX DIRECTORY options from
+    the original table. This is documented behavior.
+  */
+  local_create_info.data_file_name= local_create_info.index_file_name= NULL;
 
   if ((res= mysql_create_table_no_lock(thd, table->db, table->table_name,
                                        &local_create_info, &local_alter_info,
@@ -5321,6 +5326,12 @@ 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 */
@@ -5398,7 +5409,14 @@ mysql_prepare_alter_table(THD *thd, TABL
     if (!def->after)
       new_create_list.push_back(def);
     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
     {
       Create_field *find;
@@ -5414,6 +5432,10 @@ 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;
     }
   }

=== modified file 'sql/sql_trigger.cc'
--- a/sql/sql_trigger.cc	2011-04-15 12:02:22 +0000
+++ b/sql/sql_trigger.cc	2011-06-10 07:20:15 +0000
@@ -31,6 +31,7 @@
 #include "sql_acl.h"                       // *_ACL, is_acl_user
 #include "sql_handler.h"                        // mysql_ha_rm_tables
 #include "sp_cache.h"                     // sp_invalidate_cache
+#include <mysys_err.h>
 
 /*************************************************************************/
 
@@ -305,6 +306,55 @@ private:
 
 
 /**
+  An error handler that catches all non-OOM errors which can occur during
+  parsing of trigger body. Such errors are ignored and corresponding error
+  message is used to construct a more verbose error message which contains
+  name of problematic trigger. This error message is later emitted when
+  one tries to perform DML or some of DDL on this table.
+  Also, if possible, grabs name of the trigger being parsed so it can be
+  used to correctly drop problematic trigger.
+*/
+class Deprecated_trigger_syntax_handler : public Internal_error_handler 
+{
+private:
+
+  char m_message[MYSQL_ERRMSG_SIZE];
+  LEX_STRING *m_trigger_name;
+
+public:
+
+  Deprecated_trigger_syntax_handler() : m_trigger_name(NULL) {}
+
+  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)
+  {
+    if (sql_errno != EE_OUTOFMEMORY &&
+        sql_errno != ER_OUT_OF_RESOURCES)
+    {
+      if(thd->lex->spname)
+        m_trigger_name= &thd->lex->spname->m_name;
+      if (m_trigger_name)
+        my_snprintf(m_message, sizeof(m_message),
+                    ER(ER_ERROR_IN_TRIGGER_BODY),
+                    m_trigger_name->str, message);
+      else
+        my_snprintf(m_message, sizeof(m_message),
+                    ER(ER_ERROR_IN_UNKNOWN_TRIGGER_BODY), message);
+      return true;
+    }
+    return false;
+  }
+
+  LEX_STRING *get_trigger_name() { return m_trigger_name; }
+  char *get_error_message() { return m_message; }
+};
+
+
+/**
   Create or drop trigger for table.
 
   @param thd     current thread context (including trigger definition in LEX)
@@ -591,6 +641,8 @@ bool Table_triggers_list::create_trigger
   LEX_STRING *trg_connection_cl_name;
   LEX_STRING *trg_db_cl_name;
 
+  if (check_for_broken_triggers())
+    return true;
 
   /* Trigger must be in the same schema as target table. */
   if (my_strcasecmp(table_alias_charset, table->s->db.str,
@@ -864,7 +916,7 @@ static bool rm_trigger_file(char *path,
   @param path         char buffer of size FN_REFLEN to be used
                       for constructing path to .TRN file.
   @param db           trigger's database name
-  @param table_name   trigger's name
+  @param trigger_name trigger's name
 
   @retval
     False   success
@@ -1329,12 +1381,11 @@ bool Table_triggers_list::check_n_load(T
         lex_start(thd);
         thd->spcont= NULL;
 
-        if (parse_sql(thd, & parser_state, creation_ctx))
-        {
-          /* Currently sphead is always deleted in case of a parse error */
-          DBUG_ASSERT(lex.sphead == 0);
-          goto err_with_lex_cleanup;
-        }
+        Deprecated_trigger_syntax_handler error_handler;
+        thd->push_internal_handler(&error_handler);
+        bool parse_error= parse_sql(thd, & parser_state, creation_ctx);
+        thd->pop_internal_handler();
+
         /*
           Not strictly necessary to invoke this method here, since we know
           that we've parsed CREATE TRIGGER and not an
@@ -1345,6 +1396,54 @@ bool Table_triggers_list::check_n_load(T
         */
         lex.set_trg_event_type_for_tables();
 
+        if (parse_error)
+        {
+          if (!triggers->m_has_unparseable_trigger)
+            triggers->set_parse_error_message(error_handler.get_error_message());
+          /* Currently sphead is always set to NULL in case of a parse error */
+          DBUG_ASSERT(lex.sphead == 0);
+          if (error_handler.get_trigger_name())
+          {
+            LEX_STRING *trigger_name;
+            const LEX_STRING *orig_trigger_name= error_handler.get_trigger_name();
+
+            if (!(trigger_name= alloc_lex_string(&table->mem_root)) ||
+                !(trigger_name->str= strmake_root(&table->mem_root,
+                                                  orig_trigger_name->str,
+                                                  orig_trigger_name->length)))
+              goto err_with_lex_cleanup;
+
+            trigger_name->length= orig_trigger_name->length;
+
+            if (triggers->names_list.push_back(trigger_name,
+                                               &table->mem_root))
+              goto err_with_lex_cleanup;
+          }
+          else
+          {
+            /* 
+               The Table_triggers_list is not constructed as a list of
+               trigger objects as one would expect, but rather of lists of
+               properties of equal length. Thus, even if we don't get the
+               trigger name, we still fill all in all the lists with
+               placeholders as we might otherwise create a skew in the
+               lists. Obviously, this has to be refactored.
+            */
+            LEX_STRING *empty= alloc_lex_string(&table->mem_root);
+            if (!empty)
+              goto err_with_lex_cleanup;
+
+            empty->str= const_cast<char*>("");
+            empty->length= 0;
+            if (triggers->names_list.push_back(empty, &table->mem_root))
+              goto err_with_lex_cleanup;
+          }
+          lex_end(&lex);
+          continue;
+        }
+
+        lex.sphead->set_info(0, 0, &lex.sp_chistics, (ulong) *trg_sql_mode);
+
         int event= lex.trg_chistics.event;
         int action_time= lex.trg_chistics.action_time;
 
@@ -1411,9 +1510,8 @@ bool Table_triggers_list::check_n_load(T
         char fname[NAME_LEN + 1];
         DBUG_ASSERT((!my_strcasecmp(table_alias_charset, lex.query_tables->db, db) ||
                      (check_n_cut_mysql50_prefix(db, fname, sizeof(fname)) &&
-                      !my_strcasecmp(table_alias_charset, lex.query_tables->db, fname))) &&
-                    (!my_strcasecmp(table_alias_charset, lex.query_tables->table_name,
-                                    table_name) ||
+                      !my_strcasecmp(table_alias_charset, lex.query_tables->db, fname))));
+        DBUG_ASSERT((!my_strcasecmp(table_alias_charset, lex.query_tables->table_name, table_name) ||
                      (check_n_cut_mysql50_prefix(table_name, fname, sizeof(fname)) &&
                       !my_strcasecmp(table_alias_charset, lex.query_tables->table_name, fname))));
 #endif
@@ -1695,6 +1793,13 @@ bool Table_triggers_list::drop_all_trigg
 
     while ((trigger= it_name++))
     {
+      /*
+        Trigger, which body we failed to parse during call
+        Table_triggers_list::check_n_load(), might be missing name.
+        Such triggers have zero-length name and are skipped here.
+      */
+      if (trigger->length == 0)
+        continue;
       if (rm_trigname_file(path, db, trigger->str))
       {
         /*
@@ -1913,6 +2018,11 @@ bool Table_triggers_list::change_table_n
   }
   if (table.triggers)
   {
+    if (table.triggers->check_for_broken_triggers())
+    {
+      result= 1;
+      goto end;
+    }
     LEX_STRING old_table_name= { (char *) old_alias, strlen(old_alias) };
     LEX_STRING new_table_name= { (char *) new_table, strlen(new_table) };
     /*
@@ -2001,6 +2111,9 @@ bool Table_triggers_list::process_trigge
   sp_head *sp_trigger= bodies[event][time_type];
   SELECT_LEX *save_current_select;
 
+  if (check_for_broken_triggers())
+    return true;
+
   if (sp_trigger == NULL)
     return FALSE;
 
@@ -2134,6 +2247,22 @@ void Table_triggers_list::mark_fields_us
 }
 
 
+/**
+   Signals to the Table_triggers_list that a parse error has occured when
+   reading a trigger from file. This makes the Table_triggers_list enter an
+   error state flagged by m_has_unparseable_trigger == true. The error message
+   will be used whenever a statement invoking or manipulating triggers is
+   issued against the Table_triggers_list's table.
+
+   @param error_message The error message thrown by the parser.
+ */
+void Table_triggers_list::set_parse_error_message(char *error_message)
+{
+  m_has_unparseable_trigger= true;
+  strcpy(m_parse_error_message, error_message);
+}
+
+
 /**
   Trigger BUG#14090 compatibility hook.
 

=== modified file 'sql/sql_trigger.h'
--- a/sql/sql_trigger.h	2010-09-16 09:11:13 +0000
+++ b/sql/sql_trigger.h	2011-06-10 07:20:15 +0000
@@ -97,6 +97,27 @@ class Table_triggers_list: public Sql_al
   */
   GRANT_INFO        subject_table_grants[TRG_EVENT_MAX][TRG_ACTION_MAX];
 
+  /**
+     This flag indicates that one of the triggers was not parsed successfully,
+     and as a precaution the object has entered a state where all trigger
+     access results in errors until all such triggers are dropped. It is not
+     safe to add triggers since we don't know if the broken trigger has the
+     same name or event type. Nor is it safe to invoke any trigger for the
+     aforementioned reasons. The only safe operations are drop_trigger and
+     drop_all_triggers.
+
+     @see Table_triggers_list::set_parse_error
+   */
+  bool m_has_unparseable_trigger;
+
+  /**
+    This error will be displayed when the user tries to manipulate or invoke
+    triggers on a table that has broken triggers. It will get set only once
+    per statement and thus will contain the first parse error encountered in
+    the trigger file.
+   */
+  char m_parse_error_message[MYSQL_ERRMSG_SIZE];
+
 public:
   /**
     Field responsible for storing triggers definitions in file.
@@ -118,8 +139,9 @@ public:
 
   /* End of character ser context. */
 
-  Table_triggers_list(TABLE *table_arg):
-    record1_field(0), trigger_table(table_arg)
+  Table_triggers_list(TABLE *table_arg)
+    :record1_field(0), trigger_table(table_arg),
+    m_has_unparseable_trigger(false)
   {
     bzero((char *)bodies, sizeof(bodies));
     bzero((char *)trigger_fields, sizeof(trigger_fields));
@@ -176,6 +198,8 @@ public:
 
   void mark_fields_used(trg_event_type event);
 
+  void set_parse_error_message(char *error_message);
+
   friend class Item_trigger_field;
 
   bool add_tables_and_routines_for_triggers(THD *thd,
@@ -193,6 +217,16 @@ private:
                                      const char *new_db_name,
                                      LEX_STRING *old_table_name,
                                      LEX_STRING *new_table_name);
+
+  bool check_for_broken_triggers() 
+  {
+    if (m_has_unparseable_trigger)
+    {
+      my_message(ER_PARSE_ERROR, m_parse_error_message, MYF(0));
+      return true;
+    }
+    return false;
+  }
 };
 
 extern const LEX_STRING trg_action_time_type_names[];

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2011-02-21 15:49:03 +0000
+++ b/sql/sql_update.cc	2011-06-16 06:24:00 +0000
@@ -1071,17 +1071,27 @@ bool unsafe_key_update(TABLE_LIST *leave
             return true;
           }
 
-          if (primkey_clustered &&
-              (bitmap_is_set(table1->write_set, table1->s->primary_key) ||
-               bitmap_is_set(table2->write_set, table2->s->primary_key)))
+          if (primkey_clustered)
           {
-            // Clustered primary key is updated
-            my_error(ER_MULTI_UPDATE_KEY_CONFLICT, MYF(0),
-                     tl->belong_to_view ? tl->belong_to_view->alias
-                                        : tl->alias,
-                     tl2->belong_to_view ? tl2->belong_to_view->alias
-                                         : tl2->alias);
-            return true;
+            // The primary key can cover multiple columns
+            KEY key_info= table1->key_info[table1->s->primary_key];
+            KEY_PART_INFO *key_part= key_info.key_part;
+            KEY_PART_INFO *key_part_end= key_part + key_info.key_parts;
+
+            for (;key_part != key_part_end; ++key_part)
+            {
+              if (bitmap_is_set(table1->write_set, key_part->fieldnr-1) ||
+                  bitmap_is_set(table2->write_set, key_part->fieldnr-1))
+              {
+                // Clustered primary key is updated
+                my_error(ER_MULTI_UPDATE_KEY_CONFLICT, MYF(0),
+                         tl->belong_to_view ? tl->belong_to_view->alias
+                         : tl->alias,
+                         tl2->belong_to_view ? tl2->belong_to_view->alias
+                         : tl2->alias);
+                return true;
+              }
+            }
           }
         }
       }

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2011-05-12 05:23:16 +0000
+++ b/sql/sql_yacc.yy	2011-06-09 17:07:03 +0000
@@ -2227,16 +2227,19 @@ opt_ev_status:
         | ENABLE_SYM
           {
             Lex->event_parse_data->status= Event_parse_data::ENABLED;
+            Lex->event_parse_data->status_changed= true;
             $$= 1;
           }
         | DISABLE_SYM ON SLAVE
           {
             Lex->event_parse_data->status= Event_parse_data::SLAVESIDE_DISABLED;
+            Lex->event_parse_data->status_changed= true; 
             $$= 1;
           }
         | DISABLE_SYM
           {
             Lex->event_parse_data->status= Event_parse_data::DISABLED;
+            Lex->event_parse_data->status_changed= true;
             $$= 1;
           }
         ;

=== modified file 'sql/table.h'
--- a/sql/table.h	2011-03-25 09:06:07 +0000
+++ b/sql/table.h	2011-06-16 06:24:00 +0000
@@ -627,8 +627,8 @@ struct TABLE_SHARE
   uint db_options_in_use;		/* Options in use */
   uint db_record_offset;		/* if HA_REC_IN_SEQ */
   uint rowid_field_offset;		/* Field_nr +1 to rowid field */
-  /* Index of auto-updated TIMESTAMP field in field array */
-  uint primary_key;
+  /* Primary key index number, used in TABLE::key_info[] */
+  uint primary_key;                     
   uint next_number_index;               /* autoincrement key number */
   uint next_number_key_offset;          /* autoinc keypart offset in a key */
   uint next_number_keypart;             /* autoinc keypart number in a key */

=== modified file 'storage/archive/azio.c'
--- a/storage/archive/azio.c	2010-07-26 15:54:20 +0000
+++ b/storage/archive/azio.c	2011-06-03 07:49:05 +0000
@@ -114,6 +114,15 @@ int az_open (azio_stream *s, const char
 
   errno = 0;
   s->file = fd < 0 ? my_open(path, Flags, MYF(0)) : fd;
+  DBUG_EXECUTE_IF("simulate_archive_open_failure",
+  {
+    if (s->file >= 0)
+    {
+      my_close(s->file, MYF(0));
+      s->file= -1;
+      my_errno= EMFILE;
+    }
+  });
 
   if (s->file < 0 ) 
   {

=== modified file 'storage/archive/ha_archive.cc'
--- a/storage/archive/ha_archive.cc	2011-05-10 13:24:34 +0000
+++ b/storage/archive/ha_archive.cc	2011-06-03 07:49:05 +0000
@@ -1685,11 +1685,12 @@ int ha_archive::check(THD* thd, HA_CHECK
   azflush(&(share->archive_write), Z_SYNC_FLUSH);
   mysql_mutex_unlock(&share->mutex);
 
+  if (init_archive_reader())
+    DBUG_RETURN(HA_ADMIN_CORRUPT);
   /*
     Now we will rewind the archive file so that we are positioned at the 
     start of the file.
   */
-  init_archive_reader();
   read_data_header(&archive);
   while (!(rc= get_row(&archive, table->record[0])))
     count--;

=== modified file 'storage/innobase/btr/btr0btr.c'
--- a/storage/innobase/btr/btr0btr.c	2011-02-08 11:39:24 +0000
+++ b/storage/innobase/btr/btr0btr.c	2011-06-16 13:14:16 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -2275,7 +2275,7 @@ btr_attach_half_pages(
 /*==================*/
 	dict_index_t*	index,		/*!< in: the index tree */
 	buf_block_t*	block,		/*!< in/out: page to be split */
-	rec_t*		split_rec,	/*!< in: first record on upper
+	const rec_t*	split_rec,	/*!< in: first record on upper
 					half page */
 	buf_block_t*	new_block,	/*!< in/out: the new half page */
 	ulint		direction,	/*!< in: FSP_UP or FSP_DOWN */
@@ -2967,15 +2967,16 @@ btr_node_ptr_delete(
 	ut_a(err == DB_SUCCESS);
 
 	if (!compressed) {
-		btr_cur_compress_if_useful(&cursor, mtr);
+		btr_cur_compress_if_useful(&cursor, FALSE, mtr);
 	}
 }
 
 /*************************************************************//**
 If page is the only on its level, this function moves its records to the
-father page, thus reducing the tree height. */
+father page, thus reducing the tree height.
+@return father block */
 static
-void
+buf_block_t*
 btr_lift_page_up(
 /*=============*/
 	dict_index_t*	index,	/*!< in: index tree */
@@ -3092,6 +3093,8 @@ btr_lift_page_up(
 	}
 	ut_ad(page_validate(father_page, index));
 	ut_ad(btr_check_node_ptr(index, father_block, mtr));
+
+	return(father_block);
 }
 
 /*************************************************************//**
@@ -3108,11 +3111,13 @@ UNIV_INTERN
 ibool
 btr_compress(
 /*=========*/
-	btr_cur_t*	cursor,	/*!< in: cursor on the page to merge or lift;
-				the page must not be empty: in record delete
-				use btr_discard_page if the page would become
-				empty */
-	mtr_t*		mtr)	/*!< in: mtr */
+	btr_cur_t*	cursor,	/*!< in/out: cursor on the page to merge
+				or lift; the page must not be empty:
+				when deleting records, use btr_discard_page()
+				if the page would become empty */
+	ibool		adjust,	/*!< in: TRUE if should adjust the
+				cursor position even if compression occurs */
+	mtr_t*		mtr)	/*!< in/out: mini-transaction */
 {
 	dict_index_t*	index;
 	ulint		space;
@@ -3130,12 +3135,14 @@ btr_compress(
 	ulint*		offsets;
 	ulint		data_size;
 	ulint		n_recs;
+	ulint		nth_rec = 0; /* remove bogus warning */
 	ulint		max_ins_size;
 	ulint		max_ins_size_reorg;
 
 	block = btr_cur_get_block(cursor);
 	page = btr_cur_get_page(cursor);
 	index = btr_cur_get_index(cursor);
+
 	ut_a((ibool) !!page_is_comp(page) == dict_table_is_comp(index->table));
 
 	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
@@ -3156,6 +3163,10 @@ btr_compress(
 	offsets = btr_page_get_father_block(NULL, heap, index, block, mtr,
 					    &father_cursor);
 
+	if (adjust) {
+		nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
+	}
+
 	/* Decide the page to which we try to merge and which will inherit
 	the locks */
 
@@ -3182,9 +3193,9 @@ btr_compress(
 	} else {
 		/* The page is the only one on the level, lift the records
 		to the father */
-		btr_lift_page_up(index, block, mtr);
-		mem_heap_free(heap);
-		return(TRUE);
+
+		merge_block = btr_lift_page_up(index, block, mtr);
+		goto func_exit;
 	}
 
 	n_recs = page_get_n_recs(page);
@@ -3266,6 +3277,10 @@ err_exit:
 
 		btr_node_ptr_delete(index, block, mtr);
 		lock_update_merge_left(merge_block, orig_pred, block);
+
+		if (adjust) {
+			nth_rec += page_rec_get_n_recs_before(orig_pred);
+		}
 	} else {
 		rec_t*		orig_succ;
 #ifdef UNIV_BTR_DEBUG
@@ -3330,7 +3345,6 @@ err_exit:
 	}
 
 	btr_blob_dbg_remove(page, index, "btr_compress");
-	mem_heap_free(heap);
 
 	if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
 		/* Update the free bits of the B-tree page in the
@@ -3382,6 +3396,16 @@ err_exit:
 	btr_page_free(index, block, mtr);
 
 	ut_ad(btr_check_node_ptr(index, merge_block, mtr));
+func_exit:
+	mem_heap_free(heap);
+
+	if (adjust) {
+		btr_cur_position(
+			index,
+			page_rec_get_nth(merge_block->frame, nth_rec),
+			merge_block, cursor);
+	}
+
 	return(TRUE);
 }
 

=== modified file 'storage/innobase/btr/btr0cur.c'
--- a/storage/innobase/btr/btr0cur.c	2011-05-24 08:41:31 +0000
+++ b/storage/innobase/btr/btr0cur.c	2011-06-17 20:29:19 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, Google Inc.
 
 Portions of this file contain modifications contributed and copyrighted by
@@ -1972,7 +1972,6 @@ btr_cur_optimistic_update(
 	ulint		old_rec_size;
 	dtuple_t*	new_entry;
 	roll_ptr_t	roll_ptr;
-	trx_t*		trx;
 	mem_heap_t*	heap;
 	ulint		i;
 	ulint		n_ext;
@@ -1989,6 +1988,10 @@ btr_cur_optimistic_update(
 
 	heap = mem_heap_create(1024);
 	offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+	ut_a(!rec_offs_any_null_extern(rec, offsets)
+	     || trx_is_recv(thr_get_trx(thr)));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
 
 #ifdef UNIV_DEBUG
 	if (btr_cur_print_record_ops && thr) {
@@ -2111,13 +2114,11 @@ any_extern:
 
 	page_cur_move_to_prev(page_cursor);
 
-	trx = thr_get_trx(thr);
-
 	if (!(flags & BTR_KEEP_SYS_FLAG)) {
 		row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
 					      roll_ptr);
 		row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
-					      trx->id);
+					      thr_get_trx(thr)->id);
 	}
 
 	/* There are no externally stored columns in new_entry */
@@ -2203,7 +2204,9 @@ btr_cur_pessimistic_update(
 /*=======================*/
 	ulint		flags,	/*!< in: undo logging, locking, and rollback
 				flags */
-	btr_cur_t*	cursor,	/*!< in: cursor on the record to update */
+	btr_cur_t*	cursor,	/*!< in/out: cursor on the record to update;
+				cursor may become invalid if *big_rec == NULL
+				|| !(flags & BTR_KEEP_POS_FLAG) */
 	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap, or NULL */
 	big_rec_t**	big_rec,/*!< out: big rec vector whose fields have to
 				be stored externally by the caller, or NULL */
@@ -2342,7 +2345,7 @@ btr_cur_pessimistic_update(
 	record to be inserted: we have to remember which fields were such */
 
 	ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
-	offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, heap);
+	ut_ad(rec_offs_validate(rec, index, offsets));
 	n_ext += btr_push_update_extern_fields(new_entry, update, *heap);
 
 	if (UNIV_LIKELY_NULL(page_zip)) {
@@ -2365,6 +2368,10 @@ make_external:
 			err = DB_TOO_BIG_RECORD;
 			goto return_after_reservations;
 		}
+
+		ut_ad(page_is_leaf(page));
+		ut_ad(dict_index_is_clust(index));
+		ut_ad(flags & BTR_KEEP_POS_FLAG);
 	}
 
 	/* Store state of explicit locks on rec on the page infimum record,
@@ -2392,6 +2399,8 @@ make_external:
 	rec = btr_cur_insert_if_possible(cursor, new_entry, n_ext, mtr);
 
 	if (rec) {
+		page_cursor->rec = rec;
+
 		lock_rec_restore_from_page_infimum(btr_cur_get_block(cursor),
 						   rec, block);
 
@@ -2405,7 +2414,10 @@ make_external:
 						     rec, index, offsets, mtr);
 		}
 
-		btr_cur_compress_if_useful(cursor, mtr);
+		btr_cur_compress_if_useful(
+			cursor,
+			big_rec_vec != NULL && (flags & BTR_KEEP_POS_FLAG),
+			mtr);
 
 		if (page_zip && !dict_index_is_clust(index)
 		    && page_is_leaf(page)) {
@@ -2425,6 +2437,21 @@ make_external:
 		}
 	}
 
+	if (big_rec_vec) {
+		ut_ad(page_is_leaf(page));
+		ut_ad(dict_index_is_clust(index));
+		ut_ad(flags & BTR_KEEP_POS_FLAG);
+
+		/* btr_page_split_and_insert() in
+		btr_cur_pessimistic_insert() invokes
+		mtr_memo_release(mtr, index->lock, MTR_MEMO_X_LOCK).
+		We must keep the index->lock when we created a
+		big_rec, so that row_upd_clust_rec() can store the
+		big_rec in the same mini-transaction. */
+
+		mtr_x_lock(dict_index_get_lock(index), mtr);
+	}
+
 	/* Was the record to be updated positioned as the first user
 	record on its page? */
 	was_first = page_cur_is_before_first(page_cursor);
@@ -2440,6 +2467,7 @@ make_external:
 	ut_a(rec);
 	ut_a(err == DB_SUCCESS);
 	ut_a(dummy_big_rec == NULL);
+	page_cursor->rec = rec;
 
 	if (dict_index_is_sec_or_ibuf(index)) {
 		/* Update PAGE_MAX_TRX_ID in the index page header.
@@ -2498,6 +2526,39 @@ return_after_reservations:
 	return(err);
 }
 
+/**************************************************************//**
+Commits and restarts a mini-transaction so that it will retain an
+x-lock on index->lock and the cursor page. */
+UNIV_INTERN
+void
+btr_cur_mtr_commit_and_start(
+/*=========================*/
+	btr_cur_t*	cursor,	/*!< in: cursor */
+	mtr_t*		mtr)	/*!< in/out: mini-transaction */
+{
+	buf_block_t*	block;
+
+	block = btr_cur_get_block(cursor);
+
+	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(cursor->index),
+				MTR_MEMO_X_LOCK));
+	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+	/* Keep the locks across the mtr_commit(mtr). */
+	rw_lock_x_lock(dict_index_get_lock(cursor->index));
+	rw_lock_x_lock(&block->lock);
+	mutex_enter(&block->mutex);
+	buf_block_buf_fix_inc(block, __FILE__, __LINE__);
+	mutex_exit(&block->mutex);
+	/* Write out the redo log. */
+	mtr_commit(mtr);
+	mtr_start(mtr);
+	/* Reassociate the locks with the mini-transaction.
+	They will be released on mtr_commit(mtr). */
+	mtr_memo_push(mtr, dict_index_get_lock(cursor->index),
+		      MTR_MEMO_X_LOCK);
+	mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
+}
+
 /*==================== B-TREE DELETE MARK AND UNMARK ===============*/
 
 /****************************************************************//**
@@ -2878,10 +2939,12 @@ UNIV_INTERN
 ibool
 btr_cur_compress_if_useful(
 /*=======================*/
-	btr_cur_t*	cursor,	/*!< in: cursor on the page to compress;
-				cursor does not stay valid if compression
-				occurs */
-	mtr_t*		mtr)	/*!< in: mtr */
+	btr_cur_t*	cursor,	/*!< in/out: cursor on the page to compress;
+				cursor does not stay valid if !adjust and
+				compression occurs */
+	ibool		adjust,	/*!< in: TRUE if should adjust the
+				cursor position even if compression occurs */
+	mtr_t*		mtr)	/*!< in/out: mini-transaction */
 {
 	ut_ad(mtr_memo_contains(mtr,
 				dict_index_get_lock(btr_cur_get_index(cursor)),
@@ -2890,7 +2953,7 @@ btr_cur_compress_if_useful(
 				MTR_MEMO_PAGE_X_FIX));
 
 	return(btr_cur_compress_recommendation(cursor, mtr)
-	       && btr_compress(cursor, mtr));
+	       && btr_compress(cursor, adjust, mtr));
 }
 
 /*******************************************************//**
@@ -3132,7 +3195,7 @@ return_after_reservations:
 	mem_heap_free(heap);
 
 	if (ret == FALSE) {
-		ret = btr_cur_compress_if_useful(cursor, mtr);
+		ret = btr_cur_compress_if_useful(cursor, FALSE, mtr);
 	}
 
 	if (n_extents > 0) {
@@ -4092,7 +4155,7 @@ btr_blob_free(
 	    && buf_block_get_space(block) == space
 	    && buf_block_get_page_no(block) == page_no) {
 
-		if (buf_LRU_free_block(&block->page, all) != BUF_LRU_FREED
+		if (!buf_LRU_free_block(&block->page, all)
 		    && all && block->page.zip.data) {
 			/* Attempt to deallocate the uncompressed page
 			if the whole block cannot be deallocted. */

=== modified file 'storage/innobase/buf/buf0buddy.c'
--- a/storage/innobase/buf/buf0buddy.c	2011-01-25 08:51:13 +0000
+++ b/storage/innobase/buf/buf0buddy.c	2011-06-17 20:29:19 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 2006, 2010, Innobase Oy. 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 the Free Software
@@ -56,6 +56,14 @@ buf_buddy_get(
 	}
 }
 
+/** Validate a given zip_free list. */
+#define BUF_BUDDY_LIST_VALIDATE(b, i)				\
+	UT_LIST_VALIDATE(list, buf_page_t,			\
+			 b->zip_free[i],			\
+			 ut_ad(buf_page_get_state(		\
+				       ut_list_node_313)	\
+			       == BUF_BLOCK_ZIP_FREE))
+
 /**********************************************************************//**
 Add a block to the head of the appropriate buddy free list. */
 UNIV_INLINE
@@ -67,21 +75,11 @@ buf_buddy_add_to_free(
 	ulint		i)		/*!< in: index of
 					buf_pool->zip_free[] */
 {
-#ifdef UNIV_DEBUG_VALGRIND
-	buf_page_t*	b  = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
-
-	if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
-
 	ut_ad(buf_pool_mutex_own(buf_pool));
 	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);
 
-#ifdef UNIV_DEBUG_VALGRIND
-	if (b) UNIV_MEM_FREE(b, BUF_BUDDY_LOW << i);
-	UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
 }
 
 /**********************************************************************//**
@@ -95,25 +93,18 @@ buf_buddy_remove_from_free(
 	ulint		i)		/*!< in: index of
 					buf_pool->zip_free[] */
 {
-#ifdef UNIV_DEBUG_VALGRIND
+#ifdef UNIV_DEBUG
 	buf_page_t*	prev = UT_LIST_GET_PREV(list, bpage);
 	buf_page_t*	next = UT_LIST_GET_NEXT(list, bpage);
 
-	if (prev) UNIV_MEM_VALID(prev, BUF_BUDDY_LOW << i);
-	if (next) UNIV_MEM_VALID(next, BUF_BUDDY_LOW << i);
-
 	ut_ad(!prev || buf_page_get_state(prev) == BUF_BLOCK_ZIP_FREE);
 	ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
-#endif /* UNIV_DEBUG_VALGRIND */
+#endif /* UNIV_DEBUG */
 
 	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);
 
-#ifdef UNIV_DEBUG_VALGRIND
-	if (prev) UNIV_MEM_FREE(prev, BUF_BUDDY_LOW << i);
-	if (next) UNIV_MEM_FREE(next, BUF_BUDDY_LOW << i);
-#endif /* UNIV_DEBUG_VALGRIND */
 }
 
 /**********************************************************************//**
@@ -130,17 +121,13 @@ buf_buddy_alloc_zip(
 
 	ut_ad(buf_pool_mutex_own(buf_pool));
 	ut_a(i < BUF_BUDDY_SIZES);
+	ut_a(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
+
+	ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
 
-#ifndef UNIV_DEBUG_VALGRIND
-	/* Valgrind would complain about accessing free memory. */
-	ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
-			      ut_ad(buf_page_get_state(ut_list_node_313)
-				    == BUF_BLOCK_ZIP_FREE)));
-#endif /* !UNIV_DEBUG_VALGRIND */
 	bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
 
 	if (bpage) {
-		UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
 		ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
 
 		buf_buddy_remove_from_free(buf_pool, bpage, i);
@@ -159,13 +146,10 @@ buf_buddy_alloc_zip(
 		}
 	}
 
-#ifdef UNIV_DEBUG
 	if (bpage) {
-		memset(bpage, ~i, BUF_BUDDY_LOW << i);
+		ut_d(memset(bpage, ~i, BUF_BUDDY_LOW << i));
+		UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i);
 	}
-#endif /* UNIV_DEBUG */
-
-	UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i);
 
 	return(bpage);
 }
@@ -253,6 +237,7 @@ buf_buddy_alloc_from(
 {
 	ulint	offs	= BUF_BUDDY_LOW << j;
 	ut_ad(j <= BUF_BUDDY_SIZES);
+	ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
 	ut_ad(j >= i);
 	ut_ad(!ut_align_offset(buf, offs));
 
@@ -266,13 +251,7 @@ buf_buddy_alloc_from(
 		bpage = (buf_page_t*) ((byte*) buf + offs);
 		ut_d(memset(bpage, j, BUF_BUDDY_LOW << j));
 		bpage->state = BUF_BLOCK_ZIP_FREE;
-#ifndef UNIV_DEBUG_VALGRIND
-		/* Valgrind would complain about accessing free memory. */
-		ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
-				      ut_ad(buf_page_get_state(
-						    ut_list_node_313)
-					    == BUF_BLOCK_ZIP_FREE)));
-#endif /* !UNIV_DEBUG_VALGRIND */
+		ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i));
 		buf_buddy_add_to_free(buf_pool, bpage, j);
 	}
 
@@ -282,8 +261,8 @@ 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 only be released and reacquired if lru != NULL.
-@return	allocated block, possibly NULL if lru==NULL */
+The buf_pool_mutex may be released and reacquired.
+@return        allocated block, never NULL */
 UNIV_INTERN
 void*
 buf_buddy_alloc_low(
@@ -295,13 +274,14 @@ buf_buddy_alloc_low(
 					will be assigned TRUE if storage was
 					allocated from the LRU list and
 					buf_pool->mutex was temporarily
-					released, or NULL if the LRU list
-					should not be used */
+					released, */
 {
 	buf_block_t*	block;
 
+	ut_ad(lru);
 	ut_ad(buf_pool_mutex_own(buf_pool));
 	ut_ad(!mutex_own(&buf_pool->zip_mutex));
+	ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
 
 	if (i < BUF_BUDDY_SIZES) {
 		/* Try to allocate from the buddy system. */
@@ -320,11 +300,6 @@ buf_buddy_alloc_low(
 		goto alloc_big;
 	}
 
-	if (!lru) {
-
-		return(NULL);
-	}
-
 	/* Try replacing an uncompressed page in the buffer pool. */
 	buf_pool_mutex_exit(buf_pool);
 	block = buf_LRU_get_free_block(buf_pool);
@@ -343,63 +318,6 @@ func_exit:
 }
 
 /**********************************************************************//**
-Try to relocate the control block of a compressed page.
-@return	TRUE if relocated */
-static
-ibool
-buf_buddy_relocate_block(
-/*=====================*/
-	buf_page_t*	bpage,	/*!< in: block to relocate */
-	buf_page_t*	dpage)	/*!< in: free block to relocate to */
-{
-	buf_page_t*	b;
-	buf_pool_t*	buf_pool = buf_pool_from_bpage(bpage);
-
-	ut_ad(buf_pool_mutex_own(buf_pool));
-
-	switch (buf_page_get_state(bpage)) {
-	case BUF_BLOCK_ZIP_FREE:
-	case BUF_BLOCK_NOT_USED:
-	case BUF_BLOCK_READY_FOR_USE:
-	case BUF_BLOCK_FILE_PAGE:
-	case BUF_BLOCK_MEMORY:
-	case BUF_BLOCK_REMOVE_HASH:
-		ut_error;
-	case BUF_BLOCK_ZIP_DIRTY:
-		/* Cannot relocate dirty pages. */
-		return(FALSE);
-
-	case BUF_BLOCK_ZIP_PAGE:
-		break;
-	}
-
-	mutex_enter(&buf_pool->zip_mutex);
-
-	if (!buf_page_can_relocate(bpage)) {
-		mutex_exit(&buf_pool->zip_mutex);
-		return(FALSE);
-	}
-
-	buf_relocate(bpage, dpage);
-	ut_d(bpage->state = BUF_BLOCK_ZIP_FREE);
-
-	/* relocate buf_pool->zip_clean */
-	b = UT_LIST_GET_PREV(list, dpage);
-	UT_LIST_REMOVE(list, buf_pool->zip_clean, dpage);
-
-	if (b) {
-		UT_LIST_INSERT_AFTER(list, buf_pool->zip_clean, b, dpage);
-	} else {
-		UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, dpage);
-	}
-
-	UNIV_MEM_INVALID(bpage, sizeof *bpage);
-
-	mutex_exit(&buf_pool->zip_mutex);
-	return(TRUE);
-}
-
-/**********************************************************************//**
 Try to relocate a block.
 @return	TRUE if relocated */
 static
@@ -415,108 +333,91 @@ buf_buddy_relocate(
 	buf_page_t*	bpage;
 	const ulint	size	= BUF_BUDDY_LOW << i;
 	ullint		usec	= ut_time_us(NULL);
+	mutex_t*	mutex;
+	ulint		space;
+	ulint		page_no;
 
 	ut_ad(buf_pool_mutex_own(buf_pool));
 	ut_ad(!mutex_own(&buf_pool->zip_mutex));
 	ut_ad(!ut_align_offset(src, size));
 	ut_ad(!ut_align_offset(dst, size));
+	ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
 	UNIV_MEM_ASSERT_W(dst, size);
 
 	/* We assume that all memory from buf_buddy_alloc()
-	is used for either compressed pages or buf_page_t
-	objects covering compressed pages. */
+	is used for compressed page frames. */
 
 	/* We look inside the allocated objects returned by
-	buf_buddy_alloc() and assume that anything of
-	PAGE_ZIP_MIN_SIZE or larger is a compressed page that contains
-	a valid space_id and page_no in the page header.  Should the
-	fields be invalid, we will be unable to relocate the block.
-	We also assume that anything that fits sizeof(buf_page_t)
-	actually is a properly initialized buf_page_t object. */
-
-	if (size >= PAGE_ZIP_MIN_SIZE) {
-		/* This is a compressed page. */
-		mutex_t*	mutex;
-
-		/* 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
-		from free memory.  The memory is "owned" by the buddy
-		allocator (and it has been allocated from the buffer
-		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. */
-		ulint		space	= mach_read_from_4(
-			(const byte*) src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
-		ulint		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);
-		UNIV_MEM_VALID(&page_no, sizeof page_no);
-		bpage = buf_page_hash_get(buf_pool, space, page_no);
-
-		if (!bpage || bpage->zip.data != src) {
-			/* The block has probably been freshly
-			allocated by buf_LRU_get_free_block() but not
-			added to buf_pool->page_hash yet.  Obviously,
-			it cannot be relocated. */
+	buf_buddy_alloc() and assume that each block is a compressed
+	page that contains a valid space_id and page_no in the page
+	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
+	from free memory.  The memory is "owned" by the buddy
+	allocator (and it has been allocated from the buffer
+	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);
+	/* Suppress Valgrind warnings about conditional jump
+	on uninitialized value. */
+	UNIV_MEM_VALID(&space, sizeof space);
+	UNIV_MEM_VALID(&page_no, sizeof page_no);
+	bpage = buf_page_hash_get(buf_pool, space, page_no);
+
+	if (!bpage || bpage->zip.data != src) {
+		/* The block has probably been freshly
+		allocated by buf_LRU_get_free_block() but not
+		added to buf_pool->page_hash yet.  Obviously,
+		it cannot be relocated. */
 
-			return(FALSE);
-		}
-
-		ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
+		return(FALSE);
+	}
 
-		if (page_zip_get_size(&bpage->zip) != size) {
-			/* The block is of different size.  We would
-			have to relocate all blocks covered by src.
-			For the sake of simplicity, give up. */
-			ut_ad(page_zip_get_size(&bpage->zip) < size);
+	ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
 
-			return(FALSE);
-		}
+	if (page_zip_get_size(&bpage->zip) != size) {
+		/* The block is of different size.  We would
+		have to relocate all blocks covered by src.
+		For the sake of simplicity, give up. */
+		ut_ad(page_zip_get_size(&bpage->zip) < size);
 
-		/* The block must have been allocated, but it may
-		contain uninitialized data. */
-		UNIV_MEM_ASSERT_W(src, size);
-
-		mutex = buf_page_get_mutex(bpage);
-
-		mutex_enter(mutex);
-
-		if (buf_page_can_relocate(bpage)) {
-			/* Relocate the compressed page. */
-			ut_a(bpage->zip.data == src);
-			memcpy(dst, src, size);
-			bpage->zip.data = dst;
-			mutex_exit(mutex);
-success:
-			UNIV_MEM_INVALID(src, size);
-			{
-				buf_buddy_stat_t*	buddy_stat
-					= &buf_pool->buddy_stat[i];
-				buddy_stat->relocated++;
-				buddy_stat->relocated_usec
-					+= ut_time_us(NULL) - usec;
-			}
-			return(TRUE);
-		}
+		return(FALSE);
+	}
 
+	/* The block must have been allocated, but it may
+	contain uninitialized data. */
+	UNIV_MEM_ASSERT_W(src, size);
+
+	mutex = buf_page_get_mutex(bpage);
+
+	mutex_enter(mutex);
+
+	if (buf_page_can_relocate(bpage)) {
+		/* Relocate the compressed page. */
+		ut_a(bpage->zip.data == src);
+		memcpy(dst, src, size);
+		bpage->zip.data = dst;
 		mutex_exit(mutex);
-	} else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) {
-		/* This must be a buf_page_t object. */
-#if UNIV_WORD_SIZE == 4
-		/* On 32-bit systems, there is no padding in
-		buf_page_t.  On other systems, Valgrind could complain
-		about uninitialized pad bytes. */
-		UNIV_MEM_ASSERT_RW(src, size);
-#endif
-		if (buf_buddy_relocate_block(src, dst)) {
-
-			goto success;
+		UNIV_MEM_INVALID(src, size);
+		{
+			buf_buddy_stat_t*	buddy_stat
+				= &buf_pool->buddy_stat[i];
+			buddy_stat->relocated++;
+			buddy_stat->relocated_usec
+				+= ut_time_us(NULL) - usec;
 		}
+		return(TRUE);
 	}
 
+	mutex_exit(mutex);
 	return(FALSE);
 }
 
@@ -538,12 +439,13 @@ buf_buddy_free_low(
 	ut_ad(buf_pool_mutex_own(buf_pool));
 	ut_ad(!mutex_own(&buf_pool->zip_mutex));
 	ut_ad(i <= BUF_BUDDY_SIZES);
+	ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE));
 	ut_ad(buf_pool->buddy_stat[i].used > 0);
 
 	buf_pool->buddy_stat[i].used--;
 recombine:
 	UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i);
-	ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE);
+	((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE;
 
 	if (i == BUF_BUDDY_SIZES) {
 		buf_buddy_block_free(buf_pool, buf);
@@ -554,32 +456,36 @@ recombine:
 	ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i));
 	ut_ad(!buf_pool_contains_zip(buf_pool, buf));
 
-	/* Try to combine adjacent blocks. */
-
-	buddy = (buf_page_t*) buf_buddy_get(((byte*) buf), BUF_BUDDY_LOW << i);
-
-#ifndef UNIV_DEBUG_VALGRIND
-	/* Valgrind would complain about accessing free memory. */
-
-	if (buddy->state != BUF_BLOCK_ZIP_FREE) {
-
-		goto buddy_nonfree;
+	/* Do not recombine blocks if there are few free blocks.
+	We may waste up to 15360*max_len bytes to free blocks
+	(1024 + 2048 + 4096 + 8192 = 15360) */
+	if (UT_LIST_GET_LEN(buf_pool->zip_free[i]) < 16) {
+		goto func_exit;
 	}
-
-	/* The field buddy->state can only be trusted for free blocks.
-	If buddy->state == BUF_BLOCK_ZIP_FREE, the block is free if
-	it is in the free list. */
+ 
+	/* Try to combine adjacent blocks. */
+ 	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;
+ 	}
 #endif /* !UNIV_DEBUG_VALGRIND */
 
 	for (bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); bpage; ) {
-		UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
 		ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
 
 		if (bpage == buddy) {
-buddy_free:
 			/* The buddy is free: recombine */
 			buf_buddy_remove_from_free(buf_pool, bpage, i);
-buddy_free2:
+buddy_is_free:
 			ut_ad(buf_page_get_state(buddy) == BUF_BLOCK_ZIP_FREE);
 			ut_ad(!buf_pool_contains_zip(buf_pool, buddy));
 			i++;
@@ -589,21 +495,15 @@ buddy_free2:
 		}
 
 		ut_a(bpage != buf);
-
-		{
-			buf_page_t*	next = UT_LIST_GET_NEXT(list, bpage);
-			UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
-			bpage = next;
-		}
+		UNIV_MEM_ASSERT_W(bpage, BUF_BUDDY_LOW << i);
+		bpage = UT_LIST_GET_NEXT(list, bpage);
 	}
 
 #ifndef UNIV_DEBUG_VALGRIND
 buddy_nonfree:
-	/* Valgrind would complain about accessing free memory. */
-	ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
-			      ut_ad(buf_page_get_state(ut_list_node_313)
-				    == BUF_BLOCK_ZIP_FREE)));
-#endif /* UNIV_DEBUG_VALGRIND */
+#endif /* !UNIV_DEBUG_VALGRIND */
+
+	 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]);
@@ -611,100 +511,25 @@ buddy_nonfree:
 	if (bpage) {
 		/* Remove the block from the free list, because a successful
 		buf_buddy_relocate() will overwrite bpage->list. */
-
-		UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
 		buf_buddy_remove_from_free(buf_pool, bpage, i);
 
 		/* Try to relocate the buddy of buf to the free block. */
 		if (buf_buddy_relocate(buf_pool, buddy, bpage, i)) {
 
-			ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
-			goto buddy_free2;
+			buddy->state = BUF_BLOCK_ZIP_FREE;
+			goto buddy_is_free;
 		}
 
 		buf_buddy_add_to_free(buf_pool, bpage, i);
-
-		/* Try to relocate the buddy of the free block to buf. */
-		buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage),
-						    BUF_BUDDY_LOW << i);
-
-#ifndef UNIV_DEBUG_VALGRIND
-		/* Valgrind would complain about accessing free memory. */
-
-		/* The buddy must not be (completely) free, because we
-		always recombine adjacent free blocks.
-
-		(Parts of the buddy can be free in
-		buf_pool->zip_free[j] with j < i.) */
-		ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
-				      ut_ad(buf_page_get_state(
-						    ut_list_node_313)
-					    == BUF_BLOCK_ZIP_FREE
-					    && ut_list_node_313 != buddy)));
-#endif /* !UNIV_DEBUG_VALGRIND */
-
-		if (buf_buddy_relocate(buf_pool, buddy, buf, i)) {
-
-			buf = bpage;
-			UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
-			ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
-			goto buddy_free;
-		}
 	}
 
+func_exit:
 	/* Free the block to the buddy list. */
 	bpage = buf;
-#ifdef UNIV_DEBUG
-	if (i < buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)) {
-		/* This area has most likely been allocated for at
-		least one compressed-only block descriptor.  Check
-		that there are no live objects in the area.  This is
-		not a complete check: it may yield false positives as
-		well as false negatives.  Also, due to buddy blocks
-		being recombined, it is possible (although unlikely)
-		that this branch is never reached. */
-
-		char* c;
-
-# ifndef UNIV_DEBUG_VALGRIND
-		/* Valgrind would complain about accessing
-		uninitialized memory.  Besides, Valgrind performs a
-		more exhaustive check, at every memory access. */
-		const buf_page_t* b = buf;
-		const buf_page_t* const b_end = (buf_page_t*)
-			((char*) b + (BUF_BUDDY_LOW << i));
-
-		for (; b < b_end; b++) {
-			/* Avoid false positives (and cause false
-			negatives) by checking for b->space < 1000. */
-
-			if ((b->state == BUF_BLOCK_ZIP_PAGE
-			     || b->state == BUF_BLOCK_ZIP_DIRTY)
-			    && b->space > 0 && b->space < 1000) {
-				fprintf(stderr,
-					"buddy dirty %p %u (%u,%u) %p,%lu\n",
-					(void*) b,
-					b->state, b->space, b->offset,
-					buf, i);
-			}
-		}
-# endif /* !UNIV_DEBUG_VALGRIND */
 
-		/* Scramble the block.  This should make any pointers
-		invalid and trigger a segmentation violation.  Because
-		the scrambling can be reversed, it may be possible to
-		track down the object pointing to the freed data by
-		dereferencing the unscrambled bpage->LRU or
-		bpage->list pointers. */
-		for (c = (char*) buf + (BUF_BUDDY_LOW << i);
-		     c-- > (char*) buf; ) {
-			*c = ~*c ^ i;
-		}
-	} else {
-		/* Fill large blocks with a constant pattern. */
-		memset(bpage, i, BUF_BUDDY_LOW << i);
-	}
-#endif /* UNIV_DEBUG */
+	/* Fill large blocks with a constant pattern. */
+	ut_d(memset(bpage, i, BUF_BUDDY_LOW << i));
+	UNIV_MEM_INVALID(bpage, BUF_BUDDY_LOW << i);
 	bpage->state = BUF_BLOCK_ZIP_FREE;
 	buf_buddy_add_to_free(buf_pool, bpage, i);
 }

=== modified file 'storage/innobase/buf/buf0buf.c'
--- a/storage/innobase/buf/buf0buf.c	2011-05-24 08:41:31 +0000
+++ b/storage/innobase/buf/buf0buf.c	2011-06-20 04:37:36 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, Google Inc.
 
 Portions of this file contain modifications contributed and copyrighted by
@@ -1099,70 +1099,6 @@ buf_chunk_not_freed(
 	return(NULL);
 }
 
-/*********************************************************************//**
-Checks that all blocks in the buffer chunk are in BUF_BLOCK_NOT_USED state.
-@return	TRUE if all freed */
-static
-ibool
-buf_chunk_all_free(
-/*===============*/
-	const buf_chunk_t*	chunk)	/*!< in: chunk being checked */
-{
-	const buf_block_t*	block;
-	ulint			i;
-
-	block = chunk->blocks;
-
-	for (i = chunk->size; i--; block++) {
-
-		if (buf_block_get_state(block) != BUF_BLOCK_NOT_USED) {
-
-			return(FALSE);
-		}
-	}
-
-	return(TRUE);
-}
-
-/********************************************************************//**
-Frees a chunk of buffer frames. */
-static
-void
-buf_chunk_free(
-/*===========*/
-	buf_pool_t*	buf_pool,	/*!< in: buffer pool instance */
-	buf_chunk_t*	chunk)		/*!< out: chunk of buffers */
-{
-	buf_block_t*		block;
-	const buf_block_t*	block_end;
-
-	ut_ad(buf_pool_mutex_own(buf_pool));
-
-	block_end = chunk->blocks + chunk->size;
-
-	for (block = chunk->blocks; block < block_end; block++) {
-		ut_a(buf_block_get_state(block) == BUF_BLOCK_NOT_USED);
-		ut_a(!block->page.zip.data);
-
-		ut_ad(!block->page.in_LRU_list);
-		ut_ad(!block->in_unzip_LRU_list);
-		ut_ad(!block->page.in_flush_list);
-		/* Remove the block from the free list. */
-		ut_ad(block->page.in_free_list);
-		UT_LIST_REMOVE(list, buf_pool->free, (&block->page));
-
-		/* Free the latches. */
-		mutex_free(&block->mutex);
-		rw_lock_free(&block->lock);
-#ifdef UNIV_SYNC_DEBUG
-		rw_lock_free(&block->debug_latch);
-#endif /* UNIV_SYNC_DEBUG */
-		UNIV_MEM_UNDESC(block);
-	}
-
-	os_mem_free_large(chunk->mem, chunk->mem_size);
-}
-
 /********************************************************************//**
 Set buffer pool size variables after resizing it */
 static
@@ -1272,8 +1208,6 @@ buf_pool_free_instance(
 	chunk = chunks + buf_pool->n_chunks;
 
 	while (--chunk >= chunks) {
-		/* Bypass the checks of buf_chunk_free(), since they
-		would fail at shutdown. */
 		os_mem_free_large(chunk->mem, chunk->mem_size);
 	}
 
@@ -1533,281 +1467,6 @@ buf_relocate(
 }
 
 /********************************************************************//**
-Shrinks a buffer pool instance. */
-static
-void
-buf_pool_shrink_instance(
-/*=====================*/
-	buf_pool_t*	buf_pool,	/*!< in: buffer pool instance */
-	ulint		chunk_size)	/*!< in: number of pages to remove */
-{
-	buf_chunk_t*	chunks;
-	buf_chunk_t*	chunk;
-	ulint		max_size;
-	ulint		max_free_size;
-	buf_chunk_t*	max_chunk;
-	buf_chunk_t*	max_free_chunk;
-
-	ut_ad(!buf_pool_mutex_own(buf_pool));
-
-try_again:
-	btr_search_disable(); /* Empty the adaptive hash index again */
-	buf_pool_mutex_enter(buf_pool);
-
-shrink_again:
-	if (buf_pool->n_chunks <= 1) {
-
-		/* Cannot shrink if there is only one chunk */
-		goto func_done;
-	}
-
-	/* Search for the largest free chunk
-	not larger than the size difference */
-	chunks = buf_pool->chunks;
-	chunk = chunks + buf_pool->n_chunks;
-	max_size = max_free_size = 0;
-	max_chunk = max_free_chunk = NULL;
-
-	while (--chunk >= chunks) {
-		if (chunk->size <= chunk_size
-		    && chunk->size > max_free_size) {
-			if (chunk->size > max_size) {
-				max_size = chunk->size;
-				max_chunk = chunk;
-			}
-
-			if (buf_chunk_all_free(chunk)) {
-				max_free_size = chunk->size;
-				max_free_chunk = chunk;
-			}
-		}
-	}
-
-	if (!max_free_size) {
-
-		ulint		dirty	= 0;
-		ulint		nonfree	= 0;
-		buf_block_t*	block;
-		buf_block_t*	bend;
-
-		/* Cannot shrink: try again later
-		(do not assign srv_buf_pool_old_size) */
-		if (!max_chunk) {
-
-			goto func_exit;
-		}
-
-		block = max_chunk->blocks;
-		bend = block + max_chunk->size;
-
-		/* Move the blocks of chunk to the end of the
-		LRU list and try to flush them. */
-		for (; block < bend; block++) {
-			switch (buf_block_get_state(block)) {
-			case BUF_BLOCK_NOT_USED:
-				continue;
-			case BUF_BLOCK_FILE_PAGE:
-				break;
-			default:
-				nonfree++;
-				continue;
-			}
-
-			mutex_enter(&block->mutex);
-			/* The following calls will temporarily
-			release block->mutex and buf_pool->mutex.
-			Therefore, we have to always retry,
-			even if !dirty && !nonfree. */
-
-			if (!buf_flush_ready_for_replace(&block->page)) {
-
-				buf_LRU_make_block_old(&block->page);
-				dirty++;
-			} else if (buf_LRU_free_block(&block->page, TRUE)
-				   != BUF_LRU_FREED) {
-				nonfree++;
-			}
-
-			mutex_exit(&block->mutex);
-		}
-
-		buf_pool_mutex_exit(buf_pool);
-
-		/* Request for a flush of the chunk if it helps.
-		Do not flush if there are non-free blocks, since
-		flushing will not make the chunk freeable. */
-		if (nonfree) {
-			/* Avoid busy-waiting. */
-			os_thread_sleep(100000);
-		} else if (dirty
-			   && buf_flush_LRU(buf_pool, dirty)
-			      == ULINT_UNDEFINED) {
-
-			buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU);
-		}
-
-		goto try_again;
-	}
-
-	max_size = max_free_size;
-	max_chunk = max_free_chunk;
-
-	buf_pool->old_pool_size = buf_pool->curr_pool_size;
-
-	/* Rewrite buf_pool->chunks.  Copy everything but max_chunk. */
-	chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
-	memcpy(chunks, buf_pool->chunks,
-	       (max_chunk - buf_pool->chunks) * sizeof *chunks);
-	memcpy(chunks + (max_chunk - buf_pool->chunks),
-	       max_chunk + 1,
-	       buf_pool->chunks + buf_pool->n_chunks
-	       - (max_chunk + 1));
-	ut_a(buf_pool->curr_size > max_chunk->size);
-	buf_pool->curr_size -= max_chunk->size;
-	buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
-	chunk_size -= max_chunk->size;
-	buf_chunk_free(buf_pool, max_chunk);
-	mem_free(buf_pool->chunks);
-	buf_pool->chunks = chunks;
-	buf_pool->n_chunks--;
-
-	/* Allow a slack of one megabyte. */
-	if (chunk_size > 1048576 / UNIV_PAGE_SIZE) {
-
-		goto shrink_again;
-	}
-	goto func_exit;
-
-func_done:
-	buf_pool->old_pool_size = buf_pool->curr_pool_size;
-func_exit:
-	buf_pool_mutex_exit(buf_pool);
-	btr_search_enable();
-}
-
-/********************************************************************//**
-Shrinks the buffer pool. */
-static
-void
-buf_pool_shrink(
-/*============*/
-	ulint	chunk_size)	/*!< in: number of pages to remove */
-{
-	ulint	i;
-
-	for (i = 0; i < srv_buf_pool_instances; i++) {
-		buf_pool_t*	buf_pool;
-		ulint		instance_chunk_size;
-
-		instance_chunk_size = chunk_size / srv_buf_pool_instances;
-		buf_pool = buf_pool_from_array(i);
-		buf_pool_shrink_instance(buf_pool, instance_chunk_size);
-	}
-
-	buf_pool_set_sizes();
-}
-
-/********************************************************************//**
-Rebuild buf_pool->page_hash for a buffer pool instance. */
-static
-void
-buf_pool_page_hash_rebuild_instance(
-/*================================*/
-	buf_pool_t*	buf_pool)		/*!< in: buffer pool instance */
-{
-	ulint		i;
-	buf_page_t*	b;
-	buf_chunk_t*	chunk;
-	ulint		n_chunks;
-	hash_table_t*	zip_hash;
-	hash_table_t*	page_hash;
-
-	buf_pool_mutex_enter(buf_pool);
-
-	/* Free, create, and populate the hash table. */
-	hash_table_free(buf_pool->page_hash);
-	buf_pool->page_hash = page_hash = hash_create(2 * buf_pool->curr_size);
-	zip_hash = hash_create(2 * buf_pool->curr_size);
-
-	HASH_MIGRATE(buf_pool->zip_hash, zip_hash, buf_page_t, hash,
-		     BUF_POOL_ZIP_FOLD_BPAGE);
-
-	hash_table_free(buf_pool->zip_hash);
-	buf_pool->zip_hash = zip_hash;
-
-	/* Insert the uncompressed file pages to buf_pool->page_hash. */
-
-	chunk = buf_pool->chunks;
-	n_chunks = buf_pool->n_chunks;
-
-	for (i = 0; i < n_chunks; i++, chunk++) {
-		ulint		j;
-		buf_block_t*	block = chunk->blocks;
-
-		for (j = 0; j < chunk->size; j++, block++) {
-			if (buf_block_get_state(block)
-			    == BUF_BLOCK_FILE_PAGE) {
-				ut_ad(!block->page.in_zip_hash);
-				ut_ad(block->page.in_page_hash);
-
-				HASH_INSERT(buf_page_t, hash, page_hash,
-					    buf_page_address_fold(
-						    block->page.space,
-						    block->page.offset),
-					    &block->page);
-			}
-		}
-	}
-
-	/* Insert the compressed-only pages to buf_pool->page_hash.
-	All such blocks are either in buf_pool->zip_clean or
-	in buf_pool->flush_list. */
-
-	for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
-	     b = UT_LIST_GET_NEXT(list, b)) {
-		ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
-		ut_ad(!b->in_flush_list);
-		ut_ad(b->in_LRU_list);
-		ut_ad(b->in_page_hash);
-		ut_ad(!b->in_zip_hash);
-
-		HASH_INSERT(buf_page_t, hash, page_hash,
-			    buf_page_address_fold(b->space, b->offset), b);
-	}
-
-	buf_flush_list_mutex_enter(buf_pool);
-	for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
-	     b = UT_LIST_GET_NEXT(list, b)) {
-		ut_ad(b->in_flush_list);
-		ut_ad(b->in_LRU_list);
-		ut_ad(b->in_page_hash);
-		ut_ad(!b->in_zip_hash);
-
-		switch (buf_page_get_state(b)) {
-		case BUF_BLOCK_ZIP_DIRTY:
-			HASH_INSERT(buf_page_t, hash, page_hash,
-				    buf_page_address_fold(b->space,
-							  b->offset), b);
-			break;
-		case BUF_BLOCK_FILE_PAGE:
-			/* uncompressed page */
-			break;
-		case BUF_BLOCK_ZIP_FREE:
-		case BUF_BLOCK_ZIP_PAGE:
-		case BUF_BLOCK_NOT_USED:
-		case BUF_BLOCK_READY_FOR_USE:
-		case BUF_BLOCK_MEMORY:
-		case BUF_BLOCK_REMOVE_HASH:
-			ut_error;
-			break;
-		}
-	}
-
-	buf_flush_list_mutex_exit(buf_pool);
-	buf_pool_mutex_exit(buf_pool);
-}
-
-/********************************************************************
 Determine if a block is a sentinel for a buffer pool watch.
 @return	TRUE if a sentinel for a buffer pool watch, FALSE if not */
 UNIV_INTERN
@@ -1913,123 +1572,6 @@ buf_pool_watch_set(
 	return(NULL);
 }
 
-/********************************************************************//**
-Rebuild buf_pool->page_hash. */
-static
-void
-buf_pool_page_hash_rebuild(void)
-/*============================*/
-{
-	ulint   i;
-
-	for (i = 0; i < srv_buf_pool_instances; i++) {
-		buf_pool_page_hash_rebuild_instance(buf_pool_from_array(i));
-	}
-}
-
-/********************************************************************//**
-Increase the buffer pool size of one buffer pool instance. */
-static
-void
-buf_pool_increase_instance(
-/*=======================*/
-	buf_pool_t*	buf_pool,	/*!< in: buffer pool instane */
-	ulint		change_size)	/*!< in: new size of the pool */
-{
-	buf_chunk_t*	chunks;
-	buf_chunk_t*	chunk;
-
-	buf_pool_mutex_enter(buf_pool);
-	chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
-
-	memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks * sizeof *chunks);
-
-	chunk = &chunks[buf_pool->n_chunks];
-
-	if (!buf_chunk_init(buf_pool, chunk, change_size)) {
-		mem_free(chunks);
-	} else {
-		buf_pool->old_pool_size = buf_pool->curr_pool_size;
-		buf_pool->curr_size += chunk->size;
-		buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
-		mem_free(buf_pool->chunks);
-		buf_pool->chunks = chunks;
-		buf_pool->n_chunks++;
-	}
-
-	buf_pool_mutex_exit(buf_pool);
-}
-
-/********************************************************************//**
-Increase the buffer pool size. */
-static
-void
-buf_pool_increase(
-/*==============*/
-	ulint   change_size)
-{
-	ulint   i;
-
-	for (i = 0; i < srv_buf_pool_instances; i++) {
-		buf_pool_increase_instance(
-			buf_pool_from_array(i),
-			change_size / srv_buf_pool_instances);
-	}
-
-	buf_pool_set_sizes();
-}
-
-/********************************************************************//**
-Resizes the buffer pool. */
-UNIV_INTERN
-void
-buf_pool_resize(void)
-/*=================*/
-{
-	ulint	change_size;
-	ulint	min_change_size = 1048576 * srv_buf_pool_instances;
-
-	buf_pool_mutex_enter_all();
-
-  	if (srv_buf_pool_old_size == srv_buf_pool_size) {
-
-		buf_pool_mutex_exit_all();
-
-  		return;
-
-  	} else if (srv_buf_pool_curr_size + min_change_size
-		   > srv_buf_pool_size) {
-
-		change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
-			    / UNIV_PAGE_SIZE;
-
-		buf_pool_mutex_exit_all();
-
-  		/* Disable adaptive hash indexes and empty the index
-  		in order to free up memory in the buffer pool chunks. */
-		buf_pool_shrink(change_size);
-
-	} else if (srv_buf_pool_curr_size + min_change_size
-		   < srv_buf_pool_size) {
-
-  		/* Enlarge the buffer pool by at least one megabyte */
-
-		change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
-
-		buf_pool_mutex_exit_all();
-
-		buf_pool_increase(change_size);
-	} else {
-		srv_buf_pool_size = srv_buf_pool_old_size;
-
-		buf_pool_mutex_exit_all();
-
-		return;
-	}
-
-  	buf_pool_page_hash_rebuild();
-}
-
 /****************************************************************//**
 Remove the sentinel block for the watch before replacing it with a real block.
 buf_page_watch_clear() or buf_page_watch_occurred() will notice that
@@ -2365,7 +1907,7 @@ err_exit:
 		mutex_enter(block_mutex);
 
 		/* Discard the uncompressed page frame if possible. */
-		if (buf_LRU_free_block(bpage, FALSE) == BUF_LRU_FREED) {
+		if (buf_LRU_free_block(bpage, FALSE)) {
 
 			mutex_exit(block_mutex);
 			goto lookup;
@@ -2768,12 +2310,8 @@ loop:
 
 	if (block) {
 		/* If the guess is a compressed page descriptor that
-		has been allocated by buf_buddy_alloc(), it may have
-		been invalidated by buf_buddy_relocate().  In that
-		case, block could point to something that happens to
-		contain the expected bits in block->page.  Similarly,
-		the guess may be pointing to a buffer pool chunk that
-		has been released when resizing the buffer pool. */
+		has been allocated by buf_page_alloc_descriptor(),
+		it may have been freed by buf_relocate(). */
 
 		if (!buf_block_is_uncompressed(buf_pool, block)
 		    || offset != block->page.offset
@@ -2951,8 +2489,10 @@ wait_until_unfixed:
 
 		if (buf_page_get_state(&block->page)
 		    == BUF_BLOCK_ZIP_PAGE) {
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 			UT_LIST_REMOVE(list, buf_pool->zip_clean,
 				       &block->page);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
 			ut_ad(!block->page.in_flush_list);
 		} else {
 			/* Relocate buf_pool->flush_list. */
@@ -2978,11 +2518,10 @@ wait_until_unfixed:
 		mutex_exit(&buf_pool->zip_mutex);
 		buf_pool->n_pend_unzip++;
 
-		bpage->state = BUF_BLOCK_ZIP_FREE;
-		buf_buddy_free(buf_pool, bpage, sizeof *bpage);
-
 		buf_pool_mutex_exit(buf_pool);
 
+		buf_page_free_descriptor(bpage);
+
 		/* Decompress the page and apply buffered operations
 		while not holding buf_pool->mutex or block->mutex. */
 		success = buf_zip_decompress(block, srv_use_checksums);
@@ -3028,7 +2567,7 @@ wait_until_unfixed:
 		/* Try to evict the block from the buffer pool, to use the
 		insert buffer (change buffer) as much as possible. */
 
-		if (buf_LRU_free_block(&block->page, TRUE) == BUF_LRU_FREED) {
+		if (buf_LRU_free_block(&block->page, TRUE)) {
 			mutex_exit(&block->mutex);
 			if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
 				/* Set the watch, as it would have
@@ -3687,20 +3226,11 @@ err_exit:
 
 		mutex_exit(&block->mutex);
 	} else {
-		/* Defer buf_buddy_alloc() until after the block has
-		been found not to exist.  The buf_buddy_alloc() and
-		buf_buddy_free() calls may be expensive because of
-		buf_buddy_relocate(). */
-
 		/* The compressed page must be allocated before the
 		control block (bpage), in order to avoid the
 		invocation of buf_buddy_relocate_block() on
 		uninitialized data. */
 		data = buf_buddy_alloc(buf_pool, zip_size, &lru);
-		bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru);
-
-		/* Initialize the buf_pool pointer. */
-		bpage->buf_pool_index = buf_pool_index(buf_pool);
 
 		/* If buf_buddy_alloc() allocated storage from the LRU list,
 		it released and reacquired buf_pool->mutex.  Thus, we must
@@ -3716,8 +3246,6 @@ err_exit:
 
 				/* The block was added by some other thread. */
 				watch_page = NULL;
-				bpage->state = BUF_BLOCK_ZIP_FREE;
-				buf_buddy_free(buf_pool, bpage, sizeof *bpage);
 				buf_buddy_free(buf_pool, data, zip_size);
 
 				bpage = NULL;
@@ -3725,6 +3253,11 @@ 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;
@@ -3764,7 +3297,9 @@ err_exit:
 
 		/* The block must be put to the LRU list, to the old blocks */
 		buf_LRU_add_block(bpage, TRUE/* to old blocks */);
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 		buf_LRU_insert_zip_clean(bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
 
 		buf_page_set_io_fix(bpage, BUF_IO_READ);
 

=== modified file 'storage/innobase/buf/buf0flu.c'
--- a/storage/innobase/buf/buf0flu.c	2011-04-05 07:18:43 +0000
+++ b/storage/innobase/buf/buf0flu.c	2011-06-16 12:13:24 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
 
 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
@@ -524,7 +524,9 @@ buf_flush_remove(
 	case BUF_BLOCK_ZIP_DIRTY:
 		buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE);
 		UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 		buf_LRU_insert_zip_clean(bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
 		break;
 	case BUF_BLOCK_FILE_PAGE:
 		UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);

=== modified file 'storage/innobase/buf/buf0lru.c'
--- a/storage/innobase/buf/buf0lru.c	2011-02-28 13:39:07 +0000
+++ b/storage/innobase/buf/buf0lru.c	2011-06-17 20:29:19 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
 
 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
@@ -353,31 +353,34 @@ scan_again:
 
 	while (bpage != NULL) {
 		buf_page_t*	prev_bpage;
-		ibool		prev_bpage_buf_fix = FALSE;
+		mutex_t*	block_mutex = NULL;
 
 		ut_a(buf_page_in_file(bpage));
 
 		prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
 
 		/* bpage->space and bpage->io_fix are protected by
-		buf_pool->mutex and block_mutex.  It is safe to check
-		them while holding buf_pool->mutex only. */
+		buf_pool_mutex and block_mutex.  It is safe to check
+		them while holding buf_pool_mutex only. */
 
 		if (buf_page_get_space(bpage) != id) {
 			/* Skip this block, as it does not belong to
 			the space that is being invalidated. */
+			goto next_page;
 		} else if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
 			/* We cannot remove this page during this scan
 			yet; maybe the system is currently reading it
 			in, or flushing the modifications to the file */
 
 			all_freed = FALSE;
+			goto next_page;
 		} else {
-			mutex_t* block_mutex = buf_page_get_mutex(bpage);
+			block_mutex = buf_page_get_mutex(bpage);
 			mutex_enter(block_mutex);
 
 			if (bpage->buf_fix_count > 0) {
 
+				mutex_exit(block_mutex);
 				/* We cannot remove this page during
 				this scan yet; maybe the system is
 				currently reading it in, or flushing
@@ -387,106 +390,59 @@ scan_again:
 
 				goto next_page;
 			}
+		}
+
+		ut_ad(mutex_own(block_mutex));
 
 #ifdef UNIV_DEBUG
-			if (buf_debug_prints) {
-				fprintf(stderr,
-					"Dropping space %lu page %lu\n",
-					(ulong) buf_page_get_space(bpage),
-					(ulong) buf_page_get_page_no(bpage));
-			}
+		if (buf_debug_prints) {
+			fprintf(stderr,
+				"Dropping space %lu page %lu\n",
+				(ulong) buf_page_get_space(bpage),
+				(ulong) buf_page_get_page_no(bpage));
+		}
 #endif
-			if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
-				/* This is a compressed-only block
-				descriptor.  Ensure that prev_bpage
-				cannot be relocated when bpage is freed. */
-				if (UNIV_LIKELY(prev_bpage != NULL)) {
-					switch (buf_page_get_state(
-							prev_bpage)) {
-					case BUF_BLOCK_FILE_PAGE:
-						/* Descriptors of uncompressed
-						blocks will not be relocated,
-						because we are holding the
-						buf_pool->mutex. */
-						break;
-					case BUF_BLOCK_ZIP_PAGE:
-					case BUF_BLOCK_ZIP_DIRTY:
-						/* Descriptors of compressed-
-						only blocks can be relocated,
-						unless they are buffer-fixed.
-						Because both bpage and
-						prev_bpage are protected by
-						buf_pool_zip_mutex, it is
-						not necessary to acquire
-						further mutexes. */
-						ut_ad(&buf_pool->zip_mutex
-						      == block_mutex);
-						ut_ad(mutex_own(block_mutex));
-						prev_bpage_buf_fix = TRUE;
-						prev_bpage->buf_fix_count++;
-						break;
-					default:
-						ut_error;
-					}
-				}
-			} else if (((buf_block_t*) bpage)->is_hashed) {
-				ulint	page_no;
-				ulint	zip_size;
-
-				buf_pool_mutex_exit(buf_pool);
+		if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
+			/* This is a compressed-only block
+			descriptor. Do nothing. */
+		} else if (((buf_block_t*) bpage)->is_hashed) {
+			ulint	page_no;
+			ulint	zip_size;
 
-				zip_size = buf_page_get_zip_size(bpage);
-				page_no = buf_page_get_page_no(bpage);
+			buf_pool_mutex_exit(buf_pool);
 
-				mutex_exit(block_mutex);
+			zip_size = buf_page_get_zip_size(bpage);
+			page_no = buf_page_get_page_no(bpage);
 
-				/* Note that the following call will acquire
-				an S-latch on the page */
+			mutex_exit(block_mutex);
 
-				btr_search_drop_page_hash_when_freed(
-					id, zip_size, page_no);
-				goto scan_again;
-			}
+			/* Note that the following call will acquire
+			an S-latch on the page */
 
-			if (bpage->oldest_modification != 0) {
+			btr_search_drop_page_hash_when_freed(
+				id, zip_size, page_no);
+			goto scan_again;
+		}
 
-				buf_flush_remove(bpage);
-			}
+		if (bpage->oldest_modification != 0) {
 
-			/* Remove from the LRU list. */
+			buf_flush_remove(bpage);
+		}
 
-			if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
-			    != BUF_BLOCK_ZIP_FREE) {
-				buf_LRU_block_free_hashed_page((buf_block_t*)
-							       bpage);
-			} else {
-				/* The block_mutex should have been
-				released by buf_LRU_block_remove_hashed_page()
-				when it returns BUF_BLOCK_ZIP_FREE. */
-				ut_ad(block_mutex == &buf_pool->zip_mutex);
-				ut_ad(!mutex_own(block_mutex));
-
-				if (prev_bpage_buf_fix) {
-					/* We temporarily buffer-fixed
-					prev_bpage, so that
-					buf_buddy_free() could not
-					relocate it, in case it was a
-					compressed-only block
-					descriptor. */
-
-					mutex_enter(block_mutex);
-					ut_ad(prev_bpage->buf_fix_count > 0);
-					prev_bpage->buf_fix_count--;
-					mutex_exit(block_mutex);
-				}
+		/* Remove from the LRU list. */
 
-				goto next_page_no_mutex;
-			}
-next_page:
+		if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
+		    != BUF_BLOCK_ZIP_FREE) {
+			buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
 			mutex_exit(block_mutex);
+		} else {
+			/* The block_mutex should have been released
+			by buf_LRU_block_remove_hashed_page() when it
+			returns BUF_BLOCK_ZIP_FREE. */
+			ut_ad(block_mutex == &buf_pool->zip_mutex);
+			ut_ad(!mutex_own(block_mutex));
 		}
-
-next_page_no_mutex:
+next_page:
 		bpage = prev_bpage;
 	}
 
@@ -525,6 +481,7 @@ buf_LRU_invalidate_tablespace(
 	}
 }
 
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 /********************************************************************//**
 Insert a compressed block into buf_pool->zip_clean in the LRU order. */
 UNIV_INTERN
@@ -557,6 +514,7 @@ buf_LRU_insert_zip_clean(
 		UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, bpage);
 	}
 }
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
 
 /******************************************************************//**
 Try to free an uncompressed page of a compressed block from the unzip
@@ -600,7 +558,7 @@ buf_LRU_free_from_unzip_LRU_list(
 	     UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0);
 	     block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) {
 
-		enum buf_lru_free_block_status	freed;
+		ibool freed;
 
 		ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
 		ut_ad(block->in_unzip_LRU_list);
@@ -610,24 +568,9 @@ buf_LRU_free_from_unzip_LRU_list(
 		freed = buf_LRU_free_block(&block->page, FALSE);
 		mutex_exit(&block->mutex);
 
-		switch (freed) {
-		case BUF_LRU_FREED:
+		if (freed) {
 			return(TRUE);
-
-		case BUF_LRU_CANNOT_RELOCATE:
-			/* If we failed to relocate, try
-			regular LRU eviction. */
-			return(FALSE);
-
-		case BUF_LRU_NOT_FREED:
-			/* The block was buffer-fixed or I/O-fixed.
-			Keep looking. */
-			continue;
 		}
-
-		/* inappropriate return value from
-		buf_LRU_free_block() */
-		ut_error;
 	}
 
 	return(FALSE);
@@ -660,10 +603,9 @@ buf_LRU_free_from_common_LRU_list(
 	     UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0);
 	     bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
 
-		enum buf_lru_free_block_status	freed;
-		unsigned			accessed;
-		mutex_t*			block_mutex
-			= buf_page_get_mutex(bpage);
+		ibool		freed;
+		unsigned	accessed;
+		mutex_t*	block_mutex = buf_page_get_mutex(bpage);
 
 		ut_ad(buf_page_in_file(bpage));
 		ut_ad(bpage->in_LRU_list);
@@ -673,8 +615,7 @@ buf_LRU_free_from_common_LRU_list(
 		freed = buf_LRU_free_block(bpage, TRUE);
 		mutex_exit(block_mutex);
 
-		switch (freed) {
-		case BUF_LRU_FREED:
+		if (freed) {
 			/* Keep track of pages that are evicted without
 			ever being accessed. This gives us a measure of
 			the effectiveness of readahead */
@@ -682,21 +623,7 @@ buf_LRU_free_from_common_LRU_list(
 				++buf_pool->stat.n_ra_pages_evicted;
 			}
 			return(TRUE);
-
-		case BUF_LRU_NOT_FREED:
-			/* The block was dirty, buffer-fixed, or I/O-fixed.
-			Keep looking. */
-			continue;
-
-		case BUF_LRU_CANNOT_RELOCATE:
-			/* This should never occur, because we
-			want to discard the compressed page too. */
-			break;
 		}
-
-		/* inappropriate return value from
-		buf_LRU_free_block() */
-		ut_error;
 	}
 
 	return(FALSE);
@@ -1422,17 +1349,16 @@ buf_LRU_make_block_old(
 Try to free a block.  If bpage is a descriptor of a compressed-only
 page, the descriptor object will be freed as well.
 
-NOTE: If this function returns BUF_LRU_FREED, it will temporarily
+NOTE: If this function returns TRUE, it will temporarily
 release buf_pool->mutex.  Furthermore, the page frame will no longer be
 accessible via bpage.
 
 The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and
 release these two mutexes after the call.  No other
 buf_page_get_mutex() may be held when calling this function.
-@return BUF_LRU_FREED if freed, BUF_LRU_CANNOT_RELOCATE or
-BUF_LRU_NOT_FREED otherwise. */
+@return TRUE if freed, FALSE otherwise. */
 UNIV_INTERN
-enum buf_lru_free_block_status
+ibool
 buf_LRU_free_block(
 /*===============*/
 	buf_page_t*	bpage,	/*!< in: block to be freed */
@@ -1458,7 +1384,7 @@ buf_LRU_free_block(
 	if (!buf_page_can_relocate(bpage)) {
 
 		/* Do not free buffer-fixed or I/O-fixed blocks. */
-		return(BUF_LRU_NOT_FREED);
+		return(FALSE);
 	}
 
 #ifdef UNIV_IBUF_COUNT_DEBUG
@@ -1470,7 +1396,7 @@ buf_LRU_free_block(
 		/* Do not completely free dirty blocks. */
 
 		if (bpage->oldest_modification) {
-			return(BUF_LRU_NOT_FREED);
+			return(FALSE);
 		}
 	} else if (bpage->oldest_modification) {
 		/* Do not completely free dirty blocks. */
@@ -1478,7 +1404,7 @@ buf_LRU_free_block(
 		if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
 			ut_ad(buf_page_get_state(bpage)
 			      == BUF_BLOCK_ZIP_DIRTY);
-			return(BUF_LRU_NOT_FREED);
+			return(FALSE);
 		}
 
 		goto alloc;
@@ -1487,14 +1413,8 @@ buf_LRU_free_block(
 		If it cannot be allocated (without freeing a block
 		from the LRU list), refuse to free bpage. */
 alloc:
-		buf_pool_mutex_exit_forbid(buf_pool);
-		b = buf_buddy_alloc(buf_pool, sizeof *b, NULL);
-		buf_pool_mutex_exit_allow(buf_pool);
-
-		if (UNIV_UNLIKELY(!b)) {
-			return(BUF_LRU_CANNOT_RELOCATE);
-		}
-
+		b = buf_page_alloc_descriptor();
+		ut_a(b);
 		memcpy(b, bpage, sizeof *b);
 	}
 
@@ -1598,7 +1518,9 @@ alloc:
 			}
 
 			if (b->state == BUF_BLOCK_ZIP_PAGE) {
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 				buf_LRU_insert_zip_clean(b);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
 			} else {
 				/* Relocate on buf_pool->flush_list. */
 				buf_flush_relocate_on_flush_list(bpage, b);
@@ -1665,7 +1587,7 @@ alloc:
 		mutex_enter(block_mutex);
 	}
 
-	return(BUF_LRU_FREED);
+	return(TRUE);
 }
 
 /******************************************************************//**
@@ -1884,7 +1806,9 @@ buf_LRU_block_remove_hashed_page(
 		ut_a(bpage->zip.data);
 		ut_a(buf_page_get_zip_size(bpage));
 
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 		UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
 
 		mutex_exit(&buf_pool->zip_mutex);
 		buf_pool_mutex_exit_forbid(buf_pool);
@@ -1893,11 +1817,9 @@ buf_LRU_block_remove_hashed_page(
 			buf_pool, bpage->zip.data,
 			page_zip_get_size(&bpage->zip));
 
-		bpage->state = BUF_BLOCK_ZIP_FREE;
-		buf_buddy_free(buf_pool, bpage, sizeof(*bpage));
 		buf_pool_mutex_exit_allow(buf_pool);
+		buf_page_free_descriptor(bpage);
 
-		UNIV_MEM_UNDESC(bpage);
 		return(BUF_BLOCK_ZIP_FREE);
 
 	case BUF_BLOCK_FILE_PAGE:

=== modified file 'storage/innobase/include/btr0btr.h'
--- a/storage/innobase/include/btr0btr.h	2011-02-08 11:39:24 +0000
+++ b/storage/innobase/include/btr0btr.h	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -481,11 +481,14 @@ UNIV_INTERN
 ibool
 btr_compress(
 /*=========*/
-	btr_cur_t*	cursor,	/*!< in: cursor on the page to merge or lift;
-				the page must not be empty: in record delete
-				use btr_discard_page if the page would become
-				empty */
-	mtr_t*		mtr);	/*!< in: mtr */
+	btr_cur_t*	cursor,	/*!< in/out: cursor on the page to merge
+				or lift; the page must not be empty:
+				when deleting records, use btr_discard_page()
+				if the page would become empty */
+	ibool		adjust,	/*!< in: TRUE if should adjust the
+				cursor position even if compression occurs */
+	mtr_t*		mtr)	/*!< in/out: mini-transaction */
+	__attribute__((nonnull));
 /*************************************************************//**
 Discards a page from a B-tree. This is used to remove the last record from
 a B-tree page: the whole page must be removed at the same time. This cannot

=== modified file 'storage/innobase/include/btr0cur.h'
--- a/storage/innobase/include/btr0cur.h	2011-02-02 13:58:01 +0000
+++ b/storage/innobase/include/btr0cur.h	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -36,6 +36,9 @@ Created 10/16/1994 Heikki Tuuri
 #define BTR_NO_LOCKING_FLAG	2	/* do no record lock checking */
 #define BTR_KEEP_SYS_FLAG	4	/* sys fields will be found from the
 					update vector or inserted entry */
+#define BTR_KEEP_POS_FLAG	8	/* btr_cur_pessimistic_update()
+					must keep cursor position when
+					moving columns to big_rec */
 
 #ifndef UNIV_HOTBACKUP
 #include "que0types.h"
@@ -310,7 +313,9 @@ btr_cur_pessimistic_update(
 /*=======================*/
 	ulint		flags,	/*!< in: undo logging, locking, and rollback
 				flags */
-	btr_cur_t*	cursor,	/*!< in: cursor on the record to update */
+	btr_cur_t*	cursor,	/*!< in/out: cursor on the record to update;
+				cursor may become invalid if *big_rec == NULL
+				|| !(flags & BTR_KEEP_POS_FLAG) */
 	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap, or NULL */
 	big_rec_t**	big_rec,/*!< out: big rec vector whose fields have to
 				be stored externally by the caller, or NULL */
@@ -322,6 +327,16 @@ btr_cur_pessimistic_update(
 	que_thr_t*	thr,	/*!< in: query thread */
 	mtr_t*		mtr);	/*!< in: mtr; must be committed before
 				latching any further pages */
+/*****************************************************************
+Commits and restarts a mini-transaction so that it will retain an
+x-lock on index->lock and the cursor page. */
+UNIV_INTERN
+void
+btr_cur_mtr_commit_and_start(
+/*=========================*/
+	btr_cur_t*	cursor,	/*!< in: cursor */
+	mtr_t*		mtr)	/*!< in/out: mini-transaction */
+	UNIV_COLD __attribute__((nonnull));
 /***********************************************************//**
 Marks a clustered index record deleted. Writes an undo log record to
 undo log on this delete marking. Writes in the trx id field the id
@@ -364,10 +379,13 @@ UNIV_INTERN
 ibool
 btr_cur_compress_if_useful(
 /*=======================*/
-	btr_cur_t*	cursor,	/*!< in: cursor on the page to compress;
+	btr_cur_t*	cursor,	/*!< in/out: cursor on the page to compress;
 				cursor does not stay valid if compression
 				occurs */
-	mtr_t*		mtr);	/*!< in: mtr */
+	ibool		adjust,	/*!< in: TRUE if should adjust the
+				cursor position even if compression occurs */
+	mtr_t*		mtr)	/*!< in/out: mini-transaction */
+	__attribute__((nonnull));
 /*******************************************************//**
 Removes the record on which the tree cursor is positioned. It is assumed
 that the mtr has an x-latch on the page where the cursor is positioned,

=== modified file 'storage/innobase/include/btr0cur.ic'
--- a/storage/innobase/include/btr0cur.ic	2010-06-22 15:58:28 +0000
+++ b/storage/innobase/include/btr0cur.ic	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -139,7 +139,7 @@ btr_cur_compress_recommendation(
 	btr_cur_t*	cursor,	/*!< in: btr cursor */
 	mtr_t*		mtr)	/*!< in: mtr */
 {
-	page_t*		page;
+	const page_t*		page;
 
 	ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
 				MTR_MEMO_PAGE_X_FIX));

=== modified file 'storage/innobase/include/buf0buddy.h'
--- a/storage/innobase/include/buf0buddy.h	2010-10-20 11:46:28 +0000
+++ b/storage/innobase/include/buf0buddy.h	2011-06-17 20:29:19 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 2006, 2009, Innobase Oy. 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 the Free Software
@@ -37,25 +37,24 @@ 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 only be released and reacquired
-if lru != NULL.  This function should only be used for allocating
-compressed page frames or control blocks (buf_page_t).  Allocated
-control blocks must be properly initialized immediately after
-buf_buddy_alloc() has returned the memory, before releasing
-buf_pool->mutex.
-@return	allocated block, possibly NULL if lru == NULL */
+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*
 buf_buddy_alloc(
 /*============*/
-	buf_pool_t*	buf_pool,
-			/*!< buffer pool in which the block resides */
-	ulint	size,	/*!< in: block size, up to UNIV_PAGE_SIZE */
-	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,
-			or NULL if the LRU list should not be used */
-	__attribute__((malloc));
+	buf_pool_t*	buf_pool,	/*!< in: buffer pool in which
+					the page resides */
+	ulint		size,		/*!< in: compressed page size
+					(between PAGE_ZIP_MIN_SIZE and
+					UNIV_PAGE_SIZE) */
+	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));
 
 /**********************************************************************//**
 Release a block. */

=== modified file 'storage/innobase/include/buf0buddy.ic'
--- a/storage/innobase/include/buf0buddy.ic	2010-10-20 11:46:28 +0000
+++ b/storage/innobase/include/buf0buddy.ic	2011-06-17 20:29:19 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 2006, 2009, Innobase Oy. 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 the Free Software
@@ -36,8 +36,8 @@ 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 only be released and reacquired if lru != NULL.
-@return	allocated block, possibly NULL if lru==NULL */
+The buf_pool_mutex may be released and reacquired.
+@return	allocated block, never NULL */
 UNIV_INTERN
 void*
 buf_buddy_alloc_low(
@@ -48,9 +48,8 @@ buf_buddy_alloc_low(
 			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,
-			or NULL if the LRU list should not be used */
-	__attribute__((malloc));
+			and buf_pool_mutex was temporarily released */
+	__attribute__((malloc, nonnull));
 
 /**********************************************************************//**
 Deallocate a block. */
@@ -77,6 +76,8 @@ buf_buddy_get_slot(
 	ulint	i;
 	ulint	s;
 
+	ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+
 	for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1) {
 	}
 
@@ -87,29 +88,28 @@ 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 only be released and reacquired
-if lru != NULL.  This function should only be used for allocating
-compressed page frames or control blocks (buf_page_t).  Allocated
-control blocks must be properly initialized immediately after
-buf_buddy_alloc() has returned the memory, before releasing
-buf_pool->mutex.
-@return	allocated block, possibly NULL if lru == NULL */
+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*
 buf_buddy_alloc(
 /*============*/
 	buf_pool_t*	buf_pool,	/*!< in: buffer pool in which
 					the page resides */
-	ulint		size,		/*!< in: block size, up to
-					UNIV_PAGE_SIZE */
+	ulint		size,		/*!< in: compressed page size
+					(between PAGE_ZIP_MIN_SIZE and
+					UNIV_PAGE_SIZE) */
 	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, or NULL if
-				       	the LRU list should not be used */
+				       	temporarily released */
 {
 	ut_ad(buf_pool_mutex_own(buf_pool));
+	ut_ad(ut_is_2pow(size));
+	ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+	ut_ad(size <= UNIV_PAGE_SIZE);
 
 	return(buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), lru));
 }
@@ -127,6 +127,9 @@ buf_buddy_free(
 					UNIV_PAGE_SIZE */
 {
 	ut_ad(buf_pool_mutex_own(buf_pool));
+	ut_ad(ut_is_2pow(size));
+	ut_ad(size >= PAGE_ZIP_MIN_SIZE);
+	ut_ad(size <= UNIV_PAGE_SIZE);
 
 	buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size));
 }

=== modified file 'storage/innobase/include/buf0buf.h'
--- a/storage/innobase/include/buf0buf.h	2011-05-24 08:41:31 +0000
+++ b/storage/innobase/include/buf0buf.h	2011-06-17 20:29:19 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
 
 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
@@ -246,12 +246,6 @@ buf_relocate(
 				BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE */
 	buf_page_t*	dpage)	/*!< in/out: destination control block */
 	__attribute__((nonnull));
-/********************************************************************//**
-Resizes the buffer pool. */
-UNIV_INTERN
-void
-buf_pool_resize(void);
-/*=================*/
 /*********************************************************************//**
 Gets the current size of buffer buf_pool in bytes.
 @return	size in bytes */
@@ -275,6 +269,22 @@ ib_uint64_t
 buf_pool_get_oldest_modification(void);
 /*==================================*/
 /********************************************************************//**
+Allocates a buf_page_t descriptor. This function must succeed. In case
+of failure we assert in this function. */
+UNIV_INLINE
+buf_page_t*
+buf_page_alloc_descriptor(void)
+/*===========================*/
+	__attribute__((malloc));
+/********************************************************************//**
+Free a buf_page_t descriptor. */
+UNIV_INLINE
+void
+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 */
 UNIV_INTERN
@@ -582,6 +592,31 @@ buf_block_get_modify_clock(
 #else /* !UNIV_HOTBACKUP */
 # define buf_block_modify_clock_inc(block) ((void) 0)
 #endif /* !UNIV_HOTBACKUP */
+/*******************************************************************//**
+Increments the bufferfix count. */
+UNIV_INLINE
+void
+buf_block_buf_fix_inc_func(
+/*=======================*/
+#ifdef UNIV_SYNC_DEBUG
+	const char*	file,	/*!< in: file name */
+	ulint		line,	/*!< in: line */
+#endif /* UNIV_SYNC_DEBUG */
+	buf_block_t*	block)	/*!< in/out: block to bufferfix */
+	__attribute__((nonnull));
+#ifdef UNIV_SYNC_DEBUG
+/** Increments the bufferfix count.
+@param b	in/out: block to bufferfix
+@param f	in: file name where requested
+@param l	in: line number where requested */
+# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
+#else /* UNIV_SYNC_DEBUG */
+/** Increments the bufferfix count.
+@param b	in/out: block to bufferfix
+@param f	in: file name where requested
+@param l	in: line number where requested */
+# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
+#endif /* UNIV_SYNC_DEBUG */
 /********************************************************************//**
 Calculates a page checksum which is stored to the page when it is written
 to a file. Note that we must be careful to calculate the same value
@@ -1196,7 +1231,7 @@ ulint
 buf_get_free_list_len(void);
 /*=======================*/
 
-/********************************************************************
+/********************************************************************//**
 Determine if a block is a sentinel for a buffer pool watch.
 @return	TRUE if a sentinel for a buffer pool watch, FALSE if not */
 UNIV_INTERN
@@ -1732,8 +1767,10 @@ struct buf_pool_struct{
 	frames and buf_page_t descriptors of blocks that exist
 	in the buffer pool only in compressed form. */
 	/* @{ */
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 	UT_LIST_BASE_NODE_T(buf_page_t)	zip_clean;
 					/*!< unmodified compressed pages */
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
 	UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES];
 					/*!< buddy free lists */
 

=== modified file 'storage/innobase/include/buf0buf.ic'
--- a/storage/innobase/include/buf0buf.ic	2011-01-25 08:51:13 +0000
+++ b/storage/innobase/include/buf0buf.ic	2011-06-17 20:29:19 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, Google Inc.
 
 Portions of this file contain modifications contributed and copyrighted by
@@ -754,6 +754,35 @@ buf_block_get_lock_hash_val(
 }
 
 /********************************************************************//**
+Allocates a buf_page_t descriptor. This function must succeed. In case
+of failure we assert in this function.
+@return: the allocated descriptor. */
+UNIV_INLINE
+buf_page_t*
+buf_page_alloc_descriptor(void)
+/*===========================*/
+{
+	buf_page_t*	bpage;
+
+	bpage = (buf_page_t*) ut_malloc(sizeof *bpage);
+	ut_d(memset(bpage, 0, sizeof *bpage));
+	UNIV_MEM_ALLOC(bpage, sizeof *bpage);
+
+	return(bpage);
+}
+
+/********************************************************************//**
+Free a buf_page_t descriptor. */
+UNIV_INLINE
+void
+buf_page_free_descriptor(
+/*=====================*/
+	buf_page_t*	bpage)	/*!< in: bpage descriptor to free. */
+{
+	ut_free(bpage);
+}
+
+/********************************************************************//**
 Frees a buffer block which does not contain a file page. */
 UNIV_INLINE
 void
@@ -897,19 +926,6 @@ buf_block_buf_fix_inc_func(
 
 	block->page.buf_fix_count++;
 }
-#ifdef UNIV_SYNC_DEBUG
-/** Increments the bufferfix count.
-@param b	in/out: block to bufferfix
-@param f	in: file name where requested
-@param l	in: line number where requested */
-# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
-#else /* UNIV_SYNC_DEBUG */
-/** Increments the bufferfix count.
-@param b	in/out: block to bufferfix
-@param f	in: file name where requested
-@param l	in: line number where requested */
-# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
-#endif /* UNIV_SYNC_DEBUG */
 
 /*******************************************************************//**
 Decrements the bufferfix count. */
@@ -1160,7 +1176,7 @@ buf_block_dbg_add_level(
 				where we have acquired latch */
 	ulint		level)	/*!< in: latching order level */
 {
-	sync_thread_add_level(&block->lock, level);
+	sync_thread_add_level(&block->lock, level, FALSE);
 }
 #endif /* UNIV_SYNC_DEBUG */
 /********************************************************************//**

=== modified file 'storage/innobase/include/buf0lru.h'
--- a/storage/innobase/include/buf0lru.h	2011-01-25 08:51:13 +0000
+++ b/storage/innobase/include/buf0lru.h	2011-06-17 20:29:19 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 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
@@ -30,18 +30,6 @@ Created 11/5/1995 Heikki Tuuri
 #include "ut0byte.h"
 #include "buf0types.h"
 
-/** The return type of buf_LRU_free_block() */
-enum buf_lru_free_block_status {
-	/** freed */
-	BUF_LRU_FREED = 0,
-	/** not freed because the caller asked to remove the
-	uncompressed frame but the control block cannot be
-	relocated */
-	BUF_LRU_CANNOT_RELOCATE,
-	/** not freed because of some other reason */
-	BUF_LRU_NOT_FREED
-};
-
 /******************************************************************//**
 Tries to remove LRU flushed blocks from the end of the LRU list and put them
 to the free list. This is beneficial for the efficiency of the insert buffer
@@ -85,6 +73,7 @@ void
 buf_LRU_invalidate_tablespace(
 /*==========================*/
 	ulint	id);	/*!< in: space id */
+#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 /********************************************************************//**
 Insert a compressed block into buf_pool->zip_clean in the LRU order. */
 UNIV_INTERN
@@ -92,22 +81,22 @@ void
 buf_LRU_insert_zip_clean(
 /*=====================*/
 	buf_page_t*	bpage);	/*!< in: pointer to the block in question */
+#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
 
 /******************************************************************//**
 Try to free a block.  If bpage is a descriptor of a compressed-only
 page, the descriptor object will be freed as well.
 
-NOTE: If this function returns BUF_LRU_FREED, it will temporarily
+NOTE: If this function returns TRUE, it will temporarily
 release buf_pool->mutex.  Furthermore, the page frame will no longer be
 accessible via bpage.
 
 The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and
 release these two mutexes after the call.  No other
 buf_page_get_mutex() may be held when calling this function.
-@return BUF_LRU_FREED if freed, BUF_LRU_CANNOT_RELOCATE or
-BUF_LRU_NOT_FREED otherwise. */
+@return TRUE if freed, FALSE otherwise. */
 UNIV_INTERN
-enum buf_lru_free_block_status
+ibool
 buf_LRU_free_block(
 /*===============*/
 	buf_page_t*	bpage,	/*!< in: block to be freed */

=== modified file 'storage/innobase/include/buf0types.h'
--- a/storage/innobase/include/buf0types.h	2010-06-22 15:58:28 +0000
+++ b/storage/innobase/include/buf0types.h	2011-06-17 20:29:19 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 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
@@ -26,6 +26,8 @@ Created 11/17/1995 Heikki Tuuri
 #ifndef buf0types_h
 #define buf0types_h
 
+#include "page0types.h"
+
 /** Buffer page (uncompressed or compressed) */
 typedef	struct buf_page_struct		buf_page_t;
 /** Buffer block for which an uncompressed page exists */
@@ -60,17 +62,10 @@ enum buf_io_fix {
 
 /** Parameters of binary buddy system for compressed pages (buf0buddy.h) */
 /* @{ */
-#if UNIV_WORD_SIZE <= 4 /* 32-bit system */
-/** Base-2 logarithm of the smallest buddy block size */
-# define BUF_BUDDY_LOW_SHIFT	6
-#else /* 64-bit system */
-/** Base-2 logarithm of the smallest buddy block size */
-# define BUF_BUDDY_LOW_SHIFT	7
-#endif
+#define BUF_BUDDY_LOW_SHIFT	PAGE_ZIP_MIN_SIZE_SHIFT
+
 #define BUF_BUDDY_LOW		(1 << BUF_BUDDY_LOW_SHIFT)
-					/*!< minimum block size in the binary
-					buddy system; must be at least
-					sizeof(buf_page_t) */
+
 #define BUF_BUDDY_SIZES		(UNIV_PAGE_SIZE_SHIFT - BUF_BUDDY_LOW_SHIFT)
 					/*!< number of buddy sizes */
 

=== modified file 'storage/innobase/include/page0cur.ic'
--- a/storage/innobase/include/page0cur.ic	2010-06-22 15:58:28 +0000
+++ b/storage/innobase/include/page0cur.ic	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -27,6 +27,8 @@ Created 10/4/1994 Heikki Tuuri
 #include "buf0types.h"
 
 #ifdef UNIV_DEBUG
+# include "rem0cmp.h"
+
 /*********************************************************//**
 Gets pointer to the page frame where the cursor is positioned.
 @return	page */
@@ -268,6 +270,7 @@ page_cur_tuple_insert(
 					      index, rec, offsets, mtr);
 	}
 
+	ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, offsets));
 	mem_heap_free(heap);
 	return(rec);
 }

=== modified file 'storage/innobase/include/page0page.h'
--- a/storage/innobase/include/page0page.h	2011-05-09 08:12:26 +0000
+++ b/storage/innobase/include/page0page.h	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -284,16 +284,42 @@ page_get_supremum_offset(
 	const page_t*	page);	/*!< in: page which must have record(s) */
 #define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page))
 #define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page))
+
 /************************************************************//**
-Returns the middle record of record list. If there are an even number
-of records in the list, returns the first record of upper half-list.
-@return	middle record */
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return	nth record */
 UNIV_INTERN
+const rec_t*
+page_rec_get_nth_const(
+/*===================*/
+	const page_t*	page,	/*!< in: page */
+	ulint		nth)	/*!< in: nth record */
+	__attribute__((nonnull, warn_unused_result));
+/************************************************************//**
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return	nth record */
+UNIV_INLINE
+rec_t*
+page_rec_get_nth(
+/*=============*/
+	page_t*	page,	/*< in: page */
+	ulint	nth)	/*!< in: nth record */
+	__attribute__((nonnull, warn_unused_result));
+
+#ifndef UNIV_HOTBACKUP
+/************************************************************//**
+Returns the middle record of the records on the page. If there is an
+even number of records in the list, returns the first record of the
+upper half-list.
+@return	middle record */
+UNIV_INLINE
 rec_t*
 page_get_middle_rec(
 /*================*/
-	page_t*	page);	/*!< in: page */
-#ifndef UNIV_HOTBACKUP
+	page_t*	page)	/*!< in: page */
+	__attribute__((nonnull, warn_unused_result));
 /*************************************************************//**
 Compares a data tuple to a physical record. Differs from the function
 cmp_dtuple_rec_with_match in the way that the record must reside on an
@@ -348,6 +374,7 @@ page_get_n_recs(
 /***************************************************************//**
 Returns the number of records before the given record in chain.
 The number includes infimum and supremum records.
+This is the inverse function of page_rec_get_nth().
 @return	number of records */
 UNIV_INTERN
 ulint
@@ -618,6 +645,7 @@ rec_t*
 page_rec_find_owner_rec(
 /*====================*/
 	rec_t*	rec);	/*!< in: the physical record */
+#ifndef UNIV_HOTBACKUP
 /***********************************************************************//**
 Write a 32-bit field in a data dictionary record. */
 UNIV_INLINE
@@ -626,9 +654,10 @@ page_rec_write_field(
 /*=================*/
 	rec_t*	rec,	/*!< in/out: record to update */
 	ulint	i,	/*!< in: index of the field to update */
-	ulint	page_no,/*!< in: value to write */
+	ulint	val,	/*!< in: value to write */
 	mtr_t*	mtr)	/*!< in/out: mini-transaction */
 	__attribute__((nonnull));
+#endif /* !UNIV_HOTBACKUP */
 /************************************************************//**
 Returns the maximum combined size of records which can be inserted on top
 of record heap.

=== modified file 'storage/innobase/include/page0page.ic'
--- a/storage/innobase/include/page0page.ic	2011-05-09 08:12:26 +0000
+++ b/storage/innobase/include/page0page.ic	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -419,7 +419,37 @@ page_rec_is_infimum(
 	return(page_rec_is_infimum_low(page_offset(rec)));
 }
 
+/************************************************************//**
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return	nth record */
+UNIV_INLINE
+rec_t*
+page_rec_get_nth(
+/*=============*/
+	page_t*	page,	/*!< in: page */
+	ulint	nth)	/*!< in: nth record */
+{
+	return((rec_t*) page_rec_get_nth_const(page, nth));
+}
+
 #ifndef UNIV_HOTBACKUP
+/************************************************************//**
+Returns the middle record of the records on the page. If there is an
+even number of records in the list, returns the first record of the
+upper half-list.
+@return	middle record */
+UNIV_INLINE
+rec_t*
+page_get_middle_rec(
+/*================*/
+	page_t*	page)	/*!< in: page */
+{
+	ulint	middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2;
+
+	return(page_rec_get_nth(page, middle));
+}
+
 /*************************************************************//**
 Compares a data tuple to a physical record. Differs from the function
 cmp_dtuple_rec_with_match in the way that the record must reside on an
@@ -959,6 +989,7 @@ page_get_free_space_of_empty(
 		       - 2 * PAGE_DIR_SLOT_SIZE));
 }
 
+#ifndef UNIV_HOTBACKUP
 /***********************************************************************//**
 Write a 32-bit field in a data dictionary record. */
 UNIV_INLINE
@@ -979,6 +1010,7 @@ page_rec_write_field(
 
 	mlog_write_ulint(data, val, MLOG_4BYTES, mtr);
 }
+#endif /* !UNIV_HOTBACKUP */
 
 /************************************************************//**
 Each user record on a page, and also the deleted user records in the heap

=== modified file 'storage/innobase/include/rem0rec.h'
--- a/storage/innobase/include/rem0rec.h	2011-03-21 07:56:38 +0000
+++ b/storage/innobase/include/rem0rec.h	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -480,6 +480,18 @@ ulint
 rec_offs_any_extern(
 /*================*/
 	const ulint*	offsets);/*!< in: array returned by rec_get_offsets() */
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/******************************************************//**
+Determine if the offsets are for a record containing null BLOB pointers.
+@return	first field containing a null BLOB pointer, or NULL if none found */
+UNIV_INLINE
+const byte*
+rec_offs_any_null_extern(
+/*=====================*/
+	const rec_t*	rec,		/*!< in: record */
+	const ulint*	offsets)	/*!< in: rec_get_offsets(rec) */
+	__attribute__((nonnull, warn_unused_result));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
 /******************************************************//**
 Returns nonzero if the extern bit is set in nth field of rec.
 @return	nonzero if externally stored */

=== modified file 'storage/innobase/include/rem0rec.ic'
--- a/storage/innobase/include/rem0rec.ic	2011-03-21 07:56:38 +0000
+++ b/storage/innobase/include/rem0rec.ic	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -26,6 +26,7 @@ Created 5/30/1994 Heikki Tuuri
 #include "mach0data.h"
 #include "ut0byte.h"
 #include "dict0dict.h"
+#include "btr0types.h"
 
 /* Compact flag ORed to the extra size returned by rec_get_offsets() */
 #define REC_OFFS_COMPACT	((ulint) 1 << 31)
@@ -1087,6 +1088,44 @@ rec_offs_any_extern(
 	return(UNIV_UNLIKELY(*rec_offs_base(offsets) & REC_OFFS_EXTERNAL));
 }
 
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+/******************************************************//**
+Determine if the offsets are for a record containing null BLOB pointers.
+@return	first field containing a null BLOB pointer, or NULL if none found */
+UNIV_INLINE
+const byte*
+rec_offs_any_null_extern(
+/*=====================*/
+	const rec_t*	rec,		/*!< in: record */
+	const ulint*	offsets)	/*!< in: rec_get_offsets(rec) */
+{
+	ulint	i;
+	ut_ad(rec_offs_validate(rec, NULL, offsets));
+
+	if (!rec_offs_any_extern(offsets)) {
+		return(NULL);
+	}
+
+	for (i = 0; i < rec_offs_n_fields(offsets); i++) {
+		if (rec_offs_nth_extern(offsets, i)) {
+			ulint		len;
+			const byte*	field
+				= rec_get_nth_field(rec, offsets, i, &len);
+
+			ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
+			if (!memcmp(field + len
+				    - BTR_EXTERN_FIELD_REF_SIZE,
+				    field_ref_zero,
+				    BTR_EXTERN_FIELD_REF_SIZE)) {
+				return(field);
+			}
+		}
+	}
+
+	return(NULL);
+}
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
 /******************************************************//**
 Returns nonzero if the extern bit is set in nth field of rec.
 @return	nonzero if externally stored */

=== modified file 'storage/innobase/include/sync0rw.ic'
--- a/storage/innobase/include/sync0rw.ic	2011-02-15 09:29:56 +0000
+++ b/storage/innobase/include/sync0rw.ic	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, Google Inc.
 
 Portions of this file contain modifications contributed and copyrighted by
@@ -603,16 +603,16 @@ rw_lock_x_unlock_direct(
 
 	ut_ad((lock->lock_word % X_LOCK_DECR) == 0);
 
-#ifdef UNIV_SYNC_DEBUG
-	rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
-#endif
-
 	if (lock->lock_word == 0) {
 		lock->recursive = FALSE;
 		UNIV_MEM_INVALID(&lock->writer_thread,
 				 sizeof lock->writer_thread);
 	}
 
+#ifdef UNIV_SYNC_DEBUG
+	rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
+#endif
+
 	lock->lock_word += X_LOCK_DECR;
 
 	ut_ad(!lock->waiters);

=== modified file 'storage/innobase/include/sync0sync.h'
--- a/storage/innobase/include/sync0sync.h	2011-04-05 07:18:43 +0000
+++ b/storage/innobase/include/sync0sync.h	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, Google Inc.
 
 Portions of this file contain modifications contributed and copyrighted by
@@ -400,8 +400,10 @@ void
 sync_thread_add_level(
 /*==================*/
 	void*	latch,	/*!< in: pointer to a mutex or an rw-lock */
-	ulint	level);	/*!< in: level in the latching order; if
+	ulint	level,	/*!< in: level in the latching order; if
 			SYNC_LEVEL_VARYING, nothing is done */
+	ibool	relock)	/*!< in: TRUE if re-entering an x-lock */
+	__attribute__((nonnull));
 /******************************************************************//**
 Removes a latch from the thread level array if it is found there.
 @return TRUE if found in the array; it is no error if the latch is

=== modified file 'storage/innobase/include/univ.i'
--- a/storage/innobase/include/univ.i	2011-05-10 12:50:53 +0000
+++ b/storage/innobase/include/univ.i	2011-06-16 09:07:49 +0000
@@ -1,8 +1,7 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, Google Inc.
-Copyright (c) 2009, Sun Microsystems, Inc.
 
 Portions of this file contain modifications contributed and copyrighted by
 Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -51,7 +50,7 @@ Created 1/20/1994 Heikki Tuuri
 
 #define INNODB_VERSION_MAJOR	1
 #define INNODB_VERSION_MINOR	1
-#define INNODB_VERSION_BUGFIX	7
+#define INNODB_VERSION_BUGFIX	8
 
 /* The following is the InnoDB version as shown in
 SELECT plugin_version FROM information_schema.plugins;

=== modified file 'storage/innobase/page/page0cur.c'
--- a/storage/innobase/page/page0cur.c	2011-02-08 11:39:24 +0000
+++ b/storage/innobase/page/page0cur.c	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -1180,14 +1180,15 @@ page_cur_insert_rec_zip_reorg(
 	/* Before trying to reorganize the page,
 	store the number of preceding records on the page. */
 	pos = page_rec_get_n_recs_before(rec);
+	ut_ad(pos > 0);
 
 	if (page_zip_reorganize(block, index, mtr)) {
 		/* The page was reorganized: Find rec by seeking to pos,
 		and update *current_rec. */
-		rec = page + PAGE_NEW_INFIMUM;
-
-		while (--pos) {
-			rec = page + rec_get_next_offs(rec, TRUE);
+		if (pos > 1) {
+			rec = page_rec_get_nth(page, pos - 1);
+		} else {
+			rec = page + PAGE_NEW_INFIMUM;
 		}
 
 		*current_rec = rec;
@@ -1283,6 +1284,12 @@ page_cur_insert_rec_zip(
 			insert_rec = page_cur_insert_rec_zip_reorg(
 				current_rec, block, index, insert_rec,
 				page, page_zip, mtr);
+#ifdef UNIV_DEBUG
+			if (insert_rec) {
+				rec_offs_make_valid(
+					insert_rec, index, offsets);
+			}
+#endif /* UNIV_DEBUG */
 		}
 
 		return(insert_rec);

=== modified file 'storage/innobase/page/page0page.c'
--- a/storage/innobase/page/page0page.c	2011-05-09 08:12:26 +0000
+++ b/storage/innobase/page/page0page.c	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -1465,55 +1465,54 @@ page_dir_balance_slot(
 	}
 }
 
-#ifndef UNIV_HOTBACKUP
 /************************************************************//**
-Returns the middle record of the record list. If there are an even number
-of records in the list, returns the first record of the upper half-list.
-@return	middle record */
+Returns the nth record of the record list.
+This is the inverse function of page_rec_get_n_recs_before().
+@return	nth record */
 UNIV_INTERN
-rec_t*
-page_get_middle_rec(
-/*================*/
-	page_t*	page)	/*!< in: page */
+const rec_t*
+page_rec_get_nth_const(
+/*===================*/
+	const page_t*	page,	/*!< in: page */
+	ulint		nth)	/*!< in: nth record */
 {
-	page_dir_slot_t*	slot;
-	ulint			middle;
+	const page_dir_slot_t*	slot;
 	ulint			i;
 	ulint			n_owned;
-	ulint			count;
-	rec_t*			rec;
-
-	/* This many records we must leave behind */
-	middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2;
+	const rec_t*		rec;
 
-	count = 0;
+	ut_ad(nth < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
 
 	for (i = 0;; i++) {
 
 		slot = page_dir_get_nth_slot(page, i);
 		n_owned = page_dir_slot_get_n_owned(slot);
 
-		if (count + n_owned > middle) {
+		if (n_owned > nth) {
 			break;
 		} else {
-			count += n_owned;
+			nth -= n_owned;
 		}
 	}
 
 	ut_ad(i > 0);
 	slot = page_dir_get_nth_slot(page, i - 1);
-	rec = (rec_t*) page_dir_slot_get_rec(slot);
-	rec = page_rec_get_next(rec);
+	rec = page_dir_slot_get_rec(slot);
 
-	/* There are now count records behind rec */
-
-	for (i = 0; i < middle - count; i++) {
-		rec = page_rec_get_next(rec);
+	if (page_is_comp(page)) {
+		do {
+			rec = page_rec_get_next_low(rec, TRUE);
+			ut_ad(rec);
+		} while (nth--);
+	} else {
+		do {
+			rec = page_rec_get_next_low(rec, FALSE);
+			ut_ad(rec);
+		} while (nth--);
 	}
 
 	return(rec);
 }
-#endif /* !UNIV_HOTBACKUP */
 
 /***************************************************************//**
 Returns the number of records before the given record in chain.
@@ -1575,6 +1574,7 @@ page_rec_get_n_recs_before(
 	n--;
 
 	ut_ad(n >= 0);
+	ut_ad(n < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
 
 	return((ulint) n);
 }

=== modified file 'storage/innobase/page/page0zip.c'
--- a/storage/innobase/page/page0zip.c	2011-05-31 09:12:32 +0000
+++ b/storage/innobase/page/page0zip.c	2011-06-16 12:13:24 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 2005, 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
@@ -3912,17 +3912,9 @@ page_zip_write_trx_id_and_roll_ptr(
 	UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip));
 }
 
-#ifdef UNIV_ZIP_DEBUG
-/** Set this variable in a debugger to disable page_zip_clear_rec().
-The only observable effect should be the compression ratio due to
-deleted records not being zeroed out.  In rare cases, there can be
-page_zip_validate() failures on the node_ptr, trx_id and roll_ptr
-columns if the space is reallocated for a smaller record. */
-UNIV_INTERN ibool	page_zip_clear_rec_disable;
-#endif /* UNIV_ZIP_DEBUG */
-
 /**********************************************************************//**
-Clear an area on the uncompressed and compressed page, if possible. */
+Clear an area on the uncompressed and compressed page.
+Do not clear the data payload, as that would grow the modification log. */
 static
 void
 page_zip_clear_rec(
@@ -3934,6 +3926,9 @@ page_zip_clear_rec(
 {
 	ulint	heap_no;
 	page_t*	page	= page_align(rec);
+	byte*	storage;
+	byte*	field;
+	ulint	len;
 	/* page_zip_validate() would fail here if a record
 	containing externally stored columns is being deleted. */
 	ut_ad(rec_offs_validate(rec, index, offsets));
@@ -3949,60 +3944,46 @@ page_zip_clear_rec(
 	UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets),
 			   rec_offs_extra_size(offsets));
 
-	if (
-#ifdef UNIV_ZIP_DEBUG
-	    !page_zip_clear_rec_disable &&
-#endif /* UNIV_ZIP_DEBUG */
-	    page_zip->m_end
-	    + 1 + ((heap_no - 1) >= 64)/* size of the log entry */
-	    + page_zip_get_trailer_len(page_zip,
-				       dict_index_is_clust(index), NULL)
-	    < page_zip_get_size(page_zip)) {
-		byte*	data;
-
-		/* Clear only the data bytes, because the allocator and
-		the decompressor depend on the extra bytes. */
-		memset(rec, 0, rec_offs_data_size(offsets));
-
-		if (!page_is_leaf(page)) {
-			/* Clear node_ptr on the compressed page. */
-			byte*	storage	= page_zip->data
-				+ page_zip_get_size(page_zip)
-				- (page_dir_get_n_heap(page)
-				   - PAGE_HEAP_NO_USER_LOW)
-				* PAGE_ZIP_DIR_SLOT_SIZE;
-
-			memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
-			       0, REC_NODE_PTR_SIZE);
-		} else if (dict_index_is_clust(index)) {
-			/* Clear trx_id and roll_ptr on the compressed page. */
-			byte*	storage	= page_zip->data
-				+ page_zip_get_size(page_zip)
-				- (page_dir_get_n_heap(page)
-				   - PAGE_HEAP_NO_USER_LOW)
-				* PAGE_ZIP_DIR_SLOT_SIZE;
-
-			memset(storage - (heap_no - 1)
-			       * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
-			       0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
-		}
+	if (!page_is_leaf(page)) {
+		/* Clear node_ptr. On the compressed page,
+		there is an array of node_ptr immediately before the
+		dense page directory, at the very end of the page. */
+		storage	= page_zip->data
+			+ page_zip_get_size(page_zip)
+			- (page_dir_get_n_heap(page)
+			   - PAGE_HEAP_NO_USER_LOW)
+			* PAGE_ZIP_DIR_SLOT_SIZE;
+		ut_ad(dict_index_get_n_unique_in_tree(index) ==
+		      rec_offs_n_fields(offsets) - 1);
+		field	= rec_get_nth_field(rec, offsets,
+					    rec_offs_n_fields(offsets) - 1,
+					    &len);
+		ut_ad(len == REC_NODE_PTR_SIZE);
 
-		/* Log that the data was zeroed out. */
-		data = page_zip->data + page_zip->m_end;
-		ut_ad(!*data);
-		if (UNIV_UNLIKELY(heap_no - 1 >= 64)) {
-			*data++ = (byte) (0x80 | (heap_no - 1) >> 7);
-			ut_ad(!*data);
-		}
-		*data++ = (byte) ((heap_no - 1) << 1 | 1);
-		ut_ad(!*data);
-		ut_ad((ulint) (data - page_zip->data)
-		      < page_zip_get_size(page_zip));
-		page_zip->m_end = data - page_zip->data;
-		page_zip->m_nonempty = TRUE;
-	} else if (page_is_leaf(page) && dict_index_is_clust(index)) {
-		/* Do not clear the record, because there is not enough space
-		to log the operation. */
+		ut_ad(!rec_offs_any_extern(offsets));
+		memset(field, 0, REC_NODE_PTR_SIZE);
+		memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE,
+		       0, REC_NODE_PTR_SIZE);
+	} else if (dict_index_is_clust(index)) {
+		/* Clear trx_id and roll_ptr. On the compressed page,
+		there is an array of these fields immediately before the
+		dense page directory, at the very end of the page. */
+		const ulint	trx_id_pos
+			= dict_col_get_clust_pos(
+			dict_table_get_sys_col(
+				index->table, DATA_TRX_ID), index);
+		storage	= page_zip->data
+			+ page_zip_get_size(page_zip)
+			- (page_dir_get_n_heap(page)
+			   - PAGE_HEAP_NO_USER_LOW)
+			* PAGE_ZIP_DIR_SLOT_SIZE;
+		field	= rec_get_nth_field(rec, offsets, trx_id_pos, &len);
+		ut_ad(len == DATA_TRX_ID_LEN);
+
+		memset(field, 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
+		memset(storage - (heap_no - 1)
+		       * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN),
+		       0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
 
 		if (rec_offs_any_extern(offsets)) {
 			ulint	i;
@@ -4011,15 +3992,18 @@ page_zip_clear_rec(
 				/* Clear all BLOB pointers in order to make
 				page_zip_validate() pass. */
 				if (rec_offs_nth_extern(offsets, i)) {
-					ulint	len;
-					byte*	field = rec_get_nth_field(
+					field = rec_get_nth_field(
 						rec, offsets, i, &len);
+					ut_ad(len
+					      == BTR_EXTERN_FIELD_REF_SIZE);
 					memset(field + len
 					       - BTR_EXTERN_FIELD_REF_SIZE,
 					       0, BTR_EXTERN_FIELD_REF_SIZE);
 				}
 			}
 		}
+	} else {
+		ut_ad(!rec_offs_any_extern(offsets));
 	}
 
 #ifdef UNIV_ZIP_DEBUG

=== modified file 'storage/innobase/rem/rem0rec.c'
--- a/storage/innobase/rem/rem0rec.c	2011-05-31 09:12:32 +0000
+++ b/storage/innobase/rem/rem0rec.c	2011-06-16 12:13:24 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1994, 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
@@ -408,7 +408,7 @@ rec_init_offsets(
 		do {
 			ulint	len;
 			if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
-				len = offs += 4;
+				len = offs += REC_NODE_PTR_SIZE;
 				goto resolved;
 			}
 
@@ -640,7 +640,7 @@ rec_get_offsets_reverse(
 	do {
 		ulint	len;
 		if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
-			len = offs += 4;
+			len = offs += REC_NODE_PTR_SIZE;
 			goto resolved;
 		}
 
@@ -1131,9 +1131,9 @@ rec_convert_dtuple_to_rec_comp(
 
 		if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
 			ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
-			ut_ad(len == 4);
+			ut_ad(len == REC_NODE_PTR_SIZE);
 			memcpy(end, dfield_get_data(field), len);
-			end += 4;
+			end += REC_NODE_PTR_SIZE;
 			break;
 		}
 

=== modified file 'storage/innobase/row/row0ins.c'
--- a/storage/innobase/row/row0ins.c	2011-02-02 13:58:01 +0000
+++ b/storage/innobase/row/row0ins.c	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 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
@@ -345,9 +345,9 @@ row_ins_clust_index_entry_by_modify(
 			return(DB_LOCK_TABLE_FULL);
 
 		}
-		err = btr_cur_pessimistic_update(0, cursor,
-						 heap, big_rec, update,
-						 0, thr, mtr);
+		err = btr_cur_pessimistic_update(
+			BTR_KEEP_POS_FLAG, cursor, heap, big_rec, update,
+			0, thr, mtr);
 	}
 
 	return(err);
@@ -1973,6 +1973,7 @@ row_ins_index_entry_low(
 	ulint		modify = 0; /* remove warning */
 	rec_t*		insert_rec;
 	rec_t*		rec;
+	ulint*		offsets;
 	ulint		err;
 	ulint		n_unique;
 	big_rec_t*	big_rec			= NULL;
@@ -2081,6 +2082,42 @@ row_ins_index_entry_low(
 			err = row_ins_clust_index_entry_by_modify(
 				mode, &cursor, &heap, &big_rec, entry,
 				thr, &mtr);
+
+			if (big_rec) {
+				ut_a(err == DB_SUCCESS);
+				/* Write out the externally stored
+				columns while still x-latching
+				index->lock and block->lock. We have
+				to mtr_commit(mtr) first, so that the
+				redo log will be written in the
+				correct order. Otherwise, we would run
+				into trouble on crash recovery if mtr
+				freed B-tree pages on which some of
+				the big_rec fields will be written. */
+				btr_cur_mtr_commit_and_start(&cursor, &mtr);
+
+				rec = btr_cur_get_rec(&cursor);
+				offsets = rec_get_offsets(
+					rec, index, NULL,
+					ULINT_UNDEFINED, &heap);
+
+				err = btr_store_big_rec_extern_fields(
+					index, btr_cur_get_block(&cursor),
+					rec, offsets, &mtr, FALSE, big_rec);
+				/* If writing big_rec fails (for
+				example, because of DB_OUT_OF_FILE_SPACE),
+				the record will be corrupted. Even if
+				we did not update any externally
+				stored columns, our update could cause
+				the record to grow so that a
+				non-updated column was selected for
+				external storage. This non-update
+				would not have been written to the
+				undo log, and thus the record cannot
+				be rolled back. */
+				ut_a(err == DB_SUCCESS);
+				goto stored_big_rec;
+			}
 		} else {
 			ut_ad(!n_ext);
 			err = row_ins_sec_index_entry_by_modify(
@@ -2109,8 +2146,6 @@ function_exit:
 	mtr_commit(&mtr);
 
 	if (UNIV_LIKELY_NULL(big_rec)) {
-		rec_t*	rec;
-		ulint*	offsets;
 		mtr_start(&mtr);
 
 		btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
@@ -2124,6 +2159,7 @@ function_exit:
 			index, btr_cur_get_block(&cursor),
 			rec, offsets, &mtr, FALSE, big_rec);
 
+stored_big_rec:
 		if (modify) {
 			dtuple_big_rec_free(big_rec);
 		} else {

=== modified file 'storage/innobase/row/row0row.c'
--- a/storage/innobase/row/row0row.c	2011-05-31 09:12:32 +0000
+++ b/storage/innobase/row/row0row.c	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 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
@@ -192,6 +192,7 @@ row_build(
 
 	ut_ad(index && rec && heap);
 	ut_ad(dict_index_is_clust(index));
+	ut_ad(!mutex_own(&kernel_mutex));
 
 	if (!offsets) {
 		offsets = rec_get_offsets(rec, index, offsets_,
@@ -200,6 +201,36 @@ row_build(
 		ut_ad(rec_offs_validate(rec, index, offsets));
 	}
 
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+	if (UNIV_LIKELY_NULL(rec_offs_any_null_extern(rec, offsets))) {
+		/* This condition can occur during crash recovery before
+		trx_rollback_active() has completed execution.
+
+		This condition is possible if the server crashed
+		during an insert or update before
+		btr_store_big_rec_extern_fields() did mtr_commit() all
+		BLOB pointers to the clustered index record.
+
+		Look up the transaction that holds the implicit lock
+		on this record, and assert that it was recovered (and
+		will soon be rolled back). */
+
+		ulint		trx_id_pos	= dict_index_get_sys_col_pos(
+				index, DATA_TRX_ID);
+		ulint		len;
+		trx_id_t	trx_id		= trx_read_trx_id(
+			rec_get_nth_field(rec, offsets, trx_id_pos, &len));
+		trx_t*		trx;
+		ut_a(len == 6);
+
+		mutex_enter(&kernel_mutex);
+		trx = trx_get_on_id(trx_id);
+		ut_a(trx);
+		ut_a(trx->is_recovered);
+		mutex_exit(&kernel_mutex);
+	}
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
 	if (type != ROW_COPY_POINTERS) {
 		/* Take a copy of rec to heap */
 		buf = mem_heap_alloc(heap, rec_offs_size(offsets));
@@ -383,6 +414,10 @@ row_rec_to_index_entry(
 		rec = rec_copy(buf, rec, offsets);
 		/* Avoid a debug assertion in rec_offs_validate(). */
 		rec_offs_make_valid(rec, index, offsets);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+	} else {
+		ut_a(!rec_offs_any_null_extern(rec, offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
 	}
 
 	entry = row_rec_to_index_entry_low(rec, index, offsets, n_ext, heap);

=== modified file 'storage/innobase/row/row0upd.c'
--- a/storage/innobase/row/row0upd.c	2011-05-31 09:12:32 +0000
+++ b/storage/innobase/row/row0upd.c	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 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
@@ -1999,28 +1999,43 @@ row_upd_clust_rec(
 	ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
 				    dict_table_is_comp(index->table)));
 
-	err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur,
-					 &heap, &big_rec, node->update,
-					 node->cmpl_info, thr, mtr);
-	mtr_commit(mtr);
-
-	if (err == DB_SUCCESS && big_rec) {
+	err = btr_cur_pessimistic_update(
+		BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, btr_cur,
+		&heap, &big_rec, node->update, node->cmpl_info, thr, mtr);
+	if (big_rec) {
 		ulint		offsets_[REC_OFFS_NORMAL_SIZE];
 		rec_t*		rec;
 		rec_offs_init(offsets_);
 
-		mtr_start(mtr);
+		ut_a(err == DB_SUCCESS);
+		/* Write out the externally stored columns while still
+		x-latching index->lock and block->lock. We have to
+		mtr_commit(mtr) first, so that the redo log will be
+		written in the correct order. Otherwise, we would run
+		into trouble on crash recovery if mtr freed B-tree
+		pages on which some of the big_rec fields will be
+		written. */
+		btr_cur_mtr_commit_and_start(btr_cur, mtr);
 
-		ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
 		rec = btr_cur_get_rec(btr_cur);
 		err = btr_store_big_rec_extern_fields(
 			index, btr_cur_get_block(btr_cur), rec,
 			rec_get_offsets(rec, index, offsets_,
 					ULINT_UNDEFINED, &heap),
 			mtr, TRUE, big_rec);
-		mtr_commit(mtr);
+		/* If writing big_rec fails (for example, because of
+		DB_OUT_OF_FILE_SPACE), the record will be corrupted.
+		Even if we did not update any externally stored
+		columns, our update could cause the record to grow so
+		that a non-updated column was selected for external
+		storage. This non-update would not have been written
+		to the undo log, and thus the record cannot be rolled
+		back. */
+		ut_a(err == DB_SUCCESS);
 	}
 
+	mtr_commit(mtr);
+
 	if (UNIV_LIKELY_NULL(heap)) {
 		mem_heap_free(heap);
 	}

=== modified file 'storage/innobase/row/row0vers.c'
--- a/storage/innobase/row/row0vers.c	2011-01-25 10:35:35 +0000
+++ b/storage/innobase/row/row0vers.c	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 1997, 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
@@ -550,6 +550,11 @@ row_vers_build_for_consistent_read(
 				/* The view already sees this version: we can
 				copy it to in_heap and return */
 
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+				ut_a(!rec_offs_any_null_extern(
+					     version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
 				buf = mem_heap_alloc(in_heap,
 						     rec_offs_size(*offsets));
 				*old_vers = rec_copy(buf, version, *offsets);
@@ -583,6 +588,10 @@ row_vers_build_for_consistent_read(
 		*offsets = rec_get_offsets(prev_version, index, *offsets,
 					   ULINT_UNDEFINED, offset_heap);
 
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+		ut_a(!rec_offs_any_null_extern(prev_version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
 		trx_id = row_get_rec_trx_id(prev_version, index, *offsets);
 
 		if (read_view_sees_trx_id(view, trx_id)) {
@@ -682,6 +691,10 @@ row_vers_build_for_semi_consistent_read(
 			/* We found a version that belongs to a
 			committed transaction: return it. */
 
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+			ut_a(!rec_offs_any_null_extern(version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
 			if (rec == version) {
 				*old_vers = rec;
 				err = DB_SUCCESS;
@@ -739,6 +752,9 @@ row_vers_build_for_semi_consistent_read(
 		version = prev_version;
 		*offsets = rec_get_offsets(version, index, *offsets,
 					   ULINT_UNDEFINED, offset_heap);
+#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+		ut_a(!rec_offs_any_null_extern(version, *offsets));
+#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
 	}/* for (;;) */
 
 	if (heap) {

=== modified file 'storage/innobase/sync/sync0rw.c'
--- a/storage/innobase/sync/sync0rw.c	2011-02-25 11:21:02 +0000
+++ b/storage/innobase/sync/sync0rw.c	2011-06-16 09:07:49 +0000
@@ -782,7 +782,9 @@ rw_lock_add_debug_info(
 	rw_lock_debug_mutex_exit();
 
 	if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
-		sync_thread_add_level(lock, lock->level);
+		sync_thread_add_level(lock, lock->level,
+				      lock_type == RW_LOCK_EX
+				      && lock->lock_word < 0);
 	}
 }
 

=== modified file 'storage/innobase/sync/sync0sync.c'
--- a/storage/innobase/sync/sync0sync.c	2011-04-05 07:18:43 +0000
+++ b/storage/innobase/sync/sync0sync.c	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved.
+Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2008, Google Inc.
 
 Portions of this file contain modifications contributed and copyrighted by
@@ -690,7 +690,7 @@ mutex_set_debug_info(
 	ut_ad(mutex);
 	ut_ad(file_name);
 
-	sync_thread_add_level(mutex, mutex->level);
+	sync_thread_add_level(mutex, mutex->level, FALSE);
 
 	mutex->file_name = file_name;
 	mutex->line	 = line;
@@ -1133,8 +1133,9 @@ void
 sync_thread_add_level(
 /*==================*/
 	void*	latch,	/*!< in: pointer to a mutex or an rw-lock */
-	ulint	level)	/*!< in: level in the latching order; if
+	ulint	level,	/*!< in: level in the latching order; if
 			SYNC_LEVEL_VARYING, nothing is done */
+	ibool	relock)	/*!< in: TRUE if re-entering an x-lock */
 {
 	ulint		i;
 	sync_level_t*	slot;
@@ -1185,6 +1186,10 @@ sync_thread_add_level(
 
 	array = thread_slot->levels;
 
+	if (relock) {
+		goto levels_ok;
+	}
+
 	/* NOTE that there is a problem with _NODE and _LEAF levels: if the
 	B-tree height changes, then a leaf can change to an internal node
 	or the other way around. We do not know at present if this can cause
@@ -1350,6 +1355,7 @@ sync_thread_add_level(
 		ut_error;
 	}
 
+levels_ok:
 	if (array->next_free == ULINT_UNDEFINED) {
 		ut_a(array->n_elems < array->max_elems);
 

=== modified file 'storage/innobase/trx/trx0rec.c'
--- a/storage/innobase/trx/trx0rec.c	2011-05-31 09:12:32 +0000
+++ b/storage/innobase/trx/trx0rec.c	2011-06-16 09:07:49 +0000
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
+Copyright (c) 1996, 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
@@ -1593,6 +1593,10 @@ trx_undo_prev_version_build(
 		return(DB_ERROR);
 	}
 
+# if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
+	ut_a(!rec_offs_any_null_extern(rec, offsets));
+# endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
+
 	if (row_upd_changes_field_size_or_external(index, offsets, update)) {
 		ulint	n_ext;
 

=== modified file 'storage/myisam/mi_update.c'
--- a/storage/myisam/mi_update.c	2011-01-11 09:07:37 +0000
+++ b/storage/myisam/mi_update.c	2011-06-07 15:44:15 +0000
@@ -192,8 +192,8 @@ err:
   save_errno=my_errno;
   if (changed)
     key_changed|= HA_STATE_CHANGED;
-  if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_OUT_OF_MEM ||
-      my_errno == HA_ERR_RECORD_FILE_FULL)
+  if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL ||
+      my_errno == HA_ERR_NULL_IN_SPATIAL || my_errno == HA_ERR_OUT_OF_MEM)
   {
     info->errkey= (int) i;
     flag=0;
@@ -211,8 +211,9 @@ err:
 	{
 	  uint new_length=_mi_make_key(info,i,new_key,newrec,pos);
 	  uint old_length= _mi_make_key(info,i,old_key,oldrec,pos);
-	  if ((flag++ && _mi_ck_delete(info,i,new_key,new_length)) ||
-	      _mi_ck_write(info,i,old_key,old_length))
+	  if ((flag++ && 
+	       share->keyinfo[i].ck_delete(info, i, new_key, new_length)) ||
+	      share->keyinfo[i].ck_insert(info, i, old_key, old_length))
 	    break;
 	}
       }

=== modified file 'storage/myisam/mi_write.c'
--- a/storage/myisam/mi_write.c	2011-03-28 08:49:43 +0000
+++ b/storage/myisam/mi_write.c	2011-06-07 15:44:15 +0000
@@ -204,7 +204,7 @@ err:
         else
 	{
 	  uint key_length=_mi_make_key(info,i,buff,record,filepos);
-	  if (_mi_ck_delete(info,i,buff,key_length))
+	  if (share->keyinfo[i].ck_delete(info, i, buff, key_length))
 	  {
 	    if (local_lock_tree)
               mysql_rwlock_unlock(&share->key_root_lock[i]);

=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c	2011-03-22 11:48:56 +0000
+++ b/tests/mysql_client_test.c	2011-06-10 14:26:35 +0000
@@ -19588,6 +19588,81 @@ static void test_bug11766854()
   DBUG_VOID_RETURN;
 }
 
+/**
+  Bug#12337762: 60075: MYSQL_LIST_FIELDS() RETURNS WRONG CHARSET FOR 
+                       CHAR/VARCHAR/TEXT COLUMNS IN VIEWS 
+*/
+static void test_bug12337762()
+{
+  int rc,i=0;
+  MYSQL_RES *result;
+  MYSQL_FIELD *field;
+  unsigned int tab_charsetnr[3]= {0};
+
+  DBUG_ENTER("test_bug12337762");
+  myheader("test_bug12337762");
+
+  /*
+    Creating table with specific charset.
+  */
+  rc= mysql_query(mysql, "drop table if exists charset_tab");
+  rc= mysql_query(mysql, "create table charset_tab("\
+                         "txt1 varchar(32) character set Latin1,"\
+                         "txt2 varchar(32) character set Latin1 collate latin1_bin,"\
+                         "txt3 varchar(32) character set utf8 collate utf8_bin"\
+						 ")");
+  
+  DIE_UNLESS(rc == 0);
+  DIE_IF(mysql_errno(mysql));
+
+  /*
+    Creating view from table created earlier.
+  */
+  rc= mysql_query(mysql, "drop view if exists charset_view");
+  rc= mysql_query(mysql, "create view charset_view as "\
+                         "select * from charset_tab;");
+  DIE_UNLESS(rc == 0);
+  DIE_IF(mysql_errno(mysql));
+
+  /*
+    Checking field information for table.
+  */
+  result= mysql_list_fields(mysql, "charset_tab", NULL);
+  DIE_IF(mysql_errno(mysql));
+  i=0;
+  while((field= mysql_fetch_field(result)))
+  {
+    printf("field name %s\n", field->name);
+    printf("field table %s\n", field->table);
+    printf("field type %d\n", field->type);
+    printf("field charset %d\n", field->charsetnr);
+    tab_charsetnr[i++]= field->charsetnr;
+    printf("\n");
+  }
+  mysql_free_result(result);
+
+  /*
+    Checking field information for view.
+  */
+  result= mysql_list_fields(mysql, "charset_view", NULL);
+  DIE_IF(mysql_errno(mysql));
+  i=0;
+  while((field= mysql_fetch_field(result)))
+  {
+    printf("field name %s\n", field->name);
+    printf("field table %s\n", field->table);
+    printf("field type %d\n", field->type);
+    printf("field charset %d\n", field->charsetnr);
+    printf("\n");
+    /* 
+      charset value for field must be same for both, view and table.
+    */
+    DIE_UNLESS(field->charsetnr == tab_charsetnr[i++]);
+  }
+  mysql_free_result(result);
+
+  DBUG_VOID_RETURN;
+}
 
 /*
   Read and parse arguments and MySQL options from my.cnf
@@ -19647,10 +19722,10 @@ static struct my_option client_test_long
    &opt_getopt_ll_test, &opt_getopt_ll_test, 0,
    GET_LL, REQUIRED_ARG, 0, 0, LONGLONG_MAX, 0, 0, 0},
   {"plugin_dir", 0, "Directory for client-side plugins.",
-   (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+   &opt_plugin_dir, &opt_plugin_dir, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"default_auth", 0, "Default authentication client-side plugin to use.",
-   (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
+   &opt_default_auth, &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
@@ -19933,6 +20008,7 @@ static struct my_tests_st my_tests[]= {
   { "test_bug57058", test_bug57058 },
   { "test_bug56976", test_bug56976 },
   { "test_bug11766854", test_bug11766854 },
+  { "test_bug12337762", test_bug12337762 },
   { 0, 0 }
 };
 
@@ -20071,29 +20147,29 @@ int main(int argc, char **argv)
     if (!argc)
     {
       for (fptr= my_tests; fptr->name; fptr++)
-	(*fptr->function)();	
+        (*fptr->function)();	
     }
     else
     {
       for ( ; *argv ; argv++)
       {
-	for (fptr= my_tests; fptr->name; fptr++)
-	{
-	  if (!strcmp(fptr->name, *argv))
-	  {
-	    (*fptr->function)();
-	    break;
-	  }
-	}
-	if (!fptr->name)
-	{
-	  fprintf(stderr, "\n\nGiven test not found: '%s'\n", *argv);
-	  fprintf(stderr, "See legal test names with %s -T\n\nAborting!\n",
-		  my_progname);
-	  client_disconnect(mysql, 1);
-	  free_defaults(defaults_argv);
-	  exit(1);
-	}
+        for (fptr= my_tests; fptr->name; fptr++)
+        {
+          if (!strcmp(fptr->name, *argv))
+          {
+            (*fptr->function)();
+            break;
+          }
+        }
+        if (!fptr->name)
+        {
+          fprintf(stderr, "\n\nGiven test not found: '%s'\n", *argv);
+          fprintf(stderr, "See legal test names with %s -T\n\nAborting!\n",
+                  my_progname);
+          client_disconnect(mysql, 1);
+          free_defaults(defaults_argv);
+          exit(1);
+        }
       }
     }
 


Attachment: [text/bzr-bundle] bzr/horst.hunger@sun.com-20110704174107-d130pdxfkxroeocv.bundle
Thread
bzr commit into mysql-5.5 branch (horst.hunger:3421) WL#5710Horst.Hunger4 Jul