List:Commits« Previous MessageNext Message »
From:Christopher Powers Date:June 6 2011 8:43pm
Subject:bzr push into mysql-trunk branch (chris.powers:3301 to 3306)
View as plain text  
 3306 Christopher Powers	2011-06-06
      merge with mysql-trunk

    modified:
      storage/perfschema/pfs.cc
      storage/perfschema/pfs_column_types.h
      storage/perfschema/table_events_waits.cc
 3305 Christopher Powers	2011-06-06
      merge with mysql-trunk

    modified:
      include/mysql/psi/psi_abi_v1.h.pp
      include/mysql/psi/psi_abi_v2.h.pp
      vio/viosocket.c
 3304 cpowers	2011-06-06
      merge with mysql-trunk

    modified:
      vio/vio.c
      vio/viopipe.c
      vio/vioshm.c
      vio/viossl.c
 3303 cpowers	2011-06-06 [merge]
      merge with mysql-trunk

    added:
      extra/yassl/include/openssl/transport_types.h
      mysql-test/suite/innodb/r/innodb_index_large_prefix.result
      mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result
      mysql-test/suite/innodb/t/innodb_index_large_prefix.test
      mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test
      vio/viopipe.c
      vio/vioshm.c
    modified:
      cmake/install_layout.cmake
      cmake/os/Windows.cmake
      configure.cmake
      extra/yassl/include/openssl/ssl.h
      extra/yassl/include/socket_wrapper.hpp
      extra/yassl/src/handshake.cpp
      extra/yassl/src/socket_wrapper.cpp
      extra/yassl/src/ssl.cpp
      include/my_base.h
      include/my_global.h
      include/my_sys.h
      include/mysql.h.pp
      include/mysql_com.h
      mysql-test/extra/binlog_tests/binlog_cache_stat.test
      mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test
      mysql-test/include/mysqlhotcopy.inc
      mysql-test/include/plugin.defs
      mysql-test/mysql-test-run.pl
      mysql-test/r/innodb_mysql_lock.result
      mysql-test/r/innodb_mysql_sync.result
      mysql-test/r/myisam_debug.result
      mysql-test/r/query_cache_debug.result
      mysql-test/r/ssl.result
      mysql-test/r/wait_timeout.result
      mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result
      mysql-test/suite/binlog/r/binlog_row_cache_stat.result
      mysql-test/suite/binlog/r/binlog_stm_cache_stat.result
      mysql-test/suite/innodb/include/innodb_stats.inc
      mysql-test/suite/innodb/include/innodb_stats_bootstrap.inc
      mysql-test/suite/innodb/r/innodb-index.result
      mysql-test/suite/innodb/r/innodb_stats.result
      mysql-test/suite/innodb/r/innodb_stats_drop_locked.result
      mysql-test/suite/innodb/t/innodb-index.test
      mysql-test/suite/innodb/t/innodb_bug11933790.test
      mysql-test/suite/innodb/t/innodb_stats.test
      mysql-test/suite/innodb/t/innodb_stats_drop_locked.test
      mysql-test/suite/rpl/r/rpl_crash_safe_master.result
      mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result
      mysql-test/suite/rpl/t/rpl_crash_safe_master.test
      mysql-test/suite/sys_vars/r/all_vars.result
      mysql-test/t/innodb_mysql_lock.test
      mysql-test/t/innodb_mysql_sync.test
      mysql-test/t/myisam_debug.test
      mysql-test/t/query_cache_debug.test
      mysql-test/t/ssl.test
      mysql-test/t/wait_timeout.test
      mysql-test/t/xa.test
      mysys/my_handler_errors.h
      sql-common/client.c
      sql/binlog.cc
      sql/binlog.h
      sql/ha_partition.cc
      sql/ha_partition.h
      sql/handler.cc
      sql/handler.h
      sql/item_inetfunc.cc
      sql/log_event.cc
      sql/log_event.h
      sql/log_event_old.cc
      sql/opt_range.cc
      sql/password.c
      sql/rpl_injector.cc
      sql/share/errmsg-utf8.txt
      sql/sql_acl.cc
      sql/sql_cache.cc
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_insert.cc
      sql/sql_parse.cc
      sql/sql_table.cc
      storage/innobase/data/data0data.c
      storage/innobase/dict/dict0dict.c
      storage/innobase/dict/dict0mem.c
      storage/innobase/dict/dict0stats.c
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/handler/ha_innodb.h
      storage/innobase/handler/handler0alter.cc
      storage/innobase/include/db0err.h
      storage/innobase/include/dict0dict.h
      storage/innobase/include/dict0dict.ic
      storage/innobase/include/dict0mem.h
      storage/innobase/include/mtr0mtr.ic
      storage/innobase/include/rem0types.h
      storage/innobase/include/row0ext.h
      storage/innobase/include/row0ext.ic
      storage/innobase/mtr/mtr0mtr.c
      storage/innobase/page/page0zip.c
      storage/innobase/rem/rem0rec.c
      storage/innobase/row/row0ext.c
      storage/innobase/row/row0mysql.c
      storage/innobase/row/row0row.c
      storage/innobase/row/row0sel.c
      storage/innobase/row/row0upd.c
      storage/innobase/scripts/persistent_storage.sql
      storage/innobase/trx/trx0rec.c
      storage/innobase/ut/ut0ut.c
      tests/mysql_client_test.c
      vio/CMakeLists.txt
      vio/vio.c
      vio/vio_priv.h
      vio/viosocket.c
 3302 cpowers	2011-06-06
      Merge with mysql-trunk

    modified:
      include/mysql/psi/psi.h
      include/violite.h
      sql/net_serv.cc
      vio/vio.c
      vio/viosocket.c
      vio/viossl.c
 3301 cpowers	2011-05-27
      merge mysql-trunk

    modified:
      sql/sql_class.cc
=== modified file 'cmake/install_layout.cmake'
--- a/cmake/install_layout.cmake	2010-12-16 18:18:20 +0000
+++ b/cmake/install_layout.cmake	2011-06-01 13:22:30 +0000
@@ -99,6 +99,13 @@ IF(UNIX)
 ENDIF()
 
 #
+# plugin_tests's value should not be used by imported plugins,
+# just use if(INSTALL_PLUGINTESTDIR).
+# The plugin must set its own install path for tests
+#
+FILE(GLOB plugin_tests ${CMAKE_SOURCE_DIR}/plugin/*/tests)
+
+#
 # STANDALONE layout
 #
 SET(INSTALL_BINDIR_STANDALONE           "bin")
@@ -122,6 +129,7 @@ SET(INSTALL_SQLBENCHDIR_STANDALONE
 SET(INSTALL_SUPPORTFILESDIR_STANDALONE  "support-files")
 #
 SET(INSTALL_MYSQLDATADIR_STANDALONE     "data")
+SET(INSTALL_PLUGINTESTDIR_STANDALONE    ${plugin_tests})
 
 #
 # RPM layout
@@ -152,6 +160,7 @@ SET(INSTALL_SQLBENCHDIR_RPM
 SET(INSTALL_SUPPORTFILESDIR_RPM         "share/mysql")
 #
 SET(INSTALL_MYSQLDATADIR_RPM            "/var/lib/mysql")
+SET(INSTALL_PLUGINTESTDIR_RPM           ${plugin_tests})
 
 #
 # DEB layout
@@ -177,6 +186,7 @@ SET(INSTALL_SQLBENCHDIR_DEB
 SET(INSTALL_SUPPORTFILESDIR_DEB         "support-files")
 #
 SET(INSTALL_MYSQLDATADIR_DEB            "data")
+SET(INSTALL_PLUGINTESTDIR_DEB           ${plugin_tests})
 
 #
 # SVR4 layout
@@ -202,6 +212,7 @@ SET(INSTALL_SQLBENCHDIR_SVR4
 SET(INSTALL_SUPPORTFILESDIR_SVR4        "support-files")
 #
 SET(INSTALL_MYSQLDATADIR_SVR4           "/var/lib/mysql")
+SET(INSTALL_PLUGINTESTDIR_SVR4          ${plugin_tests})
 
 
 # Clear cached variables if install layout was changed
@@ -216,7 +227,7 @@ SET(OLD_INSTALL_LAYOUT ${INSTALL_LAYOUT}
 # will be defined  as ${INSTALL_BINDIR_STANDALONE} by default if STANDALONE
 # layout is chosen)
 FOREACH(var BIN SBIN LIB MYSQLSHARE SHARE PLUGIN INCLUDE SCRIPT DOC MAN
-  INFO MYSQLTEST SQLBENCH DOCREADME SUPPORTFILES MYSQLDATA)
+  INFO MYSQLTEST SQLBENCH DOCREADME SUPPORTFILES MYSQLDATA PLUGINTEST)
   SET(INSTALL_${var}DIR  ${INSTALL_${var}DIR_${INSTALL_LAYOUT}}
   CACHE STRING "${var} installation directory" ${FORCE})
   MARK_AS_ADVANCED(INSTALL_${var}DIR)

=== modified file 'cmake/os/Windows.cmake'
--- a/cmake/os/Windows.cmake	2011-04-14 08:09:49 +0000
+++ b/cmake/os/Windows.cmake	2011-05-31 13:52:09 +0000
@@ -121,9 +121,6 @@ LINK_LIBRARIES(ws2_32)
 # ..also for tests
 SET(CMAKE_REQUIRED_LIBRARIES ws2_32)
 
-# System checks
-SET(SIGNAL_WITH_VIO_CLOSE 1) # Something that runtime team needs
-
 # IPv6 constants appeared in Vista SDK first. We need to define them in any case if they are 
 # not in headers, to handle dual mode sockets correctly.
 CHECK_SYMBOL_EXISTS(IPPROTO_IPV6 "winsock2.h" HAVE_IPPROTO_IPV6)

=== modified file 'configure.cmake'
--- a/configure.cmake	2011-05-26 15:20:09 +0000
+++ b/configure.cmake	2011-05-31 13:52:09 +0000
@@ -52,6 +52,10 @@ IF(NOT SYSTEM_TYPE)
   ENDIF()
 ENDIF()
 
+# As a consequence of ALARMs no longer being used, thread
+# notification for KILL must close the socket to wake up
+# other threads.
+SET(SIGNAL_WITH_VIO_CLOSE 1)
 
 # Always enable -Wall for gnu C/C++
 IF(CMAKE_COMPILER_IS_GNUCXX)
@@ -914,52 +918,6 @@ CHECK_CXX_SOURCE_COMPILES("
   "
   HAVE_SOLARIS_STYLE_GETHOST)
 
-# Use of ALARMs to wakeup on timeout on sockets
-#
-# This feature makes use of a mutex and is a scalability hog we
-# try to avoid using. However we need support for SO_SNDTIMEO and
-# SO_RCVTIMEO socket options for this to work. So we will check
-# if this feature is supported by a simple TRY_RUN macro. However
-# on some OS's there is support for setting those variables but
-# they are silently ignored. For those OS's we will not attempt
-# to use SO_SNDTIMEO and SO_RCVTIMEO even if it is said to work.
-# See Bug#29093 for the problem with SO_SND/RCVTIMEO on HP/UX.
-# To use alarm is simple, simply avoid setting anything.
-
-IF(WIN32)
-  SET(HAVE_SOCKET_TIMEOUT 1)
-ELSEIF(CMAKE_SYSTEM MATCHES "HP-UX")
-  SET(HAVE_SOCKET_TIMEOUT 0)
-ELSEIF(CMAKE_CROSSCOMPILING)
-  SET(HAVE_SOCKET_TIMEOUT 0)
-ELSE()
-SET(CMAKE_REQUIRED_LIBRARIES ${LIBNSL} ${LIBSOCKET}) 
-CHECK_C_SOURCE_RUNS(
-"
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- 
- int main()
- {    
-   int fd = socket(AF_INET, SOCK_STREAM, 0);
-   struct timeval tv;
-   int ret= 0;
-   tv.tv_sec= 2;
-   tv.tv_usec= 0;
-   ret|= setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
-   ret|= setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
-   return !!ret;
- }
-" HAVE_SOCKET_TIMEOUT)
-ENDIF()
-
-SET(NO_ALARM "${HAVE_SOCKET_TIMEOUT}" CACHE BOOL 
-   "No need to use alarm to implement socket timeout")
-SET(SIGNAL_WITH_VIO_CLOSE "${HAVE_SOCKET_TIMEOUT}")
-MARK_AS_ADVANCED(NO_ALARM)
-
-
 IF(CMAKE_COMPILER_IS_GNUCXX)
 IF(WITH_ATOMIC_OPS STREQUAL "up")
   SET(MY_ATOMIC_MODE_DUMMY 1 CACHE BOOL "Assume single-CPU mode, no concurrency")

=== modified file 'extra/yassl/include/openssl/ssl.h'
--- a/extra/yassl/include/openssl/ssl.h	2011-03-29 08:01:07 +0000
+++ b/extra/yassl/include/openssl/ssl.h	2011-05-31 13:52:09 +0000
@@ -539,13 +539,23 @@ void MD5_Final(unsigned char*, MD5_CTX*)
 #define SSL_DEFAULT_CIPHER_LIST ""   /* default all */
 
 
-/* yaSSL adds */
+/* yaSSL extensions */
 int SSL_set_compression(SSL*);   /* turn on yaSSL zlib compression */
 char *yaSSL_ASN1_TIME_to_string(ASN1_TIME *time, char *buf, size_t len);
 
+#include "transport_types.h"
 
+/*
+  Set functions for yaSSL to use in order to send and receive data.
 
+  These hooks are offered in order to enable non-blocking I/O. If
+  not set, yaSSL defaults to using send() and recv().
 
+  @todo Remove hooks and accompanying code when yaSSL is fixed.
+*/
+void yaSSL_transport_set_ptr(SSL *, void *);
+void yaSSL_transport_set_recv_function(SSL *, yaSSL_recv_func_t);
+void yaSSL_transport_set_send_function(SSL *, yaSSL_send_func_t);
 
 #if defined(__cplusplus) && !defined(YASSL_MYSQL_COMPATIBLE)
 }      /* namespace  */

=== added file 'extra/yassl/include/openssl/transport_types.h'
--- a/extra/yassl/include/openssl/transport_types.h	1970-01-01 00:00:00 +0000
+++ b/extra/yassl/include/openssl/transport_types.h	2011-05-31 13:52:09 +0000
@@ -0,0 +1,8 @@
+#ifndef yaSSL_transport_types_h__
+#define yaSSL_transport_types_h__
+
+/* Type of transport functions used for sending and receiving data. */
+typedef long (*yaSSL_recv_func_t) (void *, void *, size_t);
+typedef long (*yaSSL_send_func_t) (void *, const void *, size_t);
+
+#endif

=== modified file 'extra/yassl/include/socket_wrapper.hpp'
--- a/extra/yassl/include/socket_wrapper.hpp	2007-03-28 16:47:51 +0000
+++ b/extra/yassl/include/socket_wrapper.hpp	2011-05-31 13:52:09 +0000
@@ -55,7 +55,9 @@ typedef unsigned int uint;
     const int SOCKET_ERROR = -1;
 #endif
 
-
+  extern "C" {
+    #include "openssl/transport_types.h"
+  }
 
 typedef unsigned char byte;
 
@@ -65,6 +67,9 @@ class Socket {
     socket_t socket_;                    // underlying socket descriptor
     bool     wouldBlock_;                // if non-blocking data, for last read 
     bool     nonBlocking_;               // is option set
+    void     *ptr_;                      // Argument to transport function
+    yaSSL_send_func_t send_func_;        // Function to send data
+    yaSSL_recv_func_t recv_func_;        // Function to receive data
 public:
     explicit Socket(socket_t s = INVALID_SOCKET);
     ~Socket();
@@ -73,10 +78,13 @@ public:
     uint     get_ready() const;
     socket_t get_fd()    const;
 
-    uint send(const byte* buf, unsigned int len, int flags = 0) const;
-    uint receive(byte* buf, unsigned int len, int flags = 0);
+    void set_transport_ptr(void *ptr);
+    void set_transport_recv_function(yaSSL_recv_func_t recv_func);
+    void set_transport_send_function(yaSSL_send_func_t send_func);
+
+    uint send(const byte* buf, unsigned int len) const;
+    uint receive(byte* buf, unsigned int len);
 
-    bool wait();
     bool WouldBlock() const;
     bool IsNonBlocking() const;
 

=== modified file 'extra/yassl/src/handshake.cpp'
--- a/extra/yassl/src/handshake.cpp	2009-06-29 14:00:47 +0000
+++ b/extra/yassl/src/handshake.cpp	2011-05-31 13:52:09 +0000
@@ -704,13 +704,9 @@ void build_certHashes(SSL& ssl, Hashes&
 // do process input requests, return 0 is done, 1 is call again to complete
 int DoProcessReply(SSL& ssl)
 {
-    // wait for input if blocking
-    if (!ssl.useSocket().wait()) {
-      ssl.SetError(receive_error);
-        return 0;
-    }
     uint ready = ssl.getSocket().get_ready();
-    if (!ready) return 1; 
+    if (!ready)
+      ready= 64;
 
     // add buffered data if its there
     input_buffer* buffered = ssl.useBuffers().TakeRawInput();

=== modified file 'extra/yassl/src/socket_wrapper.cpp'
--- a/extra/yassl/src/socket_wrapper.cpp	2010-07-15 11:13:30 +0000
+++ b/extra/yassl/src/socket_wrapper.cpp	2011-05-31 13:52:09 +0000
@@ -52,11 +52,32 @@
 #endif // _WIN32
 
 
+namespace {
+
+
+extern "C" long system_recv(void *ptr, void *buf, size_t count)
+{
+  yaSSL::socket_t *socket = (yaSSL::socket_t *) ptr;
+  return ::recv(*socket, reinterpret_cast<char *>(buf), count, 0);
+}
+
+
+extern "C" long system_send(void *ptr, const void *buf, size_t count)
+{
+  yaSSL::socket_t *socket = (yaSSL::socket_t *) ptr;
+  return ::send(*socket, reinterpret_cast<const char *>(buf), count, 0);
+}
+
+
+}
+
+
 namespace yaSSL {
 
 
 Socket::Socket(socket_t s) 
-    : socket_(s), wouldBlock_(false), nonBlocking_(false)
+    : socket_(s), wouldBlock_(false), nonBlocking_(false),
+      ptr_(&socket_), send_func_(system_send), recv_func_(system_recv)
 {}
 
 
@@ -108,15 +129,32 @@ uint Socket::get_ready() const
     return ready;
 }
 
+void Socket::set_transport_ptr(void *ptr)
+{
+  ptr_ = ptr;
+}
+
+
+void Socket::set_transport_recv_function(yaSSL_recv_func_t recv_func)
+{
+  recv_func_ = recv_func;
+}
+
+
+void Socket::set_transport_send_function(yaSSL_send_func_t send_func)
+{
+  send_func_ = send_func;
+}
+
 
-uint Socket::send(const byte* buf, unsigned int sz, int flags) const
+uint Socket::send(const byte* buf, unsigned int sz) const
 {
     const byte* pos = buf;
     const byte* end = pos + sz;
 
+    /* Remove send()/recv() hooks once non-blocking send is implemented. */
     while (pos != end) {
-        int sent = ::send(socket_, reinterpret_cast<const char *>(pos),
-                          static_cast<int>(end - pos), flags);
+        int sent = send_func_(ptr_, pos, static_cast<int>(end - pos));
 
     if (sent == -1)
         return 0;
@@ -128,11 +166,11 @@ uint Socket::send(const byte* buf, unsig
 }
 
 
-uint Socket::receive(byte* buf, unsigned int sz, int flags)
+uint Socket::receive(byte* buf, unsigned int sz)
 {
     wouldBlock_ = false;
 
-    int recvd = ::recv(socket_, reinterpret_cast<char *>(buf), sz, flags);
+    int recvd = recv_func_(ptr_, buf, sz);
 
     // idea to seperate error from would block by arnetheduck@stripped
     if (recvd == -1) {
@@ -150,14 +188,6 @@ uint Socket::receive(byte* buf, unsigned
 }
 
 
-// wait if blocking for input, return false for error
-bool Socket::wait()
-{
-    byte b;
-    return receive(&b, 1, MSG_PEEK) != static_cast<uint>(-1);
-}
-
-
 void Socket::shutDown(int how)
 {
     shutdown(socket_, how);

=== modified file 'extra/yassl/src/ssl.cpp'
--- a/extra/yassl/src/ssl.cpp	2011-03-29 12:52:02 +0000
+++ b/extra/yassl/src/ssl.cpp	2011-05-31 13:52:09 +0000
@@ -1683,8 +1683,22 @@ unsigned long ERR_get_error()
     }
 
 
+    void yaSSL_transport_set_ptr(SSL *ssl, void *ptr)
+    {
+      ssl->useSocket().set_transport_ptr(ptr);
+    }
+
 
+    void yaSSL_transport_set_recv_function(SSL *ssl, yaSSL_recv_func_t func)
+    {
+      ssl->useSocket().set_transport_recv_function(func);
+    }
 
 
+    void yaSSL_transport_set_send_function(SSL *ssl, yaSSL_send_func_t func)
+    {
+      ssl->useSocket().set_transport_send_function(func);
+    }
+
 } // extern "C"
 } // namespace

=== modified file 'include/my_base.h'
--- a/include/my_base.h	2011-02-02 22:02:29 +0000
+++ b/include/my_base.h	2011-05-31 09:30:59 +0000
@@ -447,7 +447,8 @@ enum ha_base_keytype {
 #define HA_ERR_TOO_MANY_CONCURRENT_TRXS 177 /*Too many active concurrent transactions */
 /* There's no explicitly listed partition in table for the given value */
 #define HA_ERR_NOT_IN_LOCK_PARTITIONS 178
-#define HA_ERR_LAST               178    /* Copy of last error nr */
+#define HA_ERR_INDEX_COL_TOO_LONG 179	 /* Index column length exceeds limit */
+#define HA_ERR_LAST               179    /* Copy of last error nr */
 
 /* Number of different errors */
 #define HA_ERR_ERRORS            (HA_ERR_LAST - HA_ERR_FIRST + 1)

=== modified file 'include/my_global.h'
--- a/include/my_global.h	2011-04-13 19:16:45 +0000
+++ b/include/my_global.h	2011-05-31 13:52:09 +0000
@@ -965,9 +965,10 @@ typedef ulong nesting_map;  /* Used for
 #define socket_errno	WSAGetLastError()
 #define SOCKET_EINTR	WSAEINTR
 #define SOCKET_EAGAIN	WSAEINPROGRESS
-#define SOCKET_ETIMEDOUT WSAETIMEDOUT
 #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
 #define SOCKET_EADDRINUSE WSAEADDRINUSE
+#define SOCKET_ETIMEDOUT WSAETIMEDOUT
+#define SOCKET_ECONNRESET WSAECONNRESET
 #define SOCKET_ENFILE	ENFILE
 #define SOCKET_EMFILE	EMFILE
 #else /* Unix */
@@ -975,9 +976,10 @@ typedef ulong nesting_map;  /* Used for
 #define closesocket(A)	close(A)
 #define SOCKET_EINTR	EINTR
 #define SOCKET_EAGAIN	EAGAIN
-#define SOCKET_ETIMEDOUT SOCKET_EINTR
 #define SOCKET_EWOULDBLOCK EWOULDBLOCK
 #define SOCKET_EADDRINUSE EADDRINUSE
+#define SOCKET_ETIMEDOUT ETIMEDOUT
+#define SOCKET_ECONNRESET ECONNRESET
 #define SOCKET_ENFILE	ENFILE
 #define SOCKET_EMFILE	EMFILE
 #endif

=== modified file 'include/my_sys.h'
--- a/include/my_sys.h	2011-05-21 09:30:35 +0000
+++ b/include/my_sys.h	2011-05-31 13:52:09 +0000
@@ -936,7 +936,6 @@ extern size_t escape_quotes_for_mysql(CH
 
 extern void thd_increment_bytes_sent(ulong length);
 extern void thd_increment_bytes_received(ulong length);
-extern void thd_increment_net_big_packet_count(ulong length);
 
 #ifdef __WIN__
 extern my_bool have_tcpip;		/* Is set if tcpip is used */

=== modified file 'include/mysql.h.pp'
--- a/include/mysql.h.pp	2011-05-06 13:46:57 +0000
+++ b/include/mysql.h.pp	2011-05-31 13:52:09 +0000
@@ -85,18 +85,15 @@ enum enum_mysql_set_option
 my_bool my_net_init(NET *net, Vio* vio);
 void my_net_local_init(NET *net);
 void net_end(NET *net);
-  void net_clear(NET *net, my_bool clear_buffer);
+void net_clear(NET *net, my_bool check_buffer);
 my_bool net_realloc(NET *net, size_t length);
 my_bool net_flush(NET *net);
 my_bool my_net_write(NET *net,const unsigned char *packet, size_t len);
 my_bool net_write_command(NET *net,unsigned char command,
      const unsigned char *header, size_t head_len,
      const unsigned char *packet, size_t len);
-int net_real_write(NET *net,const unsigned char *packet, size_t len);
+my_bool net_write_packet(NET *net, const unsigned char *packet, size_t length);
 unsigned long my_net_read(NET *net);
-struct sockaddr;
-int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen,
-        unsigned int timeout);
 struct rand_struct {
   unsigned long seed1,seed2,max_value;
   double max_value_dbl;

=== modified file 'include/mysql/psi/psi.h'
--- a/include/mysql/psi/psi.h	2011-04-28 00:15:11 +0000
+++ b/include/mysql/psi/psi.h	2011-06-06 19:16:24 +0000
@@ -410,7 +410,9 @@ enum PSI_socket_operation
   /** Socket status, as in @c sockatmark() and @c isfdtype(). */
   PSI_SOCKET_STAT= 12,
   /** Socket shutdown, as in @c shutdown(). */
-  PSI_SOCKET_SHUTDOWN= 13
+  PSI_SOCKET_SHUTDOWN= 13,
+  /** Socket select, as in @c select() and @c poll(). */
+  PSI_SOCKET_SELECT= 14
 };
 
 /**

=== modified file 'include/mysql/psi/psi_abi_v1.h.pp'
--- a/include/mysql/psi/psi_abi_v1.h.pp	2011-03-29 00:46:15 +0000
+++ b/include/mysql/psi/psi_abi_v1.h.pp	2011-06-06 20:16:03 +0000
@@ -89,7 +89,8 @@ enum PSI_socket_operation
   PSI_SOCKET_SEEK= 10,
   PSI_SOCKET_OPT= 11,
   PSI_SOCKET_STAT= 12,
-  PSI_SOCKET_SHUTDOWN= 13
+  PSI_SOCKET_SHUTDOWN= 13,
+  PSI_SOCKET_SELECT= 14
 };
 typedef unsigned int PSI_mutex_key;
 typedef unsigned int PSI_rwlock_key;

=== modified file 'include/mysql/psi/psi_abi_v2.h.pp'
--- a/include/mysql/psi/psi_abi_v2.h.pp	2011-04-22 03:07:02 +0000
+++ b/include/mysql/psi/psi_abi_v2.h.pp	2011-06-06 20:16:03 +0000
@@ -89,7 +89,8 @@ enum PSI_socket_operation
   PSI_SOCKET_SEEK= 10,
   PSI_SOCKET_OPT= 11,
   PSI_SOCKET_STAT= 12,
-  PSI_SOCKET_SHUTDOWN= 13
+  PSI_SOCKET_SHUTDOWN= 13,
+  PSI_SOCKET_SELECT= 14
 };
 typedef unsigned int PSI_mutex_key;
 typedef unsigned int PSI_rwlock_key;

=== modified file 'include/mysql_com.h'
--- a/include/mysql_com.h	2011-03-25 13:28:19 +0000
+++ b/include/mysql_com.h	2011-05-31 13:52:09 +0000
@@ -324,16 +324,6 @@ typedef struct st_net {
   /** Client library sqlstate buffer. Set along with the error message. */
   char sqlstate[SQLSTATE_LENGTH+1];
   void *extension;
-#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
-  /*
-    Controls whether a big packet should be skipped.
-
-    Initially set to FALSE by default. Unauthenticated sessions must have
-    this set to FALSE so that the server can't be tricked to read packets
-    indefinitely.
-  */
-  my_bool skip_big_packet;
-#endif
 } NET;
 
 
@@ -449,16 +439,16 @@ extern "C" {
 #endif
 
 my_bool	my_net_init(NET *net, Vio* vio);
-void	my_net_local_init(NET *net);
-void	net_end(NET *net);
-  void	net_clear(NET *net, my_bool clear_buffer);
+void my_net_local_init(NET *net);
+void net_end(NET *net);
+void net_clear(NET *net, my_bool check_buffer);
 my_bool net_realloc(NET *net, size_t length);
 my_bool	net_flush(NET *net);
 my_bool	my_net_write(NET *net,const unsigned char *packet, size_t len);
 my_bool	net_write_command(NET *net,unsigned char command,
 			  const unsigned char *header, size_t head_len,
 			  const unsigned char *packet, size_t len);
-int	net_real_write(NET *net,const unsigned char *packet, size_t len);
+my_bool net_write_packet(NET *net, const unsigned char *packet, size_t length);
 unsigned long my_net_read(NET *net);
 
 #ifdef _global_h
@@ -466,10 +456,6 @@ void my_net_set_write_timeout(NET *net,
 void my_net_set_read_timeout(NET *net, uint timeout);
 #endif
 
-struct sockaddr;
-int my_connect(my_socket s, const struct sockaddr *name, unsigned int namelen,
-	       unsigned int timeout);
-
 struct rand_struct {
   unsigned long seed1,seed2,max_value;
   double max_value_dbl;

=== modified file 'include/violite.h'
--- a/include/violite.h	2011-05-27 15:46:36 +0000
+++ b/include/violite.h	2011-06-06 19:24:25 +0000
@@ -11,7 +11,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
 /*
  * Vio Lite.
@@ -19,7 +19,7 @@
  */
 
 #ifndef vio_violite_h_
-#define vio_violite_h_
+#define	vio_violite_h_
 
 #include "my_net.h"   /* needed because of struct in_addr */
 #include <mysql/psi/mysql_socket.h>
@@ -27,7 +27,7 @@
 
 /* Simple vio interface in C;  The functions are implemented in violite.c */
 
-#ifdef __cplusplus
+#ifdef	__cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
@@ -41,6 +41,16 @@ enum enum_vio_type
   VIO_TYPE_SSL, VIO_TYPE_SHARED_MEMORY
 };
 
+/**
+  VIO I/O events.
+*/
+enum enum_vio_io_event
+{
+  VIO_IO_EVENT_READ,
+  VIO_IO_EVENT_WRITE,
+  VIO_IO_EVENT_CONNECT
+};
+
 #define VIO_LOCALHOST 1                         /* a localhost connection */
 #define VIO_BUFFERED_READ 2                     /* use buffered read */
 #define VIO_READ_BUFFER_SIZE 16384              /* size of read buffer */
@@ -60,36 +70,42 @@ Vio* vio_new_win32shared_memory(HANDLE h
 #define HANDLE void *
 #endif /* __WIN__ */
 
-void vio_delete(Vio *vio);
-int vio_close(Vio *vio);
-void    vio_reset(Vio *vio, enum enum_vio_type type,
-                  my_socket sd, HANDLE hPipe, uint flags);
-size_t vio_read(Vio *vio, uchar * buf, size_t size);
-size_t vio_read_buff(Vio *vio, uchar * buf, size_t size);
-size_t vio_write(Vio *vio, const uchar * buf, size_t size);
-int vio_blocking(Vio *vio, my_bool onoff, my_bool *old_mode);
-my_bool vio_is_blocking(Vio *vio);
+void	vio_delete(Vio* vio);
+int	vio_close(Vio* vio);
+my_bool vio_reset(Vio* vio, enum enum_vio_type type,
+                  my_socket sd, void *ssl, uint flags);
+size_t	vio_read(Vio *vio, uchar *	buf, size_t size);
+size_t  vio_read_buff(Vio *vio, uchar * buf, size_t size);
+size_t	vio_write(Vio *vio, const uchar * buf, size_t size);
 /* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible */
-int vio_fastsend(Vio *vio);
+int	vio_fastsend(Vio *vio);
 /* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible */
-int vio_keepalive(Vio *vio, my_bool onoff);
+int	vio_keepalive(Vio *vio, my_bool	onoff);
 /* Whenever we should retry the last read/write operation. */
-my_bool vio_should_retry(Vio *vio);
+my_bool	vio_should_retry(Vio *vio);
 /* Check that operation was timed out */
-my_bool vio_was_interrupted(Vio *vio);
+my_bool vio_was_timeout(Vio *vio);
 /* Short text description of the socket for those, who are curious.. */
 const char* vio_description(Vio *vio);
 /* Return the type of the connection */
-enum enum_vio_type vio_type(Vio *vio);
+enum enum_vio_type vio_type(Vio* vio);
 /* Return last error number */
-int vio_errno(Vio *vio);
+int	vio_errno(Vio*vio);
 /* Get socket number */
 my_socket vio_getfd(Vio *vio);
 /* Remote peer's address and name in text form */
 my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen);
-my_bool vio_poll_read(Vio *vio, uint timeout);
+/* Wait for an I/O event notification. */
+int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout);
 my_bool vio_is_connected(Vio *vio);
+#ifndef DBUG_OFF
 ssize_t vio_pending(Vio *vio);
+#endif
+/* Set timeout for a network operation. */
+int vio_timeout(Vio *vio, uint which, int timeout_sec);
+/* Connect to a peer. */
+my_bool vio_socket_connect(Vio *vio, struct sockaddr *addr, socklen_t len,
+                           int timeout);
 
 my_bool vio_get_normalized_ip_string(const struct sockaddr *addr, int addr_length,
                                      char *ip_string, size_t ip_string_size);
@@ -152,30 +168,23 @@ void free_vio_ssl_acceptor_fd(struct st_
 
 void vio_end(void);
 
-#ifdef __cplusplus
+#ifdef	__cplusplus
 }
 #endif
 
 #if !defined(DONT_MAP_VIO)
-#define vio_delete(vio)            (vio)->viodelete(vio)
-#define vio_errno(vio)             (vio)->vioerrno(vio)
-#define vio_read(vio, buf, size)   ((vio)->read)(vio,buf,size)
-#define vio_write(vio, buf, size)  ((vio)->write)(vio, buf, size)
-#define vio_blocking(vio, set_blocking_mode, old_mode)\
-                           (vio)->vioblocking(vio, set_blocking_mode, old_mode)
-#define vio_is_blocking(vio)       (vio)->is_blocking(vio)
-#define vio_fastsend(vio)          (vio)->fastsend(vio)
-#define vio_keepalive(vio, set_keep_alive)\
-                                   (vio)->viokeepalive(vio, set_keep_alive)
-#define vio_should_retry(vio)      (vio)->should_retry(vio)
-#define vio_was_interrupted(vio)   (vio)->was_interrupted(vio)
-#define vio_close(vio)             ((vio)->vioclose)(vio)
-#define vio_peer_addr(vio, buf, prt, buflen)\
-                                   (vio)->peer_addr(vio, buf, prt, buflen)
-#define vio_timeout(vio, which, seconds) (vio)->timeout(vio, which, seconds)
-#define vio_poll_read(vio, timeout)      (vio)->poll_read(vio, timeout)
-#define vio_is_connected(vio)            (vio)->is_connected(vio)
-#define vio_getfd(vio)                   (vio)->viogetfd(vio)
+#define vio_delete(vio) 			(vio)->viodelete(vio)
+#define vio_errno(vio)	 			(vio)->vioerrno(vio)
+#define vio_read(vio, buf, size)                ((vio)->read)(vio,buf,size)
+#define vio_write(vio, buf, size)               ((vio)->write)(vio, buf, size)
+#define vio_fastsend(vio)			(vio)->fastsend(vio)
+#define vio_keepalive(vio, set_keep_alive)	(vio)->viokeepalive(vio, set_keep_alive)
+#define vio_should_retry(vio) 			(vio)->should_retry(vio)
+#define vio_was_timeout(vio)                    (vio)->was_timeout(vio)
+#define vio_close(vio)				((vio)->vioclose)(vio)
+#define vio_peer_addr(vio, buf, prt, buflen)	(vio)->peer_addr(vio, buf, prt, buflen)
+#define vio_io_wait(vio, event, timeout)        (vio)->io_wait(vio, event, timeout)
+#define vio_is_connected(vio)                   (vio)->is_connected(vio)
 #endif /* !defined(DONT_MAP_VIO) */
 
 /* This enumerator is used in parser - should be always visible */
@@ -194,54 +203,53 @@ enum SSL_type
 struct st_vio
 {
   MYSQL_SOCKET  mysql_socket;     /* Instrumented socket */
-  HANDLE hPipe;
-  my_bool localhost;              /* Are we from localhost? */
-  int fcntl_mode;                 /* Buffered fcntl(sd,F_GETFL) */
-  struct sockaddr_storage local;  /* Local internet address */
-  struct sockaddr_storage remote; /* Remote internet address */
-  int addrLen;                    /* Length of remote address */
-  enum enum_vio_type type;        /* Type of connection */
-  char desc[30];                  /* String description */
-  char *read_buffer;              /* buffer for vio_read_buff */
-  char *read_pos;                 /* start of unfetched data in the read buffer */
-  char *read_end;                 /* end of unfetched data */
-  /* Function pointers. They are similar for socket/SSL/whatever */
+  my_bool		localhost;	/* Are we from localhost? */
+  struct sockaddr_storage	local;		/* Local internet address */
+  struct sockaddr_storage	remote;		/* Remote internet address */
+  int addrLen;                          /* Length of remote address */
+  enum enum_vio_type	type;		/* Type of connection */
+  char			desc[30];	/* String description */
+  char                  *read_buffer;   /* buffer for vio_read_buff */
+  char                  *read_pos;      /* start of unfetched data in the
+                                           read buffer */
+  char                  *read_end;      /* end of unfetched data */
+  int                   read_timeout;   /* Timeout value (ms) for read ops. */
+  int                   write_timeout;  /* Timeout value (ms) for write ops. */
+  /* function pointers. They are similar for socket/SSL/whatever */
   void    (*viodelete)(Vio*);
   int     (*vioerrno)(Vio*);
   size_t  (*read)(Vio*, uchar *, size_t);
   size_t  (*write)(Vio*, const uchar *, size_t);
-  int     (*vioblocking)(Vio*, my_bool, my_bool *);
-  my_bool (*is_blocking)(Vio*);
+  int     (*timeout)(Vio*, uint, my_bool);
   int     (*viokeepalive)(Vio*, my_bool);
   int     (*fastsend)(Vio*);
   my_bool (*peer_addr)(Vio*, char *, uint16*, size_t);
   void    (*in_addr)(Vio*, struct sockaddr_storage*);
   my_bool (*should_retry)(Vio*);
-  my_bool (*was_interrupted)(Vio*);
+  my_bool (*was_timeout)(Vio*);
   int     (*vioclose)(Vio*);
-  void    (*timeout)(Vio*, unsigned int which, unsigned int timeout);
-  my_bool (*poll_read)(Vio *vio, uint timeout);
   my_bool (*is_connected)(Vio*);
   my_bool (*has_data) (Vio*);
+  int (*io_wait)(Vio*, enum enum_vio_io_event, int);
+  my_bool (*connect)(Vio*, struct sockaddr *, socklen_t, int);
   my_socket (*viogetfd)(Vio *);
+#ifdef _WIN32
+  OVERLAPPED overlapped;
+  HANDLE hPipe;
+#endif
 #ifdef HAVE_OPENSSL
-  void *ssl_arg;
+  void	  *ssl_arg;
 #endif
 #ifdef HAVE_SMEM
-  HANDLE handle_file_map;
-  char   *handle_map;
-  HANDLE event_server_wrote;
-  HANDLE event_server_read;
-  HANDLE event_client_wrote;
-  HANDLE event_client_read;
-  HANDLE event_conn_closed;
-  size_t shared_memory_remain;
-  char   *shared_memory_pos;
+  HANDLE  handle_file_map;
+  char    *handle_map;
+  HANDLE  event_server_wrote;
+  HANDLE  event_server_read;
+  HANDLE  event_client_wrote;
+  HANDLE  event_client_read;
+  HANDLE  event_conn_closed;
+  size_t  shared_memory_remain;
+  char    *shared_memory_pos;
 #endif /* HAVE_SMEM */
-#ifdef _WIN32
-  OVERLAPPED pipe_overlapped;
-  DWORD read_timeout_ms;
-  DWORD write_timeout_ms;
-#endif
 };
 #endif /* vio_violite_h_ */

=== modified file 'mysql-test/extra/binlog_tests/binlog_cache_stat.test'
--- a/mysql-test/extra/binlog_tests/binlog_cache_stat.test	2010-11-05 17:42:37 +0000
+++ b/mysql-test/extra/binlog_tests/binlog_cache_stat.test	2011-05-12 21:51:20 +0000
@@ -20,13 +20,13 @@ create table t2 (a int) engine=myisam;
 #
 --echo **** Preparing the enviroment to check commit and its effect on status variables.
 --echo **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 let $exp_cache= 0;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 0;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -39,7 +39,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 
 --echo **** Transactional changes which are long enough so they will be flushed to disk...
 --echo **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 let $1=2000;
 disable_query_log;
 begin;
@@ -54,7 +54,7 @@ let $exp_cache= 1;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -68,7 +68,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Transactional changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 commit;
@@ -76,7 +76,7 @@ let $exp_cache= 2;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -90,7 +90,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Non-Transactional changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 commit;
@@ -98,7 +98,7 @@ let $exp_cache= 2;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 1;
+let $exp_stmt_cache= 2;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -112,7 +112,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Mixed changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );
@@ -121,7 +121,7 @@ let $exp_cache= 3;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 2;
+let $exp_stmt_cache= 3;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -137,13 +137,13 @@ if (`SELECT $got_cache <> $exp_cache ||
 #
 --echo **** Preparing the enviroment to check abort and its effect on the status variables.
 --echo **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 let $exp_cache= 0;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 0;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -156,7 +156,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 
 --echo **** Transactional changes which are long enough so they will be flushed to disk...
 --echo **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 let $1=2000;
 disable_query_log;
 begin;
@@ -171,7 +171,7 @@ let $exp_cache= 1;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -185,7 +185,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Transactional changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 rollback;
@@ -193,7 +193,7 @@ let $exp_cache= 2;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -207,7 +207,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Non-Transactional changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 rollback;
@@ -215,7 +215,7 @@ let $exp_cache= 2;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 1;
+let $exp_stmt_cache= 2;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -229,7 +229,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Mixed changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );
@@ -238,7 +238,7 @@ let $exp_cache= 3;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 2;
+let $exp_stmt_cache= 3;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);

=== modified file 'mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test'
--- a/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test	2011-02-23 20:01:27 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test	2011-05-12 21:51:20 +0000
@@ -423,10 +423,6 @@ COMMIT;
 
 --connection slave
 --let $slave_sql_errno= 1197
-if (`SELECT @@binlog_format = 'ROW'`)
-{
-  --let $slave_sql_errno= 1534
-}
 source include/wait_for_slave_sql_error.inc;
 
 SELECT count(*) FROM t1;

=== modified file 'mysql-test/include/mysqlhotcopy.inc'
--- a/mysql-test/include/mysqlhotcopy.inc	2011-02-08 09:56:04 +0000
+++ b/mysql-test/include/mysqlhotcopy.inc	2011-05-31 13:52:09 +0000
@@ -107,7 +107,7 @@ DROP DATABASE hotcopy_save;
 --replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
 --list_files $MYSQLD_DATADIR/hotcopy_save
 --replace_result $MASTER_MYSOCK MASTER_MYSOCK
---error 9,11,2304
+--error 9,11,110,2304
 --exec $MYSQLHOTCOPY --quiet -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save
 --replace_result $MASTER_MYSOCK MASTER_MYSOCK
 --exec $MYSQLHOTCOPY --quiet --allowold -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save

=== modified file 'mysql-test/include/plugin.defs'
--- a/mysql-test/include/plugin.defs	2011-02-10 17:15:19 +0000
+++ b/mysql-test/include/plugin.defs	2011-05-30 13:55:44 +0000
@@ -39,4 +39,3 @@ ha_archive         storage/archive    AR
 ha_blackhole       storage/blackhole  BLACKHOLE_PLUGIN
 ha_federated       storage/federated  FEDERATED_PLUGIN
 mypluglib          plugin/fulltext    SIMPLE_PARSER
-thread_pool        plugin/thread_pool THREADPOOL_PLUGIN thread_pool,TP_THREAD_STATE,TP_THREAD_GROUP_STATE,TP_THREAD_GROUP_STATS

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2011-05-25 14:48:51 +0000
+++ b/mysql-test/mysql-test-run.pl	2011-05-30 14:00:14 +0000
@@ -449,6 +449,11 @@ sub main {
   #
   read_plugin_defs("include/plugin.defs");
 
+  # Also read from any plugin local plugin.defs
+  for (glob "$basedir/plugin/*/tests/mtr/plugin.defs") {
+    read_plugin_defs($_);
+  }
+
   # Simplify reference to semisync plugins
   $ENV{'SEMISYNC_PLUGIN_OPT'}= $ENV{'SEMISYNC_MASTER_PLUGIN_OPT'};
 

=== modified file 'mysql-test/r/innodb_mysql_lock.result'
--- a/mysql-test/r/innodb_mysql_lock.result	2011-05-10 10:55:34 +0000
+++ b/mysql-test/r/innodb_mysql_lock.result	2011-06-01 12:24:51 +0000
@@ -164,6 +164,8 @@ id	value
 SET lock_wait_timeout=1;
 ALTER TABLE t1 ADD INDEX idx(value);
 ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ALTER TABLE t1 ADD INDEX idx(value);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
 # Connection default
 SELECT * FROM t1;
 id	value

=== modified file 'mysql-test/r/innodb_mysql_sync.result'
--- a/mysql-test/r/innodb_mysql_sync.result	2011-04-13 18:43:08 +0000
+++ b/mysql-test/r/innodb_mysql_sync.result	2011-06-01 12:24:51 +0000
@@ -94,6 +94,95 @@ SET DEBUG_SYNC= 'RESET';
 # Bug#42230 during add index, cannot do queries on storage engines
 #           that implement add_index
 #
+DROP DATABASE IF EXISTS db1;
+DROP TABLE IF EXISTS t1;
+# Test 1: Secondary index, should not block reads (original test case).
+# Connection default
+CREATE DATABASE db1;
+CREATE TABLE db1.t1(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, value INT) engine=innodb;
+INSERT INTO db1.t1(value) VALUES (1), (2);
+SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
+# Sending:
+ALTER TABLE db1.t1 ADD INDEX(value);
+# Connection con1
+SET DEBUG_SYNC= "now WAIT_FOR manage";
+USE db1;
+SELECT * FROM t1;
+id	value
+1	1
+2	2
+SET DEBUG_SYNC= "now SIGNAL query";
+# Connection default
+# Reaping: ALTER TABLE db1.t1 ADD INDEX(value)
+DROP DATABASE db1;
+# Test 2: Primary index (implicit), should block reads.
+CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb;
+SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
+# Sending:
+ALTER TABLE t1 ADD UNIQUE INDEX(a);
+# Connection con1
+SET DEBUG_SYNC= "now WAIT_FOR manage";
+USE test;
+# Sending:
+SELECT * FROM t1;
+# Connection con2
+# Waiting for SELECT to be blocked by the metadata lock on t1
+SET DEBUG_SYNC= "now SIGNAL query";
+# Connection default
+# Reaping: ALTER TABLE t1 ADD UNIQUE INDEX(a)
+# Connection con1
+# Reaping: SELECT * FROM t1
+a	b
+# Test 3: Primary index (explicit), should block reads.
+# Connection default
+ALTER TABLE t1 DROP INDEX a;
+SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
+# Sending:
+ALTER TABLE t1 ADD PRIMARY KEY (a);
+# Connection con1
+SET DEBUG_SYNC= "now WAIT_FOR manage";
+# Sending:
+SELECT * FROM t1;
+# Connection con2
+# Waiting for SELECT to be blocked by the metadata lock on t1
+SET DEBUG_SYNC= "now SIGNAL query";
+# Connection default
+# Reaping: ALTER TABLE t1 ADD PRIMARY KEY (a)
+# Connection con1
+# Reaping: SELECT * FROM t1
+a	b
+# Test 4: Secondary unique index, should not block reads.
+# Connection default
+SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
+# Sending:
+ALTER TABLE t1 ADD UNIQUE (b);
+# Connection con1
+SET DEBUG_SYNC= "now WAIT_FOR manage";
+SELECT * FROM t1;
+a	b
+SET DEBUG_SYNC= "now SIGNAL query";
+# Connection default
+# Reaping: ALTER TABLE t1 ADD UNIQUE (b)
+SET DEBUG_SYNC= "RESET";
+DROP TABLE t1;
 #
-# DISABLED due to Bug#11815600
+# Bug#11853126 RE-ENABLE CONCURRENT READS WHILE CREATING SECONDARY INDEX
+#              IN INNODB
 #
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb;
+INSERT INTO t1 VALUES (1, 12345), (2, 23456);
+# Connection con1
+SET SESSION debug= "+d,alter_table_rollback_new_index";
+ALTER TABLE t1 ADD PRIMARY KEY(a);
+ERROR HY000: Unknown error
+SELECT * FROM t1;
+a	b
+1	12345
+2	23456
+# Connection default
+SELECT * FROM t1;
+a	b
+1	12345
+2	23456
+DROP TABLE t1;

=== modified file 'mysql-test/r/myisam_debug.result'
--- a/mysql-test/r/myisam_debug.result	2009-04-30 11:03:44 +0000
+++ b/mysql-test/r/myisam_debug.result	2011-05-31 13:52:09 +0000
@@ -37,3 +37,4 @@ CHECK TABLE t1;
 Table	Op	Msg_type	Msg_text
 test.t1	check	status	OK
 DROP TABLE t1,t2;
+ERROR HY000: 137 when fixing table

=== modified file 'mysql-test/r/query_cache_debug.result'
--- a/mysql-test/r/query_cache_debug.result	2010-10-08 12:16:20 +0000
+++ b/mysql-test/r/query_cache_debug.result	2011-05-30 15:17:22 +0000
@@ -153,7 +153,9 @@ SET DEBUG_SYNC="now WAIT_FOR parked1_2";
 ** until a broadcast signal reaches them causing both threads to 
 ** come alive and check the condition.
 SET DEBUG_SYNC="now SIGNAL go2";
+** Wait for thd2 to receive the signal
 SET DEBUG_SYNC="now SIGNAL go3";
+** Wait for thd3 to receive the signal
 **
 ** Finally signal the DELETE statement on THD1 one last time.
 ** The stmt will complete the query cache invalidation and return 

=== modified file 'mysql-test/r/ssl.result'
--- a/mysql-test/r/ssl.result	2011-03-29 08:01:07 +0000
+++ b/mysql-test/r/ssl.result	2011-05-31 13:52:09 +0000
@@ -2163,3 +2163,13 @@ drop table t1;
 SHOW STATUS LIKE 'Ssl_cipher';
 Variable_name	Value
 Ssl_cipher	DHE-RSA-AES256-SHA
+#
+# Bug#54790: Use of non-blocking mode for sockets limits performance
+#
+# Open ssl_con and set a timeout.
+SET @@SESSION.wait_timeout = 2;
+# Wait for ssl_con to be disconnected.
+# Check that ssl_con has been disconnected.
+# CR_SERVER_LOST, CR_SERVER_GONE_ERROR
+SELECT 1;
+Got one of the listed errors

=== modified file 'mysql-test/r/wait_timeout.result'
--- a/mysql-test/r/wait_timeout.result	2009-01-23 17:19:09 +0000
+++ b/mysql-test/r/wait_timeout.result	2011-05-31 13:52:09 +0000
@@ -31,3 +31,26 @@ SELECT 3;
 3
 SET @@global.wait_timeout= <start_value>;
 disconnection con1;
+#
+# Bug#54790: Use of non-blocking mode for sockets limits performance
+#
+#
+# Test UNIX domain sockets timeout.
+#
+# Open con1 and set a timeout.
+SET @@SESSION.wait_timeout = 2;
+# Wait for con1 to be disconnected.
+# Check that con1 has been disconnected.
+# CR_SERVER_LOST, CR_SERVER_GONE_ERROR
+SELECT 1;
+Got one of the listed errors
+#
+# Test TCP/IP sockets timeout.
+#
+# Open con1 and set a timeout.
+SET @@SESSION.wait_timeout = 2;
+# Wait for con1 to be disconnected.
+# Check that con1 has been disconnected.
+# CR_SERVER_LOST, CR_SERVER_GONE_ERROR
+SELECT 1;
+Got one of the listed errors

=== modified file 'mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result'
--- a/mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result	2010-11-05 17:42:37 +0000
+++ b/mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result	2011-05-12 21:51:20 +0000
@@ -3,51 +3,51 @@ create table t1 (a int) engine=innodb;
 create table t2 (a int) engine=myisam;
 **** Preparing the enviroment to check commit and its effect on status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 commit;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 commit;
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );
 commit;
 **** Preparing the enviroment to check abort and its effect on the status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 rollback;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 rollback;
@@ -56,7 +56,7 @@ Warning	1196	Some non-transactional chan
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );

=== modified file 'mysql-test/suite/binlog/r/binlog_row_cache_stat.result'
--- a/mysql-test/suite/binlog/r/binlog_row_cache_stat.result	2010-11-05 17:42:37 +0000
+++ b/mysql-test/suite/binlog/r/binlog_row_cache_stat.result	2011-05-12 21:51:20 +0000
@@ -3,51 +3,51 @@ create table t1 (a int) engine=innodb;
 create table t2 (a int) engine=myisam;
 **** Preparing the enviroment to check commit and its effect on status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 commit;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 commit;
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );
 commit;
 **** Preparing the enviroment to check abort and its effect on the status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 rollback;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 rollback;
@@ -56,7 +56,7 @@ Warning	1196	Some non-transactional chan
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );

=== modified file 'mysql-test/suite/binlog/r/binlog_stm_cache_stat.result'
--- a/mysql-test/suite/binlog/r/binlog_stm_cache_stat.result	2010-11-05 17:42:37 +0000
+++ b/mysql-test/suite/binlog/r/binlog_stm_cache_stat.result	2011-05-12 21:51:20 +0000
@@ -3,51 +3,51 @@ create table t1 (a int) engine=innodb;
 create table t2 (a int) engine=myisam;
 **** Preparing the enviroment to check commit and its effect on status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 commit;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 commit;
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );
 commit;
 **** Preparing the enviroment to check abort and its effect on the status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 rollback;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 rollback;
@@ -56,7 +56,7 @@ Warning	1196	Some non-transactional chan
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );

=== modified file 'mysql-test/suite/innodb/include/innodb_stats.inc'
--- a/mysql-test/suite/innodb/include/innodb_stats.inc	2011-03-18 12:49:38 +0000
+++ b/mysql-test/suite/innodb/include/innodb_stats.inc	2011-05-30 13:56:01 +0000
@@ -9,7 +9,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND

=== modified file 'mysql-test/suite/innodb/include/innodb_stats_bootstrap.inc'
--- a/mysql-test/suite/innodb/include/innodb_stats_bootstrap.inc	2011-03-14 14:44:14 +0000
+++ b/mysql-test/suite/innodb/include/innodb_stats_bootstrap.inc	2011-05-30 13:56:01 +0000
@@ -1,9 +1,8 @@
 -- disable_warnings
 -- disable_query_log
-DROP DATABASE IF EXISTS innodb;
-CREATE DATABASE innodb;
 
-CREATE TABLE innodb.table_stats (
+DROP TABLE IF EXISTS mysql.innodb_table_stats;
+CREATE TABLE mysql.innodb_table_stats (
 	database_name			VARCHAR(64) NOT NULL,
 	table_name			VARCHAR(64) NOT NULL,
 	stats_timestamp			TIMESTAMP NOT NULL,
@@ -13,7 +12,8 @@ CREATE TABLE innodb.table_stats (
 	PRIMARY KEY (database_name, table_name)
 ) ENGINE=INNODB DEFAULT CHARSET=utf8;
 
-CREATE TABLE innodb.index_stats (
+DROP TABLE IF EXISTS mysql.innodb_index_stats;
+CREATE TABLE mysql.innodb_index_stats (
 	database_name			VARCHAR(64) NOT NULL,
 	table_name			VARCHAR(64) NOT NULL,
 	index_name			VARCHAR(64) NOT NULL,
@@ -28,7 +28,7 @@ CREATE TABLE innodb.index_stats (
 	stat_description		VARCHAR(1024) NOT NULL,
 	PRIMARY KEY (database_name, table_name, index_name, stat_name),
 	FOREIGN KEY (database_name, table_name)
-	  REFERENCES table_stats (database_name, table_name)
+	  REFERENCES mysql.innodb_table_stats (database_name, table_name)
 ) ENGINE=INNODB DEFAULT CHARSET=utf8;
 
 -- enable_warnings

=== modified file 'mysql-test/suite/innodb/r/innodb-index.result'
--- a/mysql-test/suite/innodb/r/innodb-index.result	2011-05-19 12:43:26 +0000
+++ b/mysql-test/suite/innodb/r/innodb-index.result	2011-05-31 09:30:59 +0000
@@ -841,31 +841,31 @@ create table t1(a blob,b blob,c blob,d b
 i blob,j blob,k blob,l blob,m blob,n blob,o blob,p blob,
 q blob,r blob,s blob,t blob,u blob)
 engine=innodb row_format=dynamic;
-create index t1a on t1 (a(1));
-create index t1b on t1 (b(1));
-create index t1c on t1 (c(1));
-create index t1d on t1 (d(1));
-create index t1e on t1 (e(1));
-create index t1f on t1 (f(1));
-create index t1g on t1 (g(1));
-create index t1h on t1 (h(1));
-create index t1i on t1 (i(1));
-create index t1j on t1 (j(1));
-create index t1k on t1 (k(1));
-create index t1l on t1 (l(1));
-create index t1m on t1 (m(1));
-create index t1n on t1 (n(1));
-create index t1o on t1 (o(1));
-create index t1p on t1 (p(1));
-create index t1q on t1 (q(1));
-create index t1r on t1 (r(1));
-create index t1s on t1 (s(1));
-create index t1t on t1 (t(1));
-create index t1u on t1 (u(1));
+create index t1a on t1 (a(767));
+create index t1b on t1 (b(767));
+create index t1c on t1 (c(767));
+create index t1d on t1 (d(767));
+create index t1e on t1 (e(767));
+create index t1f on t1 (f(767));
+create index t1g on t1 (g(767));
+create index t1h on t1 (h(767));
+create index t1i on t1 (i(767));
+create index t1j on t1 (j(767));
+create index t1k on t1 (k(767));
+create index t1l on t1 (l(767));
+create index t1m on t1 (m(767));
+create index t1n on t1 (n(767));
+create index t1o on t1 (o(767));
+create index t1p on t1 (p(767));
+create index t1q on t1 (q(767));
+create index t1r on t1 (r(767));
+create index t1s on t1 (s(767));
+create index t1t on t1 (t(767));
+create index t1u on t1 (u(767));
 ERROR HY000: Too big row
-create index t1ut on t1 (u(1), t(1));
+create index t1ut on t1 (u(767), t(767));
 ERROR HY000: Too big row
-create index t1st on t1 (s(1), t(1));
+create index t1st on t1 (s(767), t(767));
 show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
@@ -890,32 +890,32 @@ t1	CREATE TABLE `t1` (
   `s` blob,
   `t` blob,
   `u` blob,
-  KEY `t1a` (`a`(1)),
-  KEY `t1b` (`b`(1)),
-  KEY `t1c` (`c`(1)),
-  KEY `t1d` (`d`(1)),
-  KEY `t1e` (`e`(1)),
-  KEY `t1f` (`f`(1)),
-  KEY `t1g` (`g`(1)),
-  KEY `t1h` (`h`(1)),
-  KEY `t1i` (`i`(1)),
-  KEY `t1j` (`j`(1)),
-  KEY `t1k` (`k`(1)),
-  KEY `t1l` (`l`(1)),
-  KEY `t1m` (`m`(1)),
-  KEY `t1n` (`n`(1)),
-  KEY `t1o` (`o`(1)),
-  KEY `t1p` (`p`(1)),
-  KEY `t1q` (`q`(1)),
-  KEY `t1r` (`r`(1)),
-  KEY `t1s` (`s`(1)),
-  KEY `t1t` (`t`(1)),
-  KEY `t1st` (`s`(1),`t`(1))
+  KEY `t1a` (`a`(767)),
+  KEY `t1b` (`b`(767)),
+  KEY `t1c` (`c`(767)),
+  KEY `t1d` (`d`(767)),
+  KEY `t1e` (`e`(767)),
+  KEY `t1f` (`f`(767)),
+  KEY `t1g` (`g`(767)),
+  KEY `t1h` (`h`(767)),
+  KEY `t1i` (`i`(767)),
+  KEY `t1j` (`j`(767)),
+  KEY `t1k` (`k`(767)),
+  KEY `t1l` (`l`(767)),
+  KEY `t1m` (`m`(767)),
+  KEY `t1n` (`n`(767)),
+  KEY `t1o` (`o`(767)),
+  KEY `t1p` (`p`(767)),
+  KEY `t1q` (`q`(767)),
+  KEY `t1r` (`r`(767)),
+  KEY `t1s` (`s`(767)),
+  KEY `t1t` (`t`(767)),
+  KEY `t1st` (`s`(767),`t`(767))
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
-create index t1u on t1 (u(1));
+create index t1u on t1 (u(767));
 ERROR HY000: Too big row
 alter table t1 row_format=compact;
-create index t1u on t1 (u(1));
+create index t1u on t1 (u(767));
 drop table t1;
 set global innodb_file_per_table=0;
 set global innodb_file_format=Antelope;

=== added file 'mysql-test/suite/innodb/r/innodb_index_large_prefix.result'
--- a/mysql-test/suite/innodb/r/innodb_index_large_prefix.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/r/innodb_index_large_prefix.result	2011-05-31 09:30:59 +0000
@@ -0,0 +1,185 @@
+set global innodb_file_format="Barracuda";
+set global innodb_file_per_table=1;
+set global innodb_large_prefix=1;
+create table worklog5743(a TEXT not null, primary key (a(1000)))
+ROW_FORMAT=DYNAMIC, engine = innodb;
+insert into worklog5743 values(repeat("a", 20000));
+update worklog5743 set a = (repeat("b", 16000));
+create index idx on worklog5743(a(2000));
+begin;
+update worklog5743 set a = (repeat("x", 17000));
+select @@session.tx_isolation;
+@@session.tx_isolation
+REPEATABLE-READ
+select a = repeat("x", 17000) from worklog5743;
+a = repeat("x", 17000)
+0
+select a = repeat("b", 16000) from worklog5743;
+a = repeat("b", 16000)
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+@@session.tx_isolation
+READ-UNCOMMITTED
+select a = repeat("x", 17000) from worklog5743;
+a = repeat("x", 17000)
+1
+rollback;
+drop table worklog5743;
+create table worklog5743(a1 int, a2 TEXT not null)
+ROW_FORMAT=DYNAMIC, engine = innodb;
+create index idx on worklog5743(a1, a2(2000));
+insert into worklog5743 values(9, repeat("a", 10000));
+begin;
+update worklog5743 set a1 = 1000;
+select @@session.tx_isolation;
+@@session.tx_isolation
+REPEATABLE-READ
+explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	worklog5743	ref	idx	idx	5	const	1	
+select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+a1	a2 = repeat("a", 10000)
+9	1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+@@session.tx_isolation
+READ-UNCOMMITTED
+select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+a1	a2 = repeat("a", 10000)
+rollback;
+drop table worklog5743;
+create table worklog5743(a1 int, a2 TEXT not null)
+ROW_FORMAT=DYNAMIC, engine = innodb;
+create index idx on worklog5743(a1, a2(50));
+insert into worklog5743 values(9, repeat("a", 10000));
+begin;
+update worklog5743 set a1 = 1000;
+select @@session.tx_isolation;
+@@session.tx_isolation
+REPEATABLE-READ
+explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	worklog5743	ref	idx	idx	5	const	1	
+select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+a1	a2 = repeat("a", 10000)
+9	1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+@@session.tx_isolation
+READ-UNCOMMITTED
+select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+a1	a2 = repeat("a", 10000)
+rollback;
+drop table worklog5743;
+create table worklog5743_2(a1 int, a2 TEXT not null)
+ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2, engine = innodb;
+create table worklog5743_4(a1 int, a2 TEXT not null)
+ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4, engine = innodb;
+create index idx1 on worklog5743_2(a1, a2(942));
+ERROR HY000: Too big row
+create index idx1 on worklog5743_2(a1, a2(940));
+create index idx1 on worklog5743_4(a1, a2(1966));
+ERROR HY000: Too big row
+create index idx1 on worklog5743_4(a1, a2(1964));
+insert into worklog5743_2 values(9, repeat("a", 10000));
+insert into worklog5743_4 values(9, repeat("a", 10000));
+begin;
+update worklog5743_2 set a1 = 1000;
+update worklog5743_4 set a1 = 1000;
+select @@session.tx_isolation;
+@@session.tx_isolation
+REPEATABLE-READ
+explain select a1, a2 = repeat("a", 10000) from worklog5743_2 where a1 = 9;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	worklog5743_2	ref	idx1	idx1	5	const	1	
+select a1, a2 = repeat("a", 10000) from worklog5743_2 where a1 = 9;
+a1	a2 = repeat("a", 10000)
+9	1
+select a1, a2 = repeat("a", 10000) from worklog5743_4 where a1 = 9;
+a1	a2 = repeat("a", 10000)
+9	1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+@@session.tx_isolation
+READ-UNCOMMITTED
+select a1, a2 = repeat("a", 10000) from worklog5743_2 where a1 = 9;
+a1	a2 = repeat("a", 10000)
+select a1, a2 = repeat("a", 10000) from worklog5743_4 where a1 = 9;
+a1	a2 = repeat("a", 10000)
+rollback;
+drop table worklog5743_2;
+drop table worklog5743_4;
+create table worklog5743(a1 int, a2 varchar(3000))
+ROW_FORMAT=DYNAMIC, engine = innodb;
+create index idx on worklog5743(a1, a2);
+insert into worklog5743 values(9, repeat("a", 3000));
+begin;
+update worklog5743 set a1 = 1000;
+select @@session.tx_isolation;
+@@session.tx_isolation
+REPEATABLE-READ
+explain select a1 from worklog5743 where a1 = 9;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	worklog5743	ref	idx	idx	5	const	1	Using index
+select a1 from worklog5743 where a1 = 9;
+a1
+9
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+@@session.tx_isolation
+READ-UNCOMMITTED
+select a1 from worklog5743 where a1 = 9;
+a1
+rollback;
+drop table worklog5743;
+create table worklog5743(a TEXT not null, primary key (a(1000)))
+engine = innodb;
+ERROR HY000: Index column size too large. The maximum column size is 767 bytes.
+create table worklog5743(a TEXT) engine = innodb;
+create index idx on worklog5743(a(1000));
+ERROR HY000: Index column size too large. The maximum column size is 767 bytes.
+create index idx on worklog5743(a(725));
+insert into worklog5743 values(repeat("a", 20000));
+begin;
+insert into worklog5743 values(repeat("b", 20000));
+update worklog5743 set a = (repeat("x", 25000));
+select @@session.tx_isolation;
+@@session.tx_isolation
+REPEATABLE-READ
+select a = repeat("a", 20000) from worklog5743;
+a = repeat("a", 20000)
+1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+@@session.tx_isolation
+READ-UNCOMMITTED
+select a = repeat("x", 25000) from worklog5743;
+a = repeat("x", 25000)
+1
+1
+rollback;
+drop table worklog5743;
+create table worklog5743(a TEXT not null) ROW_FORMAT=DYNAMIC, engine = innodb;
+create index idx on worklog5743(a(3073));
+Warnings:
+Warning	1071	Specified key was too long; max key length is 3072 bytes
+Warning	1071	Specified key was too long; max key length is 3072 bytes
+create index idx2 on worklog5743(a(3072));
+show create table worklog5743;
+Table	Create Table
+worklog5743	CREATE TABLE `worklog5743` (
+  `a` text NOT NULL,
+  KEY `idx` (`a`(3072)),
+  KEY `idx2` (`a`(3072))
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC
+drop table worklog5743;
+create table worklog5743(a TEXT not null) engine = innodb;
+create index idx on worklog5743(a(768));
+ERROR HY000: Index column size too large. The maximum column size is 767 bytes.
+create index idx2 on worklog5743(a(767));
+drop table worklog5743;
+SET GLOBAL innodb_file_format=Antelope;
+SET GLOBAL innodb_file_per_table=0;
+SET GLOBAL innodb_file_format_max=Antelope;
+SET GLOBAL innodb_large_prefix=0;

=== added file 'mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result'
--- a/mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/r/innodb_prefix_index_liftedlimit.result	2011-06-01 09:55:08 +0000
@@ -0,0 +1,1439 @@
+set global innodb_file_format="Barracuda";
+set global innodb_file_per_table=1;
+set global innodb_large_prefix=1;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+SELECT COLUMN_NAME,INDEX_NAME,SUB_PART,INDEX_TYPE FROM
+INFORMATION_SCHEMA.STATISTICS WHERE table_name = 'worklog5743' ;
+COLUMN_NAME	INDEX_NAME	SUB_PART	INDEX_TYPE
+col_1_varchar	PRIMARY	3072	BTREE
+col_1_varchar	prefix_idx	3072	BTREE
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varchar = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varchar = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varchar = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+col_1_varchar = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+col_1_varchar = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (3072));
+SELECT COLUMN_NAME,INDEX_NAME,SUB_PART,INDEX_TYPE FROM
+INFORMATION_SCHEMA.STATISTICS WHERE table_name = 'worklog5743' ;
+COLUMN_NAME	INDEX_NAME	SUB_PART	INDEX_TYPE
+col_1_text	PRIMARY	3072	BTREE
+col_1_text	prefix_idx	3072	BTREE
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_text = REPEAT("a", 4000)	col_2_text = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743;
+col_1_text = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_mediumtext MEDIUMTEXT , col_2_mediumtext MEDIUMTEXT ,
+PRIMARY KEY (col_1_mediumtext(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_mediumtext (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_mediumtext = REPEAT("a", 4000),col_2_mediumtext = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_mediumtext = REPEAT("a", 4000)	col_2_mediumtext = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_mediumtext = REPEAT("c", 4000)
+WHERE col_1_mediumtext = REPEAT("a", 4000)
+AND col_2_mediumtext = REPEAT("o", 4000);
+SELECT col_1_mediumtext = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_mediumtext = REPEAT("c", 4000)
+AND col_2_mediumtext = REPEAT("o", 4000);
+col_1_mediumtext = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_mediumtext = REPEAT("b", 4000);
+SELECT col_1_mediumtext = REPEAT("c", 4000) FROM worklog5743;
+col_1_mediumtext = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_longtext LONGTEXT , col_2_longtext LONGTEXT ,
+PRIMARY KEY (col_1_longtext(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_longtext (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_longtext = REPEAT("a", 4000) , col_2_longtext = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_longtext = REPEAT("a", 4000)	col_2_longtext = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_longtext = REPEAT("c", 4000)
+WHERE col_1_longtext = REPEAT("a", 4000)
+AND col_2_longtext = REPEAT("o", 4000);
+SELECT col_1_longtext = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_longtext = REPEAT("c", 4000)
+AND col_2_longtext = REPEAT("o", 4000);
+col_1_longtext = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_longtext = REPEAT("b", 4000);
+SELECT col_1_longtext = REPEAT("c", 4000) FROM worklog5743;
+col_1_longtext = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_blob BLOB (4000) , col_2_blob BLOB (4000) ,
+PRIMARY KEY (col_1_blob(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_blob (3072));
+SELECT COLUMN_NAME,INDEX_NAME,SUB_PART,INDEX_TYPE FROM
+INFORMATION_SCHEMA.STATISTICS WHERE table_name = 'worklog5743' ;
+COLUMN_NAME	INDEX_NAME	SUB_PART	INDEX_TYPE
+col_1_blob	PRIMARY	3072	BTREE
+col_1_blob	prefix_idx	3072	BTREE
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_blob = REPEAT("a", 4000) , col_2_blob = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_blob = REPEAT("a", 4000)	col_2_blob = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_blob = REPEAT("c", 4000)
+WHERE col_1_blob = REPEAT("a", 4000) AND col_2_blob = REPEAT("o", 4000);
+SELECT col_1_blob = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_blob = REPEAT("c", 4000) AND col_2_blob = REPEAT("o", 4000);
+col_1_blob = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_blob = REPEAT("b", 4000);
+SELECT col_1_blob = REPEAT("c", 4000) FROM worklog5743;
+col_1_blob = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_mediumblob MEDIUMBLOB  , col_2_mediumblob MEDIUMBLOB  ,
+PRIMARY KEY (col_1_mediumblob(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_mediumblob (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_mediumblob = REPEAT("a", 4000),col_2_mediumblob = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_mediumblob = REPEAT("a", 4000)	col_2_mediumblob = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_mediumblob = REPEAT("c", 4000)
+WHERE col_1_mediumblob = REPEAT("a", 4000)
+AND col_2_mediumblob = REPEAT("o", 4000);
+SELECT col_1_mediumblob = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_mediumblob = REPEAT("c", 4000)
+AND col_2_mediumblob = REPEAT("o", 4000);
+col_1_mediumblob = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_mediumblob = REPEAT("b", 4000);
+SELECT col_1_mediumblob = REPEAT("c", 4000) FROM worklog5743;
+col_1_mediumblob = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_longblob LONGBLOB  , col_2_longblob LONGBLOB  ,
+PRIMARY KEY (col_1_longblob(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_longblob (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_longblob = REPEAT("a", 4000) , col_2_longblob = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_longblob = REPEAT("a", 4000)	col_2_longblob = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_longblob = REPEAT("c", 4000)
+WHERE col_1_longblob = REPEAT("a", 4000)
+AND col_2_longblob = REPEAT("o", 4000);
+SELECT col_1_longblob = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_longblob = REPEAT("c", 4000)
+AND col_2_longblob = REPEAT("o", 4000);
+col_1_longblob = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_longblob = REPEAT("b", 4000);
+SELECT col_1_longblob = REPEAT("c", 4000) FROM worklog5743;
+col_1_longblob = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_varbinary VARBINARY (4000) , col_2_varbinary VARBINARY (4000) ,
+PRIMARY KEY (col_1_varbinary(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varbinary (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varbinary = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varbinary = REPEAT("a", 4000)	col_2_varbinary = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+WHERE col_1_varbinary = REPEAT("a", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+col_1_varbinary = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("b", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743;
+col_1_varbinary = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (col_1_char CHAR (255) , col_2_char CHAR (255),
+col_3_char CHAR (255), col_4_char CHAR (255),col_5_char CHAR (255),
+col_6_char CHAR (255), col_7_char CHAR (255),col_8_char CHAR (255),
+col_9_char CHAR (255), col_10_char CHAR (255),col_11_char CHAR (255),
+col_12_char CHAR (255), col_13_char CHAR (255),col_14_char CHAR (255)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 255) , REPEAT("o", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255)
+);
+CREATE INDEX prefix_idx ON worklog5743(col_1_char(250),col_2_char(250),
+col_3_char(250),col_4_char(250),col_5_char(250),col_6_char(250),
+col_7_char(250),col_8_char(250),col_9_char(250),col_10_char(250),
+col_11_char(250),col_12_char(250),col_13_char(72)
+);
+INSERT INTO worklog5743 VALUES(REPEAT("b", 255) , REPEAT("p", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255)
+);
+SELECT col_1_char = REPEAT("a", 255) , col_2_char = REPEAT("o", 255) FROM worklog5743;
+col_1_char = REPEAT("a", 255)	col_2_char = REPEAT("o", 255)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_char = REPEAT("c", 255)
+WHERE col_1_char = REPEAT("a", 255) AND col_2_char = REPEAT("o", 255);
+SELECT col_1_char = REPEAT("c", 255) FROM worklog5743
+WHERE col_1_char = REPEAT("c", 255) AND col_2_char = REPEAT("o", 255);
+col_1_char = REPEAT("c", 255)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 255) , REPEAT("o", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255)
+);
+DELETE FROM worklog5743 WHERE col_1_char = REPEAT("b", 255);
+SELECT col_1_char = REPEAT("c", 255) FROM worklog5743;
+col_1_char = REPEAT("c", 255)
+1
+0
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (col_1_binary BINARY (255) , col_2_binary BINARY (255),
+col_3_binary BINARY(255),col_4_binary BINARY (255),col_5_binary BINARY (255),
+col_6_binary BINARY(255),col_7_binary BINARY (255),col_8_binary BINARY (255),
+col_9_binary BINARY(255),col_10_binary BINARY (255),col_11_binary BINARY (255),
+col_12_binary BINARY(255),col_13_binary BINARY (255),col_14_binary BINARY (255)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 255) , REPEAT("o", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255)
+);
+CREATE INDEX prefix_idx ON worklog5743(col_1_binary (250),col_2_binary (250),
+col_3_binary (250),col_4_binary (250),col_5_binary (250),
+col_6_binary (250),col_7_binary (250),col_8_binary (250),
+col_9_binary (250),col_10_binary (250),col_11_binary (250),
+col_12_binary (250),col_13_binary (72)
+);
+INSERT INTO worklog5743 VALUES(REPEAT("b", 255) , REPEAT("p", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255)
+);
+SELECT col_1_binary = REPEAT("a", 255) , col_2_binary = REPEAT("o", 255) FROM worklog5743;
+col_1_binary = REPEAT("a", 255)	col_2_binary = REPEAT("o", 255)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_binary = REPEAT("c", 255)
+WHERE col_1_binary = REPEAT("a", 255)
+AND col_2_binary = REPEAT("o", 255);
+SELECT col_1_binary = REPEAT("c", 255) FROM worklog5743
+WHERE col_1_binary = REPEAT("c", 255)
+AND col_2_binary = REPEAT("o", 255);
+col_1_binary = REPEAT("c", 255)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 255) , REPEAT("o", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255)
+);
+DELETE FROM worklog5743 WHERE col_1_binary = REPEAT("b", 255);
+SELECT col_1_binary = REPEAT("c", 255) FROM worklog5743;
+col_1_binary = REPEAT("c", 255)
+1
+0
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743_key2 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(948))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2, engine = innodb;
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+INSERT INTO worklog5743_key2 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varchar  = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743_key2;
+col_1_varchar  = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743_key2 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743_key2
+WHERE col_2_varchar = REPEAT("o", 4000);
+col_1_varchar = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key2 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743_key2;
+col_1_varchar = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743_key2;
+CREATE TABLE worklog5743_key4 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(1964))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4, engine = innodb;
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+INSERT INTO worklog5743_key4 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varchar  = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743_key4;
+col_1_varchar  = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743_key4 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("b", 3500) FROM worklog5743_key4
+WHERE col_1_varchar = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+col_1_varchar = REPEAT("b", 3500)
+0
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key4 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743_key4;
+col_1_varchar = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743_key4;
+CREATE TABLE worklog5743_key8 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(3072))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8, engine = innodb;
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+INSERT INTO worklog5743_key8 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varchar  = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743_key8;
+col_1_varchar  = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743_key8 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("b", 3500) FROM worklog5743_key8
+WHERE col_1_varchar = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+col_1_varchar = REPEAT("b", 3500)
+0
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key8 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743_key8;
+col_1_varchar = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743_key8;
+CREATE TABLE worklog5743_key2 (
+col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(948))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2, engine = innodb;
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+INSERT INTO worklog5743_key2 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text  = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743_key2;
+col_1_text  = REPEAT("a", 4000)	col_2_text = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743_key2 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("b", 3500) FROM worklog5743_key2
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("b", 3500)
+0
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key2 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743_key2;
+col_1_text = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743_key2;
+CREATE TABLE worklog5743_key4 (
+col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(1964))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4, engine = innodb;
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+INSERT INTO worklog5743_key4 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text  = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743_key4;
+col_1_text  = REPEAT("a", 4000)	col_2_text = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743_key4 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("b", 3500) FROM worklog5743_key4
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("b", 3500)
+0
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key4 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743_key4;
+col_1_text = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743_key4;
+CREATE TABLE worklog5743_key8 (
+col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8, engine = innodb;
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+INSERT INTO worklog5743_key8 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text  = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743_key8;
+col_1_text  = REPEAT("a", 4000)	col_2_text = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743_key8 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("b", 3500) FROM worklog5743_key8
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("b", 3500)
+0
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key8 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743_key8;
+col_1_text = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743_key8;
+CREATE TABLE worklog5743_key2 (
+col_1_blob BLOB (4000) , col_2_blob BLOB (4000) ,
+PRIMARY KEY (col_1_blob(948))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2, engine = innodb;
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+INSERT INTO worklog5743_key2 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_blob  = REPEAT("a", 4000) , col_2_blob = REPEAT("o", 4000)
+FROM worklog5743_key2;
+col_1_blob  = REPEAT("a", 4000)	col_2_blob = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743_key2 SET col_1_blob = REPEAT("c", 4000)
+WHERE col_1_blob = REPEAT("a", 4000) AND col_2_blob = REPEAT("o", 4000);
+SELECT col_1_blob = REPEAT("b", 3500) FROM worklog5743_key2
+WHERE col_1_blob = REPEAT("c", 4000) AND col_2_blob = REPEAT("o", 4000);
+col_1_blob = REPEAT("b", 3500)
+0
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key2 WHERE col_1_blob = REPEAT("b", 4000);
+SELECT col_1_blob = REPEAT("c", 4000) FROM worklog5743_key2;
+col_1_blob = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743_key2;
+CREATE TABLE worklog5743_key4 (
+col_1_blob BLOB (4000) , col_2_blob BLOB (4000) ,
+PRIMARY KEY (col_1_blob(1964))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4, engine = innodb;
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+INSERT INTO worklog5743_key4 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_blob  = REPEAT("a", 4000) , col_2_blob = REPEAT("o", 4000)
+FROM worklog5743_key4;
+col_1_blob  = REPEAT("a", 4000)	col_2_blob = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743_key4 SET col_1_blob = REPEAT("c", 4000)
+WHERE col_1_blob = REPEAT("a", 4000) AND col_2_blob = REPEAT("o", 4000);
+SELECT col_1_blob = REPEAT("b", 3500) FROM worklog5743_key4
+WHERE col_1_blob = REPEAT("c", 4000) AND col_2_blob = REPEAT("o", 4000);
+col_1_blob = REPEAT("b", 3500)
+0
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key4 WHERE col_1_blob = REPEAT("b", 4000);
+SELECT col_1_blob = REPEAT("c", 4000) FROM worklog5743_key4;
+col_1_blob = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743_key4;
+CREATE TABLE worklog5743_key8 (
+col_1_blob BLOB (4000) , col_2_blob BLOB (4000) ,
+PRIMARY KEY (col_1_blob(3072))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8, engine = innodb;
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+INSERT INTO worklog5743_key8 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_blob  = REPEAT("a", 4000) , col_2_blob = REPEAT("o", 4000)
+FROM worklog5743_key8;
+col_1_blob  = REPEAT("a", 4000)	col_2_blob = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743_key8 SET col_1_blob = REPEAT("c", 4000)
+WHERE col_1_blob = REPEAT("a", 4000) AND col_2_blob = REPEAT("o", 4000);
+SELECT col_1_blob = REPEAT("b", 3500) FROM worklog5743_key8
+WHERE col_1_blob = REPEAT("c", 4000) AND col_2_blob = REPEAT("o", 4000);
+col_1_blob = REPEAT("b", 3500)
+0
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key8 WHERE col_1_blob = REPEAT("b", 4000);
+SELECT col_1_blob = REPEAT("c", 4000) FROM worklog5743_key8;
+col_1_blob = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743_key8;
+CREATE TABLE worklog5743 (
+col_1_varbinary VARBINARY (4000) , col_2_varchar VARCHAR (4000) ,
+col_3_text TEXT (4000), col_4_blob BLOB (4000),col_5_text TEXT (4000),
+col_6_varchar VARCHAR (4000), col_7_binary BINARY (255)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) ,  REPEAT("a", 255)
+);
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varbinary = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+WHERE col_1_varbinary = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+col_1_varbinary = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("b", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743;
+col_1_varbinary = REPEAT("c", 4000)
+1
+0
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_varbinary VARBINARY (4000) , col_2_varchar VARCHAR (4000) ,
+col_3_text TEXT (4000), col_4_blob BLOB (4000),col_5_text TEXT (4000),
+col_6_varchar VARCHAR (4000), col_7_binary BINARY (255)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+CREATE INDEX prefix_idx1 ON worklog5743(col_1_varbinary (3072));
+CREATE INDEX prefix_idx2 ON worklog5743(col_2_varchar (3072));
+CREATE INDEX prefix_idx3 ON worklog5743(col_3_text (3072));
+CREATE INDEX prefix_idx4 ON worklog5743(col_4_blob (3072));
+CREATE INDEX prefix_idx5 ON worklog5743(col_5_text (3072));
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) ,  REPEAT("a", 255)
+);
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varbinary = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+ROLLBACK;
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) ,  REPEAT("a", 255)
+);
+COMMIT;
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varbinary = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+ROLLBACK;
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+col_1_varbinary = REPEAT("c", 4000)
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("b", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743;
+col_1_varbinary = REPEAT("c", 4000)
+0
+0
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_text TEXT (4000) CHARACTER SET 'utf8',
+col_2_text TEXT (4000) CHARACTER SET 'utf8',
+PRIMARY KEY (col_1_text(1024))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (1024));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000) FROM worklog5743;
+col_1_text = REPEAT("a", 4000)	col_2_text = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743;
+col_1_text = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (col_1_varchar VARCHAR (4000) CHARACTER SET 'utf8',
+col_2_varchar VARCHAR (4000) CHARACTER SET 'utf8' ,
+PRIMARY KEY (col_1_varchar(1024))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs
+CREATE TABLE worklog5743 (
+col_1_varbinary VARBINARY (4000) ,
+col_2_varchar VARCHAR (4000) CHARACTER SET 'utf8',
+col_3_text TEXT (4000) CHARACTER SET 'utf8',
+col_4_blob BLOB (4000),col_5_text TEXT (4000),
+col_6_varchar VARCHAR (4000), col_7_binary BINARY (255)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+CREATE INDEX prefix_idx2 ON worklog5743(col_2_varchar (500));
+CREATE INDEX prefix_idx3 ON worklog5743(col_3_text (500));
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) ,  REPEAT("a", 255)
+);
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varbinary = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+ROLLBACK;
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) ,  REPEAT("a", 255)
+);
+COMMIT;
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varbinary = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+ROLLBACK;
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+col_1_varbinary = REPEAT("c", 4000)
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("b", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743;
+col_1_varbinary = REPEAT("c", 4000)
+0
+0
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_text TEXT (4000) CHARACTER SET 'utf8',
+col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(1024))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("स", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (1024));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text = REPEAT("स", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_text = REPEAT("स", 4000)	col_2_text = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_text = REPEAT("क", 4000)
+WHERE col_1_text = REPEAT("स", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("क", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("क", 4000)
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("क", 4000) FROM worklog5743;
+col_1_text = REPEAT("क", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 200) , REPEAT("o", 200));
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text  = REPEAT("o", 200)
+1	1
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text = REPEAT("o", 200)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+"In connection 2"
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 200) , REPEAT("o", 200));
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text  = REPEAT("o", 200)
+1	1
+0	1
+"In connection 1"
+select @@session.tx_isolation;
+@@session.tx_isolation
+REPEATABLE-READ
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("b", 200)	col_2_text = REPEAT("o", 200)
+0	1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+@@session.tx_isolation
+READ-UNCOMMITTED
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("b", 200)	col_2_text = REPEAT("o", 200)
+0	1
+1	1
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+START TRANSACTION;
+SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text = REPEAT("o", 200)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+"In connection 2"
+COMMIT;
+"In connection 1"
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("b", 200)	col_2_text = REPEAT("o", 200)
+0	1
+SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text = REPEAT("o", 200)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+COMMIT;
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 200) , REPEAT("o", 200));
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text  = REPEAT("o", 200)
+1	1
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text = REPEAT("o", 200)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+START TRANSACTION;
+"In connection 2"
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 200) , REPEAT("o", 200));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("a", 200);
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text  = REPEAT("o", 200)
+0	1
+COMMIT;
+"In connection 1"
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+@@session.tx_isolation
+READ-UNCOMMITTED
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("b", 200)	col_2_text = REPEAT("o", 200)
+1	1
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("b", 200)	col_2_text = REPEAT("o", 200)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+COMMIT;
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 200) , REPEAT("o", 200));
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text  = REPEAT("o", 200)
+1	1
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text = REPEAT("o", 200)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+START TRANSACTION;
+"In connection 2"
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 200) , REPEAT("o", 200));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("a", 200);
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("a", 200)	col_2_text  = REPEAT("o", 200)
+0	1
+ROLLBACK;
+"In connection 1"
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+col_1_text = REPEAT("b", 200)	col_2_text = REPEAT("o", 200)
+0	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+COMMIT;
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 3500) , REPEAT("o", 3500));
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
+1	1
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+"In connection 2"
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+START TRANSACTION;
+"In connection default ....restarting the server"
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
+1	1
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 3500);
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+"In connection default ....restarting the server"
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
+1	1
+"In connection 1"
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+START TRANSACTION;
+UPDATE worklog5743 SET col_1_text = REPEAT("b", 3500) WHERE col_1_text = REPEAT("a", 3500);
+SELECT col_1_text = REPEAT("b", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("b", 3500)	col_2_text = REPEAT("o", 3500)
+1	1
+"In connection default ....restarting the server"
+SELECT COUNT(*) FROM worklog5743;
+COUNT(*)
+1
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+col_1_text = REPEAT("a", 3500)	col_2_text  = REPEAT("o", 3500)
+1	1
+DROP TABLE worklog5743;
+set global innodb_file_format="Barracuda";
+set global innodb_file_per_table=1;
+set global innodb_large_prefix=1;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varchar = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varchar = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varchar = REPEAT("c", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+col_1_varchar = REPEAT("c", 4000)
+1
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+col_1_varchar = REPEAT("c", 4000)
+0
+0
+1
+SELECT tbl1.col_1_varchar = tbl2.col_1_varchar
+FROM worklog5743 tbl1 , worklog5743 tbl2
+WHERE tbl1.col_1_varchar = tbl2.col_1_varchar ;
+tbl1.col_1_varchar = tbl2.col_1_varchar
+1
+1
+1
+SELECT tbl1.col_1_varchar = REPEAT("c", 4000) FROM worklog5743 tbl1
+WHERE col_1_varchar IN (SELECT tbl2.col_1_varchar FROM worklog5743 tbl2) ;
+tbl1.col_1_varchar = REPEAT("c", 4000)
+0
+0
+1
+SELECT tbl1.col_1_varchar = REPEAT("c", 4000) FROM worklog5743 tbl1
+WHERE col_1_varchar NOT IN (SELECT tbl2.col_1_varchar FROM worklog5743 tbl2) ;
+tbl1.col_1_varchar = REPEAT("c", 4000)
+SELECT tbl1.col_1_varchar = REPEAT("c", 4000) FROM worklog5743 tbl1 WHERE
+col_1_varchar IN (SELECT tbl2.col_1_varchar FROM worklog5743 tbl2)
+AND col_1_varchar = REPEAT("c", 4000);
+tbl1.col_1_varchar = REPEAT("c", 4000)
+1
+SELECT tbl1.col_1_varchar = REPEAT("c", 4000) FROM worklog5743 tbl1
+WHERE col_1_varchar in (
+SELECT tbl2.col_1_varchar FROM worklog5743 tbl2
+WHERE tbl1.col_1_varchar != tbl2.col_1_varchar
+) ;
+tbl1.col_1_varchar = REPEAT("c", 4000)
+SELECT tbl1.col_1_varchar = REPEAT("c", 4000) FROM worklog5743 tbl1
+WHERE col_1_varchar in (
+SELECT tbl2.col_1_varchar FROM worklog5743 tbl2
+WHERE tbl1.col_1_varchar = tbl2.col_1_varchar
+) ;
+tbl1.col_1_varchar = REPEAT("c", 4000)
+0
+0
+1
+SELECT
+REVERSE(col_1_varchar) = REPEAT("c", 4000) ,
+REVERSE(REVERSE(col_1_varchar)) = REPEAT("c", 4000)
+FROM worklog5743;
+REVERSE(col_1_varchar) = REPEAT("c", 4000)	REVERSE(REVERSE(col_1_varchar)) = REPEAT("c", 4000)
+0	0
+0	0
+1	1
+SELECT
+UPPER(col_1_varchar) = REPEAT("c", 4000) ,
+UPPER(col_1_varchar) = REPEAT("C", 4000) ,
+LOWER(UPPER(col_1_varchar)) = REPEAT("c", 4000)
+FROM worklog5743;
+UPPER(col_1_varchar) = REPEAT("c", 4000)	UPPER(col_1_varchar) = REPEAT("C", 4000)	LOWER(UPPER(col_1_varchar)) = REPEAT("c", 4000)
+0	0	0
+0	0	0
+1	1	1
+SELECT
+col_1_varchar = REPEAT("c", 4000)
+FROM worklog5743 WHERE col_1_varchar like '%c__%';
+col_1_varchar = REPEAT("c", 4000)
+1
+SELECT SUBSTRING(INSERT(col_1_varchar, 1, 4, 'kkkk'),1,10) FROM worklog5743 ;
+SUBSTRING(INSERT(col_1_varchar, 1, 4, 'kkkk'),1,10)
+kkkkaaaaaa
+kkkkbbbbbb
+kkkkcccccc
+SELECT CONCAT(SUBSTRING(col_1_varchar,-5,3),'append') FROM worklog5743 ;
+CONCAT(SUBSTRING(col_1_varchar,-5,3),'append')
+aaaappend
+bbbappend
+cccappend
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) ,
+col_2_varchar VARCHAR (4000) ,
+UNIQUE INDEX (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743
+VALUES(concat(REPEAT("a", 2000),REPEAT("b", 1000),REPEAT("c", 1000)), REPEAT("o", 4000));
+INSERT INTO worklog5743
+VALUES(concat(REPEAT("a", 2000),REPEAT("b", 2000)), REPEAT("o", 4000));
+INSERT INTO worklog5743 VALUES(NULL,NULL);
+INSERT INTO worklog5743 VALUES(NULL,NULL);
+SELECT COLUMN_NAME,INDEX_NAME,SUB_PART,INDEX_TYPE
+FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name = 'worklog5743' ;
+COLUMN_NAME	INDEX_NAME	SUB_PART	INDEX_TYPE
+col_1_varchar	col_1_varchar	3072	BTREE
+SELECT col_1_varchar FROM worklog5743 WHERE col_1_varchar IS NULL;
+col_1_varchar
+NULL
+NULL
+SELECT col_1_varchar = concat(REPEAT("a", 2000),REPEAT("b", 2000))
+FROM worklog5743 WHERE col_1_varchar IS NOT NULL ORDER BY 1;
+col_1_varchar = concat(REPEAT("a", 2000),REPEAT("b", 2000))
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(3072))) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+DROP INDEX prefix_idx ON worklog5743;
+SELECT col_1_varchar = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varchar = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varchar = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+col_1_varchar = REPEAT("c", 4000)
+1
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+col_1_varchar = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY `prefix_primary` (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+SELECT col_1_varchar = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varchar = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varchar = REPEAT("c", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+col_1_varchar = REPEAT("c", 4000)
+1
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_varchar(3072));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+ERROR 23000: Duplicate entry 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' for key 'PRIMARY'
+DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+col_1_varchar = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY `prefix_primary` (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+DROP INDEX prefix_idx ON worklog5743;
+SELECT col_1_varchar = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varchar = REPEAT("a", 4000)	col_2_varchar = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varchar = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+col_1_varchar = REPEAT("c", 4000)
+1
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_varchar(3072));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+ERROR 23000: Duplicate entry 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' for key 'PRIMARY'
+DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+col_1_varchar = REPEAT("c", 4000)
+0
+1
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR(4000) , col_2_varchar VARCHAR(4000) ,
+PRIMARY KEY (col_1_varchar (3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("c", 3500) , REPEAT("o", 3500));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+" Switching to con1 connection For select "
+SELECT col_1_varchar = REPEAT("c", 3500) , col_2_varchar = REPEAT("o", 3500)
+FROM worklog5743;
+col_1_varchar = REPEAT("c", 3500)	col_2_varchar = REPEAT("o", 3500)
+1	1
+" Switching to default connection For DMLs "
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 3500) , REPEAT("o", 3500));
+SELECT col_1_varchar = REPEAT("b", 3500) FROM worklog5743
+WHERE col_2_varchar = REPEAT("o", 3500);
+col_1_varchar = REPEAT("b", 3500)
+0
+0
+COMMIT;
+" Switching to con1 connection For Dropping index and some DMLs "
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("k", 3500),REPEAT("p", 3500));
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+UPDATE worklog5743 SET col_1_varchar  = REPEAT("b", 3500)
+WHERE col_1_varchar = REPEAT("a", 3500)
+AND col_2_varchar = REPEAT("o", 3500);
+SELECT col_1_varchar = REPEAT("b", 3500) FROM worklog5743
+WHERE col_2_varchar = REPEAT("o", 3500);
+col_1_varchar = REPEAT("b", 3500)
+1
+0
+" Switching to default connection For DELETE "
+DELETE FROM worklog5743 WHERE col_1_varchar  = REPEAT("b", 3500);
+SELECT col_1_varchar = REPEAT("a", 3500) FROM worklog5743
+WHERE col_2_varchar = REPEAT("p", 3500);
+col_1_varchar = REPEAT("a", 3500)
+0
+" Switching to con1 connection to commit changes "
+COMMIT;
+" Switching to default connection to drop and end sub-test "
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_varbinary VARBINARY (4000) , col_2_varbinary VARBINARY (4000) ,
+PRIMARY KEY (col_1_varbinary(3072))) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varbinary (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varbinary = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_varbinary = REPEAT("a", 4000)	col_2_varbinary = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+WHERE col_1_varbinary = REPEAT("a", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+col_1_varbinary = REPEAT("c", 4000)
+1
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("c", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+col_1_varbinary = REPEAT("c", 4000)
+DROP INDEX prefix_idx ON worklog5743;
+SELECT col_1_varbinary = REPEAT("b", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("b", 4000)
+AND col_2_varbinary = REPEAT("p", 4000);
+col_1_varbinary = REPEAT("b", 4000)
+1
+CREATE INDEX prefix_idx ON worklog5743(col_1_varbinary (2000));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_varbinary = REPEAT("a", 4000) FROM worklog5743;
+col_1_varbinary = REPEAT("a", 4000)
+1
+0
+UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+WHERE col_1_varbinary = REPEAT("a", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("c", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+col_1_varbinary = REPEAT("c", 4000)
+DROP INDEX prefix_idx ON worklog5743;
+CREATE INDEX prefix_idx ON worklog5743(col_1_varbinary (4000));
+Warnings:
+Warning	1071	Specified key was too long; max key length is 3072 bytes
+Warning	1071	Specified key was too long; max key length is 3072 bytes
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_varbinary = REPEAT("a", 4000) FROM worklog5743;
+col_1_varbinary = REPEAT("a", 4000)
+1
+0
+UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+WHERE col_1_varbinary = REPEAT("a", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("c", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+col_1_varbinary = REPEAT("c", 4000)
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(500))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743;
+col_1_text = REPEAT("a", 4000)	col_2_text = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000)
+AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("c", 4000)
+1
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("c", 4000)
+DROP INDEX prefix_idx ON worklog5743;
+SELECT col_1_text = REPEAT("b", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("b", 4000) AND col_2_text = REPEAT("p", 4000);
+col_1_text = REPEAT("b", 4000)
+1
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (1000));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_text = REPEAT("a", 4000) FROM worklog5743;
+col_1_text = REPEAT("a", 4000)
+1
+0
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("c", 4000)
+DROP INDEX prefix_idx ON worklog5743;
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (4000));
+Warnings:
+Warning	1071	Specified key was too long; max key length is 3072 bytes
+Warning	1071	Specified key was too long; max key length is 3072 bytes
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_text = REPEAT("a", 4000) FROM worklog5743;
+col_1_text = REPEAT("a", 4000)
+1
+0
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("c", 4000)
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(948))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000) FROM worklog5743;
+col_1_text = REPEAT("a", 4000)	col_2_text = REPEAT("o", 4000)
+1	1
+0	0
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000)
+AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000)
+AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("c", 4000)
+1
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000)
+AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("c", 4000)
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+SELECT col_1_text = REPEAT("b", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("b", 4000)
+AND col_2_text = REPEAT("p", 4000);
+col_1_text = REPEAT("b", 4000)
+1
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_text (700));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_text = REPEAT("a", 4000) FROM worklog5743;
+col_1_text = REPEAT("a", 4000)
+1
+0
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000)
+AND col_2_text = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000)
+AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("c", 4000)
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_text (950));
+ERROR HY000: Too big row
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_text = REPEAT("a", 4000) FROM worklog5743;
+col_1_text = REPEAT("a", 4000)
+0
+1
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000)
+AND col_2_text = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000)
+AND col_2_text = REPEAT("o", 4000);
+col_1_text = REPEAT("c", 4000)
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , PRIMARY KEY (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_varchar (900));
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_varchar (3073));
+ERROR 42000: Specified key was too long; max key length is 3072 bytes
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_BLOB BLOB (4000) , PRIMARY KEY (col_1_BLOB(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_BLOB (500));
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_BLOB (3073));
+ERROR 42000: Specified key was too long; max key length is 3072 bytes
+DROP TABLE worklog5743;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743
+VALUES(concat(REPEAT("a", 2000),REPEAT("b", 1000),REPEAT("c", 1000)),
+REPEAT("o", 4000));
+INSERT INTO worklog5743
+VALUES(concat(REPEAT("a", 2000),REPEAT("b", 2000)), REPEAT("o", 4000));
+ALTER TABLE worklog5743 ADD PRIMARY KEY `pk_idx` (col_1_varchar(3000));
+ERROR 23000: Duplicate entry 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' for key 'PRIMARY'
+DROP TABLE worklog5743;
+set global innodb_large_prefix=0;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+ERROR 42000: Specified key was too long; max key length is 767 bytes
+set global innodb_large_prefix=0;
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(767))
+) engine = innodb;
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (1000));
+Warnings:
+Warning	1071	Specified key was too long; max key length is 767 bytes
+Warning	1071	Specified key was too long; max key length is 767 bytes
+DROP TABLE worklog5743;
+SET GLOBAL innodb_file_format=Antelope;
+SET GLOBAL innodb_file_per_table=0;
+SET GLOBAL innodb_file_format_max=Antelope;
+SET GLOBAL innodb_large_prefix=0;

=== modified file 'mysql-test/suite/innodb/r/innodb_stats.result'
--- a/mysql-test/suite/innodb/r/innodb_stats.result	2011-03-18 12:49:38 +0000
+++ b/mysql-test/suite/innodb/r/innodb_stats.result	2011-05-30 13:56:01 +0000
@@ -10,7 +10,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND
@@ -62,7 +62,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND
@@ -114,7 +114,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND
@@ -166,7 +166,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND
@@ -218,7 +218,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND
@@ -270,7 +270,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND
@@ -322,7 +322,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND
@@ -374,7 +374,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND
@@ -426,7 +426,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND
@@ -478,7 +478,7 @@ stat_name,
 stat_value,
 sample_size,
 stat_description
-FROM innodb.index_stats
+FROM mysql.innodb_index_stats
 WHERE
 database_name = DATABASE() AND
 table_name = 'test_innodb_stats' AND

=== modified file 'mysql-test/suite/innodb/r/innodb_stats_drop_locked.result'
--- a/mysql-test/suite/innodb/r/innodb_stats_drop_locked.result	2010-09-27 16:43:02 +0000
+++ b/mysql-test/suite/innodb/r/innodb_stats_drop_locked.result	2011-05-30 13:56:01 +0000
@@ -1,12 +1,12 @@
 Table	Op	Msg_type	Msg_text
 test.innodb_stats_drop_locked	analyze	status	OK
 SET autocommit=0;
-SELECT table_name FROM innodb.table_stats
+SELECT table_name FROM mysql.innodb_table_stats
 WHERE table_name='innodb_stats_drop_locked'
 FOR UPDATE;
 table_name
 innodb_stats_drop_locked
-SELECT table_name FROM innodb.index_stats
+SELECT table_name FROM mysql.innodb_index_stats
 WHERE table_name='innodb_stats_drop_locked'
 FOR UPDATE;
 table_name
@@ -19,7 +19,7 @@ innodb_stats_drop_locked
 innodb_stats_drop_locked
 ALTER TABLE innodb_stats_drop_locked DROP INDEX c_key;
 Warnings:
-Warning	1205	Unable to delete statistics for index c_key from innodb.index_stats because the rows are locked. They can be deleted later using DELETE FROM innodb.index_stats WHERE database_name = 'test' AND table_name = 'innodb_stats_drop_locked' AND index_name = 'c_key';
+Warning	1205	Unable to delete statistics for index c_key from mysql.innodb_index_stats because the rows are locked. They can be deleted later using DELETE FROM mysql.innodb_index_stats WHERE database_name = 'test' AND table_name = 'innodb_stats_drop_locked' AND index_name = 'c_key';
 SHOW CREATE TABLE innodb_stats_drop_locked;
 Table	Create Table
 innodb_stats_drop_locked	CREATE TABLE `innodb_stats_drop_locked` (
@@ -27,15 +27,15 @@ innodb_stats_drop_locked	CREATE TABLE `i
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 DROP TABLE innodb_stats_drop_locked;
 Warnings:
-Warning	1205	Unable to delete statistics for table test.innodb_stats_drop_locked from innodb.table_stats or innodb.index_stats because the rows are locked. They can be deleted later using DELETE FROM innodb.index_stats WHERE database_name = 'test' AND table_name = 'innodb_stats_drop_locked'; DELETE FROM innodb.table_stats WHERE database_name = 'test' AND table_name = 'innodb_stats_drop_locked';
+Warning	1205	Unable to delete statistics for table test.innodb_stats_drop_locked from mysql.innodb_table_stats or mysql.innodb_index_stats because the rows are locked. They can be deleted later using DELETE FROM mysql.innodb_index_stats WHERE database_name = 'test' AND table_name = 'innodb_stats_drop_locked'; DELETE FROM mysql.innodb_table_stats WHERE database_name = 'test' AND table_name = 'innodb_stats_drop_locked';
 SHOW TABLES;
 Tables_in_test
 COMMIT;
-SELECT table_name FROM innodb.table_stats
+SELECT table_name FROM mysql.innodb_table_stats
 WHERE table_name='innodb_stats_drop_locked';
 table_name
 innodb_stats_drop_locked
-SELECT table_name FROM innodb.index_stats
+SELECT table_name FROM mysql.innodb_index_stats
 WHERE table_name='innodb_stats_drop_locked';
 table_name
 innodb_stats_drop_locked

=== modified file 'mysql-test/suite/innodb/t/innodb-index.test'
--- a/mysql-test/suite/innodb/t/innodb-index.test	2011-05-19 12:43:26 +0000
+++ b/mysql-test/suite/innodb/t/innodb-index.test	2011-05-31 09:30:59 +0000
@@ -367,36 +367,36 @@ create table t1(a blob,b blob,c blob,d b
 		i blob,j blob,k blob,l blob,m blob,n blob,o blob,p blob,
 		q blob,r blob,s blob,t blob,u blob)
 	engine=innodb row_format=dynamic;
-create index t1a on t1 (a(1));
-create index t1b on t1 (b(1));
-create index t1c on t1 (c(1));
-create index t1d on t1 (d(1));
-create index t1e on t1 (e(1));
-create index t1f on t1 (f(1));
-create index t1g on t1 (g(1));
-create index t1h on t1 (h(1));
-create index t1i on t1 (i(1));
-create index t1j on t1 (j(1));
-create index t1k on t1 (k(1));
-create index t1l on t1 (l(1));
-create index t1m on t1 (m(1));
-create index t1n on t1 (n(1));
-create index t1o on t1 (o(1));
-create index t1p on t1 (p(1));
-create index t1q on t1 (q(1));
-create index t1r on t1 (r(1));
-create index t1s on t1 (s(1));
-create index t1t on t1 (t(1));
+create index t1a on t1 (a(767));
+create index t1b on t1 (b(767));
+create index t1c on t1 (c(767));
+create index t1d on t1 (d(767));
+create index t1e on t1 (e(767));
+create index t1f on t1 (f(767));
+create index t1g on t1 (g(767));
+create index t1h on t1 (h(767));
+create index t1i on t1 (i(767));
+create index t1j on t1 (j(767));
+create index t1k on t1 (k(767));
+create index t1l on t1 (l(767));
+create index t1m on t1 (m(767));
+create index t1n on t1 (n(767));
+create index t1o on t1 (o(767));
+create index t1p on t1 (p(767));
+create index t1q on t1 (q(767));
+create index t1r on t1 (r(767));
+create index t1s on t1 (s(767));
+create index t1t on t1 (t(767));
 --error 139
-create index t1u on t1 (u(1));
+create index t1u on t1 (u(767));
 --error 139
-create index t1ut on t1 (u(1), t(1));
-create index t1st on t1 (s(1), t(1));
+create index t1ut on t1 (u(767), t(767));
+create index t1st on t1 (s(767), t(767));
 show create table t1;
 --error 139
-create index t1u on t1 (u(1));
+create index t1u on t1 (u(767));
 alter table t1 row_format=compact;
-create index t1u on t1 (u(1));
+create index t1u on t1 (u(767));
 
 drop table t1;
 eval set global innodb_file_per_table=$per_table;

=== modified file 'mysql-test/suite/innodb/t/innodb_bug11933790.test'
--- a/mysql-test/suite/innodb/t/innodb_bug11933790.test	2011-04-04 14:19:29 +0000
+++ b/mysql-test/suite/innodb/t/innodb_bug11933790.test	2011-05-30 13:56:01 +0000
@@ -22,7 +22,7 @@ ANALYZE TABLE bug11933790;
 SET autocommit=0;
 
 # lock the records in innodb.table_stats
-SELECT * FROM innodb.table_stats FOR UPDATE;
+SELECT * FROM mysql.innodb_table_stats FOR UPDATE;
 
 -- connect (con1,localhost,root,,)
 
@@ -45,4 +45,5 @@ ANALYZE TABLE bug11933790;
 COMMIT;
 
 DROP TABLE bug11933790;
-DROP DATABASE innodb;
+DROP TABLE mysql.innodb_index_stats;
+DROP TABLE mysql.innodb_table_stats;

=== added file 'mysql-test/suite/innodb/t/innodb_index_large_prefix.test'
--- a/mysql-test/suite/innodb/t/innodb_index_large_prefix.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_index_large_prefix.test	2011-05-31 09:12:32 +0000
@@ -0,0 +1,271 @@
+# Testcase for worklog #5743: Lift the limit of index key prefixes
+
+--source include/have_innodb.inc
+
+let $innodb_file_format_orig=`select @@innodb_file_format`;
+let $innodb_file_per_table_orig=`select @@innodb_file_per_table`;
+let $innodb_file_format_max_orig=`select @@innodb_file_format_max`;
+let $innodb_large_prefix_orig=`select @@innodb_large_prefix`;
+
+set global innodb_file_format="Barracuda";
+set global innodb_file_per_table=1;
+set global innodb_large_prefix=1;
+
+# Create a table of DYNAMIC format, with a primary index of 1000 bytes in
+# size
+create table worklog5743(a TEXT not null, primary key (a(1000)))
+ROW_FORMAT=DYNAMIC, engine = innodb;
+
+# Do some insertion and update to excercise the external cache
+# code path
+insert into worklog5743 values(repeat("a", 20000));
+
+# default session, update the table
+update worklog5743 set a = (repeat("b", 16000));
+
+# Create a secondary index
+create index idx on worklog5743(a(2000));
+
+# Start a few sessions to do selections on table being updated in default
+# session, so it would rebuild the previous version from undo log.
+# 1) Default session:	Initiate an update on the externally stored column
+# 2) Session con1:	Select from table with repeated read
+# 3) Session con2:	Select from table with read uncommitted
+# 4) Default session:	rollback updates
+
+begin;
+update worklog5743 set a = (repeat("x", 17000));
+
+# Start a new session to select the column to force it build
+# an earlier version of the clustered index through undo log. So it should
+# just see the result of repeat("b", 16000)
+select @@session.tx_isolation;
+--connect (con1,localhost,root,,)
+select a = repeat("x", 17000) from worklog5743;
+select a = repeat("b", 16000) from worklog5743;
+
+# Start another session doing "read uncommitted" query, it
+# should see the uncommitted update
+--connect (con2,localhost,root,,)
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+select a = repeat("x", 17000) from worklog5743;
+
+# Roll back the transaction
+--connection default
+rollback;
+
+drop table worklog5743;
+
+# Create a table with only a secondary index has large prefix column
+create table worklog5743(a1 int, a2 TEXT not null)
+ROW_FORMAT=DYNAMIC, engine = innodb;
+
+create index idx on worklog5743(a1, a2(2000));
+
+insert into worklog5743 values(9, repeat("a", 10000));
+
+begin;
+
+update worklog5743 set a1 = 1000;
+
+# Do a select from another connection that would use the secondary index
+--connection con1
+select @@session.tx_isolation;
+explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+
+# Do read uncommitted in another session, it would show there is no
+# row with a1 = 9
+--connection con2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+
+--connection default
+rollback;
+
+drop table worklog5743;
+
+# Create a table with a secondary index has small (50 bytes) prefix column
+create table worklog5743(a1 int, a2 TEXT not null)
+ROW_FORMAT=DYNAMIC, engine = innodb;
+
+create index idx on worklog5743(a1, a2(50));
+
+insert into worklog5743 values(9, repeat("a", 10000));
+
+begin;
+
+update worklog5743 set a1 = 1000;
+
+# Do a select from another connection that would use the secondary index
+--connection con1
+select @@session.tx_isolation;
+explain select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+
+# Do read uncommitted in another session, it would show there is no
+# row with a1 = 9
+--connection con2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+select a1, a2 = repeat("a", 10000) from worklog5743 where a1 = 9;
+
+--connection default
+rollback;
+
+drop table worklog5743;
+
+# Create a table of ROW_FORMAT=COMPRESSED format
+create table worklog5743_2(a1 int, a2 TEXT not null)
+ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2, engine = innodb;
+
+create table worklog5743_4(a1 int, a2 TEXT not null)
+ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4, engine = innodb;
+
+# The maximum overall index record (not prefix) length for this table
+# is page_zip_empty_size() / 2, which is 960. "Too big row" error (
+# HA_ERR_TO_BIG_ROW) will be printed if this limit is exceeded.
+# Considering other fields and their overhead, the maximum length
+# for column a2 is 940 or 941 depending on the zlib version used and
+# compressBound() value used in page_zip_empty_size() (please refer
+# to Bug #47495 for more detail).
+-- error 139
+create index idx1 on worklog5743_2(a1, a2(942));
+
+create index idx1 on worklog5743_2(a1, a2(940));
+
+# similarly, the maximum index record length for the table is
+# 1984. Considering other fields and their overhead, the
+# maximum length for column a2 is 1964 or 1965 (please refer
+# to Bug #47495 for more detail).
+-- error 139
+create index idx1 on worklog5743_4(a1, a2(1966));
+
+create index idx1 on worklog5743_4(a1, a2(1964));
+
+insert into worklog5743_2 values(9, repeat("a", 10000));
+insert into worklog5743_4 values(9, repeat("a", 10000));
+
+begin;
+
+update worklog5743_2 set a1 = 1000;
+update worklog5743_4 set a1 = 1000;
+
+# Do a select from another connection that would use the secondary index
+--connection con1
+select @@session.tx_isolation;
+explain select a1, a2 = repeat("a", 10000) from worklog5743_2 where a1 = 9;
+select a1, a2 = repeat("a", 10000) from worklog5743_2 where a1 = 9;
+select a1, a2 = repeat("a", 10000) from worklog5743_4 where a1 = 9;
+
+# Do read uncommitted in another session, it would show there is no
+# row with a1 = 9
+--connection con2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+select a1, a2 = repeat("a", 10000) from worklog5743_2 where a1 = 9;
+select a1, a2 = repeat("a", 10000) from worklog5743_4 where a1 = 9;
+
+--connection default
+rollback;
+
+drop table worklog5743_2;
+drop table worklog5743_4;
+
+# Create a table with varchar column, and create index directly on this
+# large column (without prefix)
+create table worklog5743(a1 int, a2 varchar(3000))
+ROW_FORMAT=DYNAMIC, engine = innodb;
+
+# Create an index with large column without prefix
+create index idx on worklog5743(a1, a2);
+
+insert into worklog5743 values(9, repeat("a", 3000));
+
+begin;
+
+update worklog5743 set a1 = 1000;
+
+# Do a select from another connection that would use the secondary index
+--connection con1
+select @@session.tx_isolation;
+explain select a1 from worklog5743 where a1 = 9;
+select a1 from worklog5743 where a1 = 9;
+
+# Do read uncommitted, it would show there is no row with a1 = 9
+--connection con2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+select a1 from worklog5743 where a1 = 9;
+
+--connection default
+rollback;
+
+drop table worklog5743;
+
+# Create a table with old format, and the limit is 768 bytes.
+-- error ER_INDEX_COLUMN_TOO_LONG
+create table worklog5743(a TEXT not null, primary key (a(1000)))
+engine = innodb;
+
+create table worklog5743(a TEXT) engine = innodb;
+
+# Excercise the column length check in ha_innobase::add_index()
+-- error ER_INDEX_COLUMN_TOO_LONG
+create index idx on worklog5743(a(1000));
+
+# This should be successful
+create index idx on worklog5743(a(725));
+
+# Perform some DMLs
+insert into worklog5743 values(repeat("a", 20000));
+
+begin;
+insert into worklog5743 values(repeat("b", 20000));
+update worklog5743 set a = (repeat("x", 25000));
+
+# Start a new session to select the table to force it build
+# an earlier version of the cluster index through undo log
+select @@session.tx_isolation;
+--connection con1
+select a = repeat("a", 20000) from worklog5743;
+
+--connection con2
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+select a = repeat("x", 25000) from worklog5743;
+
+--connection default
+rollback;
+
+drop table worklog5743;
+
+# Some border line test on the column length.
+# We have a limit of 3072 bytes for Barracuda table
+create table worklog5743(a TEXT not null) ROW_FORMAT=DYNAMIC, engine = innodb;
+
+# Length exceeds maximum supported key length, will auto-truncated to 3072
+create index idx on worklog5743(a(3073));
+
+create index idx2 on worklog5743(a(3072));
+
+show create table worklog5743;
+
+drop table worklog5743;
+
+# We have a limit of 767 bytes for Antelope table
+create table worklog5743(a TEXT not null) engine = innodb;
+
+-- error ER_INDEX_COLUMN_TOO_LONG
+create index idx on worklog5743(a(768));
+
+create index idx2 on worklog5743(a(767));
+
+drop table worklog5743;
+
+eval SET GLOBAL innodb_file_format=$innodb_file_format_orig;
+eval SET GLOBAL innodb_file_per_table=$innodb_file_per_table_orig;
+eval SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig;
+eval SET GLOBAL innodb_large_prefix=$innodb_large_prefix_orig;

=== added file 'mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test'
--- a/mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_prefix_index_liftedlimit.test	2011-06-01 09:55:08 +0000
@@ -0,0 +1,1428 @@
+######## suite/innodb/t/innodb_prefix_index_liftedlimit.test ##########
+#                                                                    #
+# Testcase for worklog WL#5743: Lift the limit of index key prefixes #
+# Accorrding to WL#5743 - prefix index limit is increased from 767   #
+# to 3072 for innodb. This change is applicable with Barracuda file  #
+# format.                                                            #
+# All sub-test in this file focus on prefix index along with other   #
+# operations                                                         #
+#                                                                    #
+#                                                                    #
+# Creation:                                                          #
+# 2011-05-19 Implemented this test as part of WL#5743                #
+#                                                                    #
+######################################################################
+
+
+--source include/have_innodb.inc
+# Save innodb variables
+let $innodb_file_format_orig=`select @@innodb_file_format`;
+let $innodb_file_per_table_orig=`select @@innodb_file_per_table`;
+let $innodb_file_format_max_orig=`select @@innodb_file_format_max`;
+let $innodb_large_prefix_orig=`select @@innodb_large_prefix`;
+
+# Set Innodb file format as feature works for Barracuda file format
+set global innodb_file_format="Barracuda";
+set global innodb_file_per_table=1;
+set global innodb_large_prefix=1;
+
+
+#------------------------------------------------------------------------------
+# Prefix index with VARCHAR data type , primary/secondary index and DML ops
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+# check IS
+SELECT COLUMN_NAME,INDEX_NAME,SUB_PART,INDEX_TYPE FROM
+INFORMATION_SCHEMA.STATISTICS WHERE table_name = 'worklog5743' ;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varchar = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varchar = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+
+#------------------------------------------------------------------------------
+# Prefix index with TEXT data type , primary/secondary index and DML ops
+CREATE TABLE worklog5743 (
+col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (3072));
+# check IS
+SELECT COLUMN_NAME,INDEX_NAME,SUB_PART,INDEX_TYPE FROM
+INFORMATION_SCHEMA.STATISTICS WHERE table_name = 'worklog5743' ;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+#------------------------------------------------------------------------------
+# Prefix index with MEDIUMTEXT data type , primary/secondary index and DML ops
+CREATE TABLE worklog5743 (
+col_1_mediumtext MEDIUMTEXT , col_2_mediumtext MEDIUMTEXT ,
+PRIMARY KEY (col_1_mediumtext(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_mediumtext (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_mediumtext = REPEAT("a", 4000),col_2_mediumtext = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_mediumtext = REPEAT("c", 4000)
+WHERE col_1_mediumtext = REPEAT("a", 4000)
+AND col_2_mediumtext = REPEAT("o", 4000);
+SELECT col_1_mediumtext = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_mediumtext = REPEAT("c", 4000)
+AND col_2_mediumtext = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_mediumtext = REPEAT("b", 4000);
+SELECT col_1_mediumtext = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+
+#------------------------------------------------------------------------------
+# Prefix index with LONGTEXT data type , primary/secondary index and DML ops
+CREATE TABLE worklog5743 (
+col_1_longtext LONGTEXT , col_2_longtext LONGTEXT ,
+PRIMARY KEY (col_1_longtext(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_longtext (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_longtext = REPEAT("a", 4000) , col_2_longtext = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_longtext = REPEAT("c", 4000)
+WHERE col_1_longtext = REPEAT("a", 4000)
+AND col_2_longtext = REPEAT("o", 4000);
+SELECT col_1_longtext = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_longtext = REPEAT("c", 4000)
+AND col_2_longtext = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_longtext = REPEAT("b", 4000);
+SELECT col_1_longtext = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+
+#------------------------------------------------------------------------------
+# Prefix index with BLOB data type , primary/secondary index and DML ops
+CREATE TABLE worklog5743 (
+col_1_blob BLOB (4000) , col_2_blob BLOB (4000) ,
+PRIMARY KEY (col_1_blob(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_blob (3072));
+# check IS
+SELECT COLUMN_NAME,INDEX_NAME,SUB_PART,INDEX_TYPE FROM
+INFORMATION_SCHEMA.STATISTICS WHERE table_name = 'worklog5743' ;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_blob = REPEAT("a", 4000) , col_2_blob = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_blob = REPEAT("c", 4000)
+WHERE col_1_blob = REPEAT("a", 4000) AND col_2_blob = REPEAT("o", 4000);
+SELECT col_1_blob = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_blob = REPEAT("c", 4000) AND col_2_blob = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_blob = REPEAT("b", 4000);
+SELECT col_1_blob = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+
+#------------------------------------------------------------------------------
+# Prefix index with MEDIUMBLOB data type , primary/secondary index and DML ops
+CREATE TABLE worklog5743 (
+col_1_mediumblob MEDIUMBLOB  , col_2_mediumblob MEDIUMBLOB  ,
+PRIMARY KEY (col_1_mediumblob(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_mediumblob (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_mediumblob = REPEAT("a", 4000),col_2_mediumblob = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_mediumblob = REPEAT("c", 4000)
+WHERE col_1_mediumblob = REPEAT("a", 4000)
+AND col_2_mediumblob = REPEAT("o", 4000);
+SELECT col_1_mediumblob = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_mediumblob = REPEAT("c", 4000)
+AND col_2_mediumblob = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_mediumblob = REPEAT("b", 4000);
+SELECT col_1_mediumblob = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+#------------------------------------------------------------------------------
+# Prefix index with LONGBLOB data type , primary/secondary index and DML ops
+CREATE TABLE worklog5743 (
+col_1_longblob LONGBLOB  , col_2_longblob LONGBLOB  ,
+PRIMARY KEY (col_1_longblob(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_longblob (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_longblob = REPEAT("a", 4000) , col_2_longblob = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_longblob = REPEAT("c", 4000)
+WHERE col_1_longblob = REPEAT("a", 4000)
+AND col_2_longblob = REPEAT("o", 4000);
+SELECT col_1_longblob = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_longblob = REPEAT("c", 4000)
+AND col_2_longblob = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_longblob = REPEAT("b", 4000);
+SELECT col_1_longblob = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+#------------------------------------------------------------------------------
+# Prefix index with VARBINARY data type , primary/secondary index and DML ops
+CREATE TABLE worklog5743 (
+col_1_varbinary VARBINARY (4000) , col_2_varbinary VARBINARY (4000) ,
+PRIMARY KEY (col_1_varbinary(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varbinary (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varbinary = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+WHERE col_1_varbinary = REPEAT("a", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("b", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+#------------------------------------------------------------------------------
+# Prefix index with CHAR data type , composite index and DML ops
+CREATE TABLE worklog5743 (col_1_char CHAR (255) , col_2_char CHAR (255),
+col_3_char CHAR (255), col_4_char CHAR (255),col_5_char CHAR (255),
+col_6_char CHAR (255), col_7_char CHAR (255),col_8_char CHAR (255),
+col_9_char CHAR (255), col_10_char CHAR (255),col_11_char CHAR (255),
+col_12_char CHAR (255), col_13_char CHAR (255),col_14_char CHAR (255)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 255) , REPEAT("o", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255)
+);
+# Create index with total prefix index length = 3072
+CREATE INDEX prefix_idx ON worklog5743(col_1_char(250),col_2_char(250),
+col_3_char(250),col_4_char(250),col_5_char(250),col_6_char(250),
+col_7_char(250),col_8_char(250),col_9_char(250),col_10_char(250),
+col_11_char(250),col_12_char(250),col_13_char(72)
+);
+INSERT INTO worklog5743 VALUES(REPEAT("b", 255) , REPEAT("p", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255)
+);
+SELECT col_1_char = REPEAT("a", 255) , col_2_char = REPEAT("o", 255) FROM worklog5743;
+UPDATE worklog5743 SET col_1_char = REPEAT("c", 255)
+WHERE col_1_char = REPEAT("a", 255) AND col_2_char = REPEAT("o", 255);
+SELECT col_1_char = REPEAT("c", 255) FROM worklog5743
+WHERE col_1_char = REPEAT("c", 255) AND col_2_char = REPEAT("o", 255);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 255) , REPEAT("o", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255),REPEAT("a", 255)
+);
+DELETE FROM worklog5743 WHERE col_1_char = REPEAT("b", 255);
+SELECT col_1_char = REPEAT("c", 255) FROM worklog5743;
+DROP TABLE worklog5743;
+
+#------------------------------------------------------------------------------
+# Prefix index with BINARY data type , composite index and DML ops
+CREATE TABLE worklog5743 (col_1_binary BINARY (255) , col_2_binary BINARY (255),
+col_3_binary BINARY(255),col_4_binary BINARY (255),col_5_binary BINARY (255),
+col_6_binary BINARY(255),col_7_binary BINARY (255),col_8_binary BINARY (255),
+col_9_binary BINARY(255),col_10_binary BINARY (255),col_11_binary BINARY (255),
+col_12_binary BINARY(255),col_13_binary BINARY (255),col_14_binary BINARY (255)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 255) , REPEAT("o", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255)
+);
+# Create index with total prefix index length = 3072
+CREATE INDEX prefix_idx ON worklog5743(col_1_binary (250),col_2_binary (250),
+col_3_binary (250),col_4_binary (250),col_5_binary (250),
+col_6_binary (250),col_7_binary (250),col_8_binary (250),
+col_9_binary (250),col_10_binary (250),col_11_binary (250),
+col_12_binary (250),col_13_binary (72)
+);
+INSERT INTO worklog5743 VALUES(REPEAT("b", 255) , REPEAT("p", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255)
+);
+SELECT col_1_binary = REPEAT("a", 255) , col_2_binary = REPEAT("o", 255) FROM worklog5743;
+UPDATE worklog5743 SET col_1_binary = REPEAT("c", 255)
+WHERE col_1_binary = REPEAT("a", 255)
+AND col_2_binary = REPEAT("o", 255);
+SELECT col_1_binary = REPEAT("c", 255) FROM worklog5743
+WHERE col_1_binary = REPEAT("c", 255)
+AND col_2_binary = REPEAT("o", 255);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 255) , REPEAT("o", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255),
+REPEAT("a", 255) , REPEAT("o", 255), REPEAT("a", 255)
+);
+DELETE FROM worklog5743 WHERE col_1_binary = REPEAT("b", 255);
+SELECT col_1_binary = REPEAT("c", 255) FROM worklog5743;
+DROP TABLE worklog5743;
+
+#------------------------------------------------------------------------------
+# Prefix index with VARCHAR data type , primary/seconday index , DML ops
+# and COMPRESSED row format. KEY_BLOCK_SIZE is varied as 2 , 4 , 8.
+
+# With KEY_BLOCK_SIZE = 2,prefix index limit comes around ~948 for following
+CREATE TABLE worklog5743_key2 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(948))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2, engine = innodb;
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+#CREATE INDEX prefix_idx ON worklog5743_key2 (col_1_varchar (767));
+INSERT INTO worklog5743_key2 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varchar  = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743_key2;
+UPDATE worklog5743_key2 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743_key2
+WHERE col_2_varchar = REPEAT("o", 4000);
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key2 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743_key2;
+DROP TABLE worklog5743_key2;
+
+# With KEY_BLOCK_SIZE = 4,prefix index limit comes around ~1964 for following
+CREATE TABLE worklog5743_key4 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(1964))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4, engine = innodb;
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+#CREATE INDEX prefix_idx ON worklog5743_key4 (col_1_varchar (767));
+INSERT INTO worklog5743_key4 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varchar  = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743_key4;
+UPDATE worklog5743_key4 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("b", 3500) FROM worklog5743_key4
+WHERE col_1_varchar = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key4 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743_key4;
+DROP TABLE worklog5743_key4;
+
+# With KEY_BLOCK_SIZE = 8,prefix index limit comes around ~3072 for following
+CREATE TABLE worklog5743_key8 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(3072))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8, engine = innodb;
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+#CREATE INDEX prefix_idx ON worklog5743_key8 (col_1_varchar (767));
+INSERT INTO worklog5743_key8 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varchar  = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743_key8;
+UPDATE worklog5743_key8 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("b", 3500) FROM worklog5743_key8
+WHERE col_1_varchar = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key8 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743_key8;
+DROP TABLE worklog5743_key8;
+
+# Prefix index with TEXT data type , primary/seconday index , DML ops
+# and COMPRESSED row format. KEY_BLOCK_SIZE is varied as 2 , 4 , 8.
+
+# With KEY_BLOCK_SIZE = 2,prefix index limit comes around ~948 for following
+CREATE TABLE worklog5743_key2 (
+col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(948))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2, engine = innodb;
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+#CREATE INDEX prefix_idx ON worklog5743_key2 (col_1_text (767));
+INSERT INTO worklog5743_key2 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text  = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743_key2;
+UPDATE worklog5743_key2 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("b", 3500) FROM worklog5743_key2
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key2 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743_key2;
+DROP TABLE worklog5743_key2;
+
+# With KEY_BLOCK_SIZE = 4,prefix index limit comes around ~1964 for following
+CREATE TABLE worklog5743_key4 (
+col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(1964))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4, engine = innodb;
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+#CREATE INDEX prefix_idx ON worklog5743_key4 (col_1_text (767));
+INSERT INTO worklog5743_key4 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text  = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743_key4;
+UPDATE worklog5743_key4 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("b", 3500) FROM worklog5743_key4
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key4 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743_key4;
+DROP TABLE worklog5743_key4;
+
+# With KEY_BLOCK_SIZE = 8,prefix index limit comes around ~3072 for following
+CREATE TABLE worklog5743_key8 (
+col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8, engine = innodb;
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+#CREATE INDEX prefix_idx ON worklog5743_key8 (col_1_text (767));
+INSERT INTO worklog5743_key8 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text  = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743_key8;
+UPDATE worklog5743_key8 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("b", 3500) FROM worklog5743_key8
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key8 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743_key8;
+DROP TABLE worklog5743_key8;
+
+# Prefix index with BLOB data type , primary/seconday index , DML ops
+# and COMPRESSED row format. KEY_BLOCK_SIZE is varied as 2 , 4 , 8.
+
+# With KEY_BLOCK_SIZE = 2,prefix index limit comes around ~948 for following
+CREATE TABLE worklog5743_key2 (
+col_1_blob BLOB (4000) , col_2_blob BLOB (4000) ,
+PRIMARY KEY (col_1_blob(948))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2, engine = innodb;
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+#CREATE INDEX prefix_idx ON worklog5743_key2 (col_1_blob (767));
+INSERT INTO worklog5743_key2 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_blob  = REPEAT("a", 4000) , col_2_blob = REPEAT("o", 4000)
+FROM worklog5743_key2;
+UPDATE worklog5743_key2 SET col_1_blob = REPEAT("c", 4000)
+WHERE col_1_blob = REPEAT("a", 4000) AND col_2_blob = REPEAT("o", 4000);
+SELECT col_1_blob = REPEAT("b", 3500) FROM worklog5743_key2
+WHERE col_1_blob = REPEAT("c", 4000) AND col_2_blob = REPEAT("o", 4000);
+INSERT INTO worklog5743_key2 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key2 WHERE col_1_blob = REPEAT("b", 4000);
+SELECT col_1_blob = REPEAT("c", 4000) FROM worklog5743_key2;
+DROP TABLE worklog5743_key2;
+
+# With KEY_BLOCK_SIZE = 4,prefix index limit comes around ~1964 for following
+CREATE TABLE worklog5743_key4 (
+col_1_blob BLOB (4000) , col_2_blob BLOB (4000) ,
+PRIMARY KEY (col_1_blob(1964))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4, engine = innodb;
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+#CREATE INDEX prefix_idx ON worklog5743_key4 (col_1_blob (767));
+INSERT INTO worklog5743_key4 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_blob  = REPEAT("a", 4000) , col_2_blob = REPEAT("o", 4000)
+FROM worklog5743_key4;
+UPDATE worklog5743_key4 SET col_1_blob = REPEAT("c", 4000)
+WHERE col_1_blob = REPEAT("a", 4000) AND col_2_blob = REPEAT("o", 4000);
+SELECT col_1_blob = REPEAT("b", 3500) FROM worklog5743_key4
+WHERE col_1_blob = REPEAT("c", 4000) AND col_2_blob = REPEAT("o", 4000);
+INSERT INTO worklog5743_key4 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key4 WHERE col_1_blob = REPEAT("b", 4000);
+SELECT col_1_blob = REPEAT("c", 4000) FROM worklog5743_key4;
+DROP TABLE worklog5743_key4;
+
+# With KEY_BLOCK_SIZE = 8,prefix index limit comes around ~3072 for following
+CREATE TABLE worklog5743_key8 (
+col_1_blob BLOB (4000) , col_2_blob BLOB (4000) ,
+PRIMARY KEY (col_1_blob(3072))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8, engine = innodb;
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+#CREATE INDEX prefix_idx ON worklog5743_key8 (col_1_blob (767));
+INSERT INTO worklog5743_key8 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_blob  = REPEAT("a", 4000) , col_2_blob = REPEAT("o", 4000)
+FROM worklog5743_key8;
+UPDATE worklog5743_key8 SET col_1_blob = REPEAT("c", 4000)
+WHERE col_1_blob = REPEAT("a", 4000) AND col_2_blob = REPEAT("o", 4000);
+SELECT col_1_blob = REPEAT("b", 3500) FROM worklog5743_key8
+WHERE col_1_blob = REPEAT("c", 4000) AND col_2_blob = REPEAT("o", 4000);
+INSERT INTO worklog5743_key8 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743_key8 WHERE col_1_blob = REPEAT("b", 4000);
+SELECT col_1_blob = REPEAT("c", 4000) FROM worklog5743_key8;
+DROP TABLE worklog5743_key8;
+
+
+#------------------------------------------------------------------------------
+# Create mutiple prefix index. We can not create prefix index length > 16K
+# as index is written in undo log page which of 16K size.
+# So we can create max 5 prefix index of length 3072 on table
+CREATE TABLE worklog5743 (
+col_1_varbinary VARBINARY (4000) , col_2_varchar VARCHAR (4000) ,
+col_3_text TEXT (4000), col_4_blob BLOB (4000),col_5_text TEXT (4000),
+col_6_varchar VARCHAR (4000), col_7_binary BINARY (255)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) ,  REPEAT("a", 255)
+);
+
+# Update hangs if we create following 5 indexes. Uncomment them once its fix
+# Bug#12547647 - UPDATE LOGGING COULD EXCEED LOG PAGE SIZE
+#CREATE INDEX prefix_idx1 ON worklog5743(col_1_varbinary (3072));
+#CREATE INDEX prefix_idx2 ON worklog5743(col_2_varchar (3072));
+#CREATE INDEX prefix_idx3 ON worklog5743(col_3_text (3072));
+#CREATE INDEX prefix_idx4 ON worklog5743(col_4_blob (3072));
+#CREATE INDEX prefix_idx5 ON worklog5743(col_5_text (3072));
+
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+WHERE col_1_varbinary = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("b", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+
+#------------------------------------------------------------------------------
+# Create mutiple prefix index. We can not create prefix index length > 16K as
+# we write in undo log page which of 16K size.
+# so we can create max 5 prefix index of length 3072 on table.
+# Similar to above case but with transactions
+CREATE TABLE worklog5743 (
+col_1_varbinary VARBINARY (4000) , col_2_varchar VARCHAR (4000) ,
+col_3_text TEXT (4000), col_4_blob BLOB (4000),col_5_text TEXT (4000),
+col_6_varchar VARCHAR (4000), col_7_binary BINARY (255)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+
+
+# Update hangs if we create following 5 indexes. Uncomment them once its fix
+CREATE INDEX prefix_idx1 ON worklog5743(col_1_varbinary (3072));
+CREATE INDEX prefix_idx2 ON worklog5743(col_2_varchar (3072));
+CREATE INDEX prefix_idx3 ON worklog5743(col_3_text (3072));
+CREATE INDEX prefix_idx4 ON worklog5743(col_4_blob (3072));
+CREATE INDEX prefix_idx5 ON worklog5743(col_5_text (3072));
+
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) ,  REPEAT("a", 255)
+);
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+ROLLBACK;
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) ,  REPEAT("a", 255)
+);
+COMMIT;
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+ROLLBACK;
+# Uncomment Update fater Bug#12547647 is fixed - UPDATE LOGGING COULD EXCEED LOG PAGE SIZE
+# Bug#12547647 - UPDATE LOGGING COULD EXCEED LOG PAGE SIZE
+#UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+#WHERE col_1_varbinary = REPEAT("a", 4000)
+#AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("b", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+#------------------------------------------------------------------------------
+# Prefix index with utf8 charset
+# utf8 charcter takes 3 bytes in mysql so prefix index limit is 3072/3 = 1024
+CREATE TABLE worklog5743 (
+col_1_text TEXT (4000) CHARACTER SET 'utf8',
+col_2_text TEXT (4000) CHARACTER SET 'utf8',
+PRIMARY KEY (col_1_text(1024))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (1024));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000) FROM worklog5743;
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+# Prefix index with utf8 charset + varchar.
+# For varchar we also log the column itself as oppose of TEXT so it error
+# with limit 1024 due to overhead.
+-- error 1118
+CREATE TABLE worklog5743 (col_1_varchar VARCHAR (4000) CHARACTER SET 'utf8',
+col_2_varchar VARCHAR (4000) CHARACTER SET 'utf8' ,
+PRIMARY KEY (col_1_varchar(1024))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+
+#------------------------------------------------------------------------------
+# prefinx index on utf8 charset with transaction
+CREATE TABLE worklog5743 (
+col_1_varbinary VARBINARY (4000) ,
+col_2_varchar VARCHAR (4000) CHARACTER SET 'utf8',
+col_3_text TEXT (4000) CHARACTER SET 'utf8',
+col_4_blob BLOB (4000),col_5_text TEXT (4000),
+col_6_varchar VARCHAR (4000), col_7_binary BINARY (255)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+
+
+CREATE INDEX prefix_idx2 ON worklog5743(col_2_varchar (500));
+CREATE INDEX prefix_idx3 ON worklog5743(col_3_text (500));
+
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) ,  REPEAT("a", 255)
+);
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+ROLLBACK;
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) ,  REPEAT("a", 255)
+);
+COMMIT;
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+ROLLBACK;
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000),
+REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000),
+REPEAT("a", 4000) , REPEAT("a", 255)
+);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("b", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+
+#------------------------------------------------------------------------------
+# Prefix index with utf8 charset on TEXT data type with actual utf8 character
+# like "स" and "क"
+CREATE TABLE worklog5743 (
+col_1_text TEXT (4000) CHARACTER SET 'utf8',
+col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(1024))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("स", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (1024));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text = REPEAT("स", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_text = REPEAT("क", 4000)
+WHERE col_1_text = REPEAT("स", 4000) AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("क", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 4000);
+SELECT col_1_text = REPEAT("क", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+
+#------------------------------------------------------------------------------
+# Prefix index with transaction when 2 client are ruuning there transaction
+# in different sessions.With ISOLATION LEVEL as REPEATABLE READ and
+# READ UNCOMMITTED.
+CREATE TABLE worklog5743 (
+col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 200) , REPEAT("o", 200));
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+
+--echo "In connection 1"
+--connect (con1,localhost,root,,)
+SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+
+
+--echo "In connection 2"
+--connect (con2,localhost,root,,)
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 200) , REPEAT("o", 200));
+# Uncomment after Bug#12552164 - TRANSACTION CAN NOT SEE OLD VERSION ROWS THAT
+# BEING UPDATED
+#UPDATE worklog5743 SET col_1_varchar = REPEAT("d", 200) WHERE col_1_varchar =
+#REPEAT("a", 200) AND col_2_varchar = REPEAT("o", 200);
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+
+
+--echo "In connection 1"
+--connection con1
+select @@session.tx_isolation;
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+
+START TRANSACTION;
+
+SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+
+--echo "In connection 2"
+--connection con2
+COMMIT;
+# Wait for commit
+let $wait_condition=SELECT COUNT(*)=0 FROM information_schema.processlist
+WHERE info='COMMIT';
+--source include/wait_condition.inc 
+
+--echo "In connection 1"
+--connection con1
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+COMMIT;
+
+--connection default
+DROP TABLE worklog5743;
+
+
+#------------------------------------------------------------------------------
+# Prefix index with transaction when 2 client are ruuning there transaction
+# in different sessions.With ISOLATION LEVEL as REPEATABLE READ and
+# READ UNCOMMITTED. Same as above case but con2 starts tnx before con1
+
+CREATE TABLE worklog5743 (
+col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 200) , REPEAT("o", 200));
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+
+--echo "In connection 1"
+--connection con1
+SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+START TRANSACTION;
+
+
+--echo "In connection 2"
+--connection con2
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 200) , REPEAT("o", 200));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("a", 200);
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+COMMIT;
+# Wait for commit
+let $wait_condition=SELECT COUNT(*)=0 FROM information_schema.processlist
+WHERE info='COMMIT';
+--source include/wait_condition.inc 
+
+
+--echo "In connection 1"
+--connection con1
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+select @@session.tx_isolation;
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+COMMIT;
+
+--connection default
+DROP TABLE worklog5743;
+
+#------------------------------------------------------------------------------
+
+# Prefix index with transaction when 2 client are ruuning there transaction
+# in different sessions.With ISOLATION LEVEL as REPEATABLE READ and
+# READ UNCOMMITTED. Same as above cases but with ROLLBACK
+
+CREATE TABLE worklog5743 (
+col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 200) , REPEAT("o", 200));
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+
+--echo "In connection 1"
+--connection con1
+SELECT col_1_text = REPEAT("a", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+START TRANSACTION;
+
+
+--echo "In connection 2"
+--connection con2
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 200) , REPEAT("o", 200));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("a", 200);
+SELECT col_1_text = REPEAT("a", 200) , col_2_text  = REPEAT("o", 200) FROM
+worklog5743;
+ROLLBACK;
+# Wait for rollback
+let $wait_condition=SELECT COUNT(*)=0 FROM information_schema.processlist
+WHERE info='COMMIT';
+--source include/wait_condition.inc 
+
+
+--echo "In connection 1"
+--connection con1
+SELECT col_1_text = REPEAT("b", 200) , col_2_text = REPEAT("o", 200) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+COMMIT;
+
+--disconnect con1
+--disconnect con2
+
+--connection default
+DROP TABLE worklog5743;
+
+
+#------------------------------------------------------------------------------
+# Stop the server in between when prefix index are created and see if state is
+# correct when server is restarted.
+# Server is restarted at differnt points.
+
+CREATE TABLE worklog5743 (
+col_1_text TEXT(4000) , col_2_text TEXT(4000) ,
+PRIMARY KEY (col_1_text(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 3500) , REPEAT("o", 3500));
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+
+--echo "In connection 1"
+--connect (con1,localhost,root,,)
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+
+
+--echo "In connection 2"
+--connect (con2,localhost,root,,)
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
+
+
+--echo "In connection 1"
+--connection con1
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+START TRANSACTION;
+
+
+--echo "In connection default ....restarting the server"
+--connection default
+# Restart the server
+-- source include/restart_mysqld.inc
+SELECT COUNT(*) FROM worklog5743;
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+
+--disconnect con1
+--disconnect con2
+
+--echo "In connection 1"
+--connect (con1,localhost,root,,)
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("b", 3500) , REPEAT("o", 3500));
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("b", 3500);
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+
+--echo "In connection default ....restarting the server"
+--connection default
+# Restart the server
+-- source include/restart_mysqld.inc
+SELECT COUNT(*) FROM worklog5743;
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+
+--disconnect con1
+
+--echo "In connection 1"
+--connect (con2,localhost,root,,)
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+SELECT COUNT(*) FROM worklog5743;
+START TRANSACTION;
+UPDATE worklog5743 SET col_1_text = REPEAT("b", 3500) WHERE col_1_text = REPEAT("a", 3500);
+SELECT col_1_text = REPEAT("b", 3500) , col_2_text = REPEAT("o", 3500) FROM
+worklog5743;
+
+--echo "In connection default ....restarting the server"
+--connection default
+# Restart the server
+-- source include/restart_mysqld.inc
+SELECT COUNT(*) FROM worklog5743;
+SELECT col_1_text = REPEAT("a", 3500) , col_2_text  = REPEAT("o", 3500) FROM
+worklog5743;
+
+DROP TABLE worklog5743;
+
+#------------------------------------------------------------------------------
+# Reset variables at server was restarted in previous case
+set global innodb_file_format="Barracuda";
+set global innodb_file_per_table=1;
+set global innodb_large_prefix=1;
+#------------------------------------------------------------------------------
+# Select queries on prefix index column as index will be used in queries.
+# Use few select functions , join condition , subqueries.
+
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varchar = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varchar = REPEAT("c", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+
+# Select with Join
+SELECT tbl1.col_1_varchar = tbl2.col_1_varchar
+FROM worklog5743 tbl1 , worklog5743 tbl2
+WHERE tbl1.col_1_varchar = tbl2.col_1_varchar ;
+
+# Select in subquey
+SELECT tbl1.col_1_varchar = REPEAT("c", 4000) FROM worklog5743 tbl1
+WHERE col_1_varchar IN (SELECT tbl2.col_1_varchar FROM worklog5743 tbl2) ;
+SELECT tbl1.col_1_varchar = REPEAT("c", 4000) FROM worklog5743 tbl1
+WHERE col_1_varchar NOT IN (SELECT tbl2.col_1_varchar FROM worklog5743 tbl2) ;
+SELECT tbl1.col_1_varchar = REPEAT("c", 4000) FROM worklog5743 tbl1 WHERE
+col_1_varchar IN (SELECT tbl2.col_1_varchar FROM worklog5743 tbl2)
+AND col_1_varchar = REPEAT("c", 4000);
+SELECT tbl1.col_1_varchar = REPEAT("c", 4000) FROM worklog5743 tbl1
+WHERE col_1_varchar in (
+SELECT tbl2.col_1_varchar FROM worklog5743 tbl2
+WHERE tbl1.col_1_varchar != tbl2.col_1_varchar
+) ;
+SELECT tbl1.col_1_varchar = REPEAT("c", 4000) FROM worklog5743 tbl1
+WHERE col_1_varchar in (
+SELECT tbl2.col_1_varchar FROM worklog5743 tbl2
+WHERE tbl1.col_1_varchar = tbl2.col_1_varchar
+) ;
+
+# function
+SELECT
+REVERSE(col_1_varchar) = REPEAT("c", 4000) ,
+REVERSE(REVERSE(col_1_varchar)) = REPEAT("c", 4000)
+FROM worklog5743;
+SELECT
+UPPER(col_1_varchar) = REPEAT("c", 4000) ,
+UPPER(col_1_varchar) = REPEAT("C", 4000) ,
+LOWER(UPPER(col_1_varchar)) = REPEAT("c", 4000)
+FROM worklog5743;
+SELECT
+col_1_varchar = REPEAT("c", 4000)
+FROM worklog5743 WHERE col_1_varchar like '%c__%';
+SELECT SUBSTRING(INSERT(col_1_varchar, 1, 4, 'kkkk'),1,10) FROM worklog5743 ;
+SELECT CONCAT(SUBSTRING(col_1_varchar,-5,3),'append') FROM worklog5743 ;
+
+
+DROP TABLE worklog5743;
+
+#------------------------------------------------------------------------------
+# Prefix index with NULL values
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) ,
+col_2_varchar VARCHAR (4000) ,
+UNIQUE INDEX (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743
+VALUES(concat(REPEAT("a", 2000),REPEAT("b", 1000),REPEAT("c", 1000)), REPEAT("o", 4000));
+INSERT INTO worklog5743
+VALUES(concat(REPEAT("a", 2000),REPEAT("b", 2000)), REPEAT("o", 4000));
+INSERT INTO worklog5743 VALUES(NULL,NULL);
+INSERT INTO worklog5743 VALUES(NULL,NULL);
+# check IS
+SELECT COLUMN_NAME,INDEX_NAME,SUB_PART,INDEX_TYPE
+FROM INFORMATION_SCHEMA.STATISTICS WHERE table_name = 'worklog5743' ;
+SELECT col_1_varchar FROM worklog5743 WHERE col_1_varchar IS NULL;
+SELECT col_1_varchar = concat(REPEAT("a", 2000),REPEAT("b", 2000))
+FROM worklog5743 WHERE col_1_varchar IS NOT NULL ORDER BY 1;
+
+
+DROP TABLE worklog5743;
+
+# -----------------------------------------------------------------------------
+#  Try drop and add secondary prefix index
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(3072))) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+# Create index
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+# Drop index
+DROP INDEX prefix_idx ON worklog5743;
+
+SELECT col_1_varchar = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varchar = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+# Again add index
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+# -----------------------------------------------------------------------------
+
+#  Try drop and add primary prefix index
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY `prefix_primary` (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+# Create index
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+# Drop index
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+
+SELECT col_1_varchar = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varchar = REPEAT("c", 4000)
+AND col_2_varchar = REPEAT("o", 4000);
+# Again add index
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_varchar(3072));
+
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+--error 1062
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+
+# -----------------------------------------------------------------------------
+
+#  Try drop and add both (primary/secondary) prefix index
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY `prefix_primary` (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+# Create index
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+# Drop primary index
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+# Drop secondary index
+DROP INDEX prefix_idx ON worklog5743;
+
+SELECT col_1_varchar = REPEAT("a", 4000) , col_2_varchar = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_varchar = REPEAT("c", 4000)
+WHERE col_1_varchar = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varchar = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000);
+# Again add index
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_varchar(3072));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+--error 1062
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+DELETE FROM worklog5743 WHERE col_1_varchar = REPEAT("b", 4000);
+SELECT col_1_varchar = REPEAT("c", 4000) FROM worklog5743;
+DROP TABLE worklog5743;
+
+
+# -----------------------------------------------------------------------------
+# Drop index from differnt session
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR(4000) , col_2_varchar VARCHAR(4000) ,
+PRIMARY KEY (col_1_varchar (3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("c", 3500) , REPEAT("o", 3500));
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (3072));
+
+# Start new session
+--connect (con1,localhost,root,,)
+
+
+--echo " Switching to con1 connection For select "
+--connection con1
+SELECT col_1_varchar = REPEAT("c", 3500) , col_2_varchar = REPEAT("o", 3500)
+FROM worklog5743;
+
+--echo " Switching to default connection For DMLs "
+--connection default
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 3500) , REPEAT("o", 3500));
+SELECT col_1_varchar = REPEAT("b", 3500) FROM worklog5743
+WHERE col_2_varchar = REPEAT("o", 3500);
+COMMIT;
+
+--echo " Switching to con1 connection For Dropping index and some DMLs "
+--connection con1
+START TRANSACTION;
+INSERT INTO worklog5743 VALUES(REPEAT("k", 3500),REPEAT("p", 3500));
+# Drop primary index
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+UPDATE worklog5743 SET col_1_varchar  = REPEAT("b", 3500)
+WHERE col_1_varchar = REPEAT("a", 3500)
+AND col_2_varchar = REPEAT("o", 3500);
+SELECT col_1_varchar = REPEAT("b", 3500) FROM worklog5743
+WHERE col_2_varchar = REPEAT("o", 3500);
+
+--echo " Switching to default connection For DELETE "
+--connection default
+DELETE FROM worklog5743 WHERE col_1_varchar  = REPEAT("b", 3500);
+SELECT col_1_varchar = REPEAT("a", 3500) FROM worklog5743
+WHERE col_2_varchar = REPEAT("p", 3500);
+
+--echo " Switching to con1 connection to commit changes "
+--connection con1
+COMMIT;
+
+--echo " Switching to default connection to drop and end sub-test "
+--connection default
+DROP TABLE worklog5743;
+
+
+
+# -----------------------------------------------------------------------------
+#  Create prefix index with length < 3072 , length = 3072 , length > 3072
+# - varbinary data type + secondary index
+CREATE TABLE worklog5743 (
+col_1_varbinary VARBINARY (4000) , col_2_varbinary VARBINARY (4000) ,
+PRIMARY KEY (col_1_varbinary(3072))) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+# Create index of 3072
+CREATE INDEX prefix_idx ON worklog5743(col_1_varbinary (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_varbinary = REPEAT("a", 4000) , col_2_varbinary = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+WHERE col_1_varbinary = REPEAT("a", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("c", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+# Drop index
+DROP INDEX prefix_idx ON worklog5743;
+SELECT col_1_varbinary = REPEAT("b", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("b", 4000)
+AND col_2_varbinary = REPEAT("p", 4000);
+
+
+# Again add index length < 3072
+CREATE INDEX prefix_idx ON worklog5743(col_1_varbinary (2000));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_varbinary = REPEAT("a", 4000) FROM worklog5743;
+UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+WHERE col_1_varbinary = REPEAT("a", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("c", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+# Drop index
+DROP INDEX prefix_idx ON worklog5743;
+
+# Again add index length > 3072.
+# If "innodb_large_prefix" is turned on, than the index prefix larger than 3072
+# will be truncated to 3072. If the table is REDUNDANT and COMPACT, which does
+# not support prefix > 767, the create index will be rejected. 
+CREATE INDEX prefix_idx ON worklog5743(col_1_varbinary (4000));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_varbinary = REPEAT("a", 4000) FROM worklog5743;
+UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000)
+WHERE col_1_varbinary = REPEAT("a", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_varbinary = REPEAT("c", 4000);
+SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_varbinary = REPEAT("c", 4000)
+AND col_2_varbinary = REPEAT("o", 4000);
+
+
+DROP TABLE worklog5743;
+
+# -----------------------------------------------------------------------------
+# Create prefix index with length < 3072 , length = 3072 , length > 3072
+#  text data type + secondary index
+CREATE TABLE worklog5743 (col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(500))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+# Create index of 3072
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (3072));
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000)
+FROM worklog5743;
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000)
+AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+# Drop index
+DROP INDEX prefix_idx ON worklog5743;
+SELECT col_1_text = REPEAT("b", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("b", 4000) AND col_2_text = REPEAT("p", 4000);
+
+# Again add index length < 3072
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (1000));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_text = REPEAT("a", 4000) FROM worklog5743;
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+# Drop index
+DROP INDEX prefix_idx ON worklog5743;
+
+# Again add index length > 3072. Expect error.Length exceeds maximum supported
+# key length
+# Again add index length > 3072.
+# If "innodb_large_prefix" is turned on, than the index prefix larger than 3072
+# will be truncated to 3072. If the table is REDUNDANT and COMPACT, which does
+# not support prefix > 767, the create index will be rejected.
+CREATE INDEX prefix_idx ON worklog5743(col_1_text (4000));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_text = REPEAT("a", 4000) FROM worklog5743;
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000) AND col_2_text = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000) AND col_2_text = REPEAT("o", 4000);
+
+DROP TABLE worklog5743;
+
+
+# -----------------------------------------------------------------------------
+# Create prefix index with length < 948 , length = 948 , length > 948
+# For compressed row type + primary key
+CREATE TABLE worklog5743 (
+col_1_text TEXT (4000) , col_2_text TEXT (4000) ,
+PRIMARY KEY (col_1_text(948))
+) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2, engine = innodb;
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000));
+# Create index of 767
+INSERT INTO worklog5743 VALUES(REPEAT("b", 4000) , REPEAT("p", 4000));
+SELECT col_1_text = REPEAT("a", 4000) , col_2_text = REPEAT("o", 4000) FROM worklog5743;
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000)
+AND col_2_text = REPEAT("o", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000)
+AND col_2_text = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000)
+AND col_2_text = REPEAT("o", 4000);
+# Drop index
+#DROP INDEX prefix_idx ON worklog5743;
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+SELECT col_1_text = REPEAT("b", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("b", 4000)
+AND col_2_text = REPEAT("p", 4000);
+
+# Again add index length < 767
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_text (700));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_text = REPEAT("a", 4000) FROM worklog5743;
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000)
+AND col_2_text = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000)
+AND col_2_text = REPEAT("o", 4000);
+# Drop index
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+
+# Again add index length > 948. Expect error 'to big row ' due to exceed
+# in key length.  
+-- error 139
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_text (950));
+INSERT INTO worklog5743 VALUES(REPEAT("a", 4000),REPEAT("o", 4000));
+SELECT col_1_text = REPEAT("a", 4000) FROM worklog5743;
+UPDATE worklog5743 SET col_1_text = REPEAT("c", 4000)
+WHERE col_1_text = REPEAT("a", 4000)
+AND col_2_text = REPEAT("o", 4000);
+DELETE FROM worklog5743 WHERE col_1_text = REPEAT("c", 4000);
+SELECT col_1_text = REPEAT("c", 4000) FROM worklog5743
+WHERE col_1_text = REPEAT("c", 4000)
+AND col_2_text = REPEAT("o", 4000);
+
+DROP TABLE worklog5743;
+
+# -----------------------------------------------------------------------------
+#  Create prefix index with length < 3072 , length = 3072 , length > 3072
+# data types VARCHAR
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , PRIMARY KEY (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_varchar (900));
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+# Again add index length > 3072. Expect error.Length exceeds maximum supported
+# key length
+# Again add index length > 3072.
+# If "innodb_large_prefix" is turned on, than the index prefix larger than 3072
+# will be truncated to 3072. If the table is REDUNDANT and COMPACT, which does
+# not support prefix > 767, the create index will be rejected.
+# Index length is truncated only for 'create index' , but error if we add
+# prefix index with length > 3072
+--error ER_TOO_LONG_KEY
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_varchar (3073));
+DROP TABLE worklog5743;
+
+
+CREATE TABLE worklog5743 (
+col_1_BLOB BLOB (4000) , PRIMARY KEY (col_1_BLOB(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_BLOB (500));
+ALTER TABLE worklog5743 DROP PRIMARY KEY;
+# Negative case
+# Again add index length > 3072. Expect error.Length exceeds maximum supported
+# key length
+# Index length is truncated only for 'create index' , but error if we add
+# prefix index with length > 3072
+--error ER_TOO_LONG_KEY
+ALTER TABLE worklog5743 ADD PRIMARY KEY (col_1_BLOB (3073));
+
+DROP TABLE worklog5743;
+
+# -----------------------------------------------------------------------------
+# Error on adding larger prefix if violates unique index.
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000)
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+INSERT INTO worklog5743
+VALUES(concat(REPEAT("a", 2000),REPEAT("b", 1000),REPEAT("c", 1000)),
+REPEAT("o", 4000));
+INSERT INTO worklog5743
+VALUES(concat(REPEAT("a", 2000),REPEAT("b", 2000)), REPEAT("o", 4000));
+--error 1062
+ALTER TABLE worklog5743 ADD PRIMARY KEY `pk_idx` (col_1_varchar(3000));
+DROP TABLE worklog5743;
+
+# -----------------------------------------------------------------------------
+set global innodb_large_prefix=0;
+# Prefix index > 767 is allowed if innodb_large_prefix is set to 1
+--error ER_TOO_LONG_KEY
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(3072))
+) ROW_FORMAT=DYNAMIC, engine = innodb;
+
+
+# -----------------------------------------------------------------------------
+set global innodb_large_prefix=0;
+# Backward compatibility test - Index lenghth > 767 is truncated for REDUNDANT
+# and COMPACT
+CREATE TABLE worklog5743 (
+col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) ,
+PRIMARY KEY (col_1_varchar(767))
+) engine = innodb;
+# Prefix index > 767 is truncated with REDUNDANT and COMPACT 
+CREATE INDEX prefix_idx ON worklog5743(col_1_varchar (1000));
+DROP TABLE worklog5743;
+#------------------------------------------------------------------------------
+
+eval SET GLOBAL innodb_file_format=$innodb_file_format_orig;
+eval SET GLOBAL innodb_file_per_table=$innodb_file_per_table_orig;
+eval SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig;
+eval SET GLOBAL innodb_large_prefix=$innodb_large_prefix_orig;

=== modified file 'mysql-test/suite/innodb/t/innodb_stats.test'
--- a/mysql-test/suite/innodb/t/innodb_stats.test	2010-06-29 07:10:56 +0000
+++ b/mysql-test/suite/innodb/t/innodb_stats.test	2011-05-30 13:56:01 +0000
@@ -62,4 +62,6 @@ CREATE TABLE test_innodb_stats (
 
 -- disable_query_log
 DROP TABLE test_innodb_stats;
-DROP DATABASE innodb;
+
+DROP TABLE mysql.innodb_index_stats;
+DROP TABLE mysql.innodb_table_stats;

=== modified file 'mysql-test/suite/innodb/t/innodb_stats_drop_locked.test'
--- a/mysql-test/suite/innodb/t/innodb_stats_drop_locked.test	2010-09-21 14:02:54 +0000
+++ b/mysql-test/suite/innodb/t/innodb_stats_drop_locked.test	2011-05-30 13:56:01 +0000
@@ -22,11 +22,11 @@ ANALYZE TABLE innodb_stats_drop_locked;
 
 SET autocommit=0;
 
-SELECT table_name FROM innodb.table_stats
+SELECT table_name FROM mysql.innodb_table_stats
 WHERE table_name='innodb_stats_drop_locked'
 FOR UPDATE;
 
-SELECT table_name FROM innodb.index_stats
+SELECT table_name FROM mysql.innodb_index_stats
 WHERE table_name='innodb_stats_drop_locked'
 FOR UPDATE;
 
@@ -52,11 +52,12 @@ COMMIT;
 
 # the stats should be there
 
-SELECT table_name FROM innodb.table_stats
+SELECT table_name FROM mysql.innodb_table_stats
 WHERE table_name='innodb_stats_drop_locked';
 
-SELECT table_name FROM innodb.index_stats
+SELECT table_name FROM mysql.innodb_index_stats
 WHERE table_name='innodb_stats_drop_locked';
 
 -- disable_query_log
-DROP DATABASE innodb;
+DROP TABLE mysql.innodb_index_stats;
+DROP TABLE mysql.innodb_table_stats;

=== modified file 'mysql-test/suite/rpl/r/rpl_crash_safe_master.result'
--- a/mysql-test/suite/rpl/r/rpl_crash_safe_master.result	2011-05-05 09:58:48 +0000
+++ b/mysql-test/suite/rpl/r/rpl_crash_safe_master.result	2011-05-12 21:51:20 +0000
@@ -69,7 +69,6 @@ include/stop_slave.inc
 CREATE TABLE t1(a LONGBLOB) ENGINE=INNODB;
 # Test case3: Set DEBUG POINT in the middle of binlog to
 #             make the master crash for transaction.
-SET SESSION debug="d,half_binlogged_transaction";
 BEGIN;
 INSERT INTO t1 (a) VALUES (REPEAT('a',6144));
 INSERT INTO t1 (a) VALUES (REPEAT('a',6144));
@@ -95,6 +94,7 @@ INSERT INTO t1 (a) VALUES (REPEAT('a',61
 INSERT INTO t1 (a) VALUES (REPEAT('a',6144));
 INSERT INTO t1 (a) VALUES (REPEAT('a',6144));
 INSERT INTO t1 (a) VALUES (REPEAT('a',6144));
+SET SESSION debug="d,half_binlogged_transaction";
 COMMIT;
 ERROR HY000: Lost connection to MySQL server during query
 # Restart the master server
@@ -110,8 +110,8 @@ COUNT(*)
 0
 # Test case4: Set DEBUG POINT in the middle of binlog to
 #             make the master crash for non-transaction.
-SET SESSION debug="d,half_binlogged_transaction";
 CREATE TABLE t2(a LONGBLOB) ENGINE=MYISAM;
+SET SESSION debug="d,half_binlogged_transaction";
 INSERT INTO t2 (a) VALUES (REPEAT('a',16384));
 ERROR HY000: Lost connection to MySQL server during query
 # Restart the master server

=== modified file 'mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result'
--- a/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result	2011-02-23 20:01:27 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result	2011-05-12 21:51:20 +0000
@@ -150,7 +150,7 @@ SET GLOBAL binlog_stmt_cache_size= ORIGI
 BEGIN;
 Repeat statement 'INSERT INTO t1 VALUES($n, repeat("a", 32))' 128 times
 COMMIT;
-include/wait_for_slave_sql_error.inc [errno=1534]
+include/wait_for_slave_sql_error.inc [errno=1197]
 SELECT count(*) FROM t1;
 count(*)
 0

=== modified file 'mysql-test/suite/rpl/t/rpl_crash_safe_master.test'
--- a/mysql-test/suite/rpl/t/rpl_crash_safe_master.test	2011-05-05 09:58:48 +0000
+++ b/mysql-test/suite/rpl/t/rpl_crash_safe_master.test	2011-05-12 21:51:20 +0000
@@ -168,7 +168,6 @@ CREATE TABLE t1(a LONGBLOB) ENGINE=INNOD
 
 -- echo # Test case3: Set DEBUG POINT in the middle of binlog to
 -- echo #             make the master crash for transaction.
-SET SESSION debug="d,half_binlogged_transaction";
 BEGIN;
 let $rows= 24;
 WHILE($rows)
@@ -178,6 +177,7 @@ WHILE($rows)
 }
 # Write file to make mysql-test-run.pl expect crash and restart
 -- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+SET SESSION debug="d,half_binlogged_transaction";
 # Run the crashing query
 -- error 2013
 COMMIT;
@@ -199,12 +199,12 @@ SELECT COUNT(*) FROM t1;
 
 -- echo # Test case4: Set DEBUG POINT in the middle of binlog to
 -- echo #             make the master crash for non-transaction.
-SET SESSION debug="d,half_binlogged_transaction";
-# Write file to make mysql-test-run.pl expect crash and restart
--- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
 -- let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1)
 -- let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
 CREATE TABLE t2(a LONGBLOB) ENGINE=MYISAM;
+# Write file to make mysql-test-run.pl expect crash and restart
+-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+SET SESSION debug="d,half_binlogged_transaction";
 -- error 2013
 INSERT INTO t2 (a) VALUES (REPEAT('a',16384));
 

=== modified file 'mysql-test/suite/sys_vars/r/all_vars.result'
--- a/mysql-test/suite/sys_vars/r/all_vars.result	2011-04-22 03:07:02 +0000
+++ b/mysql-test/suite/sys_vars/r/all_vars.result	2011-06-06 19:24:25 +0000
@@ -27,6 +27,7 @@ INNODB_SYNC_ARRAY_SIZE
 INNODB_MONITOR_DISABLE
 INNODB_FILE_FORMAT_MAX
 INNODB_MONITOR_ENABLE
+INNODB_LARGE_PREFIX
 INNODB_STATS_TRANSIENT_SAMPLE_PAGES
 INNODB_ROLLBACK_SEGMENTS
 INNODB_STATS_PERSISTENT_SAMPLE_PAGES
@@ -42,5 +43,6 @@ INNODB_SYNC_ARRAY_SIZE
 INNODB_MONITOR_DISABLE
 INNODB_FILE_FORMAT_MAX
 INNODB_MONITOR_ENABLE
+INNODB_LARGE_PREFIX
 drop table t1;
 drop table t2;

=== modified file 'mysql-test/t/innodb_mysql_lock.test'
--- a/mysql-test/t/innodb_mysql_lock.test	2011-05-10 10:55:34 +0000
+++ b/mysql-test/t/innodb_mysql_lock.test	2011-06-01 12:24:51 +0000
@@ -300,6 +300,10 @@ SELECT * FROM t1;
 --echo # Connection con1
 --connection con1
 SET lock_wait_timeout=1;
+# Test with two timeouts, as the first version of this patch
+# only worked with one timeout.
+--error ER_LOCK_WAIT_TIMEOUT
+ALTER TABLE t1 ADD INDEX idx(value);
 --error ER_LOCK_WAIT_TIMEOUT
 ALTER TABLE t1 ADD INDEX idx(value);
 

=== modified file 'mysql-test/t/innodb_mysql_sync.test'
--- a/mysql-test/t/innodb_mysql_sync.test	2011-04-13 18:43:08 +0000
+++ b/mysql-test/t/innodb_mysql_sync.test	2011-06-01 12:24:51 +0000
@@ -2,6 +2,7 @@
 # Test file for InnoDB tests that require the debug sync facility
 #
 --source include/have_innodb.inc
+--source include/have_debug.inc
 --source include/have_debug_sync.inc
 # Save the initial number of concurrent sessions.
 --source include/count_sessions.inc
@@ -152,133 +153,155 @@ disconnect con1;
 --echo #           that implement add_index
 --echo #
 
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+connect(con1,localhost,root);
+connect(con2,localhost,root);
+
+--echo # Test 1: Secondary index, should not block reads (original test case).
+
+--echo # Connection default
+connection default;
+CREATE DATABASE db1;
+CREATE TABLE db1.t1(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, value INT) engine=innodb;
+INSERT INTO db1.t1(value) VALUES (1), (2);
+SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
+--echo # Sending:
+--send ALTER TABLE db1.t1 ADD INDEX(value)
+
+--echo # Connection con1
+connection con1;
+SET DEBUG_SYNC= "now WAIT_FOR manage";
+# Neither of these two statements should be blocked
+USE db1;
+SELECT * FROM t1;
+SET DEBUG_SYNC= "now SIGNAL query";
+
+--echo # Connection default
+connection default;
+--echo # Reaping: ALTER TABLE db1.t1 ADD INDEX(value)
+--reap
+DROP DATABASE db1;
+
+--echo # Test 2: Primary index (implicit), should block reads.
+
+CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb;
+SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
+--echo # Sending:
+--send ALTER TABLE t1 ADD UNIQUE INDEX(a)
+
+--echo # Connection con1
+connection con1;
+SET DEBUG_SYNC= "now WAIT_FOR manage";
+USE test;
+--echo # Sending:
+--send SELECT * FROM t1
+
+--echo # Connection con2
+connection con2;
+--echo # Waiting for SELECT to be blocked by the metadata lock on t1
+let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
+  WHERE state= 'Waiting for table metadata lock'
+  AND info='SELECT * FROM t1';
+--source include/wait_condition.inc
+SET DEBUG_SYNC= "now SIGNAL query";
+
+--echo # Connection default
+connection default;
+--echo # Reaping: ALTER TABLE t1 ADD UNIQUE INDEX(a)
+--reap
+
+--echo # Connection con1
+connection con1;
+--echo # Reaping: SELECT * FROM t1
+--reap
+
+--echo # Test 3: Primary index (explicit), should block reads.
+
+--echo # Connection default
+connection default;
+ALTER TABLE t1 DROP INDEX a;
+SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
+--echo # Sending:
+--send ALTER TABLE t1 ADD PRIMARY KEY (a)
+
+--echo # Connection con1
+connection con1;
+SET DEBUG_SYNC= "now WAIT_FOR manage";
+--echo # Sending:
+--send SELECT * FROM t1
+
+--echo # Connection con2
+connection con2;
+--echo # Waiting for SELECT to be blocked by the metadata lock on t1
+let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
+  WHERE state= 'Waiting for table metadata lock'
+  AND info='SELECT * FROM t1';
+--source include/wait_condition.inc
+SET DEBUG_SYNC= "now SIGNAL query";
+
+--echo # Connection default
+connection default;
+--echo # Reaping: ALTER TABLE t1 ADD PRIMARY KEY (a)
+--reap
+
+--echo # Connection con1
+connection con1;
+--echo # Reaping: SELECT * FROM t1
+--reap
+
+--echo # Test 4: Secondary unique index, should not block reads.
+
+--echo # Connection default
+connection default;
+SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
+--echo # Sending:
+--send ALTER TABLE t1 ADD UNIQUE (b)
+
+--echo # Connection con1
+connection con1;
+SET DEBUG_SYNC= "now WAIT_FOR manage";
+SELECT * FROM t1;
+SET DEBUG_SYNC= "now SIGNAL query";
+
+--echo # Connection default
+connection default;
+--echo # Reaping: ALTER TABLE t1 ADD UNIQUE (b)
+--reap
+
+disconnect con1;
+disconnect con2;
+SET DEBUG_SYNC= "RESET";
+DROP TABLE t1;
+
+
 --echo #
---echo # DISABLED due to Bug#11815600
+--echo # Bug#11853126 RE-ENABLE CONCURRENT READS WHILE CREATING SECONDARY INDEX
+--echo #              IN INNODB
 --echo #
 
-#--disable_warnings
-#DROP DATABASE IF EXISTS db1;
-#DROP TABLE IF EXISTS t1;
-#--enable_warnings
-#
-#connect(con1,localhost,root);
-#connect(con2,localhost,root);
-#
-#--echo # Test 1: Secondary index, should not block reads (original test case).
-#
-#--echo # Connection default
-#connection default;
-#CREATE DATABASE db1;
-#CREATE TABLE db1.t1(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, value INT) engine=innodb;
-#INSERT INTO db1.t1(value) VALUES (1), (2);
-#SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
-#--echo # Sending:
-#--send ALTER TABLE db1.t1 ADD INDEX(value)
-#
-#--echo # Connection con1
-#connection con1;
-#SET DEBUG_SYNC= "now WAIT_FOR manage";
-# # Neither of these two statements should be blocked
-#USE db1;
-#SELECT * FROM t1;
-#SET DEBUG_SYNC= "now SIGNAL query";
-#
-#--echo # Connection default
-#connection default;
-#--echo # Reaping: ALTER TABLE db1.t1 ADD INDEX(value)
-#--reap
-#DROP DATABASE db1;
-#
-#--echo # Test 2: Primary index (implicit), should block reads.
-#
-#CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb;
-#SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
-#--echo # Sending:
-#--send ALTER TABLE t1 ADD UNIQUE INDEX(a)
-#
-#--echo # Connection con1
-#connection con1;
-#SET DEBUG_SYNC= "now WAIT_FOR manage";
-#USE test;
-#--echo # Sending:
-#--send SELECT * FROM t1
-#
-#--echo # Connection con2
-#connection con2;
-#--echo # Waiting for SELECT to be blocked by the metadata lock on t1
-#let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
-#  WHERE state= 'Waiting for table metadata lock'
-#  AND info='SELECT * FROM t1';
-#--source include/wait_condition.inc
-#SET DEBUG_SYNC= "now SIGNAL query";
-#
-#--echo # Connection default
-#connection default;
-#--echo # Reaping: ALTER TABLE t1 ADD UNIQUE INDEX(a)
-#--reap
-#
-#--echo # Connection con1
-#connection con1;
-#--echo # Reaping: SELECT * FROM t1
-#--reap
-#
-#--echo # Test 3: Primary index (explicit), should block reads.
-#
-#--echo # Connection default
-#connection default;
-#ALTER TABLE t1 DROP INDEX a;
-#SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
-#--echo # Sending:
-#--send ALTER TABLE t1 ADD PRIMARY KEY (a)
-#
-#--echo # Connection con1
-#connection con1;
-#SET DEBUG_SYNC= "now WAIT_FOR manage";
-#--echo # Sending:
-#--send SELECT * FROM t1
-#
-#--echo # Connection con2
-#connection con2;
-#--echo # Waiting for SELECT to be blocked by the metadata lock on t1
-#let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
-#  WHERE state= 'Waiting for table metadata lock'
-#  AND info='SELECT * FROM t1';
-#--source include/wait_condition.inc
-#SET DEBUG_SYNC= "now SIGNAL query";
-#
-#--echo # Connection default
-#connection default;
-#--echo # Reaping: ALTER TABLE t1 ADD PRIMARY KEY (a)
-#--reap
-#
-#--echo # Connection con1
-#connection con1;
-#--echo # Reaping: SELECT * FROM t1
-#--reap
-#
-#--echo # Test 4: Secondary unique index, should not block reads.
-#
-#--echo # Connection default
-#connection default;
-#SET DEBUG_SYNC= "alter_table_manage_keys SIGNAL manage WAIT_FOR query";
-#--echo # Sending:
-#--send ALTER TABLE t1 ADD UNIQUE (b)
-#
-#--echo # Connection con1
-#connection con1;
-#SET DEBUG_SYNC= "now WAIT_FOR manage";
-#SELECT * FROM t1;
-#SET DEBUG_SYNC= "now SIGNAL query";
-#
-#--echo # Connection default
-#connection default;
-#--echo # Reaping: ALTER TABLE t1 ADD UNIQUE (b)
-#--reap
-#
-#disconnect con1;
-#disconnect con2;
-#SET DEBUG_SYNC= "RESET";
-#DROP TABLE t1;
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL) engine=innodb;
+INSERT INTO t1 VALUES (1, 12345), (2, 23456);
+
+--echo # Connection con1
+--connect (con1,localhost,root)
+SET SESSION debug= "+d,alter_table_rollback_new_index";
+--error ER_UNKNOWN_ERROR
+ALTER TABLE t1 ADD PRIMARY KEY(a);
+SELECT * FROM t1;
+
+--echo # Connection default
+--connection default
+SELECT * FROM t1;
+DROP TABLE t1;
+disconnect con1;
 
 
 # Check that all connections opened by test cases in this file are really

=== modified file 'mysql-test/t/myisam_debug.test'
--- a/mysql-test/t/myisam_debug.test	2009-05-04 09:05:16 +0000
+++ b/mysql-test/t/myisam_debug.test	2011-05-31 13:52:09 +0000
@@ -54,4 +54,7 @@ INTO @thread_id;
 KILL QUERY @thread_id;
 CHECK TABLE t1; 
 DROP TABLE t1,t2;
+CONNECTION insertConn;
+--error ER_NOT_KEYFILE
+REAP;
 DISCONNECT insertConn;

=== modified file 'mysql-test/t/query_cache_debug.test'
--- a/mysql-test/t/query_cache_debug.test	2010-10-08 12:16:20 +0000
+++ b/mysql-test/t/query_cache_debug.test	2011-05-30 15:17:22 +0000
@@ -208,7 +208,17 @@ SET DEBUG_SYNC="now WAIT_FOR parked1_2";
 --echo ** until a broadcast signal reaches them causing both threads to 
 --echo ** come alive and check the condition.
 SET DEBUG_SYNC="now SIGNAL go2";
+--echo ** Wait for thd2 to receive the signal
+let $wait_condition=
+  SELECT COUNT(*) = 1 FROM information_schema.processlist
+  WHERE state = "Waiting for query cache lock";
+--source include/wait_condition.inc
 SET DEBUG_SYNC="now SIGNAL go3";
+--echo ** Wait for thd3 to receive the signal
+let $wait_condition=
+  SELECT COUNT(*) = 2 FROM information_schema.processlist
+  WHERE state = "Waiting for query cache lock";
+--source include/wait_condition.inc
 
 --echo **
 --echo ** Finally signal the DELETE statement on THD1 one last time.

=== modified file 'mysql-test/t/ssl.test'
--- a/mysql-test/t/ssl.test	2011-03-29 08:01:07 +0000
+++ b/mysql-test/t/ssl.test	2011-05-31 13:52:09 +0000
@@ -24,6 +24,32 @@ SHOW STATUS LIKE 'Ssl_cipher';
 connection default;
 disconnect ssl_con;
 
+--echo #
+--echo # Bug#54790: Use of non-blocking mode for sockets limits performance
+--echo #
+
+--echo # Open ssl_con and set a timeout.
+connect (ssl_con,localhost,root,,,,,SSL);
+
+LET $ID= `SELECT connection_id()`;
+SET @@SESSION.wait_timeout = 2;
+
+--echo # Wait for ssl_con to be disconnected.
+connection default;
+let $wait_condition=
+  SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST
+  WHERE ID = $ID;
+--source include/wait_condition.inc
+
+--echo # Check that ssl_con has been disconnected.
+connection ssl_con;
+--echo # CR_SERVER_LOST, CR_SERVER_GONE_ERROR
+--error 2006,2013
+SELECT 1;
+
+connection default;
+disconnect ssl_con;
+
 # Wait till all disconnects are completed
 --source include/wait_until_count_sessions.inc
 

=== modified file 'mysql-test/t/wait_timeout.test'
--- a/mysql-test/t/wait_timeout.test	2010-10-19 11:54:28 +0000
+++ b/mysql-test/t/wait_timeout.test	2011-05-31 13:52:09 +0000
@@ -137,6 +137,62 @@ disconnect con1;
 # The last connect is to keep tools checking the current test happy.
 connect (default,localhost,root,,test,,);
 
+--echo #
+--echo # Bug#54790: Use of non-blocking mode for sockets limits performance
+--echo #
+
+--echo #
+--echo # Test UNIX domain sockets timeout.
+--echo #
+
+--echo # Open con1 and set a timeout.
+connect(con1,localhost,root,,);
+
+LET $ID= `SELECT connection_id()`;
+SET @@SESSION.wait_timeout = 2;
+
+--echo # Wait for con1 to be disconnected.
+connection default;
+let $wait_condition=
+  SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST
+  WHERE ID = $ID;
+--source include/wait_condition.inc
+
+--echo # Check that con1 has been disconnected.
+connection con1;
+--echo # CR_SERVER_LOST, CR_SERVER_GONE_ERROR
+--error 2006,2013
+SELECT 1;
+
+disconnect con1;
+connection default;
+
+--echo #
+--echo # Test TCP/IP sockets timeout.
+--echo #
+
+--echo # Open con1 and set a timeout.
+connect(con1,127.0.0.1,root,,);
+
+LET $ID= `SELECT connection_id()`;
+SET @@SESSION.wait_timeout = 2;
+
+--echo # Wait for con1 to be disconnected.
+connection default;
+let $wait_condition=
+  SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST
+  WHERE ID = $ID;
+--source include/wait_condition.inc
+
+--echo # Check that con1 has been disconnected.
+connection con1;
+--echo # CR_SERVER_LOST, CR_SERVER_GONE_ERROR
+--error 2006,2013
+SELECT 1;
+
+disconnect con1;
+connection default;
+
 # Wait till all disconnects are completed
 --source include/wait_until_count_sessions.inc
 

=== modified file 'mysql-test/t/xa.test'
--- a/mysql-test/t/xa.test	2011-04-14 08:47:14 +0000
+++ b/mysql-test/t/xa.test	2011-05-31 13:52:09 +0000
@@ -119,7 +119,8 @@ xa rollback 'a','c';
 connect (con3,localhost,root,,);
 --connection con3
 xa start 'a','c';
-
+--connection con1
+--reap
 --disconnect con1
 --disconnect con3
 --connection default
@@ -227,7 +228,11 @@ XA START 'xid1';
 XA END 'xid1';
 XA ROLLBACK 'xid1';
 
+connection con1;
+REAP;
 disconnect con1;
+
+connection default;
 DROP TABLE t1;
 
 

=== modified file 'mysys/my_handler_errors.h'
--- a/mysys/my_handler_errors.h	2011-03-29 12:56:34 +0000
+++ b/mysys/my_handler_errors.h	2011-05-31 09:30:59 +0000
@@ -81,7 +81,8 @@ static const char *handler_error_message
   "File to short; Expected more data in file",
   "Read page with wrong checksum",
   "Too many active concurrent transactions",
-  "Record not matching the given partition set"
+  "Record not matching the given partition set",
+  "Index column length exceeds limit"
 };
 
 extern void my_handler_error_register(void);

=== modified file 'sql-common/client.c'
--- a/sql-common/client.c	2011-05-27 15:46:36 +0000
+++ b/sql-common/client.c	2011-06-06 19:24:25 +0000
@@ -11,7 +11,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
 /*
   This file is included by both libmysql.c (the MySQL client C API)
@@ -25,10 +25,8 @@
   - Support for reading local file with LOAD DATA LOCAL
   - SHARED memory handling
   - Prepared statements
-  
   - Things that only works for the server
-  - Alarm handling on connect
-  
+
   In all other cases, the code should be idential for the client and
   server.
 */ 
@@ -92,19 +90,11 @@ my_bool	net_flush(NET *net);
 #  include <sys/un.h>
 #endif
 
-#if defined(__WIN__)
-#define perror(A)
-#else
+#ifndef _WIN32
 #include <errno.h>
 #define SOCKET_ERROR -1
 #endif
 
-#ifdef __WIN__
-#define CONNECT_TIMEOUT 20
-#else
-#define CONNECT_TIMEOUT 0
-#endif
-
 #include "client_settings.h"
 #include <sql_common.h>
 #include <mysql/client_plugin.h>
@@ -127,197 +117,80 @@ static void mysql_close_free_options(MYS
 static void mysql_close_free(MYSQL *mysql);
 static void mysql_prune_stmt_list(MYSQL *mysql);
 
-#if !defined(__WIN__)
-static int wait_for_data(my_socket fd, uint timeout);
-#endif
-
 CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
 
 /* Server error code and message */
 unsigned int mysql_server_last_errno;
 char mysql_server_last_error[MYSQL_ERRMSG_SIZE];
 
-/****************************************************************************
-  A modified version of connect().  my_connect() allows you to specify
-  a timeout value, in seconds, that we should wait until we
-  derermine we can't connect to a particular host.  If timeout is 0,
-  my_connect() will behave exactly like connect().
-
-  Base version coded by Steve Bernacki, Jr. <steve@stripped>
-*****************************************************************************/
-
-int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
-	       uint timeout)
-{
-#if defined(__WIN__)
-  DBUG_ENTER("my_connect");
-  DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen));
-#else
-  int flags, res, s_err;
-  DBUG_ENTER("my_connect");
-  DBUG_PRINT("enter", ("fd: %d  timeout: %u", fd, timeout));
+/**
+  Convert the connect timeout option to a timeout value for VIO
+  functions (vio_socket_connect() and vio_io_wait()).
+
+  @param mysql  Connection handle (client side).
+
+  @return The timeout value in milliseconds, or -1 if no timeout.
+*/
+
+static int get_vio_connect_timeout(MYSQL *mysql)
+{
+  int timeout_ms;
+  uint timeout_sec;
 
   /*
-    If they passed us a timeout of zero, we should behave
-    exactly like the normal connect() call does.
+    A timeout of 0 means no timeout. Also, the connect_timeout
+    option value is in seconds, while VIO timeouts are measured
+    in milliseconds. Hence, check for a possible overflow. In
+    case of overflow, set to no timeout.
   */
+  timeout_sec= mysql->options.connect_timeout;
 
-  if (timeout == 0)
-    DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen));
-
-  flags = fcntl(fd, F_GETFL, 0);	  /* Set socket to not block */
-#ifdef O_NONBLOCK
-  fcntl(fd, F_SETFL, flags | O_NONBLOCK);  /* and save the flags..  */
-#endif
+  if (!timeout_sec || (timeout_sec > INT_MAX/1000))
+    timeout_ms= -1;
+  else
+    timeout_ms= (int) (timeout_sec * 1000);
 
-  DBUG_PRINT("info", ("connecting non-blocking"));
-  res= connect(fd, (struct sockaddr*) name, namelen);
-  DBUG_PRINT("info", ("connect result: %d  errno: %d", res, errno));
-  s_err= errno;			/* Save the error... */
-  fcntl(fd, F_SETFL, flags);
-  if ((res != 0) && (s_err != EINPROGRESS))
-  {
-    errno= s_err;			/* Restore it */
-    DBUG_RETURN(-1);
-  }
-  if (res == 0)				/* Connected quickly! */
-    DBUG_RETURN(0);
-  DBUG_RETURN(wait_for_data(fd, timeout));
-#endif
+  return timeout_ms;
 }
 
 
-/*
-  Wait up to timeout seconds for a connection to be established.
+#ifdef _WIN32
 
-  We prefer to do this with poll() as there is no limitations with this.
-  If not, we will use select()
-*/
+/**
+  Convert the connect timeout option to a timeout value for WIN32
+  synchronization functions.
 
-#if !defined(__WIN__)
+  @remark Specific for WIN32 connection methods shared memory and
+          named pipe.
 
-static int wait_for_data(my_socket fd, uint timeout)
+  @param mysql  Connection handle (client side).
+
+  @return The timeout value in milliseconds, or INFINITE if no timeout.
+*/
+
+static DWORD get_win32_connect_timeout(MYSQL *mysql)
 {
-#ifdef HAVE_POLL
-  struct pollfd ufds;
-  int res;
-  DBUG_ENTER("wait_for_data");
+  DWORD timeout_ms;
+  uint timeout_sec;
 
-  DBUG_PRINT("info", ("polling"));
-  ufds.fd= fd;
-  ufds.events= POLLIN | POLLPRI;
-  if (!(res= poll(&ufds, 1, (int) timeout*1000)))
-  {
-    DBUG_PRINT("info", ("poll timed out"));
-    errno= EINTR;
-    DBUG_RETURN(-1);
-  }
-  DBUG_PRINT("info",
-             ("poll result: %d  errno: %d  revents: 0x%02d  events: 0x%02d",
-              res, errno, ufds.revents, ufds.events));
-  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
-    DBUG_RETURN(-1);
   /*
-    At this point, we know that something happened on the socket.
-    But this does not means that everything is alright.
-    The connect might have failed. We need to retrieve the error code
-    from the socket layer. We must return success only if we are sure
-    that it was really a success. Otherwise we might prevent the caller
-    from trying another address to connect to.
+    A timeout of 0 means no timeout. Also, the connect_timeout
+    option value is in seconds, while WIN32 timeouts are in
+    milliseconds. Hence, check for a possible overflow. In case
+    of overflow, set to no timeout.
   */
-  {
-    int         s_err;
-    socklen_t   s_len= sizeof(s_err);
-
-    DBUG_PRINT("info", ("Get SO_ERROR from non-blocked connected socket."));
-    res= getsockopt(fd, SOL_SOCKET, SO_ERROR, &s_err, &s_len);
-    DBUG_PRINT("info", ("getsockopt res: %d  s_err: %d", res, s_err));
-    if (res)
-      DBUG_RETURN(res);
-    /* getsockopt() was successful, check the retrieved status value. */
-    if (s_err)
-    {
-      errno= s_err;
-      DBUG_RETURN(-1);
-    }
-    /* Status from connect() is zero. Socket is successfully connected. */
-  }
-  DBUG_RETURN(0);
-#else
-  SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
-  fd_set sfds;
-  struct timeval tv;
-  time_t start_time, now_time;
-  int res, s_err;
-  DBUG_ENTER("wait_for_data");
+  timeout_sec= mysql->options.connect_timeout;
 
-  if (fd >= FD_SETSIZE)				/* Check if wrong error */
-    DBUG_RETURN(0);					/* Can't use timeout */
+  if (!timeout_sec || (timeout_sec > INT_MAX/1000))
+    timeout_ms= INFINITE;
+  else
+    timeout_ms= (DWORD) (timeout_sec * 1000);
 
-  /*
-    Our connection is "in progress."  We can use the select() call to wait
-    up to a specified period of time for the connection to suceed.
-    If select() returns 0 (after waiting howevermany seconds), our socket
-    never became writable (host is probably unreachable.)  Otherwise, if
-    select() returns 1, then one of two conditions exist:
-   
-    1. An error occured.  We use getsockopt() to check for this.
-    2. The connection was set up sucessfully: getsockopt() will
-    return 0 as an error.
-   
-    Thanks goes to Andrew Gierth <andrew@stripped>
-    who posted this method of timing out a connect() in
-    comp.unix.programmer on August 15th, 1997.
-  */
+  return timeout_ms;
+}
 
-  FD_ZERO(&sfds);
-  FD_SET(fd, &sfds);
-  /*
-    select could be interrupted by a signal, and if it is, 
-    the timeout should be adjusted and the select restarted
-    to work around OSes that don't restart select and 
-    implementations of select that don't adjust tv upon
-    failure to reflect the time remaining
-   */
-  start_time= my_time(0);
-  for (;;)
-  {
-    tv.tv_sec = (long) timeout;
-    tv.tv_usec = 0;
-#if defined(HPUX10)
-    if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
-      break;
-#else
-    if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
-      break;
 #endif
-    if (res == 0)					/* timeout */
-      DBUG_RETURN(-1);
-    now_time= my_time(0);
-    timeout-= (uint) (now_time - start_time);
-    if (errno != EINTR || (int) timeout <= 0)
-      DBUG_RETURN(-1);
-  }
-
-  /*
-    select() returned something more interesting than zero, let's
-    see if we have any errors.  If the next two statements pass,
-    we've got an open socket!
-  */
 
-  s_err=0;
-  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
-    DBUG_RETURN(-1);
-
-  if (s_err)
-  {						/* getsockopt could succeed */
-    errno = s_err;
-    DBUG_RETURN(-1);					/* but return an error... */
-  }
-  DBUG_RETURN(0);					/* ok */
-#endif /* HAVE_POLL */
-}
-#endif /* !defined(__WIN__) */
 
 /**
   Set the internal error message to mysql handler
@@ -401,17 +274,18 @@ void set_mysql_extended_error(MYSQL *mys
   Create a named pipe connection
 */
 
-#ifdef __WIN__
+#ifdef _WIN32
 
-HANDLE create_named_pipe(MYSQL *mysql, uint connect_timeout, char **arg_host,
-			 char **arg_unix_socket)
+static HANDLE create_named_pipe(MYSQL *mysql, DWORD connect_timeout,
+                                const char **arg_host,
+                                const char **arg_unix_socket)
 {
   HANDLE hPipe=INVALID_HANDLE_VALUE;
   char pipe_name[1024];
   DWORD dwMode;
   int i;
   my_bool testing_named_pipes=0;
-  char *host= *arg_host, *unix_socket= *arg_unix_socket;
+  const char *host= *arg_host, *unix_socket= *arg_unix_socket;
 
   if ( ! unix_socket || (unix_socket)[0] == 0x00)
     unix_socket = mysql_unix_port;
@@ -442,7 +316,7 @@ HANDLE create_named_pipe(MYSQL *mysql, u
       return INVALID_HANDLE_VALUE;
     }
     /* wait for for an other instance */
-    if (! WaitNamedPipe(pipe_name, connect_timeout*1000) )
+    if (!WaitNamedPipe(pipe_name, connect_timeout))
     {
       set_mysql_extended_error(mysql, CR_NAMEDPIPEWAIT_ERROR, unknown_sqlstate,
                                ER(CR_NAMEDPIPEWAIT_ERROR),
@@ -475,15 +349,16 @@ HANDLE create_named_pipe(MYSQL *mysql, u
 /*
   Create new shared memory connection, return handler of connection
 
-  SYNOPSIS
-    create_shared_memory()
-    mysql		Pointer of mysql structure
-    net			Pointer of net structure
-    connect_timeout	Timeout of connection
+  @param mysql  Pointer of mysql structure
+  @param net    Pointer of net structure
+  @param connect_timeout  Timeout of connection (in milliseconds)
+
+  @return HANDLE to the shared memory area.
 */
 
 #ifdef HAVE_SMEM
-HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
+static HANDLE create_shared_memory(MYSQL *mysql, NET *net,
+                                   DWORD connect_timeout)
 {
   ulong smem_buffer_length = shared_memory_buffer_length + 4;
   /*
@@ -588,7 +463,7 @@ HANDLE create_shared_memory(MYSQL *mysql
   }
 
   /* Wait of answer from server */
-  if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) !=
+  if (WaitForSingleObject(event_connect_answer, connect_timeout) !=
       WAIT_OBJECT_0)
   {
     error_allow = CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR;
@@ -737,7 +612,7 @@ cli_safe_read(MYSQL *mysql)
     DBUG_PRINT("error",("Wrong connection or packet. fd: %s  len: %lu",
 			vio_description(net->vio),len));
 #ifdef MYSQL_SERVER
-    if (net->vio && vio_was_interrupted(net->vio))
+    if (net->vio && (net->last_errno == ER_NET_READ_INTERRUPTED))
       return (packet_error);
 #endif /*MYSQL_SERVER*/
     end_server(mysql);
@@ -830,9 +705,10 @@ cli_advanced_command(MYSQL *mysql, enum
   mysql->info=0;
   mysql->affected_rows= ~(my_ulonglong) 0;
   /*
-    We don't want to clear the protocol buffer on COM_QUIT, because if
-    the previous command was a shutdown command, we may have the
-    response for the COM_QUIT already in the communication buffer
+    Do not check the socket/protocol buffer on COM_QUIT as the
+    result of a previous command might not have been read. This
+    can happen if a client sends a query but does not reap the
+    result before attempting to close the connection.
   */
   net_clear(&mysql->net, (command != COM_QUIT));
 
@@ -1713,7 +1589,6 @@ mysql_init(MYSQL *mysql)
   }
   else
     memset(mysql, 0, sizeof(*(mysql)));
-  mysql->options.connect_timeout= CONNECT_TIMEOUT;
   mysql->charset=default_client_charset_info;
   strmov(mysql->net.sqlstate, not_error_sqlstate);
 
@@ -2961,10 +2836,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
   const char    *scramble_plugin;
   ulong		pkt_length;
   NET		*net= &mysql->net;
-#ifdef MYSQL_SERVER
-  thr_alarm_t   alarmed;
-  ALARM		alarm_buff;
-#endif
 #ifdef __WIN__
   HANDLE	hPipe=INVALID_HANDLE_VALUE;
 #endif
@@ -3038,9 +2909,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
        mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) &&
       (!host || !strcmp(host,LOCAL_HOST)))
   {
+    HANDLE handle_map;
     DBUG_PRINT("info", ("Using shared memory"));
-    if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) ==
-	INVALID_HANDLE_VALUE)
+
+    handle_map= create_shared_memory(mysql, net,
+                                     get_win32_connect_timeout(mysql));
+
+    if (handle_map == INVALID_HANDLE_VALUE)
     {
       DBUG_PRINT("error",
 		 ("host: '%s'  socket: '%s'  shared memory: %s  have_tcpip: %d",
@@ -3106,8 +2981,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
     UNIXaddr.sun_family= AF_UNIX;
     strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1);
 
-    if (my_connect(sock, (struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
-		   mysql->options.connect_timeout))
+    if (vio_socket_connect(net->vio, (struct sockaddr *) &UNIXaddr,
+                           sizeof(UNIXaddr), get_vio_connect_timeout(mysql)))
     {
       DBUG_PRINT("error",("Got error %d on connect to local server",
 			  socket_errno));
@@ -3121,15 +2996,16 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
     }
     mysql->options.protocol=MYSQL_PROTOCOL_SOCKET;
   }
-#elif defined(__WIN__)
+#elif defined(_WIN32)
   if (!net->vio &&
       (mysql->options.protocol == MYSQL_PROTOCOL_PIPE ||
        (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
        (! have_tcpip && (unix_socket || !host && is_NT()))))
   {
-    if ((hPipe= create_named_pipe(mysql, mysql->options.connect_timeout,
-                                  (char**) &host, (char**) &unix_socket)) ==
-	INVALID_HANDLE_VALUE)
+    hPipe= create_named_pipe(mysql, get_win32_connect_timeout(mysql),
+                             &host, &unix_socket);
+
+    if (hPipe == INVALID_HANDLE_VALUE)
     {
       DBUG_PRINT("error",
 		 ("host: '%s'  socket: '%s'  have_tcpip: %d",
@@ -3157,10 +3033,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
        mysql->options.protocol == MYSQL_PROTOCOL_TCP))
   {
     struct addrinfo *res_lst, *client_bind_ai_lst= NULL, hints, *t_res;
-    int gai_errno;
     char port_buf[NI_MAXSERV];
     my_socket sock= SOCKET_ERROR;
-    int saved_error= 0, status= -1, bind_result= 0;
+    int gai_errno, saved_error= 0, status= -1, bind_result= 0;
+    uint flags= VIO_BUFFERED_READ;
 
     unix_socket=0;				/* This is not used */
 
@@ -3172,16 +3048,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
 
     my_snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
     DBUG_PRINT("info",("Server name: '%s'.  TCP sock: %d", host, port));
-#ifdef MYSQL_SERVER
-    thr_alarm_init(&alarmed);
-    thr_alarm(&alarmed, mysql->options.connect_timeout, &alarm_buff);
-#endif
-
-    DBUG_PRINT("info",("IP '%s'", "client"));
-
-#ifdef MYSQL_SERVER
-    thr_end_alarm(&alarmed);
-#endif
 
     memset(&hints, 0, sizeof(hints));
     hints.ai_socktype= SOCK_STREAM;
@@ -3292,20 +3158,39 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
         DBUG_PRINT("info", ("Successfully bound client side of socket"));
       }
 
+      /* Create a new Vio object to abstract the socket. */
+      if (!net->vio)
+      {
+        if (!(net->vio= vio_new(sock, VIO_TYPE_TCPIP, flags)))
+        {
+          set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
+          closesocket(sock);
+          goto error;
+        }
+      }
+      /* Just reinitialize if one is already allocated. */
+      else if (vio_reset(net->vio, VIO_TYPE_TCPIP, sock, NULL, flags))
+      {
+        set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
+        closesocket(sock);
+        goto error;
+      }
+
       DBUG_PRINT("info", ("Connect socket"));
-      status= my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
-                         mysql->options.connect_timeout);
+      status= vio_socket_connect(net->vio, t_res->ai_addr, t_res->ai_addrlen,
+                                 get_vio_connect_timeout(mysql));
       /*
-        Here we rely on my_connect() to return success only if the
-        connect attempt was really successful. Otherwise we would stop
-        trying another address, believing we were successful.
+        Here we rely on vio_socket_connect() to return success only if
+        the connect attempt was really successful. Otherwise we would
+        stop trying another address, believing we were successful.
       */
       if (!status)
         break;
 
       /*
-        Save value as socket errno might be overwritten due to
-        calling a socket function below.
+        Save either the socket error status or the error code of
+        the failed vio_connection operation. It is necessary to
+        avoid having it overwritten by later operations.
       */
       saved_error= socket_errno;
 
@@ -3334,15 +3219,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
                                 ER(CR_CONN_HOST_ERROR), host, saved_error);
       goto error;
     }
-
-    net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
-    if (! net->vio )
-    {
-      DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
-      set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
-      closesocket(sock);
-      goto error;
-    }
   }
 
   DBUG_PRINT("info", ("net->vio: %p", net->vio));
@@ -3376,12 +3252,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
   /* Get version info */
   mysql->protocol_version= PROTOCOL_VERSION;	/* Assume this */
   if (mysql->options.connect_timeout &&
-      vio_poll_read(net->vio, mysql->options.connect_timeout))
+      (vio_io_wait(net->vio, VIO_IO_EVENT_READ,
+                   get_vio_connect_timeout(mysql)) < 1))
   {
     set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
                              ER(CR_SERVER_LOST_EXTENDED),
                              "waiting for initial communication packet",
-                             errno);
+                             socket_errno);
     goto error;
   }
 
@@ -3396,7 +3273,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,cons
       set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
                                ER(CR_SERVER_LOST_EXTENDED),
                                "reading initial communication packet",
-                               errno);
+                               socket_errno);
     goto error;
   }
   pkt_end= (char*)net->read_pos + pkt_length;

=== modified file 'sql/binlog.cc'
--- a/sql/binlog.cc	2011-05-26 15:20:09 +0000
+++ b/sql/binlog.cc	2011-05-30 06:25:47 +0000
@@ -35,6 +35,7 @@ const char *log_bin_basename= 0;
 MYSQL_BIN_LOG mysql_bin_log(&sync_binlog_period);
 
 static int binlog_init(void *p);
+static void binlog_start_trans_and_stmt(THD *thd, Log_event *start_event);
 static int binlog_close_connection(handlerton *hton, THD *thd);
 static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv);
 static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv);
@@ -85,10 +86,17 @@ class binlog_cache_data
 {
 public:
 
-  binlog_cache_data(): m_pending(0),
-  incident(FALSE), saved_max_binlog_cache_size(0), ptr_binlog_cache_use(0),
-  ptr_binlog_cache_disk_use(0)
-  { }
+  binlog_cache_data(bool trx_cache_arg,
+                    ulong max_binlog_cache_size_arg,
+                    ulong *ptr_binlog_cache_use_arg,
+                    ulong *ptr_binlog_cache_disk_use_arg)
+  : trx_cache(trx_cache_arg), m_pending(0), incident(FALSE),
+  saved_max_binlog_cache_size(max_binlog_cache_size_arg),
+  ptr_binlog_cache_use(ptr_binlog_cache_use_arg),
+  ptr_binlog_cache_disk_use(ptr_binlog_cache_disk_use_arg)
+  {
+    cache_log.end_of_file= saved_max_binlog_cache_size;
+  }
   
   virtual ~binlog_cache_data()
   {
@@ -116,11 +124,16 @@ public:
     incident= TRUE;
   }
   
-  bool has_incident(void)
+  bool has_incident(void) const
   {
     return(incident);
   }
 
+  bool is_trx_cache() const
+  {
+    return trx_cache;
+  }
+
   virtual void reset()
   {
     compute_statistics();
@@ -137,36 +150,6 @@ public:
     DBUG_ASSERT(empty());
   }
 
-  void set_binlog_cache_info(ulong param_max_binlog_cache_size,
-                             ulong *param_ptr_binlog_cache_use,
-                             ulong *param_ptr_binlog_cache_disk_use)
-  {
-    /*
-      The assertions guarantee that the set_binlog_cache_info is
-      called just once and information passed as parameters are
-      never zero.
-
-      This is done while calling the constructor binlog_cache_mngr.
-      We cannot set informaton in the constructor binlog_cache_data
-      because the space for binlog_cache_mngr is allocated through
-      a placement new.
-
-      In the future, we can refactor this and change it to avoid
-      the set_binlog_info. 
-    */
-    DBUG_ASSERT(saved_max_binlog_cache_size == 0 &&
-                param_max_binlog_cache_size != 0 &&
-                ptr_binlog_cache_use == 0 &&
-                param_ptr_binlog_cache_use != 0 &&
-                ptr_binlog_cache_disk_use == 0 &&
-                param_ptr_binlog_cache_disk_use != 0);
-
-    saved_max_binlog_cache_size= param_max_binlog_cache_size;
-    ptr_binlog_cache_use= param_ptr_binlog_cache_use;
-    ptr_binlog_cache_disk_use= param_ptr_binlog_cache_disk_use;
-    cache_log.end_of_file= saved_max_binlog_cache_size;
-  }
-
   /*
     Cache to store data before copying it to the binary log.
   */
@@ -189,6 +172,12 @@ protected:
     cache_log.end_of_file= saved_max_binlog_cache_size;
   }
 
+  /*
+    Defines if this is either a trx-cache or stmt-cache, respectively, a
+    transactional or non-transactional cache.
+  */
+  bool trx_cache;
+
 private:
   /*
     Pending binrows event. This event is the event where the rows are currently
@@ -243,9 +232,16 @@ private:
 class binlog_trx_cache_data : public binlog_cache_data
 {
 public:
-  binlog_trx_cache_data() : m_cannot_rollback(FALSE),
-  before_stmt_pos(MY_OFF_T_UNDEF)
-  {}
+  binlog_trx_cache_data(bool trx_cache_arg,
+                        ulong max_binlog_cache_size_arg,
+                        ulong *ptr_binlog_cache_use_arg,
+                        ulong *ptr_binlog_cache_disk_use_arg)
+  : binlog_cache_data(trx_cache_arg,
+                      max_binlog_cache_size_arg,
+                      ptr_binlog_cache_use_arg,
+                      ptr_binlog_cache_disk_use_arg),
+    m_cannot_rollback(FALSE), before_stmt_pos(MY_OFF_T_UNDEF)
+  {   }
 
   void reset()
   {
@@ -254,7 +250,7 @@ public:
     binlog_cache_data::reset();
   }
 
-  bool cannot_rollback()
+  bool cannot_rollback() const
   {
     return m_cannot_rollback;
   }
@@ -269,9 +265,9 @@ public:
     return my_b_tell(&cache_log);
   }
 
-  my_off_t get_prev_position()
+  my_off_t get_prev_position() const
   {
-     return(before_stmt_pos);
+     return before_stmt_pos;
   }
 
   void set_prev_position(my_off_t pos)
@@ -303,24 +299,26 @@ private:
     Binlog position before the start of the current statement.
   */
   my_off_t before_stmt_pos;
+
+  binlog_trx_cache_data& operator=(const binlog_trx_cache_data& info);
+  binlog_trx_cache_data(const binlog_trx_cache_data& info);
 };
 
 class binlog_cache_mngr {
 public:
-  binlog_cache_mngr(ulong param_max_binlog_stmt_cache_size,
-                    ulong param_max_binlog_cache_size,
-                    ulong *param_ptr_binlog_stmt_cache_use,
-                    ulong *param_ptr_binlog_stmt_cache_disk_use,
-                    ulong *param_ptr_binlog_cache_use,
-                    ulong *param_ptr_binlog_cache_disk_use)
-  {
-    stmt_cache.set_binlog_cache_info(param_max_binlog_stmt_cache_size,
-                                     param_ptr_binlog_stmt_cache_use,
-                                     param_ptr_binlog_stmt_cache_disk_use);
-    trx_cache.set_binlog_cache_info(param_max_binlog_cache_size,
-                                    param_ptr_binlog_cache_use,
-                                    param_ptr_binlog_cache_disk_use);
-  }
+  binlog_cache_mngr(ulong max_binlog_stmt_cache_size_arg,
+                    ulong *ptr_binlog_stmt_cache_use_arg,
+                    ulong *ptr_binlog_stmt_cache_disk_use_arg,
+                    ulong max_binlog_cache_size_arg,
+                    ulong *ptr_binlog_cache_use_arg,
+                    ulong *ptr_binlog_cache_disk_use_arg)
+  : stmt_cache(FALSE, max_binlog_stmt_cache_size_arg,
+               ptr_binlog_stmt_cache_use_arg,
+               ptr_binlog_stmt_cache_disk_use_arg),
+    trx_cache(TRUE, max_binlog_cache_size_arg,
+              ptr_binlog_cache_use_arg,
+              ptr_binlog_cache_disk_use_arg)
+  {  }
 
   void reset_stmt_cache()
   {
@@ -337,7 +335,7 @@ public:
     trx_cache.set_cannot_rollback();
   }
 
-  bool trx_cache_cannot_rollback()
+  bool trx_cache_cannot_rollback() const
   {
     return trx_cache.cannot_rollback();
   }
@@ -434,8 +432,6 @@ binlog_trans_log_savepos(THD *thd, my_of
 {
   DBUG_ENTER("binlog_trans_log_savepos");
   DBUG_ASSERT(pos != NULL);
-  if (thd_get_ha_data(thd, binlog_hton) == NULL)
-    thd->binlog_setup_trx_data();
   binlog_cache_mngr *const cache_mngr=
     (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
   DBUG_ASSERT(mysql_bin_log.is_open());
@@ -467,7 +463,6 @@ binlog_trans_log_truncate(THD *thd, my_o
   DBUG_PRINT("enter", ("pos: %lu", (ulong) pos));
 
   DBUG_ASSERT(thd_get_ha_data(thd, binlog_hton) != NULL);
-  /* Only true if binlog_trans_log_savepos() wasn't called before */
   DBUG_ASSERT(pos != ~(my_off_t) 0);
 
   binlog_cache_mngr *const cache_mngr=
@@ -516,23 +511,27 @@ static int binlog_close_connection(handl
   @param thd                The thread whose transaction should be flushed
   @param cache_data         Pointer to the cache
   @param end_ev             The end event either commit/rollback
-  @param is_transactional   The type of the cache: transactional or
-                            non-transactional
 
   @return
     nonzero if an error pops up when flushing the cache.
 */
 static inline int
-binlog_flush_cache(THD *thd, binlog_cache_data* cache_data, Log_event *end_evt,
-                   bool is_transactional)
+binlog_flush_cache(THD *thd, binlog_cache_data* cache_data, Log_event *end_evt)
 {
   DBUG_ENTER("binlog_flush_cache");
   int error= 0;
 
+  DBUG_ASSERT((end_evt->is_using_trans_cache() && cache_data->is_trx_cache()) ||
+              (!end_evt->is_using_trans_cache() && !cache_data->is_trx_cache()));
+
   if (!cache_data->empty())
   {
-    if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
+    if (thd->binlog_flush_pending_rows_event(TRUE, cache_data->is_trx_cache()))
+      DBUG_RETURN(1);
+
+    if (end_evt->write(&cache_data->cache_log))
       DBUG_RETURN(1);
+ 
     /*
       Doing a commit or a rollback including non-transactional tables,
       i.e., ending a transaction where we might write the transaction
@@ -543,8 +542,10 @@ binlog_flush_cache(THD *thd, binlog_cach
       were, we would have to ensure that we're not ending a statement
       inside a stored function.
     */
-    error= mysql_bin_log.write(thd, &cache_data->cache_log, end_evt,
-                               cache_data->has_incident());
+    bool prepared= (end_evt->get_type_code() == XID_EVENT);
+    error= mysql_bin_log.write(thd, &cache_data->cache_log,
+                               cache_data->has_incident(),
+                               prepared);
   }
   cache_data->reset();
 
@@ -565,10 +566,10 @@ static inline int
 binlog_commit_flush_stmt_cache(THD *thd,
                                binlog_cache_mngr *cache_mngr)
 {
+  binlog_cache_data* cache_data= &cache_mngr->stmt_cache;
   Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"),
-                          FALSE, TRUE, TRUE, 0);
-  return (binlog_flush_cache(thd, &cache_mngr->stmt_cache, &end_evt,
-                             FALSE));
+                          cache_data->is_trx_cache(), FALSE, TRUE, 0, TRUE);
+  return binlog_flush_cache(thd, cache_data, &end_evt);
 }
 
 /**
@@ -583,10 +584,10 @@ binlog_commit_flush_stmt_cache(THD *thd,
 static inline int
 binlog_commit_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr)
 {
+  binlog_cache_data* cache_data= &cache_mngr->trx_cache;
   Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"),
-                          TRUE, TRUE, TRUE, 0);
-  return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
-                             TRUE));
+                          cache_data->is_trx_cache(), FALSE, TRUE, 0, TRUE);
+  return binlog_flush_cache(thd, cache_data, &end_evt);
 }
 
 /**
@@ -601,10 +602,10 @@ binlog_commit_flush_trx_cache(THD *thd,
 static inline int
 binlog_rollback_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr)
 {
+  binlog_cache_data* cache_data= &cache_mngr->trx_cache;
   Query_log_event end_evt(thd, STRING_WITH_LEN("ROLLBACK"),
-                          TRUE, TRUE, TRUE, 0);
-  return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
-                             TRUE));
+                          cache_data->is_trx_cache(), FALSE, TRUE, 0, TRUE);
+  return binlog_flush_cache(thd, cache_data, &end_evt);
 }
 
 /**
@@ -622,8 +623,7 @@ binlog_commit_flush_trx_cache(THD *thd,
                               my_xid xid)
 {
   Xid_log_event end_evt(thd, xid);
-  return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
-                             TRUE));
+  return binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt);
 }
 
 /**
@@ -643,18 +643,13 @@ binlog_truncate_trx_cache(THD *thd, binl
 {
   DBUG_ENTER("binlog_truncate_trx_cache");
   int error=0;
-  /*
-    This function handles transactional changes and as such this flag
-    equals to true.
-  */
-  bool const is_transactional= TRUE;
 
   DBUG_PRINT("info", ("thd->options={ %s %s}, transaction: %s",
                       FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT),
                       FLAGSTR(thd->variables.option_bits, OPTION_BEGIN),
                       all ? "all" : "stmt"));
 
-  thd->binlog_remove_pending_rows_event(TRUE, is_transactional);
+  thd->binlog_remove_pending_rows_event(TRUE, TRUE);
   /*
     If rolling back an entire transaction or a single statement not
     inside a transaction, we reset the transaction cache.
@@ -675,7 +670,7 @@ binlog_truncate_trx_cache(THD *thd, binl
   else
     cache_mngr->trx_cache.restore_prev_position();
 
-  DBUG_ASSERT(thd->binlog_get_pending_rows_event(is_transactional) == NULL);
+  DBUG_ASSERT(thd->binlog_get_pending_rows_event(TRUE) == NULL);
   DBUG_RETURN(error);
 }
 
@@ -1148,33 +1143,6 @@ stmt_has_updated_trans_table(const THD *
   return (FALSE);
 }
 
-/** 
-  This function checks if either a trx-cache or a non-trx-cache should
-  be used. If @c bin_log_direct_non_trans_update is active or the format
-  is either MIXED or ROW, the cache to be used depends on the flag @c
-  is_transactional. 
-
-  On the other hand, if binlog_format is STMT or direct option is
-  OFF, the trx-cache should be used if and only if the statement is
-  transactional or the trx-cache is not empty. Otherwise, the
-  non-trx-cache should be used.
-
-  @param thd              The client thread.
-  @param is_transactional The changes are related to a trx-table.
-  @return
-    @c true if a trx-cache should be used, @c false otherwise.
-*/
-bool use_trans_cache(const THD* thd, bool is_transactional)
-{
-  binlog_cache_mngr *const cache_mngr=
-    (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
-
-  return
-    ((thd->is_current_stmt_binlog_format_row() ||
-     thd->variables.binlog_direct_non_trans_update) ? is_transactional :
-     (is_transactional || !cache_mngr->trx_cache.empty()));
-}
-
 /**
   This function checks if a transaction, either a multi-statement
   or a single statement transaction is about to commit or not.
@@ -3533,7 +3501,7 @@ MYSQL_BIN_LOG::remove_pending_rows_event
   DBUG_ASSERT(cache_mngr);
 
   binlog_cache_data *cache_data=
-    cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional));
+    cache_mngr->get_binlog_cache_data(is_transactional);
 
   if (Rows_log_event* pending= cache_data->pending())
   {
@@ -3570,7 +3538,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_row
   DBUG_ASSERT(cache_mngr);
 
   binlog_cache_data *cache_data=
-    cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional));
+    cache_mngr->get_binlog_cache_data(is_transactional);
 
   DBUG_PRINT("info", ("cache_mngr->pending(): 0x%lx", (long) cache_data->pending()));
 
@@ -3616,7 +3584,7 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
     */
     thd->binlog_evt_union.unioned_events= TRUE;
     thd->binlog_evt_union.unioned_events_trans |=
-      event_info->use_trans_cache();
+      event_info->is_using_trans_cache();
     DBUG_RETURN(0);
   }
 
@@ -3628,7 +3596,7 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
   bool const end_stmt=
     thd->locked_tables_mode && thd->lex->requires_prelocking();
   if (thd->binlog_flush_pending_rows_event(end_stmt,
-                                           event_info->use_trans_cache()))
+                                           event_info->is_using_trans_cache()))
     DBUG_RETURN(error);
 
   /*
@@ -3653,28 +3621,15 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
       DBUG_RETURN(0);
 #endif /* HAVE_REPLICATION */
 
-    IO_CACHE *file= NULL;
-    binlog_cache_mngr *cache_mngr= NULL;
-    binlog_cache_data *cache_data= 0;
-    bool is_trans_cache= FALSE;
-
-    if (event_info->use_direct_logging())
-    {
-      file= &log_file;
-      mysql_mutex_lock(&LOCK_log);
-    }
-    else
-    {
-      if (thd->binlog_setup_trx_data())
-        goto err;
-
-      cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
-      is_trans_cache= use_trans_cache(thd, event_info->use_trans_cache());
-      file= cache_mngr->get_binlog_cache_log(is_trans_cache);
-      cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache);
+    DBUG_ASSERT(event_info->is_using_trans_cache() || event_info->is_using_stmt_cache());
+    
+    binlog_start_trans_and_stmt(thd, event_info);
 
-      thd->binlog_start_trans_and_stmt();
-    }
+    bool is_trans_cache= event_info->is_using_trans_cache();
+    binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+    IO_CACHE *file= cache_mngr->get_binlog_cache_log(is_trans_cache);
+    binlog_cache_data *cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache);
+    
     DBUG_PRINT("info",("event type: %d",event_info->get_type_code()));
 
     /*
@@ -3689,16 +3644,11 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
     {
       if (!thd->is_current_stmt_binlog_format_row())
       {
-        /* three possibility for cache_type at this point */
-        DBUG_ASSERT(event_info->cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE ||
-                    event_info->cache_type == Log_event::EVENT_STMT_CACHE ||
-                    event_info->cache_type == Log_event::EVENT_NO_CACHE);
- 
         if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
         {
           Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
                              thd->first_successful_insert_id_in_prev_stmt_for_binlog,
-                             event_info->cache_type);
+                             event_info->event_cache_type, event_info->event_logging_type);
           if (e.write(file))
             goto err;
         }
@@ -3709,14 +3659,16 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
                              nb_elements()));
           Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT,
                              thd->auto_inc_intervals_in_cur_stmt_for_binlog.
-                             minimum(), event_info->cache_type);
+                             minimum(), event_info->event_cache_type,
+                             event_info->event_logging_type);
           if (e.write(file))
             goto err;
         }
         if (thd->rand_used)
         {
           Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2,
-                           event_info->cache_type);
+                           event_info->event_cache_type,
+                           event_info->event_logging_type);
           if (e.write(file))
             goto err;
         }
@@ -3738,7 +3690,8 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
                                  user_var_event->length,
                                  user_var_event->type,
                                  user_var_event->charset_number, flags,
-                                 event_info->cache_type);
+                                 event_info->event_cache_type,
+                                 event_info->event_logging_type);
             if (e.write(file))
               goto err;
           }
@@ -3764,25 +3717,12 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
     error= 0;
 
 err:
-    if (event_info->use_direct_logging())
+    if (event_info->is_using_immediate_logging())
     {
-      if (!error)
-      {
-        bool synced;
-        if ((error= flush_and_sync(&synced)))
-          goto unlock;
-
-        if ((error= RUN_HOOK(binlog_storage, after_flush,
-                 (thd, log_file_name, file->pos_in_file, synced))))
-        {
-          sql_print_error("Failed to run 'after_flush' hooks");
-          goto unlock;
-        }
-        signal_update();
-        rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
-      }
-unlock:
-      mysql_mutex_unlock(&LOCK_log);
+      error |= mysql_bin_log.write(thd, &cache_data->cache_log,
+                                   cache_data->has_incident(),
+                                   FALSE);
+      cache_data->reset();
     }
 
     if (error)
@@ -4135,7 +4075,18 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE
   return 0;                                     // All OK
 }
 
-bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
+/**
+  Writes an incident event to the binary log.
+
+  @param ev   Incident event to be written
+  @param lock If the binary lock should be locked or not
+
+  @retval
+    0    error
+  @retval
+    1    success
+*/
+bool MYSQL_BIN_LOG::write_incident(Incident_log_event *ev, bool lock)
 {
   uint error= 0;
   DBUG_ENTER("MYSQL_BIN_LOG::write_incident");
@@ -4143,40 +4094,61 @@ bool MYSQL_BIN_LOG::write_incident(THD *
   if (!is_open())
     DBUG_RETURN(error);
 
-  LEX_STRING const write_error_msg=
-    { C_STRING_WITH_LEN("error writing to the binary log") };
-  Incident incident= INCIDENT_LOST_EVENTS;
-  Incident_log_event ev(thd, incident, write_error_msg);
   if (lock)
     mysql_mutex_lock(&LOCK_log);
-  error= ev.write(&log_file);
+
+  error= ev->write(&log_file);
+
   if (lock)
   {
     if (!error && !(error= flush_and_sync(0)))
     {
       signal_update();
-      error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
+      error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED |
+                              RP_FORCE_ROTATE);
     }
     mysql_mutex_unlock(&LOCK_log);
   }
+
   DBUG_RETURN(error);
 }
 
 /**
+  Creates an incident event and writes it to the binary log.
+
+  @param thd  Thread variable
+  @param ev   Incident event to be written
+  @param lock If the binary lock should be locked or not
+
+  @retval
+    0    error
+  @retval
+    1    success
+*/
+bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
+{
+  DBUG_ENTER("MYSQL_BIN_LOG::write_incident");
+
+  if (!is_open())
+    DBUG_RETURN(0);
+
+  LEX_STRING const write_error_msg=
+    { C_STRING_WITH_LEN("error writing to the binary log") };
+  Incident incident= INCIDENT_LOST_EVENTS;
+  Incident_log_event ev(thd, incident, write_error_msg);
+
+  DBUG_RETURN(write_incident(&ev, lock));
+}
+
+/**
   Write a cached log entry to the binary log.
-  - To support transaction over replication, we wrap the transaction
-  with BEGIN/COMMIT or BEGIN/ROLLBACK in the binary log.
-  We want to write a BEGIN/ROLLBACK block when a non-transactional table
-  was updated in a transaction which was rolled back. This is to ensure
-  that the same updates are run on the slave.
 
-  @param thd
+  @param thd            Thread variable
   @param cache		The cache to copy to the binlog
-  @param commit_event   The commit event to print after writing the
-                        contents of the cache.
   @param incident       Defines if an incident event should be created to
                         notify that some non-transactional changes did
                         not get into the binlog.
+  @param prepared       Defines if a transaction is part of a 2-PC.
 
   @note
     We only come here if there is something in the cache.
@@ -4186,8 +4158,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *
     'cache' needs to be reinitialized after this functions returns.
 */
 
-bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
-                          bool incident)
+bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, bool incident, bool prepared)
 {
   DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)");
   mysql_mutex_lock(&LOCK_log);
@@ -4201,14 +4172,6 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C
      */
     if (my_b_tell(cache) > 0)
     {
-      /*
-        Log "BEGIN" at the beginning of every transaction.  Here, a
-        transaction is either a BEGIN..COMMIT block or a single
-        statement in autocommit mode.
-      */
-      Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, TRUE, TRUE, 0);
-      if (qinfo.write(&log_file))
-        goto err;
       DBUG_EXECUTE_IF("crash_before_writing_xid",
                       {
                         if ((write_error= write_cache(cache, false, true)))
@@ -4221,9 +4184,6 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C
       if ((write_error= write_cache(cache, false, false)))
         goto err;
 
-      if (commit_event && commit_event->write(&log_file))
-        goto err;
-
       if (incident && write_incident(thd, FALSE))
         goto err;
 
@@ -4257,7 +4217,7 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C
       If the commit_event is not Xid_log_event (then it's a Query_log_event)
       rotate binlog, if necessary.
     */
-    if (commit_event && commit_event->get_type_code() == XID_EVENT)
+    if (prepared)
     {
       mysql_mutex_lock(&LOCK_prep_xids);
       prepared_xids++;
@@ -4656,12 +4616,11 @@ int MYSQL_BIN_LOG::recover(IO_CACHE *log
   Log_event  *ev;
   HASH xids;
   MEM_ROOT mem_root;
-  my_off_t last_valid_pos= *valid_pos;
   /*
     The flag is used for handling the case that a transaction
     is partially written to the binlog.
   */
-  bool in_transaction= TRUE;
+  bool in_transaction= FALSE;
 
   if (! fdle->is_valid() ||
       my_hash_init(&xids, &my_charset_bin, TC_LOG_PAGE_SIZE/3, 0,
@@ -4679,11 +4638,7 @@ int MYSQL_BIN_LOG::recover(IO_CACHE *log
     */
     if (ev->get_type_code() == QUERY_EVENT &&
         !strcmp(((Query_log_event*)ev)->query, "BEGIN"))
-    {
       in_transaction= TRUE;
-      *valid_pos= last_valid_pos;
-    }
-    last_valid_pos= my_b_tell(log);
 
     if (ev->get_type_code() == QUERY_EVENT &&
         !strcmp(((Query_log_event*)ev)->query, "COMMIT"))
@@ -4701,16 +4656,17 @@ int MYSQL_BIN_LOG::recover(IO_CACHE *log
       if (!x || my_hash_insert(&xids, x))
         goto err2;
     }
+
+    /*
+      Recorded valid position for the crashed binlog file
+      which did not contain incorrect events.
+    */
+    if (!log->error && !in_transaction)
+      *valid_pos= my_b_tell(log);
+
     delete ev;
   }
 
-  /*
-    Recorded valid position for the crashed binlog file
-    which did not contain incorrect events.
-  */
-  if (!log->error && !in_transaction)
-    *valid_pos= last_valid_pos;
-
   if (ha_recover(&xids))
     goto err2;
 
@@ -4758,25 +4714,20 @@ int THD::binlog_setup_trx_data()
 
   cache_mngr= new (thd_get_ha_data(this, binlog_hton))
               binlog_cache_mngr(max_binlog_stmt_cache_size,
-                                max_binlog_cache_size,
                                 &binlog_stmt_cache_use,
                                 &binlog_stmt_cache_disk_use,
+                                max_binlog_cache_size,
                                 &binlog_cache_use,
                                 &binlog_cache_disk_use);
   DBUG_RETURN(0);
 }
 
-/*
+/**
   Function to start a statement and optionally a transaction for the
   binary log.
 
-  SYNOPSIS
-    binlog_start_trans_and_stmt()
-
-  DESCRIPTION
-
-    This function does three things:
-    - Start a transaction if not in autocommit mode or if a BEGIN
+  This function does three things:
+    - Starts a transaction if not in autocommit mode or if a BEGIN
       statement has been seen.
 
     - Start a statement transaction to allow us to truncate the cache.
@@ -4791,55 +4742,89 @@ int THD::binlog_setup_trx_data()
       we should use the first. This means that calls to this function
       can be used to start the statement before the first table map
       event, to include some extra events.
- */
 
-void
-THD::binlog_start_trans_and_stmt()
+  Note however that IMMEDIATE_LOGGING implies that the statement is
+  written without BEGIN/COMMIT.
+
+  @param thd         Thread variable
+  @param start_event The first event requested to be written into the
+                     binary log
+ */
+inline void binlog_start_trans_and_stmt(THD *thd, Log_event *start_event)
 {
-  binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
   DBUG_ENTER("binlog_start_trans_and_stmt");
-  DBUG_PRINT("enter", ("cache_mngr: %p  cache_mngr->trx_cache.get_prev_position(): %lu",
-                       cache_mngr,
-                       (cache_mngr ? (ulong) cache_mngr->trx_cache.get_prev_position() :
-                        (ulong) 0)));
-
-  if (cache_mngr == NULL ||
-      cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
-  {
-    this->binlog_set_stmt_begin();
-    if (in_multi_stmt_transaction_mode())
-      trans_register_ha(this, TRUE, binlog_hton);
-    trans_register_ha(this, FALSE, binlog_hton);
+ 
+  /*
+    Initialize the cache manager if this was not done yet.
+  */ 
+  if (thd_get_ha_data(thd, binlog_hton) == NULL)
+    thd->binlog_setup_trx_data();
+
+  /*
+    If the event is requesting immediatly logging, there is no need to go
+    further and set savepoint and register callbacks.
+  */ 
+  if (start_event->is_using_immediate_logging())
+    DBUG_VOID_RETURN;
+
+  /*
+    Retrieve the appropriated cache.
+  */
+  bool is_transactional= start_event->is_using_trans_cache();
+  binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+  binlog_cache_data *cache= cache_mngr->get_binlog_cache_data(is_transactional);
+ 
+  /*
+    If this is the first call to this funciton while processing a statement,
+    the transactional cache does not have a savepoint defined. So, in what
+    follows:
+      . an implicit savepoint is defined;
+      . callbacks are registered;
+      . binary log is set as read/write.
+
+    The savepoint allows for truncating the trx-cache transactional changes
+    fail. Callbacks are necessary to flush caches upon committing or rolling
+    back a statement or a transaction. However, notifications do not happen
+    if the binary log is set as read/write.
+  */
+  if (cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
+  {
     /*
-      Mark statement transaction as read/write. We never start
-      a binary log transaction and keep it read-only,
-      therefore it's best to mark the transaction read/write just
-      at the same time we start it.
-      Not necessary to mark the normal transaction read/write
-      since the statement-level flag will be propagated automatically
-      inside ha_commit_trans.
+      Set an implicit savepoint in order to be able to truncate a trx-cache.
     */
-    ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
-  }
-  DBUG_VOID_RETURN;
-}
+    my_off_t pos= 0;
+    binlog_trans_log_savepos(thd, &pos);
+    cache_mngr->trx_cache.set_prev_position(pos);
 
-void THD::binlog_set_stmt_begin() {
-  binlog_cache_mngr *cache_mngr=
-    (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
+    /*
+      Set callbacks in order to be able to call commmit or rollback.
+    */
+    if (thd->in_multi_stmt_transaction_mode())
+      trans_register_ha(thd, TRUE, binlog_hton);
+    trans_register_ha(thd, FALSE, binlog_hton);
+
+    /*
+      Set the binary log as read/write otherwise callbacks are not called.
+    */
+    thd->ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
+  }
 
   /*
-    The call to binlog_trans_log_savepos() might create the cache_mngr
-    structure, if it didn't exist before, so we save the position
-    into an auto variable and then write it into the transaction
-    data for the binary log (i.e., cache_mngr).
-  */
-  my_off_t pos= 0;
-  binlog_trans_log_savepos(this, &pos);
-  cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
-  cache_mngr->trx_cache.set_prev_position(pos);
-}
+    If the cache is empty log "BEGIN" at the beginning of every transaction.
+    Here, a transaction is either a BEGIN..COMMIT/ROLLBACK block or a single
+    statement in autocommit mode.
+  */
+  if (cache->empty())
+  {
+    IO_CACHE *file=
+      cache_mngr->get_binlog_cache_log(is_transactional);
+    Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"),
+                          is_transactional, FALSE, TRUE, 0, TRUE);
+    qinfo.write(file);
+  }
 
+  DBUG_VOID_RETURN;
+}
 
 /**
   This function writes a table map to the binary log. 
@@ -4876,14 +4861,13 @@ int THD::binlog_write_table_map(TABLE *t
   Table_map_log_event
     the_event(this, table, table->s->table_map_id, is_transactional);
 
-  if (binlog_table_maps == 0)
-    binlog_start_trans_and_stmt();
+  binlog_start_trans_and_stmt(this, &the_event);
 
   binlog_cache_mngr *const cache_mngr=
     (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
 
   IO_CACHE *file=
-    cache_mngr->get_binlog_cache_log(use_trans_cache(this, is_transactional));
+    cache_mngr->get_binlog_cache_log(is_transactional);
 
   if (binlog_rows_query && this->query())
   {
@@ -4927,7 +4911,7 @@ THD::binlog_get_pending_rows_event(bool
   if (cache_mngr)
   {
     binlog_cache_data *cache_data=
-      cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional));
+      cache_mngr->get_binlog_cache_data(is_transactional);
 
     rows= cache_data->pending();
   }
@@ -4947,16 +4931,13 @@ THD::binlog_get_pending_rows_event(bool
 void
 THD::binlog_set_pending_rows_event(Rows_log_event* ev, bool is_transactional)
 {
-  if (thd_get_ha_data(this, binlog_hton) == NULL)
-    binlog_setup_trx_data();
-
   binlog_cache_mngr *const cache_mngr=
     (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
 
   DBUG_ASSERT(cache_mngr);
 
   binlog_cache_data *cache_data=
-    cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional));
+    cache_mngr->get_binlog_cache_data(is_transactional);
 
   cache_data->set_pending(ev);
 }
@@ -5380,13 +5361,6 @@ THD::binlog_prepare_pending_rows_event(T
   /* Fetch the type code for the RowsEventT template parameter */
   int const type_code= RowsEventT::TYPE_CODE;
 
-  /*
-    There is no good place to set up the transactional data, so we
-    have to do it here.
-  */
-  if (binlog_setup_trx_data())
-    DBUG_RETURN(NULL);
-
   Rows_log_event* pending= binlog_get_pending_rows_event(is_transactional);
 
   if (unlikely(pending && !pending->is_valid()))

=== modified file 'sql/binlog.h'
--- a/sql/binlog.h	2011-05-16 14:30:54 +0000
+++ b/sql/binlog.h	2011-05-17 20:08:26 +0000
@@ -229,12 +229,13 @@ public:
   int new_file();
 
   bool write(Log_event* event_info); // binary log write
-  bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
-
-  bool write_incident(THD *thd, bool lock);
+  bool write(THD *thd, IO_CACHE *cache, bool incident, bool prepared);
   int  write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
+
   void set_write_error(THD *thd, bool is_transactional);
   bool check_write_error(THD *thd);
+  bool write_incident(THD *thd, bool lock);
+  bool write_incident(Incident_log_event *ev, bool lock);
 
   void start_union_events(THD *thd, query_id_t query_id_param);
   void stop_union_events(THD *thd);
@@ -320,7 +321,6 @@ extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG
 
 bool trans_has_updated_trans_table(const THD* thd);
 bool stmt_has_updated_trans_table(const THD *thd);
-bool use_trans_cache(const THD* thd, bool is_transactional);
 bool ending_trans(THD* thd, const bool all);
 bool ending_single_stmt_trans(THD* thd, const bool all);
 bool trans_cannot_safely_rollback(const THD* thd);

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2011-05-26 15:20:09 +0000
+++ b/sql/ha_partition.cc	2011-06-01 09:11:28 +0000
@@ -6875,22 +6875,29 @@ bool ha_partition::check_if_incompatible
 
 
 /**
-  Support of fast or online add/drop index
+  Support of in-place add/drop index
 */
-int ha_partition::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys)
+int ha_partition::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
+                            handler_add_index **add)
 {
   handler **file;
   int ret= 0;
 
   DBUG_ENTER("ha_partition::add_index");
+  *add= new handler_add_index(table, key_info, num_of_keys);
   /*
     There has already been a check in fix_partition_func in mysql_alter_table
     before this call, which checks for unique/primary key violations of the
     partitioning function. So no need for extra check here.
   */
   for (file= m_file; *file; file++)
-    if ((ret=  (*file)->add_index(table_arg, key_info, num_of_keys)))
+  {
+    handler_add_index *add_index;
+    if ((ret= (*file)->add_index(table_arg, key_info, num_of_keys, &add_index)))
+      goto err;
+    if ((ret= (*file)->final_add_index(add_index, true)))
       goto err;
+  }
   DBUG_RETURN(ret);
 err:
   if (file > m_file)
@@ -6915,6 +6922,42 @@ err:
 }
 
 
+/**
+   Second phase of in-place add index.
+
+   @note If commit is false, index changes are rolled back by dropping the
+         added indexes. If commit is true, nothing is done as the indexes
+         were already made active in ::add_index()
+ */
+
+int ha_partition::final_add_index(handler_add_index *add, bool commit)
+{
+  DBUG_ENTER("ha_partition::final_add_index");
+  // Rollback by dropping indexes.
+  if (!commit)
+  {
+    TABLE *table_arg= add->table;
+    uint num_of_keys= add->num_of_keys;
+    handler **file;
+    uint *key_numbers= (uint*) ha_thd()->alloc(sizeof(uint) * num_of_keys);
+    uint old_num_of_keys= table_arg->s->keys;
+    uint i;
+    /* The newly created keys have the last id's */
+    for (i= 0; i < num_of_keys; i++)
+      key_numbers[i]= i + old_num_of_keys;
+    if (!table_arg->key_info)
+      table_arg->key_info= add->key_info;
+    for (file= m_file; *file; file++)
+    {
+      (void) (*file)->prepare_drop_index(table_arg, key_numbers, num_of_keys);
+      (void) (*file)->final_drop_index(table_arg);
+    }
+    if (table_arg->key_info == add->key_info)
+      table_arg->key_info= NULL;
+  }
+  DBUG_RETURN(0);
+}
+
 int ha_partition::prepare_drop_index(TABLE *table_arg, uint *key_num,
                                  uint num_of_keys)
 {

=== modified file 'sql/ha_partition.h'
--- a/sql/ha_partition.h	2011-05-16 11:32:07 +0000
+++ b/sql/ha_partition.h	2011-06-01 09:11:28 +0000
@@ -1052,7 +1052,9 @@ public:
     They are used for on-line/fast alter table add/drop index:
     -------------------------------------------------------------------------
   */
-  virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys);
+  virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
+                        handler_add_index **add);
+  virtual int final_add_index(handler_add_index *add, bool commit);
   virtual int prepare_drop_index(TABLE *table_arg, uint *key_num,
                                  uint num_of_keys);
   virtual int final_drop_index(TABLE *table_arg);

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2011-05-26 15:20:09 +0000
+++ b/sql/handler.cc	2011-05-31 09:30:59 +0000
@@ -366,6 +366,7 @@ int ha_init_errors(void)
   SETMSG(HA_ERR_AUTOINC_READ_FAILED,    ER_DEFAULT(ER_AUTOINC_READ_FAILED));
   SETMSG(HA_ERR_AUTOINC_ERANGE,         ER_DEFAULT(ER_WARN_DATA_OUT_OF_RANGE));
   SETMSG(HA_ERR_TOO_MANY_CONCURRENT_TRXS, ER_DEFAULT(ER_TOO_MANY_CONCURRENT_TRXS));
+  SETMSG(HA_ERR_INDEX_COL_TOO_LONG,	ER_DEFAULT(ER_INDEX_COLUMN_TOO_LONG));
 
   /* Register the error messages for use with my_error(). */
   return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
@@ -3065,6 +3066,9 @@ void handler::print_error(int error, myf
   case HA_ERR_TOO_MANY_CONCURRENT_TRXS:
     textno= ER_TOO_MANY_CONCURRENT_TRXS;
     break;
+  case HA_ERR_INDEX_COL_TOO_LONG:
+    textno= ER_INDEX_COLUMN_TOO_LONG;
+    break;
   case HA_ERR_NOT_IN_LOCK_PARTITIONS:
     textno=ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET;
     break;

=== modified file 'sql/handler.h'
--- a/sql/handler.h	2011-05-12 17:29:19 +0000
+++ b/sql/handler.h	2011-06-01 09:11:28 +0000
@@ -1214,6 +1214,27 @@ uint calculate_key_len(TABLE *, uint, co
 */
 #define make_prev_keypart_map(N) (((key_part_map)1 << (N)) - 1)
 
+
+/**
+  Index creation context.
+  Created by handler::add_index() and freed by handler::final_add_index().
+*/
+
+class handler_add_index
+{
+public:
+  /* Table where the indexes are added */
+  TABLE* const table;
+  /* Indexes being created */
+  KEY* const key_info;
+  /* Size of key_info[] */
+  const uint num_of_keys;
+  handler_add_index(TABLE *table_arg, KEY *key_info_arg, uint num_of_keys_arg)
+    : table (table_arg), key_info (key_info_arg), num_of_keys (num_of_keys_arg)
+  {}
+  virtual ~handler_add_index() {}
+};
+
 /**
   The handler class is the interface for dynamically loadable
   storage engines. Do not add ifdefs and take care when adding or
@@ -1909,8 +1930,36 @@ public:
 
   virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0;
 
-  virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys)
+/**
+   First phase of in-place add index.
+   Handlers are supposed to create new indexes here but not make them
+   visible.
+
+   @param table_arg   Table to add index to
+   @param key_info    Information about new indexes
+   @param num_of_key  Number of new indexes
+   @param add[out]    Context of handler specific information needed
+                      for final_add_index().
+
+   @note This function can be called with less than exclusive metadata
+   lock depending on which flags are listed in alter_table_flags.
+*/
+  virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
+                        handler_add_index **add)
+  { return (HA_ERR_WRONG_COMMAND); }
+
+/**
+   Second and last phase of in-place add index.
+   Commit or rollback pending new indexes.
+
+   @param add     Context of handler specific information from add_index().
+   @param commit  If true, commit. If false, rollback index changes.
+
+   @note This function is called with exclusive metadata lock.
+*/
+  virtual int final_add_index(handler_add_index *add, bool commit)
   { return (HA_ERR_WRONG_COMMAND); }
+
   virtual int prepare_drop_index(TABLE *table_arg, uint *key_num,
                                  uint num_of_keys)
   { return (HA_ERR_WRONG_COMMAND); }

=== modified file 'sql/item_inetfunc.cc'
--- a/sql/item_inetfunc.cc	2011-05-26 15:20:09 +0000
+++ b/sql/item_inetfunc.cc	2011-05-30 07:26:59 +0000
@@ -15,7 +15,7 @@
 
 #include "item_inetfunc.h"
 
-#include "violite.h"  // vio_getnameinfo()
+#include "my_net.h"
 
 ///////////////////////////////////////////////////////////////////////////
 
@@ -531,7 +531,7 @@ static bool str_to_ipv6(const char *str,
                   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.
+  Windows Vista, but the minimum supported version is Windows 2000.
 */
 
 static void ipv4_to_str(const in_addr *ipv4, char *str)

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2011-05-26 15:20:09 +0000
+++ b/sql/log_event.cc	2011-05-30 06:25:47 +0000
@@ -678,18 +678,16 @@ const char* Log_event::get_type_str()
 */
 
 #ifndef MYSQL_CLIENT
-Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
+Log_event::Log_event(THD* thd_arg, uint16 flags_arg,
+                     enum_event_cache_type cache_type_arg,
+                     enum_event_logging_type logging_type_arg)
   :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg),
-   cache_type(Log_event::EVENT_INVALID_CACHE), crc(0), thd(thd_arg),
-   checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
+  event_cache_type(cache_type_arg),
+  event_logging_type(logging_type_arg),
+  crc(0), thd(thd_arg), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
 {
   server_id=	thd->server_id;
   when=		thd->start_time;
-
-  if (using_trans)
-    cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
-  else
-    cache_type= Log_event::EVENT_STMT_CACHE;
 }
 
 /**
@@ -699,9 +697,11 @@ Log_event::Log_event(THD* thd_arg, uint1
   the binlog but we have no THD, so we need this minimal constructor).
 */
 
-Log_event::Log_event()
-  :temp_buf(0), exec_time(0), flags(0),  crc(0), thd(0),
-   checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
+Log_event::Log_event(enum_event_cache_type cache_type_arg,
+                     enum_event_logging_type logging_type_arg)
+  :temp_buf(0), exec_time(0), flags(0), event_cache_type(cache_type_arg),
+  event_logging_type(logging_type_arg), crc(0), thd(0),
+  checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
 {
   server_id=	::server_id;
   /*
@@ -720,8 +720,10 @@ Log_event::Log_event()
 
 Log_event::Log_event(const char* buf,
                      const Format_description_log_event* description_event)
-  :temp_buf(0), exec_time(0), cache_type(Log_event::EVENT_INVALID_CACHE),
-    crc(0), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
+  :temp_buf(0), exec_time(0),
+  event_cache_type(EVENT_INVALID_CACHE),
+  event_logging_type(EVENT_INVALID_LOGGING),
+  crc(0), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
 {
 #ifndef MYSQL_CLIENT
   thd = 0;
@@ -904,18 +906,20 @@ void Log_event::init_show_field_list(Lis
 my_bool Log_event::need_checksum()
 {
   DBUG_ENTER("Log_event::need_checksum");
-  my_bool ret;
+  my_bool ret= FALSE;
   /* 
      few callers of Log_event::write 
      (incl FD::write, FD constructing code on the slave side, Rotate relay log
      and Stop event) 
      provides their checksum alg preference through Log_event::checksum_alg.
   */
-  ret= (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) ?
-    (checksum_alg != BINLOG_CHECKSUM_ALG_OFF) :
-    ((binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF) &&
-     (cache_type == Log_event::EVENT_NO_CACHE))? binlog_checksum_options :
-    FALSE;
+  if (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF)
+    ret= (checksum_alg != BINLOG_CHECKSUM_ALG_OFF);
+  else if (binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF &&
+           event_cache_type == Log_event::EVENT_NO_CACHE)
+    ret= binlog_checksum_options;
+  else
+    ret= FALSE;
 
   /*
     FD calls the methods before data_written has been calculated.
@@ -955,7 +959,7 @@ my_bool Log_event::need_checksum()
   DBUG_ASSERT(((get_type_code() != ROTATE_EVENT &&
                 get_type_code() != STOP_EVENT) ||
                get_type_code() != FORMAT_DESCRIPTION_EVENT) ||
-              cache_type == Log_event::EVENT_NO_CACHE);
+              event_cache_type == Log_event::EVENT_NO_CACHE);
 
   DBUG_RETURN(ret);
 }
@@ -2681,29 +2685,33 @@ Query_log_event::Query_log_event()
 }
 
 
-/*
-  SYNOPSIS
-    Query_log_event::Query_log_event()
-      thd_arg           - thread handle
-      query_arg         - array of char representing the query
-      query_length      - size of the  `query_arg' array
-      using_trans       - there is a modified transactional table
-      suppress_use      - suppress the generation of 'USE' statements
-      errcode           - the error code of the query
-      
-  DESCRIPTION
-  Creates an event for binlogging
-  The value for `errcode' should be supplied by caller.
+/**
+  Creates a Query Log Event.
+
+  @param thd_arg      Thread handle
+  @param query_arg    Array of char representing the query
+  @param query_length Size of the 'query_arg' array
+  @param using_trans  Indicates that there are transactional changes.
+  @param immediate    After being written to the binary log, the event
+                      must be flushed immediately. This indirectly implies
+                      the stmt-cache.
+  @param suppress_use Suppress the generation of 'USE' statements
+  @param errcode      The error code of the query
+  @param ignore       Ignore user's statement, i.e. lex information, while
+                      deciding which cache must be used.
 */
 Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
 				 ulong query_length, bool using_trans,
-				 bool direct, bool suppress_use, int errcode)
+				 bool immediate, bool suppress_use,
+                                 int errcode, bool ignore_cmd_internals)
 
   :Log_event(thd_arg,
              (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F :
               0) |
              (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0),
-	     using_trans),
+	     using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                          Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
    data_buf(0), query(query_arg), catalog(thd_arg->catalog),
    db(thd_arg->db), q_len((uint32) query_length),
    thread_id(thd_arg->thread_id),
@@ -2781,62 +2789,146 @@ Query_log_event::Query_log_event(THD* th
   else
     time_zone_len= 0;
 
-  LEX *lex= thd->lex;
   /*
-    Defines that the statement will be written directly to the binary log
-    without being wrapped by a BEGIN...COMMIT. Otherwise, the statement
-    will be written to either the trx-cache or stmt-cache.
+    In what follows, we define in which cache, trx-cache or stmt-cache,
+    this Query Log Event will be written to.
 
-    Note that a cache will not be used if the parameter direct is TRUE.
+    If ignore_cmd_internals is defined, we rely on the is_trans flag to
+    choose the cache and this is done in the base class Log_event. False
+    means that the stmt-cache will be used and upon statement commit/rollback
+    the cache will be flushed to disk. True means that the trx-cache will
+    be used and upon transaction commit/rollback the cache will be flushed
+    to disk.
+
+    If set immediate cache is defined, for convenience, we automatically
+    use the stmt-cache. This mean that the statement will be written
+    to the stmt-cache and immediately flushed to disk without waiting
+    for a commit/rollback notification.
+
+    For example, the cluster/ndb captures a request to execute a DDL
+    statement and synchronously propagate it to all available MySQL
+    servers. Unfortunately, the current protocol assumes that the
+    generated events are immediately written to diks and does not check
+    for commit/rollback.
+
+    Upon dropping a connection, DDLs (i.e. DROP TEMPORARY TABLE) are
+    generated and in this case the statements have the immediate flag
+    set because there is no commit/rollback.
+
+    If the immediate flag is not set, the decision on the cache is based
+    on the current statement and the flag is_trans, which indicates if
+    a transactional engine was updated. 
+
+    Statements are classifed as row producers (i.e. can_generate_row_events())
+    or non-row producers. Non-row producers, DDL in general, are treated
+    as the immediate flag was set and for convenience are written to the
+    stmt-cache and immediately flushed to disk. 
+
+    Row producers are handled in general according to the is_trans flag.
+    False means that the stmt-cache will be used and upon statement
+    commit/rollback the cache will be flushed to disk. True means that the
+    trx-cache will be used and upon transaction commit/rollback the cache
+    will be flushed to disk.
+
+    Unfortunately, there are exceptions to this non-row and row producer
+    rules:
+
+      . The SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT does not
+        have the flag is_trans set because there is no updated engine but
+        must be written to the trx-cache.
+
+      . SET does not have the flag is_trans set but, if auto-commit is off,
+        must be written to the trx-cache.
+
+      . CREATE TABLE is classfied as non-row producer but CREATE TEMPORARY
+        must be handled as row producer.
+
+      . DROP TABLE is classfied as non-row producer but DROP TEMPORARY
+        must be handled as row producer.
+
+    Finally, some statements that does not have the flag is_trans set may
+    be written to the trx-cache based on the following criteria:
+
+      . updated both a transactional and a non-transactional engine (i.e.
+        stmt_has_updated_trans_table()).
+
+      . accessed both a transactional and a non-transactional engine and
+        is classified as unsafe (i.e. is_mixed_stmt_unsafe()).
+
+      . is executed within a transaction and previously a transactional
+        engine was updated and the flag binlog_direct_non_trans_update
+        is set.
   */
-  bool use_cache= FALSE;
-  /*
-    TRUE defines that the trx-cache must be used and by consequence the
-    use_cache is TRUE.
+  if (ignore_cmd_internals)
+    return;
 
-    Note that a cache will not be used if the parameter direct is TRUE.
+  /*
+    TRUE defines that the trx-cache must be used.
   */
-  bool trx_cache= FALSE;
-  cache_type= Log_event::EVENT_INVALID_CACHE;
-
-  switch (lex->sql_command)
+  bool cmd_can_generate_row_events= FALSE;
+  /*
+    TRUE defines that the trx-cache must be used.
+  */
+  bool cmd_must_go_to_trx_cache= FALSE;
+   
+  LEX *lex= thd->lex;
+  if (!immediate)
   {
-    case SQLCOM_DROP_TABLE:
-      use_cache= (lex->drop_temporary && thd->in_multi_stmt_transaction_mode());
-    break;
-
-    case SQLCOM_CREATE_TABLE:
-      trx_cache= (lex->select_lex.item_list.elements &&
-                  thd->is_current_stmt_binlog_format_row());
-      use_cache= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
-                   thd->in_multi_stmt_transaction_mode()) || trx_cache;
-      break;
-    case SQLCOM_SET_OPTION:
-      use_cache= trx_cache= (lex->autocommit ? FALSE : TRUE);
-      break;
-    case SQLCOM_RELEASE_SAVEPOINT:
-    case SQLCOM_ROLLBACK_TO_SAVEPOINT:
-    case SQLCOM_SAVEPOINT:
-      use_cache= trx_cache= TRUE;
-      break;
-    default:
-      use_cache= sqlcom_can_generate_row_events(thd);
-      break;
+    switch (lex->sql_command)
+    {
+      case SQLCOM_DROP_TABLE:
+        cmd_can_generate_row_events= lex->drop_temporary &&
+                                     thd->in_multi_stmt_transaction_mode();
+      break;
+      case SQLCOM_CREATE_TABLE:
+        cmd_must_go_to_trx_cache= lex->select_lex.item_list.elements &&
+                                  thd->is_current_stmt_binlog_format_row();
+        cmd_can_generate_row_events= 
+          ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
+            thd->in_multi_stmt_transaction_mode()) || cmd_must_go_to_trx_cache;
+        break;
+      case SQLCOM_SET_OPTION:
+        cmd_can_generate_row_events= cmd_must_go_to_trx_cache=
+          (lex->autocommit ? FALSE : TRUE);
+        break;
+      case SQLCOM_RELEASE_SAVEPOINT:
+      case SQLCOM_ROLLBACK_TO_SAVEPOINT:
+      case SQLCOM_SAVEPOINT:
+        cmd_can_generate_row_events= cmd_must_go_to_trx_cache= TRUE;
+        break;
+      default:
+        cmd_can_generate_row_events= sqlcom_can_generate_row_events(thd);
+        break;
+    }
   }
-
-  if (!use_cache || direct)
+  
+  if (cmd_can_generate_row_events)
   {
-    cache_type= Log_event::EVENT_NO_CACHE;
+    cmd_must_go_to_trx_cache= cmd_must_go_to_trx_cache || using_trans;
+    if (cmd_must_go_to_trx_cache || stmt_has_updated_trans_table(thd) ||
+        thd->lex->is_mixed_stmt_unsafe(thd->in_multi_stmt_transaction_mode(),
+                                       thd->variables.binlog_direct_non_trans_update,
+                                       trans_has_updated_trans_table(thd),
+                                       thd->tx_isolation) ||
+        (!thd->variables.binlog_direct_non_trans_update && trans_has_updated_trans_table(thd)))
+    {
+      event_logging_type= Log_event::EVENT_NORMAL_LOGGING; 
+      event_cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
+    }
+    else
+    {
+      event_logging_type= Log_event::EVENT_NORMAL_LOGGING; 
+      event_cache_type= Log_event::EVENT_STMT_CACHE;
+    }
   }
-  else if (using_trans || trx_cache || stmt_has_updated_trans_table(thd) ||
-           thd->lex->is_mixed_stmt_unsafe(thd->in_multi_stmt_transaction_mode(),
-                                          thd->variables.binlog_direct_non_trans_update,
-                                          trans_has_updated_trans_table(thd),
-                                          thd->tx_isolation))
-    cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
   else
-    cache_type= Log_event::EVENT_STMT_CACHE;
-  DBUG_ASSERT(cache_type != Log_event::EVENT_INVALID_CACHE);
+  {
+    event_logging_type= Log_event::EVENT_IMMEDIATE_LOGGING;
+    event_cache_type= Log_event::EVENT_STMT_CACHE;
+  }
+
+  DBUG_ASSERT(event_cache_type != Log_event::EVENT_INVALID_CACHE);
+  DBUG_ASSERT(event_logging_type != Log_event::EVENT_INVALID_LOGGING);
   DBUG_PRINT("info",("Query_log_event has flags2: %lu  sql_mode: %llu",
                      (ulong) flags2, sql_mode));
 }
@@ -4828,7 +4920,9 @@ Load_log_event::Load_log_event(THD *thd_
 			       bool ignore, bool using_trans)
   :Log_event(thd_arg,
              thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0,
-             using_trans),
+             using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                           Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
    thread_id(thd_arg->thread_id),
    slave_proxy_id(thd_arg->variables.pseudo_thread_id),
    num_fields(0),fields(0),
@@ -5473,9 +5567,9 @@ void Rotate_log_event::print(FILE* file,
 Rotate_log_event::Rotate_log_event(const char* new_log_ident_arg,
                                    uint ident_len_arg, ulonglong pos_arg,
                                    uint flags_arg)
-  :Log_event(), new_log_ident(new_log_ident_arg),
-   pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
-                          (uint) strlen(new_log_ident_arg)), flags(flags_arg)
+  :Log_event(Log_event::EVENT_NO_CACHE, Log_event::EVENT_IMMEDIATE_LOGGING),
+   new_log_ident(new_log_ident_arg), pos(pos_arg),ident_len(ident_len_arg ?
+   ident_len_arg : (uint) strlen(new_log_ident_arg)), flags(flags_arg)
 {
 #ifndef DBUG_OFF
   char buff[22];
@@ -5483,7 +5577,8 @@ Rotate_log_event::Rotate_log_event(const
   DBUG_PRINT("enter",("new_log_ident: %s  pos: %s  flags: %lu", new_log_ident_arg,
                       llstr(pos_arg, buff), (ulong) flags));
 #endif
-  cache_type= EVENT_NO_CACHE;
+  event_cache_type= EVENT_NO_CACHE;
+  event_logging_type= EVENT_IMMEDIATE_LOGGING;
   if (flags & DUP_NAME)
     new_log_ident= my_strndup(new_log_ident_arg, ident_len, MYF(MY_WME));
   if (flags & RELAY_LOG)
@@ -6838,7 +6933,11 @@ Append_block_log_event::Append_block_log
 					       uchar *block_arg,
 					       uint block_len_arg,
 					       bool using_trans)
-  :Log_event(thd_arg,0, using_trans), block(block_arg),
+  :Log_event(thd_arg, 0,
+             using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                           Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
+   block(block_arg),
    block_len(block_len_arg), file_id(thd_arg->file_id), db(db_arg)
 {
 }
@@ -7004,7 +7103,11 @@ err:
 #ifndef MYSQL_CLIENT
 Delete_file_log_event::Delete_file_log_event(THD *thd_arg, const char* db_arg,
 					     bool using_trans)
-  :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id), db(db_arg)
+  :Log_event(thd_arg, 0, 
+             using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                           Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
+  file_id(thd_arg->file_id), db(db_arg)
 {
 }
 #endif
@@ -7100,7 +7203,11 @@ int Delete_file_log_event::do_apply_even
 Execute_load_log_event::Execute_load_log_event(THD *thd_arg,
                                                const char* db_arg,
 					       bool using_trans)
-  :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id), db(db_arg)
+  :Log_event(thd_arg, 0,
+             using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                           Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
+  file_id(thd_arg->file_id), db(db_arg)
 {
 }
 #endif
@@ -7316,9 +7423,9 @@ Execute_load_query_log_event(THD *thd_ar
                              ulong query_length_arg, uint fn_pos_start_arg,
                              uint fn_pos_end_arg,
                              enum_load_dup_handling dup_handling_arg,
-                             bool using_trans, bool direct, bool suppress_use,
+                             bool using_trans, bool immediate, bool suppress_use,
                              int errcode):
-  Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, direct,
+  Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, immediate,
                   suppress_use, errcode),
   file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg),
   fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg)
@@ -7593,8 +7700,11 @@ const char *sql_ex_info::init(const char
 
 #ifndef MYSQL_CLIENT
 Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid,
-                               MY_BITMAP const *cols, bool is_transactional)
-  : Log_event(thd_arg, 0, is_transactional),
+                               MY_BITMAP const *cols, bool using_trans)
+  : Log_event(thd_arg, 0,
+             using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                           Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
     m_row_count(0),
     m_table(tbl_arg),
     m_table_id(tid),
@@ -8516,8 +8626,11 @@ int Table_map_log_event::save_field_meta
  */
 #if !defined(MYSQL_CLIENT)
 Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
-                                         bool is_transactional)
-  : Log_event(thd, 0, is_transactional),
+                                         bool using_trans)
+  : Log_event(thd, 0,
+              using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                            Log_event::EVENT_STMT_CACHE,
+              Log_event::EVENT_NORMAL_LOGGING),
     m_table(tbl),
     m_dbnam(tbl->s->db.str),
     m_dblen(m_dbnam ? tbl->s->db.length : 0),

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2011-03-22 11:44:40 +0000
+++ b/sql/log_event.h	2011-05-12 21:51:20 +0000
@@ -926,9 +926,10 @@ public:
     EVENT_SKIP_COUNT
   };
 
+protected:
   enum enum_event_cache_type 
   {
-    EVENT_INVALID_CACHE,
+    EVENT_INVALID_CACHE= 0,
     /* 
       If possible the event should use a non-transactional cache before
       being flushed to the binary log. This means that it must be flushed
@@ -943,15 +944,35 @@ public:
     EVENT_TRANSACTIONAL_CACHE,
     /* 
       The event must be written directly to the binary log without going
-      through a cache.
+      through any cache.
     */
     EVENT_NO_CACHE,
-    /**
+    /*
        If there is a need for different types, introduce them before this.
     */
     EVENT_CACHE_COUNT
   };
 
+  enum enum_event_logging_type
+  {
+    EVENT_INVALID_LOGGING= 0,
+    /*
+      The event must be written to a cache and upon commit or rollback
+      written to the binary log.
+    */
+    EVENT_NORMAL_LOGGING,
+    /*
+      The event must be written to an empty cache and immediatly written
+      to the binary log without waiting for any other event.
+    */
+    EVENT_IMMEDIATE_LOGGING,
+    /*
+       If there is a need for different types, introduce them before this.
+    */
+    EVENT_CACHE_LOGGING_COUNT
+  };
+
+public:
   /*
     The following type definition is to be used whenever data is placed 
     and manipulated in a common buffer. Use this typedef for buffers
@@ -1002,12 +1023,6 @@ public:
   */
   uint16 flags;
   
-  /*
-    Defines the type of the cache, if any, where the event will be
-    stored before being flushed to disk.
-  */
-  uint16 cache_type;
-
   /**
     A storage to cache the global system variable's value.
     Handling of a separate event will be governed its member.
@@ -1015,14 +1030,28 @@ public:
   ulong slave_exec_mode;
 
   /**
+    Defines the type of the cache, if any, where the event will be
+    stored before being flushed to disk.
+  */
+  enum_event_cache_type event_cache_type;
+
+  /**
+    Defines when information, i.e. event or cache, will be flushed
+    to disk.
+  */
+  enum_event_logging_type event_logging_type;
+  /**
     Placeholder for event checksum while writing to binlog.
    */
   ha_checksum crc;
 #ifdef MYSQL_SERVER
   THD* thd;
 
-  Log_event();
-  Log_event(THD* thd_arg, uint16 flags_arg, bool is_transactional);
+  Log_event(enum_event_cache_type cache_type_arg= EVENT_INVALID_CACHE,
+            enum_event_logging_type logging_type_arg= EVENT_INVALID_LOGGING);
+  Log_event(THD* thd_arg, uint16 flags_arg,
+            enum_event_cache_type cache_type_arg,
+            enum_event_logging_type logging_type_arg);
   /*
     read_log_event() functions read an event from a binlog or relay
     log; used by SHOW BINLOG EVENTS, the binlog_dump thread on the
@@ -1063,7 +1092,10 @@ public:
     return thd ? thd->db : 0;
   }
 #else
-  Log_event() : temp_buf(0) {}
+  Log_event(enum_event_cache_type cache_type_arg= EVENT_INVALID_CACHE,
+            enum_event_logging_type logging_type_arg= EVENT_INVALID_LOGGING)
+  : temp_buf(0), event_cache_type(cache_type_arg),
+  event_logging_type(logging_type_arg) { }
     /* avoid having to link mysqlbinlog against libpthread */
   static Log_event* read_log_event(IO_CACHE* file,
                                    const Format_description_log_event
@@ -1137,17 +1169,17 @@ public:
   bool is_relay_log_event() const { return flags & LOG_EVENT_RELAY_LOG_F; }
   bool is_ignorable_event() const { return flags & LOG_EVENT_IGNORABLE_F; }
   bool is_no_filter_event() const { return flags & LOG_EVENT_NO_FILTER_F; }
-  inline bool use_trans_cache() const
-  { 
-    return (cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE);
+  inline bool is_using_trans_cache() const
+  {
+    return (event_cache_type == EVENT_TRANSACTIONAL_CACHE);
   }
-  inline void set_direct_logging()
+  inline bool is_using_stmt_cache() const
   {
-    cache_type = Log_event::EVENT_NO_CACHE;
+    return(event_cache_type == EVENT_STMT_CACHE);
   }
-  inline bool use_direct_logging()
+  inline bool is_using_immediate_logging() const
   {
-    return (cache_type == Log_event::EVENT_NO_CACHE);
+    return(event_logging_type == EVENT_IMMEDIATE_LOGGING);
   }
   Log_event(const char* buf, const Format_description_log_event
             *description_event);
@@ -1774,7 +1806,8 @@ public:
 #ifdef MYSQL_SERVER
 
   Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
-                  bool using_trans, bool direct, bool suppress_use, int error);
+                  bool using_trans, bool immediate, bool suppress_use,
+                  int error, bool ignore_command= FALSE);
   const char* get_db() { return db; }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
@@ -2365,9 +2398,10 @@ public:
 
 #ifdef MYSQL_SERVER
   Intvar_log_event(THD* thd_arg, uchar type_arg, ulonglong val_arg,
-                   uint16 cache_type_arg)
-    :Log_event(thd_arg, 0, 0), val(val_arg), type(type_arg)
-  { cache_type= cache_type_arg; }
+                   enum_event_cache_type cache_type_arg,
+                   enum_event_logging_type logging_type_arg)
+    :Log_event(thd_arg, 0, cache_type_arg, logging_type_arg),
+    val(val_arg), type(type_arg) { }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
 #endif /* HAVE_REPLICATION */
@@ -2442,9 +2476,10 @@ class Rand_log_event: public Log_event
 
 #ifdef MYSQL_SERVER
   Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg,
-                 uint16 cache_type_arg)
-    :Log_event(thd_arg, 0, 0), seed1(seed1_arg), seed2(seed2_arg)
-    { cache_type= cache_type_arg; }
+                 enum_event_cache_type cache_type_arg,
+                 enum_event_logging_type logging_type_arg)
+    :Log_event(thd_arg, 0, cache_type_arg, logging_type_arg),
+    seed1(seed1_arg), seed2(seed2_arg) { }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
 #endif /* HAVE_REPLICATION */
@@ -2488,8 +2523,12 @@ class Xid_log_event: public Log_event
    my_xid xid;
 
 #ifdef MYSQL_SERVER
-  Xid_log_event(THD* thd_arg, my_xid x): Log_event(thd_arg, 0, TRUE), xid(x)
-  { cache_type= EVENT_NO_CACHE; }
+  Xid_log_event(THD* thd_arg, my_xid x)
+  : Log_event(thd_arg, 0, 
+              Log_event::EVENT_TRANSACTIONAL_CACHE,
+              Log_event::EVENT_NORMAL_LOGGING),
+  xid(x)
+  { }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
 #endif /* HAVE_REPLICATION */
@@ -2542,11 +2581,14 @@ public:
   User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
                      char *val_arg, ulong val_len_arg, Item_result type_arg,
 		     uint charset_number_arg, uchar flags_arg,
-                     uint16 cache_type_arg)
-    :Log_event(thd_arg, 0, 0), name(name_arg), name_len(name_len_arg), val(val_arg),
-     val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg),
-     flags(flags_arg)
-    { is_null= !val; cache_type= cache_type_arg; }
+                     enum_event_cache_type cache_type_arg,
+                     enum_event_logging_type logging_type_arg)
+    :Log_event(thd_arg, 0, cache_type_arg, logging_type_arg), name(name_arg),
+     name_len(name_len_arg), val(val_arg), val_len(val_len_arg), type(type_arg),
+     charset_number(charset_number_arg), flags(flags_arg)
+    { 
+      is_null= !val;
+    }
   void pack_info(Protocol* protocol);
 #else
   void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -2986,7 +3028,7 @@ public:
                                ulong query_length, uint fn_pos_start_arg,
                                uint fn_pos_end_arg,
                                enum_load_dup_handling dup_handling_arg,
-                               bool using_trans, bool direct,
+                               bool using_trans, bool immediate,
                                bool suppress_use, int errcode);
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
@@ -4006,18 +4048,20 @@ class Incident_log_event : public Log_ev
 public:
 #ifdef MYSQL_SERVER
   Incident_log_event(THD *thd_arg, Incident incident)
-    : Log_event(thd_arg, LOG_EVENT_NO_FILTER_F, FALSE), m_incident(incident)
+    : Log_event(thd_arg, LOG_EVENT_NO_FILTER_F, Log_event::EVENT_NO_CACHE,
+                Log_event::EVENT_IMMEDIATE_LOGGING), m_incident(incident)
   {
     DBUG_ENTER("Incident_log_event::Incident_log_event");
     DBUG_PRINT("enter", ("m_incident: %d", m_incident));
     m_message.str= NULL;                    /* Just as a precaution */
     m_message.length= 0;
-    set_direct_logging();
     DBUG_VOID_RETURN;
   }
 
   Incident_log_event(THD *thd_arg, Incident incident, LEX_STRING const msg)
-    : Log_event(thd_arg, LOG_EVENT_NO_FILTER_F, FALSE), m_incident(incident)
+    : Log_event(thd_arg, LOG_EVENT_NO_FILTER_F,
+                Log_event::EVENT_NO_CACHE,
+                Log_event::EVENT_IMMEDIATE_LOGGING), m_incident(incident)
   {
     DBUG_ENTER("Incident_log_event::Incident_log_event");
     DBUG_PRINT("enter", ("m_incident: %d", m_incident));
@@ -4031,7 +4075,6 @@ public:
     }
     strmake(m_message.str, msg.str, msg.length);
     m_message.length= msg.length;
-    set_direct_logging();
     DBUG_VOID_RETURN;
   }
 #endif
@@ -4089,7 +4132,9 @@ class Ignorable_log_event : public Log_e
 public:
 #ifndef MYSQL_CLIENT
   Ignorable_log_event(THD *thd_arg)
-      : Log_event(thd_arg, LOG_EVENT_IGNORABLE_F, FALSE)
+      : Log_event(thd_arg, LOG_EVENT_IGNORABLE_F, 
+                  Log_event::EVENT_STMT_CACHE,
+                  Log_event::EVENT_NORMAL_LOGGING)
   {
     DBUG_ENTER("Ignorable_log_event::Ignorable_log_event");
     DBUG_VOID_RETURN;

=== modified file 'sql/log_event_old.cc'
--- a/sql/log_event_old.cc	2010-11-01 05:40:27 +0000
+++ b/sql/log_event_old.cc	2011-05-12 21:51:20 +0000
@@ -1230,8 +1230,11 @@ int Update_rows_log_event_old::do_exec_r
 #ifndef MYSQL_CLIENT
 Old_rows_log_event::Old_rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid,
                                        MY_BITMAP const *cols,
-                                       bool is_transactional)
-  : Log_event(thd_arg, 0, is_transactional),
+                                       bool using_trans)
+  : Log_event(thd_arg, 0,
+              using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                            Log_event::EVENT_STMT_CACHE,
+              Log_event::EVENT_NORMAL_LOGGING),
     m_row_count(0),
     m_table(tbl_arg),
     m_table_id(tid),
@@ -1746,7 +1749,7 @@ int Old_rows_log_event::do_apply_event(R
     last_event_start_time here instead.
   */
   if (table && (table->s->primary_key == MAX_KEY) &&
-      !use_trans_cache() && get_flags(STMT_END_F) == RLE_NO_FLAGS)
+      !is_using_trans_cache() && get_flags(STMT_END_F) == RLE_NO_FLAGS)
   {
     /*
       ------------ Temporary fix until WL#2975 is implemented ---------

=== modified file 'sql/net_serv.cc'
--- a/sql/net_serv.cc	2011-03-09 21:28:05 +0000
+++ b/sql/net_serv.cc	2011-06-06 19:24:25 +0000
@@ -10,8 +10,8 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
 
 /**
   @file
@@ -61,50 +61,27 @@
   the client should have a bigger max_allowed_packet.
 */
 
-#if defined(__WIN__) || !defined(MYSQL_SERVER)
-  /* The following is because alarms doesn't work on windows. */
-#ifndef NO_ALARM
-#define NO_ALARM
-#endif
-#endif
-
-#ifndef NO_ALARM
-#include "my_pthread.h"
-void sql_print_error(const char *format,...);
-#else
-#define DONT_USE_THR_ALARM
-#endif /* NO_ALARM */
-
-#include "thr_alarm.h"
-
 #ifdef MYSQL_SERVER
 /*
   The following variables/functions should really not be declared
   extern, but as it's hard to include sql_priv.h here, we have to
   live with this for a while.
 */
-extern uint test_flags;
-extern ulong bytes_sent, bytes_received, net_big_packet_count;
-#ifndef MYSQL_INSTANCE_MANAGER
 #ifdef HAVE_QUERY_CACHE
 #define USE_QUERY_CACHE
 extern void query_cache_insert(const char *packet, ulong length,
                                unsigned pkt_nr);
-#endif // HAVE_QUERY_CACHE
+#endif /* HAVE_QUERY_CACHE */
 #define update_statistics(A) A
-#endif /* MYSQL_INSTANCE_MANGER */
-#endif /* defined(MYSQL_SERVER) && !defined(MYSQL_INSTANCE_MANAGER) */
-
-#if !defined(MYSQL_SERVER) || defined(MYSQL_INSTANCE_MANAGER)
+#else /* MYSQL_SERVER */
 #define update_statistics(A)
 #define thd_increment_bytes_sent(N)
 #endif
 
-#define TEST_BLOCKING		8
+#define VIO_SOCKET_ERROR  ((size_t) -1)
 #define MAX_PACKET_LENGTH (256L*256L*256L-1)
 
-static my_bool net_write_buff(NET *net,const uchar *packet,ulong len);
-
+static my_bool net_write_buff(NET *, const uchar *, ulong);
 
 /** Init with packet info. */
 
@@ -126,20 +103,11 @@ my_bool my_net_init(NET *net, Vio* vio)
   net->where_b = net->remain_in_buf=0;
   net->last_errno=0;
   net->unused= 0;
-#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
-  net->skip_big_packet= FALSE;
-#endif
 
-  if (vio != 0)					/* If real connection */
+  if (vio)
   {
-    net->fd  = vio_getfd(vio);			/* For perl DBI/DBD */
-#if defined(MYSQL_SERVER) && !defined(__WIN__)
-    if (!(test_flags & TEST_BLOCKING))
-    {
-      my_bool old_mode;
-      vio_blocking(vio, FALSE, &old_mode);
-    }
-#endif
+    /* For perl DBI/DBD. */
+    net->fd= vio_getfd(vio);
     vio_fastsend(vio);
   }
   DBUG_RETURN(0);
@@ -180,7 +148,7 @@ my_bool net_realloc(NET *net, size_t len
   /*
     We must allocate some extra bytes for the end 0 and to be able to
     read big compressed blocks + 1 safety byte since uint3korr() in
-    my_real_read() may actually read 4 bytes depending on build flags and
+    net_read_packet() may actually read 4 bytes depending on build flags and
     platform.
   */
   if (!(buff= (uchar*) my_realloc((char*) net->buff, pkt_length +
@@ -200,128 +168,29 @@ my_bool net_realloc(NET *net, size_t len
 
 
 /**
-  Check if there is any data to be read from the socket.
+  Clear (reinitialize) the NET structure for a new command.
 
-  @param sd   socket descriptor
+  @remark Performs debug checking of the socket buffer to
+          ensure that the protocol sequence is correct.
 
-  @retval
-    0  No data to read
-  @retval
-    1  Data or EOF to read
-  @retval
-    -1   Don't know if data is ready or not
+  @param net          NET handler
+  @param check_buffer  Whether to check the socket buffer.
 */
 
-#if !defined(EMBEDDED_LIBRARY)
-
-static int net_data_is_ready(my_socket sd)
+void net_clear(NET *net,
+               my_bool check_buffer __attribute__((unused)))
 {
-#ifdef HAVE_POLL
-  struct pollfd ufds;
-  int res;
-
-  ufds.fd= sd;
-  ufds.events= POLLIN | POLLPRI;
-  if (!(res= poll(&ufds, 1, 0)))
-    return 0;
-  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
-    return 0;
-  return 1;
-#else
-  fd_set sfds;
-  struct timeval tv;
-  int res;
-
-#ifndef __WIN__
-  /* Windows uses an _array_ of 64 fd's as default, so it's safe */
-  if (sd >= FD_SETSIZE)
-    return -1;
-#define NET_DATA_IS_READY_CAN_RETURN_MINUS_ONE
-#endif
-
-  FD_ZERO(&sfds);
-  FD_SET(sd, &sfds);
-
-  tv.tv_sec= tv.tv_usec= 0;
-
-  if ((res= select((int) (sd + 1), &sfds, NULL, NULL, &tv)) < 0)
-    return 0;
-  else
-    return test(res ? FD_ISSET(sd, &sfds) : 0);
-#endif /* HAVE_POLL */
-}
-
-#endif /* EMBEDDED_LIBRARY */
-
-/**
-  Remove unwanted characters from connection
-  and check if disconnected.
-
-    Read from socket until there is nothing more to read. Discard
-    what is read.
-
-    If there is anything when to read 'net_clear' is called this
-    normally indicates an error in the protocol.
-
-    When connection is properly closed (for TCP it means with
-    a FIN packet), then select() considers a socket "ready to read",
-    in the sense that there's EOF to read, but read() returns 0.
-
-  @param net			NET handler
-  @param clear_buffer           if <> 0, then clear all data from comm buff
-*/
-
-void net_clear(NET *net, my_bool clear_buffer)
-{
-#if !defined(EMBEDDED_LIBRARY)
-  size_t count;
-  int ready;
-#endif
   DBUG_ENTER("net_clear");
 
 #if !defined(EMBEDDED_LIBRARY)
-  if (clear_buffer)
-  {
-    while ((ready= net_data_is_ready(vio_getfd(net->vio))) > 0)
-    {
-      /* The socket is ready */
-      if ((long) (count= vio_read(net->vio, net->buff,
-                                  (size_t) net->max_packet)) > 0)
-      {
-        DBUG_PRINT("info",("skipped %ld bytes from file: %s",
-                           (long) count, vio_description(net->vio)));
-#if defined(EXTRA_DEBUG)
-        fprintf(stderr,"Note: net_clear() skipped %ld bytes from file: %s\n",
-                (long) count, vio_description(net->vio));
+  /* Ensure the socket buffer is empty, except for an EOF (at least 1). */
+  DBUG_ASSERT(!check_buffer || (vio_pending(net->vio) <= 1));
 #endif
-      }
-      else
-      {
-        DBUG_PRINT("info",("socket ready but only EOF to read - disconnected"));
-        net->error= 2;
-        break;
-      }
-    }
-#ifdef NET_DATA_IS_READY_CAN_RETURN_MINUS_ONE
-    /* 'net_data_is_ready' returned "don't know" */
-    if (ready == -1)
-    {
-      /* Read unblocking to clear net */
-      my_bool old_mode;
-      if (!vio_blocking(net->vio, FALSE, &old_mode))
-      {
-        while ((long) (count= vio_read(net->vio, net->buff,
-                                       (size_t) net->max_packet)) > 0)
-          DBUG_PRINT("info",("skipped %ld bytes from file: %s",
-                             (long) count, vio_description(net->vio)));
-        vio_blocking(net->vio, TRUE, &old_mode);
-      }
-    }
-#endif /* NET_DATA_IS_READY_CAN_RETURN_MINUS_ONE */
-  }
-#endif /* EMBEDDED_LIBRARY */
-  net->pkt_nr=net->compress_pkt_nr=0;		/* Ready for new command */
-  net->write_pos=net->buff;
+
+  /* Ready for new command */
+  net->pkt_nr= net->compress_pkt_nr= 0;
+  net->write_pos= net->buff;
+
   DBUG_VOID_RETURN;
 }
 
@@ -334,9 +203,9 @@ my_bool net_flush(NET *net)
   DBUG_ENTER("net_flush");
   if (net->buff != net->write_pos)
   {
-    error=test(net_real_write(net, net->buff,
-			      (size_t) (net->write_pos - net->buff)));
-    net->write_pos=net->buff;
+    error= net_write_packet(net, net->buff,
+                            (size_t) (net->write_pos - net->buff));
+    net->write_pos= net->buff;
   }
   /* Sync packet number if using compression */
   if (net->compress)
@@ -345,6 +214,42 @@ my_bool net_flush(NET *net)
 }
 
 
+/**
+  Whether a I/O operation should be retried later.
+
+  @param net          NET handler.
+  @param retry_count  Maximum number of interrupted operations.
+
+  @retval TRUE    Operation should be retried.
+  @retval FALSE   Operation should not be retried. Fatal error.
+*/
+
+static my_bool
+net_should_retry(NET *net, uint *retry_count __attribute__((unused)))
+{
+  my_bool retry;
+
+#if !defined(MYSQL_SERVER) && defined(THREAD_SAFE_CLIENT)
+  /*
+    In the thread safe client library, interrupted I/O operations
+    are always retried.  Otherwise, its either a timeout or a
+    unrecoverable error.
+  */
+  retry= vio_should_retry(net->vio);
+#else
+  /*
+    In the non-thread safe client library, or in the server,
+    interrupted I/O operations are retried up to a limit.
+    In this scenario, pthread_kill can be used to wake up
+    (interrupt) threads waiting for I/O.
+  */
+  retry= vio_should_retry(net->vio) && ((*retry_count)++ < net->retry_count);
+#endif
+
+  return retry;
+}
+
+
 /*****************************************************************************
 ** Write something to server/client buffer
 *****************************************************************************/
@@ -352,15 +257,13 @@ my_bool net_flush(NET *net)
 /**
   Write a logical packet with packet header.
 
-  Format: Packet length (3 bytes), packet number(1 byte)
-  When compression is used a 3 byte compression length is added
+  Format: Packet length (3 bytes), packet number (1 byte)
+  When compression is used, a 3 byte compression length is added.
 
-  @note
-    If compression is used the original package is modified!
+  @note If compression is used, the original packet is modified!
 */
 
-my_bool
-my_net_write(NET *net,const uchar *packet,size_t len)
+my_bool my_net_write(NET *net, const uchar *packet, size_t len)
 {
   uchar buff[NET_HEADER_SIZE];
   int rc;
@@ -405,6 +308,7 @@ my_net_write(NET *net,const uchar *packe
   return rc;
 }
 
+
 /**
   Send a command to the server.
 
@@ -480,6 +384,7 @@ net_write_command(NET *net,uchar command
   DBUG_RETURN(rc);
 }
 
+
 /**
   Caching the data in a local buffer before sending it.
 
@@ -497,7 +402,7 @@ net_write_command(NET *net,uchar command
   @note
     The cached buffer can be sent as it is with 'net_flush()'.
     In this code we have to be careful to not send a packet longer than
-    MAX_PACKET_LENGTH to net_real_write() if we are using the compressed
+    MAX_PACKET_LENGTH to net_write_packet() if we are using the compressed
     protocol as we store the length of the compressed packet in 3 bytes.
 
   @retval
@@ -523,9 +428,9 @@ net_write_buff(NET *net, const uchar *pa
     if (net->write_pos != net->buff)
     {
       /* Fill up already used packet and write it */
-      memcpy((char*) net->write_pos,packet,left_length);
-      if (net_real_write(net, net->buff, 
-			 (size_t) (net->write_pos - net->buff) + left_length))
+      memcpy(net->write_pos, packet, left_length);
+      if (net_write_packet(net, net->buff,
+                           (size_t) (net->write_pos - net->buff) + left_length))
 	return 1;
       net->write_pos= net->buff;
       packet+= left_length;
@@ -540,461 +445,380 @@ net_write_buff(NET *net, const uchar *pa
       left_length= MAX_PACKET_LENGTH;
       while (len > left_length)
       {
-	if (net_real_write(net, packet, left_length))
+	if (net_write_packet(net, packet, left_length))
 	  return 1;
 	packet+= left_length;
 	len-= left_length;
       }
     }
     if (len > net->max_packet)
-      return net_real_write(net, packet, len) ? 1 : 0;
+      return net_write_packet(net, packet, len);
     /* Send out rest of the blocks as full sized blocks */
   }
-  memcpy((char*) net->write_pos,packet,len);
+  memcpy(net->write_pos, packet, len);
   net->write_pos+= len;
   return 0;
 }
 
 
 /**
-  Read and write one packet using timeouts.
-  If needed, the packet is compressed before sending.
+  Write a determined number of bytes to a network handler.
 
-  @todo
-    - TODO is it needed to set this variable if we have no socket
+  @param  net     NET handler.
+  @param  buf     Buffer containing the data to be written.
+  @param  count   The length, in bytes, of the buffer.
+
+  @return TRUE on error, FALSE on success.
 */
 
-int
-net_real_write(NET *net,const uchar *packet, size_t len)
+static my_bool
+net_write_raw_loop(NET *net, const uchar *buf, size_t count)
 {
-  size_t length;
-  const uchar *pos,*end;
-  thr_alarm_t alarmed;
-#ifndef NO_ALARM
-  ALARM alarm_buff;
+  unsigned int retry_count= 0;
+
+  while (count)
+  {
+    size_t sentcnt= vio_write(net->vio, buf, count);
+
+    /* VIO_SOCKET_ERROR (-1) indicates an error. */
+    if (sentcnt == VIO_SOCKET_ERROR)
+    {
+      /* A recoverable I/O error occurred? */
+      if (net_should_retry(net, &retry_count))
+        continue;
+      else
+        break;
+    }
+
+    count-= sentcnt;
+    buf+= sentcnt;
+    update_statistics(thd_increment_bytes_sent(sentcnt));
+  }
+
+  /* On failure, propagate the error code. */
+  if (count)
+  {
+    /* Socket should be closed. */
+    net->error= 2;
+
+    /* Interrupted by a timeout? */
+    if (vio_was_timeout(net->vio))
+      net->last_errno= ER_NET_WRITE_INTERRUPTED;
+    else
+      net->last_errno= ER_NET_ERROR_ON_WRITE;
+
+#ifdef MYSQL_SERVER
+    my_error(net->last_errno, MYF(0));
 #endif
-  uint retry_count=0;
-  my_bool net_blocking = vio_is_blocking(net->vio);
-  DBUG_ENTER("net_real_write");
+  }
+
+  return test(count);
+}
+
+
+/**
+  Compress and encapsulate a packet into a compressed packet.
+
+  @param          net      NET handler.
+  @param          packet   The packet to compress.
+  @param[in,out]  length   Length of the packet.
+
+  A compressed packet header is compromised of the packet
+  length (3 bytes), packet number (1 byte) and the length
+  of the original (uncompressed) packet.
+
+  @return Pointer to the (new) compressed packet.
+*/
+
+static uchar *
+compress_packet(NET *net, const uchar *packet, size_t *length)
+{
+  uchar *compr_packet;
+  size_t compr_length;
+  const uint header_length= NET_HEADER_SIZE + COMP_HEADER_SIZE;
+
+  compr_packet= (uchar *) my_malloc(*length + header_length, MYF(MY_WME));
+
+  if (compr_packet == NULL)
+    return NULL;
+
+  memcpy(compr_packet + header_length, packet, *length);
+
+  /* Compress the encapsulated packet. */
+  if (my_compress(compr_packet + header_length, length, &compr_length))
+  {
+    /*
+      If the length of the compressed packet is larger than the
+      original packet, the original packet is sent uncompressed.
+    */
+    compr_length= 0;
+  }
+
+  /* Length of the compressed (original) packet. */
+  int3store(&compr_packet[NET_HEADER_SIZE], compr_length);
+  /* Length of this packet. */
+  int3store(compr_packet, *length);
+  /* Packet number. */
+  compr_packet[3]= (uchar) (net->compress_pkt_nr++);
+
+  *length+= header_length;
+
+  return compr_packet;
+}
+
+
+/**
+  Write a MySQL protocol packet to the network handler.
+
+  @param  net     NET handler.
+  @param  packet  The packet to write.
+  @param  length  Length of the packet.
+
+  @remark The packet might be encapsulated into a compressed packet.
+
+  @return TRUE on error, FALSE on success.
+*/
+
+my_bool
+net_write_packet(NET *net, const uchar *packet, size_t length)
+{
+  my_bool res;
+  DBUG_ENTER("net_write_packet");
 
 #if defined(MYSQL_SERVER) && defined(USE_QUERY_CACHE)
-  query_cache_insert((char*) packet, len, net->pkt_nr);
+  query_cache_insert((char*) packet, length, net->pkt_nr);
 #endif
 
+  /* Socket can't be used */
   if (net->error == 2)
-    DBUG_RETURN(-1);				/* socket can't be used */
+    DBUG_RETURN(TRUE);
+
+  net->reading_or_writing= 2;
 
-  net->reading_or_writing=2;
 #ifdef HAVE_COMPRESS
   if (net->compress)
   {
-    size_t complen;
-    uchar *b;
-    uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
-    if (!(b= (uchar*) my_malloc(len + NET_HEADER_SIZE +
-                                COMP_HEADER_SIZE, MYF(MY_WME))))
+    if ((packet= compress_packet(net, packet, &length)) == NULL)
     {
       net->error= 2;
       net->last_errno= ER_OUT_OF_RESOURCES;
-      /* In the server, the error is reported by MY_WME flag. */
+      /* In the server, allocation failure raises a error. */
       net->reading_or_writing= 0;
-      DBUG_RETURN(1);
+      DBUG_RETURN(TRUE);
     }
-    memcpy(b+header_length,packet,len);
-
-    if (my_compress(b+header_length, &len, &complen))
-      complen=0;
-    int3store(&b[NET_HEADER_SIZE],complen);
-    int3store(b,len);
-    b[3]=(uchar) (net->compress_pkt_nr++);
-    len+= header_length;
-    packet= b;
   }
 #endif /* HAVE_COMPRESS */
 
 #ifdef DEBUG_DATA_PACKETS
-  DBUG_DUMP("data", packet, len);
+  DBUG_DUMP("data", packet, length);
 #endif
 
-#ifndef NO_ALARM
-  thr_alarm_init(&alarmed);
-  if (net_blocking)
-    thr_alarm(&alarmed, net->write_timeout, &alarm_buff);
-#else
-  alarmed=0;
-  /* Write timeout is set in my_net_set_write_timeout */
-#endif /* NO_ALARM */
-
-  pos= packet;
-  end=pos+len;
-  while (pos != end)
-  {
-    if ((long) (length= vio_write(net->vio,pos,(size_t) (end-pos))) <= 0)
-    {
-      my_bool interrupted = vio_should_retry(net->vio);
-#if !defined(__WIN__)
-      if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed))
-      {
-        if (!thr_alarm(&alarmed, net->write_timeout, &alarm_buff))
-        {                                       /* Always true for client */
-	  my_bool old_mode;
-	  while (vio_blocking(net->vio, TRUE, &old_mode) < 0)
-	  {
-	    if (vio_should_retry(net->vio) && retry_count++ < net->retry_count)
-	      continue;
-#ifdef EXTRA_DEBUG
-	    fprintf(stderr,
-		    "%s: my_net_write: fcntl returned error %d, aborting thread\n",
-		    my_progname,vio_errno(net->vio));
-#endif /* EXTRA_DEBUG */
-	    net->error= 2;                     /* Close socket */
-            net->last_errno= ER_NET_PACKET_TOO_LARGE;
-#ifdef MYSQL_SERVER
-            my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
-#endif
-	    goto end;
-	  }
-	  retry_count=0;
-	  continue;
-	}
-      }
-      else
-#endif /* !defined(__WIN__) */
-	if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) &&
-	    interrupted)
-      {
-	if (retry_count++ < net->retry_count)
-	    continue;
-#ifdef EXTRA_DEBUG
-	  fprintf(stderr, "%s: write looped, aborting thread\n",
-		  my_progname);
-#endif /* EXTRA_DEBUG */
-      }
-#if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER)
-      if (vio_errno(net->vio) == SOCKET_EINTR)
-      {
-	DBUG_PRINT("warning",("Interrupted write. Retrying..."));
-	continue;
-      }
-#endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */
-      net->error= 2;				/* Close socket */
-      net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
-                               ER_NET_ERROR_ON_WRITE);
-#ifdef MYSQL_SERVER
-      my_error(net->last_errno, MYF(0));
-#endif /* MYSQL_SERVER */
-      break;
-    }
-    pos+=length;
-    update_statistics(thd_increment_bytes_sent(length));
-  }
-#ifndef __WIN__
- end:
-#endif
+  res= net_write_raw_loop(net, packet, length);
+
 #ifdef HAVE_COMPRESS
   if (net->compress)
-    my_free((void*) packet);
+    my_free((void *) packet);
 #endif
-  if (thr_alarm_in_use(&alarmed))
-  {
-    my_bool old_mode;
-    thr_end_alarm(&alarmed);
-    vio_blocking(net->vio, net_blocking, &old_mode);
-  }
-  net->reading_or_writing=0;
-  DBUG_RETURN(((int) (pos != end)));
-}
 
+  net->reading_or_writing= 0;
+
+  DBUG_RETURN(res);
+}
 
 /*****************************************************************************
 ** Read something from server/clinet
 *****************************************************************************/
 
-#ifndef NO_ALARM
+/**
+  Read a determined number of bytes from a network handler.
+
+  @param  net     NET handler.
+  @param  count   The number of bytes to read.
 
-static my_bool net_safe_read(NET *net, uchar *buff, size_t length,
-			     thr_alarm_t *alarmed)
+  @return TRUE on error, FALSE on success.
+*/
+
+static my_bool net_read_raw_loop(NET *net, size_t count)
 {
-  uint retry_count=0;
-  while (length > 0)
+  bool eof= false;
+  unsigned int retry_count= 0;
+  uchar *buf= net->buff + net->where_b;
+
+  while (count)
   {
-    size_t tmp;
-    if ((long) (tmp= vio_read(net->vio, buff, length)) <= 0)
+    size_t recvcnt= vio_read(net->vio, buf, count);
+
+    /* VIO_SOCKET_ERROR (-1) indicates an error. */
+    if (recvcnt == VIO_SOCKET_ERROR)
     {
-      my_bool interrupted = vio_should_retry(net->vio);
-      if (!thr_got_alarm(alarmed) && interrupted)
-      {					/* Probably in MIT threads */
-	if (retry_count++ < net->retry_count)
-	  continue;
-      }
-      return 1;
+      /* A recoverable I/O error occurred? */
+      if (net_should_retry(net, &retry_count))
+        continue;
+      else
+        break;
+    }
+    /* Zero indicates end of file. */
+    else if (!recvcnt)
+    {
+      eof= true;
+      break;
     }
-    length-= tmp;
-    buff+= tmp;
+
+    count-= recvcnt;
+    buf+= recvcnt;
+    update_statistics(thd_increment_bytes_received(recvcnt));
   }
-  return 0;
+
+  /* On failure, propagate the error code. */
+  if (count)
+  {
+    /* Socket should be closed. */
+    net->error= 2;
+
+    /* Interrupted by a timeout? */
+    if (!eof && vio_was_timeout(net->vio))
+      net->last_errno= ER_NET_READ_INTERRUPTED;
+    else
+      net->last_errno= ER_NET_READ_ERROR;
+
+#ifdef MYSQL_SERVER
+    my_error(net->last_errno, MYF(0));
+#endif
+  }
+
+  return test(count);
 }
 
+
 /**
-  Help function to clear the commuication buffer when we get a too big packet.
+  Read the header of a packet. The MySQL protocol packet header
+  consists of the length, in bytes, of the payload (packet data)
+  and a serial number.
 
-  @param net		Communication handle
-  @param remain	Bytes to read
-  @param alarmed	Parameter for thr_alarm()
-  @param alarm_buff	Parameter for thr_alarm()
+  @remark The encoded length is the length of the packet payload,
+          which does not include the packet header.
 
-  @retval
-   0	Was able to read the whole packet
-  @retval
-   1	Got mailformed packet from client
+  @remark The serial number is used to ensure that the packets are
+          received in order. If the packet serial number does not
+          match the expected value, a error is returned.
+
+  @param  net  NET handler.
+
+  @return TRUE on error, FALSE on success.
 */
 
-static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed,
-				ALARM *alarm_buff)
+static my_bool net_read_packet_header(NET *net)
 {
-  uint32 old=remain;
-  DBUG_ENTER("my_net_skip_rest");
-  DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain));
+  uchar pkt_nr;
+  size_t count= NET_HEADER_SIZE;
 
-  /* The following is good for debugging */
-  update_statistics(thd_increment_net_big_packet_count(1));
+  if (net->compress)
+    count+= COMP_HEADER_SIZE;
 
-  if (!thr_alarm_in_use(alarmed))
-  {
-    my_bool old_mode;
-    if (thr_alarm(alarmed,net->read_timeout, alarm_buff) ||
-	vio_blocking(net->vio, TRUE, &old_mode) < 0)
-      DBUG_RETURN(1);				/* Can't setup, abort */
-  }
-  for (;;)
+  if (net_read_raw_loop(net, count))
+    return TRUE;
+
+  DBUG_DUMP("packet_header", net->buff + net->where_b, NET_HEADER_SIZE);
+
+  pkt_nr= net->buff[net->where_b + 3];
+
+  /*
+    Verify packet serial number against the truncated packet counter.
+    The local packet counter must be truncated since its not reset.
+  */
+  if (pkt_nr != (uchar) net->pkt_nr)
   {
-    while (remain > 0)
-    {
-      size_t length= min(remain, net->max_packet);
-      if (net_safe_read(net, net->buff, length, alarmed))
-	DBUG_RETURN(1);
-      update_statistics(thd_increment_bytes_received(length));
-      remain -= (uint32) length;
-    }
-    if (old != MAX_PACKET_LENGTH)
-      break;
-    if (net_safe_read(net, net->buff, NET_HEADER_SIZE, alarmed))
-      DBUG_RETURN(1);
-    old=remain= uint3korr(net->buff);
-    net->pkt_nr++;
+    /* Not a NET error on the client. XXX: why? */
+#if defined(MYSQL_SERVER)
+    my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0));
+#elif defined(EXTRA_DEBUG)
+    /*
+      We don't make noise server side, since the client is expected
+      to break the protocol for e.g. --send LOAD DATA .. LOCAL where
+      the server expects the client to send a file, but the client
+      may reply with a new command instead.
+    */
+    fprintf(stderr, "Error: packets out of order (found %u, expected %u)\n",
+            (uint) pkt_nr, net->pkt_nr);
+    DBUG_ASSERT(pkt_nr == net->pkt_nr);
+#endif
+    return TRUE;
   }
-  DBUG_RETURN(0);
+
+  net->pkt_nr++;
+
+  return FALSE;
 }
-#endif /* NO_ALARM */
 
 
 /**
-  Reads one packet to net->buff + net->where_b.
-  Long packets are handled by my_net_read().
-  This function reallocates the net->buff buffer if necessary.
+  Read one (variable-length) MySQL protocol packet.
+  A MySQL packet consists of a header and a payload.
 
-  @return
-    Returns length of packet.
+  @remark Reads one packet to net->buff + net->where_b.
+  @remark Long packets are handled by my_net_read().
+  @remark The network buffer is expanded if necessary.
+
+  @return The length of the packet, or @packet_error on error.
 */
 
-static ulong
-my_real_read(NET *net, size_t *complen)
+static ulong net_read_packet(NET *net, size_t *complen)
 {
-  uchar *pos;
-  size_t length;
-  uint i,retry_count=0;
-  ulong len=packet_error;
-  thr_alarm_t alarmed;
-#ifndef NO_ALARM
-  ALARM alarm_buff;
-#endif
-  my_bool net_blocking=vio_is_blocking(net->vio);
-  uint32 remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
-		  NET_HEADER_SIZE);
-  *complen = 0;
-
-  net->reading_or_writing=1;
-  thr_alarm_init(&alarmed);
-#ifndef NO_ALARM
-  if (net_blocking)
-    thr_alarm(&alarmed,net->read_timeout,&alarm_buff);
-#else
-  /* Read timeout is set in my_net_set_read_timeout */
-#endif /* NO_ALARM */
+  size_t pkt_len, pkt_data_len;
 
-    pos = net->buff + net->where_b;		/* net->packet -4 */
-    for (i=0 ; i < 2 ; i++)
-    {
-      while (remain > 0)
-      {
-	/* First read is done with non blocking mode */
-        if ((long) (length= vio_read(net->vio, pos, remain)) <= 0L)
-        {
-          my_bool interrupted = vio_should_retry(net->vio);
-
-	  DBUG_PRINT("info",("vio_read returned %ld  errno: %d",
-			     (long) length, vio_errno(net->vio)));
-#if !defined(__WIN__) || defined(MYSQL_SERVER)
-	  /*
-	    We got an error that there was no data on the socket. We now set up
-	    an alarm to not 'read forever', change the socket to non blocking
-	    mode and try again
-	  */
-	  if ((interrupted || length == 0) && !thr_alarm_in_use(&alarmed))
-	  {
-	    if (!thr_alarm(&alarmed,net->read_timeout,&alarm_buff)) /* Don't wait too long */
-	    {
-	      my_bool old_mode;
-	      while (vio_blocking(net->vio, TRUE, &old_mode) < 0)
-	      {
-		if (vio_should_retry(net->vio) &&
-		    retry_count++ < net->retry_count)
-		  continue;
-		DBUG_PRINT("error",
-			   ("fcntl returned error %d, aborting thread",
-			    vio_errno(net->vio)));
-#ifdef EXTRA_DEBUG
-		fprintf(stderr,
-			"%s: read: fcntl returned error %d, aborting thread\n",
-			my_progname,vio_errno(net->vio));
-#endif /* EXTRA_DEBUG */
-		len= packet_error;
-		net->error= 2;                 /* Close socket */
-	        net->last_errno= ER_NET_FCNTL_ERROR;
-#ifdef MYSQL_SERVER
-		my_error(ER_NET_FCNTL_ERROR, MYF(0));
-#endif
-		goto end;
-	      }
-	      retry_count=0;
-	      continue;
-	    }
-	  }
-#endif /* (!defined(__WIN__) || defined(MYSQL_SERVER) */
-	  if (thr_alarm_in_use(&alarmed) && !thr_got_alarm(&alarmed) &&
-	      interrupted)
-	  {					/* Probably in MIT threads */
-	    if (retry_count++ < net->retry_count)
-	      continue;
-#ifdef EXTRA_DEBUG
-	    fprintf(stderr, "%s: read looped with error %d, aborting thread\n",
-		    my_progname,vio_errno(net->vio));
-#endif /* EXTRA_DEBUG */
-	  }
-#if defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER)
-	  if (vio_errno(net->vio) == SOCKET_EINTR)
-	  {
-	    DBUG_PRINT("warning",("Interrupted read. Retrying..."));
-	    continue;
-	  }
-#endif
-	  DBUG_PRINT("error",("Couldn't read packet: remain: %u  errno: %d  length: %ld",
-			      remain, vio_errno(net->vio), (long) length));
-	  len= packet_error;
-	  net->error= 2;				/* Close socket */
-          net->last_errno= (vio_was_interrupted(net->vio) ?
-                                   ER_NET_READ_INTERRUPTED :
-                                   ER_NET_READ_ERROR);
-#ifdef MYSQL_SERVER
-          my_error(net->last_errno, MYF(0));
-#endif
-	  goto end;
-	}
-	remain -= (uint32) length;
-	pos+= length;
-	update_statistics(thd_increment_bytes_received(length));
-      }
-      if (i == 0)
-      {					/* First parts is packet length */
-	ulong helping;
-        DBUG_DUMP("packet_header", net->buff+net->where_b,
-                  NET_HEADER_SIZE);
-	if (net->buff[net->where_b + 3] != (uchar) net->pkt_nr)
-	{
-	  if (net->buff[net->where_b] != (uchar) 255)
-	  {
-	    DBUG_PRINT("error",
-		       ("Packets out of order (Found: %d, expected %u)",
-			(int) net->buff[net->where_b + 3],
-			net->pkt_nr));
-            /* 
-              We don't make noise server side, since the client is expected
-              to break the protocol for e.g. --send LOAD DATA .. LOCAL where
-              the server expects the client to send a file, but the client
-              may reply with a new command instead.
-            */
-#if defined (EXTRA_DEBUG) && !defined (MYSQL_SERVER)
-            fflush(stdout);
-	    fprintf(stderr,"Error: Packets out of order (Found: %d, expected %d)\n",
-		    (int) net->buff[net->where_b + 3],
-		    (uint) (uchar) net->pkt_nr);
-            fflush(stderr);
-            DBUG_ASSERT(0);
-#endif
-	  }
-	  len= packet_error;
-          /* Not a NET error on the client. XXX: why? */
-#ifdef MYSQL_SERVER
-	  my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0));
-#endif
-	  goto end;
-	}
-	net->compress_pkt_nr= ++net->pkt_nr;
-#ifdef HAVE_COMPRESS
-	if (net->compress)
-	{
-          /*
-            The following uint3korr() may read 4 bytes, so make sure we don't
-            read unallocated or uninitialized memory. The right-hand expression
-            must match the size of the buffer allocated in net_realloc().
-          */
-          DBUG_ASSERT(net->where_b + NET_HEADER_SIZE + sizeof(uint32) <=
-                      net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1);
-	  /*
-	    If the packet is compressed then complen > 0 and contains the
-	    number of bytes in the uncompressed packet
-	  */
-	  *complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
-	}
-#endif
+  *complen= 0;
 
-	len=uint3korr(net->buff+net->where_b);
-	if (!len)				/* End of big multi-packet */
-	  goto end;
-	helping = max(len,*complen) + net->where_b;
-	/* The necessary size of net->buff */
-	if (helping >= net->max_packet)
-	{
-	  if (net_realloc(net,helping))
-	  {
-#if defined(MYSQL_SERVER) && !defined(NO_ALARM)
-	    if (!net->compress &&
-                net->skip_big_packet &&
-		!my_net_skip_rest(net, (uint32) len, &alarmed, &alarm_buff))
-	      net->error= 3;		/* Successfully skiped packet */
-#endif
-	    len= packet_error;          /* Return error and close connection */
-	    goto end;
-	  }
-	}
-	pos=net->buff + net->where_b;
-	remain = (uint32) len;
-      }
-    }
+  net->reading_or_writing= 1;
 
-end:
-  if (thr_alarm_in_use(&alarmed))
+  /* Retrieve packet length and number. */
+  if (net_read_packet_header(net))
+    goto error;
+
+  net->compress_pkt_nr= net->pkt_nr;
+
+#ifdef HAVE_COMPRESS
+  if (net->compress)
   {
-    my_bool old_mode;
-    thr_end_alarm(&alarmed);
-    vio_blocking(net->vio, net_blocking, &old_mode);
+    /*
+      The following uint3korr() may read 4 bytes, so make sure we don't
+      read unallocated or uninitialized memory. The right-hand expression
+      must match the size of the buffer allocated in net_realloc().
+    */
+    DBUG_ASSERT(net->where_b + NET_HEADER_SIZE + sizeof(uint32) <=
+                net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1);
+
+    /*
+      If the packet is compressed then complen > 0 and contains the
+      number of bytes in the uncompressed packet.
+    */
+    *complen= uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
   }
-  net->reading_or_writing=0;
-#ifdef DEBUG_DATA_PACKETS
-  if (len != packet_error)
-    DBUG_DUMP("data", net->buff+net->where_b, len);
 #endif
-  return(len);
+
+  /* The length of the packet that follows. */
+  pkt_len= uint3korr(net->buff+net->where_b);
+
+  /* End of big multi-packet. */
+  if (!pkt_len)
+    goto end;
+
+  pkt_data_len = max(pkt_len, *complen) + net->where_b;
+
+  /* Expand packet buffer if necessary. */
+  if ((pkt_data_len >= net->max_packet) && net_realloc(net, pkt_data_len))
+    goto error;
+
+  /* Read the packet data (payload). */
+  if (net_read_raw_loop(net, pkt_len))
+    goto error;
+
+end:
+  net->reading_or_writing= 0;
+  return pkt_len;
+
+error:
+  net->reading_or_writing= 0;
+  return packet_error;
 }
 
 
@@ -1025,7 +849,7 @@ my_net_read(NET *net)
   if (!net->compress)
   {
 #endif
-    len = my_real_read(net,&complen);
+    len= net_read_packet(net, &complen);
     if (len == MAX_PACKET_LENGTH)
     {
       /* First packet of a multi-packet.  Concatenate the packets */
@@ -1035,7 +859,7 @@ my_net_read(NET *net)
       {
 	net->where_b += len;
 	total_length += len;
-	len = my_real_read(net,&complen);
+	len= net_read_packet(net, &complen);
       } while (len == MAX_PACKET_LENGTH);
       if (len != packet_error)
 	len+= total_length;
@@ -1127,7 +951,7 @@ my_net_read(NET *net)
       }
 
       net->where_b=buf_length;
-      if ((packet_len = my_real_read(net,&complen)) == packet_error)
+      if ((packet_len= net_read_packet(net, &complen)) == packet_error)
       {
         MYSQL_NET_READ_DONE(1, 0);
 	return packet_error;
@@ -1165,10 +989,8 @@ void my_net_set_read_timeout(NET *net, u
   DBUG_ENTER("my_net_set_read_timeout");
   DBUG_PRINT("enter", ("timeout: %d", timeout));
   net->read_timeout= timeout;
-#ifdef NO_ALARM
   if (net->vio)
     vio_timeout(net->vio, 0, timeout);
-#endif
   DBUG_VOID_RETURN;
 }
 
@@ -1178,9 +1000,8 @@ void my_net_set_write_timeout(NET *net,
   DBUG_ENTER("my_net_set_write_timeout");
   DBUG_PRINT("enter", ("timeout: %d", timeout));
   net->write_timeout= timeout;
-#ifdef NO_ALARM
   if (net->vio)
     vio_timeout(net->vio, 1, timeout);
-#endif
   DBUG_VOID_RETURN;
 }
+

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2011-05-26 15:20:09 +0000
+++ b/sql/opt_range.cc	2011-05-30 07:00:39 +0000
@@ -9045,7 +9045,7 @@ int QUICK_RANGE_SELECT::reset()
       (Now ndb stores  complete row in here, instead of only the used fields
       which gives us valgrind warnings in compare_record[])
     */
-    memset(mrange_buff, 0, mrange_bufsiz);
+    memset(mrange_buff, 0, buf_size);
 #endif
   }
 

=== modified file 'sql/password.c'
--- a/sql/password.c	2011-05-26 15:20:09 +0000
+++ b/sql/password.c	2011-05-30 11:42:03 +0000
@@ -205,21 +205,16 @@ void scramble_323(char *to, const char *
 }
 
 
-/*
-    Check scrambled message
-    Used in pre 4.1 password handling
-  SYNOPSIS
-    check_scramble_323()
-    scrambled  scrambled message to check.
-    message    original random message which was used for scrambling; must
-               be exactly SCRAMBLED_LENGTH_323 bytes long and
-               NULL-terminated.
-    hash_pass  password which should be used for scrambling
-    All params are IN.
-
-  RETURN VALUE
-    0 - password correct
-   !0 - password invalid
+/**
+  Check scrambled message. Used in pre 4.1 password handling.
+
+  @param scrambled  Scrambled message to check.
+  @param message    Original random message which was used for scrambling.
+  @param hash_pass  Password which should be used for scrambling.
+
+  @remark scrambled and message must be SCRAMBLED_LENGTH_323 bytes long.
+
+  @return FALSE if password is correct, TRUE otherwise.
 */
 
 my_bool
@@ -228,9 +223,16 @@ check_scramble_323(const unsigned char *
 {
   struct rand_struct rand_st;
   ulong hash_message[2];
-  uchar buff[16],*to,extra;                     /* Big enough for check */
+  /* Big enough for checks. */
+  uchar buff[16], scrambled_buff[SCRAMBLE_LENGTH_323 + 1];
+  uchar *to, extra;
   const uchar *pos;
 
+  /* Ensure that the scrambled message is null-terminated. */
+  memcpy(scrambled_buff, scrambled, SCRAMBLE_LENGTH_323);
+  scrambled_buff[SCRAMBLE_LENGTH_323]= '\0';
+  scrambled= scrambled_buff;
+
   hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
   randominit(&rand_st,hash_pass[0] ^ hash_message[0],
              hash_pass[1] ^ hash_message[1]);

=== modified file 'sql/rpl_injector.cc'
--- a/sql/rpl_injector.cc	2011-05-16 14:30:54 +0000
+++ b/sql/rpl_injector.cc	2011-05-17 20:08:26 +0000
@@ -245,15 +245,11 @@ void injector::new_trans(THD *thd, injec
 int injector::record_incident(THD *thd, Incident incident)
 {
   Incident_log_event ev(thd, incident);
-  if (int error= mysql_bin_log.write(&ev))
-    return error;
-  return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+  return mysql_bin_log.write_incident(&ev, TRUE);
 }
 
 int injector::record_incident(THD *thd, Incident incident, LEX_STRING const message)
 {
   Incident_log_event ev(thd, incident, message);
-  if (int error= mysql_bin_log.write(&ev))
-    return error;
-  return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+  return mysql_bin_log.write_incident(&ev, TRUE);
 }

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	2011-05-12 17:29:19 +0000
+++ b/sql/share/errmsg-utf8.txt	2011-05-31 09:30:59 +0000
@@ -6458,7 +6458,6 @@ ER_MULTI_UPDATE_KEY_CONFLICT
 
 ER_BINLOG_STMT_CACHE_SIZE_GREATER_THAN_MAX
   eng "Option binlog_stmt_cache_size (%lu) is greater than max_binlog_stmt_cache_size (%lu); setting binlog_stmt_cache_size equal to max_binlog_stmt_cache_size."
-
 ER_CANT_UPDATE_TABLE_IN_CREATE_TABLE_SELECT
   eng "Can't update table '%-.192s' while '%-.192s' is being created."
 
@@ -6503,3 +6502,6 @@ ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_CR
   eng "The creation of some temporary tables could not be rolled back."
 ER_WARNING_NOT_COMPLETE_ROLLBACK_WITH_DROPPED_TEMP_TABLE
   eng "Some temporary tables were dropped, but these operations could not be rolled back."
+
+ER_INDEX_COLUMN_TOO_LONG
+  eng "Index column size too large. The maximum column size is %lu bytes."

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2011-05-26 15:20:09 +0000
+++ b/sql/sql_acl.cc	2011-05-31 13:52:09 +0000
@@ -8481,14 +8481,21 @@ static bool parse_com_change_user_packet
 }
 
 #ifndef EMBEDDED_LIBRARY
+
+/** Get a string according to the protocol of the underlying buffer. */
+typedef char * (*get_proto_string_func_t) (char **, size_t *, size_t *);
+
 /**
-  Get a null character terminated string from a user-supplied buffer.
+  Get a string formatted according to the 4.1 version of the MySQL protocol.
 
-  @param buffer[in, out]    Pointer to the buffer to be scanned.
+  @param buffer[in, out]    Pointer to the user-supplied buffer to be scanned.
   @param max_bytes_available[in, out]  Limit the bytes to scan.
   @param string_length[out] The number of characters scanned not including
                             the null character.
 
+  @remark Strings are always null character terminated in this version of the
+          protocol.
+
   @remark The string_length does not include the terminating null character.
           However, after the call, the buffer is increased by string_length+1
           bytes, beyond the null character if there still available bytes to
@@ -8499,9 +8506,9 @@ static bool parse_com_change_user_packet
 */
 
 static
-char *get_null_terminated_string(char **buffer,
-                                 size_t *max_bytes_available,
-                                 size_t *string_length)
+char *get_41_protocol_string(char **buffer,
+                             size_t *max_bytes_available,
+                             size_t *string_length)
 {
   char *str= (char *)memchr(*buffer, '\0', *max_bytes_available);
 
@@ -8511,7 +8518,60 @@ char *get_null_terminated_string(char **
   *string_length= (size_t)(str - *buffer);
   *max_bytes_available-= *string_length + 1;
   str= *buffer;
-  *buffer += *string_length + 1;  
+  *buffer += *string_length + 1;
+
+  return str;
+}
+
+
+/**
+  Get a string formatted according to the 4.0 version of the MySQL protocol.
+
+  @param buffer[in, out]    Pointer to the user-supplied buffer to be scanned.
+  @param max_bytes_available[in, out]  Limit the bytes to scan.
+  @param string_length[out] The number of characters scanned not including
+                            the null character.
+
+  @remark If there are not enough bytes left after the current position of
+          the buffer to satisfy the current string, the string is considered
+          to be empty and a pointer to empty_c_string is returned.
+
+  @remark A string at the end of the packet is not null terminated.
+
+  @return Pointer to beginning of the string scanned, or a pointer to a empty
+          string.
+*/
+static
+char *get_40_protocol_string(char **buffer,
+                             size_t *max_bytes_available,
+                             size_t *string_length)
+{
+  char *str;
+  size_t len;
+
+  /* No bytes to scan left, treat string as empty. */
+  if ((*max_bytes_available) == 0)
+  {
+    *string_length= 0;
+    return empty_c_string;
+  }
+
+  str= (char *) memchr(*buffer, '\0', *max_bytes_available);
+
+  /*
+    If the string was not null terminated by the client,
+    the remainder of the packet is the string. Otherwise,
+    advance the buffer past the end of the null terminated
+    string.
+  */
+  if (str == NULL)
+    len= *string_length= *max_bytes_available;
+  else
+    len= (*string_length= (size_t)(str - *buffer)) + 1;
+
+  str= *buffer;
+  *buffer+= len;
+  *max_bytes_available-= len;
 
   return str;
 }
@@ -8522,7 +8582,7 @@ char *get_null_terminated_string(char **
   @param buffer[in, out] The buffer to scan; updates position after scan.
   @param max_bytes_available[in, out] Limit the number of bytes to scan
   @param string_length[out] Number of characters scanned
-  
+
   @remark In case the length is zero, then the total size of the string is
     considered to be 1 byte; the size byte.
 
@@ -8638,7 +8698,20 @@ static ulong parse_client_handshake_pack
   if ((mpvio->client_capabilities & CLIENT_TRANSACTIONS) &&
       opt_using_transactions)
     net->return_status= mpvio->server_status;
- 
+
+  /*
+    The 4.0 and 4.1 versions of the protocol differ on how strings
+    are terminated. In the 4.0 version, if a string is at the end
+    of the packet, the string is not null terminated. Do not assume
+    that the returned string is always null terminated.
+  */
+  get_proto_string_func_t get_string;
+
+  if (mpvio->client_capabilities & CLIENT_PROTOCOL_41)
+    get_string= get_41_protocol_string;
+  else
+    get_string= get_40_protocol_string;
+
   /*
     In order to safely scan a head for '\0' string terminators
     we must keep track of how many bytes remain in the allocated
@@ -8647,8 +8720,7 @@ static ulong parse_client_handshake_pack
   size_t bytes_remaining_in_packet= pkt_len - (end - (char *)net->read_pos);
 
   size_t user_len;
-  char *user= get_null_terminated_string(&end, &bytes_remaining_in_packet,
-                                         &user_len);
+  char *user= get_string(&end, &bytes_remaining_in_packet, &user_len);
   if (user == NULL)
     return packet_error;
 
@@ -8673,8 +8745,7 @@ static ulong parse_client_handshake_pack
     /*
       Old passwords are zero terminated strings.
     */
-    passwd= get_null_terminated_string(&end, &bytes_remaining_in_packet,
-                                       &passwd_len);
+    passwd= get_string(&end, &bytes_remaining_in_packet, &passwd_len);
   }
 
   if (passwd == NULL)
@@ -8685,40 +8756,43 @@ static ulong parse_client_handshake_pack
 
   if (mpvio->client_capabilities & CLIENT_CONNECT_WITH_DB)
   {
-    db= get_null_terminated_string(&end, &bytes_remaining_in_packet,
-                                   &db_len);
+    db= get_string(&end, &bytes_remaining_in_packet, &db_len);
     if (db == NULL)
       return packet_error;
   }
 
   size_t client_plugin_len= 0;
-  char *client_plugin= get_null_terminated_string(&end,
-                                                  &bytes_remaining_in_packet,
-                                                  &client_plugin_len);
+  char *client_plugin= get_string(&end, &bytes_remaining_in_packet,
+                                  &client_plugin_len);
   if (client_plugin == NULL)
     client_plugin= &empty_c_string[0];
- 
+
   char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
   char user_buff[USERNAME_LENGTH + 1];	// buffer to store user in utf8
   uint dummy_errors;
-  
 
-  /* Since 4.1 all database names are stored in utf8 */
+
+  /*
+    Copy and convert the user and database names to the character set used
+    by the server. Since 4.1 all database names are stored in UTF-8. Also,
+    ensure that the names are properly null-terminated as this is relied
+    upon later.
+  */
   if (db)
   {
     db_len= copy_and_convert(db_buff, sizeof(db_buff) - 1, system_charset_info,
                              db, db_len, mpvio->charset_adapter->charset(),
                              &dummy_errors);
+    db_buff[db_len]= '\0';
     db= db_buff;
-    db_buff[db_len]= 0;
   }
 
   user_len= copy_and_convert(user_buff, sizeof(user_buff) - 1,
-                                system_charset_info, user, user_len,
-                                mpvio->charset_adapter->charset(),
-                                &dummy_errors);
+                             system_charset_info, user, user_len,
+                             mpvio->charset_adapter->charset(),
+                             &dummy_errors);
+  user_buff[user_len]= '\0';
   user= user_buff;
-  user_buff[user_len]= 0;
 
   /* If username starts and ends in "'", chop them off */
   if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
@@ -9468,16 +9542,6 @@ acl_authenticate(THD *thd, uint connect_
   else
     my_ok(thd);
 
-#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
-  /*
-    Allow the network layer to skip big packets. Although a malicious
-    authenticated session might use this to trick the server to read
-    big packets indefinitely, this is a previously established behavior
-    that needs to be preserved as to not break backwards compatibility.
-  */
-  thd->net.skip_big_packet= TRUE;
-#endif
-
 #ifdef HAVE_PSI_THREAD_INTERFACE
   if (likely(PSI_server != NULL))
   {

=== modified file 'sql/sql_cache.cc'
--- a/sql/sql_cache.cc	2011-05-26 15:20:09 +0000
+++ b/sql/sql_cache.cc	2011-05-31 13:52:09 +0000
@@ -275,14 +275,14 @@ functions:
        - Called before parsing and used to match a statement with the stored
          queries hash.
          If a match is found the cached result set is sent through repeated
-         calls to net_real_write. (note: calling thread doesn't have a regis-
+         calls to net_write_packet. (note: calling thread doesn't have a regis-
          tered result set writer: thd->net.query_cache_query=0)
  2. Query_cache::store_query
        - Called just before handle_select() and is used to register a result
          set writer to the statement currently being processed
          (thd->net.query_cache_query).
  3. query_cache_insert
-       - Called from net_real_write to append a result set to a cached query
+       - Called from net_write_packet to append a result set to a cached query
          if (and only if) this query has a registered result set writer
          (thd->net.query_cache_query).
  4. Query_cache::invalidate
@@ -1407,12 +1407,12 @@ send_data_in_chunks(NET *net, const ucha
 
   while (len > MAX_CHUNK_LENGTH)
   {
-    if (net_real_write(net, packet, MAX_CHUNK_LENGTH))
+    if (net_write_packet(net, packet, MAX_CHUNK_LENGTH))
       return TRUE;
     packet+= MAX_CHUNK_LENGTH;
     len-= MAX_CHUNK_LENGTH;
   }
-  if (len && net_real_write(net, packet, len))
+  if (len && net_write_packet(net, packet, len))
     return TRUE;
 
   return FALSE;

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2011-05-27 16:13:03 +0000
+++ b/sql/sql_class.cc	2011-06-06 19:24:25 +0000
@@ -3287,12 +3287,6 @@ void thd_increment_bytes_received(ulong
 }
 
 
-void thd_increment_net_big_packet_count(ulong length)
-{
-  current_thd->status_var.net_big_packet_count+= length;
-}
-
-
 void THD::set_status_var_init()
 {
   memset(&status_var, 0, sizeof(status_var));

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2011-05-26 15:20:09 +0000
+++ b/sql/sql_class.h	2011-05-31 13:52:09 +0000
@@ -561,7 +561,6 @@ typedef struct system_status_var
   ulong key_cache_write;
   /* END OF KEY_CACHE parts */
 
-  ulong net_big_packet_count;
   ulong opened_tables;
   ulong opened_shares;
   ulong select_full_join_count;
@@ -1851,8 +1850,6 @@ public:
   /*
     Public interface to write RBR events to the binlog
   */
-  void binlog_start_trans_and_stmt();
-  void binlog_set_stmt_begin();
   int binlog_write_table_map(TABLE *table, bool is_transactional,
                              bool binlog_rows_query);
   int binlog_write_row(TABLE* table, bool is_transactional,

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2011-05-26 15:20:09 +0000
+++ b/sql/sql_insert.cc	2011-05-30 06:25:47 +0000
@@ -3895,19 +3895,6 @@ select_create::prepare(List<Item> &value
   hook_ptr= &hooks;
 
   unit= u;
-
-  /*
-    Start a statement transaction before the create if we are using
-    row-based replication for the statement.  If we are creating a
-    temporary table, we need to start a statement transaction.
-  */
-  if ((thd->lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) == 0 &&
-      thd->is_current_stmt_binlog_format_row() &&
-      mysql_bin_log.is_open())
-  {
-    thd->binlog_start_trans_and_stmt();
-  }
-
   DBUG_ASSERT(create_table->table == NULL);
 
   DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists", my_sleep(6000000););

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2011-05-27 15:46:36 +0000
+++ b/sql/sql_parse.cc	2011-06-06 19:24:25 +0000
@@ -3006,8 +3006,7 @@ end_with_restore_list:
       if (incident)
       {
         Incident_log_event ev(thd, incident);
-        (void) mysql_bin_log.write(&ev);        /* error is ignored */
-        if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
+        if (mysql_bin_log.write_incident(&ev, TRUE))
         {
           res= 1;
           break;

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2011-05-26 15:20:09 +0000
+++ b/sql/sql_table.cc	2011-06-01 09:11:28 +0000
@@ -5931,6 +5931,8 @@ bool mysql_alter_table(THD *thd,char *ne
   uint index_drop_count= 0;
   uint *index_drop_buffer= NULL;
   uint index_add_count= 0;
+  handler_add_index *add= NULL;
+  bool pending_inplace_add_index= false;
   uint *index_add_buffer= NULL;
   uint candidate_key_count= 0;
   bool no_pk;
@@ -6687,6 +6689,9 @@ bool mysql_alter_table(THD *thd,char *ne
   }
   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 
+  if (error)
+    goto err_new_table_cleanup;
+
   /* If we did not need to copy, we might still need to add/drop indexes. */
   if (! new_table)
   {
@@ -6718,7 +6723,8 @@ bool mysql_alter_table(THD *thd,char *ne
           key_part->field= table->field[key_part->fieldnr];
       }
       /* Add the indexes. */
-      if ((error= table->file->add_index(table, key_info, index_add_count)))
+      if ((error= table->file->add_index(table, key_info, index_add_count,
+                                         &add)))
       {
         /*
           Exchange the key_info for the error message. If we exchange
@@ -6730,11 +6736,27 @@ bool mysql_alter_table(THD *thd,char *ne
         table->key_info= save_key_info;
         goto err_new_table_cleanup;
       }
+      pending_inplace_add_index= true;
     }
     /*end of if (index_add_count)*/
 
     if (index_drop_count)
     {
+      /* Currently we must finalize add index if we also drop indexes */
+      if (pending_inplace_add_index)
+      {
+        /* Committing index changes needs exclusive metadata lock. */
+        DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE,
+                                                   table_list->db,
+                                                   table_list->table_name,
+                                                   MDL_EXCLUSIVE));
+        if ((error= table->file->final_add_index(add, true)))
+        {
+          table->file->print_error(error, MYF(0));
+          goto err_new_table_cleanup;
+        }
+        pending_inplace_add_index= false;
+      }
       /* The prepare_drop_index() method takes an array of key numbers. */
       key_numbers= (uint*) thd->alloc(sizeof(uint) * index_drop_count);
       keyno_p= key_numbers;
@@ -6775,11 +6797,14 @@ bool mysql_alter_table(THD *thd,char *ne
   }
   /*end of if (! new_table) for add/drop index*/
 
-  if (error)
-    goto err_new_table_cleanup;
-
   if (table->s->tmp_table != NO_TMP_TABLE)
   {
+    /*
+      In-place operations are not supported for temporary tables, so
+      we don't have to call final_add_index() in this case. The assert
+      verifies that in-place add index has not been done.
+    */
+    DBUG_ASSERT(!pending_inplace_add_index);
     /* Close lock if this is a transactional table */
     if (thd->lock)
     {
@@ -6846,8 +6871,30 @@ bool mysql_alter_table(THD *thd,char *ne
     my_casedn_str(files_charset_info, old_name);
 
   if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
+  {
+    if (pending_inplace_add_index)
+    {
+      pending_inplace_add_index= false;
+      table->file->final_add_index(add, false);
+    }
+    // Mark this TABLE instance as stale to avoid out-of-sync index information.
+    table->m_needs_reopen= true;
     goto err_new_table_cleanup;
-
+  }
+  if (pending_inplace_add_index)
+  {
+    pending_inplace_add_index= false;
+    DBUG_EXECUTE_IF("alter_table_rollback_new_index", {
+      table->file->final_add_index(add, false);
+      my_error(ER_UNKNOWN_ERROR, MYF(0));
+      goto err_new_table_cleanup;
+    });
+    if ((error= table->file->final_add_index(add, true)))
+    {
+      table->file->print_error(error, MYF(0));
+      goto err_new_table_cleanup;
+    }
+  }
 
   close_all_tables_for_name(thd, table->s,
                             new_name != table_name || new_db != db);

=== modified file 'storage/innobase/data/data0data.c'
--- a/storage/innobase/data/data0data.c	2011-03-23 13:43:14 +0000
+++ b/storage/innobase/data/data0data.c	2011-05-31 09:30:59 +0000
@@ -585,7 +585,8 @@ dtuple_convert_big_rec(
 
 	if (dict_table_get_format(index->table) < UNIV_FORMAT_B) {
 		/* up to MySQL 5.1: store a 768-byte prefix locally */
-		local_len = BTR_EXTERN_FIELD_REF_SIZE + DICT_MAX_INDEX_COL_LEN;
+		local_len = BTR_EXTERN_FIELD_REF_SIZE
+			+ DICT_ANTELOPE_MAX_INDEX_COL_LEN;
 	} else {
 		/* new-format table: do not store any BLOB prefix locally */
 		local_len = BTR_EXTERN_FIELD_REF_SIZE;
@@ -757,7 +758,10 @@ dtuple_convert_back_big_rec(
 
 		local_len -= BTR_EXTERN_FIELD_REF_SIZE;
 
-		ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
+		/* Only in REDUNDANT and COMPACT format, we store
+		up to DICT_ANTELOPE_MAX_INDEX_COL_LEN (768) bytes
+		locally */
+		ut_ad(local_len <= DICT_ANTELOPE_MAX_INDEX_COL_LEN);
 
 		dfield_set_data(dfield,
 				(char*) b->data - local_len,

=== modified file 'storage/innobase/dict/dict0dict.c'
--- a/storage/innobase/dict/dict0dict.c	2011-04-26 18:59:22 +0000
+++ b/storage/innobase/dict/dict0dict.c	2011-05-31 09:30:59 +0000
@@ -1735,36 +1735,63 @@ dict_index_too_big_for_undo(
 		ulint			fixed_size
 			= dict_col_get_fixed_size(col,
 						  dict_table_is_comp(table));
+		ulint			max_prefix
+			= col->max_prefix;
 
 		if (fixed_size) {
 			/* Fixed-size columns are stored locally. */
 			max_size = fixed_size;
 		} else if (max_size <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
 			/* Short columns are stored locally. */
-		} else if (!col->ord_part) {
+		} else if (!col->ord_part
+			   || (col->max_prefix
+			       < (ulint) DICT_MAX_FIELD_LEN_BY_FORMAT(table))) {
 			/* See if col->ord_part would be set
-			because of new_index. */
+			because of new_index. Also check if the new
+			index could have longer prefix on columns
+			that already had ord_part set  */
 			ulint	j;
 
 			for (j = 0; j < new_index->n_uniq; j++) {
 				if (dict_index_get_nth_col(
 					    new_index, j) == col) {
+					const dict_field_t*     field
+						= dict_index_get_nth_field(
+							new_index, j);
+
+					if (field->prefix_len
+					    > col->max_prefix) {
+						max_prefix =
+							 field->prefix_len;
+					}
 
 					goto is_ord_part;
 				}
 			}
 
+			if (col->ord_part) {
+				goto is_ord_part;
+			}
+
 			/* This is not an ordering column in any index.
 			Thus, it can be stored completely externally. */
 			max_size = BTR_EXTERN_FIELD_REF_SIZE;
 		} else {
+			ulint	max_field_len;
 is_ord_part:
+			max_field_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table);
+
 			/* This is an ordering column in some index.
 			A long enough prefix must be written to the
 			undo log.  See trx_undo_page_fetch_ext(). */
+			max_size = ut_min(max_size, max_field_len);
+
+			/* We only store the needed prefix length in undo log */
+			if (max_prefix) {
+			     ut_ad(dict_table_get_format(table)
+				   >= UNIV_FORMAT_B);
 
-			if (max_size > REC_MAX_INDEX_COL_LEN) {
-				max_size = REC_MAX_INDEX_COL_LEN;
+				max_size = ut_min(max_prefix, max_size);
 			}
 
 			max_size += BTR_EXTERN_FIELD_REF_SIZE;
@@ -2018,15 +2045,16 @@ too_big:
 		/* In dtuple_convert_big_rec(), variable-length columns
 		that are longer than BTR_EXTERN_FIELD_REF_SIZE * 2
 		may be chosen for external storage.  If the column appears
-		in an ordering column of an index, a longer prefix of
-		REC_MAX_INDEX_COL_LEN will be copied to the undo log
-		by trx_undo_page_report_modify() and
+		in an ordering column of an index, a longer prefix determined
+		by dict_max_field_len_store_undo() will be copied to the undo
+		log by trx_undo_page_report_modify() and
 		trx_undo_page_fetch_ext().  It suffices to check the
 		capacity of the undo log whenever new_index includes
 		a column prefix on a column that may be stored externally. */
 
 		if (field->prefix_len /* prefix index */
-		    && !col->ord_part /* not yet ordering column */
+		    && (!col->ord_part /* not yet ordering column */
+			|| field->prefix_len > col->max_prefix)
 		    && !dict_col_get_fixed_size(col, TRUE) /* variable-length */
 		    && dict_col_get_max_size(col)
 		    > BTR_EXTERN_FIELD_REF_SIZE * 2 /* long enough */) {
@@ -2043,11 +2071,17 @@ too_big:
 	}
 
 undo_size_ok:
-	/* Flag the ordering columns */
+	/* Flag the ordering columns and also set column max_prefix */
 
 	for (i = 0; i < n_ord; i++) {
+		const dict_field_t*	field
+			= dict_index_get_nth_field(new_index, i);
 
-		dict_index_get_nth_field(new_index, i)->col->ord_part = 1;
+		field->col->ord_part = 1;
+
+		if (field->prefix_len > field->col->max_prefix) {
+			field->col->max_prefix = field->prefix_len;
+		}
 	}
 
 	/* Add the new index as the last index for the table */
@@ -2271,14 +2305,14 @@ dict_index_add_col(
 	variable-length fields, so that the extern flag can be embedded in
 	the length word. */
 
-	if (field->fixed_len > DICT_MAX_INDEX_COL_LEN) {
+	if (field->fixed_len > DICT_MAX_FIXED_COL_LEN) {
 		field->fixed_len = 0;
 	}
-#if DICT_MAX_INDEX_COL_LEN != 768
+#if DICT_MAX_FIXED_COL_LEN != 768
 	/* The comparison limit above must be constant.  If it were
 	changed, the disk format of some fixed-length columns would
 	change, which would be a disaster. */
-# error "DICT_MAX_INDEX_COL_LEN != 768"
+# error "DICT_MAX_FIXED_COL_LEN != 768"
 #endif
 
 	if (!(col->prtype & DATA_NOT_NULL)) {

=== modified file 'storage/innobase/dict/dict0mem.c'
--- a/storage/innobase/dict/dict0mem.c	2011-04-27 21:49:19 +0000
+++ b/storage/innobase/dict/dict0mem.c	2011-05-31 09:30:59 +0000
@@ -236,6 +236,7 @@ dict_mem_fill_column_struct(
 
 	column->ind = (unsigned int) col_pos;
 	column->ord_part = 0;
+	column->max_prefix = 0;
 	column->mtype = (unsigned int) mtype;
 	column->prtype = (unsigned int) prtype;
 	column->len = (unsigned int) col_len;

=== modified file 'storage/innobase/dict/dict0stats.c'
--- a/storage/innobase/dict/dict0stats.c	2011-04-04 14:19:29 +0000
+++ b/storage/innobase/dict/dict0stats.c	2011-06-01 09:42:10 +0000
@@ -110,10 +110,10 @@ where n=1..n_uniq.
 @} */
 
 /* names of the tables from the persistent statistics storage */
-#define TABLE_STATS_NAME	"innodb/table_stats"
-#define TABLE_STATS_NAME_PRINT	"innodb.table_stats"
-#define INDEX_STATS_NAME	"innodb/index_stats"
-#define INDEX_STATS_NAME_PRINT	"innodb.index_stats"
+#define TABLE_STATS_NAME	"mysql/innodb_table_stats"
+#define TABLE_STATS_NAME_PRINT	"mysql.innodb_table_stats"
+#define INDEX_STATS_NAME	"mysql/innodb_index_stats"
+#define INDEX_STATS_NAME_PRINT	"mysql.innodb_index_stats"
 
 #ifdef UNIV_STATS_DEBUG
 #define DEBUG_PRINTF(fmt, ...)	printf(fmt, ## __VA_ARGS__)
@@ -1674,7 +1674,7 @@ end_free:
 
 /*********************************************************************//**
 Called for the row that is selected by
-SELECT ... FROM innodb.table_stats WHERE table='...'
+SELECT ... FROM mysql.innodb_table_stats WHERE table='...'
 The second argument is a pointer to the table and the fetched stats are
 written to it.
 dict_stats_fetch_table_stats_step() @{
@@ -1703,7 +1703,7 @@ dict_stats_fetch_table_stats_step(
 		void*		data = dfield_get_data(dfield);
 
 		switch (i) {
-		case 0: /* innodb.table_stats.n_rows */
+		case 0: /* mysql.innodb_table_stats.n_rows */
 
 			ut_a(dtype_get_mtype(type) == DATA_INT);
 			ut_a(len == 8);
@@ -1712,7 +1712,7 @@ dict_stats_fetch_table_stats_step(
 
 			break;
 
-		case 1: /* innodb.table_stats.clustered_index_size */
+		case 1: /* mysql.innodb_table_stats.clustered_index_size */
 
 			ut_a(dtype_get_mtype(type) == DATA_INT);
 			ut_a(len == 8);
@@ -1722,7 +1722,7 @@ dict_stats_fetch_table_stats_step(
 
 			break;
 
-		case 2: /* innodb.table_stats.sum_of_other_index_sizes */
+		case 2: /* mysql.innodb_table_stats.sum_of_other_index_sizes */
 
 			ut_a(dtype_get_mtype(type) == DATA_INT);
 			ut_a(len == 8);
@@ -1736,7 +1736,7 @@ dict_stats_fetch_table_stats_step(
 
 			/* someone changed SELECT
 			n_rows,clustered_index_size,sum_of_other_index_sizes
-			to select more columns from table_stats without
+			to select more columns from innodb_table_stats without
 			adjusting here */
 			ut_error;
 		}
@@ -1744,7 +1744,7 @@ dict_stats_fetch_table_stats_step(
 
 	/* if i < 3 this means someone changed the
 	SELECT n_rows,clustered_index_size,sum_of_other_index_sizes
-	to select less columns from table_stats without adjusting here;
+	to select less columns from innodb_table_stats without adjusting here;
 	if i > 3 we would have ut_error'ed earlier */
 	ut_a(i == 3 /*n_rows,clustered_index_size,sum_of_other_index_sizes*/);
 
@@ -1753,19 +1753,28 @@ dict_stats_fetch_table_stats_step(
 }
 /* @} */
 
+/** Aux struct used to pass a table and a boolean to
+dict_stats_fetch_index_stats_step(). */
+typedef struct index_fetch_struct {
+	dict_table_t*	table;	/*!< table whose indexes are to be modified */
+	ibool		stats_were_modified; /*!< will be set to TRUE if at
+				least one index stats were modified */
+} index_fetch_t;
+
 /*********************************************************************//**
 Called for the rows that are selected by
-SELECT ... FROM innodb.index_stats WHERE table='...'
+SELECT ... FROM mysql.innodb_index_stats WHERE table='...'
 The second argument is a pointer to the table and the fetched stats are
 written to its indexes.
-Let a table has N indexes and each index has Ui unique columns, then
-innodb.index_stats will have N*SUM(Ui) rows for for that table. So this
-function will be called N*SUM(Ui) times. In each call it searches for the
-currently fetched index into table->indexes linearly,
-assuming this list is not sorted. Thus, overall, fetching all indexes' stats
-from innodb.index_stats is O(N^2) where N is the number of indexes. This can
-be improved if we sort table->indexes in a temporary area just once and then
-search in that sorted list. Then the complexity will be O(N*log(N)).
+Let a table has N indexes and each index has Ui unique columns for i=1..N,
+then mysql.innodb_index_stats will have SUM(Ui) i=1..N rows for that table.
+So this function will be called SUM(Ui) times where SUM(Ui) is of magnitude
+N*AVG(Ui). In each call it searches for the currently fetched index into
+table->indexes linearly, assuming this list is not sorted. Thus, overall,
+fetching all indexes' stats from mysql.innodb_index_stats is O(N^2) where N
+is the number of indexes.
+This can be improved if we sort table->indexes in a temporary area just once
+and then search in that sorted list. Then the complexity will be O(N*log(N)).
 We assume a table will not have more than 100 indexes, so we go with the
 simpler N^2 algorithm.
 dict_stats_fetch_index_stats_step() @{
@@ -1775,10 +1784,12 @@ void*
 dict_stats_fetch_index_stats_step(
 /*==============================*/
 	void*	node_void,	/*!< in: select node */
-	void*	table_void)	/*!< out: table */
+	void*	arg_void)	/*!< out: table + a flag that tells if we
+				modified anything */
 {
 	sel_node_t*	node = (sel_node_t*) node_void;
-	dict_table_t*	table = (dict_table_t*) table_void;
+	index_fetch_t*	arg = (index_fetch_t*) arg_void;
+	dict_table_t*	table = arg->table;
 	dict_index_t*	index = NULL;
 	que_common_t*	cnode;
 	const char*	stat_name = NULL;
@@ -1799,7 +1810,7 @@ dict_stats_fetch_index_stats_step(
 		void*		data = dfield_get_data(dfield);
 
 		switch (i) {
-		case 0: /* innodb.index_stats.index_name */
+		case 0: /* mysql.innodb_index_stats.index_name */
 
 			ut_a(dtype_get_mtype(type) == DATA_VARMYSQL);
 
@@ -1817,9 +1828,9 @@ dict_stats_fetch_index_stats_step(
 			}
 
 			/* if index is NULL here this means that
-			innodb.index_stats contains more rows than the number
-			of indexes in the table; this is ok, we just return
-			ignoring those extra rows; in other words
+			mysql.innodb_index_stats contains more rows than the
+			number of indexes in the table; this is ok, we just
+			return ignoring those extra rows; in other words
 			dict_stats_fetch_index_stats_step() has been called
 			for a row from index_stats with unknown index_name
 			column */
@@ -1830,7 +1841,7 @@ dict_stats_fetch_index_stats_step(
 
 			break;
 
-		case 1: /* innodb.index_stats.stat_name */
+		case 1: /* mysql.innodb_index_stats.stat_name */
 
 			ut_a(dtype_get_mtype(type) == DATA_VARMYSQL);
 
@@ -1841,7 +1852,7 @@ dict_stats_fetch_index_stats_step(
 
 			break;
 
-		case 2: /* innodb.index_stats.stat_value */
+		case 2: /* mysql.innodb_index_stats.stat_value */
 
 			ut_a(dtype_get_mtype(type) == DATA_INT);
 			ut_a(len == 8);
@@ -1854,7 +1865,7 @@ dict_stats_fetch_index_stats_step(
 
 			break;
 
-		case 3: /* innodb.index_stats.sample_size */
+		case 3: /* mysql.innodb_index_stats.sample_size */
 
 			ut_a(dtype_get_mtype(type) == DATA_INT);
 			ut_a(len == 8 || len == UNIV_SQL_NULL);
@@ -1877,7 +1888,7 @@ dict_stats_fetch_index_stats_step(
 
 			/* someone changed
 			SELECT index_name,stat_name,stat_value,sample_size
-			to select more columns from index_stats without
+			to select more columns from innodb_index_stats without
 			adjusting here */
 			ut_error;
 		}
@@ -1885,7 +1896,7 @@ dict_stats_fetch_index_stats_step(
 
 	/* if i < 4 this means someone changed the
 	SELECT index_name,stat_name,stat_value,sample_size
-	to select less columns from index_stats without adjusting here;
+	to select less columns from innodb_index_stats without adjusting here;
 	if i > 4 we would have ut_error'ed earlier */
 	ut_a(i == 4 /* index_name,stat_name,stat_value,sample_size */);
 
@@ -1899,9 +1910,11 @@ dict_stats_fetch_index_stats_step(
 
 	if (strncasecmp("size", stat_name, stat_name_len) == 0) {
 		index->stat_index_size = (ulint) stat_value;
+		arg->stats_were_modified = TRUE;
 	} else if (strncasecmp("n_leaf_pages", stat_name, stat_name_len)
 		   == 0) {
 		index->stat_n_leaf_pages = (ulint) stat_value;
+		arg->stats_were_modified = TRUE;
 	} else if (strncasecmp(PFX, stat_name,
 			       ut_min(strlen(PFX), stat_name_len)) == 0) {
 
@@ -1920,12 +1933,13 @@ dict_stats_fetch_index_stats_step(
 			ut_print_timestamp(stderr);
 			fprintf(stderr,
 				" InnoDB: Ignoring strange row from "
-				"innodb.index_stats WHERE "
+				"%s WHERE "
 				"database_name = '%.*s' AND "
 				"table_name = '%s' AND "
 				"index_name = '%s' AND "
 				"stat_name = '%.*s'; because stat_name "
 				"is malformed\n",
+				INDEX_STATS_NAME_PRINT,
 				(int) dict_get_db_name_len(table->name),
 				table->name,
 				dict_remove_db_name(table->name),
@@ -1945,13 +1959,14 @@ dict_stats_fetch_index_stats_step(
 			ut_print_timestamp(stderr);
 			fprintf(stderr,
 				" InnoDB: Ignoring strange row from "
-				"innodb.index_stats WHERE "
+				"%s WHERE "
 				"database_name = '%.*s' AND "
 				"table_name = '%s' AND "
 				"index_name = '%s' AND "
 				"stat_name = '%.*s'; because stat_name is "
 				"out of range, the index has %lu unique "
 				"columns\n",
+				INDEX_STATS_NAME_PRINT,
 				(int) dict_get_db_name_len(table->name),
 				table->name,
 				dict_remove_db_name(table->name),
@@ -1972,6 +1987,8 @@ dict_stats_fetch_index_stats_step(
 			table manually and SET sample_size = NULL */
 			index->stat_n_sample_sizes[n_pfx] = 0;
 		}
+
+		arg->stats_were_modified = TRUE;
 	} else {
 		/* silently ignore rows with unknown stat_name, the
 		user may have developed her own stats */
@@ -1994,6 +2011,7 @@ dict_stats_fetch_from_ps(
 	ibool		caller_has_dict_sys_mutex)/*!< in: TRUE if the caller
 					owns dict_sys->mutex */
 {
+	index_fetch_t	index_fetch_arg;
 	trx_t*		trx;
 	pars_info_t*	pinfo;
 	ulint		ret;
@@ -2024,10 +2042,12 @@ dict_stats_fetch_from_ps(
 			       dict_stats_fetch_table_stats_step,
 			       table);
 
+	index_fetch_arg.table = table;
+	index_fetch_arg.stats_were_modified = FALSE;
 	pars_info_add_function(pinfo,
 			       "fetch_index_stats_step",
 			       dict_stats_fetch_index_stats_step,
-			       table);
+			       &index_fetch_arg);
 
 	ret = que_eval_sql(pinfo,
 			   "PROCEDURE FETCH_STATS () IS\n"
@@ -2087,19 +2107,23 @@ dict_stats_fetch_from_ps(
 
 	/* pinfo is freed by que_eval_sql() */
 
-	/* XXX If innodb.index_stats contained less rows than the number
+	/* XXX If mysql.innodb_index_stats contained less rows than the number
 	of indexes in the table, then some of the indexes of the table
 	were left uninitialized. Currently this is ignored and those
 	indexes are left with uninitialized stats until ANALYZE TABLE is
 	run. This condition happens when the user creates a new index
 	on a table. We could return DB_STATS_DO_NOT_EXIST from here,
-	forcing the usage of transient stats until innodb.index_stats
+	forcing the usage of transient stats until mysql.innodb_index_stats
 	is complete. */
 
 	trx_commit_for_mysql(trx);
 
 	trx_free_for_background(trx);
 
+	if (!index_fetch_arg.stats_were_modified) {
+		return(DB_STATS_DO_NOT_EXIST);
+	}
+
 	return(ret);
 }
 /* @} */
@@ -2497,7 +2521,7 @@ dict_stats_delete_table_stats(
 		return(DB_SUCCESS);
 	}
 
-	/* skip table_stats and index_stats themselves */
+	/* skip innodb_table_stats and innodb_index_stats themselves */
 	if (strcmp(table_name, TABLE_STATS_NAME) == 0
 	    || strcmp(table_name, INDEX_STATS_NAME) == 0) {
 
@@ -2836,10 +2860,12 @@ test_dict_stats_save()
 	ut_a(ret == DB_SUCCESS);
 
 	printf("\nOK: stats saved successfully, now go ahead and read "
-	       "what's inside innodb.table_stats and innodb.index_stats:\n\n");
+	       "what's inside %s and %s:\n\n",
+	       TABLE_STATS_NAME_PRINT,
+	       INDEX_STATS_NAME_PRINT);
 
 	printf("SELECT COUNT(*) = 1 AS table_stats_saved_successfully\n"
-	       "FROM innodb.table_stats\n"
+	       "FROM %s\n"
 	       "WHERE\n"
 	       "database_name = '%s' AND\n"
 	       "table_name = '%s' AND\n"
@@ -2847,6 +2873,7 @@ test_dict_stats_save()
 	       "clustered_index_size = %d AND\n"
 	       "sum_of_other_index_sizes = %d;\n"
 	       "\n",
+	       TABLE_STATS_NAME_PRINT,
 	       TEST_DATABASE_NAME,
 	       TEST_TABLE_NAME,
 	       TEST_N_ROWS,
@@ -2854,7 +2881,7 @@ test_dict_stats_save()
 	       TEST_SUM_OF_OTHER_INDEX_SIZES);
 
 	printf("SELECT COUNT(*) = 3 AS tidx1_stats_saved_successfully\n"
-	       "FROM innodb.index_stats\n"
+	       "FROM %s\n"
 	       "WHERE\n"
 	       "database_name = '%s' AND\n"
 	       "table_name = '%s' AND\n"
@@ -2868,6 +2895,7 @@ test_dict_stats_save()
 	       "  sample_size = '%d' AND stat_description = '%s')\n"
 	       ");\n"
 	       "\n",
+	       INDEX_STATS_NAME_PRINT,
 	       TEST_DATABASE_NAME,
 	       TEST_TABLE_NAME,
 	       TEST_IDX1_NAME,
@@ -2878,7 +2906,7 @@ test_dict_stats_save()
 	       TEST_IDX1_COL1_NAME);
 
 	printf("SELECT COUNT(*) = 6 AS tidx2_stats_saved_successfully\n"
-	       "FROM innodb.index_stats\n"
+	       "FROM %s\n"
 	       "WHERE\n"
 	       "database_name = '%s' AND\n"
 	       "table_name = '%s' AND\n"
@@ -2898,6 +2926,7 @@ test_dict_stats_save()
 	       "  sample_size = '%d' AND stat_description = '%s,%s,%s,%s')\n"
 	       ");\n"
 	       "\n",
+	       INDEX_STATS_NAME_PRINT,
 	       TEST_DATABASE_NAME,
 	       TEST_TABLE_NAME,
 	       TEST_IDX2_NAME,

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2011-05-26 15:20:09 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2011-06-01 09:11:28 +0000
@@ -170,6 +170,7 @@ static my_bool	innobase_locks_unsafe_for
 static my_bool	innobase_rollback_on_timeout		= FALSE;
 static my_bool	innobase_create_status_file		= FALSE;
 static my_bool	innobase_stats_on_metadata		= TRUE;
+static my_bool	innobase_large_prefix			= FALSE;
 
 
 static char*	internal_innobase_data_file_path	= NULL;
@@ -1064,7 +1065,7 @@ int
 convert_error_code_to_mysql(
 /*========================*/
 	int	error,	/*!< in: InnoDB error code */
-	ulint	flags,	/*!< in: InnoDB table flags, or 0 */
+	ulint	flags,  /*!< in: InnoDB table flags, or 0 */
 	THD*	thd)	/*!< in: user thread handle or NULL */
 {
 	switch (error) {
@@ -1168,6 +1169,11 @@ convert_error_code_to_mysql(
 						      & DICT_TF_COMPACT) / 2);
 		return(HA_ERR_TO_BIG_ROW);
 
+	case DB_TOO_BIG_INDEX_COL:
+		my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
+			 DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
+		return(HA_ERR_INDEX_COL_TOO_LONG);
+
 	case DB_NO_SAVEPOINT:
 		return(HA_ERR_NO_SAVEPOINT);
 
@@ -2842,8 +2848,10 @@ innobase_alter_table_flags(
 	uint	flags)
 {
 	return(HA_INPLACE_ADD_INDEX_NO_READ_WRITE
+		| HA_INPLACE_ADD_INDEX_NO_WRITE
 		| HA_INPLACE_DROP_INDEX_NO_READ_WRITE
 		| HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE
+		| HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE
 		| HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE
 		| HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE);
 }
@@ -4182,7 +4190,11 @@ uint
 ha_innobase::max_supported_key_part_length() const
 /*==============================================*/
 {
-	return(DICT_MAX_INDEX_COL_LEN - 1);
+	/* A table format specific index column length check will be performed
+	at ha_innobase::add_index() and row_create_index_for_mysql() */
+	return(innobase_large_prefix
+		? REC_VERSION_56_MAX_INDEX_COL_LEN
+		: REC_ANTELOPE_MAX_INDEX_COL_LEN - 1);
 }
 
 /******************************************************************//**
@@ -7448,8 +7460,8 @@ ha_innobase::create(
 
 		if (i != (uint) primary_key_no) {
 
-			if ((error = create_index(trx, form, flags, norm_name,
-						  i))) {
+			if ((error = create_index(trx, form, flags,
+						  norm_name, i))) {
 				goto cleanup;
 			}
 		}
@@ -12154,6 +12166,11 @@ static MYSQL_SYSVAR_STR(flush_method, in
   PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
   "With which method to flush data.", NULL, NULL, NULL);
 
+static MYSQL_SYSVAR_BOOL(large_prefix, innobase_large_prefix,
+  PLUGIN_VAR_NOCMDARG,
+  "Support large index prefix length of REC_VERSION_56_MAX_INDEX_COL_LEN (3072) bytes.",
+  NULL, NULL, FALSE);
+
 static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
   PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
   "Force InnoDB to not use next-key locking, to use only row-level locking.",
@@ -12465,6 +12482,7 @@ static struct st_mysql_sys_var* innobase
   MYSQL_SYSVAR(flush_log_at_trx_commit),
   MYSQL_SYSVAR(flush_method),
   MYSQL_SYSVAR(force_recovery),
+  MYSQL_SYSVAR(large_prefix),
   MYSQL_SYSVAR(locks_unsafe_for_binlog),
   MYSQL_SYSVAR(lock_wait_timeout),
 #ifdef UNIV_LOG_ARCHIVE

=== modified file 'storage/innobase/handler/ha_innodb.h'
--- a/storage/innobase/handler/ha_innodb.h	2011-04-11 14:57:47 +0000
+++ b/storage/innobase/handler/ha_innodb.h	2011-06-01 09:11:28 +0000
@@ -213,7 +213,9 @@ class ha_innobase: public handler
 	bool primary_key_is_clustered();
 	int cmp_ref(const uchar *ref1, const uchar *ref2);
 	/** Fast index creation (smart ALTER TABLE) @see handler0alter.cc @{ */
-	int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys);
+	int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
+		      handler_add_index **add);
+	int final_add_index(handler_add_index *add, bool commit);
 	int prepare_drop_index(TABLE *table_arg, uint *key_num,
 			       uint num_of_keys);
 	int final_drop_index(TABLE *table_arg);

=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc	2011-04-27 21:49:19 +0000
+++ b/storage/innobase/handler/handler0alter.cc	2011-06-01 09:11:28 +0000
@@ -541,7 +541,7 @@ innobase_create_key_def(
 	if (!new_primary && (key_info->flags & HA_NOSAME)
 	    && (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
 	    && row_table_got_default_clust_index(table)) {
-		uint    key_part = key_info->key_parts;
+		uint	key_part = key_info->key_parts;
 
 		new_primary = TRUE;
 
@@ -597,6 +597,27 @@ innobase_create_key_def(
 }
 
 /*******************************************************************//**
+Check each index column size, make sure they do not exceed the max limit
+@return	HA_ERR_INDEX_COL_TOO_LONG if index column size exceeds limit */
+static
+int
+innobase_check_column_length(
+/*=========================*/
+	const dict_table_t*table,	/*!< in: table definition */
+	const KEY*	key_info)	/*!< in: Indexes to be created */
+{
+	ulint	max_col_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table);
+
+	for (ulint key_part = 0; key_part < key_info->key_parts; key_part++) {
+		if (key_info->key_part[key_part].length > max_col_len) {
+			my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0), max_col_len);
+			return(HA_ERR_INDEX_COL_TOO_LONG);
+		}
+	}
+	return(0);
+}
+
+/*******************************************************************//**
 Create a temporary tablename using query id, thread id, and id
 @return	temporary tablename */
 static
@@ -621,6 +642,18 @@ innobase_create_temporary_tablename(
 	return(name);
 }
 
+class ha_innobase_add_index : public handler_add_index
+{
+public:
+	/** table where the indexes are being created */
+	dict_table_t* indexed_table;
+	ha_innobase_add_index(TABLE* table, KEY* key_info, uint num_of_keys,
+			      dict_table_t* indexed_table_arg) :
+		handler_add_index(table, key_info, num_of_keys),
+		indexed_table (indexed_table_arg) {}
+	~ha_innobase_add_index() {}
+};
+
 /*******************************************************************//**
 Clean up on ha_innobase::add_index error. */
 static
@@ -673,12 +706,15 @@ UNIV_INTERN
 int
 ha_innobase::add_index(
 /*===================*/
-	TABLE*	table,		/*!< in: Table where indexes are created */
-	KEY*	key_info,	/*!< in: Indexes to be created */
-	uint	num_of_keys)	/*!< in: Number of indexes to be created */
+	TABLE*			table,		/*!< in: Table where indexes
+						are created */
+	KEY*			key_info,	/*!< in: Indexes
+						to be created */
+	uint			num_of_keys,	/*!< in: Number of indexes
+						to be created */
+	handler_add_index**	add)		/*!< out: context */
 {
 	dict_index_t**	index;		/*!< Index to be created */
-	dict_table_t*	innodb_table;	/*!< InnoDB table in dictionary */
 	dict_table_t*	indexed_table;	/*!< Table where indexes are created */
 	merge_index_def_t* index_defs;	/*!< Index definitions */
 	mem_heap_t*     heap;		/*!< Heap for index definitions */
@@ -694,6 +730,8 @@ ha_innobase::add_index(
 	ut_a(key_info);
 	ut_a(num_of_keys);
 
+	*add = NULL;
+
 	if (srv_created_new_raw || srv_force_recovery) {
 		DBUG_RETURN(HA_ERR_WRONG_COMMAND);
 	}
@@ -711,20 +749,32 @@ ha_innobase::add_index(
 
 	indexed_table = dict_table_open_on_name(prebuilt->table->name, FALSE);
 
-	innodb_table = indexed_table;
-
-	if (UNIV_UNLIKELY(!innodb_table)) {
+	if (UNIV_UNLIKELY(!indexed_table)) {
 		DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
 	}
 
+	ut_a(indexed_table == prebuilt->table);
+
 	/* Check that index keys are sensible */
-	error = innobase_check_index_keys(key_info, num_of_keys, innodb_table);
+	error = innobase_check_index_keys(key_info, num_of_keys, prebuilt->table);
 
 	if (UNIV_UNLIKELY(error)) {
-		dict_table_close(innodb_table, FALSE);
+		dict_table_close(prebuilt->table, FALSE);
 		DBUG_RETURN(error);
 	}
 
+	/* Check each index's column length to make sure they do not
+	exceed limit */
+	for (ulint i = 0; i < num_of_keys; i++) {
+		error = innobase_check_column_length(prebuilt->table,
+						     &key_info[i]);
+
+		if (error) {
+			dict_table_close(prebuilt->table, FALSE);
+			DBUG_RETURN(error);
+		}
+	}
+
 	heap = mem_heap_create(1024);
 	trx_start_if_not_started(prebuilt->trx);
 
@@ -741,8 +791,8 @@ ha_innobase::add_index(
 
 	row_mysql_lock_data_dictionary(trx);
 
-	if (innodb_table->can_be_evicted) {
-		dict_table_move_from_lru_to_non_lru(innodb_table);
+	if (prebuilt->table->can_be_evicted) {
+		dict_table_move_from_lru_to_non_lru(prebuilt->table);
 	}
 
 	row_mysql_unlock_data_dictionary(trx);
@@ -754,7 +804,7 @@ ha_innobase::add_index(
 	num_of_idx = num_of_keys;
 
 	index_defs = innobase_create_key_def(
-		trx, innodb_table, heap, key_info, num_of_idx);
+		trx, prebuilt->table, heap, key_info, num_of_idx);
 
 	new_primary = DICT_CLUSTERED & index_defs[0].ind_type;
 
@@ -768,7 +818,7 @@ ha_innobase::add_index(
 	trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
 
 	/* Acquire a lock on the table before creating any indexes. */
-	error = row_merge_lock_table(prebuilt->trx, innodb_table,
+	error = row_merge_lock_table(prebuilt->trx, prebuilt->table,
 				     new_primary ? LOCK_X : LOCK_S);
 
 	if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
@@ -782,7 +832,7 @@ ha_innobase::add_index(
 	row_mysql_lock_data_dictionary(trx);
 	dict_locked = TRUE;
 
-	ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
+	ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
 
 	/* If a new primary key is defined for the table we need
 	to drop the original table and rebuild all indexes. */
@@ -791,15 +841,15 @@ ha_innobase::add_index(
 		/* This transaction should be the only one
 		operating on the table. The table get above
 		would have incremented the ref count to 2. */
-		ut_a(innodb_table->n_ref_count == 2);
+		ut_a(prebuilt->table->n_ref_count == 2);
 
 		char*	new_table_name = innobase_create_temporary_tablename(
-			heap, '1', innodb_table->name);
+			heap, '1', prebuilt->table->name);
 
 		/* Clone the table. */
 		trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
 		indexed_table = row_merge_create_temporary_table(
-			new_table_name, index_defs, innodb_table, trx);
+			new_table_name, index_defs, prebuilt->table, trx);
 
 		if (!indexed_table) {
 
@@ -813,17 +863,18 @@ ha_innobase::add_index(
 				break;
 			default:
 				error = convert_error_code_to_mysql(
-					trx->error_state, innodb_table->flags,
+					trx->error_state,
+					prebuilt->table->flags,
 					user_thd);
 			}
 
-			ut_d(dict_table_check_for_dup_indexes(innodb_table,
+			ut_d(dict_table_check_for_dup_indexes(prebuilt->table,
 							      FALSE));
 			row_mysql_unlock_data_dictionary(trx);
 			mem_heap_free(heap);
 
 			innobase_add_index_cleanup(
-				prebuilt, trx, innodb_table);
+				prebuilt, trx, prebuilt->table);
 
 			DBUG_RETURN(error);
 		}
@@ -833,17 +884,15 @@ ha_innobase::add_index(
 
 	/* Create the indexes in SYS_INDEXES and load into dictionary. */
 
-	for (ulint i = 0; i < num_of_idx; i++) {
+	for (num_created = 0; num_created < num_of_idx; num_created++) {
 
-		index[i] = row_merge_create_index(trx, indexed_table,
-						  &index_defs[i]);
+		index[num_created] = row_merge_create_index(
+			trx, indexed_table, &index_defs[num_created]);
 
-		if (!index[i]) {
+		if (!index[num_created]) {
 			error = trx->error_state;
 			goto error_handling;
 		}
-
-		num_created++;
 	}
 
 	ut_ad(error == DB_SUCCESS);
@@ -864,7 +913,7 @@ ha_innobase::add_index(
 	if (UNIV_UNLIKELY(new_primary)) {
 		/* A primary key is to be built.  Acquire an exclusive
 		table lock also on the table that is being created. */
-		ut_ad(indexed_table != innodb_table);
+		ut_ad(indexed_table != prebuilt->table);
 
 		error = row_merge_lock_table(prebuilt->trx, indexed_table,
 					     LOCK_X);
@@ -878,7 +927,7 @@ ha_innobase::add_index(
 	/* Read the clustered index of the table and build indexes
 	based on this information using temporary files and merge sort. */
 	error = row_merge_build_indexes(prebuilt->trx,
-					innodb_table, indexed_table,
+					prebuilt->table, indexed_table,
 					index, num_of_idx, table);
 
 error_handling:
@@ -887,74 +936,17 @@ error_handling:
 	dictionary which were defined. */
 
 	switch (error) {
-		const char*	old_name;
-		char*		tmp_name;
 	case DB_SUCCESS:
 		ut_a(!dict_locked);
-		row_mysql_lock_data_dictionary(trx);
-		dict_locked = TRUE;
 
+		ut_d(mutex_enter(&dict_sys->mutex));
 		ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
+		ut_d(mutex_exit(&dict_sys->mutex));
+		*add = new ha_innobase_add_index(table, key_info, num_of_keys,
+                                                 indexed_table);
 
-		if (!new_primary) {
-			error = row_merge_rename_indexes(trx, indexed_table);
-
-			if (error != DB_SUCCESS) {
-				row_merge_drop_indexes(trx, indexed_table,
-						       index, num_created);
-			}
-
-			dict_table_close(innodb_table, dict_locked);
-
-			goto convert_error;
-		}
-
-		/* If a new primary key was defined for the table and
-		there was no error at this point, we can now rename
-		the old table as a temporary table, rename the new
-		temporary table as the old table and drop the old table. */
-		old_name = innodb_table->name;
-		tmp_name = innobase_create_temporary_tablename(heap, '2',
-							       old_name);
-
-		error = row_merge_rename_tables(innodb_table, indexed_table,
-						tmp_name, trx);
-
-		dict_table_close(innodb_table, dict_locked);
-		ut_a(innodb_table->n_ref_count == 1);
-
-		if (error != DB_SUCCESS) {
-
-			ut_a(indexed_table->n_ref_count == 0);
-
-			row_merge_drop_table(trx, indexed_table);
-
-			switch (error) {
-			case DB_TABLESPACE_ALREADY_EXISTS:
-			case DB_DUPLICATE_KEY:
-				innobase_convert_tablename(tmp_name);
-				my_error(HA_ERR_TABLE_EXIST, MYF(0), tmp_name);
-				error = HA_ERR_TABLE_EXIST;
-				break;
-			default:
-				goto convert_error;
-			}
-			break;
-		}
-
-		trx_commit_for_mysql(prebuilt->trx);
-
-		row_prebuilt_free(prebuilt, TRUE);
-
-		ut_a(innodb_table->n_ref_count == 0);
-
-		error = row_merge_drop_table(trx, innodb_table);
-
-		prebuilt = row_create_prebuilt(indexed_table);
-
-		innodb_table = indexed_table;
-
-		goto convert_error;
+		dict_table_close(prebuilt->table, dict_locked);
+		break;
 
 	case DB_TOO_BIG_RECORD:
 		my_error(HA_ERR_TO_BIG_ROW, MYF(0));
@@ -967,12 +959,12 @@ error:
 		prebuilt->trx->error_info = NULL;
 		/* fall through */
 	default:
-		dict_table_close(innodb_table, dict_locked);
+		dict_table_close(prebuilt->table, dict_locked);
 
 		trx->error_state = DB_SUCCESS;
 
 		if (new_primary) {
-			if (indexed_table != innodb_table) {
+			if (indexed_table != prebuilt->table) {
 				dict_table_close(indexed_table, dict_locked);
 				row_merge_drop_table(trx, indexed_table);
 			}
@@ -985,40 +977,166 @@ error:
 			row_merge_drop_indexes(trx, indexed_table,
 					       index, num_created);
 		}
-
-convert_error:
-		if (error == DB_SUCCESS) {
-			/* Build index is successful. We will need to
-			rebuild index translation table.  Reset the
-			index entry count in the translation table
-			to zero, so that translation table will be rebuilt */
-			share->idx_trans_tbl.index_count = 0;
-		}
-
-		error = convert_error_code_to_mysql(error,
-						    innodb_table->flags,
-						    user_thd);
 	}
 
-	ut_a(!new_primary || innodb_table->n_ref_count == 1);
+	ut_a(!new_primary || prebuilt->table->n_ref_count == 1);
 
-	mem_heap_free(heap);
 	trx_commit_for_mysql(trx);
 	if (prebuilt->trx) {
 		trx_commit_for_mysql(prebuilt->trx);
 	}
 
 	if (dict_locked) {
-		ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
 		row_mysql_unlock_data_dictionary(trx);
 	}
 
 	trx_free_for_mysql(trx);
+	mem_heap_free(heap);
+
+	/* There might be work for utility threads.*/
+	srv_active_wake_master_thread();
+
+	DBUG_RETURN(convert_error_code_to_mysql(error, prebuilt->table->flags,
+						user_thd));
+}
+
+/*******************************************************************//**
+Finalize or undo add_index().
+@return	0 or error number */
+UNIV_INTERN
+int
+ha_innobase::final_add_index(
+/*=========================*/
+	handler_add_index*	add_arg,/*!< in: context from add_index() */
+	bool			commit)	/*!< in: true=commit, false=rollback */
+{
+	ha_innobase_add_index*	add;
+	trx_t*			trx;
+	int			err	= 0;
+
+	DBUG_ENTER("ha_innobase::final_add_index");
+
+	ut_ad(add_arg);
+	add = static_cast<class ha_innobase_add_index*>(add_arg);
+
+	/* Create a background transaction for the operations on
+	the data dictionary tables. */
+	trx = innobase_trx_allocate(user_thd);
+	trx_start_if_not_started(trx);
+
+	/* Flag this transaction as a dictionary operation, so that
+	the data dictionary will be locked in crash recovery. */
+	trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
+
+	/* Latch the InnoDB data dictionary exclusively so that no deadlocks
+	or lock waits can happen in it during an index create operation. */
+	row_mysql_lock_data_dictionary(trx);
+
+	if (add->indexed_table != prebuilt->table) {
+		ulint	error;
+
+		/* We copied the table (new_primary). */
+		if (commit) {
+			mem_heap_t*	heap;
+			char*		tmp_name;
+
+			heap = mem_heap_create(1024);
+
+			/* A new primary key was defined for the table
+			and there was no error at this point. We can
+			now rename the old table as a temporary table,
+			rename the new temporary table as the old
+			table and drop the old table. */
+			tmp_name = innobase_create_temporary_tablename(
+				heap, '2', prebuilt->table->name);
+
+			error = row_merge_rename_tables(
+				prebuilt->table, add->indexed_table,
+				tmp_name, trx);
+
+			ut_a(prebuilt->table->n_ref_count == 1);
+
+			switch (error) {
+			case DB_TABLESPACE_ALREADY_EXISTS:
+			case DB_DUPLICATE_KEY:
+				ut_a(add->indexed_table->n_ref_count == 0);
+				innobase_convert_tablename(tmp_name);
+				my_error(HA_ERR_TABLE_EXIST, MYF(0), tmp_name);
+				err = HA_ERR_TABLE_EXIST;
+				break;
+			default:
+				err = convert_error_code_to_mysql(
+					error, prebuilt->table->flags,
+					user_thd);
+				break;
+			}
+
+			mem_heap_free(heap);
+		}
+
+		if (!commit || err) {
+			dict_table_close(add->indexed_table, TRUE);
+			error = row_merge_drop_table(trx, add->indexed_table);
+			trx_commit_for_mysql(prebuilt->trx);
+		} else {
+			dict_table_t*	old_table = prebuilt->table;
+			trx_commit_for_mysql(prebuilt->trx);
+			row_prebuilt_free(prebuilt, TRUE);
+			error = row_merge_drop_table(trx, old_table);
+			prebuilt = row_create_prebuilt(add->indexed_table);
+		}
+
+		err = convert_error_code_to_mysql(
+			error, prebuilt->table->flags, user_thd);
+	} else {
+		/* We created secondary indexes (!new_primary). */
+
+		if (commit) {
+			err = convert_error_code_to_mysql(
+				row_merge_rename_indexes(trx, prebuilt->table),
+				prebuilt->table->flags, user_thd);
+		}
+
+		if (!commit || err) {
+			dict_index_t*	index;
+			dict_index_t*	next_index;
+
+			for (index = dict_table_get_first_index(
+				     prebuilt->table);
+			     index; index = next_index) {
+
+				next_index = dict_table_get_next_index(index);
+
+				if (*index->name == TEMP_INDEX_PREFIX) {
+					row_merge_drop_index(
+						index, prebuilt->table, trx);
+				}
+			}
+		}
+	}
+
+	/* If index is successfully built, we will need to rebuild index
+	translation table. Set valid index entry count in the translation
+	table to zero. */
+	if (err == 0 && commit) {
+		share->idx_trans_tbl.index_count = 0;
+	}
+
+	trx_commit_for_mysql(trx);
+	if (prebuilt->trx) {
+		trx_commit_for_mysql(prebuilt->trx);
+	}
+
+	ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
+	row_mysql_unlock_data_dictionary(trx);
+
+	trx_free_for_mysql(trx);
 
 	/* There might be work for utility threads.*/
 	srv_active_wake_master_thread();
 
-	DBUG_RETURN(error);
+	delete add;
+	DBUG_RETURN(err);
 }
 
 /*******************************************************************//**

=== modified file 'storage/innobase/include/db0err.h'
--- a/storage/innobase/include/db0err.h	2010-11-15 07:25:12 +0000
+++ b/storage/innobase/include/db0err.h	2011-05-31 09:30:59 +0000
@@ -110,6 +110,8 @@ enum db_err {
 	DB_PARENT_NO_INDEX,		/* the parent table does not
 					have an index that contains the
 					foreign keys as its prefix columns */
+	DB_TOO_BIG_INDEX_COL,		/* index column size exceeds maximum
+					limit */
 
 	/* The following are partial failure codes */
 	DB_FAIL = 1000,

=== modified file 'storage/innobase/include/dict0dict.h'
--- a/storage/innobase/include/dict0dict.h	2011-04-27 21:49:19 +0000
+++ b/storage/innobase/include/dict0dict.h	2011-05-31 09:30:59 +0000
@@ -137,6 +137,19 @@ dict_col_copy_type(
 /*===============*/
 	const dict_col_t*	col,	/*!< in: column */
 	dtype_t*		type);	/*!< out: data type */
+/**********************************************************************//**
+Determine bytes of column prefix to be stored in the undo log. Please
+note if the table format is UNIV_FORMAT_A (< UNIV_FORMAT_B), no prefix
+needs to be stored in the undo log.
+@return bytes of column prefix to be stored in the undo log */
+UNIV_INLINE
+ulint
+dict_max_field_len_store_undo(
+/*==========================*/
+	dict_table_t*		table,	/*!< in: table */
+	const dict_col_t*	col);	/*!< in: column which index prefix
+					is based on */
+
 #endif /* !UNIV_HOTBACKUP */
 #ifdef UNIV_DEBUG
 /*********************************************************************//**

=== modified file 'storage/innobase/include/dict0dict.ic'
--- a/storage/innobase/include/dict0dict.ic	2011-04-27 21:49:19 +0000
+++ b/storage/innobase/include/dict0dict.ic	2011-05-31 09:30:59 +0000
@@ -820,4 +820,29 @@ dict_index_get_space_reserve(void)
 	return(UNIV_PAGE_SIZE / 16);
 }
 
+/**********************************************************************//**
+Determine bytes of column prefix to be stored in the undo log. Please
+note if the table format is UNIV_FORMAT_A (< UNIV_FORMAT_B), no prefix
+needs to be stored in the undo log.
+@return bytes of column prefix to be stored in the undo log */
+UNIV_INLINE
+ulint
+dict_max_field_len_store_undo(
+/*==========================*/
+	dict_table_t*		table,	/*!< in: table */
+	const dict_col_t*	col)	/*!< in: column which index prefix
+					is based on */
+{
+	ulint	prefix_len = 0;
+
+	if (dict_table_get_format(table) >= UNIV_FORMAT_B)
+	{
+		prefix_len = col->max_prefix
+			? col->max_prefix
+			: DICT_MAX_FIELD_LEN_BY_FORMAT(table);
+	}
+
+	return(prefix_len);
+}
+
 #endif /* !UNIV_HOTBACKUP */

=== modified file 'storage/innobase/include/dict0mem.h'
--- a/storage/innobase/include/dict0mem.h	2011-04-27 21:49:19 +0000
+++ b/storage/innobase/include/dict0mem.h	2011-05-31 09:30:59 +0000
@@ -294,32 +294,58 @@ struct dict_col_struct{
 	unsigned	ord_part:1;	/*!< nonzero if this column
 					appears in the ordering fields
 					of an index */
+	unsigned	max_prefix:12;	/*!< maximum index prefix length on
+					this column. Our current max limit is
+					3072 for Barracuda table */
 };
 
-/** @brief DICT_MAX_INDEX_COL_LEN is measured in bytes and is the maximum
-indexed column length (or indexed prefix length).
+/** @brief DICT_ANTELOPE_MAX_INDEX_COL_LEN is measured in bytes and
+is the maximum indexed column length (or indexed prefix length) in
+ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT. Also, in any format,
+any fixed-length field that is longer than this will be encoded as
+a variable-length field.
 
 It is set to 3*256, so that one can create a column prefix index on
 256 characters of a TEXT or VARCHAR column also in the UTF-8
 charset. In that charset, a character may take at most 3 bytes.  This
 constant MUST NOT BE CHANGED, or the compatibility of InnoDB data
 files would be at risk! */
-#define DICT_MAX_INDEX_COL_LEN		REC_MAX_INDEX_COL_LEN
+#define DICT_ANTELOPE_MAX_INDEX_COL_LEN	REC_ANTELOPE_MAX_INDEX_COL_LEN
+
+/** Find out maximum indexed column length by its table format.
+For ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT, the maximum
+field length is REC_ANTELOPE_MAX_INDEX_COL_LEN - 1 (767). For new
+barracuda format, the length could be REC_VERSION_56_MAX_INDEX_COL_LEN
+(3072) bytes */
+#define DICT_MAX_FIELD_LEN_BY_FORMAT(table)				\
+		((dict_table_get_format(table) < UNIV_FORMAT_B)		\
+			? (REC_ANTELOPE_MAX_INDEX_COL_LEN - 1)		\
+			: REC_VERSION_56_MAX_INDEX_COL_LEN)
+
+#define DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags)			\
+		((((flags & DICT_TF_FORMAT_MASK) >> DICT_TF_FORMAT_SHIFT)\
+		    < UNIV_FORMAT_B)					\
+			? (REC_ANTELOPE_MAX_INDEX_COL_LEN - 1)		\
+			: REC_VERSION_56_MAX_INDEX_COL_LEN)
+
+/** Defines the maximum fixed length column size */
+#define DICT_MAX_FIXED_COL_LEN		DICT_ANTELOPE_MAX_INDEX_COL_LEN
 
 /** Data structure for a field in an index */
 struct dict_field_struct{
 	dict_col_t*	col;		/*!< pointer to the table column */
 	const char*	name;		/*!< name of the column */
-	unsigned	prefix_len:10;	/*!< 0 or the length of the column
+	unsigned	prefix_len:12;	/*!< 0 or the length of the column
 					prefix in bytes in a MySQL index of
 					type, e.g., INDEX (textcol(25));
 					must be smaller than
-					DICT_MAX_INDEX_COL_LEN; NOTE that
-					in the UTF-8 charset, MySQL sets this
-					to 3 * the prefix len in UTF-8 chars */
+					DICT_MAX_FIELD_LEN_BY_FORMAT;
+					NOTE that in the UTF-8 charset, MySQL
+					sets this to (mbmaxlen * the prefix len)
+					in UTF-8 chars */
 	unsigned	fixed_len:10;	/*!< 0 or the fixed length of the
 					column if smaller than
-					DICT_MAX_INDEX_COL_LEN */
+					DICT_ANTELOPE_MAX_INDEX_COL_LEN */
 };
 
 /** Data structure for an index.  Most fields will be

=== modified file 'storage/innobase/include/mtr0mtr.ic'
--- a/storage/innobase/include/mtr0mtr.ic	2011-05-04 09:54:04 +0000
+++ b/storage/innobase/include/mtr0mtr.ic	2011-05-31 08:18:27 +0000
@@ -47,6 +47,8 @@ mtr_start(
 /*======*/
 	mtr_t*	mtr)	/*!< out: mini-transaction */
 {
+	UNIV_MEM_INVALID(mtr, sizeof *mtr);
+
 	dyn_array_create(&(mtr->memo));
 	dyn_array_create(&(mtr->log));
 

=== modified file 'storage/innobase/include/rem0types.h'
--- a/storage/innobase/include/rem0types.h	2010-07-16 21:00:50 +0000
+++ b/storage/innobase/include/rem0types.h	2011-05-31 09:30:59 +0000
@@ -34,13 +34,21 @@ typedef byte	rec_t;
 #define REC_MAX_HEAP_NO		(2 * 8192 - 1)
 #define REC_MAX_N_OWNED		(16 - 1)
 
-/* REC_MAX_INDEX_COL_LEN is measured in bytes and is the maximum
-indexed column length (or indexed prefix length). It is set to 3*256,
-so that one can create a column prefix index on 256 characters of a
-TEXT or VARCHAR column also in the UTF-8 charset. In that charset,
-a character may take at most 3 bytes.
+/* REC_ANTELOPE_MAX_INDEX_COL_LEN is measured in bytes and is the maximum
+indexed field length (or indexed prefix length) for indexes on tables of
+ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT format.
+Before we support UTF-8 encodings with mbmaxlen = 4, a UTF-8 character
+may take at most 3 bytes.  So the limit was set to 3*256, so that one
+can create a column prefix index on 256 characters of a TEXT or VARCHAR
+column also in the UTF-8 charset.
 This constant MUST NOT BE CHANGED, or the compatibility of InnoDB data
 files would be at risk! */
-#define REC_MAX_INDEX_COL_LEN	768
+#define REC_ANTELOPE_MAX_INDEX_COL_LEN		768
+
+/** Maximum indexed field length for table format UNIV_FORMAT_B and
+beyond.
+This (3072) is the maximum index row length allowed, so we cannot create index
+prefix column longer than that. */
+#define REC_VERSION_56_MAX_INDEX_COL_LEN	3072
 
 #endif

=== modified file 'storage/innobase/include/row0ext.h'
--- a/storage/innobase/include/row0ext.h	2010-07-16 21:00:50 +0000
+++ b/storage/innobase/include/row0ext.h	2011-05-31 09:30:59 +0000
@@ -30,6 +30,7 @@ Created September 2006 Marko Makela
 #include "row0types.h"
 #include "data0types.h"
 #include "mem0mem.h"
+#include "dict0types.h"
 
 /********************************************************************//**
 Creates a cache of column prefixes of externally stored columns.
@@ -43,13 +44,13 @@ row_ext_create(
 				in the InnoDB table object, as reported by
 				dict_col_get_no(); NOT relative to the records
 				in the clustered index */
+	ulint		flags, /*!< in: table->flags */
 	const dtuple_t*	tuple,	/*!< in: data tuple containing the field
 				references of the externally stored
 				columns; must be indexed by col_no;
 				the clustered index record must be
 				covered by a lock or a page latch
 				to prevent deletion (rollback or purge). */
-	ulint		zip_size,/*!< compressed page size in bytes, or 0 */
 	mem_heap_t*	heap);	/*!< in: heap where created */
 
 /********************************************************************//**
@@ -63,7 +64,8 @@ row_ext_lookup_ith(
 	const row_ext_t*	ext,	/*!< in/out: column prefix cache */
 	ulint			i,	/*!< in: index of ext->ext[] */
 	ulint*			len);	/*!< out: length of prefix, in bytes,
-					at most REC_MAX_INDEX_COL_LEN */
+					at most the length determined by
+					DICT_MAX_FIELD_LEN_BY_FORMAT() */
 /********************************************************************//**
 Looks up a column prefix of an externally stored column.
 @return column prefix, or NULL if the column is not stored externally,
@@ -78,13 +80,18 @@ row_ext_lookup(
 					dict_col_get_no(); NOT relative to the
 					records in the clustered index */
 	ulint*			len);	/*!< out: length of prefix, in bytes,
-					at most REC_MAX_INDEX_COL_LEN */
+					at most the length determined by
+					DICT_MAX_FIELD_LEN_BY_FORMAT() */
 
 /** Prefixes of externally stored columns */
 struct row_ext_struct{
 	ulint		n_ext;	/*!< number of externally stored columns */
 	const ulint*	ext;	/*!< col_no's of externally stored columns */
 	byte*		buf;	/*!< backing store of the column prefix cache */
+	ulint		max_len;/*!< maximum prefix length, it could be
+				REC_ANTELOPE_MAX_INDEX_COL_LEN or
+				REC_VERSION_56_MAX_INDEX_COL_LEN depending
+				on row format */
 	ulint		len[1];	/*!< prefix lengths; 0 if not cached */
 };
 

=== modified file 'storage/innobase/include/row0ext.ic'
--- a/storage/innobase/include/row0ext.ic	2010-07-16 21:00:50 +0000
+++ b/storage/innobase/include/row0ext.ic	2011-05-31 09:30:59 +0000
@@ -37,7 +37,7 @@ row_ext_lookup_ith(
 	const row_ext_t*	ext,	/*!< in/out: column prefix cache */
 	ulint			i,	/*!< in: index of ext->ext[] */
 	ulint*			len)	/*!< out: length of prefix, in bytes,
-					at most REC_MAX_INDEX_COL_LEN */
+					at most ext->max_len */
 {
 	ut_ad(ext);
 	ut_ad(len);
@@ -45,11 +45,14 @@ row_ext_lookup_ith(
 
 	*len = ext->len[i];
 
+	ut_ad(*len <= ext->max_len);
+	ut_ad(ext->max_len > 0);
+
 	if (UNIV_UNLIKELY(*len == 0)) {
 		/* The BLOB could not be fetched to the cache. */
 		return(field_ref_zero);
 	} else {
-		return(ext->buf + i * REC_MAX_INDEX_COL_LEN);
+		return(ext->buf + i * ext->max_len);
 	}
 }
 
@@ -67,7 +70,7 @@ row_ext_lookup(
 					dict_col_get_no(); NOT relative to the
 					records in the clustered index */
 	ulint*			len)	/*!< out: length of prefix, in bytes,
-					at most REC_MAX_INDEX_COL_LEN */
+					at most ext->max_len */
 {
 	ulint	i;
 

=== modified file 'storage/innobase/mtr/mtr0mtr.c'
--- a/storage/innobase/mtr/mtr0mtr.c	2011-05-04 09:54:04 +0000
+++ b/storage/innobase/mtr/mtr0mtr.c	2011-05-31 08:18:27 +0000
@@ -296,9 +296,20 @@ mtr_commit(
 	mtr_memo_pop_all(mtr);
 #endif /* !UNIV_HOTBACKUP */
 
-	ut_d(mtr->state = MTR_COMMITTED);
 	dyn_array_free(&(mtr->memo));
 	dyn_array_free(&(mtr->log));
+#ifdef UNIV_DEBUG_VALGRIND
+	/* Declare everything uninitialized except
+	mtr->start_lsn, mtr->end_lsn and mtr->state. */
+	{
+		lsn_t	start_lsn	= mtr->start_lsn;
+		lsn_t	end_lsn		= mtr->end_lsn;
+		UNIV_MEM_INVALID(mtr, sizeof *mtr);
+		mtr->start_lsn = start_lsn;
+		mtr->end_lsn = end_lsn;
+	}
+#endif /* UNIV_DEBUG_VALGRIND */
+	ut_d(mtr->state = MTR_COMMITTED);
 }
 
 #ifndef UNIV_HOTBACKUP

=== modified file 'storage/innobase/page/page0zip.c'
--- a/storage/innobase/page/page0zip.c	2011-04-27 21:49:19 +0000
+++ b/storage/innobase/page/page0zip.c	2011-05-31 09:30:59 +0000
@@ -465,7 +465,7 @@ page_zip_fields_encode(
 
 			if (fixed_sum && UNIV_UNLIKELY
 			    (fixed_sum + field->fixed_len
-			     > DICT_MAX_INDEX_COL_LEN)) {
+			     > DICT_MAX_FIXED_COL_LEN)) {
 				/* Write out the length of the
 				preceding non-nullable fields,
 				to avoid exceeding the maximum

=== modified file 'storage/innobase/rem/rem0rec.c'
--- a/storage/innobase/rem/rem0rec.c	2010-10-19 10:03:25 +0000
+++ b/storage/innobase/rem/rem0rec.c	2011-05-31 09:30:59 +0000
@@ -1174,7 +1174,7 @@ rec_convert_dtuple_to_rec_comp(
 		} else if (dfield_is_ext(field)) {
 			ut_ad(ifield->col->len >= 256
 			      || ifield->col->mtype == DATA_BLOB);
-			ut_ad(len <= REC_MAX_INDEX_COL_LEN
+			ut_ad(len <= REC_ANTELOPE_MAX_INDEX_COL_LEN
 			      + BTR_EXTERN_FIELD_REF_SIZE);
 			*lens-- = (byte) (len >> 8) | 0xc0;
 			*lens-- = (byte) len;

=== modified file 'storage/innobase/row/row0ext.c'
--- a/storage/innobase/row/row0ext.c	2011-03-23 13:43:14 +0000
+++ b/storage/innobase/row/row0ext.c	2011-05-31 09:30:59 +0000
@@ -44,8 +44,9 @@ row_ext_cache_fill(
 {
 	const byte*	field	= dfield_get_data(dfield);
 	ulint		f_len	= dfield_get_len(dfield);
-	byte*		buf	= ext->buf + i * REC_MAX_INDEX_COL_LEN;
+	byte*		buf	= ext->buf + i * ext->max_len;
 
+	ut_ad(ext->max_len > 0);
 	ut_ad(i < ext->n_ext);
 	ut_ad(dfield_is_ext(dfield));
 	ut_a(f_len >= BTR_EXTERN_FIELD_REF_SIZE);
@@ -56,14 +57,14 @@ row_ext_cache_fill(
 		/* The BLOB pointer is not set: we cannot fetch it */
 		ext->len[i] = 0;
 	} else {
-		/* Fetch at most REC_MAX_INDEX_COL_LEN of the column.
+		/* Fetch at most ext->max_len of the column.
 		The column should be non-empty.  However,
 		trx_rollback_or_clean_all_recovered() may try to
 		access a half-deleted BLOB if the server previously
 		crashed during the execution of
 		btr_free_externally_stored_field(). */
 		ext->len[i] = btr_copy_externally_stored_field_prefix(
-			buf, REC_MAX_INDEX_COL_LEN, zip_size, field, f_len);
+			buf, ext->max_len, zip_size, field, f_len);
 	}
 }
 
@@ -79,16 +80,18 @@ row_ext_create(
 				in the InnoDB table object, as reported by
 				dict_col_get_no(); NOT relative to the records
 				in the clustered index */
+	ulint		flags,	/*!< in: table->flags */
 	const dtuple_t*	tuple,	/*!< in: data tuple containing the field
 				references of the externally stored
 				columns; must be indexed by col_no;
 				the clustered index record must be
 				covered by a lock or a page latch
 				to prevent deletion (rollback or purge). */
-	ulint		zip_size,/*!< compressed page size in bytes, or 0 */
 	mem_heap_t*	heap)	/*!< in: heap where created */
 {
 	ulint		i;
+	ulint		zip_size = dict_table_flags_to_zip_size(flags);
+
 	row_ext_t*	ret = mem_heap_alloc(heap, (sizeof *ret)
 					     + (n_ext - 1) * sizeof ret->len);
 
@@ -97,10 +100,12 @@ row_ext_create(
 
 	ret->n_ext = n_ext;
 	ret->ext = ext;
-	ret->buf = mem_heap_alloc(heap, n_ext * REC_MAX_INDEX_COL_LEN);
+	ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags);
+
+	ret->buf = mem_heap_alloc(heap, n_ext * ret->max_len);
 #ifdef UNIV_DEBUG
-	memset(ret->buf, 0xaa, n_ext * REC_MAX_INDEX_COL_LEN);
-	UNIV_MEM_ALLOC(ret->buf, n_ext * REC_MAX_INDEX_COL_LEN);
+	memset(ret->buf, 0xaa, n_ext * ret->max_len);
+	UNIV_MEM_ALLOC(ret->buf, n_ext * ret->max_len);
 #endif
 
 	/* Fetch the BLOB prefixes */

=== modified file 'storage/innobase/row/row0mysql.c'
--- a/storage/innobase/row/row0mysql.c	2011-05-22 20:19:06 +0000
+++ b/storage/innobase/row/row0mysql.c	2011-05-31 09:30:59 +0000
@@ -2009,6 +2009,7 @@ row_create_index_for_mysql(
 	ulint		i;
 	ulint		len;
 	char*		table_name;
+	dict_table_t*	table;
 
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
@@ -2022,6 +2023,9 @@ row_create_index_for_mysql(
 	que_run_threads()) and thus index->table_name is not available. */
 	table_name = mem_strdup(index->table_name);
 
+	table = dict_table_open_on_name_no_stats(table_name, TRUE,
+						 DICT_ERR_IGNORE_NONE);
+
 	trx_start_if_not_started_xa(trx);
 
 	/* Check that the same column does not appear twice in the index.
@@ -2054,7 +2058,7 @@ row_create_index_for_mysql(
 		}
 
 		/* Check also that prefix_len and actual length
-		< DICT_MAX_INDEX_COL_LEN */
+		is less than that from DICT_MAX_FIELD_LEN_BY_FORMAT() */
 
 		len = dict_index_get_nth_field(index, i)->prefix_len;
 
@@ -2062,8 +2066,9 @@ row_create_index_for_mysql(
 			len = ut_max(len, field_lengths[i]);
 		}
 
-		if (len >= DICT_MAX_INDEX_COL_LEN) {
-			err = DB_TOO_BIG_RECORD;
+		/* Column or prefix length exceeds maximum column length */
+		if (len > (ulint) DICT_MAX_FIELD_LEN_BY_FORMAT(table)) {
+			err = DB_TOO_BIG_INDEX_COL;
 
 			goto error_handling;
 		}
@@ -2088,6 +2093,8 @@ row_create_index_for_mysql(
 	que_graph_free((que_t*) que_node_get_parent(thr));
 
 error_handling:
+	dict_table_close(table, TRUE);
+
 	if (err != DB_SUCCESS) {
 		/* We have special error handling here */
 

=== modified file 'storage/innobase/row/row0row.c'
--- a/storage/innobase/row/row0row.c	2011-05-24 12:05:57 +0000
+++ b/storage/innobase/row/row0row.c	2011-05-31 09:30:59 +0000
@@ -122,8 +122,6 @@ row_build_index_entry(
 		} else if (dfield_is_ext(dfield)) {
 			ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
 			len -= BTR_EXTERN_FIELD_REF_SIZE;
-			ut_a(ind_field->prefix_len <= len
-			     || dict_index_is_clust(index));
 		}
 
 		len = dtype_get_at_most_n_mbchars(
@@ -272,8 +270,7 @@ row_build(
 		ut_ad(dict_table_get_format(index->table)
 		      < UNIV_FORMAT_B);
 	} else if (j) {
-		*ext = row_ext_create(j, ext_cols, row,
-				      dict_table_zip_size(index->table),
+		*ext = row_ext_create(j, ext_cols, index->table->flags, row,
 				      heap);
 	} else {
 		*ext = NULL;

=== modified file 'storage/innobase/row/row0sel.c'
--- a/storage/innobase/row/row0sel.c	2011-05-04 09:54:04 +0000
+++ b/storage/innobase/row/row0sel.c	2011-05-31 09:30:59 +0000
@@ -101,10 +101,12 @@ row_sel_sec_rec_is_for_blob(
 	ulint		clust_len,	/*!< in: length of clust_field */
 	const byte*	sec_field,	/*!< in: column in secondary index */
 	ulint		sec_len,	/*!< in: length of sec_field */
-	ulint		zip_size)	/*!< in: compressed page size, or 0 */
+	dict_table_t*	table)		/*!< in: table */
 {
 	ulint	len;
-	byte	buf[DICT_MAX_INDEX_COL_LEN];
+	byte	buf[REC_VERSION_56_MAX_INDEX_COL_LEN];
+	ulint	zip_size = dict_table_flags_to_zip_size(table->flags);
+	ulint	max_prefix_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table);
 
 	ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
 
@@ -118,7 +120,7 @@ row_sel_sec_rec_is_for_blob(
 		return(FALSE);
 	}
 
-	len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
+	len = btr_copy_externally_stored_field_prefix(buf, max_prefix_len,
 						      zip_size,
 						      clust_field, clust_len);
 
@@ -224,8 +226,7 @@ row_sel_sec_rec_is_for_clust_rec(
 					    col->mbminmaxlen,
 					    clust_field, clust_len,
 					    sec_field, sec_len,
-					    dict_table_zip_size(
-						    clust_index->table))) {
+					    clust_index->table)) {
 					goto inequal;
 				}
 

=== modified file 'storage/innobase/row/row0upd.c'
--- a/storage/innobase/row/row0upd.c	2011-04-26 11:14:22 +0000
+++ b/storage/innobase/row/row0upd.c	2011-05-31 09:30:59 +0000
@@ -1209,8 +1209,8 @@ row_upd_replace(
 	}
 
 	if (n_ext_cols) {
-		*ext = row_ext_create(n_ext_cols, ext_cols, row,
-				      dict_table_zip_size(table), heap);
+		*ext = row_ext_create(n_ext_cols, ext_cols, table->flags, row,
+				      heap);
 	} else {
 		*ext = NULL;
 	}

=== modified file 'storage/innobase/scripts/persistent_storage.sql'
--- a/storage/innobase/scripts/persistent_storage.sql	2011-03-14 14:44:14 +0000
+++ b/storage/innobase/scripts/persistent_storage.sql	2011-05-30 13:56:01 +0000
@@ -1,8 +1,5 @@
-DROP DATABASE IF EXISTS innodb;
-CREATE DATABASE innodb;
-
--- DROP TABLE IF EXISTS innodb.table_stats;
-CREATE TABLE innodb.table_stats (
+DROP TABLE IF EXISTS mysql.innodb_table_stats;
+CREATE TABLE mysql.innodb_table_stats (
 	database_name			VARCHAR(64) NOT NULL,
 	table_name			VARCHAR(64) NOT NULL,
 	stats_timestamp			TIMESTAMP NOT NULL,
@@ -12,8 +9,8 @@ CREATE TABLE innodb.table_stats (
 	PRIMARY KEY (database_name, table_name)
 ) ENGINE=INNODB DEFAULT CHARSET=utf8;
 
--- DROP TABLE IF EXISTS innodb.index_stats;
-CREATE TABLE innodb.index_stats (
+DROP TABLE IF EXISTS mysql.innodb_index_stats;
+CREATE TABLE mysql.innodb_index_stats (
 	database_name			VARCHAR(64) NOT NULL,
 	table_name			VARCHAR(64) NOT NULL,
 	index_name			VARCHAR(64) NOT NULL,
@@ -28,5 +25,5 @@ CREATE TABLE innodb.index_stats (
 	stat_description		VARCHAR(1024) NOT NULL,
 	PRIMARY KEY (database_name, table_name, index_name, stat_name),
 	FOREIGN KEY (database_name, table_name)
-	  REFERENCES table_stats (database_name, table_name)
+	  REFERENCES mysql.innodb_table_stats (database_name, table_name)
 ) ENGINE=INNODB DEFAULT CHARSET=utf8;

=== modified file 'storage/innobase/trx/trx0rec.c'
--- a/storage/innobase/trx/trx0rec.c	2011-05-04 11:29:29 +0000
+++ b/storage/innobase/trx/trx0rec.c	2011-05-31 09:30:59 +0000
@@ -352,10 +352,11 @@ trx_undo_rec_get_col_val(
 		ut_ad(*orig_len >= BTR_EXTERN_FIELD_REF_SIZE);
 		ut_ad(*len > *orig_len);
 		/* @see dtuple_convert_big_rec() */
-		ut_ad(*len >= BTR_EXTERN_FIELD_REF_SIZE * 2);
+		ut_ad(*len >= BTR_EXTERN_FIELD_REF_SIZE);
+
 		/* we do not have access to index->table here
 		ut_ad(dict_table_get_format(index->table) >= UNIV_FORMAT_B
-		      || *len >= REC_MAX_INDEX_COL_LEN
+		      || *len >= col->max_prefix
 		      + BTR_EXTERN_FIELD_REF_SIZE);
 		*/
 
@@ -457,9 +458,10 @@ static
 byte*
 trx_undo_page_fetch_ext(
 /*====================*/
-	byte*		ext_buf,	/*!< in: a buffer of
-					REC_MAX_INDEX_COL_LEN
-					+ BTR_EXTERN_FIELD_REF_SIZE */
+	byte*		ext_buf,	/*!< in: buffer to hold the prefix
+					data and BLOB pointer */
+	ulint		prefix_len,	/*!< in: prefix size to store
+					in the undo log */
 	ulint		zip_size,	/*!< compressed page size in bytes,
 					or 0 for uncompressed BLOB  */
 	const byte*	field,		/*!< in: an externally stored column */
@@ -468,7 +470,7 @@ trx_undo_page_fetch_ext(
 {
 	/* Fetch the BLOB. */
 	ulint	ext_len = btr_copy_externally_stored_field_prefix(
-		ext_buf, REC_MAX_INDEX_COL_LEN, zip_size, field, *len);
+		ext_buf, prefix_len, zip_size, field, *len);
 	/* BLOBs should always be nonempty. */
 	ut_a(ext_len);
 	/* Append the BLOB pointer to the prefix. */
@@ -489,10 +491,11 @@ trx_undo_page_report_modify_ext(
 	byte*		ptr,		/*!< in: undo log position,
 					at least 15 bytes must be available */
 	byte*		ext_buf,	/*!< in: a buffer of
-					REC_MAX_INDEX_COL_LEN
-					+ BTR_EXTERN_FIELD_REF_SIZE,
+					DICT_MAX_FIELD_LEN_BY_FORMAT() size,
 					or NULL when should not fetch
 					a longer prefix */
+	ulint		prefix_len,	/*!< prefix size to store in the
+					undo log */
 	ulint		zip_size,	/*!< compressed page size in bytes,
 					or 0 for uncompressed BLOB  */
 	const byte**	field,		/*!< in/out: the locally stored part of
@@ -500,6 +503,8 @@ trx_undo_page_report_modify_ext(
 	ulint*		len)		/*!< in/out: length of field, in bytes */
 {
 	if (ext_buf) {
+		ut_a(prefix_len > 0);
+
 		/* If an ordering column is externally stored, we will
 		have to store a longer prefix of the field.  In this
 		case, write to the log a marker followed by the
@@ -508,7 +513,7 @@ trx_undo_page_report_modify_ext(
 
 		ptr += mach_write_compressed(ptr, *len);
 
-		*field = trx_undo_page_fetch_ext(ext_buf, zip_size,
+		*field = trx_undo_page_fetch_ext(ext_buf, prefix_len, zip_size,
 						 *field, len);
 
 		ptr += mach_write_compressed(ptr, *len);
@@ -554,7 +559,7 @@ trx_undo_page_report_modify(
 	ulint		i;
 	trx_id_t	trx_id;
 	ibool		ignore_prefix = FALSE;
-	byte		ext_buf[REC_MAX_INDEX_COL_LEN
+	byte		ext_buf[REC_VERSION_56_MAX_INDEX_COL_LEN
 				+ BTR_EXTERN_FIELD_REF_SIZE];
 
 	ut_a(dict_index_is_clust(index));
@@ -666,6 +671,7 @@ trx_undo_page_report_modify(
 	/* Save to the undo log the old values of the columns to be updated. */
 
 	if (update) {
+
 		if (trx_undo_left(undo_page, ptr) < 5) {
 
 			return(0);
@@ -694,13 +700,21 @@ trx_undo_page_report_modify(
 			}
 
 			if (rec_offs_nth_extern(offsets, pos)) {
+				const dict_col_t*	col
+					= dict_index_get_nth_col(index, pos);
+				ulint			prefix_len
+					= dict_max_field_len_store_undo(
+						table, col);
+
+				ut_ad(prefix_len + BTR_EXTERN_FIELD_REF_SIZE
+				      <= sizeof ext_buf);
+
 				ptr = trx_undo_page_report_modify_ext(
 					ptr,
-					dict_index_get_nth_col(index, pos)
-					->ord_part
+					col->ord_part
 					&& !ignore_prefix
-					&& flen < REC_MAX_INDEX_COL_LEN
-					? ext_buf : NULL,
+					&& flen < REC_ANTELOPE_MAX_INDEX_COL_LEN
+					? ext_buf : NULL, prefix_len,
 					dict_table_zip_size(table),
 					&field, &flen);
 
@@ -779,11 +793,20 @@ trx_undo_page_report_modify(
 							  &flen);
 
 				if (rec_offs_nth_extern(offsets, pos)) {
+					const dict_col_t*	col =
+						dict_index_get_nth_col(
+							index, pos);
+					ulint			prefix_len =
+						dict_max_field_len_store_undo(
+							table, col);
+
+					ut_a(prefix_len < sizeof ext_buf);
+
 					ptr = trx_undo_page_report_modify_ext(
 						ptr,
-						flen < REC_MAX_INDEX_COL_LEN
+						flen < REC_ANTELOPE_MAX_INDEX_COL_LEN
 						&& !ignore_prefix
-						? ext_buf : NULL,
+						? ext_buf : NULL, prefix_len,
 						dict_table_zip_size(table),
 						&field, &flen);
 				} else {
@@ -1083,11 +1106,11 @@ trx_undo_rec_get_partial_row(
 			undo log record. */
 			if (!ignore_prefix && col->ord_part) {
 				ut_a(dfield_get_len(dfield)
-				     >= 2 * BTR_EXTERN_FIELD_REF_SIZE);
+				     >= BTR_EXTERN_FIELD_REF_SIZE);
 				ut_a(dict_table_get_format(index->table)
 				     >= UNIV_FORMAT_B
 				     || dfield_get_len(dfield)
-				     >= REC_MAX_INDEX_COL_LEN
+				     >= REC_ANTELOPE_MAX_INDEX_COL_LEN
 				     + BTR_EXTERN_FIELD_REF_SIZE);
 			}
 		}

=== modified file 'storage/innobase/ut/ut0ut.c'
--- a/storage/innobase/ut/ut0ut.c	2011-05-17 11:42:10 +0000
+++ b/storage/innobase/ut/ut0ut.c	2011-05-31 09:30:59 +0000
@@ -642,6 +642,8 @@ ut_strerr(
 		return("Table is being used");
 	case DB_TOO_BIG_RECORD:
 		return("Record too big");
+	case DB_TOO_BIG_INDEX_COL:
+		return("Index columns size too big");
 	case DB_LOCK_WAIT_TIMEOUT:
 		return("Lock wait timeout");
 	case DB_NO_REFERENCED_ROW:

=== modified file 'storage/perfschema/pfs.cc'
--- a/storage/perfschema/pfs.cc	2011-05-17 17:34:45 +0000
+++ b/storage/perfschema/pfs.cc	2011-06-06 20:42:17 +0000
@@ -1141,7 +1141,8 @@ static enum_operation_type socket_operat
   OPERATION_TYPE_SOCKETSEEK,
   OPERATION_TYPE_SOCKETOPT,
   OPERATION_TYPE_SOCKETSTAT,
-  OPERATION_TYPE_SOCKETSHUTDOWN
+  OPERATION_TYPE_SOCKETSHUTDOWN,
+  OPERATION_TYPE_SOCKETSELECT
 };
 
 /**
@@ -2843,6 +2844,7 @@ get_thread_socket_locker_v1(PSI_socket_l
       case PSI_SOCKET_STAT:
       case PSI_SOCKET_SHUTDOWN:
       case PSI_SOCKET_CLOSE:
+      case PSI_SOCKET_SELECT:
         {
         PFS_socket *pfs_socket= reinterpret_cast<PFS_socket *>(socket);
         pfs_socket->m_socket_stat.m_io_stat.m_misc.aggregate_counted();
@@ -4593,6 +4595,7 @@ static void end_socket_wait_v1(PSI_socke
   case PSI_SOCKET_OPT:
   case PSI_SOCKET_STAT:
   case PSI_SOCKET_SHUTDOWN:
+  case PSI_SOCKET_SELECT:
     byte_stat= &socket->m_socket_stat.m_io_stat.m_misc;
     break;
   case PSI_SOCKET_CLOSE:

=== modified file 'storage/perfschema/pfs_column_types.h'
--- a/storage/perfschema/pfs_column_types.h	2011-04-14 01:36:24 +0000
+++ b/storage/perfschema/pfs_column_types.h	2011-06-06 20:42:17 +0000
@@ -164,9 +164,10 @@ enum enum_operation_type
   OPERATION_TYPE_SOCKETOPT = 52,
   OPERATION_TYPE_SOCKETSTAT = 53,
   OPERATION_TYPE_SOCKETSHUTDOWN = 54,
+  OPERATION_TYPE_SOCKETSELECT = 55,
 
   /* Idle operation */
-  OPERATION_TYPE_IDLE= 55
+  OPERATION_TYPE_IDLE= 56
 };
 /** Integer, first value of @sa enum_operation_type. */
 #define FIRST_OPERATION_TYPE (static_cast<int> (OPERATION_TYPE_LOCK))

=== modified file 'storage/perfschema/table_events_waits.cc'
--- a/storage/perfschema/table_events_waits.cc	2011-03-28 23:37:10 +0000
+++ b/storage/perfschema/table_events_waits.cc	2011-06-06 20:42:17 +0000
@@ -555,6 +555,7 @@ static const LEX_STRING operation_names_
   { C_STRING_WITH_LEN("opt") },
   { C_STRING_WITH_LEN("stat") },
   { C_STRING_WITH_LEN("shutdown") },
+  { C_STRING_WITH_LEN("select") },
 
   /* Idle operations */
   { C_STRING_WITH_LEN("idle") }

=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c	2011-05-26 15:20:09 +0000
+++ b/tests/mysql_client_test.c	2011-05-31 13:52:09 +0000
@@ -19594,6 +19594,46 @@ static void test_bug11766854()
 }
 
 
+/**
+  Bug#54790: Use of non-blocking mode for sockets limits performance
+*/
+
+static void test_bug54790()
+{
+  int rc;
+  MYSQL *lmysql;
+  uint timeout= 2;
+
+  DBUG_ENTER("test_bug54790");
+  myheader("test_bug54790");
+
+  lmysql= mysql_client_init(NULL);
+  DIE_UNLESS(lmysql);
+
+  rc= mysql_options(lmysql, MYSQL_OPT_READ_TIMEOUT, &timeout);
+  DIE_UNLESS(!rc);
+
+  if (!mysql_real_connect(lmysql, opt_host, opt_user, opt_password,
+                          opt_db ? opt_db : "test", opt_port,
+                          opt_unix_socket, 0))
+  {
+    mysql= lmysql;
+    myerror("mysql_real_connect failed");
+    mysql_close(lmysql);
+    exit(1);
+  }
+
+  rc= mysql_query(lmysql, "SELECT SLEEP(100);");
+  myquery_r(rc);
+
+  /* A timeout error (ER_NET_READ_INTERRUPTED) would be more appropriate. */
+  DIE_UNLESS(mysql_errno(lmysql) == CR_SERVER_LOST);
+
+  mysql_close(lmysql);
+
+  DBUG_VOID_RETURN;
+}
+
 /*
   Read and parse arguments and MySQL options from my.cnf
 */
@@ -19938,6 +19978,7 @@ static struct my_tests_st my_tests[]= {
   { "test_bug57058", test_bug57058 },
   { "test_bug56976", test_bug56976 },
   { "test_bug11766854", test_bug11766854 },
+  { "test_bug54790", test_bug54790 },
   { 0, 0 }
 };
 

=== modified file 'vio/CMakeLists.txt'
--- a/vio/CMakeLists.txt	2010-08-12 15:19:57 +0000
+++ b/vio/CMakeLists.txt	2011-05-31 13:52:09 +0000
@@ -17,6 +17,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/
 ${SSL_INCLUDE_DIRS})
 ADD_DEFINITIONS(${SSL_DEFINES})
 
-SET(VIO_SOURCES  vio.c viosocket.c viossl.c viosslfactories.c)
+SET(VIO_SOURCES vio.c viosocket.c viossl.c viopipe.c vioshm.c viosslfactories.c)
 ADD_CONVENIENCE_LIBRARY(vio ${VIO_SOURCES})
 TARGET_LINK_LIBRARIES(vio ${LIBSOCKET})

=== modified file 'vio/vio.c'
--- a/vio/vio.c	2011-05-27 15:46:36 +0000
+++ b/vio/vio.c	2011-06-06 19:57:05 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -11,7 +11,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
 /*
   Note that we can't have assertion on file descriptors;  The reason for
@@ -22,24 +22,26 @@
 
 #include "vio_priv.h"
 
-#if defined(__WIN__) || defined(HAVE_SMEM)
+#ifdef _WIN32
 
 /**
-  Stub poll_read method that defaults to indicate that there
-  is data to read.
+  Stub io_wait method that defaults to indicate that
+  requested I/O event is ready.
 
   Used for named pipe and shared memory VIO types.
 
   @param vio      Unused.
+  @param event    Unused.
   @param timeout  Unused.
 
-  @retval FALSE   There is data to read.
+  @retval 1       The requested I/O event has occurred.
 */
 
-static my_bool no_poll_read(Vio *vio __attribute__((unused)),
-                            uint timeout __attribute__((unused)))
+static int no_io_wait(Vio *vio __attribute__((unused)),
+                      enum enum_vio_io_event event __attribute__((unused)),
+                      int timeout __attribute__((unused)))
 {
-  return FALSE;
+  return 1;
 }
 
 #endif
@@ -53,8 +55,8 @@ static my_bool has_no_data(Vio *vio __at
  * Helper to fill most of the Vio* with defaults.
  */
 
-static void vio_init(Vio* vio, enum enum_vio_type type,
-                     my_socket sd, HANDLE hPipe, uint flags)
+static void vio_init(Vio *vio, enum enum_vio_type type,
+                     my_socket sd, uint flags)
 {
   DBUG_ENTER("vio_init");
   DBUG_PRINT("enter", ("type: %d  sd: %d  flags: %d", type, sd, flags));
@@ -66,125 +68,142 @@ static void vio_init(Vio* vio, enum enum
   vio->type= type;
   vio->mysql_socket= MYSQL_INVALID_SOCKET;
   mysql_socket_setfd(&vio->mysql_socket, sd);
-  vio->hPipe= hPipe;
   vio->localhost= flags & VIO_LOCALHOST;
+  vio->read_timeout= vio->write_timeout= -1;
   if ((flags & VIO_BUFFERED_READ) &&
       !(vio->read_buffer= (char*)my_malloc(VIO_READ_BUFFER_SIZE, MYF(MY_WME))))
     flags&= ~VIO_BUFFERED_READ;
 #ifdef _WIN32
   if (type == VIO_TYPE_NAMEDPIPE)
   {
-    vio->viodelete=       vio_delete;
-    vio->vioerrno=        vio_errno;
-    vio->read=            vio_read_pipe;
-    vio->write=           vio_write_pipe;
-    vio->fastsend=        vio_fastsend;
-    vio->viokeepalive=    vio_keepalive;
-    vio->should_retry=    vio_should_retry;
-    vio->was_interrupted= vio_was_interrupted;
-    vio->vioclose=        vio_close_pipe;
-    vio->peer_addr=       vio_peer_addr;
-    vio->vioblocking=     vio_blocking;
-    vio->is_blocking=     vio_is_blocking;
-    vio->poll_read=       no_poll_read;
-    vio->is_connected=    vio_is_connected_pipe;
-    vio->has_data=        has_no_data;
-    vio->timeout=         vio_win32_timeout;
-    vio->viogetfd=        vio_getfd;
-
-    /* Set default timeout */
-    vio->read_timeout_ms= INFINITE;
-    vio->write_timeout_ms= INFINITE;
-    vio->pipe_overlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL);
+    vio->viodelete	=vio_delete;
+    vio->vioerrno	=vio_errno;
+    vio->read           =vio_read_pipe;
+    vio->write          =vio_write_pipe;
+    vio->fastsend	=vio_fastsend;
+    vio->viokeepalive	=vio_keepalive;
+    vio->should_retry	=vio_should_retry;
+    vio->was_timeout    =vio_was_timeout;
+    vio->vioclose	=vio_close_pipe;
+    vio->peer_addr	=vio_peer_addr;
+    vio->io_wait        =no_io_wait;
+    vio->is_connected   =vio_is_connected_pipe;
+    vio->has_data       =has_no_data;
     DBUG_VOID_RETURN;
   }
 #endif
 #ifdef HAVE_SMEM
   if (type == VIO_TYPE_SHARED_MEMORY)
   {
-    vio->viodelete=       vio_delete;
-    vio->vioerrno=        vio_errno;
-    vio->read=            vio_read_shared_memory;
-    vio->write=           vio_write_shared_memory;
-    vio->fastsend=        vio_fastsend;
-    vio->viokeepalive=    vio_keepalive;
-    vio->should_retry=    vio_should_retry;
-    vio->was_interrupted= vio_was_interrupted;
-    vio->vioclose=        vio_close_shared_memory;
-    vio->peer_addr=       vio_peer_addr;
-    vio->vioblocking=     vio_blocking;
-    vio->is_blocking=     vio_is_blocking;
-    vio->poll_read=       no_poll_read;
-    vio->is_connected=    vio_is_connected_shared_memory;
-    vio->has_data=        has_no_data;
-    vio->viogetfd=        vio_getfd;
-
-    /* Currently, shared memory is on Windows only, hence the below is ok*/
-    vio->timeout= vio_win32_timeout;
-
-    /* Set default timeout */
-    vio->read_timeout_ms= INFINITE;
-    vio->write_timeout_ms= INFINITE;
+    vio->viodelete	=vio_delete;
+    vio->vioerrno	=vio_errno;
+    vio->read           =vio_read_shared_memory;
+    vio->write          =vio_write_shared_memory;
+    vio->fastsend	=vio_fastsend;
+    vio->viokeepalive	=vio_keepalive;
+    vio->should_retry	=vio_should_retry;
+    vio->was_timeout    =vio_was_timeout;
+    vio->vioclose	=vio_close_shared_memory;
+    vio->peer_addr	=vio_peer_addr;
+    vio->io_wait        =no_io_wait;
+    vio->is_connected   =vio_is_connected_shared_memory;
+    vio->has_data       =has_no_data;
     DBUG_VOID_RETURN;
   }
 #endif
 #ifdef HAVE_OPENSSL
   if (type == VIO_TYPE_SSL)
   {
-    vio->viodelete=       vio_ssl_delete;
-    vio->vioerrno=        vio_errno;
-    vio->read=            vio_ssl_read;
-    vio->write=           vio_ssl_write;
-    vio->fastsend=        vio_fastsend;
-    vio->viokeepalive=    vio_keepalive;
-    vio->should_retry=    vio_should_retry;
-    vio->was_interrupted= vio_was_interrupted;
-    vio->vioclose=        vio_ssl_close;
-    vio->peer_addr=       vio_peer_addr;
-    vio->vioblocking=     vio_ssl_blocking;
-    vio->is_blocking=     vio_is_blocking;
-    vio->timeout=         vio_timeout;
-    vio->poll_read=       vio_poll_read;
-    vio->is_connected=    vio_is_connected;
-    vio->has_data=        vio_ssl_has_data;
-    vio->viogetfd=        vio_getfd;
-
+    vio->viodelete	=vio_ssl_delete;
+    vio->vioerrno	=vio_errno;
+    vio->read		=vio_ssl_read;
+    vio->write		=vio_ssl_write;
+    vio->fastsend	=vio_fastsend;
+    vio->viokeepalive	=vio_keepalive;
+    vio->should_retry	=vio_should_retry;
+    vio->was_timeout    =vio_was_timeout;
+    vio->vioclose	=vio_ssl_close;
+    vio->peer_addr	=vio_peer_addr;
+    vio->io_wait        =vio_io_wait;
+    vio->is_connected   =vio_is_connected;
+    vio->has_data       =vio_ssl_has_data;
+    vio->timeout        =vio_socket_timeout;
     DBUG_VOID_RETURN;
   }
 #endif /* HAVE_OPENSSL */
-  vio->viodelete=       vio_delete;
-  vio->vioerrno=        vio_errno;
+  vio->viodelete        =vio_delete;
+  vio->vioerrno         =vio_errno;
   vio->read=            (flags & VIO_BUFFERED_READ) ? vio_read_buff : vio_read;
-  vio->write=           vio_write;
-  vio->fastsend=        vio_fastsend;
-  vio->viokeepalive=    vio_keepalive;
-  vio->should_retry=    vio_should_retry;
-  vio->was_interrupted= vio_was_interrupted;
-  vio->vioclose=        vio_close;
-  vio->peer_addr=       vio_peer_addr;
-  vio->vioblocking=     vio_blocking;
-  vio->is_blocking=     vio_is_blocking;
-  vio->timeout=         vio_timeout;
-  vio->poll_read=       vio_poll_read;
-  vio->is_connected=    vio_is_connected;
-  vio->has_data= (flags & VIO_BUFFERED_READ) ? vio_buff_has_data : has_no_data;
-  vio->viogetfd=        vio_getfd;
+  vio->write            =vio_write;
+  vio->fastsend         =vio_fastsend;
+  vio->viokeepalive     =vio_keepalive;
+  vio->should_retry     =vio_should_retry;
+  vio->was_timeout      =vio_was_timeout;
+  vio->vioclose         =vio_close;
+  vio->peer_addr        =vio_peer_addr;
+  vio->io_wait          =vio_io_wait;
+  vio->is_connected     =vio_is_connected;
+  vio->timeout          =vio_socket_timeout;
+  vio->has_data=        (flags & VIO_BUFFERED_READ) ?
+                            vio_buff_has_data : has_no_data;
   DBUG_VOID_RETURN;
 }
 
 
-/* Reset initialized VIO to use with another transport type */
+/**
+  Reinitialize an existing Vio object.
+
+  @remark Used to rebind an initialized socket-based Vio object
+          to another socket-based transport type. For example,
+          rebind a TCP/IP transport to SSL.
+
+  @param vio    A VIO object.
+  @param type   A socket-based transport type.
+  @param sd     The socket.
+  @param ssl    An optional SSL structure.
+  @param flags  Flags passed to vio_init.
+
+  @return Return value is zero on success.
+*/
 
-void vio_reset(Vio* vio, enum enum_vio_type type,
-               my_socket sd, HANDLE hPipe, uint flags)
+my_bool vio_reset(Vio* vio, enum enum_vio_type type,
+                  my_socket sd, void *ssl __attribute__((unused)), uint flags)
 {
+  int ret= FALSE;
+  Vio old_vio= *vio;
+  DBUG_ENTER("vio_reset");
+
+  /* The only supported rebind is from a socket-based transport type. */
+  DBUG_ASSERT(vio->type == VIO_TYPE_TCPIP || vio->type == VIO_TYPE_SOCKET);
+
+  /*
+    Will be reinitialized depending on the flags.
+    Nonetheless, already buffered inside the SSL layer.
+  */
   my_free(vio->read_buffer);
-  vio_init(vio, type, sd, hPipe, flags);
+
+  vio_init(vio, type, sd, flags);
+
+#ifdef HAVE_OPENSSL
+  vio->ssl_arg= ssl;
+#endif
+
+  /*
+    Propagate the timeout values. Necessary to also propagate
+    the underlying proprieties associated with the timeout,
+    such as the socket blocking mode.
+  */
+  if (old_vio.read_timeout >= 0)
+    ret|= vio_timeout(vio, 0, old_vio.read_timeout);
+
+  if (old_vio.write_timeout >= 0)
+    ret|= vio_timeout(vio, 1, old_vio.write_timeout);
+
+  DBUG_RETURN(test(ret));
 }
 
-/* Instrumented version of vio_new() for use in the server. The
- * non-instrumented vio_new() is used in the client library.
- */
+
+/* Create a new VIO for socket or TCP/IP connection. */
 
 Vio *mysql_socket_vio_new(MYSQL_SOCKET mysql_socket, enum enum_vio_type type, uint flags)
 {
@@ -192,40 +211,11 @@ Vio *mysql_socket_vio_new(MYSQL_SOCKET m
   my_socket sd= mysql_socket_getfd(mysql_socket);
   DBUG_ENTER("mysql_socket_vio_new");
   DBUG_PRINT("enter", ("sd: %d", sd));
-
   if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
   {
-    vio_init(vio, type, sd, 0, flags);
+    vio_init(vio, type, sd, flags);
     sprintf(vio->desc,
-     (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"), sd);
-#if !defined(__WIN__)
-#if !defined(NO_FCNTL_NONBLOCK)
-    /*
-      We call fcntl() to set the flags and then immediately read them back
-      to make sure that we and the system are in agreement on the state of
-      things.
-
-      An example of why we need to do this is FreeBSD (and apparently some
-      other BSD-derived systems, like Mac OS X), where the system sometimes
-      reports that the socket is set for non-blocking when it really will
-      block.
-    */
-    fcntl(sd, F_SETFL, 0);
-    vio->fcntl_mode= fcntl(sd, F_GETFL);
-#elif defined(HAVE_SYS_IOCTL_H)   /* hpux */
-    /* Non blocking sockets doesn't work good on HPUX 11.0 */
-    (void) ioctl(sd,FIOSNBIO,0);
-    vio->fcntl_mode &= ~O_NONBLOCK;
-#endif
-#else /* !defined(__WIN__) */
-    {
-      /* set to blocking mode by default */
-      ulong arg=0, r;
-      r = ioctlsocket(sd,FIONBIO,(void*) &arg);
-      vio->fcntl_mode &= ~O_NONBLOCK;
-    }
-#endif
-
+	    (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"), sd);
     vio->mysql_socket= mysql_socket;
   }
   DBUG_RETURN(vio);
@@ -246,8 +236,7 @@ Vio *vio_new(my_socket sd, enum enum_vio
   DBUG_RETURN(vio);
 }
 
-
-#ifdef __WIN__
+#ifdef _WIN32
 
 Vio *vio_new_win32pipe(HANDLE hPipe)
 {
@@ -255,7 +244,15 @@ Vio *vio_new_win32pipe(HANDLE hPipe)
   DBUG_ENTER("vio_new_handle");
   if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
   {
-    vio_init(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, VIO_LOCALHOST);
+    vio_init(vio, VIO_TYPE_NAMEDPIPE, 0, VIO_LOCALHOST);
+    /* Create an object for event notification. */
+    vio->overlapped.hEvent= CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (vio->overlapped.hEvent == NULL)
+    {
+      my_free(vio);
+      DBUG_RETURN(NULL);
+    }
+    vio->hPipe= hPipe;
     strmov(vio->desc, "named pipe");
   }
   DBUG_RETURN(vio);
@@ -271,7 +268,7 @@ Vio *vio_new_win32shared_memory(HANDLE h
   DBUG_ENTER("vio_new_win32shared_memory");
   if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
   {
-    vio_init(vio, VIO_TYPE_SHARED_MEMORY, 0, 0, VIO_LOCALHOST);
+    vio_init(vio, VIO_TYPE_SHARED_MEMORY, 0, VIO_LOCALHOST);
     vio->handle_file_map= handle_file_map;
     vio->handle_map= handle_map;
     vio->event_server_wrote= event_server_wrote;
@@ -289,6 +286,49 @@ Vio *vio_new_win32shared_memory(HANDLE h
 #endif
 
 
+/**
+  Set timeout for a network send or receive operation.
+
+  @remark A non-infinite timeout causes the socket to be
+          set to non-blocking mode. On infinite timeouts,
+          the socket is set to blocking mode.
+
+  @remark A negative timeout means an infinite timeout.
+
+  @param vio      A VIO object.
+  @param which    Whether timeout is for send (1) or receive (0).
+  @param timeout  Timeout interval in seconds.
+
+  @return FALSE on success, TRUE otherwise.
+*/
+
+int vio_timeout(Vio *vio, uint which, int timeout_sec)
+{
+  int timeout_ms;
+  my_bool old_mode;
+
+  /*
+    Vio timeouts are measured in milliseconds. Check for a possible
+    overflow. In case of overflow, set to infinite.
+  */
+  if (timeout_sec > INT_MAX/1000)
+    timeout_ms= -1;
+  else
+    timeout_ms= (int) (timeout_sec * 1000);
+
+  /* Deduce the current timeout status mode. */
+  old_mode= vio->write_timeout < 0 && vio->read_timeout < 0;
+
+  if (which)
+    vio->write_timeout= timeout_ms;
+  else
+    vio->read_timeout= timeout_ms;
+
+  /* VIO-specific timeout handling. Might change the blocking mode. */
+  return vio->timeout ? vio->timeout(vio, which, old_mode) : 0;
+}
+
+
 void vio_delete(Vio* vio)
 {
   if (!vio)

=== modified file 'vio/vio_priv.h'
--- a/vio/vio_priv.h	2011-04-15 09:33:58 +0000
+++ b/vio/vio_priv.h	2011-05-31 13:52:09 +0000
@@ -1,6 +1,3 @@
-#ifndef VIO_PRIV_INCLUDED
-#define VIO_PRIV_INCLUDED
-
 /* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
@@ -16,6 +13,9 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
+#ifndef VIO_PRIV_INCLUDED
+#define VIO_PRIV_INCLUDED
+
 /* Structures and functions private to the vio package */
 
 #define DONT_MAP_VIO
@@ -26,10 +26,6 @@
 #include <violite.h>
 
 #ifdef _WIN32
-void	vio_win32_timeout(Vio *vio, uint which, uint timeout);
-#endif
-
-#ifdef __WIN__
 size_t vio_read_pipe(Vio *vio, uchar * buf, size_t size);
 size_t vio_write_pipe(Vio *vio, const uchar * buf, size_t size);
 my_bool vio_is_connected_pipe(Vio *vio);
@@ -43,8 +39,9 @@ my_bool vio_is_connected_shared_memory(V
 int vio_close_shared_memory(Vio * vio);
 #endif
 
-void	vio_timeout(Vio *vio,uint which, uint timeout);
 my_bool vio_buff_has_data(Vio *vio);
+int vio_socket_io_wait(Vio *vio, enum enum_vio_io_event event);
+int vio_socket_timeout(Vio *vio, uint which, my_bool old_mode);
 
 #ifdef HAVE_OPENSSL
 #include "my_net.h"			/* needed because of struct in_addr */
@@ -55,9 +52,6 @@ size_t	vio_ssl_write(Vio *vio,const ucha
 /* When the workday is over... */
 int vio_ssl_close(Vio *vio);
 void vio_ssl_delete(Vio *vio);
-
-int vio_ssl_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode);
-
 my_bool vio_ssl_has_data(Vio *vio);
 
 #endif /* HAVE_OPENSSL */

=== added file 'vio/viopipe.c'
--- a/vio/viopipe.c	1970-01-01 00:00:00 +0000
+++ b/vio/viopipe.c	2011-06-06 19:57:05 +0000
@@ -0,0 +1,122 @@
+/* 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 */
+
+#include "vio_priv.h"
+
+#ifdef _WIN32
+
+static size_t wait_overlapped_result(Vio *vio, int timeout)
+{
+  size_t ret= (size_t) -1;
+  DWORD transferred, wait_status, timeout_ms;
+
+  timeout_ms= timeout >= 0 ? timeout : INFINITE;
+
+  /* Wait for the overlapped operation to be completed. */
+  wait_status= WaitForSingleObject(vio->overlapped.hEvent, timeout_ms);
+
+  /* The operation might have completed, attempt to retrieve the result. */
+  if (wait_status == WAIT_OBJECT_0)
+  {
+    /* If retrieval fails, a error code will have been set. */
+    if (GetOverlappedResult(vio->hPipe, &vio->overlapped, &transferred, FALSE))
+      ret= transferred;
+  }
+  else
+  {
+    /* Error or timeout, cancel the pending I/O operation. */
+    CancelIo(vio->hPipe);
+
+    /*
+      If the wait timed out, set error code to indicate a
+      timeout error. Otherwise, wait_status is WAIT_FAILED
+      and extended error information was already set.
+    */
+    if (wait_status == WAIT_TIMEOUT)
+      SetLastError(SOCKET_ETIMEDOUT);
+  }
+
+  return ret;
+}
+
+
+size_t vio_read_pipe(Vio *vio, uchar *buf, size_t count)
+{
+  DWORD transferred;
+  size_t ret= (size_t) -1;
+  DBUG_ENTER("vio_read_pipe");
+
+  /* Attempt to read from the pipe (overlapped I/O). */
+  if (ReadFile(vio->hPipe, buf, count, &transferred, &vio->overlapped))
+  {
+    /* The operation completed immediately. */
+    ret= transferred;
+  }
+  /* Read operation is pending completion asynchronously? */
+  else if (GetLastError() == ERROR_IO_PENDING)
+    ret= wait_overlapped_result(vio, vio->read_timeout);
+
+  DBUG_RETURN(ret);
+}
+
+
+size_t vio_write_pipe(Vio *vio, const uchar *buf, size_t count)
+{
+  DWORD transferred;
+  size_t ret= (size_t) -1;
+  DBUG_ENTER("vio_write_pipe");
+
+  /* Attempt to write to the pipe (overlapped I/O). */
+  if (WriteFile(vio->hPipe, buf, count, &transferred, &vio->overlapped))
+  {
+    /* The operation completed immediately. */
+    ret= transferred;
+  }
+  /* Write operation is pending completion asynchronously? */
+  else if (GetLastError() == ERROR_IO_PENDING)
+    ret= wait_overlapped_result(vio, vio->write_timeout);
+
+  DBUG_RETURN(ret);
+}
+
+
+my_bool vio_is_connected_pipe(Vio *vio)
+{
+  if (PeekNamedPipe(vio->hPipe, NULL, 0, NULL, NULL, NULL))
+    return TRUE;
+  else
+    return (GetLastError() != ERROR_BROKEN_PIPE);
+}
+
+
+int vio_close_pipe(Vio *vio)
+{
+  BOOL ret;
+  DBUG_ENTER("vio_close_pipe");
+
+  CancelIo(vio->hPipe);
+  CloseHandle(vio->overlapped.hEvent);
+  DisconnectNamedPipe(vio->hPipe);
+  ret= CloseHandle(vio->hPipe);
+
+  vio->type= VIO_CLOSED;
+  vio->hPipe= NULL;
+  vio->mysql_socket= MYSQL_INVALID_SOCKET;
+
+  DBUG_RETURN(ret);
+}
+
+#endif
+

=== added file 'vio/vioshm.c'
--- a/vio/vioshm.c	1970-01-01 00:00:00 +0000
+++ b/vio/vioshm.c	2011-06-06 19:57:05 +0000
@@ -0,0 +1,217 @@
+/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   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 */
+
+#include "vio_priv.h"
+
+#if defined(_WIN32) && defined(HAVE_SMEM)
+
+size_t vio_read_shared_memory(Vio *vio, uchar *buf, size_t size)
+{
+  size_t length;
+  size_t remain_local;
+  char *current_position;
+  HANDLE events[2];
+  DWORD timeout;
+  DBUG_ENTER("vio_read_shared_memory");
+
+  remain_local= size;
+  current_position= buf;
+  timeout= vio->read_timeout >= 0 ? vio->read_timeout : INFINITE;
+
+  events[0]= vio->event_server_wrote;
+  events[1]= vio->event_conn_closed;
+
+  do
+  {
+    if (vio->shared_memory_remain == 0)
+    {
+      DWORD wait_status;
+
+      wait_status= WaitForMultipleObjects(array_elements(events), events,
+                                          FALSE, timeout);
+
+      /*
+        WaitForMultipleObjects can return next values:
+         WAIT_OBJECT_0+0 - event from vio->event_server_wrote
+         WAIT_OBJECT_0+1 - event from vio->event_conn_closed.
+                           We can't read anything
+         WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail.  We can't read anything
+      */
+      if (wait_status != WAIT_OBJECT_0)
+      {
+        /*
+          If wait_status is WAIT_TIMEOUT, set error code to indicate a
+          timeout error. If vio->event_conn_closed was set, use an EOF
+          condition (return value of zero) to indicate that the operation
+          has been aborted.
+        */
+        if (wait_status == WAIT_TIMEOUT)
+          SetLastError(SOCKET_ETIMEDOUT);
+        else if (wait_status == (WAIT_OBJECT_0 + 1))
+          DBUG_RETURN(0);
+
+        DBUG_RETURN(-1);
+      }
+
+      vio->shared_memory_pos= vio->handle_map;
+      vio->shared_memory_remain= uint4korr((ulong*)vio->shared_memory_pos);
+      vio->shared_memory_pos+= 4;
+    }
+
+    length= size;
+
+    if (vio->shared_memory_remain < length)
+       length= vio->shared_memory_remain;
+    if (length > remain_local)
+       length= remain_local;
+
+    memcpy(current_position, vio->shared_memory_pos, length);
+
+    vio->shared_memory_remain-= length;
+    vio->shared_memory_pos+= length;
+    current_position+= length;
+    remain_local-= length;
+
+    if (!vio->shared_memory_remain)
+    {
+      if (!SetEvent(vio->event_client_read))
+        DBUG_RETURN(-1);
+    }
+  } while (remain_local);
+  length= size;
+
+  DBUG_RETURN(length);
+}
+
+
+size_t vio_write_shared_memory(Vio *vio, const uchar *buf, size_t size)
+{
+  size_t length, remain, sz;
+  HANDLE pos;
+  const uchar *current_position;
+  HANDLE events[2];
+  DWORD timeout;
+  DBUG_ENTER("vio_write_shared_memory");
+
+  remain= size;
+  current_position= buf;
+  timeout= vio->write_timeout >= 0 ? vio->write_timeout : INFINITE;
+
+  events[0]= vio->event_server_read;
+  events[1]= vio->event_conn_closed;
+
+  while (remain != 0)
+  {
+    DWORD wait_status;
+
+    wait_status= WaitForMultipleObjects(array_elements(events), events,
+                                        FALSE, timeout);
+
+    if (wait_status != WAIT_OBJECT_0)
+    {
+      /* Set error code to indicate a timeout error or disconnect. */
+      if (wait_status == WAIT_TIMEOUT)
+        SetLastError(SOCKET_ETIMEDOUT);
+      else
+        SetLastError(ERROR_GRACEFUL_DISCONNECT);
+
+      DBUG_RETURN((size_t) -1);
+    }
+
+    sz= (remain > shared_memory_buffer_length ? shared_memory_buffer_length :
+         remain);
+
+    int4store(vio->handle_map, sz);
+    pos= vio->handle_map + 4;
+    memcpy(pos, current_position, sz);
+    remain-= sz;
+    current_position+= sz;
+    if (!SetEvent(vio->event_client_wrote))
+      DBUG_RETURN((size_t) -1);
+  }
+  length= size;
+
+  DBUG_RETURN(length);
+}
+
+
+my_bool vio_is_connected_shared_memory(Vio *vio)
+{
+  return (WaitForSingleObject(vio->event_conn_closed, 0) != WAIT_OBJECT_0);
+}
+
+
+/**
+ Close shared memory and DBUG_PRINT any errors that happen on closing.
+ @return Zero if all closing functions succeed, and nonzero otherwise.
+*/
+int vio_close_shared_memory(Vio * vio)
+{
+  int error_count= 0;
+  DBUG_ENTER("vio_close_shared_memory");
+  if (vio->type != VIO_CLOSED)
+  {
+    /*
+      Set event_conn_closed for notification of both client and server that
+      connection is closed
+    */
+    SetEvent(vio->event_conn_closed);
+    /*
+      Close all handlers. UnmapViewOfFile and CloseHandle return non-zero
+      result if they are success.
+    */
+    if (UnmapViewOfFile(vio->handle_map) == 0)
+    {
+      error_count++;
+      DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed"));
+    }
+    if (CloseHandle(vio->event_server_wrote) == 0)
+    {
+      error_count++;
+      DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed"));
+    }
+    if (CloseHandle(vio->event_server_read) == 0)
+    {
+      error_count++;
+      DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed"));
+    }
+    if (CloseHandle(vio->event_client_wrote) == 0)
+    {
+      error_count++;
+      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed"));
+    }
+    if (CloseHandle(vio->event_client_read) == 0)
+    {
+      error_count++;
+      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed"));
+    }
+    if (CloseHandle(vio->handle_file_map) == 0)
+    {
+      error_count++;
+      DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed"));
+    }
+    if (CloseHandle(vio->event_conn_closed) == 0)
+    {
+      error_count++;
+      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed"));
+    }
+  }
+  vio->type= VIO_CLOSED;
+  vio->mysql_socket= MYSQL_INVALID_SOCKET;
+  DBUG_RETURN(error_count);
+}
+
+#endif /* #if defined(_WIN32) && defined(HAVE_SMEM) */
+

=== modified file 'vio/viosocket.c'
--- a/vio/viosocket.c	2011-05-17 17:34:45 +0000
+++ b/vio/viosocket.c	2011-06-06 20:16:03 +0000
@@ -30,44 +30,100 @@
 
 int vio_errno(Vio *vio __attribute__((unused)))
 {
-  return socket_errno;		/* On Win32 this mapped to WSAGetLastError() */
+  /* These transport types are not Winsock based. */
+#ifdef _WIN32
+  if (vio->type == VIO_TYPE_NAMEDPIPE ||
+      vio->type == VIO_TYPE_SHARED_MEMORY)
+    return GetLastError();
+#endif
+
+  /* Mapped to WSAGetLastError() on Win32. */
+  return socket_errno;
 }
 
 
-size_t vio_read(Vio* vio, uchar* buf, size_t size)
+/**
+  Attempt to wait for an I/O event on a socket.
+
+  @param vio      VIO object representing a connected socket.
+  @param event    The type of I/O event (read or write) to wait for.
+
+  @return Return value is -1 on failure, 0 on success.
+*/
+
+int vio_socket_io_wait(Vio *vio, enum enum_vio_io_event event)
 {
-  size_t r;
-  size_t bytes_read= 0;
-  my_socket sd= mysql_socket_getfd(vio->mysql_socket);
-  MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
+  int timeout, ret;
+
+  DBUG_ASSERT(event == VIO_IO_EVENT_READ || event == VIO_IO_EVENT_WRITE);
+
+  /* Choose an appropriate timeout. */
+  if (event == VIO_IO_EVENT_READ)
+    timeout= vio->read_timeout;
+  else
+    timeout= vio->write_timeout;
+
+  /* Wait for input data to become available. */
+  switch (vio_io_wait(vio, event, timeout))
+  {
+  case -1:
+    /* Upon failure, vio_read/write() shall return -1. */
+    ret= -1;
+    break;
+  case  0:
+    /* The wait timed out. */
+    ret= -1;
+    break;
+  default:
+    /* A positive value indicates an I/O event. */
+    ret= 0;
+    break;
+  }
+
+  return ret;
+}
+
+
+/*
+  Define a stub MSG_DONTWAIT if unavailable. In this case, fcntl
+  (or a equivalent) is used to enable non-blocking operations.
+  The flag must be supported in both send and recv operations.
+*/
+#if defined(__linux__)
+#define VIO_USE_DONTWAIT  1
+#define VIO_DONTWAIT      MSG_DONTWAIT
+#else
+#define VIO_DONTWAIT 0
+#endif
+
+
+size_t vio_read(Vio *vio, uchar *buf, size_t size)
+{
+  ssize_t ret;
+  int flags= 0;
   DBUG_ENTER("vio_read");
-  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", sd, (long)buf,
-                      (uint)size));
-  MYSQL_START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_RECV, size);
 
-  /* Ensure nobody uses vio_read_buff and vio_read simultaneously */
+  /* Ensure nobody uses vio_read_buff and vio_read simultaneously. */
   DBUG_ASSERT(vio->read_end == vio->read_pos);
-#ifdef __WIN__
-  r = recv(sd, (char*)buf, size,0);
-#else
-  errno=0;					/* For linux */
-  r = read(sd, buf, size);
-#endif /* __WIN__ */
 
-#ifdef HAVE_PSI_INTERFACE
-  bytes_read= (r != (size_t)-1) ? r : 0;
-#endif
-  MYSQL_END_SOCKET_WAIT(locker, bytes_read);
+  /* If timeout is enabled, do not block if data is unavailable. */
+  if (vio->read_timeout >= 0)
+    flags= VIO_DONTWAIT;
 
-#ifndef DBUG_OFF
-  if (r == (size_t) -1)
+  while ((ret= mysql_socket_recv(vio->mysql_socket, (SOCKBUF_T *)buf, size, flags)) == -1)
   {
-    DBUG_PRINT("vio_error", ("Got error %d during read",errno));
+    int error= socket_errno;
+
+    /* The operation would block? */
+    if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
+      break;
+
+    /* Wait for input data to become available. */
+    if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_READ)))
+      break;
   }
-#endif /* DBUG_OFF */
 
-  DBUG_PRINT("exit", ("%ld", (long) r));
-  DBUG_RETURN(r);
+  DBUG_RETURN(ret);
 }
 
 
@@ -115,124 +171,158 @@ size_t vio_read_buff(Vio *vio, uchar* bu
 #undef VIO_UNBUFFERED_READ_MIN_SIZE
 }
 
+
 my_bool vio_buff_has_data(Vio *vio)
 {
   return (vio->read_pos != vio->read_end);
 }
 
-size_t vio_write(Vio * vio, const uchar* buf, size_t size)
+
+size_t vio_write(Vio *vio, const uchar* buf, size_t size)
 {
-  size_t r;
-  size_t bytes_written= 0;
-  MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
-  my_socket sd= mysql_socket_getfd(vio->mysql_socket);
+  ssize_t ret;
+  int flags= 0;
   DBUG_ENTER("vio_write");
-  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", sd, (long)buf,
-             (uint)size));
-  MYSQL_START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_SEND,
-                          size);
-#ifdef __WIN__
-  r = send(sd, (char *)buf, size,0);
-#else
-  r = write(sd, buf, size);
-#endif /* __WIN__ */
 
-#ifdef HAVE_PSI_INTERFACE
-  bytes_written= (r != (size_t)-1) ? r : 0;
-#endif
-MYSQL_END_SOCKET_WAIT(locker, bytes_written);
+  /* If timeout is enabled, do not block. */
+  if (vio->write_timeout >= 0)
+    flags= VIO_DONTWAIT;
 
-#ifndef DBUG_OFF
-  if (r == (size_t) -1)
+  while ((ret= mysql_socket_send(vio->mysql_socket, (SOCKBUF_T *)buf, size, flags)) == -1)
   {
-    DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno));
+    int error= socket_errno;
+
+    /* The operation would block? */
+    if (error != SOCKET_EAGAIN && error != SOCKET_EWOULDBLOCK)
+      break;
+
+    /* Wait for the output buffer to become writable.*/
+    if ((ret= vio_socket_io_wait(vio, VIO_IO_EVENT_WRITE)))
+      break;
   }
-#endif /* DBUG_OFF */
-  DBUG_PRINT("exit", ("%u", (uint) r));
-  DBUG_RETURN(r);
+
+  DBUG_RETURN(ret);
 }
 
-int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
-		             my_bool *old_mode)
+//WL#4896: Not covered
+static int vio_set_blocking(Vio *vio, my_bool status)
 {
-  int r=0;
-  my_socket sd= mysql_socket_getfd(vio->mysql_socket);
-  DBUG_ENTER("vio_blocking");
+  DBUG_ENTER("vio_set_blocking");
 
-  *old_mode= test(!(vio->fcntl_mode & O_NONBLOCK));
-  DBUG_PRINT("enter", ("set_blocking_mode: %d  old_mode: %d",
-		       (int) set_blocking_mode, (int) *old_mode));
-
-#if !defined(__WIN__)
-#if !defined(NO_FCNTL_NONBLOCK)
-  if (sd >= 0)
-  {
-    int old_fcntl=vio->fcntl_mode;
-    if (set_blocking_mode)
-      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
-    else
-      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
-    if (old_fcntl != vio->fcntl_mode)
-    {
-      r= fcntl(sd, F_SETFL, vio->fcntl_mode);
-      if (r == -1)
-      {
-        DBUG_PRINT("info", ("fcntl failed, errno %d", errno));
-        vio->fcntl_mode= old_fcntl;
-      }
-    }
+#ifdef _WIN32
+  DBUG_ASSERT(vio->type != VIO_TYPE_NAMEDPIPE);
+  DBUG_ASSERT(vio->type != VIO_TYPE_SHARED_MEMORY);
+  {
+    int ret;
+    u_long arg= status ? 0 : 1;
+    ret= ioctlsocket(mysql_socket_getfd(vio->mysql_socket), FIONBIO, &arg);
+    DBUG_RETURN(ret);
   }
 #else
-  r= set_blocking_mode ? 0 : 1;
-#endif /* !defined(NO_FCNTL_NONBLOCK) */
-#else /* !defined(__WIN__) */
-  if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY)
-  {
-    ulong arg;
-    int old_fcntl=vio->fcntl_mode;
-    if (set_blocking_mode)
+  {
+    int flags;
+
+    if ((flags= fcntl(mysql_socket_getfd(vio->mysql_socket), F_GETFL, NULL)) < 0)
+      DBUG_RETURN(-1);
+
+    /*
+      Always set/clear the flag to avoid inheritance issues. This is
+      a issue mainly on Mac OS X Tiger (version 10.4) where although
+      the O_NONBLOCK flag is inherited from the parent socket, the
+      actual non-blocking behavior is not inherited.
+    */
+    if (status)
+      flags&= ~O_NONBLOCK;
+    else
+      flags|= O_NONBLOCK;
+
+    if (fcntl(mysql_socket_getfd(vio->mysql_socket), F_SETFL, flags) == -1)
+      DBUG_RETURN(-1);
+  }
+#endif
+
+  DBUG_RETURN(0);
+}
+
+
+int vio_socket_timeout(Vio *vio,
+                       uint which __attribute__((unused)),
+                       my_bool old_mode __attribute__((unused)))
+{
+  int ret= 0;
+  DBUG_ENTER("vio_socket_timeout");
+
+#if defined(_WIN32)
+  {
+    int optname;
+    DWORD timeout= 0;
+    const char *optval= (const char *) &timeout;
+
+    /*
+      The default socket timeout value is zero, which means an infinite
+      timeout. Values less than 500 milliseconds are interpreted to be of
+      500 milliseconds. Hence, the VIO behavior for zero timeout, which is
+      intended to cause the send or receive operation to fail immediately
+      if no data is available, is not supported on WIN32 and neither is
+      necessary as it's not possible to set the VIO timeout value to zero.
+
+      Assert that the VIO timeout is either positive or set to infinite.
+    */
+    DBUG_ASSERT(which || vio->read_timeout);
+    DBUG_ASSERT(!which || vio->write_timeout);
+
+    if (which)
     {
-      arg = 0;
-      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
+      optname= SO_SNDTIMEO;
+      if (vio->write_timeout > 0)
+        timeout= vio->write_timeout;
     }
     else
     {
-      arg = 1;
-      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
+      optname= SO_RCVTIMEO;
+      if (vio->read_timeout > 0)
+        timeout= vio->read_timeout;
     }
-    if (old_fcntl != vio->fcntl_mode)
-      r = ioctlsocket(sd, FIONBIO, (void*) &arg);
+
+    ret= mysql_socket_setsockopt(vio->mysql_socket, SOL_SOCKET, optname,
+	                             optval, sizeof(timeout));
   }
-  else
-    r=  test(!(vio->fcntl_mode & O_NONBLOCK)) != set_blocking_mode;
-#endif /* !defined(__WIN__) */
-  DBUG_PRINT("exit", ("%d", r));
-  DBUG_RETURN(r);
-}
+#else
+  /*
+    The MSG_DONTWAIT trick is not used with SSL sockets as the send and
+    receive I/O operations are wrapped through SSL-specific functions
+    (SSL_read and SSL_write) which are not equivalent to the standard
+    recv(2) and send(2) used in vio_read() and vio_write(). Hence, the
+    socket blocking mode is changed and vio_io_wait() is used to wait
+    for I/O or timeout.
+  */
+#ifdef VIO_USE_DONTWAIT
+  if (vio->type == VIO_TYPE_SSL)
+#endif
+  {
+    /* Deduce what should be the new blocking mode of the socket. */
+    my_bool new_mode= vio->write_timeout < 0 && vio->read_timeout < 0;
 
-my_bool
-vio_is_blocking(Vio * vio)
-{
-  my_bool r;
-  DBUG_ENTER("vio_is_blocking");
-  r = !(vio->fcntl_mode & O_NONBLOCK);
-  DBUG_PRINT("exit", ("%d", (int) r));
-  DBUG_RETURN(r);
+    /* If necessary, update the blocking mode. */
+    if (new_mode != old_mode)
+      ret= vio_set_blocking(vio, new_mode);
+  }
+#endif
+
+  DBUG_RETURN(ret);
 }
 
 
-int vio_fastsend(Vio* vio __attribute__((unused)))
+int vio_fastsend(Vio * vio __attribute__((unused)))
 {
   int r=0;
-  my_socket sd= mysql_socket_getfd(vio->mysql_socket);
-  MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
   DBUG_ENTER("vio_fastsend");
-  MYSQL_START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_OPT, 0);
 
 #if defined(IPTOS_THROUGHPUT)
   {
     int tos = IPTOS_THROUGHPUT;
-    r= setsockopt(sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos));
+    r= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_IP, IP_TOS,
+	                           (void *)&tos, sizeof(tos));
   }
 #endif                                    /* IPTOS_THROUGHPUT */
   if (!r)
@@ -243,13 +333,11 @@ int vio_fastsend(Vio* vio __attribute__(
     int nodelay = 1;
 #endif
 
-    r= setsockopt(sd, IPPROTO_TCP, TCP_NODELAY,
+    r= mysql_socket_setsockopt(vio->mysql_socket, IPPROTO_TCP, TCP_NODELAY,
                   IF_WIN((const char*), (void*)) &nodelay,
                   sizeof(nodelay));
-  }
-
-  MYSQL_END_SOCKET_WAIT(locker, 0);
 
+  }
   if (r)
   {
     DBUG_PRINT("warning", ("Couldn't set socket option for fast send"));
@@ -263,47 +351,51 @@ int vio_keepalive(Vio* vio, my_bool set_
 {
   int r=0;
   uint opt = 0;
-  MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
-  my_socket sd= mysql_socket_getfd(vio->mysql_socket);
   DBUG_ENTER("vio_keepalive");
-  DBUG_PRINT("enter", ("sd: %d  set_keep_alive: %d", sd, (int)set_keep_alive));
-  MYSQL_START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_OPT, 0);
-
+  DBUG_PRINT("enter", ("sd: %d  set_keep_alive: %d",
+             mysql_socket_getfd(vio->mysql_socket), (int)set_keep_alive));
   if (vio->type != VIO_TYPE_NAMEDPIPE)
   {
     if (set_keep_alive)
       opt = 1;
-    r = setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
+    r = mysql_socket_setsockopt(vio->mysql_socket, SOL_SOCKET, SO_KEEPALIVE,
+	                            (char *)&opt, sizeof(opt));
   }
-
-  MYSQL_END_SOCKET_WAIT(locker, 0);
   DBUG_RETURN(r);
 }
 
 
+/**
+  Indicate whether a I/O operation must be retried later.
+
+  @param vio  A VIO object
+
+  @return Whether a I/O operation should be deferred.
+  @retval TRUE    Temporary failure, retry operation.
+  @retval FALSE   Indeterminate failure.
+*/
+
 my_bool
-vio_should_retry(Vio * vio)
+vio_should_retry(Vio *vio)
 {
-  int en = socket_errno;
-  /*
-    man 2 read write
-      EAGAIN or EWOULDBLOCK when a socket is a non-blocking mode means
-      that the read/write would block.
-    man 7 socket
-      EAGAIN or EWOULDBLOCK when a socket is in a blocking mode means
-      that the corresponding receiving or sending timeout was reached.
-  */
-  return  en == SOCKET_EINTR ||
-          (!vio_is_blocking(vio) &&
-            (en == SOCKET_EAGAIN || en == SOCKET_EWOULDBLOCK));
+  return (vio_errno(vio) == SOCKET_EINTR);
 }
 
 
-my_bool vio_was_interrupted(Vio *vio __attribute__((unused)))
+/**
+  Indicate whether a I/O operation timed out.
+
+  @param vio  A VIO object
+
+  @return Whether a I/O operation timed out.
+  @retval TRUE    Operation timed out.
+  @retval FALSE   Not a timeout failure.
+*/
+
+my_bool
+vio_was_timeout(Vio *vio)
 {
-  int en= socket_errno;
-  return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
-	  en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
+  return (vio_errno(vio) == SOCKET_ETIMEDOUT);
 }
 
 
@@ -317,8 +409,8 @@ int vio_close(Vio * vio)
     DBUG_ASSERT(vio->type ==  VIO_TYPE_TCPIP ||
       vio->type == VIO_TYPE_SOCKET ||
       vio->type == VIO_TYPE_SSL);
-    DBUG_ASSERT(mysql_socket_getfd(vio->mysql_socket) >= 0);
 
+    DBUG_ASSERT(mysql_socket_getfd(vio->mysql_socket) >= 0);
     if (mysql_socket_shutdown(vio->mysql_socket, SHUT_RDWR))
       r= -1;
     if (mysql_socket_close(vio->mysql_socket))
@@ -345,7 +437,7 @@ enum enum_vio_type vio_type(Vio* vio)
   return vio->type;
 }
 
-my_socket vio_getfd(Vio *vio)
+my_socket vio_getfd(Vio* vio)
 {
   return mysql_socket_getfd(vio->mysql_socket);
 }
@@ -487,9 +579,9 @@ my_bool vio_get_normalized_ip_string(con
 my_bool vio_peer_addr(Vio *vio, char *ip_buffer, uint16 *port,
                       size_t ip_buffer_size)
 {
-  my_socket sd= mysql_socket_getfd(vio->mysql_socket);
   DBUG_ENTER("vio_peer_addr");
-  DBUG_PRINT("enter", ("Client socked fd: %d", (int)sd));
+  DBUG_PRINT("enter", ("Client socked fd: %d",
+            (int)mysql_socket_getfd(vio->mysql_socket)));
 
   if (vio->localhost)
   {
@@ -520,7 +612,7 @@ my_bool vio_peer_addr(Vio *vio, char *ip
 
     /* Get sockaddr by socked fd. */
 
-    err_code= getpeername(sd, addr, &addr_length);
+    err_code= mysql_socket_getpeername(vio->mysql_socket, addr, &addr_length);
 
     if (err_code)
     {
@@ -558,58 +650,6 @@ my_bool vio_peer_addr(Vio *vio, char *ip
 
 
 /**
-  Indicate whether there is data to read on a given socket.
-
-  @note An exceptional condition event and/or errors are
-        interpreted as if there is data to read.
-
-  @param sd       A connected socket.
-  @param timeout  Maximum time in seconds to poll.
-
-  @retval FALSE   There is data to read.
-  @retval TRUE    There is no data to read.
-*/
-
-static my_bool socket_poll_read(my_socket sd, uint timeout)
-{
-#ifdef __WIN__
-  int res;
-  my_socket fd= sd;
-  fd_set readfds, errorfds;
-  struct timeval tm;
-  DBUG_ENTER("socket_poll_read");
-  tm.tv_sec= timeout;
-  tm.tv_usec= 0;
-  FD_ZERO(&readfds);
-  FD_ZERO(&errorfds);
-  FD_SET(fd, &readfds);
-  FD_SET(fd, &errorfds);
-  /* The first argument is ignored on Windows, so a conversion to int is OK */
-  if ((res= select((int) fd, &readfds, NULL, &errorfds, &tm) <= 0))
-  {
-    DBUG_RETURN(res < 0 ? 0 : 1);
-  }
-  res= FD_ISSET(fd, &readfds) || FD_ISSET(fd, &errorfds);
-  DBUG_RETURN(!res);
-#elif defined(HAVE_POLL)
-  struct pollfd fds;
-  int res;
-  DBUG_ENTER("socket_poll_read");
-  fds.fd=sd;
-  fds.events=POLLIN;
-  fds.revents=0;
-  if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
-  {
-    DBUG_RETURN(res < 0 ? 0 : 1);		/* Don't return 1 on errors */
-  }
-  DBUG_RETURN(fds.revents & (POLLIN | POLLERR | POLLHUP) ? 0 : 1);
-#else
-  return 0;
-#endif
-}
-
-
-/**
   Retrieve the amount of data that can be read from a socket.
 
   @param vio          A VIO object.
@@ -618,7 +658,7 @@ static my_bool socket_poll_read(my_socke
   @retval FALSE   Success.
   @retval TRUE    Failure.
 */
-
+// WL#4896: Not covered
 static my_bool socket_peek_read(Vio *vio, uint *bytes)
 {
   my_socket sd= mysql_socket_getfd(vio->mysql_socket);
@@ -644,459 +684,354 @@ static my_bool socket_peek_read(Vio *vio
 #endif
 }
 
+#ifndef _WIN32
 
 /**
-  Indicate whether there is data to read on a given socket.
-
-  @remark Errors are interpreted as if there is data to read.
-
-  @param sd       A connected socket.
-  @param timeout  Maximum time in seconds to wait.
-
-  @retval FALSE   There is data (or EOF) to read. Also FALSE if error.
-  @retval TRUE    There is _NO_ data to read or timed out.
+  Set of event flags grouped by operations.
 */
 
-my_bool vio_poll_read(Vio *vio, uint timeout)
-{
-  my_socket sd= mysql_socket_getfd(vio->mysql_socket);
-  DBUG_ENTER("vio_poll_read");
-#ifdef HAVE_OPENSSL
-  if (vio->type == VIO_TYPE_SSL)
-    sd= SSL_get_fd((SSL*) vio->ssl_arg);
+/*
+  Linux specific flag used to detect connection shutdown. The flag is
+  also used for half-closed notification, which here is interpreted as
+  if there is data available to be read from the socket.
+*/
+#ifndef POLLRDHUP
+#define POLLRDHUP 0
 #endif
-  DBUG_RETURN(socket_poll_read(sd, timeout));
-}
 
+/* Data may be read. */
+#define MY_POLL_SET_IN      (POLLIN | POLLPRI)
+/* Data may be written. */
+#define MY_POLL_SET_OUT     (POLLOUT)
+/* An error or hangup. */
+#define MY_POLL_SET_ERR     (POLLERR | POLLHUP | POLLNVAL)
+
+#endif
 
 /**
-  Determine if the endpoint of a connection is still available.
+  Wait for an I/O event on a VIO socket.
 
-  @remark The socket is assumed to be disconnected if an EOF
-          condition is encountered.
+  @param vio      VIO object representing a connected socket.
+  @param event    The type of I/O event to wait for.
+  @param timeout  Interval (in milliseconds) to wait for an I/O event.
+                  A negative timeout value means an infinite timeout.
 
-  @param vio      The VIO object.
+  @remark sock_errno is set to SOCKET_ETIMEDOUT on timeout.
 
-  @retval TRUE    EOF condition not found.
-  @retval FALSE   EOF condition is signaled.
+  @return A three-state value which indicates the operation status.
+  @retval -1  Failure, socket_errno indicates the error.
+  @retval  0  The wait has timed out.
+  @retval  1  The requested I/O event has occurred.
 */
 
-my_bool vio_is_connected(Vio *vio)
+#ifndef _WIN32
+//WL#4896: Use IDLE
+int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout)
 {
-  uint bytes= 0;
-  DBUG_ENTER("vio_is_connected");
+  int ret;
+  short revents= 0;
+  struct pollfd pfd;
+  my_socket sd= mysql_socket_getfd(vio->mysql_socket);
+  MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
+  DBUG_ENTER("vio_io_wait");
 
-  /* In the presence of errors the socket is assumed to be connected. */
+  memset(&pfd, 0, sizeof(pfd));
 
-  /*
-    The first step of detecting a EOF condition is veryfing
-    whether there is data to read. Data in this case would
-    be the EOF.
-  */
-  if (vio_poll_read(vio, 0))
-    DBUG_RETURN(TRUE);
+  pfd.fd= sd;
 
   /*
-    The second step is read() or recv() from the socket returning
-    0 (EOF). Unfortunelly, it's not possible to call read directly
-    as we could inadvertently read meaningful connection data.
-    Simulate a read by retrieving the number of bytes available to
-    read -- 0 meaning EOF.
+    Set the poll bitmask describing the type of events.
+    The error flags are only valid in the revents bitmask.
   */
-  if (socket_peek_read(vio, &bytes))
-    DBUG_RETURN(TRUE);
-
-#ifdef HAVE_OPENSSL
-  /* There might be buffered data at the SSL layer. */
-  if (!bytes && vio->type == VIO_TYPE_SSL)
-    bytes= SSL_pending((SSL*) vio->ssl_arg);
-#endif
-
-  DBUG_RETURN(bytes ? TRUE : FALSE);
-}
-
-
-void vio_timeout(Vio *vio, uint which, uint timeout)
-{
-my_socket sd= mysql_socket_getfd(vio->mysql_socket);
-#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
-  int r;
-  DBUG_ENTER("vio_timeout");
+  switch (event)
   {
-#ifdef __WIN__
-  /* Windows expects time in milliseconds as int */
-  int wait_timeout= (int) timeout * 1000;
-#else
-  /* POSIX specifies time as struct timeval. */
-  struct timeval wait_timeout;
-  wait_timeout.tv_sec= timeout;
-  wait_timeout.tv_usec= 0;
-#endif
-
-  r= setsockopt(sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO,
-                IF_WIN((const char*), (const void*))&wait_timeout,
-                sizeof(wait_timeout));
-
+  case VIO_IO_EVENT_READ:
+    pfd.events= MY_POLL_SET_IN;
+    revents= MY_POLL_SET_IN | MY_POLL_SET_ERR | POLLRDHUP;
+    break;
+  case VIO_IO_EVENT_WRITE:
+  case VIO_IO_EVENT_CONNECT:
+    pfd.events= MY_POLL_SET_OUT;
+    revents= MY_POLL_SET_OUT | MY_POLL_SET_ERR;
+    break;
   }
 
-  if (r != 0)
-    DBUG_PRINT("error", ("setsockopt failed: %d, errno: %d", r, socket_errno));
-
-  DBUG_VOID_RETURN;
-#else
-/*
-  Platforms not suporting setting of socket timeout should either use
-  thr_alarm or just run without read/write timeout(s)
-*/
-#endif
-}
-
-
-#ifdef __WIN__
-
-/*
-  Finish pending IO on pipe. Honor wait timeout
-*/
-static size_t pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_ms)
-{
-  DWORD length;
-  DWORD ret;
-
-  DBUG_ENTER("pipe_complete_io");
+  MYSQL_START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_SELECT, 0);
 
-  ret= WaitForSingleObject(vio->pipe_overlapped.hEvent, timeout_ms);
   /*
-    WaitForSingleObjects will normally return WAIT_OBJECT_O (success, IO completed)
-    or WAIT_TIMEOUT.
+    Wait for the I/O event and return early in case of
+    error or timeout.
   */
-  if(ret != WAIT_OBJECT_0)
-  {
-    CancelIo(vio->hPipe);
-    DBUG_PRINT("error",("WaitForSingleObject() returned  %d", ret));
-    DBUG_RETURN((size_t)-1);
-  }
-
-  if (!GetOverlappedResult(vio->hPipe,&(vio->pipe_overlapped),&length, FALSE))
+  switch ((ret= poll(&pfd, 1, timeout)))
   {
-    DBUG_PRINT("error",("GetOverlappedResult() returned last error  %d",
-      GetLastError()));
-    DBUG_RETURN((size_t)-1);
+  case -1:
+    /* On error, -1 is returned. */
+    break;
+  case 0:
+    /*
+      Set errno to indicate a timeout error.
+      (This is not compiled in on WIN32.)
+    */
+    errno= SOCKET_ETIMEDOUT;
+    break;
+  default:
+    /* Ensure that the requested I/O event has completed. */
+    DBUG_ASSERT(pfd.revents & revents);
+    break;
   }
 
-  DBUG_RETURN(length);
+  MYSQL_END_SOCKET_WAIT(locker, 0);
+  DBUG_RETURN(ret);
 }
 
+#else
 
-size_t vio_read_pipe(Vio * vio, uchar *buf, size_t size)
+int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout)
 {
-  DWORD bytes_read;
-  size_t retval;
-  DBUG_ENTER("vio_read_pipe");
-  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u",
-             mysql_socket_getfd(vio->mysql_socket),(long)buf, (uint)size));
+  int ret;
+  struct timeval tm;
+  my_socket fd= mysql_socket_getfd(vio->mysql_socket);
+  fd_set readfds, writefds, exceptfds;
+  MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */
+  DBUG_ENTER("vio_io_wait");
 
-  if (ReadFile(vio->hPipe, buf, (DWORD)size, &bytes_read,
-      &(vio->pipe_overlapped)))
+  /* Convert the timeout, in milliseconds, to seconds and microseconds. */
+  if (timeout >= 0)
   {
-    retval= bytes_read;
+    tm.tv_sec= timeout / 1000;
+    tm.tv_usec= (timeout % 1000) * 1000;
   }
-  else
-  {
-    if (GetLastError() != ERROR_IO_PENDING)
-    {
-      DBUG_PRINT("error",("ReadFile() returned last error %d",
-                 GetLastError()));
-      DBUG_RETURN((size_t)-1);
-    }
-    retval= pipe_complete_io(vio, buf, size,vio->read_timeout_ms);
-  }
-
-  DBUG_PRINT("exit", ("%lld", (longlong)retval));
-  DBUG_RETURN(retval);
-}
 
+  FD_ZERO(&readfds);
+  FD_ZERO(&writefds);
+  FD_ZERO(&exceptfds);
 
-size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size)
-{
-  DWORD bytes_written;
-  size_t retval;
-  DBUG_ENTER("vio_write_pipe");
-  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u",
-             mysql_socket_getfd(vio->mysql_socket), (long)buf, (uint)size));
+  /* Always receive notification of exceptions. */
+  FD_SET(fd, &exceptfds);
 
-  if (WriteFile(vio->hPipe, buf, (DWORD)size, &bytes_written,
-      &(vio->pipe_overlapped)))
+  switch (event)
   {
-    retval= bytes_written;
-  }
-  else
-  {
-    if (GetLastError() != ERROR_IO_PENDING)
-    {
-      DBUG_PRINT("vio_error",("WriteFile() returned last error %d",
-        GetLastError()));
-      DBUG_RETURN((size_t)-1);
-    }
-    retval= pipe_complete_io(vio, (char *)buf, size, vio->write_timeout_ms);
+  case VIO_IO_EVENT_READ:
+    /* Readiness for reading. */
+    FD_SET(fd, &readfds);
+    break;
+  case VIO_IO_EVENT_WRITE:
+  case VIO_IO_EVENT_CONNECT:
+    /* Readiness for writing. */
+    FD_SET(fd, &writefds);
+    break;
   }
 
-  DBUG_PRINT("exit", ("%lld", (longlong)retval));
-  DBUG_RETURN(retval);
-}
-
+  MYSQL_START_SOCKET_WAIT(locker, &state, vio->mysql_socket, PSI_SOCKET_SELECT, 0);
 
-my_bool vio_is_connected_pipe(Vio *vio)
-{
-  if (PeekNamedPipe(vio->hPipe, NULL, 0, NULL, NULL, NULL))
-    return TRUE;
-  else
-    return (GetLastError() != ERROR_BROKEN_PIPE);
-}
+  /* The first argument is ignored on Windows. */
+  ret= select(0, &readfds, &writefds, &exceptfds, (timeout >= 0) ? &tm : NULL);
 
+  MYSQL_END_SOCKET_WAIT(locker, 0);
 
-int vio_close_pipe(Vio * vio)
-{
-  int r;
-  DBUG_ENTER("vio_close_pipe");
+  /* Set error code to indicate a timeout error. */
+  if (ret == 0)
+    WSASetLastError(SOCKET_ETIMEDOUT);
+
+  /* Error or timeout? */
+  if (ret <= 0)
+    DBUG_RETURN(ret);
 
-  CancelIo(vio->hPipe);
-  CloseHandle(vio->pipe_overlapped.hEvent);
-  DisconnectNamedPipe(vio->hPipe);
-  r= CloseHandle(vio->hPipe);
-  if (r)
+  /* The requested I/O event is ready? */
+  switch (event)
   {
-    DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError()));
-    /* FIXME: error handling (not critical for MySQL) */
+  case VIO_IO_EVENT_READ:
+    ret= test(FD_ISSET(fd, &readfds));
+    break;
+  case VIO_IO_EVENT_WRITE:
+  case VIO_IO_EVENT_CONNECT:
+    ret= test(FD_ISSET(fd, &writefds));
+    break;
   }
-  vio->type= VIO_CLOSED;
-  vio->mysql_socket= MYSQL_INVALID_SOCKET;
-  DBUG_RETURN(r);
-}
 
+  /* Error conditions pending? */
+  ret|= test(FD_ISSET(fd, &exceptfds));
 
-void vio_win32_timeout(Vio *vio, uint which , uint timeout_sec)
-{
-    DWORD timeout_ms;
-    /*
-      Windows is measuring timeouts in milliseconds. Check for possible int
-      overflow.
-    */
-    if (timeout_sec > UINT_MAX/1000)
-      timeout_ms= INFINITE;
-    else
-      timeout_ms= timeout_sec * 1000;
+  /* Not a timeout, ensure that a condition was met. */
+  DBUG_ASSERT(ret);
 
-    /* which == 1 means "write", which == 0 means "read".*/
-    if(which)
-      vio->write_timeout_ms= timeout_ms;
-    else
-      vio->read_timeout_ms= timeout_ms;
+  DBUG_RETURN(ret);
 }
 
+#endif /* _WIN32 */
 
-#ifdef HAVE_SMEM
-
-size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size)
-{
-  size_t length;
-  size_t remain_local;
-  char *current_position;
-  HANDLE events[2];
 
-  DBUG_ENTER("vio_read_shared_memory");
-  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %d",
-             mysql_socket_getfd(vio->mysql_socket), (long)buf, size));
+/**
+  Connect to a peer address.
 
-  remain_local = size;
-  current_position=buf;
+  @param vio       A VIO object.
+  @param addr      Socket address containing the peer address.
+  @param len       Length of socket address.
+  @param timeout   Interval (in milliseconds) to wait until a
+                   connection is established.
 
-  events[0]= vio->event_server_wrote;
-  events[1]= vio->event_conn_closed;
+  @retval FALSE   A connection was successfully established.
+  @retval TRUE    A fatal error. See socket_errno.
+*/
 
-  do
-  {
-    if (vio->shared_memory_remain == 0)
-    {
-      /*
-        WaitForMultipleObjects can return next values:
-         WAIT_OBJECT_0+0 - event from vio->event_server_wrote
-         WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read
-		           anything
-         WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail.  We can't read anything
-      */
-      if (WaitForMultipleObjects(array_elements(events), events, FALSE,
-                                 vio->read_timeout_ms) != WAIT_OBJECT_0)
-      {
-        DBUG_RETURN(-1);
-      };
+my_bool
+vio_socket_connect(Vio *vio, struct sockaddr *addr, socklen_t len, int timeout)
+{
+  int ret, wait;
+  DBUG_ENTER("vio_socket_connect");
 
-      vio->shared_memory_pos = vio->handle_map;
-      vio->shared_memory_remain = uint4korr((ulong*)vio->shared_memory_pos);
-      vio->shared_memory_pos+=4;
-    }
+  /* Only for socket-based transport types. */
+  DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP);
 
-    length = size;
+  /* If timeout is not infinite, set socket to non-blocking mode. */
+  if ((timeout > -1) && vio_set_blocking(vio, FALSE))
+    DBUG_RETURN(TRUE);
 
-    if (vio->shared_memory_remain < length)
-       length = vio->shared_memory_remain;
-    if (length > remain_local)
-       length = remain_local;
+  /* Initiate the connection. */
+  ret= mysql_socket_connect(vio->mysql_socket, addr, len);
 
-    memcpy(current_position,vio->shared_memory_pos,length);
+#ifdef _WIN32
+  wait= (ret == SOCKET_ERROR) &&
+        (WSAGetLastError() == WSAEINPROGRESS ||
+         WSAGetLastError() == WSAEWOULDBLOCK);
+#else
+  wait= (ret == -1) && (errno == EINPROGRESS || errno == EALREADY);
+#endif
 
-    vio->shared_memory_remain-=length;
-    vio->shared_memory_pos+=length;
-    current_position+=length;
-    remain_local-=length;
+  /*
+    The connection is in progress. The vio_io_wait() call can be used
+    to wait up to a specified period of time for the connection to
+    succeed.
+
+    If vio_io_wait() returns 0 (after waiting however many seconds),
+    the socket never became writable (host is probably unreachable.)
+    Otherwise, if vio_io_wait() returns 1, then one of two conditions
+    exist:
+
+    1. An error occurred. Use getsockopt() to check for this.
+    2. The connection was set up successfully: getsockopt() will
+       return 0 as an error.
+  */
+  if (wait && (vio_io_wait(vio, VIO_IO_EVENT_CONNECT, timeout) == 1))
+  {
+    int error;
+    IF_WIN(int, socklen_t) optlen= sizeof(error);
+    IF_WIN(char, void) *optval= (IF_WIN(char, void) *) &error;
 
-    if (!vio->shared_memory_remain)
+    /*
+      At this point, we know that something happened on the socket.
+      But this does not means that everything is alright. The connect
+      might have failed. We need to retrieve the error code from the
+      socket layer. We must return success only if we are sure that
+      it was really a success. Otherwise we might prevent the caller
+      from trying another address to connect to.
+    */
+    if (!(ret= mysql_socket_getsockopt(vio->mysql_socket, SOL_SOCKET, SO_ERROR, optval, &optlen)))
     {
-      if (!SetEvent(vio->event_client_read))
-        DBUG_RETURN(-1);
+#ifdef _WIN32
+      WSASetLastError(error);
+#else
+      errno= error;
+#endif
+      ret= test(error);
     }
-  } while (remain_local);
-  length = size;
+  }
 
-  DBUG_PRINT("exit", ("%lu", (ulong) length));
-  DBUG_RETURN(length);
+  /* If necessary, restore the blocking mode, but only if connect succeeded. */
+  if ((timeout > -1) && (ret == 0))
+  {
+    if (vio_set_blocking(vio, TRUE))
+      DBUG_RETURN(TRUE);
+  }
+
+  DBUG_RETURN(test(ret));
 }
 
 
-size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size)
-{
-  size_t length, remain, sz;
-  HANDLE pos;
-  const uchar *current_position;
-  HANDLE events[2];
+/**
+  Determine if the endpoint of a connection is still available.
 
-  DBUG_ENTER("vio_write_shared_memory");
-  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %d",
-             mysql_socket_getfd(vio->mysql_socket), (long)buf, size));
+  @remark The socket is assumed to be disconnected if an EOF
+          condition is encountered.
 
-  remain = size;
-  current_position = buf;
+  @param vio      The VIO object.
 
-  events[0]= vio->event_server_read;
-  events[1]= vio->event_conn_closed;
+  @retval TRUE    EOF condition not found.
+  @retval FALSE   EOF condition is signaled.
+*/
 
-  while (remain != 0)
-  {
-    if (WaitForMultipleObjects(array_elements(events), events, FALSE,
-                               vio->write_timeout_ms) != WAIT_OBJECT_0)
-    {
-      DBUG_RETURN((size_t) -1);
-    }
+my_bool vio_is_connected(Vio *vio)
+{
+  uint bytes= 0;
+  DBUG_ENTER("vio_is_connected");
 
-    sz= (remain > shared_memory_buffer_length ? shared_memory_buffer_length :
-         remain);
+  /*
+    The first step of detecting an EOF condition is verifying
+    whether there is data to read. Data in this case would be
+    the EOF. An exceptional condition event and/or errors are
+    interpreted as if there is data to read.
+  */
+  if (!vio_io_wait(vio, VIO_IO_EVENT_READ, 0))
+    DBUG_RETURN(TRUE);
 
-    int4store(vio->handle_map,sz);
-    pos = vio->handle_map + 4;
-    memcpy(pos,current_position,sz);
-    remain-=sz;
-    current_position+=sz;
-    if (!SetEvent(vio->event_client_wrote))
-      DBUG_RETURN((size_t) -1);
+  /*
+    The second step is read() or recv() from the socket returning
+    0 (EOF). Unfortunately, it's not possible to call read directly
+    as we could inadvertently read meaningful connection data.
+    Simulate a read by retrieving the number of bytes available to
+    read -- 0 meaning EOF. In the presence of unrecoverable errors,
+    the socket is assumed to be disconnected.
+  */
+  while (socket_peek_read(vio, &bytes))
+  {
+    if (socket_errno != SOCKET_EINTR)
+      DBUG_RETURN(FALSE);
   }
-  length = size;
-
-  DBUG_PRINT("exit", ("%lu", (ulong) length));
-  DBUG_RETURN(length);
-}
 
+#ifdef HAVE_OPENSSL
+  /* There might be buffered data at the SSL layer. */
+  if (!bytes && vio->type == VIO_TYPE_SSL)
+    bytes= SSL_pending((SSL*) vio->ssl_arg);
+#endif
 
-my_bool vio_is_connected_shared_memory(Vio *vio)
-{
-  return (WaitForSingleObject(vio->event_conn_closed, 0) != WAIT_OBJECT_0);
+  DBUG_RETURN(bytes ? TRUE : FALSE);
 }
 
+#ifndef DBUG_OFF
 
 /**
- Close shared memory and DBUG_PRINT any errors that happen on closing.
- @return Zero if all closing functions succeed, and nonzero otherwise.
-*/
-int vio_close_shared_memory(Vio * vio)
-{
-  int error_count= 0;
-  DBUG_ENTER("vio_close_shared_memory");
-  if (vio->type != VIO_CLOSED)
-  {
-    /*
-      Set event_conn_closed for notification of both client and server that
-      connection is closed
-    */
-    SetEvent(vio->event_conn_closed);
-    /*
-      Close all handlers. UnmapViewOfFile and CloseHandle return non-zero
-      result if they are success.
-    */
-    if (UnmapViewOfFile(vio->handle_map) == 0)
-    {
-      error_count++;
-      DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed"));
-    }
-    if (CloseHandle(vio->event_server_wrote) == 0)
-    {
-      error_count++;
-      DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed"));
-    }
-    if (CloseHandle(vio->event_server_read) == 0)
-    {
-      error_count++;
-      DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed"));
-    }
-    if (CloseHandle(vio->event_client_wrote) == 0)
-    {
-      error_count++;
-      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed"));
-    }
-    if (CloseHandle(vio->event_client_read) == 0)
-    {
-      error_count++;
-      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed"));
-    }
-    if (CloseHandle(vio->handle_file_map) == 0)
-    {
-      error_count++;
-      DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed"));
-    }
-    if (CloseHandle(vio->event_conn_closed) == 0)
-    {
-      error_count++;
-      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed"));
-    }
-  }
-  vio->type= VIO_CLOSED;
-  vio->mysql_socket= MYSQL_INVALID_SOCKET;
-  DBUG_RETURN(error_count);
-}
-#endif /* HAVE_SMEM */
-#endif /* __WIN__ */
+  Number of bytes in the read or socket buffer
 
+  @remark An EOF condition might count as one readable byte.
 
-/**
-  Number of bytes in the read buffer.
-
-  @return number of bytes in the read buffer or < 0 if error.
+  @return number of bytes in one of the buffers or < 0 if error.
 */
 
 ssize_t vio_pending(Vio *vio)
 {
-#ifdef HAVE_OPENSSL
-  SSL *ssl= (SSL*) vio->ssl_arg;
-#endif
+  uint bytes= 0;
 
+  /* Data pending on the read buffer. */
   if (vio->read_pos < vio->read_end)
     return vio->read_end - vio->read_pos;
 
-#ifdef HAVE_OPENSSL
-  if (ssl)
-    return SSL_pending(ssl);
-#endif
+  /* Skip non-socket based transport types. */
+  if (vio->type == VIO_TYPE_TCPIP || vio->type == VIO_TYPE_SOCKET)
+  {
+    /* Obtain number of readable bytes in the socket buffer. */
+    if (socket_peek_read(vio, &bytes))
+      return -1;
+  }
 
-  return 0;
+  /*
+    SSL not checked due to a yaSSL bug in SSL_pending that
+    causes it to attempt to read from the socket.
+  */
+
+  return (ssize_t) bytes;
 }
 
+#endif
 
 /**
   Checks if the error code, returned by vio_getnameinfo(), means it was the

=== modified file 'vio/viossl.c'
--- a/vio/viossl.c	2011-05-27 15:46:36 +0000
+++ b/vio/viossl.c	2011-06-06 19:57:05 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -11,7 +11,7 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
 /*
   Note that we can't have assertion on file descriptors;  The reason for
@@ -54,40 +54,161 @@ report_errors(SSL* ssl)
 #endif
 
 
-size_t vio_ssl_read(Vio *vio, uchar* buf, size_t size)
+/**
+  Obtain the equivalent system error status for the last SSL I/O operation.
+
+  @param ssl_error  The result code of the failed TLS/SSL I/O operation.
+*/
+
+static void ssl_set_sys_error(int ssl_error)
 {
-  size_t r;
-  DBUG_ENTER("vio_ssl_read");
-  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u  ssl: 0x%lx",
-		         mysql_socket_getfd(vio->mysql_socket), (long) buf, (uint) size,
-             (long) vio->ssl_arg));
+  int error= 0;
 
-  r= SSL_read((SSL*) vio->ssl_arg, buf, size);
-#ifndef DBUG_OFF
-  if (r == (size_t) -1)
-    report_errors((SSL*) vio->ssl_arg);
+  switch (ssl_error)
+  {
+  case SSL_ERROR_ZERO_RETURN:
+    error= SOCKET_ECONNRESET;
+    break;
+  case SSL_ERROR_WANT_READ:
+  case SSL_ERROR_WANT_WRITE:
+#ifdef SSL_ERROR_WANT_CONNECT
+  case SSL_ERROR_WANT_CONNECT:
+#endif
+#ifdef SSL_ERROR_WANT_ACCEPT
+  case SSL_ERROR_WANT_ACCEPT:
+#endif
+    error= SOCKET_EWOULDBLOCK;
+    break;
+  case SSL_ERROR_SSL:
+    /* Protocol error. */
+#ifdef EPROTO
+    error= EPROTO;
+#else
+    error= SOCKET_ECONNRESET;
+#endif
+    break;
+  case SSL_ERROR_SYSCALL:
+  case SSL_ERROR_NONE:
+  default:
+    break;
+  };
+
+  /* Set error status to a equivalent of the SSL error. */
+  if (error)
+  {
+#ifdef _WIN32
+    WSASetLastError(error);
+#else
+    errno= error;
 #endif
-  DBUG_PRINT("exit", ("%u", (uint) r));
-  DBUG_RETURN(r);
+  }
 }
 
 
-size_t vio_ssl_write(Vio *vio, const uchar* buf, size_t size)
+/**
+  Indicate whether a SSL I/O operation must be retried later.
+
+  @param vio  VIO object representing a SSL connection.
+  @param ret  Value returned by a SSL I/O function.
+  @param event[out] The type of I/O event to wait/retry.
+
+  @return Whether a SSL I/O operation should be deferred.
+  @retval TRUE    Temporary failure, retry operation.
+  @retval FALSE   Indeterminate failure.
+*/
+
+static my_bool ssl_should_retry(Vio *vio, int ret, enum enum_vio_io_event *event)
 {
-  size_t r;
-  DBUG_ENTER("vio_ssl_write");
-  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u",
-             mysql_socket_getfd(vio->mysql_socket), (long) buf, (uint) size));
+  int ssl_error;
+  SSL *ssl= vio->ssl_arg;
+  my_bool should_retry= TRUE;
 
-  r= SSL_write((SSL*) vio->ssl_arg, buf, size);
+  /* Retrieve the result for the SSL I/O operation. */
+  ssl_error= SSL_get_error(ssl, ret);
+
+  /* Retrieve the result for the SSL I/O operation. */
+  switch (ssl_error)
+  {
+  case SSL_ERROR_WANT_READ:
+    *event= VIO_IO_EVENT_READ;
+    break;
+  case SSL_ERROR_WANT_WRITE:
+    *event= VIO_IO_EVENT_WRITE;
+    break;
+  default:
 #ifndef DBUG_OFF
-  if (r == (size_t) -1)
-    report_errors((SSL*) vio->ssl_arg);
+    report_errors(ssl);
 #endif
-  DBUG_PRINT("exit", ("%u", (uint) r));
-  DBUG_RETURN(r);
+    should_retry= FALSE;
+    ssl_set_sys_error(ssl_error);
+    break;
+  }
+
+  return should_retry;
+}
+
+
+size_t vio_ssl_read(Vio *vio, uchar *buf, size_t size)
+{
+  int ret;
+  SSL *ssl= vio->ssl_arg;
+  DBUG_ENTER("vio_ssl_read");
+
+  while ((ret= SSL_read(ssl, buf, size)) < 0)
+  {
+    enum enum_vio_io_event event;
+
+    /* Process the SSL I/O error. */
+    if (!ssl_should_retry(vio, ret, &event))
+      break;
+
+    /* Attempt to wait for an I/O event. */
+    if (vio_socket_io_wait(vio, event))
+      break;
+  }
+
+  DBUG_RETURN(ret < 0 ? -1 : ret);
+}
+
+
+size_t vio_ssl_write(Vio *vio, const uchar *buf, size_t size)
+{
+  int ret;
+  SSL *ssl= vio->ssl_arg;
+  DBUG_ENTER("vio_ssl_write");
+
+  while ((ret= SSL_write(ssl, buf, size)) < 0)
+  {
+    enum enum_vio_io_event event;
+
+    /* Process the SSL I/O error. */
+    if (!ssl_should_retry(vio, ret, &event))
+      break;
+
+    /* Attempt to wait for an I/O event. */
+    if (vio_socket_io_wait(vio, event))
+      break;
+  }
+
+  DBUG_RETURN(ret < 0 ? -1 : ret);
 }
 
+#ifdef HAVE_YASSL
+
+/* Emulate a blocking recv() call with vio_read(). */
+static long yassl_recv(void *ptr, void *buf, size_t len)
+{
+  return vio_read(ptr, buf, len);
+}
+
+
+/* Emulate a blocking send() call with vio_write(). */
+static long yassl_send(void *ptr, const void *buf, size_t len)
+{
+  return vio_write(ptr, buf, len);
+}
+
+#endif
 
 int vio_ssl_close(Vio *vio)
 {
@@ -146,27 +267,60 @@ void vio_ssl_delete(Vio *vio)
 }
 
 
+/** SSL handshake handler. */
+typedef int (*ssl_handshake_func_t)(SSL*);
+
+
+/**
+  Loop and wait until a SSL handshake is completed.
+
+  @param vio    VIO object representing a SSL connection.
+  @param ssl    SSL structure for the connection.
+  @param func   SSL handshake handler.
+
+  @return Return value is 1 on success.
+*/
+
+static int ssl_handshake_loop(Vio *vio, SSL *ssl, ssl_handshake_func_t func)
+{
+  int ret;
+
+  vio->ssl_arg= ssl;
+
+  /* Initiate the SSL handshake. */
+  while ((ret= func(ssl)) < 1)
+  {
+    enum enum_vio_io_event event;
+
+    /* Process the SSL I/O error. */
+    if (!ssl_should_retry(vio, ret, &event))
+      break;
+
+    /* Wait for I/O so that the handshake can proceed. */
+    if (vio_socket_io_wait(vio, event))
+      break;
+  }
+
+  vio->ssl_arg= NULL;
+
+  return ret;
+}
+
+
 static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
-                  int (*connect_accept_func)(SSL*), unsigned long *errptr)
+                  ssl_handshake_func_t func, unsigned long *errptr)
 {
   int r;
   SSL *ssl;
-  my_bool unused;
-  my_bool was_blocking;
   my_socket sd= mysql_socket_getfd(vio->mysql_socket);
-
   DBUG_ENTER("ssl_do");
   DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d  ctx: 0x%lx",
                        (long) ptr, sd, (long) ptr->ssl_context));
 
-  /* Set socket to blocking if not already set */
-  vio_blocking(vio, 1, &was_blocking);
-
   if (!(ssl= SSL_new(ptr->ssl_context)))
   {
     DBUG_PRINT("error", ("SSL_new failure"));
     *errptr= ERR_get_error();
-    vio_blocking(vio, was_blocking, &unused);
     DBUG_RETURN(1);
   }
   DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout));
@@ -174,12 +328,25 @@ static int ssl_do(struct st_VioSSLFd *pt
   SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
   SSL_set_fd(ssl, sd);
 
-  if ((r= connect_accept_func(ssl)) < 1)
+  /*
+    Since yaSSL does not support non-blocking send operations, use
+    special transport functions that properly handles non-blocking
+    sockets. These functions emulate the behavior of blocking I/O
+    operations by waiting for I/O to become available.
+  */
+#ifdef HAVE_YASSL
+  /* Set first argument of the transport functions. */
+  yaSSL_transport_set_ptr(ssl, vio);
+  /* Set functions to use in order to send and receive data. */
+  yaSSL_transport_set_recv_function(ssl, yassl_recv);
+  yaSSL_transport_set_send_function(ssl, yassl_send);
+#endif
+
+  if ((r= ssl_handshake_loop(vio, ssl, func)) < 1)
   {
     DBUG_PRINT("error", ("SSL_connect/accept failure"));
     *errptr= SSL_get_error(ssl, r);
     SSL_free(ssl);
-    vio_blocking(vio, was_blocking, &unused);
     DBUG_RETURN(1);
   }
 
@@ -188,8 +355,8 @@ static int ssl_do(struct st_VioSSLFd *pt
     change type, set sd to the fd used when connecting
     and set pointer to the SSL structure
   */
-  vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), 0, 0);
-  vio->ssl_arg= (void*)ssl;
+  if (vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), ssl, 0))
+    DBUG_RETURN(1);
 
 #ifndef DBUG_OFF
   {
@@ -239,16 +406,6 @@ int sslconnect(struct st_VioSSLFd *ptr,
 }
 
 
-int vio_ssl_blocking(Vio *vio __attribute__((unused)),
-		     my_bool set_blocking_mode,
-		     my_bool *old_mode)
-{
-  /* Mode is always blocking */
-  *old_mode= 1;
-  /* Return error if we try to change to non_blocking mode */
-  return (set_blocking_mode ? 0 : 1);
-}
-
 my_bool vio_ssl_has_data(Vio *vio)
 {
   return SSL_pending(vio->ssl_arg) > 0 ? TRUE : FALSE;

Attachment: [text/bzr-bundle] bzr/chris.powers@oracle.com-20110606204217-bonh0dct1gn2i3x4.bundle
Thread
bzr push into mysql-trunk branch (chris.powers:3301 to 3306) Christopher Powers7 Jun