List:Commits« Previous MessageNext Message »
From:Alexander Barkov Date:May 4 2011 8:33am
Subject:bzr push into mysql-trunk branch (alexander.barkov:3335 to 3363) WL#5787
View as plain text  
 3363 Alexander Nozdrin	2011-05-03
      WL#5787 follow-up: fix compilation warning.

    modified:
      sql/item_inetfunc.cc
 3362 Alexander Nozdrin	2011-05-03
      MTR tests for QA sign off of wl#5787: adding forgotten file.

    added:
      mysql-test/include/ipv6_func.inc
 3361 Kent Boortz	2011-05-03 [merge]
      Merge

 3360 Alexander Nozdrin	2011-05-03
      MTR tests for QA sign off of wl#5787.

    modified:
      mysql-test/include/ipv6.inc
      mysql-test/r/ipv4_as_ipv6.result
      mysql-test/r/ipv6.result
      mysql-test/t/ipv4_as_ipv6.test
      mysql-test/t/ipv6.test
 3359 Alexander Nozdrin	2011-05-03
      Patch for WL#5787 (IPv6-capable INET_ATON and INET_NTOA functions).
      
      The patch introduces the following new functions:
        - INET6_ATON()
        - INET6_NTOA()
        - IS_IPV4()
        - IS_IPV6()
        - IS_IPV4_COMPAT()
        - IS_IPV4_MAPPED()

    modified:
      mysql-test/r/func_misc.result
      mysql-test/t/func_misc.test
      sql/item_create.cc
      sql/item_inetfunc.cc
      sql/item_inetfunc.h
 3358 Tor Didriksen	2011-05-03
      BUG#11766327 post-push fix: build break with optimized/-DMYSQL_MAINTAINER_MODE=1

    modified:
      sql/sql_select.cc
 3357 Vasil Dimov	2011-05-02 [merge]
      Merge mysql-trunk-innodb -> mysql-trunk

    modified:
      storage/innobase/trx/trx0rec.c
 3356 Sven Sandberg	2011-05-02 [merge]
      marked tests experimental

    modified:
      mysql-test/collections/default.experimental
 3355 Jorgen Loland	2011-05-02
      BUG#11766327: Range analysis should not be done many times
                    for the same index
      
      (Former bug 59415)
            
      The optimizer often choses to access a table through an index
      that does not provide the correct ordering for free. To remedy
      this, the function test_if_skip_sort_order() is called to see
      if another index is as good as the chosen index and at the
      same time is able to provide ordering.
                  
      This implies that test_if_skip_sort_ordering() goes through a
      full range analysis (if range access is applicable) to check
      whether or not another range access plan should be used
      instead of the currently chosen ref/range access method.
              
      The problem is that if range analysis is performed and it is
      decided that it is not better than whatever we had, the range
      analysis will most likely be performed again and again with
      the same outcome because test_if_skip_sort_order() is called
      from multiple locations.
                  
      This patch avoids the unnecessarily repeated range analysis
      described above by introducing key_map
      JOIN_TAB::quick_order_tested which is checked to see
      if range analysis has already been performed for a given key.
     @ sql/sql_select.h
        Introduce JOIN_TAB::quick_order_tested used to avoid repeated range analysis for the same key in test_if_skip_sort_order()

    modified:
      sql/sql_select.cc
      sql/sql_select.h
 3354 Jorgen Loland	2011-05-02
      BUG#11766327: Range analysis should not be done many times 
                    for the   same index
      
      (formerly 59415)
      
      Pre-bugfix changes: 
       * Make JOIN_TAB::select_cond private, add getter
       * Rename JOIN_TAB::select_cond to m_condition
       * Rename JOIN_TAB::pre_idx_push_select_cond to 
         pre_idx_push_cond
       * Make use of and_with_condition() where possible to 
         simplify code
       * Rename JOIN_TAB::set_select_cond() to 
         set_condition() since it sets JOIN_TAB->m_condition, not 
         join_tab->select->cond as the name suggested
       * Rename JOIN_TAB::set_cond() to 
         set_jt_and_sel_condition() since it sets 
         join_tab->m_condition AND join_tab->select->cond
     @ sql/sql_select.cc
        JOIN_TAB::cond made private, rename JOIN_TAB functions for getting and setting condition to better reflect reality, use and_with_condition() where possible to simplify code.
     @ sql/sql_select.h
        Fix naming of JOIN_TAB variables and functions to better reflect reality. Make JOIN_TAB::m_condition (formerly select_cond) private.
     @ sql/sql_show.cc
        JOIN_TAB::m_condition (formerly select_cond) is made private

    modified:
      sql/sql_select.cc
      sql/sql_select.h
      sql/sql_show.cc
 3353 Vasil Dimov	2011-05-02 [merge]
      Merge mysql-5.5 -> mysql-trunk (empty)

 3352 Bjorn Munch	2011-05-02 [merge]
      null upmerge

 3351 Bjorn Munch	2011-05-02 [merge]
      merge from trunk-mtr

    modified:
      mysql-test/mysql-test-run.pl
 3350 Marc Alff	2011-04-30
      Fixed tree name

    modified:
      .bzr-mysql/default.conf
 3349 Nirbhay Choubey	2011-04-30 [merge]
      Merge of fix for bug#11757855 from mysql-5.5 -> mysql-trunk.

    modified:
      cmake/os/WindowsCache.cmake
      cmd-line-utils/libedit/el.c
      config.h.cmake
      configure.cmake
 3348 Marc Alff	2011-04-29
      Re branched tree for WL#5378

    modified:
      .bzr-mysql/default.conf
 3347 Davi Arnaut	2011-04-29 [merge]
      Merge of mysql-5.5 into mysql-trunk.

    modified:
      config.h.cmake
      configure.cmake
      vio/viosocket.c
 3346 Rafal Somla	2011-04-29 [merge]
      null merge of bug#11766631 and bug#11879051 from mysql-5.5

    added:
      libmysql/authentication_win/
      libmysql/authentication_win/CMakeLists.txt
      libmysql/authentication_win/common.cc
      libmysql/authentication_win/common.h
      libmysql/authentication_win/handshake.cc
      libmysql/authentication_win/handshake.h
      libmysql/authentication_win/handshake_client.cc
      libmysql/authentication_win/log_client.cc
      libmysql/authentication_win/plugin_client.cc
    modified:
      libmysql/CMakeLists.txt
      sql-common/client.c
 3345 Bjorn Munch	2011-04-29 [merge]
      null upmerge

 3344 Bjorn Munch	2011-04-29 [merge]
      merge from trunk-mtr

    modified:
      mysql-test/lib/My/ConfigFactory.pm
      mysql-test/lib/My/SafeProcess/safe_process.pl
      mysql-test/mysql-test-run.pl
 3343 Vasil Dimov	2011-04-29 [merge]
      Merge mysql-trunk-innodb -> mysql-trunk

    modified:
      storage/innobase/include/trx0purge.h
      storage/innobase/include/trx0rec.h
      storage/innobase/trx/trx0purge.c
      storage/innobase/trx/trx0rec.c
 3342 Mattias Jonsson	2011-04-29 [merge]
      merge

 3341 Mattias Jonsson	2011-04-29 [merge]
      merge

    modified:
      mysql-test/r/partition_myisam.result
      mysql-test/t/partition_myisam.test
      sql/ha_partition.cc
 3340 Georgi Kodinov	2011-04-29 [merge]
      merge mysql-5.5->mysql-trunk

    modified:
      sql-common/client_plugin.c
 3339 Marc Alff	2011-04-28
      Bug#12409247 - STAGE TIMER DEFAULT SHOULD BE NANOSECONDS
      
      Changed the STAGE timer default unit to be NANOSECOND.
      Adjusted the test suite accordingly.

    modified:
      mysql-test/suite/perfschema/r/column_privilege.result
      mysql-test/suite/perfschema/r/dml_setup_timers.result
      mysql-test/suite/perfschema/r/start_server_nothing.result
      mysql-test/suite/perfschema/t/column_privilege.test
      mysql-test/suite/perfschema/t/dml_setup_timers.test
      storage/perfschema/pfs_timer.cc
 3338 Davi Arnaut	2011-04-28
      Bug#11765860: main.kill fails under valgrind with 'invalid file descriptor' warning
      
      A pre-requisite patch for removing signal-based alarms, aiming
      to replace signal-based alarms with standard synchronization
      functions in order to simplify the process of killing a slave
      thread.
      
      A new pair of mutex and condition variable is introduced
      to synchronize thread sleep and finalization. A new mutex is
      required because the slave threads are terminated while holding
      the slave thread locks (run_lock), which can not be relinquished
      during termination as this would affect the lock order.
     @ sql/mysqld.cc
        Add performance schema instrumentation for the new locks.
     @ sql/rpl_info.h
        Introduce a new pair of mutex and condition variable to
        implement a interruptible sleep.
     @ sql/rpl_slave.cc
        Use a timed wait on a condition variable to implement a
        interruptible sleep. The wait is registered with the THD
        object so that the thread will be woken up if killed.

    modified:
      sql/mysqld.cc
      sql/mysqld.h
      sql/rpl_info.cc
      sql/rpl_info.h
      sql/rpl_info_factory.cc
      sql/rpl_mi.cc
      sql/rpl_mi.h
      sql/rpl_rli.cc
      sql/rpl_rli.h
      sql/rpl_slave.cc
 3337 Georgi Kodinov	2011-04-28 [merge]
      merge mysql-5.5->mysql-trunk

 3336 Georgi Kodinov	2011-04-28 [merge]
      Merged mysql-5.5->mysql-trunk

    modified:
      include/mysql/client_plugin.h
      include/mysql/client_plugin.h.pp
      libmysql/libmysql.def
 3335 Tor Didriksen	2011-04-28 [merge]
      Automerge opt-team => trunk

    modified:
      mysql-test/r/order_by_all.result
      sql/handler.cc
      sql/sql_select.cc
      sql/sql_select.h
=== modified file 'cmake/os/WindowsCache.cmake'
--- a/cmake/os/WindowsCache.cmake	2011-04-13 19:16:45 +0000
+++ b/cmake/os/WindowsCache.cmake	2011-04-30 05:36:44 +0000
@@ -104,6 +104,10 @@ ENDIF()
 SET(HAVE_ISINF CACHE  INTERNAL "")
 SET(HAVE_ISNAN CACHE  INTERNAL "")
 SET(HAVE_ISSETUGID CACHE  INTERNAL "")
+SET(HAVE_GETUID CACHE  INTERNAL "")
+SET(HAVE_GETEUID CACHE  INTERNAL "")
+SET(HAVE_GETGID CACHE  INTERNAL "")
+SET(HAVE_GETEGID CACHE  INTERNAL "")
 SET(HAVE_LANGINFO_H CACHE  INTERNAL "")
 SET(HAVE_LDIV 1 CACHE  INTERNAL "")
 SET(HAVE_LIMITS_H 1 CACHE  INTERNAL "")

=== modified file 'cmd-line-utils/libedit/el.c'
--- a/cmd-line-utils/libedit/el.c	2009-06-11 16:21:32 +0000
+++ b/cmd-line-utils/libedit/el.c	2011-04-29 13:22:46 +0000
@@ -478,7 +478,13 @@ el_source(EditLine *el, const char *fnam
 
 	fp = NULL;
 	if (fname == NULL) {
-#ifdef HAVE_ISSETUGID
+/* XXXMYSQL: Bug#49967 */
+#if defined(HAVE_GETUID) && defined(HAVE_GETEUID) && \
+    defined(HAVE_GETGID) && defined(HAVE_GETEGID)
+#define HAVE_IDENTITY_FUNCS 1
+#endif
+
+#if (defined(HAVE_ISSETUGID) || defined(HAVE_IDENTITY_FUNCS))
 		static const char elpath[] = "/.editrc";
 /* XXXMYSQL: Portability fix (for which platforms?) */
 #ifdef MAXPATHLEN
@@ -486,9 +492,13 @@ el_source(EditLine *el, const char *fnam
 #else
 		char path[4096];
 #endif
-
+#ifdef HAVE_ISSETUGID
 		if (issetugid())
 			return (-1);
+#elif defined(HAVE_IDENTITY_FUNCS)
+                if (getuid() != geteuid() || getgid() != getegid())
+                  return (-1);
+#endif
 		if ((ptr = getenv("HOME")) == NULL)
 			return (-1);
 		if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
@@ -498,9 +508,10 @@ el_source(EditLine *el, const char *fnam
 		fname = path;
 #else
 		/*
-		 * If issetugid() is missing, always return an error, in order
-		 * to keep from inadvertently opening up the user to a security
-		 * hole.
+		 * If issetugid() or the above mentioned get[e][u|g]id()
+		 * functions are missing, always return an error, in order
+		 * to keep from inadvertently opening up the user to a
+		 * security hole.
 		 */
 		return (-1);
 #endif

=== modified file 'config.h.cmake'
--- a/config.h.cmake	2011-04-14 08:09:49 +0000
+++ b/config.h.cmake	2011-04-30 05:36:44 +0000
@@ -124,6 +124,7 @@
 #cmakedefine FIONREAD_IN_SYS_IOCTL 1
 #cmakedefine GWINSZ_IN_SYS_IOCTL 1
 #cmakedefine TIOCSTAT_IN_SYS_IOCTL 1
+#cmakedefine FIONREAD_IN_SYS_FILIO 1
 
 /* Functions we may want to use. */
 #cmakedefine HAVE_AIOWAIT 1
@@ -172,6 +173,10 @@
 #cmakedefine gmtime_r @gmtime_r@
 #cmakedefine HAVE_INITGROUPS 1
 #cmakedefine HAVE_ISSETUGID 1
+#cmakedefine HAVE_GETUID 1
+#cmakedefine HAVE_GETEUID 1
+#cmakedefine HAVE_GETGID 1
+#cmakedefine HAVE_GETEGID 1
 #cmakedefine HAVE_ISNAN 1
 #cmakedefine HAVE_ISINF 1
 #cmakedefine HAVE_LARGE_PAGE_OPTION 1

=== modified file 'configure.cmake'
--- a/configure.cmake	2011-04-13 19:16:45 +0000
+++ b/configure.cmake	2011-04-30 05:36:44 +0000
@@ -353,6 +353,10 @@ CHECK_FUNCTION_EXISTS (getwd HAVE_GETWD)
 CHECK_FUNCTION_EXISTS (gmtime_r HAVE_GMTIME_R)
 CHECK_FUNCTION_EXISTS (initgroups HAVE_INITGROUPS)
 CHECK_FUNCTION_EXISTS (issetugid HAVE_ISSETUGID)
+CHECK_FUNCTION_EXISTS (getuid HAVE_GETUID)
+CHECK_FUNCTION_EXISTS (geteuid HAVE_GETEUID)
+CHECK_FUNCTION_EXISTS (getgid HAVE_GETGID)
+CHECK_FUNCTION_EXISTS (getegid HAVE_GETEGID)
 CHECK_FUNCTION_EXISTS (ldiv HAVE_LDIV)
 CHECK_FUNCTION_EXISTS (localtime_r HAVE_LOCALTIME_R)
 CHECK_FUNCTION_EXISTS (longjmp HAVE_LONGJMP)
@@ -478,6 +482,7 @@ CHECK_SYMBOL_EXISTS(getpagesize "unistd.
 CHECK_SYMBOL_EXISTS(TIOCGWINSZ "sys/ioctl.h" GWINSZ_IN_SYS_IOCTL)
 CHECK_SYMBOL_EXISTS(FIONREAD "sys/ioctl.h" FIONREAD_IN_SYS_IOCTL)
 CHECK_SYMBOL_EXISTS(TIOCSTAT "sys/ioctl.h" TIOCSTAT_IN_SYS_IOCTL)
+CHECK_SYMBOL_EXISTS(FIONREAD "sys/filio.h" FIONREAD_IN_SYS_FILIO)
 CHECK_SYMBOL_EXISTS(gettimeofday "sys/time.h" HAVE_GETTIMEOFDAY)
 
 CHECK_SYMBOL_EXISTS(finite  "math.h" HAVE_FINITE_IN_MATH_H)

=== modified file 'include/mysql/client_plugin.h'
--- a/include/mysql/client_plugin.h	2010-11-10 15:55:57 +0000
+++ b/include/mysql/client_plugin.h	2011-04-06 14:31:26 +0000
@@ -156,8 +156,7 @@ mysql_client_register_plugin(struct st_m
 
   @retval 0 on success, 1 in case of failure
 **/
-int STDCALL mysql_plugin_options(struct st_mysql_client_plugin *plugin,
-                                 const char *option,
-                                 const void *value);
+int mysql_plugin_options(struct st_mysql_client_plugin *plugin,
+                         const char *option, const void *value);
 #endif
 

=== modified file 'include/mysql/client_plugin.h.pp'
--- a/include/mysql/client_plugin.h.pp	2010-10-13 15:11:29 +0000
+++ b/include/mysql/client_plugin.h.pp	2011-04-28 10:08:05 +0000
@@ -35,6 +35,5 @@ mysql_client_find_plugin(struct st_mysql
 struct st_mysql_client_plugin *
 mysql_client_register_plugin(struct st_mysql *mysql,
                              struct st_mysql_client_plugin *plugin);
-int STDCALL mysql_plugin_options(struct st_mysql_client_plugin *plugin,
-                                 const char *option,
-                                 const void *value);
+int mysql_plugin_options(struct st_mysql_client_plugin *plugin,
+                         const char *option, const void *value);

=== modified file 'libmysql/CMakeLists.txt'
--- a/libmysql/CMakeLists.txt	2011-03-28 08:49:43 +0000
+++ b/libmysql/CMakeLists.txt	2011-04-29 21:53:46 +0000
@@ -1,4 +1,4 @@
-# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
 # 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -134,6 +134,12 @@ CACHE INTERNAL "Functions exported by cl
 
 )
 
+IF(WIN32)
+  ADD_SUBDIRECTORY(authentication_win)
+  SET(WITH_AUTHENTICATION_WIN 1)
+  ADD_DEFINITIONS(-DAUTHENTICATION_WIN)
+ENDIF(WIN32)
+
 SET(CLIENT_SOURCES
   get_password.c 
   libmysql.c
@@ -151,6 +157,10 @@ ADD_DEPENDENCIES(clientlib GenError)
 
 SET(LIBS clientlib dbug strings vio mysys ${ZLIB_LIBRARY} ${SSL_LIBRARIES} ${LIBDL})
 
+IF(WITH_AUTHENTICATION_WIN)
+  LIST(APPEND LIBS auth_win_client)
+ENDIF(WITH_AUTHENTICATION_WIN)
+
 # Merge several convenience libraries into one big mysqlclient
 # and link them together into shared library.
 MERGE_LIBRARIES(mysqlclient STATIC ${LIBS} COMPONENT Development)

=== added directory 'libmysql/authentication_win'
=== added file 'libmysql/authentication_win/CMakeLists.txt'
--- a/libmysql/authentication_win/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ b/libmysql/authentication_win/CMakeLists.txt	2011-04-29 21:53:46 +0000
@@ -0,0 +1,33 @@
+# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+#
+# Configuration for building Windows Authentication Plugin (client-side)
+#
+
+ADD_DEFINITIONS(-DSECURITY_WIN32)
+ADD_DEFINITIONS(-DDEBUG_ERRROR_LOG)  # no error logging in production builds
+ADD_DEFINITIONS(-DWINAUTH_USE_DBUG_LIB)      # it is OK to use dbug library in statically
+                                             # linked plugin
+
+SET(HEADERS common.h handshake.h)
+SET(PLUGIN_SOURCES plugin_client.cc handshake_client.cc log_client.cc common.cc handshake.cc)
+
+ADD_CONVENIENCE_LIBRARY(auth_win_client ${PLUGIN_SOURCES} ${HEADERS})
+TARGET_LINK_LIBRARIES(auth_win_client Secur32)
+
+# In IDE, group headers in a separate folder.
+
+SOURCE_GROUP(Headers REGULAR_EXPRESSION ".*h$")

=== added file 'libmysql/authentication_win/common.cc'
--- a/libmysql/authentication_win/common.cc	1970-01-01 00:00:00 +0000
+++ b/libmysql/authentication_win/common.cc	2011-04-29 21:53:46 +0000
@@ -0,0 +1,492 @@
+/* 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 "common.h"
+#include <sddl.h>   // for ConvertSidToStringSid()
+#include <secext.h> // for GetUserNameEx()
+
+
+template <> void error_log_print<error_log_level::INFO>(const char *fmt, ...);
+template <> void error_log_print<error_log_level::WARNING>(const char *fmt, ...);
+template <> void error_log_print<error_log_level::ERROR>(const char *fmt, ...);
+
+
+/** Connection class **************************************************/
+
+/**
+  Create connection out of an active MYSQL_PLUGIN_VIO object.
+
+  @param[in] vio  pointer to a @c MYSQL_PLUGIN_VIO object used for
+                  connection - it can not be NULL
+*/
+
+Connection::Connection(MYSQL_PLUGIN_VIO *vio): m_vio(vio), m_error(0)
+{
+  DBUG_ASSERT(vio);
+}
+
+
+/**
+  Write data to the connection.
+
+  @param[in]  blob  data to be written
+
+  @return 0 on success, VIO error code on failure.
+
+  @note In case of error, VIO error code is stored in the connection object
+  and can be obtained with @c error() method.
+*/
+
+int Connection::write(const Blob &blob)
+{
+  m_error= m_vio->write_packet(m_vio, blob.ptr(), blob.len());
+
+#ifndef DBUG_OFF
+  if (m_error)
+    DBUG_PRINT("error", ("vio write error %d", m_error));
+#endif
+
+  return m_error;
+}
+
+
+/**
+  Read data from connection.
+
+  @return A Blob containing read packet or null Blob in case of error.
+
+  @note In case of error, VIO error code is stored in the connection object
+  and can be obtained with @c error() method.
+*/
+
+Blob Connection::read()
+{
+  unsigned char *ptr;
+  int len= m_vio->read_packet(m_vio, &ptr);
+
+  if (len < 0)
+  {
+    m_error= true;
+    return Blob();
+  }
+
+  return Blob(ptr, len);
+}
+
+
+/** Sid class *****************************************************/
+
+
+/**
+  Create Sid object corresponding to a given account name.
+
+  @param[in]  account_name  name of a Windows account
+
+  The account name can be in any form accepted by @c LookupAccountName()
+  function.
+
+  @note In case of errors created object is invalid and its @c is_valid()
+  method returns @c false.
+*/
+
+Sid::Sid(const wchar_t *account_name): m_data(NULL)
+#ifndef DBUG_OFF
+, m_as_string(NULL)
+#endif
+{
+  DWORD sid_size= 0, domain_size= 0;
+  bool success;
+
+  // Determine required buffer sizes
+
+  success= LookupAccountNameW(NULL, account_name, NULL, &sid_size,
+                             NULL, &domain_size, &m_type);
+
+  if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+  {
+#ifndef DBUG_OFF
+    Error_message_buf error_buf;
+    DBUG_PRINT("error", ("Could not determine SID buffer size, "
+                         "LookupAccountName() failed with error %X (%s)",
+                         GetLastError(), get_last_error_message(error_buf)));
+#endif
+    return;
+  }
+
+  // Query for SID (domain is ignored)
+
+  wchar_t *domain= new wchar_t[domain_size];
+  m_data= (TOKEN_USER*) new BYTE[sid_size + sizeof(TOKEN_USER)];
+  m_data->User.Sid= (BYTE*)m_data + sizeof(TOKEN_USER);
+
+  success= LookupAccountNameW(NULL, account_name,
+                             m_data->User.Sid, &sid_size,
+                             domain, &domain_size,
+                             &m_type);
+
+  if (!success || !is_valid())
+  {
+#ifndef DBUG_OFF
+    Error_message_buf error_buf;
+    DBUG_PRINT("error", ("Could not determine SID of '%S', "
+                         "LookupAccountName() failed with error %X (%s)",
+                         account_name, GetLastError(),
+                         get_last_error_message(error_buf)));
+#endif
+    goto fail;
+  }
+
+  goto end;
+
+fail:
+  if (m_data)
+    delete [] m_data;
+  m_data= NULL;
+
+end:
+  if (domain)
+    delete [] domain;
+}
+
+
+/**
+  Create Sid object corresponding to a given security token.
+
+  @param[in]  token   security token of a Windows account
+
+  @note In case of errors created object is invalid and its @c is_valid()
+  method returns @c false.
+*/
+
+Sid::Sid(HANDLE token): m_data(NULL)
+#ifndef DBUG_OFF
+, m_as_string(NULL)
+#endif
+{
+  DWORD             req_size= 0;
+  bool              success;
+
+  // Determine required buffer size
+
+  success= GetTokenInformation(token, TokenUser, NULL, 0, &req_size);
+  if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+  {
+#ifndef DBUG_OFF
+    Error_message_buf error_buf;
+    DBUG_PRINT("error", ("Could not determine SID buffer size, "
+                         "GetTokenInformation() failed with error %X (%s)",
+                         GetLastError(), get_last_error_message(error_buf)));
+#endif
+    return;
+  }
+
+  m_data= (TOKEN_USER*) new BYTE[req_size];
+  success= GetTokenInformation(token, TokenUser, m_data, req_size, &req_size);
+
+  if (!success || !is_valid())
+  {
+    delete [] m_data;
+    m_data= NULL;
+#ifndef DBUG_OFF
+    if (!success)
+    {
+      Error_message_buf error_buf;
+      DBUG_PRINT("error", ("Could not read SID from security token, "
+                           "GetTokenInformation() failed with error %X (%s)",
+                           GetLastError(), get_last_error_message(error_buf)));
+    }
+#endif
+  }
+}
+
+
+Sid::~Sid()
+{
+  if (m_data)
+    delete [] m_data;
+#ifndef DBUG_OFF
+  if (m_as_string)
+    LocalFree(m_as_string);
+#endif
+}
+
+/// Check if Sid object is valid.
+bool Sid::is_valid(void) const
+{
+  return m_data && m_data->User.Sid && IsValidSid(m_data->User.Sid);
+}
+
+
+#ifndef DBUG_OFF
+
+/**
+  Produces string representation of the SID.
+
+  @return String representation of the SID or NULL in case of errors.
+
+  @note Memory allocated for the string is automatically freed in Sid's
+  destructor.
+*/
+
+const char* Sid::as_string()
+{
+  if (!m_data)
+    return NULL;
+
+  if (!m_as_string)
+  {
+    bool success= ConvertSidToStringSid(m_data->User.Sid, &m_as_string);
+
+    if (!success)
+    {
+#ifndef DBUG_OFF
+      Error_message_buf error_buf;
+      DBUG_PRINT("error", ("Could not get textual representation of a SID, "
+                           "ConvertSidToStringSid() failed with error %X (%s)",
+                           GetLastError(), get_last_error_message(error_buf)));
+#endif
+      m_as_string= NULL;
+      return NULL;
+    }
+  }
+
+  return m_as_string;
+}
+
+#endif
+
+
+bool Sid::operator ==(const Sid &other)
+{
+  if (!is_valid() || !other.is_valid())
+    return false;
+
+  return EqualSid(m_data->User.Sid, other.m_data->User.Sid);
+}
+
+
+/** Generating User Principal Name *************************/
+
+/**
+  Call Windows API functions to get UPN of the current user and store it
+  in internal buffer.
+*/
+
+UPN::UPN(): m_buf(NULL)
+{
+  wchar_t  buf1[MAX_SERVICE_NAME_LENGTH];
+
+  // First we try to use GetUserNameEx.
+
+  m_len= sizeof(buf1)/sizeof(wchar_t);
+
+  if (!GetUserNameExW(NameUserPrincipal, buf1, (PULONG)&m_len))
+  {
+    if (GetLastError())
+    {
+#ifndef DBUG_OFF
+      Error_message_buf error_buf;
+      DBUG_PRINT("note", ("When determining UPN"
+                          ", GetUserNameEx() failed with error %X (%s)",
+                          GetLastError(), get_last_error_message(error_buf)));
+#endif
+      if (ERROR_MORE_DATA == GetLastError())
+        ERROR_LOG(INFO, ("Buffer overrun when determining UPN:"
+                         " need %ul characters but have %ul",
+                         m_len, sizeof(buf1)/sizeof(WCHAR)));
+    }
+
+    m_len= 0;   // m_len == 0 indicates invalid UPN
+    return;
+  }
+
+  /*
+    UPN is stored in buf1 in wide-char format - convert it to utf8
+    for sending over network.
+  */
+
+  m_buf= wchar_to_utf8(buf1, &m_len);
+
+  if(!m_buf)
+    ERROR_LOG(ERROR, ("Failed to convert UPN to utf8"));
+
+  // Note: possible error would be indicated by the fact that m_buf is NULL.
+  return;
+}
+
+
+UPN::~UPN()
+{
+  if (m_buf)
+    free(m_buf);
+}
+
+
+/**
+  Convert a wide-char string to utf8 representation.
+
+  @param[in]     string   null-terminated wide-char string to be converted
+  @param[in,out] len      length of the string to be converted or 0; on
+                          return length (in bytes, excluding terminating
+                          null character) of the converted string
+
+  If len is 0 then the length of the string will be computed by this function.
+
+  @return Pointer to a buffer containing utf8 representation or NULL in
+          case of error.
+
+  @note The returned buffer must be freed with @c free() call.          
+*/
+
+char* wchar_to_utf8(const wchar_t *string, size_t *len)
+{
+  char   *buf= NULL; 
+  size_t  str_len= len && *len ? *len : wcslen(string);
+
+  /*
+    A conversion from utf8 to wchar_t will never take more than 3 bytes per
+    character, so a buffer of length 3 * str_len schould be sufficient. 
+    We check that assumption with an assertion later.
+  */
+
+  size_t  buf_len= 3 * str_len;
+
+  buf= (char*)malloc(buf_len + 1);
+  if (!buf)
+  {
+    DBUG_PRINT("error",("Out of memory when converting string '%S' to utf8",
+                        string));
+    return NULL;
+  }
+
+  int res= WideCharToMultiByte(CP_UTF8,              // convert to UTF-8
+                               0,                    // conversion flags
+                               string,               // input buffer
+                               str_len,              // its length
+                               buf, buf_len,         // output buffer and its size
+                               NULL, NULL);          // default character (not used)
+
+  if (res)
+  {
+    buf[res]= '\0';
+    if (len)
+      *len= res;
+    return buf;
+  }
+
+  // res is 0 which indicates error
+
+#ifndef DBUG_OFF
+  Error_message_buf error_buf;
+  DBUG_PRINT("error", ("Could not convert string '%S' to utf8"
+                       ", WideCharToMultiByte() failed with error %X (%s)",
+                       string, GetLastError(), 
+                       get_last_error_message(error_buf)));
+#endif
+
+  // Let's check our assumption about sufficient buffer size
+  DBUG_ASSERT(ERROR_INSUFFICIENT_BUFFER != GetLastError());
+
+  return NULL;
+}
+
+
+/**
+  Convert an utf8 string to a wide-char string.
+
+  @param[in]     string   null-terminated utf8 string to be converted
+  @param[in,out] len      length of the string to be converted or 0; on
+                          return length (in chars) of the converted string
+
+  If len is 0 then the length of the string will be computed by this function.
+
+  @return Pointer to a buffer containing wide-char representation or NULL in
+          case of error.
+
+  @note The returned buffer must be freed with @c free() call.          
+*/
+
+wchar_t* utf8_to_wchar(const char *string, size_t *len)
+{
+  size_t buf_len;
+
+  /* 
+    Note: length (in bytes) of an utf8 string is always bigger than the
+    number of characters in this string. Hence a buffer of size len will
+    be sufficient. We add 1 for the terminating null character.
+  */
+
+  buf_len= len && *len ? *len : strlen(string);
+  wchar_t *buf=  (wchar_t*)malloc((buf_len+1)*sizeof(wchar_t));
+
+  if (!buf)
+  {
+    DBUG_PRINT("error",("Out of memory when converting utf8 string '%s'"
+                        " to wide-char representation", string));
+    return NULL;
+  }
+
+  size_t  res;
+  res= MultiByteToWideChar(CP_UTF8,            // convert from UTF-8
+                           0,                  // conversion flags
+                           string,             // input buffer
+                           buf_len,            // its size
+                           buf, buf_len);      // output buffer and its size
+  if (res)
+  {
+    buf[res]= '\0';
+    if (len)
+      *len= res;
+    return buf;
+  }
+
+  // error in MultiByteToWideChar()
+
+#ifndef DBUG_OFF
+  Error_message_buf error_buf;
+  DBUG_PRINT("error", ("Could not convert UPN from UTF-8"
+                       ", MultiByteToWideChar() failed with error %X (%s)",
+                       GetLastError(), get_last_error_message(error_buf)));
+#endif
+
+  // Let's check our assumption about sufficient buffer size
+  DBUG_ASSERT(ERROR_INSUFFICIENT_BUFFER != GetLastError());
+
+  return NULL;
+}
+
+
+/** Error handling ****************************************************/
+
+
+/**
+  Returns error message corresponding to the last Windows error given
+  by GetLastError().
+
+  @note Error message is overwritten by next call to
+  @c get_last_error_message().
+*/
+
+const char* get_last_error_message(Error_message_buf buf)
+{
+  int error= GetLastError();
+
+  buf[0]= '\0';
+  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPTSTR)buf, sizeof(buf), NULL );
+
+  return buf;
+}

=== added file 'libmysql/authentication_win/common.h'
--- a/libmysql/authentication_win/common.h	1970-01-01 00:00:00 +0000
+++ b/libmysql/authentication_win/common.h	2011-04-29 21:53:46 +0000
@@ -0,0 +1,324 @@
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <my_global.h>
+#include <windows.h>
+#include <sspi.h>              // for CtxtHandle
+#include <mysql/plugin_auth.h> // for MYSQL_PLUGIN_VIO
+
+/// Maximum length of the target service name.
+#define MAX_SERVICE_NAME_LENGTH  1024
+
+
+/** Debugging and error reporting infrastructure ***************************/
+
+/*
+  Note: We use plugin local logging and error reporting mechanisms until
+  WL#2940 (plugin service: error reporting) is available.
+*/
+
+#undef INFO
+#undef WARNING
+#undef ERROR
+
+struct error_log_level
+{
+  typedef enum {INFO, WARNING, ERROR}  type;
+};
+
+
+/*
+  If DEBUG_ERROR_LOG is defined then error logging happens only
+  in debug-copiled code. Otherwise ERROR_LOG() expands to 
+  error_log_print() even in production code. Note that in client
+  plugin, error_log_print() will print nothing if opt_auth_win_clinet_log
+  is 0.
+
+  Note: Macro ERROR_LOG() can use printf-like format string like this:
+
+    ERROR_LOG(Level, ("format string", args));
+
+  The implementation should handle it correctly. Currently it is passed 
+  to fprintf() (see error_log_vprint() function).
+*/
+
+extern "C" int opt_auth_win_client_log;
+
+#if defined(DEBUG_ERROR_LOG) && defined(DBUG_OFF)
+#define ERROR_LOG(Level, Msg)     do {} while (0)
+#else
+#define ERROR_LOG(Level, Msg)     error_log_print< error_log_level::Level > Msg
+#endif
+
+
+void error_log_vprint(error_log_level::type level,
+                        const char *fmt, va_list args);
+
+template <error_log_level::type Level>
+void error_log_print(const char *fmt, ...)
+{
+  va_list args;
+  va_start(args, fmt);
+  error_log_vprint(Level, fmt, args);
+  va_end(args);
+}
+
+typedef char Error_message_buf[1024];
+const char* get_last_error_message(Error_message_buf);
+
+
+/*
+  Internal implementation of debug message printing which does not use
+  dbug library. This is invoked via macro:
+
+    DBUG_PRINT_DO(Keyword, ("format string", args));
+
+  This is supposed to be used as an implementation of DBUG_PRINT() macro,
+  unless the dbug library implementation is used or debug messages are disabled.
+*/
+
+#ifndef DBUG_OFF
+
+#define DBUG_PRINT_DO(Keyword, Msg) \
+  do { \
+    if (2 > opt_auth_win_client_log) break; \
+    fprintf(stderr, "winauth: %s: ", Keyword); \
+    debug_msg Msg; \
+  } while (0)
+
+inline
+void debug_msg(const char *fmt, ...)
+{
+  va_list args;
+  va_start(args, fmt);
+  vfprintf(stderr, fmt, args);
+  fputc('\n', stderr);
+  fflush(stderr);
+  va_end(args);
+}
+
+#else
+#define DBUG_PRINT_DO(K, M)  do {} while (0)
+#endif
+
+
+#ifndef WINAUTH_USE_DBUG_LIB
+
+#undef  DBUG_PRINT
+#define DBUG_PRINT(Keyword, Msg)  DBUG_PRINT_DO(Keyword, Msg)
+
+/*
+  Redefine few more debug macros to make sure that no symbols from
+  dbug library are used.
+*/
+
+#undef DBUG_ENTER
+#define DBUG_ENTER(X)  do {} while (0)
+
+#undef DBUG_RETURN
+#define DBUG_RETURN(X) return (X)
+
+#undef DBUG_ASSERT
+#ifndef DBUG_OFF
+#define DBUG_ASSERT(X) assert (X)
+#else
+#define DBUG_ASSERT(X) do {} while (0)
+#endif
+
+#undef DBUG_DUMP
+#define DBUG_DUMP(A,B,C) do {} while (0)
+
+#endif
+
+
+/** Blob class *************************************************************/
+
+typedef unsigned char byte;
+
+/**
+  Class representing a region of memory (e.g., a string or binary buffer).
+
+  @note This class does not allocate memory. It merely describes a region
+  of memory which must be allocated externally (if it is dynamic memory).
+*/
+
+class Blob
+{
+  byte   *m_ptr;  ///< Pointer to the first byte of the memory region.
+  size_t  m_len;  ///< Length of the memory region.
+
+public:
+
+  Blob(): m_ptr(NULL), m_len(0)
+  {}
+
+  Blob(const byte *ptr, const size_t len)
+  : m_ptr(const_cast<byte*>(ptr)), m_len(len)
+  {}
+
+  Blob(const char *str): m_ptr((byte*)str)
+  {
+    m_len= strlen(str);
+  }
+
+  byte*  ptr() const
+  {
+    return m_ptr;
+  }
+
+  size_t len() const
+  {
+    return m_len;
+  }
+
+  byte& operator[](unsigned pos) const
+  {
+    static byte out_of_range= 0;  // alas, no exceptions...
+    return pos < len() ? m_ptr[pos] : out_of_range;
+  }
+
+  bool is_null() const
+  {
+    return m_ptr == NULL;
+  }
+
+  void trim(size_t l)
+  {
+    m_len= l;
+  }
+};
+
+
+/** Connection class *******************************************************/
+
+/**
+  Convenience wrapper around MYSQL_PLUGIN_VIO object providing basic
+  read/write operations.
+*/
+
+class Connection
+{
+  MYSQL_PLUGIN_VIO *m_vio;    ///< Pointer to @c MYSQL_PLUGIN_VIO structure.
+
+  /**
+    If non-zero, indicates that connection is broken. If this has happened
+    because of failed operation, stores non-zero error code from that failure.
+  */
+  int               m_error;
+
+public:
+
+  Connection(MYSQL_PLUGIN_VIO *vio);
+  int write(const Blob&);
+  Blob read();
+
+  int error() const
+  {
+    return m_error;
+  }
+};
+
+
+/** Sid class **************************************************************/
+
+/**
+  Class for storing and manipulating Windows security identifiers (SIDs).
+*/
+
+class Sid
+{
+  TOKEN_USER    *m_data;  ///< Pointer to structure holding identifier's data.
+  SID_NAME_USE   m_type;  ///< Type of identified entity.
+
+public:
+
+  Sid(const wchar_t*);
+  Sid(HANDLE sec_token);
+  ~Sid();
+
+  bool is_valid(void) const;
+
+  bool is_group(void) const
+  {
+    return m_type == SidTypeGroup
+           || m_type == SidTypeWellKnownGroup
+           || m_type == SidTypeAlias;
+  }
+
+  bool is_user(void) const
+  {
+    return m_type == SidTypeUser;
+  }
+
+  bool operator==(const Sid&);
+
+  operator PSID() const
+  {
+    return (PSID)m_data->User.Sid;
+  }
+
+#ifndef DBUG_OFF
+
+private:
+    char *m_as_string;  ///< Cached string representation of the SID.
+public:
+    const char* as_string();
+
+#endif
+};
+
+
+/** UPN class **************************************************************/
+
+/**
+  An object of this class obtains and stores User Principal Name of the
+  account under which current process is running.
+*/
+
+class UPN
+{
+  char   *m_buf;  ///< Pointer to UPN in utf8 representation.
+  size_t  m_len;  ///< Length of the name.
+
+public:
+
+  UPN();
+  ~UPN();
+
+  bool is_valid() const
+  {
+    return m_len > 0;
+  }
+
+  const Blob as_blob() const
+  {
+    return m_len ? Blob((byte*)m_buf, m_len) : Blob();
+  }
+
+  const char* as_string() const
+  {
+    return (const char*)m_buf;
+  }
+
+};
+
+
+char*     wchar_to_utf8(const wchar_t*, size_t*);
+wchar_t*  utf8_to_wchar(const char*, size_t*);
+
+#endif

=== added file 'libmysql/authentication_win/handshake.cc'
--- a/libmysql/authentication_win/handshake.cc	1970-01-01 00:00:00 +0000
+++ b/libmysql/authentication_win/handshake.cc	2011-04-29 21:53:46 +0000
@@ -0,0 +1,289 @@
+/* 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 "handshake.h"
+
+
+/** Handshake class implementation **********************************/
+
+/**
+  Create common part of handshake context.
+
+  @param[in]  ssp   name of the SSP (Security Service Provider) to
+                    be used for authentication
+  @param[in]  side  is this handshake object used for server- or
+                    client-side handshake
+
+  Prepare for handshake using the @c ssp security module. We use
+  "Negotiate" which picks best available module. Parameter @c side
+  tells if this is preparing for server or client side authentication
+  and is used to prepare appropriate credentials.
+*/
+
+Handshake::Handshake(const char *ssp, side_t side)
+: m_atts(0L), m_error(0), m_complete(FALSE),
+  m_have_credentials(false), m_have_sec_context(false)
+#ifndef DBUG_OFF
+  , m_ssp_info(NULL)
+#endif
+{
+  SECURITY_STATUS ret;
+
+  // Obtain credentials for the authentication handshake.
+
+  ret= AcquireCredentialsHandle(NULL, (SEC_CHAR*)ssp,
+         side == SERVER ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND,
+         NULL, NULL, NULL, NULL, &m_cred, &m_expire);
+
+  if (ret != SEC_E_OK)
+  {
+    DBUG_PRINT("error", ("AcqireCredentialsHandle() failed"
+                         " with error %X", ret));
+    ERROR_LOG(ERROR, ("Could not obtain local credentials"
+                      " required for authentication"));
+    m_error= ret;
+  }
+
+  m_have_credentials= true;
+}
+
+
+Handshake::~Handshake()
+{
+  if (m_have_credentials)
+    FreeCredentialsHandle(&m_cred);
+  if (m_have_sec_context)
+    DeleteSecurityContext(&m_sctx);
+  m_output.free();
+
+#ifndef DBUG_OFF
+  if (m_ssp_info)
+    FreeContextBuffer(m_ssp_info);
+#endif
+}
+
+
+/**
+  Read and process data packets from the other end of a connection.
+
+  @param[IN] con  a connection to read packets from
+
+  Packets are read and processed until authentication handshake is 
+  complete. It is assumed that the peer will send at least one packet. 
+  Packets are processed with @c process_data() method. If new data is
+  generated during packet processing, this data is sent to the peer and
+  another round of packet exchange starts.
+
+  @return 0 on success.
+
+  @note In case of error, appropriate error message is logged.
+*/
+int Handshake::packet_processing_loop()
+{
+  m_round= 0;
+
+  do {
+    ++m_round;
+    // Read packet send by the peer
+
+    DBUG_PRINT("info", ("Waiting for packet"));
+    Blob packet= read_packet();
+    if (error())
+    {
+      ERROR_LOG(ERROR, ("Error reading packet in round %d", m_round));
+      return 1;
+    }
+    DBUG_PRINT("info", ("Got packet of length %d", packet.len()));
+
+    /*
+      Process received data, possibly generating new data to be sent.
+    */
+
+    Blob new_data= process_data(packet);
+
+    if (error())
+    {
+      ERROR_LOG(ERROR, ("Error processing packet in round %d", m_round));
+      return 1;
+    }
+
+    /*
+      If new data has been generated, send it to the peer. Otherwise
+      handshake must be completed.
+    */
+
+    if (!new_data.is_null())
+    {
+      DBUG_PRINT("info", ("Round %d started", m_round));
+
+      DBUG_PRINT("info", ("Sending packet of length %d", new_data.len()));
+      int ret= write_packet(new_data);
+      if (ret)
+      {
+        ERROR_LOG(ERROR, ("Error writing packet in round %d", m_round));
+        return 1;
+      }
+      DBUG_PRINT("info", ("Data sent"));
+    }
+    else if (!is_complete())
+    {
+      ERROR_LOG(ERROR, ("No data to send in round %d"
+                        " but handshake is not complete", m_round));
+      return 1;
+    }
+
+    /*
+      To protect against malicious clients, break handshake exchange if
+      too many rounds.
+    */
+
+    if (m_round > MAX_HANDSHAKE_ROUNDS)
+    {
+      ERROR_LOG(ERROR, ("Authentication handshake could not be completed"
+                        " after %d rounds", m_round));
+      return 1;
+    }
+
+  } while(!is_complete());
+
+  ERROR_LOG(INFO, ("Handshake completed after %d rounds", m_round));
+  return 0;
+}
+
+
+#ifndef DBUG_OFF
+
+/**
+  Get name of the security package which was used in authentication.
+
+  This method should be called only after handshake was completed. It is
+  available only in debug builds.
+
+  @return Name of security package or NULL if it can not be obtained.
+*/
+
+const char* Handshake::ssp_name()
+{
+  if (!m_ssp_info && m_complete)
+  {
+    SecPkgContext_PackageInfo pinfo;
+
+    int ret= QueryContextAttributes(&m_sctx, SECPKG_ATTR_PACKAGE_INFO, &pinfo);
+
+    if (SEC_E_OK == ret)
+    {
+      m_ssp_info= pinfo.PackageInfo;
+    }
+    else
+      DBUG_PRINT("error",
+                 ("Could not obtain SSP info from authentication context"
+                  ", QueryContextAttributes() failed with error %X", ret));
+  }
+
+  return m_ssp_info ? m_ssp_info->Name : NULL;
+}
+
+#endif
+
+
+/**
+  Process result of @c {Initialize,Accept}SecurityContext() function.
+
+  @param[in]  ret   return code from @c {Initialize,Accept}SecurityContext()
+                    function
+
+  This function analyses return value of Windows
+  @c {Initialize,Accept}SecurityContext() function. A call to
+  @c CompleteAuthToken() is done if requested. If authentication is complete,
+  this fact is marked in the internal state of the Handshake object.
+  If errors are detected the object is moved to error state.
+
+  @return True if error has been detected.
+*/
+
+bool Handshake::process_result(int ret)
+{
+  /*
+    First check for errors and set the m_complete flag if the result
+    indicates that handshake is complete.
+  */
+
+  switch (ret)
+  {
+  case SEC_E_OK:
+  case SEC_I_COMPLETE_NEEDED:
+    // Handshake completed
+    m_complete= true;
+    break;
+
+  case SEC_I_CONTINUE_NEEDED:
+  case SEC_I_COMPLETE_AND_CONTINUE:
+    break;
+
+  default:
+    m_error= ret;
+    return true;
+  }
+
+  m_have_sec_context= true;
+
+  /*
+    If the result indicates a need for this, complete the authentication
+    token.
+  */
+
+  switch (ret)
+  {
+  case SEC_I_COMPLETE_NEEDED:
+  case SEC_I_COMPLETE_AND_CONTINUE:
+    ret= CompleteAuthToken(&m_sctx, &m_output);
+    if (ret != 0)
+    {
+      DBUG_PRINT("error", ("CompleteAuthToken() failed with error %X", ret));
+      m_error= ret;
+      return true;
+    }
+  default:
+    break;
+  }
+
+  return false;
+}
+
+
+/** Security_buffer class implementation **********************************/
+
+
+Security_buffer::Security_buffer(const Blob &blob): m_allocated(false)
+{
+  init(blob.ptr(), blob.len());
+}
+
+
+Security_buffer::Security_buffer(): m_allocated(true)
+{
+  init(NULL, 0);
+}
+
+
+void Security_buffer::free(void)
+{
+  if (!m_allocated)
+    return;
+  if (!ptr())
+    return;
+  FreeContextBuffer(ptr());
+  m_allocated= false;
+}

=== added file 'libmysql/authentication_win/handshake.h'
--- a/libmysql/authentication_win/handshake.h	1970-01-01 00:00:00 +0000
+++ b/libmysql/authentication_win/handshake.h	2011-04-29 21:53:46 +0000
@@ -0,0 +1,181 @@
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef HANDSHAKE_H
+#define HANDSHAKE_H
+
+#include "common.h"
+
+/**
+  Name of the SSP (Security Support Provider) to be used for authentication.
+
+  We use "Negotiate" which will find the most secure SSP which can be used
+  and redirect to that SSP.
+*/
+#define SSP_NAME  "Negotiate"
+
+/**
+  Maximal number of rounds in authentication handshake.
+
+  Server will interrupt authentication handshake with error if client's
+  identity can not be determined within this many rounds.
+*/
+#define MAX_HANDSHAKE_ROUNDS  50
+
+
+/// Convenience wrapper around @c SecBufferDesc.
+
+class Security_buffer: public SecBufferDesc
+{
+  SecBuffer m_buf;        ///< A @c SecBuffer instance.
+
+  void init(byte *ptr, size_t len)
+  {
+    ulVersion= 0;
+    cBuffers=  1;
+    pBuffers=  &m_buf;
+
+    m_buf.BufferType= SECBUFFER_TOKEN;
+    m_buf.pvBuffer= ptr;
+    m_buf.cbBuffer= len;
+  }
+
+  /// If @c false, no deallocation will be done in the destructor.
+  bool m_allocated;
+
+ public:
+
+  Security_buffer(const Blob&);
+  Security_buffer();
+
+  ~Security_buffer()
+  {
+    free();
+  }
+
+  byte*  ptr() const
+  {
+    return (byte*)m_buf.pvBuffer;
+  }
+
+  size_t len() const
+  {
+    return m_buf.cbBuffer;
+  }
+
+  bool is_valid() const
+  {
+    return ptr() != NULL;
+  }
+
+  const Blob as_blob() const
+  {
+    return Blob(ptr(), len());
+  }
+
+  void free(void);
+};
+
+
+/// Common base for Handshake_{server,client}.
+
+class Handshake
+{
+public:
+
+  typedef enum {CLIENT, SERVER} side_t;
+
+  Handshake(const char *ssp, side_t side);
+  virtual ~Handshake();
+
+  int Handshake::packet_processing_loop();
+
+  bool virtual is_complete() const
+  {
+    return m_complete;
+  }
+
+  int error() const
+  {
+    return m_error;
+  }
+
+protected:
+
+  /// Security context object created during the handshake.
+  CtxtHandle  m_sctx;
+
+  /// Credentials of the principal performing this handshake.
+  CredHandle  m_cred;
+
+  /// Stores expiry date of the created security context.
+  TimeStamp  m_expire;
+
+  /// Stores attributes of the created security context.
+  ULONG  m_atts;
+
+  /**
+    Round of the handshake (starting from round 1). One round
+    consist of reading packet from the other side, processing it and
+    optionally sending a reply (see @c packet_processing_loop()).
+  */
+  unsigned int m_round;
+
+  /// If non-zero, stores error code of the last failed operation.
+  int  m_error;
+
+  /// @c true when handshake is complete.
+  bool  m_complete;
+
+  /// @c true when the principal credentials has been determined.
+  bool  m_have_credentials;
+
+  /// @c true when the security context has been created.
+  bool  m_have_sec_context;
+
+  /// Buffer for data to be send to the other side.
+  Security_buffer  m_output;
+
+  bool process_result(int);
+
+  /**
+    This method is used inside @c packet_processing_loop to process
+    data packets received from the other end.
+
+    @param[IN]  data  data to be processed
+
+    @return A blob with data to be sent to the other end or null blob if
+    no more data needs to be exchanged.
+  */
+  virtual Blob process_data(const Blob &data) =0;
+
+  /// Read packet from the other end.
+  virtual Blob read_packet()  =0;
+
+  /// Write packet to the other end.
+  virtual int  write_packet(Blob &data) =0;
+
+#ifndef DBUG_OFF
+
+private:
+  SecPkgInfo  *m_ssp_info;
+public:
+  const char* ssp_name();
+
+#endif
+};
+
+
+#endif

=== added file 'libmysql/authentication_win/handshake_client.cc'
--- a/libmysql/authentication_win/handshake_client.cc	1970-01-01 00:00:00 +0000
+++ b/libmysql/authentication_win/handshake_client.cc	2011-04-29 21:53:46 +0000
@@ -0,0 +1,378 @@
+/* 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 "handshake.h"
+
+#include <mysql.h> // for MYSQL structure
+
+
+/// Client-side context for authentication handshake
+
+class Handshake_client: public Handshake
+{
+  /**
+    Name of the server's service for which we authenticate.
+
+    The service name is sent by server in the initial packet. If no
+    service name is used, this member is @c NULL.
+  */
+  SEC_WCHAR  *m_service_name;
+
+  /// Buffer for storing service name obtained from server.
+  SEC_WCHAR   m_service_name_buf[MAX_SERVICE_NAME_LENGTH];
+
+  Connection &m_con;
+
+public:
+
+  Handshake_client(Connection &con, const char *target, size_t len);
+  ~Handshake_client();
+
+  Blob  first_packet();
+  Blob  process_data(const Blob&);
+
+  Blob read_packet();
+  int write_packet(Blob &data);
+};
+
+
+/**
+  Create authentication handshake context for client.
+
+  @param con     connection for communication with the peer 
+  @param target  name of the target service with which we will authenticate
+                 (can be NULL if not used)
+
+  Some security packages (like Kerberos) require providing explicit name
+  of the service with which a client wants to authenticate. The server-side
+  authentication plugin sends this name in the greeting packet
+  (see @c win_auth_handshake_{server,client}() functions).
+*/
+
+Handshake_client::Handshake_client(Connection &con, 
+                                   const char *target, size_t len)
+: Handshake(SSP_NAME, CLIENT), m_service_name(NULL), m_con(con)
+{
+  if (!target || 0 == len)
+    return;
+
+  // Convert received UPN to internal WCHAR representation.
+
+  m_service_name= utf8_to_wchar(target, &len);
+
+  if (m_service_name)
+    DBUG_PRINT("info", ("Using target service: %S\n", m_service_name));
+  else
+  {
+    /*
+      Note: we ignore errors here - m_target will be NULL, the target name
+      will not be used and system will fall-back to NTLM authentication. But
+      we leave trace in error log.
+    */
+    ERROR_LOG(WARNING, ("Could not decode UPN sent by the server"
+                        "; target service name will not be used"
+                        " and Kerberos authentication will not work"));
+  }
+}
+
+
+Handshake_client::~Handshake_client()
+{
+  if (m_service_name)
+    free(m_service_name);
+}
+
+
+Blob Handshake_client::read_packet()
+{
+  /*
+    We do a fake read in the first round because first
+    packet from the server containing UPN must be read
+    before the handshake context is created and the packet
+    processing loop starts. We return an empty blob here
+    and process_data() function will ignore it.
+  */
+  if (m_round == 1)
+    return Blob();
+
+  // Otherwise we read packet from the connection.
+
+  Blob packet= m_con.read();
+  m_error= m_con.error();
+  if (!m_error && packet.is_null())
+    m_error= true;  // (no specific error code assigned)
+
+  if (m_error)
+    return Blob();
+
+  DBUG_PRINT("dump", ("Got the following bytes"));
+  DBUG_DUMP("dump", packet.ptr(), packet.len());
+  return packet;
+}
+
+
+
+int Handshake_client::write_packet(Blob &data)
+{
+  /*
+   Length of the first data payload send by client authentication plugin is
+   limited to 255 bytes (because it is wrapped inside client authentication
+   packet and is length-encoded with 1 byte for the length).
+
+   If the data payload is longer than 254 bytes, then it is sent in two parts:
+   first part of length 255 will be embedded in the authentication packet, 
+   second part will be sent in the following packet. Byte 255 of the first 
+   part contains information about the total length of the payload. It is a
+   number of blocks of size 512 bytes which is sufficient to store the
+   combined packets.
+
+   Server's logic for reading first client's payload is as follows
+   (see Handshake_server::read_packet()):
+   1. Read data from the authentication packet, if it is shorter than 255 bytes 
+      then that is all data sent by client.
+   2. If there is 255 bytes of data in the authentication packet, read another
+      packet and append it to the data, skipping byte 255 of the first packet
+      which can be used to allocate buffer of appropriate size.
+  */
+
+  size_t len2= 0;   // length of the second part of first data payload
+  byte saved_byte;  // for saving byte 255 in which data length is stored
+
+  if (m_round == 1 && data.len() > 254)
+  {
+    len2= data.len() - 254;
+    DBUG_PRINT("info", ("Splitting first packet of length %lu"
+                        ", %lu bytes will be sent in a second part", 
+                        data.len(), len2));
+    /* 
+      Store in byte 255 the number of 512b blocks that are needed to
+      keep all the data.
+    */
+    unsigned block_count= data.len()/512 + ((data.len() % 512) ? 1 : 0);
+    DBUG_ASSERT(block_count < (unsigned)0x100);
+    saved_byte= data[254];
+    data[254] = block_count;
+
+    data.trim(255);
+  }
+
+  DBUG_PRINT("dump", ("Sending the following data"));
+  DBUG_DUMP("dump", data.ptr(), data.len());
+  int ret= m_con.write(data);
+
+  if (ret)
+    return ret;
+
+  // Write second part if it is present.
+  if (len2)
+  {
+    data[254]= saved_byte;
+    Blob data2(data.ptr() + 254, len2);
+    DBUG_PRINT("info", ("Sending second part of data"));
+    DBUG_DUMP("info", data2.ptr(), data2.len());
+    ret= m_con.write(data2);
+  }
+
+  return ret;
+}
+
+
+/**
+  Process data sent by server.
+
+  @param[in]  data  blob with data from server
+
+  This method analyses data sent by server during authentication handshake.
+  If client should continue packet exchange, this method returns data to
+  be sent to the server next. If no more data needs to be exchanged, an
+  empty blob is returned and @c is_complete() is @c true. In case of error
+  an empty blob is returned and @c error() gives non-zero error code.
+
+  When invoked for the first time (in the first round of the handshake)
+  there is no data from the server (data blob is null) and the intial
+  packet is generated without an input.
+
+  @return Data to be sent to the server next or null blob if no more data
+  needs to be exchanged or in case of error.
+*/
+
+Blob Handshake_client::process_data(const Blob &data)
+{
+#if !defined(DBUG_OFF) && defined(WINAUTH_USE_DBUG_LIB)
+  /*
+    Code for testing the logic for sending the first client payload.
+
+    A fake data of length given by environment variable TEST_PACKET_LENGTH
+    (or default 255 bytes) is sent to the server. First 2 bytes of the
+    payload contain its total length (LSB first). The length of test data
+    is limited to 2048 bytes.
+
+    Upon receiving test data, server will check that data is correct and
+    refuse connection. If server detects data errors it will crash on 
+    assertion.
+
+    This code is executed if debug flag "winauth_first_packet_test" is
+    set, e.g. using client option:
+
+     --debug="d,winauth_first_packet_test"
+
+     The same debug flag must be enabled in the server, e.g. using 
+     statement:
+
+     SET GLOBAL debug= '+d,winauth_first_packet_test'; 
+  */
+
+  static byte test_buf[2048];
+
+  if (m_round == 1 
+      && DBUG_EVALUATE_IF("winauth_first_packet_test", true, false))
+  {
+    const char *env= getenv("TEST_PACKET_LENGTH");
+    size_t len= env ? atoi(env) : 0;
+    if (!len)
+      len= 255;
+    if (len > sizeof(test_buf))
+      len= sizeof(test_buf);
+
+    // Store data length in first 2 bytes.
+    byte *ptr= test_buf;
+    *ptr++= len & 0xFF;
+    *ptr++= len >> 8;
+
+    // Fill remaining bytes with known values.
+    for (byte b= 0; ptr < test_buf + len; ++ptr, ++b)
+      *ptr= b;
+
+    return Blob(test_buf, len);
+  };
+
+#endif
+
+  Security_buffer  input(data);
+  SECURITY_STATUS  ret;
+
+  m_output.free();
+
+  ret= InitializeSecurityContextW(
+         &m_cred,
+         m_round == 1 ? NULL : &m_sctx,        // partial context
+         m_service_name,                       // service name
+         ASC_REQ_ALLOCATE_MEMORY,              // requested attributes
+         0,                                    // reserved
+         SECURITY_NETWORK_DREP,                // data representation
+         m_round == 1 ? NULL : &input,         // input data
+         0,                                    // reserved
+         &m_sctx,                              // context
+         &m_output,                            // output data
+         &m_atts,                              // attributes
+         &m_expire);                           // expire date
+
+  if (process_result(ret))
+  {
+    DBUG_PRINT("error",
+               ("InitializeSecurityContext() failed with error %X", ret));
+    return Blob();
+  }
+
+  return m_output.as_blob();
+}
+
+
+/**********************************************************************/
+
+
+/**
+  Perform authentication handshake from client side.
+
+  @param[in]  vio    pointer to @c MYSQL_PLUGIN_VIO instance to be used
+                     for communication with the server
+  @param[in]  mysql  pointer to a MySQL connection for which we authenticate
+
+  After reading the initial packet from server, containing its UPN to be
+  used as service name, client starts packet exchange by sending the first
+  packet in this exchange. While handshake is not yet completed, client
+  reads packets sent by the server and process them, possibly generating new
+  data to be sent to the server.
+
+  This function reports errors.
+
+  @return 0 on success.
+*/
+
+int win_auth_handshake_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+  DBUG_ENTER("win_auth_handshake_client");
+
+  /*
+    Check if we should enable logging.
+  */
+  {
+    const char *opt= getenv("AUTHENTICATION_WIN_LOG");
+    int opt_val= opt ? atoi(opt) : 0;
+    if (opt && !opt_val)
+    {
+      if (!strncasecmp("on", opt, 2))    opt_val= 1;
+      if (!strncasecmp("yes", opt, 3))   opt_val= 1;
+      if (!strncasecmp("true", opt, 4))  opt_val= 1;
+      if (!strncasecmp("debug", opt, 5)) opt_val= 2;
+      if (!strncasecmp("dbug", opt, 4))  opt_val= 2;
+    }
+    opt_auth_win_client_log= opt_val;
+  }
+
+  ERROR_LOG(INFO, ("Authentication handshake for account %s", mysql->user));
+
+  // Create connection object.
+
+  Connection con(vio);
+  DBUG_ASSERT(!con.error());
+
+  // Read initial packet from server containing service name.
+
+  Blob service_name= con.read();
+
+  if (con.error() || service_name.is_null())
+  {
+    ERROR_LOG(ERROR, ("Error reading initial packet"));
+    DBUG_RETURN(CR_ERROR);
+  }
+  DBUG_PRINT("info", ("Got initial packet of length %d", service_name.len()));
+
+  // Create authentication handshake context using the given service name.
+
+  Handshake_client hndshk(con,
+                          service_name[0] ? (char *)service_name.ptr() : NULL,
+                          service_name.len());
+  if (hndshk.error())
+  {
+    ERROR_LOG(ERROR, ("Could not create authentication handshake context"));
+    DBUG_RETURN(CR_ERROR);
+  }
+
+  DBUG_ASSERT(!hndshk.error());
+
+  /*
+    Read and process packets from server until handshake is complete.
+    Note that the first read from server is dummy 
+    (see Handshake_client::read_packet()) as we already have read the 
+    first packet to establish service name.
+  */
+  if (hndshk.packet_processing_loop())
+    DBUG_RETURN(CR_ERROR);
+
+  DBUG_ASSERT(!hndshk.error() && hndshk.is_complete());
+
+  DBUG_RETURN(CR_OK);
+}

=== added file 'libmysql/authentication_win/log_client.cc'
--- a/libmysql/authentication_win/log_client.cc	1970-01-01 00:00:00 +0000
+++ b/libmysql/authentication_win/log_client.cc	2011-04-29 21:53:46 +0000
@@ -0,0 +1,55 @@
+/* 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 <my_global.h>
+#include "common.h"
+
+/**
+  This option is set in win_auth_handshake_client() function 
+  in handshake_client.cc.
+
+  Values:
+  0 - no logging
+  1 - log error/warning/info messages
+  2 - also log debug messages
+
+  Note: No error or debug messages are logged in production code
+  (see logging macros in common.h).
+*/
+int opt_auth_win_client_log= 0;
+
+
+// Client-side logging function
+
+void error_log_vprint(error_log_level::type level,
+                        const char *fmt, va_list args)
+{
+  if (0 == opt_auth_win_client_log)
+    return;
+
+  const char *level_string= "";
+
+  switch (level)
+  {
+  case error_log_level::INFO:    level_string= "Note"; break;
+  case error_log_level::WARNING: level_string= "Warning"; break;
+  case error_log_level::ERROR:   level_string= "ERROR"; break;
+  }
+
+  fprintf(stderr, "Windows Authentication Plugin %s: ", level_string);
+  vfprintf(stderr, fmt, args);
+  fputc('\n', stderr);
+  fflush(stderr);
+}

=== added file 'libmysql/authentication_win/plugin_client.cc'
--- a/libmysql/authentication_win/plugin_client.cc	1970-01-01 00:00:00 +0000
+++ b/libmysql/authentication_win/plugin_client.cc	2011-04-29 21:53:46 +0000
@@ -0,0 +1,58 @@
+/* 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 <my_global.h>
+#include <mysql.h>
+#include <mysql/plugin_auth.h>
+#include <mysql/client_plugin.h>
+
+#include "common.h"
+
+static int win_auth_client_plugin_init(char*, size_t, int, va_list)
+{
+  return 0;
+}
+
+
+static int win_auth_client_plugin_deinit()
+{
+  return 0;
+}
+
+
+int win_auth_handshake_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+
+
+/*
+  Client plugin declaration. This is added to mysql_client_builtins[]
+  in sql-common/client.c
+*/
+
+extern "C"
+st_mysql_client_plugin_AUTHENTICATION win_auth_client_plugin=
+{
+  MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+  MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+  "authentication_windows_client",
+  "Rafal Somla",
+  "Windows Authentication Plugin - client side",
+  {0,1,0},
+  "GPL",
+  NULL,
+  win_auth_client_plugin_init,
+  win_auth_client_plugin_deinit,
+  NULL,                            // option handling
+  win_auth_handshake_client
+};

=== modified file 'libmysql/libmysql.def'
--- a/libmysql/libmysql.def	2010-10-04 12:54:41 +0000
+++ b/libmysql/libmysql.def	2011-04-06 14:31:26 +0000
@@ -104,4 +104,3 @@ EXPORTS
 	mysql_server_end
 	mysql_set_character_set
 	mysql_get_character_set_info
-        mysql_plugin_options

=== modified file 'mysql-test/collections/default.experimental'
--- a/mysql-test/collections/default.experimental	2011-04-27 12:59:39 +0000
+++ b/mysql-test/collections/default.experimental	2011-05-02 14:43:45 +0000
@@ -19,11 +19,14 @@ main.type_float @freebsd                
 main.wait_timeout @solaris               # Bug#51244 2010-04-26 alik wait_timeout fails on OpenSolaris
 
 rpl.rpl_checksum                         # BUG#12370830 2011-04-18 sven rpl_checksum failed on pb2 (server crash)
+rpl.rpl_cross_version                    # BUG#12416611 2011-05-02 sven fails sporadically on pb2, valgrind errors
+rpl.rpl_delayed_slave                    # BUG#57514 rpl_delayed_slave fails sporadically in pb
 rpl.rpl_heartbeat_basic                  # BUG#12403008 2011-04-27 sven fails sporadically
 rpl.rpl_innodb_bug28430                  # Bug#46029
+rpl.rpl_row_ignorable_event              # BUG#12416768 2011-05-02 sven fails sporadically on pb2, result mistmatch in output from mysqlbinlog
 rpl.rpl_row_sp011  @solaris              # Bug#47791 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun
-rpl.rpl_delayed_slave                    # BUG#57514 rpl_delayed_slave fails sporadically in pb
 rpl.rpl_seconds_behind_master            # BUG#58053 2010-11-24 luis fails sporadically on pb2
+rpl.rpl_show_slave_hosts                 # BUG#12416700 2011-05-02 sven fails sporadically
 rpl.rpl_show_slave_running               # BUG#12346048 2011-04-11 sven fails sporadically on pb2
 
 sys_vars.max_sp_recursion_depth_func @solaris # Bug#47791 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun

=== modified file 'mysql-test/include/ipv6.inc'
--- a/mysql-test/include/ipv6.inc	2010-02-08 10:43:56 +0000
+++ b/mysql-test/include/ipv6.inc	2011-05-03 13:04:00 +0000
@@ -1,11 +1,6 @@
 eval CREATE USER testuser@'$IPv6' identified by '1234';
 eval GRANT ALL ON test.* TO testuser@'$IPv6';
 eval SHOW GRANTS FOR testuser@'$IPv6';
-# deliver NULL instead of a valid number, see bug#34037
-eval SET @nip= inet_aton('$IPv6');
-SELECT @nip;
-SELECT inet_ntoa(@nip);
-# delivers a wrong value, see bug#34037
 --replace_result ::1 localhost
 SELECT USER();
 --replace_result ::1 localhost

=== added file 'mysql-test/include/ipv6_func.inc'
--- a/mysql-test/include/ipv6_func.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/ipv6_func.inc	2011-05-03 18:05:37 +0000
@@ -0,0 +1,36 @@
+eval SET @nip= inet_aton('$IPv6');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+SELECT inet_ntoa(c2) FROM t1;
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+SELECT inet_ntoa(c3) FROM t1;
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+SELECT inet_ntoa(c4) FROM t1;
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+SELECT inet_ntoa(c5) FROM t1;
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+SELECT inet_ntoa(c6) FROM t1;
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+SELECT inet_ntoa(@nip);
+
+eval SET @nip6= inet6_aton('$IPv6');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+SELECT inet6_ntoa(c1) FROM t1;
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+SELECT inet6_ntoa(c2) FROM t1;
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+SELECT inet6_ntoa(c3) FROM t1;
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+SELECT inet6_ntoa(c4) FROM t1;
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+SELECT inet6_ntoa(c5) FROM t1;
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+SELECT inet6_ntoa(c6) FROM t1;
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+

=== modified file 'mysql-test/lib/My/ConfigFactory.pm'
--- a/mysql-test/lib/My/ConfigFactory.pm	2011-01-18 11:09:49 +0000
+++ b/mysql-test/lib/My/ConfigFactory.pm	2011-04-18 13:38:00 +0000
@@ -1,5 +1,5 @@
 # -*- cperl -*-
-# 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 Library General Public
@@ -150,7 +150,11 @@ sub fix_tmpdir {
 sub fix_log_error {
   my ($self, $config, $group_name, $group)= @_;
   my $dir= $self->{ARGS}->{vardir};
-  return "$dir/log/$group_name.err";
+  if ( $::opt_valgrind and $::opt_debug ) {
+    return "$dir/log/$group_name.trace";
+  } else {
+    return "$dir/log/$group_name.err";
+  }
 }
 
 sub fix_log {

=== modified file 'mysql-test/lib/My/SafeProcess/safe_process.pl'
--- a/mysql-test/lib/My/SafeProcess/safe_process.pl	2007-12-20 17:39:33 +0000
+++ b/mysql-test/lib/My/SafeProcess/safe_process.pl	2011-04-20 12:58:53 +0000
@@ -94,7 +94,7 @@ eval {
   local $SIG{INT}=  \&handle_signal;
   local $SIG{CHLD}= sub {
     message("Got signal @_");
-    kill(9, -$child_pid);
+    kill('KILL', -$child_pid);
     my $ret= waitpid($child_pid, 0);
     if ($? & 127){
       exit(65); # Killed by signal
@@ -134,7 +134,7 @@ if ( $@ ) {
 # Use negative pid in order to kill the whole
 # process group
 #
-my $ret= kill(9, -$child_pid);
+my $ret= kill('KILL', -$child_pid);
 message("Killed child: $child_pid, ret: $ret");
 if ($ret > 0) {
   message("Killed child: $child_pid");

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2011-04-15 08:39:02 +0000
+++ b/mysql-test/mysql-test-run.pl	2011-04-29 14:12:09 +0000
@@ -275,12 +275,13 @@ my $opt_strace_client;
 
 our $opt_user = "root";
 
-my $opt_valgrind= 0;
+our $opt_valgrind= 0;
 my $opt_valgrind_mysqld= 0;
 my $opt_valgrind_mysqltest= 0;
 my @default_valgrind_args= ("--show-reachable=yes");
 my @valgrind_args;
 my $opt_valgrind_path;
+my $valgrind_reports= 0;
 my $opt_callgrind;
 my %mysqld_logs;
 my $opt_debug_sync_timeout= 300; # Default timeout for WAIT_FOR actions.
@@ -505,6 +506,25 @@ sub main {
 
   push @$completed, run_ctest() if $opt_ctest;
 
+  if ($opt_valgrind) {
+    # Create minimalistic "test" for the reporting
+    my $tinfo = My::Test->new
+      (
+       name           => 'valgrind_report',
+      );
+    # Set dummy worker id to align report with normal tests
+    $tinfo->{worker} = 0 if $opt_parallel > 1;
+    if ($valgrind_reports) {
+      $tinfo->{result}= 'MTR_RES_FAILED';
+      $tinfo->{comment}= "Valgrind reported failures at shutdown, see above";
+      $tinfo->{failures}= 1;
+    } else {
+      $tinfo->{result}= 'MTR_RES_PASSED';
+    }
+    mtr_report_test($tinfo);
+    push @$completed, $tinfo;
+  }
+
   mtr_print_line();
 
   if ( $opt_gcov ) {
@@ -705,6 +725,9 @@ sub run_test_server ($$$) {
 	elsif ($line =~ /^SPENT/) {
 	  add_total_times($line);
 	}
+	elsif ($line eq 'VALGREP' && $opt_valgrind) {
+	  $valgrind_reports= 1;
+	}
 	else {
 	  mtr_error("Unknown response: '$line' from client");
 	}
@@ -890,6 +913,7 @@ sub run_worker ($) {
       my $valgrind_reports= 0;
       if ($opt_valgrind_mysqld) {
         $valgrind_reports= valgrind_exit_reports();
+	print $server "VALGREP\n" if $valgrind_reports;
       }
       if ( $opt_gprof ) {
 	gprof_collect (find_mysqld($basedir), keys %gprof_dirs);
@@ -2198,7 +2222,12 @@ sub environment_setup {
   $ENV{'DEFAULT_MASTER_PORT'}= $mysqld_variables{'port'};
   $ENV{'MYSQL_TMP_DIR'}=      $opt_tmpdir;
   $ENV{'MYSQLTEST_VARDIR'}=   $opt_vardir;
+  # Used for guessing default plugin dir, we can't really know for sure
   $ENV{'MYSQL_LIBDIR'}=       "$basedir/lib";
+  # Override if this does not exist, but lib64 does (best effort)
+  if (! -d "$basedir/lib" && -d "$basedir/lib64") {
+    $ENV{'MYSQL_LIBDIR'}=     "$basedir/lib64";
+  }
   $ENV{'MYSQL_BINDIR'}=       "$bindir";
   $ENV{'MYSQL_SHAREDIR'}=     $path_language;
   $ENV{'MYSQL_CHARSETSDIR'}=  $path_charsetsdir;
@@ -4094,6 +4123,9 @@ sub extract_warning_lines ($$) {
     );
   my $skip_valgrind= 0;
 
+  my $last_pat= "";
+  my $num_rep= 0;
+
   foreach my $line ( @lines )
   {
     if ($opt_valgrind_mysqld) {
@@ -4108,11 +4140,29 @@ sub extract_warning_lines ($$) {
     {
       if ( $line =~ /$pat/ )
       {
-	print $Fwarn $line;
+	# Remove initial timestamp and look for consecutive identical lines
+	my $line_pat= $line;
+	$line_pat =~ s/^[0-9: ]*//;
+	if ($line_pat eq $last_pat) {
+	  $num_rep++;
+	} else {
+	  # Previous line had been repeated, report that first
+	  if ($num_rep) {
+	    print $Fwarn ".... repeated $num_rep times: $last_pat";
+	    $num_rep= 0;
+	  }
+	  $last_pat= $line_pat;
+	  print $Fwarn $line;
+	}
 	last;
       }
     }
   }
+  # Catch the case of last warning being repeated
+  if ($num_rep) {
+    print $Fwarn ".... repeated $num_rep times: $last_pat";
+  }
+
   $Fwarn = undef; # Close file
 
 }
@@ -4749,13 +4799,6 @@ sub mysqld_start ($$) {
   unlink($mysqld->value('pid-file'));
 
   my $output= $mysqld->value('#log-error');
-  if ( $opt_valgrind and $opt_debug )
-  {
-    # When both --valgrind and --debug is selected, send
-    # all output to the trace file, making it possible to
-    # see the exact location where valgrind complains
-    $output= "$opt_vardir/log/".$mysqld->name().".trace";
-  }
   # Remember this log file for valgrind error report search
   $mysqld_logs{$output}= 1 if $opt_valgrind;
   # Remember data dir for gmon.out files if using gprof
@@ -5690,6 +5733,7 @@ sub valgrind_exit_reports() {
                         @culprits);
             mtr_print_line();
             print ("$valgrind_rep\n");
+            $found_err= 1;
             $err_in_report= 0;
           }
           # Make ready to collect new report

=== modified file 'mysql-test/r/func_misc.result'
--- a/mysql-test/r/func_misc.result	2010-12-17 14:02:56 +0000
+++ b/mysql-test/r/func_misc.result	2011-05-03 13:03:00 +0000
@@ -400,6 +400,594 @@ DROP TABLE t1;
 #
 # End of 5.5 tests
 #
+
+# --
+# -- WL#5787: IPv6-capable INET_ATON and INET_NTOA functions.
+# --
+
+# -- INET6_ATON: checking NULL, invalid types, out-of range values...
+
+SELECT INET6_ATON(NULL) IS NULL;
+INET6_ATON(NULL) IS NULL
+1
+SELECT INET6_ATON(123) IS NULL;
+INET6_ATON(123) IS NULL
+1
+SELECT INET6_ATON(123.45) IS NULL;
+INET6_ATON(123.45) IS NULL
+1
+SELECT INET6_ATON(NOW()) IS NULL;
+INET6_ATON(NOW()) IS NULL
+1
+SELECT INET6_ATON('1.2.3') IS NULL;
+INET6_ATON('1.2.3') IS NULL
+1
+SELECT INET6_ATON('1.2.3.') IS NULL;
+INET6_ATON('1.2.3.') IS NULL
+1
+SELECT INET6_ATON('1..3.4') IS NULL;
+INET6_ATON('1..3.4') IS NULL
+1
+SELECT INET6_ATON('-1.2.3.4') IS NULL;
+INET6_ATON('-1.2.3.4') IS NULL
+1
+SELECT INET6_ATON('1.2.3.256') IS NULL;
+INET6_ATON('1.2.3.256') IS NULL
+1
+SELECT INET6_ATON('1.2.3.4.5') IS NULL;
+INET6_ATON('1.2.3.4.5') IS NULL
+1
+SELECT INET6_ATON('0001.2.3.4') IS NULL;
+INET6_ATON('0001.2.3.4') IS NULL
+1
+SELECT INET6_ATON('0x1.2.3.4') IS NULL;
+INET6_ATON('0x1.2.3.4') IS NULL
+1
+SELECT INET6_ATON('a.2.3.4') IS NULL;
+INET6_ATON('a.2.3.4') IS NULL
+1
+SELECT INET6_ATON('1.2.3.4:80') IS NULL;
+INET6_ATON('1.2.3.4:80') IS NULL
+1
+SELECT INET6_ATON('1.2.3.4/32') IS NULL;
+INET6_ATON('1.2.3.4/32') IS NULL
+1
+SELECT INET6_ATON('mysql.com') IS NULL;
+INET6_ATON('mysql.com') IS NULL
+1
+SELECT INET6_ATON(':::') IS NULL;
+INET6_ATON(':::') IS NULL
+1
+SELECT INET6_ATON(':1:2:3') IS NULL;
+INET6_ATON(':1:2:3') IS NULL
+1
+SELECT INET6_ATON('1:2:3:') IS NULL;
+INET6_ATON('1:2:3:') IS NULL
+1
+SELECT INET6_ATON(':1::2:3') IS NULL;
+INET6_ATON(':1::2:3') IS NULL
+1
+SELECT INET6_ATON('1::2:3:') IS NULL;
+INET6_ATON('1::2:3:') IS NULL
+1
+SELECT INET6_ATON('::00001') IS NULL;
+INET6_ATON('::00001') IS NULL
+1
+SELECT INET6_ATON('::00001:2') IS NULL;
+INET6_ATON('::00001:2') IS NULL
+1
+SELECT INET6_ATON('::12345') IS NULL;
+INET6_ATON('::12345') IS NULL
+1
+SELECT INET6_ATON('1020::3040::5060') IS NULL;
+INET6_ATON('1020::3040::5060') IS NULL
+1
+SELECT INET6_ATON('::ABCZ') IS NULL;
+INET6_ATON('::ABCZ') IS NULL
+1
+SELECT INET6_ATON('::0x1.2.3.4') IS NULL;
+INET6_ATON('::0x1.2.3.4') IS NULL
+1
+SELECT INET6_ATON('::1.0x2.3.4') IS NULL;
+INET6_ATON('::1.0x2.3.4') IS NULL
+1
+SELECT INET6_ATON('::a.b.c.d') IS NULL;
+INET6_ATON('::a.b.c.d') IS NULL
+1
+SELECT INET6_ATON('::FFFF:0x1.2.3.4') IS NULL;
+INET6_ATON('::FFFF:0x1.2.3.4') IS NULL
+1
+SELECT INET6_ATON('::FFFF:1.0x2.3.4') IS NULL;
+INET6_ATON('::FFFF:1.0x2.3.4') IS NULL
+1
+SELECT INET6_ATON('::FFFF:a.b.c.d') IS NULL;
+INET6_ATON('::FFFF:a.b.c.d') IS NULL
+1
+SELECT INET6_ATON('::1.2.3.4:ABCD') IS NULL;
+INET6_ATON('::1.2.3.4:ABCD') IS NULL
+1
+# NOTE: such addresses are supported because getaddrinfo() supports them.
+# This is just to record the current behaviour.
+SELECT HEX(INET6_ATON('::ABCD:1.2.3.4'));
+HEX(INET6_ATON('::ABCD:1.2.3.4'))
+00000000000000000000ABCD01020304
+
+# -- INET6_ATON: checking binary representation...
+
+SELECT HEX(INET6_ATON('0.0.0.0'));
+HEX(INET6_ATON('0.0.0.0'))
+00000000
+SELECT HEX(INET6_ATON('00.00.00.00'));
+HEX(INET6_ATON('00.00.00.00'))
+00000000
+SELECT HEX(INET6_ATON('000.000.000.000'));
+HEX(INET6_ATON('000.000.000.000'))
+00000000
+SELECT HEX(INET6_ATON('1.2.3.4'));
+HEX(INET6_ATON('1.2.3.4'))
+01020304
+SELECT HEX(INET6_ATON('01.02.03.04'));
+HEX(INET6_ATON('01.02.03.04'))
+01020304
+SELECT HEX(INET6_ATON('001.002.003.004'));
+HEX(INET6_ATON('001.002.003.004'))
+01020304
+SELECT HEX(INET6_ATON('255.255.255.255'));
+HEX(INET6_ATON('255.255.255.255'))
+FFFFFFFF
+SELECT HEX(INET6_ATON('::'));
+HEX(INET6_ATON('::'))
+00000000000000000000000000000000
+SELECT HEX(INET6_ATON('0::0'));
+HEX(INET6_ATON('0::0'))
+00000000000000000000000000000000
+SELECT HEX(INET6_ATON('1::2'));
+HEX(INET6_ATON('1::2'))
+00010000000000000000000000000002
+SELECT HEX(INET6_ATON('0::'));
+HEX(INET6_ATON('0::'))
+00000000000000000000000000000000
+SELECT HEX(INET6_ATON('1::'));
+HEX(INET6_ATON('1::'))
+00010000000000000000000000000000
+SELECT HEX(INET6_ATON('::0'));
+HEX(INET6_ATON('::0'))
+00000000000000000000000000000000
+SELECT HEX(INET6_ATON('::1'));
+HEX(INET6_ATON('::1'))
+00000000000000000000000000000001
+SELECT HEX(INET6_ATON('1:2:3:4:5:6:7:8'));
+HEX(INET6_ATON('1:2:3:4:5:6:7:8'))
+00010002000300040005000600070008
+SELECT HEX(INET6_ATON('::2:3:4:5:6:7:8'));
+HEX(INET6_ATON('::2:3:4:5:6:7:8'))
+00000002000300040005000600070008
+SELECT HEX(INET6_ATON('1::3:4:5:6:7:8'));
+HEX(INET6_ATON('1::3:4:5:6:7:8'))
+00010000000300040005000600070008
+SELECT HEX(INET6_ATON('1:2::4:5:6:7:8'));
+HEX(INET6_ATON('1:2::4:5:6:7:8'))
+00010002000000040005000600070008
+SELECT HEX(INET6_ATON('1:2:3::5:6:7:8'));
+HEX(INET6_ATON('1:2:3::5:6:7:8'))
+00010002000300000005000600070008
+SELECT HEX(INET6_ATON('1:2:3:4::6:7:8'));
+HEX(INET6_ATON('1:2:3:4::6:7:8'))
+00010002000300040000000600070008
+SELECT HEX(INET6_ATON('1:2:3:4:5::7:8'));
+HEX(INET6_ATON('1:2:3:4:5::7:8'))
+00010002000300040005000000070008
+SELECT HEX(INET6_ATON('1:2:3:4:5:6::8'));
+HEX(INET6_ATON('1:2:3:4:5:6::8'))
+00010002000300040005000600000008
+SELECT HEX(INET6_ATON('1:2:3:4:5:6:7::'));
+HEX(INET6_ATON('1:2:3:4:5:6:7::'))
+00010002000300040005000600070000
+SELECT HEX(INET6_ATON('0000:0000::0000:0001'));
+HEX(INET6_ATON('0000:0000::0000:0001'))
+00000000000000000000000000000001
+SELECT HEX(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed'));
+HEX(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed'))
+123456789ABCDEF043218765CBA90FED
+SELECT HEX(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001'));
+HEX(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001'))
+00000000000000000000000000000001
+SELECT HEX(INET6_ATON('::C0A8:0102'));
+HEX(INET6_ATON('::C0A8:0102'))
+000000000000000000000000C0A80102
+SELECT HEX(INET6_ATON('::c0a8:0102'));
+HEX(INET6_ATON('::c0a8:0102'))
+000000000000000000000000C0A80102
+SELECT HEX(INET6_ATON('::192.168.1.2'));
+HEX(INET6_ATON('::192.168.1.2'))
+000000000000000000000000C0A80102
+SELECT HEX(INET6_ATON('::FfFf:C0a8:0102'));
+HEX(INET6_ATON('::FfFf:C0a8:0102'))
+00000000000000000000FFFFC0A80102
+SELECT HEX(INET6_ATON('::ffff:c0a8:0102'));
+HEX(INET6_ATON('::ffff:c0a8:0102'))
+00000000000000000000FFFFC0A80102
+SELECT HEX(INET6_ATON('::ffff:192.168.1.2'));
+HEX(INET6_ATON('::ffff:192.168.1.2'))
+00000000000000000000FFFFC0A80102
+SELECT HEX(INET6_ATON('::01.2.3.4'));
+HEX(INET6_ATON('::01.2.3.4'))
+00000000000000000000000001020304
+SELECT HEX(INET6_ATON('::1.02.3.4'));
+HEX(INET6_ATON('::1.02.3.4'))
+00000000000000000000000001020304
+SELECT HEX(INET6_ATON('::1.2.03.4'));
+HEX(INET6_ATON('::1.2.03.4'))
+00000000000000000000000001020304
+SELECT HEX(INET6_ATON('::1.2.3.04'));
+HEX(INET6_ATON('::1.2.3.04'))
+00000000000000000000000001020304
+SELECT HEX(INET6_ATON('::1.2.3.00'));
+HEX(INET6_ATON('::1.2.3.00'))
+00000000000000000000000001020300
+SELECT HEX(INET6_ATON('::FFFF:01.2.3.4'));
+HEX(INET6_ATON('::FFFF:01.2.3.4'))
+00000000000000000000FFFF01020304
+SELECT HEX(INET6_ATON('::FFFF:1.02.3.4'));
+HEX(INET6_ATON('::FFFF:1.02.3.4'))
+00000000000000000000FFFF01020304
+SELECT HEX(INET6_ATON('::FFFF:1.2.03.4'));
+HEX(INET6_ATON('::FFFF:1.2.03.4'))
+00000000000000000000FFFF01020304
+SELECT HEX(INET6_ATON('::FFFF:1.2.3.04'));
+HEX(INET6_ATON('::FFFF:1.2.3.04'))
+00000000000000000000FFFF01020304
+SELECT HEX(INET6_ATON('::FFFF:1.2.3.00'));
+HEX(INET6_ATON('::FFFF:1.2.3.00'))
+00000000000000000000FFFF01020300
+
+# -- INET6_ATON: checking the length is either 4 or 16...
+
+SELECT LENGTH(INET6_ATON('0.0.0.0'));
+LENGTH(INET6_ATON('0.0.0.0'))
+4
+SELECT LENGTH(INET6_ATON('255.255.255.255'));
+LENGTH(INET6_ATON('255.255.255.255'))
+4
+SELECT LENGTH(INET6_ATON('::'));
+LENGTH(INET6_ATON('::'))
+16
+SELECT LENGTH(INET6_ATON('1020:3040:5060:7080:90A0:B0C0:D0E0:F010'));
+LENGTH(INET6_ATON('1020:3040:5060:7080:90A0:B0C0:D0E0:F010'))
+16
+
+# -- INET6_NTOA: checking NULL, invalid types, out-of range values...
+
+SELECT INET6_NTOA(NULL);
+INET6_NTOA(NULL)
+NULL
+SELECT INET6_NTOA(123);
+INET6_NTOA(123)
+NULL
+SELECT INET6_NTOA(123.456);
+INET6_NTOA(123.456)
+NULL
+SELECT INET6_NTOA(NOW());
+INET6_NTOA(NOW())
+NULL
+SELECT INET6_NTOA(UNHEX('C0A801'));
+INET6_NTOA(UNHEX('C0A801'))
+NULL
+SELECT INET6_NTOA(UNHEX('C0A80102'));
+INET6_NTOA(UNHEX('C0A80102'))
+192.168.1.2
+SELECT INET6_NTOA(UNHEX('C0A8010203'));
+INET6_NTOA(UNHEX('C0A8010203'))
+NULL
+SELECT INET6_NTOA(UNHEX('0102030405060708090A0B0C0D0E0F'));
+INET6_NTOA(UNHEX('0102030405060708090A0B0C0D0E0F'))
+NULL
+SELECT INET6_NTOA(UNHEX('0102030405060708090A0B0C0D0E0F10'));
+INET6_NTOA(UNHEX('0102030405060708090A0B0C0D0E0F10'))
+102:304:506:708:90a:b0c:d0e:f10
+SELECT INET6_NTOA(UNHEX('0102030405060708090A0B0C0D0E0F1011'));
+INET6_NTOA(UNHEX('0102030405060708090A0B0C0D0E0F1011'))
+NULL
+SELECT INET6_NTOA('1234'), INET6_NTOA(BINARY('1234'));
+INET6_NTOA('1234')	INET6_NTOA(BINARY('1234'))
+NULL	49.50.51.52
+SELECT INET6_NTOA('0123456789abcdef'), INET6_NTOA(BINARY('0123456789abcdef'));
+INET6_NTOA('0123456789abcdef')	INET6_NTOA(BINARY('0123456789abcdef'))
+NULL	3031:3233:3435:3637:3839:6162:6364:6566
+
+# -- Checking double-conversion...
+
+SELECT INET6_NTOA(INET6_ATON('::'));
+INET6_NTOA(INET6_ATON('::'))
+::
+SELECT INET6_NTOA(INET6_ATON('0::0'));
+INET6_NTOA(INET6_ATON('0::0'))
+::
+SELECT INET6_NTOA(INET6_ATON('1::2'));
+INET6_NTOA(INET6_ATON('1::2'))
+1::2
+SELECT INET6_NTOA(INET6_ATON('0::'));
+INET6_NTOA(INET6_ATON('0::'))
+::
+SELECT INET6_NTOA(INET6_ATON('1::'));
+INET6_NTOA(INET6_ATON('1::'))
+1::
+SELECT INET6_NTOA(INET6_ATON('::0'));
+INET6_NTOA(INET6_ATON('::0'))
+::
+SELECT INET6_NTOA(INET6_ATON('::1'));
+INET6_NTOA(INET6_ATON('::1'))
+::1
+SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5:6:7:8'));
+INET6_NTOA(INET6_ATON('1:2:3:4:5:6:7:8'))
+1:2:3:4:5:6:7:8
+SELECT INET6_NTOA(INET6_ATON('::2:3:4:5:6:7:8'));
+INET6_NTOA(INET6_ATON('::2:3:4:5:6:7:8'))
+::2:3:4:5:6:7:8
+SELECT INET6_NTOA(INET6_ATON('1::3:4:5:6:7:8'));
+INET6_NTOA(INET6_ATON('1::3:4:5:6:7:8'))
+1::3:4:5:6:7:8
+SELECT INET6_NTOA(INET6_ATON('1:2::4:5:6:7:8'));
+INET6_NTOA(INET6_ATON('1:2::4:5:6:7:8'))
+1:2::4:5:6:7:8
+SELECT INET6_NTOA(INET6_ATON('1:2:3::5:6:7:8'));
+INET6_NTOA(INET6_ATON('1:2:3::5:6:7:8'))
+1:2:3::5:6:7:8
+SELECT INET6_NTOA(INET6_ATON('1:2:3:4::6:7:8'));
+INET6_NTOA(INET6_ATON('1:2:3:4::6:7:8'))
+1:2:3:4::6:7:8
+SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5::7:8'));
+INET6_NTOA(INET6_ATON('1:2:3:4:5::7:8'))
+1:2:3:4:5::7:8
+SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5:6::8'));
+INET6_NTOA(INET6_ATON('1:2:3:4:5:6::8'))
+1:2:3:4:5:6::8
+SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5:6:7::'));
+INET6_NTOA(INET6_ATON('1:2:3:4:5:6:7::'))
+1:2:3:4:5:6:7::
+SELECT INET6_NTOA(INET6_ATON('0000:0000::0000:0001'));
+INET6_NTOA(INET6_ATON('0000:0000::0000:0001'))
+::1
+SELECT INET6_NTOA(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed'));
+INET6_NTOA(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed'))
+1234:5678:9abc:def0:4321:8765:cba9:fed
+SELECT INET6_NTOA(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001'));
+INET6_NTOA(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001'))
+::1
+SELECT INET6_NTOA(INET6_ATON('::C0A8:0102'));
+INET6_NTOA(INET6_ATON('::C0A8:0102'))
+::192.168.1.2
+SELECT INET6_NTOA(INET6_ATON('::c0a8:0102'));
+INET6_NTOA(INET6_ATON('::c0a8:0102'))
+::192.168.1.2
+SELECT INET6_NTOA(INET6_ATON('::192.168.1.2'));
+INET6_NTOA(INET6_ATON('::192.168.1.2'))
+::192.168.1.2
+SELECT INET6_NTOA(INET6_ATON('::FfFf:C0a8:0102'));
+INET6_NTOA(INET6_ATON('::FfFf:C0a8:0102'))
+::ffff:192.168.1.2
+SELECT INET6_NTOA(INET6_ATON('::ffff:c0a8:0102'));
+INET6_NTOA(INET6_ATON('::ffff:c0a8:0102'))
+::ffff:192.168.1.2
+SELECT INET6_NTOA(INET6_ATON('::ffff:192.168.1.2'));
+INET6_NTOA(INET6_ATON('::ffff:192.168.1.2'))
+::ffff:192.168.1.2
+SELECT INET6_NTOA(INET6_ATON('::01.2.3.4'));
+INET6_NTOA(INET6_ATON('::01.2.3.4'))
+::1.2.3.4
+SELECT INET6_NTOA(INET6_ATON('::1.02.3.4'));
+INET6_NTOA(INET6_ATON('::1.02.3.4'))
+::1.2.3.4
+SELECT INET6_NTOA(INET6_ATON('::1.2.03.4'));
+INET6_NTOA(INET6_ATON('::1.2.03.4'))
+::1.2.3.4
+SELECT INET6_NTOA(INET6_ATON('::1.2.3.04'));
+INET6_NTOA(INET6_ATON('::1.2.3.04'))
+::1.2.3.4
+SELECT INET6_NTOA(INET6_ATON('::1.2.3.00'));
+INET6_NTOA(INET6_ATON('::1.2.3.00'))
+::1.2.3.0
+SELECT INET6_NTOA(INET6_ATON('::FFFF:01.2.3.4'));
+INET6_NTOA(INET6_ATON('::FFFF:01.2.3.4'))
+::ffff:1.2.3.4
+SELECT INET6_NTOA(INET6_ATON('::FFFF:1.02.3.4'));
+INET6_NTOA(INET6_ATON('::FFFF:1.02.3.4'))
+::ffff:1.2.3.4
+SELECT INET6_NTOA(INET6_ATON('::FFFF:1.2.03.4'));
+INET6_NTOA(INET6_ATON('::FFFF:1.2.03.4'))
+::ffff:1.2.3.4
+SELECT INET6_NTOA(INET6_ATON('::FFFF:1.2.3.04'));
+INET6_NTOA(INET6_ATON('::FFFF:1.2.3.04'))
+::ffff:1.2.3.4
+SELECT INET6_NTOA(INET6_ATON('::FFFF:1.2.3.00'));
+INET6_NTOA(INET6_ATON('::FFFF:1.2.3.00'))
+::ffff:1.2.3.0
+
+# -- Comparing INET_ATON() and INET6_ATON()...
+
+SELECT HEX(INET_ATON('192.168.1.2'));
+HEX(INET_ATON('192.168.1.2'))
+C0A80102
+SELECT HEX(INET6_ATON('192.168.1.2'));
+HEX(INET6_ATON('192.168.1.2'))
+C0A80102
+SELECT HEX(INET_ATON('255.255.255.255'));
+HEX(INET_ATON('255.255.255.255'))
+FFFFFFFF
+SELECT HEX(INET6_ATON('255.255.255.255'));
+HEX(INET6_ATON('255.255.255.255'))
+FFFFFFFF
+SELECT HEX(INET_ATON('192.168.08.2'));
+HEX(INET_ATON('192.168.08.2'))
+C0A80802
+SELECT HEX(INET6_ATON('192.168.08.2'));
+HEX(INET6_ATON('192.168.08.2'))
+C0A80802
+SELECT HEX(INET_ATON('192.168.0x8.2'));
+HEX(INET_ATON('192.168.0x8.2'))
+NULL
+SELECT HEX(INET6_ATON('192.168.0x8.2'));
+HEX(INET6_ATON('192.168.0x8.2'))
+NULL
+SELECT HEX(INET_ATON('1.2.255'));
+HEX(INET_ATON('1.2.255'))
+10200FF
+SELECT HEX(INET6_ATON('1.2.255'));
+HEX(INET6_ATON('1.2.255'))
+NULL
+SELECT HEX(INET_ATON('1.2.256'));
+HEX(INET_ATON('1.2.256'))
+NULL
+SELECT HEX(INET6_ATON('1.2.256'));
+HEX(INET6_ATON('1.2.256'))
+NULL
+SELECT HEX(INET_ATON('1.0002.3.4'));
+HEX(INET_ATON('1.0002.3.4'))
+1020304
+SELECT HEX(INET6_ATON('1.0002.3.4'));
+HEX(INET6_ATON('1.0002.3.4'))
+NULL
+SELECT HEX(INET_ATON('1.2.3.4.5'));
+HEX(INET_ATON('1.2.3.4.5'))
+102030405
+SELECT HEX(INET6_ATON('1.2.3.4.5'));
+HEX(INET6_ATON('1.2.3.4.5'))
+NULL
+
+# -- Checking mix of INET- and INET6- functions...
+
+SELECT HEX(INET6_ATON(INET_NTOA(INET_ATON('1.2.3.4')))) AS x;
+x
+01020304
+
+# -- Checking IS_IPV4() / IS_IPV6()...
+
+SELECT IS_IPV4(NULL);
+IS_IPV4(NULL)
+0
+SELECT IS_IPV4(1);
+IS_IPV4(1)
+0
+SELECT IS_IPV4(1.0);
+IS_IPV4(1.0)
+0
+SELECT IS_IPV4('1.2.3.4');
+IS_IPV4('1.2.3.4')
+1
+SELECT IS_IPV4('001.02.000.255');
+IS_IPV4('001.02.000.255')
+1
+SELECT IS_IPV4('::1.2.0.255');
+IS_IPV4('::1.2.0.255')
+0
+SELECT IS_IPV4('::1');
+IS_IPV4('::1')
+0
+SELECT IS_IPV4(BINARY('1.2.3.4'));
+IS_IPV4(BINARY('1.2.3.4'))
+1
+SELECT IS_IPV6(NULL);
+IS_IPV6(NULL)
+0
+SELECT IS_IPV6(1);
+IS_IPV6(1)
+0
+SELECT IS_IPV6(1.0);
+IS_IPV6(1.0)
+0
+SELECT IS_IPV6('1.2.3.4');
+IS_IPV6('1.2.3.4')
+0
+SELECT IS_IPV6('001.02.000.255');
+IS_IPV6('001.02.000.255')
+0
+SELECT IS_IPV6('::001.02.000.255');
+IS_IPV6('::001.02.000.255')
+1
+SELECT IS_IPV6('::1.2.0.255');
+IS_IPV6('::1.2.0.255')
+1
+SELECT IS_IPV6('::1');
+IS_IPV6('::1')
+1
+SELECT IS_IPV6('0000:0000:0000:0000:0000:0000:0000:0001');
+IS_IPV6('0000:0000:0000:0000:0000:0000:0000:0001')
+1
+SELECT IS_IPV6(BINARY('0000:0000:0000:0000:0000:0000:0000:0001'));
+IS_IPV6(BINARY('0000:0000:0000:0000:0000:0000:0000:0001'))
+1
+
+# -- Checking IS_IPV4_MAPPED() and IS_IPV4_COMPAT()...
+
+SELECT IS_IPV4_MAPPED(INET6_ATON('1.2.3.4')),
+IS_IPV4_COMPAT(INET6_ATON('1.2.3.4'));
+IS_IPV4_MAPPED(INET6_ATON('1.2.3.4'))	IS_IPV4_COMPAT(INET6_ATON('1.2.3.4'))
+0	0
+SELECT IS_IPV4_MAPPED(INET6_ATON('::1.2.3.4')),
+IS_IPV4_COMPAT(INET6_ATON('::1.2.3.4'));
+IS_IPV4_MAPPED(INET6_ATON('::1.2.3.4'))	IS_IPV4_COMPAT(INET6_ATON('::1.2.3.4'))
+0	1
+SELECT IS_IPV4_MAPPED(INET6_ATON('::FFFF:1.2.3.4')),
+IS_IPV4_COMPAT(INET6_ATON('::FFFF:1.2.3.4'));
+IS_IPV4_MAPPED(INET6_ATON('::FFFF:1.2.3.4'))	IS_IPV4_COMPAT(INET6_ATON('::FFFF:1.2.3.4'))
+1	0
+SELECT IS_IPV4_MAPPED(INET6_ATON('::ABCD:1.2.3.4')),
+IS_IPV4_COMPAT(INET6_ATON('::ABCD:1.2.3.4'));
+IS_IPV4_MAPPED(INET6_ATON('::ABCD:1.2.3.4'))	IS_IPV4_COMPAT(INET6_ATON('::ABCD:1.2.3.4'))
+0	0
+SELECT IS_IPV4_MAPPED(INET6_ATON('::1')),
+IS_IPV4_COMPAT(INET6_ATON('::1'));
+IS_IPV4_MAPPED(INET6_ATON('::1'))	IS_IPV4_COMPAT(INET6_ATON('::1'))
+0	0
+SELECT IS_IPV4_MAPPED(INET6_ATON('::')),
+IS_IPV4_COMPAT(INET6_ATON('::'));
+IS_IPV4_MAPPED(INET6_ATON('::'))	IS_IPV4_COMPAT(INET6_ATON('::'))
+0	0
+
+# -- Checking IS_IPV4_COMPAT()...
+
+
+# -- Working with a table...
+
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+CREATE TABLE t1(ip INT UNSIGNED);
+CREATE TABLE t2(ip VARBINARY(16));
+
+INSERT INTO t1 VALUES
+(INET_ATON('1.2.3.4')), (INET_ATON('255.255.255.255'));
+SELECT INET_NTOA(ip) FROM t1;
+INET_NTOA(ip)
+1.2.3.4
+255.255.255.255
+
+INSERT INTO t2 SELECT INET6_ATON(INET_NTOA(ip)) FROM t1;
+SELECT INET6_NTOA(ip), HEX(ip), LENGTH(ip) FROM t2;
+INET6_NTOA(ip)	HEX(ip)	LENGTH(ip)
+1.2.3.4	01020304	4
+255.255.255.255	FFFFFFFF	4
+DELETE FROM t2;
+
+INSERT INTO t2 VALUES
+(INET6_ATON('1.2.3.4')), (INET6_ATON('255.255.255.255')),
+(INET6_ATON('::1.2.3.4')), (INET6_ATON('::ffff:255.255.255.255')),
+(INET6_ATON('::')), (INET6_ATON('::1')),
+(INET6_ATON('1020:3040:5060:7080:90A0:B0C0:D0E0:F010'));
+SELECT INET6_NTOA(ip), HEX(ip), LENGTH(ip) FROM t2;
+INET6_NTOA(ip)	HEX(ip)	LENGTH(ip)
+1.2.3.4	01020304	4
+255.255.255.255	FFFFFFFF	4
+::1.2.3.4	00000000000000000000000001020304	16
+::ffff:255.255.255.255	00000000000000000000FFFFFFFFFFFF	16
+::	00000000000000000000000000000000	16
+::1	00000000000000000000000000000001	16
+1020:3040:5060:7080:90a0:b0c0:d0e0:f010	102030405060708090A0B0C0D0E0F010	16
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+# -- Done.
+
 #
 # End of tests
 #

=== modified file 'mysql-test/r/ipv4_as_ipv6.result'
--- a/mysql-test/r/ipv4_as_ipv6.result	2010-10-18 16:20:26 +0000
+++ b/mysql-test/r/ipv4_as_ipv6.result	2011-05-03 13:04:00 +0000
@@ -6,13 +6,6 @@ SHOW GRANTS FOR testuser@'127.0.0.1';
 Grants for testuser@stripped
 GRANT USAGE ON *.* TO 'testuser'@'127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF'
 GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'127.0.0.1'
-SET @nip= inet_aton('127.0.0.1');
-SELECT @nip;
-@nip
-2130706433
-SELECT inet_ntoa(@nip);
-inet_ntoa(@nip)
-127.0.0.1
 SELECT USER();
 USER()
 root@localhost
@@ -27,6 +20,98 @@ SELECT USER();
 USER()
 root@localhost
 DROP USER testuser1@'127.0.0.1';
+SET @nip= inet_aton('127.0.0.1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+inet_ntoa(c1)
+127.0.0.1
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c1 AS UNSIGNED))
+127.0.0.1
+SELECT inet_ntoa(c2) FROM t1;
+inet_ntoa(c2)
+127.0.0.1
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c2 AS UNSIGNED))
+127.0.0.1
+SELECT inet_ntoa(c3) FROM t1;
+inet_ntoa(c3)
+127.0.0.1
+Warnings:
+Warning	1292	Truncated incorrect INTEGER value: '2130706433\x00\x00\x00\x00\x00\x00'
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c3 AS UNSIGNED))
+127.0.0.1
+Warnings:
+Warning	1292	Truncated incorrect INTEGER value: '2130706433\x00\x00\x00\x00\x00\x00'
+SELECT inet_ntoa(c4) FROM t1;
+inet_ntoa(c4)
+127.0.0.1
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c4 AS UNSIGNED))
+127.0.0.1
+SELECT inet_ntoa(c5) FROM t1;
+inet_ntoa(c5)
+127.0.0.1
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c5 AS UNSIGNED))
+127.0.0.1
+SELECT inet_ntoa(c6) FROM t1;
+inet_ntoa(c6)
+127.0.0.1
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+@nip
+2130706433
+SELECT inet_ntoa(@nip);
+inet_ntoa(@nip)
+127.0.0.1
+SET @nip6= inet6_aton('127.0.0.1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+Warnings:
+Warning	1366	Incorrect integer value: '\x7F\x00\x00\x01' for column 'c6' at row 1
+SELECT inet6_ntoa(c1) FROM t1;
+inet6_ntoa(c1)
+127.0.0.1
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c1 AS BINARY(16)))
+7f00:1::
+SELECT inet6_ntoa(c2) FROM t1;
+inet6_ntoa(c2)
+NULL
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c2 AS BINARY(16)))
+7f00:1::
+SELECT inet6_ntoa(c3) FROM t1;
+inet6_ntoa(c3)
+7f00:1::
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c3 AS BINARY(16)))
+7f00:1::
+SELECT inet6_ntoa(c4) FROM t1;
+inet6_ntoa(c4)
+NULL
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c4 AS BINARY(16)))
+7f00:1::
+SELECT inet6_ntoa(c5) FROM t1;
+inet6_ntoa(c5)
+NULL
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c5 AS BINARY(16)))
+7f00:1::
+SELECT inet6_ntoa(c6) FROM t1;
+inet6_ntoa(c6)
+NULL
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c6 AS BINARY(16)))
+3000::
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+inet6_ntoa(@nip6)
+127.0.0.1
 =============Test of '0:0:0:0:0:FFFF:127.0.0.1' ===================
 mysqld is alive
 CREATE USER testuser@'0:0:0:0:0:FFFF:127.0.0.1' identified by '1234';
@@ -35,13 +120,6 @@ SHOW GRANTS FOR testuser@'0:0:0:0:0:FFFF
 Grants for testuser@0:0:0:0:0:ffff:127.0.0.1
 GRANT USAGE ON *.* TO 'testuser'@'0:0:0:0:0:ffff:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF'
 GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0:0:0:0:0:ffff:127.0.0.1'
-SET @nip= inet_aton('0:0:0:0:0:FFFF:127.0.0.1');
-SELECT @nip;
-@nip
-NULL
-SELECT inet_ntoa(@nip);
-inet_ntoa(@nip)
-NULL
 SELECT USER();
 USER()
 root@localhost
@@ -56,6 +134,94 @@ SELECT USER();
 USER()
 root@localhost
 DROP USER testuser1@'0:0:0:0:0:FFFF:127.0.0.1';
+SET @nip= inet_aton('0:0:0:0:0:FFFF:127.0.0.1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+inet_ntoa(c1)
+NULL
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c1 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c2) FROM t1;
+inet_ntoa(c2)
+NULL
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c2 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c3) FROM t1;
+inet_ntoa(c3)
+NULL
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c3 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c4) FROM t1;
+inet_ntoa(c4)
+NULL
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c4 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c5) FROM t1;
+inet_ntoa(c5)
+NULL
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c5 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c6) FROM t1;
+inet_ntoa(c6)
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+@nip
+NULL
+SELECT inet_ntoa(@nip);
+inet_ntoa(@nip)
+NULL
+SET @nip6= inet6_aton('0:0:0:0:0:FFFF:127.0.0.1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+Warnings:
+Warning	1366	Incorrect integer value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x7F\x00\x00\x01' for column 'c6' at row 1
+SELECT inet6_ntoa(c1) FROM t1;
+inet6_ntoa(c1)
+::ffff:127.0.0.1
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c1 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c2) FROM t1;
+inet6_ntoa(c2)
+NULL
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c2 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c3) FROM t1;
+inet6_ntoa(c3)
+::ffff:127.0.0.1
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c3 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c4) FROM t1;
+inet6_ntoa(c4)
+NULL
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c4 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c5) FROM t1;
+inet6_ntoa(c5)
+NULL
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c5 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c6) FROM t1;
+inet6_ntoa(c6)
+NULL
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c6 AS BINARY(16)))
+3000::
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+inet6_ntoa(@nip6)
+::ffff:127.0.0.1
 =============Test of '0000:0000:0000:0000:0000:FFFF:127.0.0.1' ====
 mysqld is alive
 CREATE USER testuser@'0000:0000:0000:0000:0000:FFFF:127.0.0.1' identified by '1234';
@@ -64,13 +230,6 @@ SHOW GRANTS FOR testuser@'0000:0000:0000
 Grants for testuser@0000:0000:0000:0000:0000:ffff:127.0.0.1
 GRANT USAGE ON *.* TO 'testuser'@'0000:0000:0000:0000:0000:ffff:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF'
 GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0000:0000:0000:0000:0000:ffff:127.0.0.1'
-SET @nip= inet_aton('0000:0000:0000:0000:0000:FFFF:127.0.0.1');
-SELECT @nip;
-@nip
-NULL
-SELECT inet_ntoa(@nip);
-inet_ntoa(@nip)
-NULL
 SELECT USER();
 USER()
 root@localhost
@@ -85,6 +244,94 @@ SELECT USER();
 USER()
 root@localhost
 DROP USER testuser1@'0000:0000:0000:0000:0000:FFFF:127.0.0.1';
+SET @nip= inet_aton('0000:0000:0000:0000:0000:FFFF:127.0.0.1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+inet_ntoa(c1)
+NULL
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c1 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c2) FROM t1;
+inet_ntoa(c2)
+NULL
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c2 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c3) FROM t1;
+inet_ntoa(c3)
+NULL
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c3 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c4) FROM t1;
+inet_ntoa(c4)
+NULL
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c4 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c5) FROM t1;
+inet_ntoa(c5)
+NULL
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c5 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c6) FROM t1;
+inet_ntoa(c6)
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+@nip
+NULL
+SELECT inet_ntoa(@nip);
+inet_ntoa(@nip)
+NULL
+SET @nip6= inet6_aton('0000:0000:0000:0000:0000:FFFF:127.0.0.1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+Warnings:
+Warning	1366	Incorrect integer value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x7F\x00\x00\x01' for column 'c6' at row 1
+SELECT inet6_ntoa(c1) FROM t1;
+inet6_ntoa(c1)
+::ffff:127.0.0.1
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c1 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c2) FROM t1;
+inet6_ntoa(c2)
+NULL
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c2 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c3) FROM t1;
+inet6_ntoa(c3)
+::ffff:127.0.0.1
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c3 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c4) FROM t1;
+inet6_ntoa(c4)
+NULL
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c4 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c5) FROM t1;
+inet6_ntoa(c5)
+NULL
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c5 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c6) FROM t1;
+inet6_ntoa(c6)
+NULL
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c6 AS BINARY(16)))
+3000::
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+inet6_ntoa(@nip6)
+::ffff:127.0.0.1
 =============Test of '0:0000:0000:0:0000:FFFF:127.0.0.1' ====
 mysqld is alive
 CREATE USER testuser@'0:0000:0000:0:0000:FFFF:127.0.0.1' identified by '1234';
@@ -93,13 +340,6 @@ SHOW GRANTS FOR testuser@'0:0000:0000:0:
 Grants for testuser@0:0000:0000:0:0000:ffff:127.0.0.1
 GRANT USAGE ON *.* TO 'testuser'@'0:0000:0000:0:0000:ffff:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF'
 GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0:0000:0000:0:0000:ffff:127.0.0.1'
-SET @nip= inet_aton('0:0000:0000:0:0000:FFFF:127.0.0.1');
-SELECT @nip;
-@nip
-NULL
-SELECT inet_ntoa(@nip);
-inet_ntoa(@nip)
-NULL
 SELECT USER();
 USER()
 root@localhost
@@ -114,6 +354,94 @@ SELECT USER();
 USER()
 root@localhost
 DROP USER testuser1@'0:0000:0000:0:0000:FFFF:127.0.0.1';
+SET @nip= inet_aton('0:0000:0000:0:0000:FFFF:127.0.0.1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+inet_ntoa(c1)
+NULL
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c1 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c2) FROM t1;
+inet_ntoa(c2)
+NULL
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c2 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c3) FROM t1;
+inet_ntoa(c3)
+NULL
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c3 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c4) FROM t1;
+inet_ntoa(c4)
+NULL
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c4 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c5) FROM t1;
+inet_ntoa(c5)
+NULL
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c5 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c6) FROM t1;
+inet_ntoa(c6)
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+@nip
+NULL
+SELECT inet_ntoa(@nip);
+inet_ntoa(@nip)
+NULL
+SET @nip6= inet6_aton('0:0000:0000:0:0000:FFFF:127.0.0.1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+Warnings:
+Warning	1366	Incorrect integer value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x7F\x00\x00\x01' for column 'c6' at row 1
+SELECT inet6_ntoa(c1) FROM t1;
+inet6_ntoa(c1)
+::ffff:127.0.0.1
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c1 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c2) FROM t1;
+inet6_ntoa(c2)
+NULL
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c2 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c3) FROM t1;
+inet6_ntoa(c3)
+::ffff:127.0.0.1
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c3 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c4) FROM t1;
+inet6_ntoa(c4)
+NULL
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c4 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c5) FROM t1;
+inet6_ntoa(c5)
+NULL
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c5 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c6) FROM t1;
+inet6_ntoa(c6)
+NULL
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c6 AS BINARY(16)))
+3000::
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+inet6_ntoa(@nip6)
+::ffff:127.0.0.1
 =============Test of '0::0000:FFFF:127.0.0.1' ====
 mysqld is alive
 CREATE USER testuser@'0::0000:FFFF:127.0.0.1' identified by '1234';
@@ -122,13 +450,6 @@ SHOW GRANTS FOR testuser@'0::0000:FFFF:1
 Grants for testuser@0::0000:ffff:127.0.0.1
 GRANT USAGE ON *.* TO 'testuser'@'0::0000:ffff:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF'
 GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0::0000:ffff:127.0.0.1'
-SET @nip= inet_aton('0::0000:FFFF:127.0.0.1');
-SELECT @nip;
-@nip
-NULL
-SELECT inet_ntoa(@nip);
-inet_ntoa(@nip)
-NULL
 SELECT USER();
 USER()
 root@localhost
@@ -143,7 +464,181 @@ SELECT USER();
 USER()
 root@localhost
 DROP USER testuser1@'0::0000:FFFF:127.0.0.1';
+SET @nip= inet_aton('0::0000:FFFF:127.0.0.1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+inet_ntoa(c1)
+NULL
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c1 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c2) FROM t1;
+inet_ntoa(c2)
+NULL
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c2 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c3) FROM t1;
+inet_ntoa(c3)
+NULL
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c3 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c4) FROM t1;
+inet_ntoa(c4)
+NULL
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c4 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c5) FROM t1;
+inet_ntoa(c5)
+NULL
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c5 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c6) FROM t1;
+inet_ntoa(c6)
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+@nip
+NULL
+SELECT inet_ntoa(@nip);
+inet_ntoa(@nip)
+NULL
+SET @nip6= inet6_aton('0::0000:FFFF:127.0.0.1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+Warnings:
+Warning	1366	Incorrect integer value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x7F\x00\x00\x01' for column 'c6' at row 1
+SELECT inet6_ntoa(c1) FROM t1;
+inet6_ntoa(c1)
+::ffff:127.0.0.1
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c1 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c2) FROM t1;
+inet6_ntoa(c2)
+NULL
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c2 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c3) FROM t1;
+inet6_ntoa(c3)
+::ffff:127.0.0.1
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c3 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c4) FROM t1;
+inet6_ntoa(c4)
+NULL
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c4 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c5) FROM t1;
+inet6_ntoa(c5)
+NULL
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c5 AS BINARY(16)))
+::ffff:127.0.0.1
+SELECT inet6_ntoa(c6) FROM t1;
+inet6_ntoa(c6)
+NULL
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c6 AS BINARY(16)))
+3000::
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+inet6_ntoa(@nip6)
+::ffff:127.0.0.1
 =============Test of '0:0:0:0:0:FFFF:127.0.0.1/96' ================
+SET @nip= inet_aton('0:0:0:0:0:FFFF:127.0.0.1/96');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+inet_ntoa(c1)
+NULL
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c1 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c2) FROM t1;
+inet_ntoa(c2)
+NULL
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c2 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c3) FROM t1;
+inet_ntoa(c3)
+NULL
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c3 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c4) FROM t1;
+inet_ntoa(c4)
+NULL
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c4 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c5) FROM t1;
+inet_ntoa(c5)
+NULL
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c5 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c6) FROM t1;
+inet_ntoa(c6)
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+@nip
+NULL
+SELECT inet_ntoa(@nip);
+inet_ntoa(@nip)
+NULL
+SET @nip6= inet6_aton('0:0:0:0:0:FFFF:127.0.0.1/96');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+SELECT inet6_ntoa(c1) FROM t1;
+inet6_ntoa(c1)
+NULL
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c1 AS BINARY(16)))
+NULL
+SELECT inet6_ntoa(c2) FROM t1;
+inet6_ntoa(c2)
+NULL
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c2 AS BINARY(16)))
+NULL
+SELECT inet6_ntoa(c3) FROM t1;
+inet6_ntoa(c3)
+NULL
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c3 AS BINARY(16)))
+NULL
+SELECT inet6_ntoa(c4) FROM t1;
+inet6_ntoa(c4)
+NULL
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c4 AS BINARY(16)))
+NULL
+SELECT inet6_ntoa(c5) FROM t1;
+inet6_ntoa(c5)
+NULL
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c5 AS BINARY(16)))
+NULL
+SELECT inet6_ntoa(c6) FROM t1;
+inet6_ntoa(c6)
+NULL
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c6 AS BINARY(16)))
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+inet6_ntoa(@nip6)
+NULL
 =============Test of '::FFFF:127.0.0.1' ===========================
 mysqld is alive
 CREATE USER testuser@'::FFFF:127.0.0.1' identified by '1234';
@@ -152,13 +647,6 @@ SHOW GRANTS FOR testuser@'::FFFF:127.0.0
 Grants for testuser@::ffff:127.0.0.1
 GRANT USAGE ON *.* TO 'testuser'@'::ffff:127.0.0.1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF'
 GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'::ffff:127.0.0.1'
-SET @nip= inet_aton('::FFFF:127.0.0.1');
-SELECT @nip;
-@nip
-NULL
-SELECT inet_ntoa(@nip);
-inet_ntoa(@nip)
-NULL
 SELECT USER();
 USER()
 root@localhost
@@ -174,6 +662,92 @@ USER()
 root@localhost
 DROP USER testuser1@'::FFFF:127.0.0.1';
 =============Test of '::FFFF:127.0.0.1/96' ========================
+SET @nip= inet_aton('::FFFF:127.0.0.1/96');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+inet_ntoa(c1)
+NULL
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c1 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c2) FROM t1;
+inet_ntoa(c2)
+NULL
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c2 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c3) FROM t1;
+inet_ntoa(c3)
+NULL
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c3 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c4) FROM t1;
+inet_ntoa(c4)
+NULL
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c4 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c5) FROM t1;
+inet_ntoa(c5)
+NULL
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c5 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c6) FROM t1;
+inet_ntoa(c6)
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+@nip
+NULL
+SELECT inet_ntoa(@nip);
+inet_ntoa(@nip)
+NULL
+SET @nip6= inet6_aton('::FFFF:127.0.0.1/96');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+SELECT inet6_ntoa(c1) FROM t1;
+inet6_ntoa(c1)
+NULL
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c1 AS BINARY(16)))
+NULL
+SELECT inet6_ntoa(c2) FROM t1;
+inet6_ntoa(c2)
+NULL
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c2 AS BINARY(16)))
+NULL
+SELECT inet6_ntoa(c3) FROM t1;
+inet6_ntoa(c3)
+NULL
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c3 AS BINARY(16)))
+NULL
+SELECT inet6_ntoa(c4) FROM t1;
+inet6_ntoa(c4)
+NULL
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c4 AS BINARY(16)))
+NULL
+SELECT inet6_ntoa(c5) FROM t1;
+inet6_ntoa(c5)
+NULL
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c5 AS BINARY(16)))
+NULL
+SELECT inet6_ntoa(c6) FROM t1;
+inet6_ntoa(c6)
+NULL
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c6 AS BINARY(16)))
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+inet6_ntoa(@nip6)
+NULL
 =============Test of '::1' ========================
 connect (con1, ::1, root, , test, MASTER_MYPORT,);
 Got one of the listed errors

=== modified file 'mysql-test/r/ipv6.result'
--- a/mysql-test/r/ipv6.result	2010-01-29 10:48:11 +0000
+++ b/mysql-test/r/ipv6.result	2011-05-03 13:04:00 +0000
@@ -6,13 +6,6 @@ SHOW GRANTS FOR testuser@'::1';
 Grants for testuser@::1
 GRANT USAGE ON *.* TO 'testuser'@'::1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF'
 GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'::1'
-SET @nip= inet_aton('::1');
-SELECT @nip;
-@nip
-NULL
-SELECT inet_ntoa(@nip);
-inet_ntoa(@nip)
-NULL
 SELECT USER();
 USER()
 root@localhost
@@ -27,6 +20,94 @@ SELECT USER();
 USER()
 root@localhost
 DROP USER testuser1@'::1';
+SET @nip= inet_aton('::1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+inet_ntoa(c1)
+NULL
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c1 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c2) FROM t1;
+inet_ntoa(c2)
+NULL
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c2 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c3) FROM t1;
+inet_ntoa(c3)
+NULL
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c3 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c4) FROM t1;
+inet_ntoa(c4)
+NULL
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c4 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c5) FROM t1;
+inet_ntoa(c5)
+NULL
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c5 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c6) FROM t1;
+inet_ntoa(c6)
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+@nip
+NULL
+SELECT inet_ntoa(@nip);
+inet_ntoa(@nip)
+NULL
+SET @nip6= inet6_aton('::1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+Warnings:
+Warning	1366	Incorrect integer value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' for column 'c6' at row 1
+SELECT inet6_ntoa(c1) FROM t1;
+inet6_ntoa(c1)
+::1
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c1 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c2) FROM t1;
+inet6_ntoa(c2)
+NULL
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c2 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c3) FROM t1;
+inet6_ntoa(c3)
+::1
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c3 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c4) FROM t1;
+inet6_ntoa(c4)
+NULL
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c4 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c5) FROM t1;
+inet6_ntoa(c5)
+NULL
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c5 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c6) FROM t1;
+inet6_ntoa(c6)
+NULL
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c6 AS BINARY(16)))
+3000::
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+inet6_ntoa(@nip6)
+::1
 =============Test of '::1/128' ====================================
 =============Test of '0000:0000:0000:0000:0000:0000:0000:0001' ====
 mysqld is alive
@@ -36,13 +117,6 @@ SHOW GRANTS FOR testuser@'0000:0000:0000
 Grants for testuser@0000:0000:0000:0000:0000:0000:0000:0001
 GRANT USAGE ON *.* TO 'testuser'@'0000:0000:0000:0000:0000:0000:0000:0001' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF'
 GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0000:0000:0000:0000:0000:0000:0000:0001'
-SET @nip= inet_aton('0000:0000:0000:0000:0000:0000:0000:0001');
-SELECT @nip;
-@nip
-NULL
-SELECT inet_ntoa(@nip);
-inet_ntoa(@nip)
-NULL
 SELECT USER();
 USER()
 root@localhost
@@ -57,6 +131,94 @@ SELECT USER();
 USER()
 root@localhost
 DROP USER testuser1@'0000:0000:0000:0000:0000:0000:0000:0001';
+SET @nip= inet_aton('0000:0000:0000:0000:0000:0000:0000:0001');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+inet_ntoa(c1)
+NULL
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c1 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c2) FROM t1;
+inet_ntoa(c2)
+NULL
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c2 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c3) FROM t1;
+inet_ntoa(c3)
+NULL
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c3 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c4) FROM t1;
+inet_ntoa(c4)
+NULL
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c4 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c5) FROM t1;
+inet_ntoa(c5)
+NULL
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c5 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c6) FROM t1;
+inet_ntoa(c6)
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+@nip
+NULL
+SELECT inet_ntoa(@nip);
+inet_ntoa(@nip)
+NULL
+SET @nip6= inet6_aton('0000:0000:0000:0000:0000:0000:0000:0001');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+Warnings:
+Warning	1366	Incorrect integer value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' for column 'c6' at row 1
+SELECT inet6_ntoa(c1) FROM t1;
+inet6_ntoa(c1)
+::1
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c1 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c2) FROM t1;
+inet6_ntoa(c2)
+NULL
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c2 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c3) FROM t1;
+inet6_ntoa(c3)
+::1
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c3 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c4) FROM t1;
+inet6_ntoa(c4)
+NULL
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c4 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c5) FROM t1;
+inet6_ntoa(c5)
+NULL
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c5 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c6) FROM t1;
+inet6_ntoa(c6)
+NULL
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c6 AS BINARY(16)))
+3000::
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+inet6_ntoa(@nip6)
+::1
 =============Test of '0:0:0:0:0:0:0:1' ============================
 mysqld is alive
 CREATE USER testuser@'0:0:0:0:0:0:0:1' identified by '1234';
@@ -65,13 +227,6 @@ SHOW GRANTS FOR testuser@'0:0:0:0:0:0:0:
 Grants for testuser@0:0:0:0:0:0:0:1
 GRANT USAGE ON *.* TO 'testuser'@'0:0:0:0:0:0:0:1' IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF'
 GRANT ALL PRIVILEGES ON `test`.* TO 'testuser'@'0:0:0:0:0:0:0:1'
-SET @nip= inet_aton('0:0:0:0:0:0:0:1');
-SELECT @nip;
-@nip
-NULL
-SELECT inet_ntoa(@nip);
-inet_ntoa(@nip)
-NULL
 SELECT USER();
 USER()
 root@localhost
@@ -86,3 +241,91 @@ SELECT USER();
 USER()
 root@localhost
 DROP USER testuser1@'0:0:0:0:0:0:0:1';
+SET @nip= inet_aton('0:0:0:0:0:0:0:1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip,@nip,@nip,@nip,@nip,@nip);
+SELECT inet_ntoa(c1) FROM t1;
+inet_ntoa(c1)
+NULL
+SELECT inet_ntoa(CAST(c1 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c1 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c2) FROM t1;
+inet_ntoa(c2)
+NULL
+SELECT inet_ntoa(CAST(c2 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c2 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c3) FROM t1;
+inet_ntoa(c3)
+NULL
+SELECT inet_ntoa(CAST(c3 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c3 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c4) FROM t1;
+inet_ntoa(c4)
+NULL
+SELECT inet_ntoa(CAST(c4 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c4 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c5) FROM t1;
+inet_ntoa(c5)
+NULL
+SELECT inet_ntoa(CAST(c5 AS UNSIGNED)) FROM t1;
+inet_ntoa(CAST(c5 AS UNSIGNED))
+NULL
+SELECT inet_ntoa(c6) FROM t1;
+inet_ntoa(c6)
+NULL
+DROP TABLE IF EXISTS t1;
+SELECT @nip;
+@nip
+NULL
+SELECT inet_ntoa(@nip);
+inet_ntoa(@nip)
+NULL
+SET @nip6= inet6_aton('0:0:0:0:0:0:0:1');
+CREATE TABLE t1 (c1 varbinary(16), c2 varchar(16), c3 binary(16), c4 char(16), c5 long, c6 int);
+INSERT INTO t1 VALUES (@nip6,@nip6,@nip6,@nip6,@nip6,@nip6);
+Warnings:
+Warning	1366	Incorrect integer value: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' for column 'c6' at row 1
+SELECT inet6_ntoa(c1) FROM t1;
+inet6_ntoa(c1)
+::1
+SELECT inet6_ntoa(CAST(c1 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c1 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c2) FROM t1;
+inet6_ntoa(c2)
+NULL
+SELECT inet6_ntoa(CAST(c2 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c2 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c3) FROM t1;
+inet6_ntoa(c3)
+::1
+SELECT inet6_ntoa(CAST(c3 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c3 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c4) FROM t1;
+inet6_ntoa(c4)
+NULL
+SELECT inet6_ntoa(CAST(c4 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c4 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c5) FROM t1;
+inet6_ntoa(c5)
+NULL
+SELECT inet6_ntoa(CAST(c5 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c5 AS BINARY(16)))
+::1
+SELECT inet6_ntoa(c6) FROM t1;
+inet6_ntoa(c6)
+NULL
+SELECT inet6_ntoa(CAST(c6 AS BINARY(16))) FROM t1;
+inet6_ntoa(CAST(c6 AS BINARY(16)))
+3000::
+DROP TABLE IF EXISTS t1;
+SELECT inet6_ntoa(@nip6);
+inet6_ntoa(@nip6)
+::1

=== modified file 'mysql-test/r/partition_myisam.result'
--- a/mysql-test/r/partition_myisam.result	2011-03-31 14:35:51 +0000
+++ b/mysql-test/r/partition_myisam.result	2011-04-29 08:19:16 +0000
@@ -239,3 +239,12 @@ a
 DROP TABLE t1;
 # Should not be any files left here
 # End of bug#30102 test.
+# Test of post-push fix for bug#11766249/59316
+CREATE TABLE t1 (a INT, b VARCHAR(255), PRIMARY KEY (a))
+ENGINE = MyISAM
+PARTITION BY RANGE (a)
+(PARTITION p0 VALUES LESS THAN (0) MAX_ROWS=100,
+PARTITION p1 VALUES LESS THAN (100) MAX_ROWS=100,
+PARTITION pMax VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, "Partition p1, first row");
+DROP TABLE t1;

=== modified file 'mysql-test/suite/perfschema/r/column_privilege.result'
--- a/mysql-test/suite/perfschema/r/column_privilege.result	2011-02-14 14:23:55 +0000
+++ b/mysql-test/suite/perfschema/r/column_privilege.result	2011-04-28 22:01:07 +0000
@@ -24,7 +24,3 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM
 DROP USER 'pfs_user_5'@localhost;
 flush privileges;
 UPDATE performance_schema.setup_instruments SET enabled = 'YES', timed = 'YES';
-UPDATE performance_schema.setup_consumers SET enabled = 'YES';
-UPDATE performance_schema.setup_timers SET timer_name = 'CYCLE' where name="wait_timer";
-UPDATE performance_schema.setup_timers SET timer_name = 'CYCLE' where name="stage_timer";
-UPDATE performance_schema.setup_timers SET timer_name = 'NANOSECONDS' where name="statement_timer";

=== modified file 'mysql-test/suite/perfschema/r/dml_setup_timers.result'
--- a/mysql-test/suite/perfschema/r/dml_setup_timers.result	2011-02-14 14:23:55 +0000
+++ b/mysql-test/suite/perfschema/r/dml_setup_timers.result	2011-04-28 22:01:07 +0000
@@ -1,7 +1,7 @@
 select * from performance_schema.setup_timers;
 NAME	TIMER_NAME
 wait	CYCLE
-stage	CYCLE
+stage	NANOSECOND
 statement	NANOSECOND
 select * from performance_schema.setup_timers
 where name='Wait';
@@ -11,7 +11,6 @@ select * from performance_schema.setup_t
 where timer_name='CYCLE';
 NAME	TIMER_NAME
 wait	CYCLE
-stage	CYCLE
 insert into performance_schema.setup_timers
 set name='FOO', timer_name='CYCLE';
 ERROR 42000: INSERT command denied to user 'root'@'localhost' for table 'setup_timers'
@@ -36,3 +35,14 @@ LOCK TABLES performance_schema.setup_tim
 UNLOCK TABLES;
 LOCK TABLES performance_schema.setup_timers WRITE;
 UNLOCK TABLES;
+update performance_schema.setup_timers
+set timer_name='CYCLE' where name="wait";
+update performance_schema.setup_timers
+set timer_name='NANOSECOND' where name="stage";
+update performance_schema.setup_timers
+set timer_name='NANOSECOND' where name="statement";
+select * from performance_schema.setup_timers;
+NAME	TIMER_NAME
+wait	CYCLE
+stage	NANOSECOND
+statement	NANOSECOND

=== modified file 'mysql-test/suite/perfschema/r/start_server_nothing.result'
--- a/mysql-test/suite/perfschema/r/start_server_nothing.result	2011-02-15 14:31:13 +0000
+++ b/mysql-test/suite/perfschema/r/start_server_nothing.result	2011-04-28 22:01:07 +0000
@@ -131,7 +131,7 @@ thread_instrumentation	YES
 select * from performance_schema.setup_timers;
 NAME	TIMER_NAME
 wait	CYCLE
-stage	CYCLE
+stage	NANOSECOND
 statement	NANOSECOND
 select * from performance_schema.cond_instances;
 NAME	OBJECT_INSTANCE_BEGIN

=== modified file 'mysql-test/suite/perfschema/t/column_privilege.test'
--- a/mysql-test/suite/perfschema/t/column_privilege.test	2011-02-14 14:23:55 +0000
+++ b/mysql-test/suite/perfschema/t/column_privilege.test	2011-04-28 22:01:07 +0000
@@ -73,8 +73,4 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM
 DROP USER 'pfs_user_5'@localhost;
 flush privileges;
 UPDATE performance_schema.setup_instruments SET enabled = 'YES', timed = 'YES';
-UPDATE performance_schema.setup_consumers SET enabled = 'YES';
-UPDATE performance_schema.setup_timers SET timer_name = 'CYCLE' where name="wait_timer";
-UPDATE performance_schema.setup_timers SET timer_name = 'CYCLE' where name="stage_timer";
-UPDATE performance_schema.setup_timers SET timer_name = 'NANOSECONDS' where name="statement_timer";
 

=== modified file 'mysql-test/suite/perfschema/t/dml_setup_timers.test'
--- a/mysql-test/suite/perfschema/t/dml_setup_timers.test	2010-11-08 19:35:17 +0000
+++ b/mysql-test/suite/perfschema/t/dml_setup_timers.test	2011-04-28 22:01:07 +0000
@@ -55,3 +55,14 @@ UNLOCK TABLES;
 LOCK TABLES performance_schema.setup_timers WRITE;
 UNLOCK TABLES;
 
+# Cleanup, restore the default values
+
+update performance_schema.setup_timers
+ set timer_name='CYCLE' where name="wait";
+update performance_schema.setup_timers
+ set timer_name='NANOSECOND' where name="stage";
+update performance_schema.setup_timers
+ set timer_name='NANOSECOND' where name="statement";
+
+select * from performance_schema.setup_timers;
+

=== modified file 'mysql-test/t/func_misc.test'
--- a/mysql-test/t/func_misc.test	2010-12-17 14:02:56 +0000
+++ b/mysql-test/t/func_misc.test	2011-05-03 13:03:00 +0000
@@ -541,6 +541,299 @@ DROP TABLE t1;
 --echo # End of 5.5 tests
 --echo #
 
+--echo
+--echo # --
+--echo # -- WL#5787: IPv6-capable INET_ATON and INET_NTOA functions.
+--echo # --
+
+--echo
+--echo # -- INET6_ATON: checking NULL, invalid types, out-of range values...
+--echo
+
+SELECT INET6_ATON(NULL) IS NULL;
+SELECT INET6_ATON(123) IS NULL;
+SELECT INET6_ATON(123.45) IS NULL;
+SELECT INET6_ATON(NOW()) IS NULL;
+
+SELECT INET6_ATON('1.2.3') IS NULL;
+SELECT INET6_ATON('1.2.3.') IS NULL;
+SELECT INET6_ATON('1..3.4') IS NULL;
+SELECT INET6_ATON('-1.2.3.4') IS NULL;
+SELECT INET6_ATON('1.2.3.256') IS NULL;
+SELECT INET6_ATON('1.2.3.4.5') IS NULL;
+SELECT INET6_ATON('0001.2.3.4') IS NULL;
+SELECT INET6_ATON('0x1.2.3.4') IS NULL;
+SELECT INET6_ATON('a.2.3.4') IS NULL;
+
+SELECT INET6_ATON('1.2.3.4:80') IS NULL;
+SELECT INET6_ATON('1.2.3.4/32') IS NULL;
+
+SELECT INET6_ATON('mysql.com') IS NULL;
+
+SELECT INET6_ATON(':::') IS NULL;
+SELECT INET6_ATON(':1:2:3') IS NULL;
+SELECT INET6_ATON('1:2:3:') IS NULL;
+SELECT INET6_ATON(':1::2:3') IS NULL;
+SELECT INET6_ATON('1::2:3:') IS NULL;
+SELECT INET6_ATON('::00001') IS NULL;
+SELECT INET6_ATON('::00001:2') IS NULL;
+SELECT INET6_ATON('::12345') IS NULL;
+SELECT INET6_ATON('1020::3040::5060') IS NULL;
+SELECT INET6_ATON('::ABCZ') IS NULL;
+
+SELECT INET6_ATON('::0x1.2.3.4') IS NULL;
+SELECT INET6_ATON('::1.0x2.3.4') IS NULL;
+SELECT INET6_ATON('::a.b.c.d') IS NULL;
+
+SELECT INET6_ATON('::FFFF:0x1.2.3.4') IS NULL;
+SELECT INET6_ATON('::FFFF:1.0x2.3.4') IS NULL;
+SELECT INET6_ATON('::FFFF:a.b.c.d') IS NULL;
+
+SELECT INET6_ATON('::1.2.3.4:ABCD') IS NULL;
+
+--echo # NOTE: such addresses are supported because getaddrinfo() supports them.
+--echo # This is just to record the current behaviour.
+SELECT HEX(INET6_ATON('::ABCD:1.2.3.4'));
+
+--echo
+--echo # -- INET6_ATON: checking binary representation...
+--echo
+
+SELECT HEX(INET6_ATON('0.0.0.0'));
+SELECT HEX(INET6_ATON('00.00.00.00'));
+SELECT HEX(INET6_ATON('000.000.000.000'));
+SELECT HEX(INET6_ATON('1.2.3.4'));
+SELECT HEX(INET6_ATON('01.02.03.04'));
+SELECT HEX(INET6_ATON('001.002.003.004'));
+SELECT HEX(INET6_ATON('255.255.255.255'));
+SELECT HEX(INET6_ATON('::'));
+SELECT HEX(INET6_ATON('0::0'));
+SELECT HEX(INET6_ATON('1::2'));
+SELECT HEX(INET6_ATON('0::'));
+SELECT HEX(INET6_ATON('1::'));
+SELECT HEX(INET6_ATON('::0'));
+SELECT HEX(INET6_ATON('::1'));
+SELECT HEX(INET6_ATON('1:2:3:4:5:6:7:8'));
+SELECT HEX(INET6_ATON('::2:3:4:5:6:7:8'));
+SELECT HEX(INET6_ATON('1::3:4:5:6:7:8'));
+SELECT HEX(INET6_ATON('1:2::4:5:6:7:8'));
+SELECT HEX(INET6_ATON('1:2:3::5:6:7:8'));
+SELECT HEX(INET6_ATON('1:2:3:4::6:7:8'));
+SELECT HEX(INET6_ATON('1:2:3:4:5::7:8'));
+SELECT HEX(INET6_ATON('1:2:3:4:5:6::8'));
+SELECT HEX(INET6_ATON('1:2:3:4:5:6:7::'));
+SELECT HEX(INET6_ATON('0000:0000::0000:0001'));
+SELECT HEX(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed'));
+SELECT HEX(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001'));
+SELECT HEX(INET6_ATON('::C0A8:0102'));
+SELECT HEX(INET6_ATON('::c0a8:0102'));
+SELECT HEX(INET6_ATON('::192.168.1.2'));
+SELECT HEX(INET6_ATON('::FfFf:C0a8:0102'));
+SELECT HEX(INET6_ATON('::ffff:c0a8:0102'));
+SELECT HEX(INET6_ATON('::ffff:192.168.1.2'));
+SELECT HEX(INET6_ATON('::01.2.3.4'));
+SELECT HEX(INET6_ATON('::1.02.3.4'));
+SELECT HEX(INET6_ATON('::1.2.03.4'));
+SELECT HEX(INET6_ATON('::1.2.3.04'));
+SELECT HEX(INET6_ATON('::1.2.3.00'));
+SELECT HEX(INET6_ATON('::FFFF:01.2.3.4'));
+SELECT HEX(INET6_ATON('::FFFF:1.02.3.4'));
+SELECT HEX(INET6_ATON('::FFFF:1.2.03.4'));
+SELECT HEX(INET6_ATON('::FFFF:1.2.3.04'));
+SELECT HEX(INET6_ATON('::FFFF:1.2.3.00'));
+
+--echo
+--echo # -- INET6_ATON: checking the length is either 4 or 16...
+--echo
+
+SELECT LENGTH(INET6_ATON('0.0.0.0'));
+SELECT LENGTH(INET6_ATON('255.255.255.255'));
+SELECT LENGTH(INET6_ATON('::'));
+SELECT LENGTH(INET6_ATON('1020:3040:5060:7080:90A0:B0C0:D0E0:F010'));
+
+--echo
+--echo # -- INET6_NTOA: checking NULL, invalid types, out-of range values...
+--echo
+
+SELECT INET6_NTOA(NULL);
+SELECT INET6_NTOA(123);
+SELECT INET6_NTOA(123.456);
+SELECT INET6_NTOA(NOW());
+SELECT INET6_NTOA(UNHEX('C0A801'));     # 3 bytes -> NULL
+SELECT INET6_NTOA(UNHEX('C0A80102'));   # 4 bytes -> 192.168.1.2
+SELECT INET6_NTOA(UNHEX('C0A8010203')); # 5 bytes -> NULL
+SELECT INET6_NTOA(UNHEX('0102030405060708090A0B0C0D0E0F'));     # 15 bytes -> NULL
+SELECT INET6_NTOA(UNHEX('0102030405060708090A0B0C0D0E0F10'));   # 16 bytes -> IP
+SELECT INET6_NTOA(UNHEX('0102030405060708090A0B0C0D0E0F1011')); # 17 bytes -> NULL
+
+SELECT INET6_NTOA('1234'), INET6_NTOA(BINARY('1234'));
+SELECT INET6_NTOA('0123456789abcdef'), INET6_NTOA(BINARY('0123456789abcdef'));
+
+--echo
+--echo # -- Checking double-conversion...
+--echo
+
+SELECT INET6_NTOA(INET6_ATON('::'));
+SELECT INET6_NTOA(INET6_ATON('0::0'));
+SELECT INET6_NTOA(INET6_ATON('1::2'));
+SELECT INET6_NTOA(INET6_ATON('0::'));
+SELECT INET6_NTOA(INET6_ATON('1::'));
+SELECT INET6_NTOA(INET6_ATON('::0'));
+SELECT INET6_NTOA(INET6_ATON('::1'));
+SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5:6:7:8'));
+SELECT INET6_NTOA(INET6_ATON('::2:3:4:5:6:7:8'));
+SELECT INET6_NTOA(INET6_ATON('1::3:4:5:6:7:8'));
+SELECT INET6_NTOA(INET6_ATON('1:2::4:5:6:7:8'));
+SELECT INET6_NTOA(INET6_ATON('1:2:3::5:6:7:8'));
+SELECT INET6_NTOA(INET6_ATON('1:2:3:4::6:7:8'));
+SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5::7:8'));
+SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5:6::8'));
+SELECT INET6_NTOA(INET6_ATON('1:2:3:4:5:6:7::'));
+SELECT INET6_NTOA(INET6_ATON('0000:0000::0000:0001'));
+SELECT INET6_NTOA(INET6_ATON('1234:5678:9abc:def0:4321:8765:cba9:0fed'));
+SELECT INET6_NTOA(INET6_ATON('0000:0000:0000:0000:0000:0000:0000:0001'));
+SELECT INET6_NTOA(INET6_ATON('::C0A8:0102'));
+SELECT INET6_NTOA(INET6_ATON('::c0a8:0102'));
+SELECT INET6_NTOA(INET6_ATON('::192.168.1.2'));
+SELECT INET6_NTOA(INET6_ATON('::FfFf:C0a8:0102'));
+SELECT INET6_NTOA(INET6_ATON('::ffff:c0a8:0102'));
+SELECT INET6_NTOA(INET6_ATON('::ffff:192.168.1.2'));
+SELECT INET6_NTOA(INET6_ATON('::01.2.3.4'));
+SELECT INET6_NTOA(INET6_ATON('::1.02.3.4'));
+SELECT INET6_NTOA(INET6_ATON('::1.2.03.4'));
+SELECT INET6_NTOA(INET6_ATON('::1.2.3.04'));
+SELECT INET6_NTOA(INET6_ATON('::1.2.3.00'));
+SELECT INET6_NTOA(INET6_ATON('::FFFF:01.2.3.4'));
+SELECT INET6_NTOA(INET6_ATON('::FFFF:1.02.3.4'));
+SELECT INET6_NTOA(INET6_ATON('::FFFF:1.2.03.4'));
+SELECT INET6_NTOA(INET6_ATON('::FFFF:1.2.3.04'));
+SELECT INET6_NTOA(INET6_ATON('::FFFF:1.2.3.00'));
+
+--echo
+--echo # -- Comparing INET_ATON() and INET6_ATON()...
+--echo
+
+SELECT HEX(INET_ATON('192.168.1.2'));
+SELECT HEX(INET6_ATON('192.168.1.2'));
+
+SELECT HEX(INET_ATON('255.255.255.255'));
+SELECT HEX(INET6_ATON('255.255.255.255'));
+
+SELECT HEX(INET_ATON('192.168.08.2'));
+SELECT HEX(INET6_ATON('192.168.08.2'));
+
+SELECT HEX(INET_ATON('192.168.0x8.2'));
+SELECT HEX(INET6_ATON('192.168.0x8.2'));
+
+SELECT HEX(INET_ATON('1.2.255'));
+SELECT HEX(INET6_ATON('1.2.255'));
+
+SELECT HEX(INET_ATON('1.2.256'));
+SELECT HEX(INET6_ATON('1.2.256'));
+
+SELECT HEX(INET_ATON('1.0002.3.4'));
+SELECT HEX(INET6_ATON('1.0002.3.4'));
+
+SELECT HEX(INET_ATON('1.2.3.4.5'));
+SELECT HEX(INET6_ATON('1.2.3.4.5'));
+
+--echo
+--echo # -- Checking mix of INET- and INET6- functions...
+--echo
+
+SELECT HEX(INET6_ATON(INET_NTOA(INET_ATON('1.2.3.4')))) AS x;
+
+--echo
+--echo # -- Checking IS_IPV4() / IS_IPV6()...
+--echo
+
+SELECT IS_IPV4(NULL);
+SELECT IS_IPV4(1);
+SELECT IS_IPV4(1.0);
+SELECT IS_IPV4('1.2.3.4');
+SELECT IS_IPV4('001.02.000.255');
+SELECT IS_IPV4('::1.2.0.255');
+SELECT IS_IPV4('::1');
+SELECT IS_IPV4(BINARY('1.2.3.4'));
+
+SELECT IS_IPV6(NULL);
+SELECT IS_IPV6(1);
+SELECT IS_IPV6(1.0);
+SELECT IS_IPV6('1.2.3.4');
+SELECT IS_IPV6('001.02.000.255');
+SELECT IS_IPV6('::001.02.000.255');
+SELECT IS_IPV6('::1.2.0.255');
+SELECT IS_IPV6('::1');
+SELECT IS_IPV6('0000:0000:0000:0000:0000:0000:0000:0001');
+SELECT IS_IPV6(BINARY('0000:0000:0000:0000:0000:0000:0000:0001'));
+
+--echo
+--echo # -- Checking IS_IPV4_MAPPED() and IS_IPV4_COMPAT()...
+--echo
+
+SELECT IS_IPV4_MAPPED(INET6_ATON('1.2.3.4')),
+       IS_IPV4_COMPAT(INET6_ATON('1.2.3.4'));
+SELECT IS_IPV4_MAPPED(INET6_ATON('::1.2.3.4')),
+       IS_IPV4_COMPAT(INET6_ATON('::1.2.3.4'));
+SELECT IS_IPV4_MAPPED(INET6_ATON('::FFFF:1.2.3.4')),
+       IS_IPV4_COMPAT(INET6_ATON('::FFFF:1.2.3.4'));
+SELECT IS_IPV4_MAPPED(INET6_ATON('::ABCD:1.2.3.4')),
+       IS_IPV4_COMPAT(INET6_ATON('::ABCD:1.2.3.4'));
+SELECT IS_IPV4_MAPPED(INET6_ATON('::1')),
+       IS_IPV4_COMPAT(INET6_ATON('::1'));
+SELECT IS_IPV4_MAPPED(INET6_ATON('::')),
+       IS_IPV4_COMPAT(INET6_ATON('::'));
+
+# NOTE: IS_IPV4_COMPAT() / IS_IPV4_MAPPED() could work with "regular strings in
+# binary collation" too, but there is no way to create a "regular string"
+# starting with \0.
+
+--echo
+--echo # -- Checking IS_IPV4_COMPAT()...
+--echo
+
+--echo
+--echo # -- Working with a table...
+--echo
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+--enable_warnings
+
+CREATE TABLE t1(ip INT UNSIGNED);
+CREATE TABLE t2(ip VARBINARY(16));
+
+--echo
+
+INSERT INTO t1 VALUES
+  (INET_ATON('1.2.3.4')), (INET_ATON('255.255.255.255'));
+SELECT INET_NTOA(ip) FROM t1;
+
+--echo
+
+INSERT INTO t2 SELECT INET6_ATON(INET_NTOA(ip)) FROM t1;
+SELECT INET6_NTOA(ip), HEX(ip), LENGTH(ip) FROM t2;
+DELETE FROM t2;
+
+--echo
+
+INSERT INTO t2 VALUES
+  (INET6_ATON('1.2.3.4')), (INET6_ATON('255.255.255.255')),
+  (INET6_ATON('::1.2.3.4')), (INET6_ATON('::ffff:255.255.255.255')),
+  (INET6_ATON('::')), (INET6_ATON('::1')),
+  (INET6_ATON('1020:3040:5060:7080:90A0:B0C0:D0E0:F010'));
+SELECT INET6_NTOA(ip), HEX(ip), LENGTH(ip) FROM t2;
+
+--echo
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+--echo
+--echo # -- Done.
+--echo
+
 --echo #
 --echo # End of tests
 --echo #

=== modified file 'mysql-test/t/ipv4_as_ipv6.test'
--- a/mysql-test/t/ipv4_as_ipv6.test	2010-01-29 10:48:11 +0000
+++ b/mysql-test/t/ipv4_as_ipv6.test	2011-05-03 13:04:00 +0000
@@ -16,31 +16,37 @@ echo =============Test of '127.0.0.1' (I
 let $IPv6= 127.0.0.1;
 --source include/ipv6_clients.inc
 --source include/ipv6.inc
+--source include/ipv6_func.inc
 
 echo =============Test of '0:0:0:0:0:FFFF:127.0.0.1' ===================;
 let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1;
 --source include/ipv6_clients.inc
 --source include/ipv6.inc
+--source include/ipv6_func.inc
 
 echo =============Test of '0000:0000:0000:0000:0000:FFFF:127.0.0.1' ====;
 let $IPv6= 0000:0000:0000:0000:0000:FFFF:127.0.0.1;
 --source include/ipv6_clients.inc
 --source include/ipv6.inc
+--source include/ipv6_func.inc
 
 echo =============Test of '0:0000:0000:0:0000:FFFF:127.0.0.1' ====;
 let $IPv6= 0:0000:0000:0:0000:FFFF:127.0.0.1;
 --source include/ipv6_clients.inc
 --source include/ipv6.inc
+--source include/ipv6_func.inc
 
 echo =============Test of '0::0000:FFFF:127.0.0.1' ====;
 let $IPv6= 0::0000:FFFF:127.0.0.1;
 --source include/ipv6_clients.inc
 --source include/ipv6.inc
+--source include/ipv6_func.inc
 
 echo =============Test of '0:0:0:0:0:FFFF:127.0.0.1/96' ================;
 let $IPv6= 0:0:0:0:0:FFFF:127.0.0.1/96;
 #--source include/ipv6_clients.inc
 #--source include/ipv6.inc
+--source include/ipv6_func.inc
 
 echo =============Test of '::FFFF:127.0.0.1' ===========================;
 let $IPv6= ::FFFF:127.0.0.1;
@@ -51,6 +57,7 @@ echo =============Test of '::FFFF:127.0.
 let $IPv6= ::FFFF:127.0.0.1/96;
 #--source include/ipv6_clients.inc
 #--source include/ipv6.inc
+--source include/ipv6_func.inc
 
 echo =============Test of '::1' ========================;
 let $IPv6= ::1;

=== modified file 'mysql-test/t/ipv6.test'
--- a/mysql-test/t/ipv6.test	2010-01-29 10:48:11 +0000
+++ b/mysql-test/t/ipv6.test	2011-05-03 13:04:00 +0000
@@ -16,6 +16,7 @@ echo =============Test of '::1' ========
 let $IPv6= ::1;
 --source include/ipv6_clients.inc
 --source include/ipv6.inc
+--source include/ipv6_func.inc
 
 echo =============Test of '::1/128' ====================================;
 let $IPv6= ::1/128;
@@ -26,11 +27,13 @@ echo =============Test of '0000:0000:000
 let $IPv6= 0000:0000:0000:0000:0000:0000:0000:0001;
 --source include/ipv6_clients.inc
 --source include/ipv6.inc
+--source include/ipv6_func.inc
 
 echo =============Test of '0:0:0:0:0:0:0:1' ============================;
 let $IPv6= 0:0:0:0:0:0:0:1;
 --source include/ipv6_clients.inc
 --source include/ipv6.inc
+--source include/ipv6_func.inc
 
 # Wait till all disconnects are completed
 --source include/wait_until_count_sessions.inc

=== modified file 'mysql-test/t/partition_myisam.test'
--- a/mysql-test/t/partition_myisam.test	2011-03-31 14:35:51 +0000
+++ b/mysql-test/t/partition_myisam.test	2011-04-29 08:19:16 +0000
@@ -1,5 +1,4 @@
--- source include/have_partition.inc
-
+--source include/have_partition.inc
 --disable_warnings
 DROP TABLE IF EXISTS t1, t2;
 --enable_warnings
@@ -171,3 +170,13 @@ DROP TABLE t1;
 --list_files $MYSQLD_DATADIR/test t1*
 --list_files $MYSQLD_DATADIR/test t2*
 --echo # End of bug#30102 test.
+
+--echo # Test of post-push fix for bug#11766249/59316
+CREATE TABLE t1 (a INT, b VARCHAR(255), PRIMARY KEY (a))
+ENGINE = MyISAM
+PARTITION BY RANGE (a)
+(PARTITION p0 VALUES LESS THAN (0) MAX_ROWS=100,
+ PARTITION p1 VALUES LESS THAN (100) MAX_ROWS=100,
+ PARTITION pMax VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, "Partition p1, first row");
+DROP TABLE t1;

=== modified file 'sql-common/client.c'
--- a/sql-common/client.c	2011-04-15 09:33:58 +0000
+++ b/sql-common/client.c	2011-04-29 21:53:46 +0000
@@ -2318,11 +2318,18 @@ static auth_plugin_t clear_password_clie
   clear_password_auth_client
 };
 
+#ifdef AUTHENTICATION_WIN
+extern auth_plugin_t win_auth_client_plugin;
+#endif
+
 struct st_mysql_client_plugin *mysql_client_builtins[]=
 {
   (struct st_mysql_client_plugin *)&native_password_client_plugin,
   (struct st_mysql_client_plugin *)&old_password_client_plugin,
   (struct st_mysql_client_plugin *)&clear_password_client_plugin,
+#ifdef AUTHENTICATION_WIN
+  (struct st_mysql_client_plugin *)&win_auth_client_plugin,
+#endif
   0
 };
 

=== modified file 'sql-common/client_plugin.c'
--- a/sql-common/client_plugin.c	2011-03-17 14:06:30 +0000
+++ b/sql-common/client_plugin.c	2011-04-29 08:37:43 +0000
@@ -460,7 +460,7 @@ mysql_client_find_plugin(MYSQL *mysql, c
 
 
 /* see <mysql/client_plugin.h> for a full description */
-int STDCALL mysql_plugin_options(struct st_mysql_client_plugin *plugin,
+int mysql_plugin_options(struct st_mysql_client_plugin *plugin,
                                  const char *option,
                                  const void *value)
 {

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2011-04-26 11:30:14 +0000
+++ b/sql/ha_partition.cc	2011-04-29 08:19:16 +0000
@@ -2872,7 +2872,7 @@ int ha_partition::open(const char *name,
                       (PARTITION_ENABLED_TABLE_FLAGS));
   while (*(++file))
   {
-    DBUG_ASSERT(ref_length >= (*file)->ref_length);
+    /* MyISAM can have smaller ref_length for partitions with MAX_ROWS set */
     set_if_bigger(ref_length, ((*file)->ref_length));
     /*
       Verify that all partitions have the same set of table flags.
@@ -4258,20 +4258,17 @@ end_dont_reset_start_part:
 void ha_partition::position(const uchar *record)
 {
   handler *file= m_file[m_last_part];
+  uint pad_length;
   DBUG_ASSERT(bitmap_is_set(&(m_part_info->read_partitions), m_last_part));
   DBUG_ENTER("ha_partition::position");
 
   file->position(record);
   int2store(ref, m_last_part);
-  memcpy((ref + PARTITION_BYTES_IN_POS), file->ref,
-	 (ref_length - PARTITION_BYTES_IN_POS));
+  memcpy((ref + PARTITION_BYTES_IN_POS), file->ref, file->ref_length);
+  pad_length= m_ref_length - PARTITION_BYTES_IN_POS - file->ref_length;
+  if (pad_length)
+    memset((ref + PARTITION_BYTES_IN_POS + file->ref_length), 0, pad_length);
 
-#ifdef SUPPORTING_PARTITION_OVER_DIFFERENT_ENGINES
-#ifdef HAVE_purify
-  bzero(ref + PARTITION_BYTES_IN_POS + ref_length,
-        max_ref_length-ref_length);
-#endif /* HAVE_purify */
-#endif
   DBUG_VOID_RETURN;
 }
 

=== modified file 'sql/item_create.cc'
--- a/sql/item_create.cc	2011-04-15 09:04:21 +0000
+++ b/sql/item_create.cc	2011-05-03 13:03:00 +0000
@@ -1204,6 +1204,84 @@ protected:
 };
 
 
+class Create_func_inet6_aton : public Create_func_arg1
+{
+public:
+  virtual Item *create(THD *thd, Item *arg1);
+
+  static Create_func_inet6_aton s_singleton;
+
+protected:
+  Create_func_inet6_aton() {}
+  virtual ~Create_func_inet6_aton() {}
+};
+
+
+class Create_func_inet6_ntoa : public Create_func_arg1
+{
+public:
+  virtual Item *create(THD *thd, Item *arg1);
+
+  static Create_func_inet6_ntoa s_singleton;
+
+protected:
+  Create_func_inet6_ntoa() {}
+  virtual ~Create_func_inet6_ntoa() {}
+};
+
+
+class Create_func_is_ipv4 : public Create_func_arg1
+{
+public:
+  virtual Item *create(THD *thd, Item *arg1);
+
+  static Create_func_is_ipv4 s_singleton;
+
+protected:
+  Create_func_is_ipv4() {}
+  virtual ~Create_func_is_ipv4() {}
+};
+
+
+class Create_func_is_ipv6 : public Create_func_arg1
+{
+public:
+  virtual Item *create(THD *thd, Item *arg1);
+
+  static Create_func_is_ipv6 s_singleton;
+
+protected:
+  Create_func_is_ipv6() {}
+  virtual ~Create_func_is_ipv6() {}
+};
+
+
+class Create_func_is_ipv4_compat : public Create_func_arg1
+{
+public:
+  virtual Item *create(THD *thd, Item *arg1);
+
+  static Create_func_is_ipv4_compat s_singleton;
+
+protected:
+  Create_func_is_ipv4_compat() {}
+  virtual ~Create_func_is_ipv4_compat() {}
+};
+
+
+class Create_func_is_ipv4_mapped : public Create_func_arg1
+{
+public:
+  virtual Item *create(THD *thd, Item *arg1);
+
+  static Create_func_is_ipv4_mapped s_singleton;
+
+protected:
+  Create_func_is_ipv4_mapped() {}
+  virtual ~Create_func_is_ipv4_mapped() {}
+};
+
+
 class Create_func_instr : public Create_func_arg2
 {
 public:
@@ -3904,6 +3982,24 @@ Create_func_inet_ntoa::create(THD *thd, 
 }
 
 
+Create_func_inet6_aton Create_func_inet6_aton::s_singleton;
+
+Item*
+Create_func_inet6_aton::create(THD *thd, Item *arg1)
+{
+  return new (thd->mem_root) Item_func_inet6_aton(arg1);
+}
+
+
+Create_func_inet6_ntoa Create_func_inet6_ntoa::s_singleton;
+
+Item*
+Create_func_inet6_ntoa::create(THD *thd, Item *arg1)
+{
+  return new (thd->mem_root) Item_func_inet6_ntoa(arg1);
+}
+
+
 Create_func_inet_aton Create_func_inet_aton::s_singleton;
 
 Item*
@@ -3913,6 +4009,42 @@ Create_func_inet_aton::create(THD *thd, 
 }
 
 
+Create_func_is_ipv4 Create_func_is_ipv4::s_singleton;
+
+Item*
+Create_func_is_ipv4::create(THD *thd, Item *arg1)
+{
+  return new (thd->mem_root) Item_func_is_ipv4(arg1);
+}
+
+
+Create_func_is_ipv6 Create_func_is_ipv6::s_singleton;
+
+Item*
+Create_func_is_ipv6::create(THD *thd, Item *arg1)
+{
+  return new (thd->mem_root) Item_func_is_ipv6(arg1);
+}
+
+
+Create_func_is_ipv4_compat Create_func_is_ipv4_compat::s_singleton;
+
+Item*
+Create_func_is_ipv4_compat::create(THD *thd, Item *arg1)
+{
+  return new (thd->mem_root) Item_func_is_ipv4_compat(arg1);
+}
+
+
+Create_func_is_ipv4_mapped Create_func_is_ipv4_mapped::s_singleton;
+
+Item*
+Create_func_is_ipv4_mapped::create(THD *thd, Item *arg1)
+{
+  return new (thd->mem_root) Item_func_is_ipv4_mapped(arg1);
+}
+
+
 Create_func_instr Create_func_instr::s_singleton;
 
 Item*
@@ -5279,6 +5411,12 @@ static Native_func_registry func_array[]
   { { C_STRING_WITH_LEN("IFNULL") }, BUILDER(Create_func_ifnull)},
   { { C_STRING_WITH_LEN("INET_ATON") }, BUILDER(Create_func_inet_aton)},
   { { C_STRING_WITH_LEN("INET_NTOA") }, BUILDER(Create_func_inet_ntoa)},
+  { { C_STRING_WITH_LEN("INET6_ATON") }, BUILDER(Create_func_inet6_aton)},
+  { { C_STRING_WITH_LEN("INET6_NTOA") }, BUILDER(Create_func_inet6_ntoa)},
+  { { C_STRING_WITH_LEN("IS_IPV4") }, BUILDER(Create_func_is_ipv4)},
+  { { C_STRING_WITH_LEN("IS_IPV6") }, BUILDER(Create_func_is_ipv6)},
+  { { C_STRING_WITH_LEN("IS_IPV4_COMPAT") }, BUILDER(Create_func_is_ipv4_compat)},
+  { { C_STRING_WITH_LEN("IS_IPV4_MAPPED") }, BUILDER(Create_func_is_ipv4_mapped)},
   { { C_STRING_WITH_LEN("INSTR") }, BUILDER(Create_func_instr)},
   { { C_STRING_WITH_LEN("INTERIORRINGN") }, GEOM_BUILDER(Create_func_interiorringn)},
   { { C_STRING_WITH_LEN("INTERSECTS") }, GEOM_BUILDER(Create_func_mbr_intersects)},

=== modified file 'sql/item_inetfunc.cc'
--- a/sql/item_inetfunc.cc	2011-04-15 09:42:59 +0000
+++ b/sql/item_inetfunc.cc	2011-05-03 18:06:21 +0000
@@ -19,6 +19,14 @@
 
 ///////////////////////////////////////////////////////////////////////////
 
+static const int IN_ADDR_SIZE= sizeof (in_addr);
+static const int IN6_ADDR_SIZE= sizeof (in6_addr);
+static const int IN6_ADDR_NUM_WORDS= IN6_ADDR_SIZE / 2;
+
+static const char HEX_DIGITS[]= "0123456789abcdef";
+
+///////////////////////////////////////////////////////////////////////////
+
 longlong Item_func_inet_aton::val_int()
 {
   DBUG_ASSERT(fixed);
@@ -131,3 +139,699 @@ String* Item_func_inet_ntoa::val_str(Str
 
   return str;
 }
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Check the function argument, handle errors properly.
+
+  @return The function value.
+*/
+
+longlong Item_func_inet_bool_base::val_int()
+{
+  DBUG_ASSERT(fixed);
+
+  if (args[0]->result_type() != STRING_RESULT ||  // String argument expected
+      args[0]->null_value)                        // Not-NULL argument expected
+    return 0;
+
+  String buffer;
+  String *arg_str= args[0]->val_str(&buffer);
+
+  if (!arg_str) // Out-of memory happened. The error has been reported.
+    return 0;
+
+  return calc_value(arg_str) ? 1 : 0;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Check the function argument, handle errors properly.
+
+  @param [out] buffer Buffer for string operations.
+
+  @return The function value.
+*/
+
+String *Item_func_inet_str_base::val_str_ascii(String *buffer)
+{
+  DBUG_ASSERT(fixed);
+
+  if (args[0]->result_type() != STRING_RESULT ||  // String argument expected
+      args[0]->null_value)                        // Not-NULL argument expected
+  {
+    null_value= true;
+    return NULL;
+  }
+
+  String *arg_str= args[0]->val_str(buffer);
+
+  if (!arg_str) // Out-of memory happened. The error has been reported.
+  {
+    null_value= true;
+    return NULL;
+  }
+
+  null_value= !calc_value(arg_str, buffer);
+
+  return null_value ? NULL : buffer;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Tries to convert given string to binary IPv4-address representation.
+  This is a portable alternative to inet_pton(AF_INET).
+
+  @param      str          String to convert.
+  @param      str_len      String length.
+  @param[out] ipv4_address Buffer to store IPv4-address.
+
+  @return Completion status.
+  @retval false Given string does not represent an IPv4-address.
+  @retval true  The string has been converted sucessfully.
+
+  @note The problem with inet_pton() is that it treats leading zeros in
+  IPv4-part differently on different platforms.
+*/
+
+static bool str_to_ipv4(const char *str, int str_length, in_addr *ipv4_address)
+{
+  if (str_length < 7)
+  {
+    DBUG_PRINT("error", ("str_to_ipv4(%.*s): "
+                         "invalid IPv4 address: too short.",
+                         str_length, str));
+    return false;
+  }
+
+  if (str_length > 15)
+  {
+    DBUG_PRINT("error", ("str_to_ipv4(%.*s): "
+                         "invalid IPv4 address: too long.",
+                         str_length, str));
+    return false;
+  }
+
+  unsigned char *ipv4_bytes= (unsigned char *) ipv4_address;
+  const char *p= str;
+  int byte_value= 0;
+  int chars_in_group= 0;
+  int dot_count= 0;
+  char c= 0;
+
+  while (*p && ((p - str) < str_length))
+  {
+    c= *p++;
+
+    if (my_isdigit(&my_charset_latin1, c))
+    {
+      ++chars_in_group;
+
+      if (chars_in_group > 3)
+      {
+        DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: "
+                             "too many characters in a group.",
+                             str_length, str));
+        return false;
+      }
+
+      byte_value= byte_value * 10 + (c - '0');
+
+      if (byte_value > 255)
+      {
+        DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: "
+                             "invalid byte value.",
+                             str_length, str));
+        return false;
+      }
+    }
+    else if (c == '.')
+    {
+      if (chars_in_group == 0)
+      {
+        DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: "
+                             "too few characters in a group.",
+                             str_length, str));
+        return false;
+      }
+
+      ipv4_bytes[dot_count]= (unsigned char) byte_value;
+
+      ++dot_count;
+      byte_value= 0;
+      chars_in_group= 0;
+
+      if (dot_count > 3)
+      {
+        DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: "
+                             "too many dots.", str_length, str));
+        return false;
+      }
+    }
+    else
+    {
+      DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: "
+                           "invalid character at pos %d.",
+                           str_length, str, (int) (p - str)));
+      return false;
+    }
+  }
+
+  if (c == '.')
+  {
+    DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: "
+                         "ending at '.'.", str_length, str));
+    return false;
+  }
+
+  if (dot_count != 3)
+  {
+    DBUG_PRINT("error", ("str_to_ipv4(%.*s): invalid IPv4 address: "
+                         "classful address (too few groups).",
+                         str_length, str));
+    return false;
+  }
+
+  ipv4_bytes[3]= (unsigned char) byte_value;
+
+  DBUG_PRINT("info", ("str_to_ipv4(%.*s): valid IPv4 address: %d.%d.%d.%d",
+                      str_length, str,
+                      ipv4_bytes[0], ipv4_bytes[1],
+                      ipv4_bytes[2], ipv4_bytes[3]));
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Tries to convert given string to binary IPv6-address representation.
+  This is a portable alternative to inet_pton(AF_INET6).
+
+  @param      str          String to convert.
+  @param      str_len      String length.
+  @param[out] ipv6_address Buffer to store IPv6-address.
+
+  @return Completion status.
+  @retval false Given string does not represent an IPv6-address.
+  @retval true  The string has been converted sucessfully.
+
+  @note The problem with inet_pton() is that it treats leading zeros in
+  IPv4-part differently on different platforms.
+*/
+
+static bool str_to_ipv6(const char *str, int str_length, in6_addr *ipv6_address)
+{
+  if (str_length < 2)
+  {
+    DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: too short.",
+                         str_length, str));
+    return false;
+  }
+
+  if (str_length > 8 * 4 + 7)
+  {
+    DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: too long.",
+                         str_length, str));
+    return false;
+  }
+
+  bzero(ipv6_address, IN6_ADDR_SIZE);
+
+  const char *p= str;
+
+  if (*p == ':')
+  {
+    ++p;
+
+    if (*p != ':')
+    {
+      DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                           "can not start with ':x'.", str_length, str));
+      return false;
+    }
+  }
+
+  char *ipv6_bytes= (char *) ipv6_address;
+  char *ipv6_bytes_end= ipv6_bytes + IN6_ADDR_SIZE;
+  char *dst= ipv6_bytes;
+  char *gap_ptr= NULL;
+  const char *group_start_ptr= p;
+  int chars_in_group= 0;
+  int group_value= 0;
+
+  while (*p && ((p - str) < str_length))
+  {
+    char c= *p++;
+
+    if (c == ':')
+    {
+      group_start_ptr= p;
+
+      if (!chars_in_group)
+      {
+        if (gap_ptr)
+        {
+          DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                               "too many gaps(::).", str_length, str));
+          return false;
+        }
+
+        gap_ptr= dst;
+        continue;
+      }
+
+      if (!*p || ((p - str) >= str_length))
+      {
+        DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                             "ending at ':'.", str_length, str));
+        return false;
+      }
+
+      if (dst + 2 > ipv6_bytes_end)
+      {
+        DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                             "too many groups (1).", str_length, str));
+        return false;
+      }
+
+      dst[0]= (unsigned char) (group_value >> 8) & 0xff;
+      dst[1]= (unsigned char) group_value & 0xff;
+      dst += 2;
+
+      chars_in_group= 0;
+      group_value= 0;
+    }
+    else if (c == '.')
+    {
+      if (dst + IN_ADDR_SIZE > ipv6_bytes_end)
+      {
+        DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                             "unexpected IPv4-part.", str_length, str));
+        return false;
+      }
+
+      if (!str_to_ipv4(group_start_ptr,
+                       str + str_length - group_start_ptr,
+                       (in_addr *) dst))
+      {
+        DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                             "invalid IPv4-part.", str_length, str));
+        return false;
+      }
+
+      dst += IN_ADDR_SIZE;
+      chars_in_group= 0;
+
+      break;
+    }
+    else
+    {
+      const char *hdp= strchr(HEX_DIGITS, my_tolower(&my_charset_latin1, c));
+
+      if (!hdp)
+      {
+        DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                             "invalid character at pos %d.",
+                             str_length, str, (int) (p - str)));
+        return false;
+      }
+
+      if (chars_in_group >= 4)
+      {
+        DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                             "too many digits in group.",
+                             str_length, str));
+        return false;
+      }
+
+      group_value <<= 4;
+      group_value |= hdp - HEX_DIGITS;
+
+      DBUG_ASSERT(group_value <= 0xffff);
+
+      ++chars_in_group;
+    }
+  }
+
+  if (chars_in_group > 0)
+  {
+    if (dst + 2 > ipv6_bytes_end)
+    {
+      DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                           "too many groups (2).", str_length, str));
+      return false;
+    }
+
+    dst[0]= (unsigned char) (group_value >> 8) & 0xff;
+    dst[1]= (unsigned char) group_value & 0xff;
+    dst += 2;
+  }
+
+  if (gap_ptr)
+  {
+    if (dst == ipv6_bytes_end)
+    {
+      DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                           "no room for a gap (::).", str_length, str));
+      return false;
+    }
+
+    int bytes_to_move= dst - gap_ptr;
+
+    for (int i= 1; i <= bytes_to_move; ++i)
+    {
+      ipv6_bytes_end[-i]= gap_ptr[bytes_to_move - i];
+      gap_ptr[bytes_to_move - i]= 0;
+    }
+
+    dst= ipv6_bytes_end;
+  }
+
+  if (dst < ipv6_bytes_end)
+  {
+    DBUG_PRINT("error", ("str_to_ipv6(%.*s): invalid IPv6 address: "
+                         "too few groups.", str_length, str));
+    return false;
+  }
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Converts IPv4-binary-address to a string. This function is a portable
+  alternative to inet_ntop(AF_INET).
+
+  @param[in] ipv4 IPv4-address data (byte array)
+  @param[out] str A buffer to store string representation of IPv4-address.
+                  It must be at least of INET_ADDRSTRLEN.
+
+  @note The problem with inet_ntop() is that it is available starting from
+  Windows Vista, but out the minimum supported version is Windows 2000.
+*/
+
+static void ipv4_to_str(const in_addr *ipv4, char *str)
+{
+  const unsigned char *ipv4_bytes= (const unsigned char *) ipv4;
+
+  sprintf(str, "%d.%d.%d.%d",
+          ipv4_bytes[0], ipv4_bytes[1], ipv4_bytes[2], ipv4_bytes[3]);
+}
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Converts IPv6-binary-address to a string. This function is a portable
+  alternative to inet_ntop(AF_INET6).
+
+  @param[in] ipv6 IPv6-address data (byte array)
+  @param[out] str A buffer to store string representation of IPv6-address.
+                  It must be at least of INET6_ADDRSTRLEN.
+
+  @note The problem with inet_ntop() is that it is available starting from
+  Windows Vista, but out the minimum supported version is Windows 2000.
+*/
+
+static void ipv6_to_str(const in6_addr *ipv6, char *str)
+{
+  struct Region
+  {
+    int pos;
+    int length;
+  };
+
+  const unsigned char *ipv6_bytes= (const unsigned char *) ipv6;
+
+  // 1. Translate IPv6-address bytes to words.
+  // We can't just cast to short, because it's not guaranteed
+  // that sizeof (short) == 2. So, we have to make a copy.
+
+  uint16 ipv6_words[IN6_ADDR_NUM_WORDS];
+
+  for (int i= 0; i < IN6_ADDR_NUM_WORDS; ++i)
+    ipv6_words[i]= (ipv6_bytes[2 * i] << 8) + ipv6_bytes[2 * i + 1];
+
+  // 2. Find "the gap" -- longest sequence of zeros in IPv6-address.
+
+  Region gap= { -1, -1 };
+
+  {
+    Region rg= { -1, -1 };
+
+    for (int i = 0; i < IN6_ADDR_NUM_WORDS; ++i)
+    {
+      if (ipv6_words[i] != 0)
+      {
+        if (rg.pos >= 0)
+        {
+          if (rg.length > gap.length)
+            gap= rg;
+
+          rg.pos= -1;
+          rg.length= -1;
+        }
+      }
+      else
+      {
+        if (rg.pos >= 0)
+        {
+          ++rg.length;
+        }
+        else
+        {
+          rg.pos= i;
+          rg.length= 1;
+        }
+      }
+    }
+
+    if (rg.pos >= 0)
+    {
+      if (rg.length > gap.length)
+        gap= rg;
+    }
+  }
+
+  // 3. Convert binary data to string.
+
+  char *p= str;
+
+  for (int i = 0; i < IN6_ADDR_NUM_WORDS; ++i)
+  {
+    if (i == gap.pos)
+    {
+      // We're at the gap position. We should put trailing ':' and jump to
+      // the end of the gap.
+
+      if (i == 0)
+      {
+        // The gap starts from the beginning of the data -- leading ':'
+        // should be put additionally.
+
+        *p= ':';
+        ++p;
+      }
+
+      *p= ':';
+      ++p;
+
+      i += gap.length - 1;
+    }
+    else if (i == 6 && gap.pos == 0 &&
+             (gap.length == 6 ||                           // IPv4-compatible
+              (gap.length == 5 && ipv6_words[5] == 0xffff) // IPv4-mapped
+             ))
+    {
+      // The data represents either IPv4-compatible or IPv4-mapped address.
+      // The IPv6-part (zeros or zeros + ffff) has been already put into
+      // the string (str). Now it's time to dump IPv4-part.
+
+      ipv4_to_str((const in_addr *) (ipv6_bytes + 12), p);
+      return;
+    }
+    else
+    {
+      // Usual IPv6-address-field. Print it out using lower-case
+      // hex-letters without leading zeros (recommended IPv6-format).
+      //
+      // If it is not the last field, append closing ':'.
+
+      p += sprintf(p, "%x", ipv6_words[i]);
+
+      if (i != IN6_ADDR_NUM_WORDS - 1)
+      {
+        *p= ':';
+        ++p;
+      }
+    }
+  }
+
+  *p= 0;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Converts IP-address-string to IP-address-data.
+
+  @param       arg    IP-address-string.
+  @param [out] buffer Buffer to store IP-address-data.
+
+  @return Completion status.
+  @retval false Given string does not represent an IP-address.
+  @retval true  The string has been converted sucessfully.
+*/
+
+bool Item_func_inet6_aton::calc_value(String *arg, String *buffer)
+{
+  // ipv4-string -> varbinary(4)
+  // ipv6-string -> varbinary(16)
+
+  in_addr ipv4_address;
+  in6_addr ipv6_address;
+
+  if (str_to_ipv4(arg->ptr(), arg->length(), &ipv4_address))
+  {
+    buffer->length(0);
+    buffer->append((char *) &ipv4_address, sizeof (in_addr), &my_charset_bin);
+
+    return true;
+  }
+
+  if (str_to_ipv6(arg->ptr(), arg->length(), &ipv6_address))
+  {
+    buffer->length(0);
+    buffer->append((char *) &ipv6_address, sizeof (in6_addr), &my_charset_bin);
+
+    return true;
+  }
+
+  return false;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Converts IP-address-data to IP-address-string.
+
+  @param       arg    IP-address-data.
+  @param [out] buffer Buffer to store IP-address-string.
+
+  @return Completion status.
+  @retval false The argument does not correspond to IP-address.
+  @retval true  The string has been converted sucessfully.
+*/
+
+bool Item_func_inet6_ntoa::calc_value(String *arg, String *buffer)
+{
+  if (arg->charset() != &my_charset_bin)
+    return false;
+
+  if ((int) arg->length() == IN_ADDR_SIZE)
+  {
+    char str[INET_ADDRSTRLEN];
+
+    ipv4_to_str((const in_addr *) arg->ptr(), str);
+
+    buffer->length(0);
+    buffer->append(str, (uint32) strlen(str), &my_charset_latin1);
+
+    return true;
+  }
+  else if ((int) arg->length() == IN6_ADDR_SIZE)
+  {
+    char str[INET6_ADDRSTRLEN];
+
+    ipv6_to_str((const in6_addr *) arg->ptr(), str);
+
+    buffer->length(0);
+    buffer->append(str, (uint32) strlen(str), &my_charset_latin1);
+
+    return true;
+  }
+
+  DBUG_PRINT("info",
+             ("INET6_NTOA(): varbinary(4) or varbinary(16) expected."));
+  return false;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Checks if the passed string represents an IPv4-address.
+
+  @param arg The string to check.
+
+  @return Check status.
+  @retval false The passed string does not represent an IPv4-address.
+  @retval true  The passed string represents an IPv4-address.
+*/
+
+bool Item_func_is_ipv4::calc_value(const String *arg)
+{
+  in_addr ipv4_address;
+
+  return str_to_ipv4(arg->ptr(), arg->length(), &ipv4_address);
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Checks if the passed string represents an IPv6-address.
+
+  @param arg The string to check.
+
+  @return Check status.
+  @retval false The passed string does not represent an IPv6-address.
+  @retval true  The passed string represents an IPv6-address.
+*/
+
+bool Item_func_is_ipv6::calc_value(const String *arg)
+{
+  in6_addr ipv6_address;
+
+  return str_to_ipv6(arg->ptr(), arg->length(), &ipv6_address);
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Checks if the passed IPv6-address is an IPv4-compat IPv6-address.
+
+  @param arg The IPv6-address to check.
+
+  @return Check status.
+  @retval false The passed IPv6-address is not an IPv4-compatible IPv6-address.
+  @retval true  The passed IPv6-address is an IPv4-compatible IPv6-address.
+*/
+
+bool Item_func_is_ipv4_compat::calc_value(const String *arg)
+{
+  if ((int) arg->length() != IN6_ADDR_SIZE || arg->charset() != &my_charset_bin)
+    return false;
+
+  return IN6_IS_ADDR_V4COMPAT((struct in6_addr *) arg->ptr());
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Checks if the passed IPv6-address is an IPv4-mapped IPv6-address.
+
+  @param arg The IPv6-address to check.
+
+  @return Check status.
+  @retval false The passed IPv6-address is not an IPv4-mapped IPv6-address.
+  @retval true  The passed IPv6-address is an IPv4-mapped IPv6-address.
+*/
+
+bool Item_func_is_ipv4_mapped::calc_value(const String *arg)
+{
+  if ((int) arg->length() != IN6_ADDR_SIZE || arg->charset() != &my_charset_bin)
+    return false;
+
+  return IN6_IS_ADDR_V4MAPPED((struct in6_addr *) arg->ptr());
+}

=== modified file 'sql/item_inetfunc.h'
--- a/sql/item_inetfunc.h	2011-04-15 09:39:46 +0000
+++ b/sql/item_inetfunc.h	2011-05-03 13:03:00 +0000
@@ -71,4 +71,185 @@ public:
   }
 };
 
+
+/*************************************************************************
+  Item_func_inet_bool_base implements common code for INET6/IP-related
+  functions returning boolean value.
+*************************************************************************/
+
+class Item_func_inet_bool_base : public Item_bool_func
+{
+public:
+  inline Item_func_inet_bool_base(Item *ip_addr)
+    : Item_bool_func(ip_addr)
+  {
+    null_value= false;
+  }
+
+public:
+  virtual longlong val_int();
+
+protected:
+  virtual bool calc_value(const String *arg) = 0;
+};
+
+
+/*************************************************************************
+  Item_func_inet_bool_base implements common code for INET6/IP-related
+  functions returning string value.
+*************************************************************************/
+
+class Item_func_inet_str_base : public Item_str_ascii_func
+{
+public:
+  inline Item_func_inet_str_base(Item *arg)
+    : Item_str_ascii_func(arg)
+  { }
+
+public:
+  virtual String *val_str_ascii(String *buffer);
+
+protected:
+  virtual bool calc_value(String *arg, String *buffer) = 0;
+};
+
+
+/*************************************************************************
+  Item_func_inet6_aton implements INET6_ATON() SQL-function.
+*************************************************************************/
+
+class Item_func_inet6_aton : public Item_func_inet_str_base
+{
+public:
+  inline Item_func_inet6_aton(Item *ip_addr)
+    : Item_func_inet_str_base(ip_addr)
+  { }
+
+public:
+  virtual const char *func_name() const
+  { return "inet6_aton"; }
+
+  virtual void fix_length_and_dec()
+  {
+    decimals= 0;
+    fix_length_and_charset(16, &my_charset_bin);
+    maybe_null= 1;
+  }
+
+protected:
+  virtual bool calc_value(String *arg, String *buffer);
+};
+
+
+/*************************************************************************
+  Item_func_inet6_ntoa implements INET6_NTOA() SQL-function.
+*************************************************************************/
+
+class Item_func_inet6_ntoa : public Item_func_inet_str_base
+{
+public:
+  inline Item_func_inet6_ntoa(Item *ip_addr)
+    : Item_func_inet_str_base(ip_addr)
+  { }
+
+public:
+  virtual const char *func_name() const
+  { return "inet6_ntoa"; }
+
+  virtual void fix_length_and_dec()
+  {
+    decimals= 0;
+
+    // max length: IPv6-address -- 16 bytes
+    // 16 bytes / 2 bytes per group == 8 groups => 7 delimiter
+    // 4 symbols per group
+    fix_length_and_charset(8 * 4 + 7, default_charset());
+
+    maybe_null= 1;
+  }
+
+protected:
+  virtual bool calc_value(String *arg, String *buffer);
+};
+
+
+/*************************************************************************
+  Item_func_is_ipv4 implements IS_IPV4() SQL-function.
+*************************************************************************/
+
+class Item_func_is_ipv4 : public Item_func_inet_bool_base
+{
+public:
+  inline Item_func_is_ipv4(Item *ip_addr)
+    : Item_func_inet_bool_base(ip_addr)
+  { }
+
+public:
+  virtual const char *func_name() const
+  { return "is_ipv4"; }
+
+protected:
+  virtual bool calc_value(const String *arg);
+};
+
+
+/*************************************************************************
+  Item_func_is_ipv6 implements IS_IPV6() SQL-function.
+*************************************************************************/
+
+class Item_func_is_ipv6 : public Item_func_inet_bool_base
+{
+public:
+  inline Item_func_is_ipv6(Item *ip_addr)
+    : Item_func_inet_bool_base(ip_addr)
+  { }
+
+public:
+  virtual const char *func_name() const
+  { return "is_ipv6"; }
+
+protected:
+  virtual bool calc_value(const String *arg);
+};
+
+
+/*************************************************************************
+  Item_func_is_ipv4_compat implements IS_IPV4_COMPAT() SQL-function.
+*************************************************************************/
+
+class Item_func_is_ipv4_compat : public Item_func_inet_bool_base
+{
+public:
+  inline Item_func_is_ipv4_compat(Item *ip_addr)
+    : Item_func_inet_bool_base(ip_addr)
+  { }
+
+public:
+  virtual const char *func_name() const
+  { return "is_ipv4_compat"; }
+
+protected:
+  virtual bool calc_value(const String *arg);
+};
+
+
+/*************************************************************************
+  Item_func_is_ipv4_mapped implements IS_IPV4_MAPPED() SQL-function.
+*************************************************************************/
+
+class Item_func_is_ipv4_mapped : public Item_func_inet_bool_base
+{
+public:
+  inline Item_func_is_ipv4_mapped(Item *ip_addr)
+    : Item_func_inet_bool_base(ip_addr)
+  { }
+
+public:
+  virtual const char *func_name() const
+  { return "is_ipv4_mapped"; }
+
+protected:
+  virtual bool calc_value(const String *arg);
+};
+
 #endif // ITEM_INETFUNC_INCLUDED

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2011-04-19 03:29:06 +0000
+++ b/sql/mysqld.cc	2011-04-28 16:50:10 +0000
@@ -8126,7 +8126,9 @@ PSI_mutex_key key_BINLOG_LOCK_index, key
   key_LOCK_system_variables_hash, key_LOCK_table_share, key_LOCK_thd_data,
   key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log,
   key_master_info_data_lock, key_master_info_run_lock,
+  key_master_info_sleep_lock,
   key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
+  key_relay_log_info_sleep_lock,
   key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
   key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
   key_LOCK_error_messages, key_LOG_INFO_lock, key_LOCK_thread_count,
@@ -8172,8 +8174,10 @@ static PSI_mutex_info all_server_mutexes
   { &key_LOG_LOCK_log, "LOG::LOCK_log", 0},
   { &key_master_info_data_lock, "Master_info::data_lock", 0},
   { &key_master_info_run_lock, "Master_info::run_lock", 0},
+  { &key_master_info_sleep_lock, "Master_info::sleep_lock", 0},
   { &key_mutex_slave_reporting_capability_err_lock, "Slave_reporting_capability::err_lock", 0},
   { &key_relay_log_info_data_lock, "Relay_log_info::data_lock", 0},
+  { &key_relay_log_info_sleep_lock, "Relay_log_info::sleep_lock", 0},
   { &key_relay_log_info_log_space_lock, "Relay_log_info::log_space_lock", 0},
   { &key_relay_log_info_run_lock, "Relay_log_info::run_lock", 0},
   { &key_structure_guard_mutex, "Query_cache::structure_guard_mutex", 0},
@@ -8211,8 +8215,10 @@ PSI_cond_key key_BINLOG_COND_prep_xids, 
   key_delayed_insert_cond, key_delayed_insert_cond_client,
   key_item_func_sleep_cond, key_master_info_data_cond,
   key_master_info_start_cond, key_master_info_stop_cond,
+  key_master_info_sleep_cond,
   key_relay_log_info_data_cond, key_relay_log_info_log_space_cond,
   key_relay_log_info_start_cond, key_relay_log_info_stop_cond,
+  key_relay_log_info_sleep_cond,
   key_TABLE_SHARE_cond, key_user_level_lock_cond,
   key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache;
 PSI_cond_key key_RELAYLOG_update_cond;
@@ -8239,10 +8245,12 @@ static PSI_cond_info all_server_conds[]=
   { &key_master_info_data_cond, "Master_info::data_cond", 0},
   { &key_master_info_start_cond, "Master_info::start_cond", 0},
   { &key_master_info_stop_cond, "Master_info::stop_cond", 0},
+  { &key_master_info_sleep_cond, "Master_info::sleep_cond", 0},
   { &key_relay_log_info_data_cond, "Relay_log_info::data_cond", 0},
   { &key_relay_log_info_log_space_cond, "Relay_log_info::log_space_cond", 0},
   { &key_relay_log_info_start_cond, "Relay_log_info::start_cond", 0},
   { &key_relay_log_info_stop_cond, "Relay_log_info::stop_cond", 0},
+  { &key_relay_log_info_sleep_cond, "Relay_log_info::sleep_cond", 0},
   { &key_TABLE_SHARE_cond, "TABLE_SHARE::cond", 0},
   { &key_user_level_lock_cond, "User_level_lock::cond", 0},
   { &key_COND_thread_count, "COND_thread_count", PSI_FLAG_GLOBAL},

=== modified file 'sql/mysqld.h'
--- a/sql/mysqld.h	2011-04-22 07:02:59 +0000
+++ b/sql/mysqld.h	2011-04-28 16:50:10 +0000
@@ -254,7 +254,9 @@ extern PSI_mutex_key key_BINLOG_LOCK_ind
   key_LOCK_table_share, key_LOCK_thd_data,
   key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log,
   key_master_info_data_lock, key_master_info_run_lock,
+  key_master_info_sleep_lock,
   key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
+  key_relay_log_info_sleep_lock,
   key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
   key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
   key_LOCK_error_messages, key_LOCK_thread_count, key_PARTITION_LOCK_auto_inc;
@@ -274,8 +276,10 @@ extern PSI_cond_key key_BINLOG_COND_prep
   key_delayed_insert_cond, key_delayed_insert_cond_client,
   key_item_func_sleep_cond, key_master_info_data_cond,
   key_master_info_start_cond, key_master_info_stop_cond,
+  key_master_info_sleep_cond,
   key_relay_log_info_data_cond, key_relay_log_info_log_space_cond,
   key_relay_log_info_start_cond, key_relay_log_info_stop_cond,
+  key_relay_log_info_sleep_cond,
   key_TABLE_SHARE_cond, key_user_level_lock_cond,
   key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache;
 extern PSI_cond_key key_RELAYLOG_update_cond;

=== modified file 'sql/rpl_info.cc'
--- a/sql/rpl_info.cc	2011-03-23 23:28:49 +0000
+++ b/sql/rpl_info.cc	2011-04-28 16:50:10 +0000
@@ -21,18 +21,22 @@ Rpl_info::Rpl_info(const char* type
 #ifdef HAVE_PSI_INTERFACE
                    ,PSI_mutex_key *param_key_info_run_lock,
                    PSI_mutex_key *param_key_info_data_lock,
+                   PSI_mutex_key *param_key_info_sleep_lock,
                    PSI_mutex_key *param_key_info_data_cond,
                    PSI_mutex_key *param_key_info_start_cond,
-                   PSI_mutex_key *param_key_info_stop_cond
+                   PSI_mutex_key *param_key_info_stop_cond,
+                   PSI_mutex_key *param_key_info_sleep_cond
 #endif
                  )
   :Slave_reporting_capability(type),
 #ifdef HAVE_PSI_INTERFACE
   key_info_run_lock(param_key_info_run_lock),
   key_info_data_lock(param_key_info_data_lock),
+  key_info_sleep_lock(param_key_info_sleep_lock),
   key_info_data_cond(param_key_info_data_cond),
   key_info_start_cond(param_key_info_start_cond),
   key_info_stop_cond(param_key_info_stop_cond),
+  key_info_sleep_cond(param_key_info_sleep_cond),
 #endif
   info_thd(0), inited(0), abort_slave(0),
   slave_running(0), slave_run_id(0),
@@ -43,15 +47,20 @@ Rpl_info::Rpl_info(const char* type
                     &run_lock, MY_MUTEX_INIT_FAST);
   mysql_mutex_init(*key_info_data_lock,
                    &data_lock, MY_MUTEX_INIT_FAST);
+  mysql_mutex_init(*key_info_sleep_lock,
+                    &sleep_lock, MY_MUTEX_INIT_FAST);
   mysql_cond_init(*key_info_data_cond, &data_cond, NULL);
   mysql_cond_init(*key_info_start_cond, &start_cond, NULL);
   mysql_cond_init(*key_info_stop_cond, &stop_cond, NULL);
+  mysql_cond_init(*key_info_sleep_cond, &sleep_cond, NULL);
 #else
   mysql_mutex_init(NULL, &run_lock, MY_MUTEX_INIT_FAST);
   mysql_mutex_init(NULL, &data_lock, MY_MUTEX_INIT_FAST);
+  mysql_mutex_init(NULL, &sleep_lock, MY_MUTEX_INIT_FAST);
   mysql_cond_init(NULL, &data_cond, NULL);
   mysql_cond_init(NULL, &start_cond, NULL);
   mysql_cond_init(NULL, &stop_cond, NULL);
+  mysql_cond_init(NULL, &sleep_cond, NULL);
 #endif
 }
 

=== modified file 'sql/rpl_info.h'
--- a/sql/rpl_info.h	2011-03-23 23:28:49 +0000
+++ b/sql/rpl_info.h	2011-04-28 16:50:10 +0000
@@ -36,19 +36,22 @@ public:
   /*
     standard lock acquisition order to avoid deadlocks:
     run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index
+    run_lock, sleep_lock
   */
-  mysql_mutex_t data_lock,run_lock;
+  mysql_mutex_t data_lock, run_lock, sleep_lock;
   /*
     start_cond is broadcast when SQL thread is started
-    stop_cond - when stopped
-    data_cond - when data protected by data_lock changes
+    stop_cond  - when stopped
+    data_cond  - when data protected by data_lock changes
+    sleep_cond - when killed
   */
-  mysql_cond_t data_cond,start_cond, stop_cond;
+  mysql_cond_t data_cond, start_cond, stop_cond, sleep_cond;
 
 #ifdef HAVE_PSI_INTERFACE
-  PSI_mutex_key *key_info_run_lock, *key_info_data_lock;
+  PSI_mutex_key *key_info_run_lock, *key_info_data_lock, *key_info_sleep_lock;
 
-  PSI_mutex_key *key_info_data_cond, *key_info_start_cond, *key_info_stop_cond;
+  PSI_mutex_key *key_info_data_cond, *key_info_start_cond, *key_info_stop_cond,
+                *key_info_sleep_cond;
 #endif
 
   THD *info_thd;
@@ -144,9 +147,11 @@ protected:
 #ifdef HAVE_PSI_INTERFACE
            ,PSI_mutex_key *param_key_info_run_lock,
            PSI_mutex_key *param_key_info_data_lock,
+           PSI_mutex_key *param_key_info_sleep_lock,
            PSI_mutex_key *param_key_info_data_cond,
            PSI_mutex_key *param_key_info_start_cond,
-           PSI_mutex_key *param_key_info_stop_cond
+           PSI_mutex_key *param_key_info_stop_cond,
+           PSI_mutex_key *param_key_info_sleep_cond
 #endif
           );
 

=== modified file 'sql/rpl_info_factory.cc'
--- a/sql/rpl_info_factory.cc	2011-04-05 15:51:15 +0000
+++ b/sql/rpl_info_factory.cc	2011-04-28 16:50:10 +0000
@@ -84,9 +84,11 @@ Master_info *Rpl_info_factory::create_mi
 #ifdef HAVE_PSI_INTERFACE
                             &key_master_info_run_lock,
                             &key_master_info_data_lock,
+                            &key_master_info_sleep_lock,
                             &key_master_info_data_cond,
                             &key_master_info_start_cond,
-                            &key_master_info_stop_cond
+                            &key_master_info_stop_cond,
+                            &key_master_info_sleep_cond
 #endif
                            )))
     goto err;
@@ -183,9 +185,11 @@ Relay_log_info *Rpl_info_factory::create
 #ifdef HAVE_PSI_INTERFACE
                                 ,&key_relay_log_info_run_lock,
                                 &key_relay_log_info_data_lock,
+                                &key_relay_log_info_sleep_lock,
                                 &key_relay_log_info_data_cond,
                                 &key_relay_log_info_start_cond,
-                                &key_relay_log_info_stop_cond
+                                &key_relay_log_info_stop_cond,
+                                &key_relay_log_info_sleep_cond
 #endif
                                )))
     goto err;

=== modified file 'sql/rpl_mi.cc'
--- a/sql/rpl_mi.cc	2011-04-04 09:42:22 +0000
+++ b/sql/rpl_mi.cc	2011-04-28 16:50:10 +0000
@@ -80,16 +80,19 @@ Master_info::Master_info(
 #ifdef HAVE_PSI_INTERFACE
                          PSI_mutex_key *param_key_info_run_lock,
                          PSI_mutex_key *param_key_info_data_lock,
+                         PSI_mutex_key *param_key_info_sleep_lock,
                          PSI_mutex_key *param_key_info_data_cond,
                          PSI_mutex_key *param_key_info_start_cond,
-                         PSI_mutex_key *param_key_info_stop_cond
+                         PSI_mutex_key *param_key_info_stop_cond,
+                         PSI_mutex_key *param_key_info_sleep_cond
 #endif
                         )
    :Rpl_info("I/O"
 #ifdef HAVE_PSI_INTERFACE
              ,param_key_info_run_lock, param_key_info_data_lock,
+             param_key_info_sleep_lock,
              param_key_info_data_cond, param_key_info_start_cond,
-             param_key_info_stop_cond
+             param_key_info_stop_cond, param_key_info_sleep_cond
 #endif
             ),
    ssl(0), ssl_verify_server_cert(0),

=== modified file 'sql/rpl_mi.h'
--- a/sql/rpl_mi.h	2011-03-23 23:28:49 +0000
+++ b/sql/rpl_mi.h	2011-04-28 16:50:10 +0000
@@ -144,9 +144,11 @@ private:
 #ifdef HAVE_PSI_INTERFACE
               PSI_mutex_key *param_key_info_run_lock,
               PSI_mutex_key *param_key_info_data_lock,
+              PSI_mutex_key *param_key_info_sleep_lock,
               PSI_mutex_key *param_key_info_data_cond,
               PSI_mutex_key *param_key_info_start_cond,
-              PSI_mutex_key *param_key_info_stop_cond
+              PSI_mutex_key *param_key_info_stop_cond,
+              PSI_mutex_key *param_key_info_sleep_cond
 #endif
              );
   Master_info(const Master_info& info);

=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc	2011-04-04 09:42:22 +0000
+++ b/sql/rpl_rli.cc	2011-04-28 16:50:10 +0000
@@ -49,16 +49,19 @@ Relay_log_info::Relay_log_info(bool is_s
 #ifdef HAVE_PSI_INTERFACE
                                ,PSI_mutex_key *param_key_info_run_lock,
                                PSI_mutex_key *param_key_info_data_lock,
+                               PSI_mutex_key *param_key_info_sleep_lock,
                                PSI_mutex_key *param_key_info_data_cond,
                                PSI_mutex_key *param_key_info_start_cond,
-                               PSI_mutex_key *param_key_info_stop_cond
+                               PSI_mutex_key *param_key_info_stop_cond,
+                               PSI_mutex_key *param_key_info_sleep_cond
 #endif
                               )
    :Rpl_info("SQL"
 #ifdef HAVE_PSI_INTERFACE
              ,param_key_info_run_lock, param_key_info_data_lock,
+             param_key_info_sleep_lock,
              param_key_info_data_cond, param_key_info_start_cond,
-             param_key_info_stop_cond
+             param_key_info_stop_cond, param_key_info_sleep_cond
 #endif
             ),
    replicate_same_server_id(::replicate_same_server_id),

=== modified file 'sql/rpl_rli.h'
--- a/sql/rpl_rli.h	2011-03-23 23:28:49 +0000
+++ b/sql/rpl_rli.h	2011-04-28 16:50:10 +0000
@@ -617,9 +617,11 @@ private:
 #ifdef HAVE_PSI_INTERFACE
                  ,PSI_mutex_key *param_key_info_run_lock,
                  PSI_mutex_key *param_key_info_data_lock,
+                 PSI_mutex_key *param_key_info_sleep_lock,
                  PSI_mutex_key *param_key_info_data_cond,
                  PSI_mutex_key *param_key_info_start_cond,
-                 PSI_mutex_key *param_key_info_stop_cond
+                 PSI_mutex_key *param_key_info_stop_cond,
+                 PSI_mutex_key *param_key_info_sleep_cond
 #endif
                 );
   Relay_log_info(const Relay_log_info& info);

=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc	2011-04-19 03:29:06 +0000
+++ b/sql/rpl_slave.cc	2011-04-28 16:50:10 +0000
@@ -68,8 +68,6 @@ bool use_slave_mask = 0;
 MY_BITMAP slave_error_mask;
 char slave_skip_error_names[SHOW_VAR_FUNC_BUFF_SIZE];
 
-typedef bool (*CHECK_KILLED_FUNC)(THD*,void*);
-
 char* slave_load_tmpdir = 0;
 Master_info *active_mi= 0;
 my_bool replicate_same_server_id;
@@ -153,8 +151,6 @@ static int safe_reconnect(THD* thd, MYSQ
                           bool suppress_warnings);
 static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi,
                              bool reconnect, bool suppress_warnings);
-static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
-                      void* thread_killed_arg);
 static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi);
 static int get_master_uuid(MYSQL *mysql, Master_info *mi);
 int io_thread_init_commands(MYSQL *mysql, Master_info *mi);
@@ -2357,53 +2353,42 @@ static int init_slave_thread(THD* thd, S
 
 
 /**
-  Sleep for the given amount of time. If the sleep is interrupted,
-  continue sleeping unless the THD has been killed.
-
-  @param thd The THD object passed as first parameter to
-  (*thread_killed).
-
-  @param sec The number of seconds to sleep.
-
-  @param thread_killed Pointer to function that checks if the thread
-  has been killed or not.
+  Sleep for a given amount of time or until killed.
 
-  @param thread_killed_arg Pointer passed as second parameter to
-  (*thread_killed).
+  @param thd        Thread context of the current thread.
+  @param seconds    The number of seconds to sleep.
+  @param func       Function object to check if the thread has been killed.
+  @param info       The Rpl_info object associated with this sleep.
 
-  @retval 0 If we slept the given number of seconds and THD was not
-  killed.
-
-  @retval 1 If sleep was interrupted and THD killed.
+  @retval True if the thread has been killed, false otherwise.
 */
-static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
-                      void* thread_killed_arg)
+template <typename killed_func, typename rpl_info>
+static inline bool slave_sleep(THD *thd, time_t seconds,
+                               killed_func func, rpl_info info)
 {
-  int nap_time;
-  thr_alarm_t alarmed;
-  DBUG_ENTER("safe_sleep");
+  bool ret;
+  struct timespec abstime;
+  const char *old_proc_info;
+  mysql_mutex_t *lock= &info->sleep_lock;
+  mysql_cond_t *cond= &info->sleep_cond;
 
-  thr_alarm_init(&alarmed);
-  time_t start_time= my_time(0);
-  time_t end_time= start_time+sec;
+  /* Absolute system time at which the sleep time expires. */
+  set_timespec(abstime, seconds);
 
-  while ((nap_time= (int) (end_time - start_time)) > 0)
-  {
-    ALARM alarm_buff;
-    /*
-      The only reason we are asking for alarm is so that
-      we will be woken up in case of murder, so if we do not get killed,
-      set the alarm so it goes off after we wake up naturally
-    */
-    thr_alarm(&alarmed, 2 * nap_time, &alarm_buff);
-    sleep(nap_time);
-    thr_end_alarm(&alarmed);
+  mysql_mutex_lock(lock);
+  old_proc_info= thd->enter_cond(cond, lock, thd->proc_info);
 
-    if ((*thread_killed)(thd,thread_killed_arg))
-      DBUG_RETURN(1);
-    start_time= my_time(0);
+  while (! (ret= func(thd, info)))
+  {
+    int error= mysql_cond_timedwait(cond, lock, &abstime);
+    if (error == ETIMEDOUT || error == ETIME)
+      break;
   }
-  DBUG_RETURN(0);
+
+  /* Implicitly unlocks the mutex. */
+  thd->exit_cond(old_proc_info);
+
+  return ret;
 }
 
 
@@ -2569,8 +2554,7 @@ static int sql_delay_event(Log_event *ev
                           nap_time));
       rli->start_sql_delay(sql_delay_end);
       mysql_mutex_unlock(&rli->data_lock);
-      DBUG_RETURN(safe_sleep(thd, nap_time,
-                             (CHECK_KILLED_FUNC)sql_slave_killed, (void*)rli));
+      DBUG_RETURN(slave_sleep(thd, nap_time, sql_slave_killed, rli));
     }
   }
 
@@ -2938,8 +2922,8 @@ static int exec_relay_log_event(THD* thd
             exec_res= 0;
             rli->cleanup_context(thd, 1);
             /* chance for concurrent connection to get more locks */
-            safe_sleep(thd, min(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE),
-                       (CHECK_KILLED_FUNC)sql_slave_killed, (void*)rli);
+            slave_sleep(thd, min(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE),
+                        sql_slave_killed, rli);
             mysql_mutex_lock(&rli->data_lock); // because of SHOW STATUS
             rli->trans_retries++;
             rli->retried_trans++;
@@ -3039,8 +3023,7 @@ static int try_to_reconnect(THD *thd, MY
   {
     if (*retry_count > mi->retry_count)
       return 1;                             // Don't retry forever
-    safe_sleep(thd, mi->connect_retry, (CHECK_KILLED_FUNC) io_slave_killed,
-               (void *) mi);
+    slave_sleep(thd, mi->connect_retry, io_slave_killed, mi);
   }
   if (check_io_slave_killed(thd, mi, messages[SLAVE_RECON_MSG_KILLED_WAITING]))
     return 1;
@@ -4762,8 +4745,7 @@ static int connect_to_master(THD* thd, M
       slave_was_killed=1;
       break;
     }
-    safe_sleep(thd,mi->connect_retry,(CHECK_KILLED_FUNC)io_slave_killed,
-               (void*)mi);
+    slave_sleep(thd, mi->connect_retry, io_slave_killed, mi);
   }
 
   if (!slave_was_killed)

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2011-04-28 08:28:18 +0000
+++ b/sql/sql_select.cc	2011-05-03 06:46:06 +0000
@@ -3324,8 +3324,8 @@ JOIN::exec()
 	    DBUG_VOID_RETURN;
 	  curr_table->select->cond->fix_fields(thd, 0);
 	}
-        curr_table->set_select_cond(curr_table->select->cond, __LINE__);
-	curr_table->select_cond->top_level_item();
+        curr_table->set_condition(curr_table->select->cond, __LINE__);
+        curr_table->condition()->top_level_item();
 	DBUG_EXECUTE("where",print_where(curr_table->select->cond,
 					 "select and having",
                                          QT_ORDINARY););
@@ -3339,20 +3339,20 @@ JOIN::exec()
           to get sort_table_cond. An alternative could be to use
           Item::copy_andor_structure() to make a copy of sort_table_cond.
         */
-        if (curr_table->pre_idx_push_select_cond)
+        if (curr_table->pre_idx_push_cond)
         {
           sort_table_cond= make_cond_for_table(curr_join->tmp_having,
                                                used_tables, used_tables, 0);
           if (!sort_table_cond)
             DBUG_VOID_RETURN;
-          Item* new_pre_idx_push_select_cond= 
-            new Item_cond_and(curr_table->pre_idx_push_select_cond, 
+          Item* new_pre_idx_push_cond= 
+            new Item_cond_and(curr_table->pre_idx_push_cond, 
                               sort_table_cond);
-          if (!new_pre_idx_push_select_cond)
+          if (!new_pre_idx_push_cond)
             DBUG_VOID_RETURN;
-          if (new_pre_idx_push_select_cond->fix_fields(thd, 0))
+          if (new_pre_idx_push_cond->fix_fields(thd, 0))
             DBUG_VOID_RETURN;
-          curr_table->pre_idx_push_select_cond= new_pre_idx_push_select_cond;
+          curr_table->pre_idx_push_cond= new_pre_idx_push_cond;
 	}
 
 	curr_join->tmp_having= make_cond_for_table(curr_join->tmp_having,
@@ -3380,7 +3380,7 @@ JOIN::exec()
 	    table->keyuse is set in the case there was an original WHERE clause
 	    on the table that was optimized away.
 	  */
-	  if (curr_table->select_cond ||
+	  if (curr_table->condition() ||
 	      (curr_table->keyuse && !curr_table->first_inner))
 	  {
 	    /* We have to sort all rows */
@@ -5745,7 +5745,7 @@ add_key_field(KEY_FIELD **key_fields,uin
     othertbl.field can be NULL, there will be no matches if othertbl.field 
     has NULL value.
     We use null_rejecting in add_not_null_conds() to add
-    'othertbl.field IS NOT NULL' to tab->select_cond, if this is not an outer
+    'othertbl.field IS NOT NULL' to tab->m_condition, if this is not an outer
     join. We also use it to shortcut reading "tbl" when othertbl.field is
     found to be a NULL value (in join_read_always_key() and BKA).
   */
@@ -9323,28 +9323,43 @@ JOIN::make_simple_join(JOIN *parent, TAB
   DBUG_RETURN(FALSE);
 }
 
+/**
+  Extend e1 by AND'ing e2 to the condition e1 points to. The resulting
+  condition is fixed. Requirement: the input Items must already have
+  been fixed.
+
+  @param[in,out]   e1 Pointer to condition that will be extended with e2
+  @param           e2 Condition that will extend e1
 
-inline void add_cond_and_fix(Item **e1, Item *e2)
+  @retval true   if there was a memory allocation error, in which case
+                 e1 remains unchanged
+  @retval false  otherwise
+*/
+inline bool and_conditions(Item **e1, Item *e2)
 {
+  DBUG_ASSERT(!(*e1) || (*e1)->fixed);
+  DBUG_ASSERT(!e2 || e2->fixed);
   if (*e1)
   {
     if (!e2)
-      return;
-    Item *res;
-    if ((res= new Item_cond_and(*e1, e2)))
-    {
-      *e1= res;
-      res->quick_fix_field();
-      res->update_used_tables();
-    }
+      return false;
+    Item *res= new Item_cond_and(*e1, e2);
+    if (unlikely(!res))
+      return true;
+
+    *e1= res;
+    res->quick_fix_field();
+    res->update_used_tables();
+
   }
   else
     *e1= e2;
+  return false;
 }
 
 
 /**
-  Add to join_tab->select_cond[i] "table.field IS NOT NULL" conditions
+  Add to join_tab[i]->condition() "table.field IS NOT NULL" conditions
   we've inferred from ref/eq_ref access performed.
 
     This function is a part of "Early NULL-values filtering for ref access"
@@ -9390,7 +9405,7 @@ inline void add_cond_and_fix(Item **e1, 
          predicates in in KEY_FIELD::null_rejecting
       1.1 add_key_part saves these to Key_use.
       2. create_ref_for_key copies them to TABLE_REF.
-      3. add_not_null_conds adds "x IS NOT NULL" to join_tab->select_cond of
+      3. add_not_null_conds adds "x IS NOT NULL" to join_tab->m_condition of
          appropiate JOIN_TAB members.
 */
 
@@ -9434,9 +9449,7 @@ static void add_not_null_conds(JOIN *joi
           DBUG_EXECUTE("where",print_where(notnull,
                                            referred_tab->table->alias,
                                            QT_ORDINARY););
-          Item *new_cond= referred_tab->select_cond;
-          add_cond_and_fix(&new_cond, notnull);
-          referred_tab->set_select_cond(new_cond, __LINE__);
+          referred_tab->and_with_condition(notnull, __LINE__);
         }
       }
     }
@@ -9573,24 +9586,6 @@ make_outerjoin_info(JOIN *join)
   DBUG_VOID_RETURN;
 }
 
-static bool extend_select_cond(JOIN_TAB *cond_tab, Item *tmp_cond)
-{
-  DBUG_ENTER("extend_select_cond");
-
-  Item *new_cond= !cond_tab->select_cond ? tmp_cond :
-    new Item_cond_and(cond_tab->select_cond, tmp_cond);
-  cond_tab->set_select_cond(new_cond, __LINE__);
-  if (!cond_tab->select_cond)
-    DBUG_RETURN(1);
-  cond_tab->select_cond->update_used_tables();
-  cond_tab->select_cond->quick_fix_field();
-  if (cond_tab->select)
-    cond_tab->select->cond= cond_tab->select_cond; 
-
-  DBUG_RETURN(0);
-}
-
-
 /**
    Local helper function for make_join_select().
 
@@ -9619,11 +9614,11 @@ static bool pushdown_on_conditions(JOIN*
         continue;
       tmp_cond= new Item_func_trig_cond(tmp_cond, &cond_tab->not_null_compl);
       if (!tmp_cond)
-        DBUG_RETURN(1);
+        DBUG_RETURN(true);
       tmp_cond->quick_fix_field();
 
-      if (extend_select_cond(cond_tab, tmp_cond))
-        DBUG_RETURN(1);
+      if (cond_tab->and_with_jt_and_sel_condition(tmp_cond, __LINE__))
+        DBUG_RETURN(true);
     }       
   }
 
@@ -9673,12 +9668,13 @@ static bool pushdown_on_conditions(JOIN*
       */ 
       tmp_cond= new Item_func_trig_cond(tmp_cond,
                                         &first_inner_tab->not_null_compl);
-      if (tmp_cond)
-        tmp_cond->quick_fix_field();
+      if (!tmp_cond)
+        DBUG_RETURN(true);
+      tmp_cond->quick_fix_field();
 
       /* Add the predicate to other pushed down predicates */
-      if (extend_select_cond(cond_tab, tmp_cond))
-        DBUG_RETURN(1);
+      if (cond_tab->and_with_jt_and_sel_condition(tmp_cond, __LINE__))
+        DBUG_RETURN(true);
     }
     first_inner_tab= first_inner_tab->first_upper;       
   }
@@ -9737,8 +9733,11 @@ static bool make_join_select(JOIN *join,
                               (table_map) 0, 1);
         /* Add conditions added by add_not_null_conds(). */
         for (uint i= 0 ; i < join->const_tables ; i++)
-          add_cond_and_fix(&const_cond, join->join_tab[i].select_cond);
-
+        {
+          if (and_conditions(&const_cond, join->join_tab[i].condition()))
+            DBUG_RETURN(true);
+        }
+          
         DBUG_EXECUTE("where",print_where(const_cond,"constants", QT_ORDINARY););
         for (JOIN_TAB *tab= join->join_tab+join->const_tables;
              tab < join->join_tab+join->tables ; tab++)
@@ -9753,14 +9752,11 @@ static bool make_join_select(JOIN *join,
               continue;
             tmp= new Item_func_trig_cond(tmp, &cond_tab->not_null_compl);
             if (!tmp)
-              DBUG_RETURN(1);
+              DBUG_RETURN(true);
+
             tmp->quick_fix_field();
-            Item *new_cond= !cond_tab->select_cond ? tmp :
-              new Item_cond_and(cond_tab->select_cond, tmp);
-            cond_tab->set_select_cond(new_cond, __LINE__);
-            if (!cond_tab->select_cond)
-	      DBUG_RETURN(1);
-            cond_tab->select_cond->quick_fix_field();
+            if (cond_tab->and_with_condition(tmp, __LINE__))
+              DBUG_RETURN(true);
           }       
         }
         if (const_cond && !const_cond->val_int())
@@ -9840,8 +9836,9 @@ static bool make_join_select(JOIN *join,
       if (cond)
         tmp= make_cond_for_table(cond,used_tables,current_map, 0);
       /* Add conditions added by add_not_null_conds(). */
-      if (tab->select_cond)
-        add_cond_and_fix(&tmp, tab->select_cond);
+      if (tab->condition() && and_conditions(&tmp, tab->condition()))
+        DBUG_RETURN(true);
+
 
       if (cond && !tmp && tab->quick)
       {						// Outer join
@@ -9888,9 +9885,9 @@ static bool make_join_select(JOIN *join,
             a cond, so neutralize the hack above.
           */
           if (!(tmp= add_found_match_trig_cond(first_inner_tab, tmp, 0)))
-            DBUG_RETURN(1);
+            DBUG_RETURN(true);
           sel->cond= tmp;
-          tab->set_select_cond(tmp, __LINE__);
+          tab->set_condition(tmp, __LINE__);
           /* Push condition to storage engine if this is enabled
              and the condition is not guarded */
 	  if (thd->optimizer_switch_flag(OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) &&
@@ -9909,7 +9906,7 @@ static bool make_join_select(JOIN *join,
         else
         {
           sel->cond= NULL;
-          tab->set_select_cond(NULL, __LINE__);
+          tab->set_condition(NULL, __LINE__);
         }
 
 	sel->head=tab->table;
@@ -10129,7 +10126,7 @@ static bool uses_index_fields_only(Item 
     TODO: Consider cloning the triggered condition and using the copies for:
       1. push the first copy down, to have most restrictive index condition
          possible
-      2. Put the second copy into tab->select_cond. 
+      2. Put the second copy into tab->m_condition. 
   */
   if (item_type == Item::FUNC_ITEM && 
       ((Item_func*)item)->functype() == Item_func::TRIG_COND_FUNC)
@@ -10366,7 +10363,7 @@ Item *make_cond_remainder(Item *cond, bo
   SYNOPSIS
     push_index_cond()
       tab            A join tab that has tab->table->file and its condition
-                     in tab->select_cond
+                     in tab->m_condition
       keyno          Index for which extract and push the condition
       other_tbls_ok  TRUE <=> Fields of other non-const tables are allowed
 
@@ -10394,7 +10391,7 @@ static void push_index_cond(JOIN_TAB *ta
        that can be turned on or off during execution of a 'Full scan on NULL 
        key'.
   */
-  if (tab->select_cond &&
+  if (tab->condition() &&
       tab->table->file->index_flags(keyno, 0, 1) &
       HA_DO_INDEX_COND_PUSHDOWN &&
       tab->join->thd->optimizer_switch_flag(OPTIMIZER_SWITCH_INDEX_CONDITION_PUSHDOWN) &&
@@ -10402,15 +10399,15 @@ static void push_index_cond(JOIN_TAB *ta
       tab->join->thd->lex->sql_command != SQLCOM_DELETE_MULTI &&
       !tab->has_guarded_conds())
   {
-    DBUG_EXECUTE("where", print_where(tab->select_cond, "full cond",
+    DBUG_EXECUTE("where", print_where(tab->condition(), "full cond",
                  QT_ORDINARY););
-    Item *idx_cond= make_cond_for_index(tab->select_cond, tab->table, keyno,
-                                        other_tbls_ok);
+    Item *idx_cond= make_cond_for_index(tab->condition(), tab->table,
+                                        keyno, other_tbls_ok);
     DBUG_EXECUTE("where", print_where(idx_cond, "idx cond", QT_ORDINARY););
     if (idx_cond)
     {
       Item *idx_remainder_cond= 0;
-      tab->pre_idx_push_select_cond= tab->select_cond;
+      tab->pre_idx_push_cond= tab->condition();
 
       /*
         For BKA cache we store condition to special BKA cache field
@@ -10448,30 +10445,27 @@ static void push_index_cond(JOIN_TAB *ta
       if (idx_remainder_cond != idx_cond)
         tab->ref.disable_cache= TRUE;
 
-      Item *row_cond= make_cond_remainder(tab->select_cond, TRUE);
+      Item *row_cond= make_cond_remainder(tab->condition(), TRUE);
       DBUG_EXECUTE("where", print_where(row_cond, "remainder cond",
                    QT_ORDINARY););
       
       if (row_cond)
       {
         if (!idx_remainder_cond)
-          tab->set_select_cond(row_cond, __LINE__);
+          tab->set_condition(row_cond, __LINE__);
         else
         {
-          Item *new_cond= new Item_cond_and(row_cond, idx_remainder_cond);
-          tab->set_select_cond(new_cond, __LINE__);
-	  tab->select_cond->quick_fix_field();
-          ((Item_cond_and*)tab->select_cond)->used_tables_cache= 
-            row_cond->used_tables() | idx_remainder_cond->used_tables();
+          and_conditions(&row_cond, idx_remainder_cond);
+          tab->set_condition(row_cond, __LINE__);
         }
       }
       else
-        tab->set_select_cond(idx_remainder_cond, __LINE__);
+        tab->set_condition(idx_remainder_cond, __LINE__);
       if (tab->select)
       {
-        DBUG_EXECUTE("where", print_where(tab->select->cond, "select_cond",
+        DBUG_EXECUTE("where", print_where(tab->select->cond, "cond",
                      QT_ORDINARY););
-        tab->select->cond= tab->select_cond;
+        tab->select->cond= tab->condition();
       }
     }
   }
@@ -10972,19 +10966,22 @@ static bool is_cond_sj_in_equality(Item 
 }
 
 
-void remove_sj_conds(Item **tree)
+/**
+  Strip injected semi-join conditions from Item tree
+
+  @param tree  An item tree that may contain semi-join equality conditions
+  @return      The same item tree without semi-join equality conditions
+ */
+Item *remove_sj_conds(Item *tree)
 {
-  if (*tree)
+  if (tree)
   {
-    if (is_cond_sj_in_equality(*tree))
-    {
-      *tree= NULL;
-      return;
-    }
-    else if ((*tree)->type() == Item::COND_ITEM) 
+    if (is_cond_sj_in_equality(tree))
+      return NULL;
+    else if (tree->type() == Item::COND_ITEM) 
     {
       Item *item;
-      List_iterator<Item> li(*(((Item_cond*)*tree)->argument_list()));
+      List_iterator<Item> li(*(((Item_cond*)tree)->argument_list()));
       while ((item= li++))
       {
         if (is_cond_sj_in_equality(item))
@@ -10992,9 +10989,9 @@ void remove_sj_conds(Item **tree)
       }
     }
   }
+  return tree;
 }
 
-
 /*
   Create subquery equalities assuming use of materialization strategy
   
@@ -11153,10 +11150,11 @@ bool setup_sj_materialization(JOIN_TAB *
     */
     for (i= 0; i < sjm->table_count; i++)
     {
-      remove_sj_conds(&tab[i].select_cond);
+      tab[i].set_condition(remove_sj_conds(tab[i].condition()), __LINE__);
       if (tab[i].select)
-        remove_sj_conds(&tab[i].select->cond);
+        tab[i].select->cond= remove_sj_conds(tab[i].select->cond);
     }
+
     if (!(sjm->in_equality= create_subquery_equalities(thd, emb_sj_nest)))
       DBUG_RETURN(TRUE); /* purecov: inspected */
   }
@@ -11542,6 +11540,56 @@ uint JOIN_TAB::get_sj_strategy() const
   return s;
 }
 
+/**
+  Extend join_tab->m_condition and join_tab->select->cond by AND'ing
+  add_cond to them
+
+  @param add_cond   The condition to AND with the existing conditions
+  @param line       Code line this method was called from
+
+  @retval true   if there was a memory allocation error
+  @retval false  otherwise
+
+*/
+bool JOIN_TAB::and_with_jt_and_sel_condition(Item *add_cond, uint line)
+{
+  if (and_with_condition(add_cond, line))
+    return true;
+
+  if (select)
+  {
+    DBUG_PRINT("info", 
+               ("select::cond extended. Change %p -> %p "
+                "at line %u tab %p select %p",
+                select->cond, m_condition, line, this, select));
+    select->cond= m_condition;
+  }
+  return false;
+}
+
+/**
+  Extend join_tab->cond by AND'ing add_cond to it
+
+  @param add_cond    The condition to AND with the existing cond
+                     for this JOIN_TAB
+  @param line        Code line this method was called from
+
+  @retval true   if there was a memory allocation error
+  @retval false  otherwise
+*/
+bool JOIN_TAB::and_with_condition(Item *add_cond, uint line)
+{
+  Item *old_cond __attribute__((unused))= m_condition;
+  if (and_conditions(&m_condition, add_cond))
+    return true;
+  DBUG_PRINT("info", ("JOIN_TAB::m_condition extended. Change %p -> %p "
+                      "at line %u tab %p",
+                      old_cond, m_condition, line, this));
+  return false;
+}
+
+
+
 
 /**
   Partially cleanup JOIN after it has executed: close index or rnd read
@@ -17326,10 +17374,10 @@ sub_select_sjm(JOIN *join, JOIN_TAB *joi
     /* Do full scan of the materialized table */
     JOIN_TAB *last_tab= join_tab + (sjm->table_count - 1);
 
-    Item *save_cond= last_tab->select_cond;
-    last_tab->set_select_cond(sjm->join_cond, __LINE__);
+    Item *save_cond= last_tab->condition();
+    last_tab->set_condition(sjm->join_cond, __LINE__);
     rc= sub_select(join, last_tab, end_of_records);
-    last_tab->set_select_cond(save_cond, __LINE__);
+    last_tab->set_condition(save_cond, __LINE__);
     DBUG_RETURN(rc);
   }
   else
@@ -17458,7 +17506,7 @@ sub_select_cache(JOIN *join, JOIN_TAB *j
     given the selected plan prescribes to nest retrievals of the
     joined tables in the following order: t1,t2,t3.
     A pushed down predicate are attached to the table which it pushed to,
-    at the field join_tab->select_cond.
+    at the field join_tab->cond.
     When executing a nested loop of level k the function runs through
     the rows of 'join_tab' and for each row checks the pushed condition
     attached to the table.
@@ -17756,14 +17804,14 @@ evaluate_join_record(JOIN *join, JOIN_TA
 {
   bool not_used_in_distinct=join_tab->not_used_in_distinct;
   ha_rows found_records=join->found_records;
-  Item *select_cond= join_tab->select_cond;
+  Item *condition= join_tab->condition();
   bool found= TRUE;
 
   DBUG_ENTER("evaluate_join_record");
 
   DBUG_PRINT("enter",
              ("evaluate_join_record join: %p join_tab: %p"
-              " cond: %p error: %d", join, join_tab, select_cond, error));
+              " cond: %p error: %d", join, join_tab, condition, error));
   if (error > 0 || (join->thd->is_error()))     // Fatal error
     DBUG_RETURN(NESTED_LOOP_ERROR);
   if (error < 0)
@@ -17773,11 +17821,11 @@ evaluate_join_record(JOIN *join, JOIN_TA
     join->thd->send_kill_message();
     DBUG_RETURN(NESTED_LOOP_KILLED);            /* purecov: inspected */
   }
-  DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
+  DBUG_PRINT("info", ("condition %p", condition));
 
-  if (select_cond)
+  if (condition)
   {
-    found= test(select_cond->val_int());
+    found= test(condition->val_int());
 
     /* check for errors evaluating the condition */
     if (join->thd->is_error())
@@ -17786,7 +17834,7 @@ evaluate_join_record(JOIN *join, JOIN_TA
   if (found)
   {
     /*
-      There is no select condition or the attached pushed down
+      There is no condition on this join_tab or the attached pushed down
       condition is true => a match is found.
     */
     while (join_tab->first_unmatched && found)
@@ -17812,7 +17860,7 @@ evaluate_join_record(JOIN *join, JOIN_TA
         */
         /*
           not_exists_optimize has been created from a
-          select_cond containing 'is_null'. This 'is_null'
+          condition containing 'is_null'. This 'is_null'
           predicate is still present on any 'tab' with
           'not_exists_optimize'. Furthermore, the usual rules
           for condition guards also applies for
@@ -17821,9 +17869,9 @@ evaluate_join_record(JOIN *join, JOIN_TA
           the 'not_exists_optimize'.
         */
         DBUG_ASSERT(!(tab->table->reginfo.not_exists_optimize &&
-                     !tab->select_cond));
+                     !tab->condition()));
 
-        if (tab->select_cond && !tab->select_cond->val_int())
+        if (tab->condition() && !tab->condition()->val_int())
         {
           /* The condition attached to table tab is false */
 
@@ -17987,8 +18035,6 @@ evaluate_null_complemented_join_record(J
     and no matches has been found for the current outer row.
   */
   JOIN_TAB *last_inner_tab= join_tab->last_inner;
-  /* Cache variables for faster loop */
-  Item *select_cond;
 
   DBUG_ENTER("evaluate_null_complemented_join_record");
 
@@ -18000,9 +18046,8 @@ evaluate_null_complemented_join_record(J
     /* The outer row is complemented by nulls for each inner tables */
     restore_record(join_tab->table,s->default_values);  // Make empty record
     mark_as_null_row(join_tab->table);       // For group by without error
-    select_cond= join_tab->select_cond;
     /* Check all attached conditions for inner table rows. */
-    if (select_cond && !select_cond->val_int())
+    if (join_tab->condition() && !join_tab->condition()->val_int())
       DBUG_RETURN(NESTED_LOOP_OK);
   }
   join_tab= last_inner_tab;
@@ -18730,9 +18775,13 @@ end_send(JOIN *join, JOIN_TAB *join_tab 
       if (join->select_options & OPTION_FOUND_ROWS)
       {
 	JOIN_TAB *jt=join->join_tab;
-	if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
-	    && !join->send_group_parts && !join->having && !jt->select_cond &&
-	    !(jt->select && jt->select->quick) &&
+	if ((join->tables == 1) &&
+            !join->tmp_table &&
+            !join->sort_and_group &&
+            !join->send_group_parts &&
+            !join->having &&
+            !jt->condition() &&
+            !(jt->select && jt->select->quick) &&
 	    (jt->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
             (jt->ref.key < 0))
 	{
@@ -20101,8 +20150,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
   SQL_SELECT *select=tab->select;
   QUICK_SELECT_I *save_quick= 0;
   int best_key= -1;
-  Item *orig_select_cond= 0;
-  bool orig_select_cond_saved= false;
+  Item *orig_cond= 0;
+  bool orig_cond_saved= false;
   bool changed_key= false;
   DBUG_ENTER("test_if_skip_sort_order");
   LINT_INIT(ref_key_parts);
@@ -20176,10 +20225,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
         select condition is saved so that it can be restored when
         exiting this function (if we have not changed index).
       */
-      if (tab->pre_idx_push_select_cond)
+      if (tab->pre_idx_push_cond)
       {
-        orig_select_cond= tab->set_cond(tab->pre_idx_push_select_cond, __LINE__);
-        orig_select_cond_saved= true;
+        orig_cond= 
+          tab->set_jt_and_sel_condition(tab->pre_idx_push_cond, __LINE__);
+        orig_cond_saved= true;
       }
 
       if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
@@ -20268,8 +20318,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
 
     if (best_key >= 0)
     {
-      if (table->quick_keys.is_set(best_key) && best_key != ref_key)
+      if (table->quick_keys.is_set(best_key) &&
+          !tab->quick_order_tested.is_set(best_key) &&
+          best_key != ref_key)
       {
+        tab->quick_order_tested.set_bit(best_key);
         key_map map;           // Force the creation of quick select
         map.set_bit(best_key); // only best_key.
         select->quick= 0;
@@ -20350,15 +20403,15 @@ check_reverse_order:                  
 
         if (table->covering_keys.is_set(best_key))
           table->set_keyread(TRUE);
-        if (tab->pre_idx_push_select_cond)
+        if (tab->pre_idx_push_cond)
         {
-          tab->set_cond(tab->pre_idx_push_select_cond, __LINE__);
+          tab->set_jt_and_sel_condition(tab->pre_idx_push_cond, __LINE__);
           /*
-            orig_select_cond is a part of pre_idx_push_select_cond,
+            orig_cond is a part of pre_idx_push_cond,
             no need to restore it.
           */
-          orig_select_cond= 0;
-          orig_select_cond_saved= false;
+          orig_cond= 0;
+          orig_cond_saved= false;
         }
         table->file->ha_index_or_rnd_end();
         if (tab->join->select_options & SELECT_DESCRIBE)
@@ -20440,18 +20493,17 @@ skipped_filesort:
     Restore condition only if we didn't chose index different to what we used
     for ICP.
   */
-  if (orig_select_cond_saved && !changed_key)
-    tab->set_cond(orig_select_cond, __LINE__);
-  DBUG_RETURN(1);
+  if (orig_cond_saved && !changed_key)
+    tab->set_jt_and_sel_condition(orig_cond, __LINE__);
+  DBUG_RETURN(true);
 
 use_filesort:
   // Restore original save_quick
   if (select && select->quick != save_quick)
     select->set_quick(save_quick);
-
-  if (orig_select_cond_saved)
-    tab->set_cond(orig_select_cond, __LINE__);
-  DBUG_RETURN(0);
+  if (orig_cond_saved)
+    tab->set_jt_and_sel_condition(orig_cond, __LINE__);
+  DBUG_RETURN(false);
 }
 
 
@@ -20591,7 +20643,7 @@ create_sort_index(THD *thd, JOIN *join, 
     table->quick_keys.clear_all();  // as far as we cleanup select->quick
     table->sort.io_cache= tablesort_result_cache;
   }
-  tab->set_select_cond(NULL, __LINE__);
+  tab->set_condition(NULL, __LINE__);
   tab->last_inner= 0;
   tab->first_unmatched= 0;
   tab->type=JT_ALL;				// Read with normal read_record
@@ -22365,26 +22417,26 @@ static bool add_ref_to_table_cond(THD *t
     if (join_tab->select->cond)
       error=(int) cond->add(join_tab->select->cond);
     join_tab->select->cond= cond;
-    join_tab->set_select_cond(cond, __LINE__);
+    join_tab->set_condition(cond, __LINE__);
   }
   else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0,
                                           &error)))
-    join_tab->set_select_cond(cond, __LINE__);
+    join_tab->set_condition(cond, __LINE__);
 
   /*
     If we have pushed parts of the select condition down to the
     storage engine we also need to add the condition for the const
-    reference to the pre_idx_push_select_cond since this might be used
-    later (in test_if_skip_sort_order()) instead of the select_cond.
+    reference to the pre_idx_push_cond since this might be used
+    later (in test_if_skip_sort_order()) instead of the condition.
   */
-  if (join_tab->pre_idx_push_select_cond)
+  if (join_tab->pre_idx_push_cond)
   {
     cond= create_cond_for_const_ref(thd, join_tab);
     if (!cond)
       DBUG_RETURN(TRUE);
-    if (cond->add(join_tab->pre_idx_push_select_cond))
+    if (cond->add(join_tab->pre_idx_push_cond))
       DBUG_RETURN(TRUE);
-    join_tab->pre_idx_push_select_cond = cond;
+    join_tab->pre_idx_push_cond = cond;
   }
 
   DBUG_RETURN(error ? TRUE : FALSE);

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2011-04-28 08:28:18 +0000
+++ b/sql/sql_select.h	2011-05-02 11:51:41 +0000
@@ -258,7 +258,9 @@ typedef struct st_join_table : public Sq
   TABLE		*table;
   Key_use	*keyuse;			/**< pointer to first used key */
   SQL_SELECT	*select;
-  Item		*select_cond;
+private:
+  Item          *m_condition;   /**< condition for this join_tab               */
+public:
   QUICK_SELECT_I *quick;
   Item	       **on_expr_ref;   /**< pointer to the associated on expression   */
   COND_EQUAL    *cond_equal;    /**< multiple equalities for the on expression */
@@ -269,13 +271,13 @@ typedef struct st_join_table : public Sq
   st_join_table *first_upper;  /**< first inner table for embedding outer join */
   st_join_table *first_unmatched; /**< used for optimization purposes only     */
   /* 
-    The value of select_cond before we've attempted to do Index Condition
+    The value of m_condition before we've attempted to do Index Condition
     Pushdown. We may need to restore everything back if we first choose one
     index but then reconsider (see test_if_skip_sort_order() for such
     scenarios).
     NULL means no index condition pushdown was performed.
   */
-  Item          *pre_idx_push_select_cond;
+  Item          *pre_idx_push_cond;
   
   /* Special content for EXPLAIN 'Extra' column or NULL if none */
   const char	*info;
@@ -300,6 +302,15 @@ typedef struct st_join_table : public Sq
   key_map	checked_keys;			/**< Keys checked */
   key_map	needed_reg;
   key_map       keys;                           /**< all keys with can be used */
+  /**
+    Used to avoid repeated range analysis for the same key in
+    test_if_skip_sort_order(). This would otherwise happen if the best
+    range access plan found for a key is turned down.
+    quick_order_tested is cleared every time the select condition for
+    this JOIN_TAB changes since a new condition may give another plan
+    and cost from range analysis.
+   */
+  key_map       quick_order_tested;
 
   /* Either #rows in the table or 1 for const table.  */
   ha_rows	records;
@@ -436,22 +447,31 @@ typedef struct st_join_table : public Sq
   {
     return first_inner && first_inner == this;
   }
-  void set_select_cond(Item *to, uint line)
+  Item *condition()
   {
-    DBUG_PRINT("info", ("select_cond changes %p -> %p at line %u tab %p",
-                        select_cond, to, line, this));
-    select_cond= to;
+    return m_condition;
   }
-  Item *set_cond(Item *new_cond, uint line)
+  void set_condition(Item *to, uint line)
   {
-    Item *tmp_select_cond= select_cond;
-    set_select_cond(new_cond, line);
+    DBUG_PRINT("info", 
+               ("JOIN_TAB::m_condition changes %p -> %p at line %u tab %p",
+                m_condition, to, line, this));
+    m_condition= to;
+    quick_order_tested.clear_all();
+  }
+
+  Item *set_jt_and_sel_condition(Item *new_cond, uint line)
+  {
+    Item *tmp_cond= m_condition;
+    set_condition(new_cond, line);
     if (select)
       select->cond= new_cond;
-    return tmp_select_cond;
+    return tmp_cond;
   }
   uint get_sj_strategy() const;
 
+  bool and_with_condition(Item *tmp_cond, uint line);
+  bool and_with_jt_and_sel_condition(Item *tmp_cond, uint line);
 
   /**
     Check if there are triggered/guarded conditions that might be
@@ -467,13 +487,12 @@ typedef struct st_join_table : public Sq
   }
 } JOIN_TAB;
 
-
 inline
 st_join_table::st_join_table()
   : table(NULL),
     keyuse(NULL),
     select(NULL),
-    select_cond(NULL),
+    m_condition(NULL),
     quick(NULL),
     on_expr_ref(NULL),
     cond_equal(NULL),
@@ -483,7 +502,7 @@ st_join_table::st_join_table()
     last_inner(NULL),
     first_upper(NULL),
     first_unmatched(NULL),
-    pre_idx_push_select_cond(NULL),
+    pre_idx_push_cond(NULL),
     info(NULL),
     packed_info(0),
     read_first_record(NULL),
@@ -496,6 +515,7 @@ st_join_table::st_join_table()
     checked_keys(),
     needed_reg(),
     keys(),
+    quick_order_tested(),
 
     records(0),
     found_records(0),

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	2011-04-15 12:14:35 +0000
+++ b/sql/sql_show.cc	2011-05-02 11:16:36 +0000
@@ -6771,7 +6771,7 @@ static bool do_fill_table(THD *thd,
   thd->warning_info= &wi;
 
   bool res= table_list->schema_table->fill_table(
-    thd, table_list, join_table->select_cond);
+    thd, table_list, join_table->condition());
 
   thd->warning_info= wi_saved;
 

=== modified file 'storage/innobase/include/trx0purge.h'
--- a/storage/innobase/include/trx0purge.h	2011-04-27 21:49:19 +0000
+++ b/storage/innobase/include/trx0purge.h	2011-04-28 07:33:49 +0000
@@ -100,13 +100,6 @@ trx_purge(
 					submit to task queue. */
 	ulint	limit);			/*!< in: the maximum number of
 					records to purge in one batch */
-/******************************************************************//**
-Prints information of the purge system to stderr. */
-UNIV_INTERN
-void
-trx_purge_sys_print(void);
-/*======================*/
-
 /** This is the purge pointer/iterator. We need both the undo no and the
 transaction no up to which purge has parsed and applied the records. */
 typedef struct purge_iter_struct {

=== modified file 'storage/innobase/include/trx0rec.h'
--- a/storage/innobase/include/trx0rec.h	2010-08-07 06:52:02 +0000
+++ b/storage/innobase/include/trx0rec.h	2011-04-28 07:33:49 +0000
@@ -245,8 +245,7 @@ that the caller has a latch on the index
 and an s-latch on the purge_view. This guarantees that the stack of versions
 is locked.
 @return DB_SUCCESS, or DB_MISSING_HISTORY if the previous version is
-earlier than purge_view, which means that it may have been removed,
-DB_ERROR if corrupted record */
+earlier than purge_view, which means that it may have been removed */
 UNIV_INTERN
 ulint
 trx_undo_prev_version_build(

=== modified file 'storage/innobase/trx/trx0purge.c'
--- a/storage/innobase/trx/trx0purge.c	2011-04-14 06:46:38 +0000
+++ b/storage/innobase/trx/trx0purge.c	2011-04-28 07:33:49 +0000
@@ -1309,28 +1309,3 @@ run_synchronously:
 
 	return(n_pages_handled);
 }
-
-/******************************************************************//**
-Prints information of the purge system to stderr. */
-UNIV_INTERN
-void
-trx_purge_sys_print(void)
-/*=====================*/
-{
-	fprintf(stderr, "InnoDB: Purge system view:\n");
-	read_view_print(purge_sys->view);
-
-	fprintf(stderr, "InnoDB: Purge trx n:o " TRX_ID_FMT
-		", undo n:o " TRX_ID_FMT "\n",
-		(ullint) purge_sys->limit.trx_no,
-		(ullint) purge_sys->limit.undo_no);
-	fprintf(stderr,
-		"InnoDB: Purge next stored %lu, page_no %lu, offset %lu,\n"
-		"InnoDB: Purge hdr_page_no %lu, hdr_offset %lu\n",
-		(ulong) purge_sys->next_stored,
-		(ulong) purge_sys->page_no,
-		(ulong) purge_sys->offset,
-		(ulong) purge_sys->hdr_page_no,
-		(ulong) purge_sys->hdr_offset);
-}
-

=== modified file 'storage/innobase/trx/trx0rec.c'
--- a/storage/innobase/trx/trx0rec.c	2011-03-23 13:43:14 +0000
+++ b/storage/innobase/trx/trx0rec.c	2011-05-02 16:18:01 +0000
@@ -1400,21 +1400,27 @@ trx_undo_get_undo_rec(
 	return(DB_SUCCESS);
 }
 
+#ifdef UNIV_DEBUG
+#define ATTRIB_USED_ONLY_IN_DEBUG
+#else /* UNIV_DEBUG */
+#define ATTRIB_USED_ONLY_IN_DEBUG	__attribute__((unused))
+#endif /* UNIV_DEBUG */
+
 /*******************************************************************//**
 Build a previous version of a clustered index record. This function checks
 that the caller has a latch on the index page of the clustered index record
 and an s-latch on the purge_view. This guarantees that the stack of versions
 is locked all the way down to the purge_view.
 @return DB_SUCCESS, or DB_MISSING_HISTORY if the previous version is
-earlier than purge_view, which means that it may have been removed,
-DB_ERROR if corrupted record */
+earlier than purge_view, which means that it may have been removed */
 UNIV_INTERN
 ulint
 trx_undo_prev_version_build(
 /*========================*/
-	const rec_t*	index_rec,/*!< in: clustered index record in the
+	const rec_t*	index_rec ATTRIB_USED_ONLY_IN_DEBUG,
+				/*!< in: clustered index record in the
 				index tree */
-	mtr_t*		index_mtr __attribute__((unused)),
+	mtr_t*		index_mtr ATTRIB_USED_ONLY_IN_DEBUG,
 				/*!< in: mtr which contains the latch to
 				index_rec page and purge_view */
 	const rec_t*	rec,	/*!< in: version of a clustered index record */
@@ -1451,20 +1457,7 @@ trx_undo_prev_version_build(
 	      || mtr_memo_contains_page(index_mtr, index_rec,
 					MTR_MEMO_PAGE_X_FIX));
 	ut_ad(rec_offs_validate(rec, index, offsets));
-
-	if (!dict_index_is_clust(index)) {
-		fprintf(stderr, "InnoDB: Error: trying to access"
-			" update undo rec for non-clustered index %s\n"
-			"InnoDB: Submit a detailed bug report to"
-			" http://bugs.mysql.com\n"
-			"InnoDB: index record ", index->name);
-		rec_print(stderr, index_rec, index);
-		fputs("\n"
-		      "InnoDB: record version ", stderr);
-		rec_print_new(stderr, rec, offsets);
-		putc('\n', stderr);
-		return(DB_ERROR);
-	}
+	ut_a(dict_index_is_clust(index));
 
 	roll_ptr = row_get_rec_roll_ptr(rec, index, offsets);
 	old_roll_ptr = roll_ptr;
@@ -1484,7 +1477,9 @@ trx_undo_prev_version_build(
 
 	if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
 		/* The undo record may already have been purged.
-		This should never happen in InnoDB. */
+		This should never happen for user transactions, but
+		it can happen in purge. */
+		ut_ad(err == DB_MISSING_HISTORY);
 
 		return(err);
 	}
@@ -1522,54 +1517,8 @@ trx_undo_prev_version_build(
 	ptr = trx_undo_update_rec_get_update(ptr, index, type, trx_id,
 					     roll_ptr, info_bits,
 					     NULL, heap, &update);
-
-	if (UNIV_UNLIKELY(table_id != index->table->id)) {
-		ptr = NULL;
-
-		fprintf(stderr,
-			"InnoDB: Error: trying to access update undo rec"
-			" for table %s\n"
-			"InnoDB: but the table id in the"
-			" undo record is wrong\n"
-			"InnoDB: Submit a detailed bug report"
-			" to http://bugs.mysql.com\n"
-			"InnoDB: Run also CHECK TABLE %s\n",
-			index->table_name, index->table_name);
-	}
-
-	if (ptr == NULL) {
-		/* The record was corrupted, return an error; these printfs
-		should catch an elusive bug in row_vers_old_has_index_entry */
-
-		fprintf(stderr,
-			"InnoDB: table %s, index %s, n_uniq %lu\n"
-			"InnoDB: undo rec address %p, type %lu cmpl_info %lu\n"
-			"InnoDB: undo rec table id %llu,"
-			" index table id %llu\n"
-			"InnoDB: dump of 150 bytes in undo rec: ",
-			index->table_name, index->name,
-			(ulong) dict_index_get_n_unique(index),
-			undo_rec, (ulong) type, (ulong) cmpl_info,
-			(ullint) table_id,
-			(ullint) index->table->id);
-		ut_print_buf(stderr, undo_rec, 150);
-		fputs("\n"
-		      "InnoDB: index record ", stderr);
-		rec_print(stderr, index_rec, index);
-		fputs("\n"
-		      "InnoDB: record version ", stderr);
-		rec_print_new(stderr, rec, offsets);
-		fprintf(stderr, "\n"
-			"InnoDB: Record trx id " TRX_ID_FMT
-			", update rec trx id " TRX_ID_FMT "\n"
-			"InnoDB: Roll ptr in rec " TRX_ID_FMT
-			", in update rec" TRX_ID_FMT "\n",
-			(ullint) rec_trx_id, (ullint) trx_id,
-			(ullint) old_roll_ptr, (ullint) roll_ptr);
-
-		trx_purge_sys_print();
-		return(DB_ERROR);
-	}
+	ut_a(table_id == index->table->id);
+	ut_a(ptr);
 
 	if (row_upd_changes_field_size_or_external(index, offsets, update)) {
 		ulint	n_ext;

=== modified file 'storage/perfschema/pfs_timer.cc'
--- a/storage/perfschema/pfs_timer.cc	2011-02-14 14:23:55 +0000
+++ b/storage/perfschema/pfs_timer.cc	2011-04-28 22:01:07 +0000
@@ -23,7 +23,7 @@
 #include "my_rdtsc.h"
 
 enum_timer_name wait_timer= TIMER_NAME_CYCLE;
-enum_timer_name stage_timer= TIMER_NAME_CYCLE;
+enum_timer_name stage_timer= TIMER_NAME_NANOSEC;
 enum_timer_name statement_timer= TIMER_NAME_NANOSEC;
 MY_TIMER_INFO pfs_timer_info;
 

=== modified file 'vio/viosocket.c'
--- a/vio/viosocket.c	2011-04-08 10:23:36 +0000
+++ b/vio/viosocket.c	2011-04-29 21:48:23 +0000
@@ -22,6 +22,10 @@
 
 #include "vio_priv.h"
 
+#ifdef FIONREAD_IN_SYS_FILIO
+# include <sys/filio.h>
+#endif
+
 int vio_errno(Vio *vio __attribute__((unused)))
 {
   return socket_errno;		/* On Win32 this mapped to WSAGetLastError() */
@@ -583,13 +587,13 @@ static my_bool socket_poll_read(my_socke
 
 static my_bool socket_peek_read(Vio *vio, uint *bytes)
 {
-#ifdef __WIN__
+#if defined(_WIN32)
   int len;
   if (ioctlsocket(vio->sd, FIONREAD, &len))
     return TRUE;
   *bytes= len;
   return FALSE;
-#elif FIONREAD_IN_SYS_IOCTL
+#elif defined(FIONREAD_IN_SYS_IOCTL) || defined(FIONREAD_IN_SYS_FILIO)
   int len;
   if (ioctl(vio->sd, FIONREAD, &len) < 0)
     return TRUE;

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (alexander.barkov:3335 to 3363) WL#5787Alexander Barkov4 May