[packages/percona-server/v5.1.x: 14/21] - up to 5.1.59 + update percona patches

glen glen at pld-linux.org
Wed Oct 21 16:09:20 CEST 2015


commit 3700c2a6faf77bb34f5738b9058751c3bdf31162
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Sat Nov 19 15:02:15 2011 +0000

    - up to 5.1.59 + update percona patches
    
    Changed files:
        bug45702.patch -> 1.1.2.1
        bug53761.patch -> 1.1.2.2
        bug860910.patch -> 1.1.2.1
        innodb_bug47167_test_fix.patch -> 1.1.2.2
        innodb_fake_changes.patch -> 1.1.2.1
        innodb_kill_idle_transaction.patch -> 1.1.2.1
        mysql-bug580324.patch -> 1.1.2.2.4.2
        mysql-bugfix48929.patch -> 1.1.2.2.4.2
        mysql-control_online_alter_index.patch -> 1.1.2.2.4.2
        mysql-error_pad.patch -> 1.1.2.2.4.2
        mysql-i_s_innodb_buffer_pool_pages.patch -> 1.1.2.3.4.2
        mysql-innodb_adjust_defaults.patch -> 1.1.2.3.4.2
        mysql-innodb_admin_command_base.patch -> 1.1.2.3.4.2
        mysql-innodb_buffer_pool_shm.patch -> 1.1.2.3.4.2
        mysql-innodb_deadlock_count.patch -> 1.1.2.4.4.2
        mysql-innodb_dict_size_limit.patch -> 1.2.2.3.4.2
        mysql-innodb_expand_fast_index_creation.patch -> 1.1.2.1.4.2
        mysql-innodb_expand_import.patch -> 1.1.2.4.4.2
        mysql-innodb_expand_undo_slots.patch -> 1.1.2.3.4.2
        mysql-innodb_extend_slow.patch -> 1.2.2.3.4.2
        mysql-innodb_extra_rseg.patch -> 1.2.2.3.4.2
        mysql-innodb_fast_checksum.patch -> 1.1.2.4.4.2
        mysql-innodb_fast_shutdown.patch -> 1.1.2.2.4.2
        mysql-innodb_files_extend.patch -> 1.1.2.4.4.2
        mysql-innodb_fix_misc.patch -> 1.1.2.5.4.2
        mysql-innodb_io_patches.patch -> 1.1.4.3.4.2
        mysql-innodb_lru_dump_restore.patch -> 1.1.2.4.4.2
        mysql-innodb_opt_lru_count.patch -> 1.1.2.2.4.2
        mysql-innodb_overwrite_relay_log_info.patch -> 1.1.2.3.4.2
        mysql-innodb_pass_corrupt_table.patch -> 1.1.2.4.4.2
        mysql-innodb_purge_thread.patch -> 1.1.2.3.4.2
        mysql-innodb_recovery_patches.patch -> 1.1.4.3.4.2
        mysql-innodb_separate_doublewrite.patch -> 1.1.2.4.4.2
        mysql-innodb_show_enhancements.patch -> 1.1.2.3.4.2
        mysql-innodb_show_lock_name.patch -> 1.1.2.3.4.2
        mysql-innodb_show_status.patch -> 1.1.2.3.4.2
        mysql-innodb_show_sys_tables.patch -> 1.1.2.3.4.2
        mysql-innodb_split_buf_pool_mutex.patch -> 1.3.2.2.4.2
        mysql-innodb_stats.patch -> 1.1.2.3.4.2
        mysql-innodb_swap_builtin_plugin.patch -> 1.1.2.4.4.2
        mysql-innodb_thread_concurrency_timer_based.patch -> 1.2.2.3.4.2
        mysql-log_connection_error.patch -> 1.1.2.2.4.2
        mysql-mysql-syslog.patch -> 1.1.2.2.4.2
        mysql-mysql_remove_eol_carret.patch -> 1.1.2.2.4.2
        mysql-optimizer_fix.patch -> 1.1.2.3.4.2
        mysql-profiling_slow.patch -> 1.2.2.3.4.2
        mysql-query_cache_enhance.patch -> 1.1.2.3.4.2
        mysql-show_patches.patch -> 1.1.4.3.4.2
        mysql-show_slave_status_nolock.patch -> 1.1.2.2.4.2
        mysql-show_temp_51.patch -> 1.1.2.3.4.2
        mysql-slow_extended.patch -> 1.1.2.3.4.2
        mysql-sql_no_fcache.patch -> 1.1.2.2.4.2
        mysql-suppress_log_warning_1592.patch -> 1.1.2.3.4.2
        mysql-userstat.patch -> 1.2.2.3.4.2
        mysql.spec -> 1.496.2.12.4.2
        response_time_distribution.patch -> 1.7.2.2
        subunit.patch -> 1.1.2.1
        utf8_general50_ci.patch -> 1.1.2.2
        warning_fixes.patch -> 1.1.2.1

 bug45702.patch                                    |  725 +++++++++++++
 bug53761.patch                                    |   81 +-
 bug860910.patch                                   |   92 ++
 innodb_bug47167_test_fix.patch                    |    8 -
 innodb_fake_changes.patch                         |  768 ++++++++++++++
 innodb_kill_idle_transaction.patch                |  402 ++++++++
 mysql-bug580324.patch                             |    8 +-
 mysql-bugfix48929.patch                           |   32 +-
 mysql-control_online_alter_index.patch            |   12 +-
 mysql-error_pad.patch                             |   14 +-
 mysql-i_s_innodb_buffer_pool_pages.patch          |    4 +-
 mysql-innodb_adjust_defaults.patch                |    8 +-
 mysql-innodb_admin_command_base.patch             |   20 +-
 mysql-innodb_buffer_pool_shm.patch                |    6 +-
 mysql-innodb_deadlock_count.patch                 |   10 +-
 mysql-innodb_dict_size_limit.patch                |   14 +-
 mysql-innodb_expand_fast_index_creation.patch     |  718 +++++++++++--
 mysql-innodb_expand_import.patch                  |   20 +-
 mysql-innodb_expand_undo_slots.patch              |    6 +-
 mysql-innodb_extend_slow.patch                    |   89 +-
 mysql-innodb_extra_rseg.patch                     |   10 +-
 mysql-innodb_fast_checksum.patch                  |   18 +-
 mysql-innodb_fast_shutdown.patch                  |   16 +-
 mysql-innodb_files_extend.patch                   |   43 +-
 mysql-innodb_fix_misc.patch                       |  590 +----------
 mysql-innodb_io_patches.patch                     |   44 +-
 mysql-innodb_lru_dump_restore.patch               |   89 +-
 mysql-innodb_opt_lru_count.patch                  |   50 +-
 mysql-innodb_overwrite_relay_log_info.patch       |   16 +-
 mysql-innodb_pass_corrupt_table.patch             |  112 +-
 mysql-innodb_purge_thread.patch                   |   26 +-
 mysql-innodb_recovery_patches.patch               |   14 +-
 mysql-innodb_separate_doublewrite.patch           |   40 +-
 mysql-innodb_show_enhancements.patch              |    2 +-
 mysql-innodb_show_lock_name.patch                 |   14 +-
 mysql-innodb_show_status.patch                    |   16 +-
 mysql-innodb_show_sys_tables.patch                |    2 +-
 mysql-innodb_split_buf_pool_mutex.patch           | 1135 ++++++++-------------
 mysql-innodb_stats.patch                          |   70 +-
 mysql-innodb_swap_builtin_plugin.patch            |   13 +-
 mysql-innodb_thread_concurrency_timer_based.patch |   24 +-
 mysql-log_connection_error.patch                  |    6 +-
 mysql-mysql-syslog.patch                          |   18 +-
 mysql-mysql_remove_eol_carret.patch               |   16 +-
 mysql-optimizer_fix.patch                         |   10 +-
 mysql-profiling_slow.patch                        |   28 +-
 mysql-query_cache_enhance.patch                   |   82 +-
 mysql-show_patches.patch                          |   18 +-
 mysql-show_slave_status_nolock.patch              |  304 ++++--
 mysql-show_temp_51.patch                          |   20 +-
 mysql-slow_extended.patch                         |  799 ++++++++++++---
 mysql-sql_no_fcache.patch                         |   32 +-
 mysql-suppress_log_warning_1592.patch             |   12 +-
 mysql-userstat.patch                              |  214 ++--
 mysql.spec                                        |   86 +-
 response_time_distribution.patch                  |  563 +++++++---
 subunit.patch                                     |  199 ++++
 utf8_general50_ci.patch                           |    8 +-
 warning_fixes.patch                               |   24 +
 59 files changed, 5483 insertions(+), 2337 deletions(-)
---
diff --git a/mysql.spec b/mysql.spec
index 9603a5c..f3fffce 100644
--- a/mysql.spec
+++ b/mysql.spec
@@ -31,13 +31,13 @@ Summary(ru.UTF-8):	MySQL - быстрый SQL-сервер
 Summary(uk.UTF-8):	MySQL - швидкий SQL-сервер
 Summary(zh_CN.UTF-8):	MySQL数据库服务器
 Name:		mysql
-Version:	5.1.58
+Version:	5.1.59
 Release:	1
 License:	GPL + MySQL FLOSS Exception
 Group:		Applications/Databases
 #Source0Download: http://dev.mysql.com/downloads/mysql/5.1.html#source
 Source0:	http://vesta.informatik.rwth-aachen.de/mysql/Downloads/MySQL-5.1/%{name}-%{version}.tar.gz
-# Source0-md5:	ae5aef506088e521e4b1cc4f668e96d2
+# Source0-md5:	1e89816164692f44f768024db4bc05f6
 Source100:	http://www.sphinxsearch.com/downloads/sphinx-0.9.9.tar.gz
 # Source100-md5:	7b9b618cb9b378f949bb1b91ddcc4f54
 Source1:	%{name}.init
@@ -94,46 +94,52 @@ Patch117:	%{name}-innodb_thread_concurrency_timer_based.patch
 Patch118:	%{name}-innodb_dict_size_limit.patch
 Patch119:	%{name}-innodb_split_buf_pool_mutex.patch
 Patch120:	%{name}-innodb_expand_import.patch
-Patch121:	%{name}-innodb_stats.patch
-Patch122:	%{name}-innodb_recovery_patches.patch
-Patch123:	%{name}-innodb_purge_thread.patch
-Patch124:	%{name}-innodb_admin_command_base.patch
-Patch125:	%{name}-innodb_show_lock_name.patch
-Patch126:	%{name}-innodb_extend_slow.patch
-Patch127:	%{name}-innodb_lru_dump_restore.patch
-Patch128:	%{name}-innodb_separate_doublewrite.patch
-Patch129:	%{name}-innodb_pass_corrupt_table.patch
+Patch121:	%{name}-innodb_recovery_patches.patch
+Patch122:	%{name}-innodb_purge_thread.patch
+Patch123:	%{name}-innodb_admin_command_base.patch
+Patch124:	%{name}-innodb_show_lock_name.patch
+Patch125:	%{name}-innodb_extend_slow.patch
+Patch126:	%{name}-innodb_lru_dump_restore.patch
+Patch127:	%{name}-innodb_separate_doublewrite.patch
+Patch128:	%{name}-innodb_pass_corrupt_table.patch
+Patch129:	%{name}-innodb_stats.patch
 Patch130:	%{name}-innodb_fast_checksum.patch
 Patch131:	%{name}-innodb_files_extend.patch
 Patch132:	%{name}-innodb_show_sys_tables.patch
 Patch133:	%{name}-innodb_fix_misc.patch
 Patch134:	%{name}-innodb_adjust_defaults.patch
-Patch135:	%{name}-innodb_deadlock_count.patch
-Patch136:	%{name}-bug580324.patch
-Patch137:	%{name}-bugfix48929.patch
-Patch138:	%{name}-query_cache_enhance.patch
-Patch139:	%{name}-control_online_alter_index.patch
-Patch140:	%{name}-log_connection_error.patch
-Patch141:	%{name}-mysql-syslog.patch
-Patch142:	%{name}-innodb_buffer_pool_shm.patch
-Patch143:	%{name}-error_pad.patch
-Patch144:	response_time_distribution.patch
-Patch145:	%{name}-remove_fcntl_excessive_calls.patch
-Patch146:	%{name}-sql_no_fcache.patch
-Patch147:	%{name}-show_slave_status_nolock.patch
-Patch148:	%{name}-innodb_fast_shutdown.patch
-Patch149:	%{name}-bug677407.patch
-Patch150:	%{name}-fix-bug671764.patch
-Patch151:	%{name}-mysql_remove_eol_carret.patch
-Patch152:	%{name}-innodb_expand_fast_index_creation.patch
-Patch153:	%{name}-innodb_bug60788.patch
-Patch154:	slave_timeout_fix.patch
-Patch155:	utf8_general50_ci.patch
-Patch156:	bug813587.patch
-Patch157:	innodb_bug47167_test_fix.patch
-Patch158:	disable_query_cache_28249_test_sporadic_failure.patch
-Patch159:	bug53761.patch
-Patch160:	xtradb_bug317074.patch
+Patch135:	innodb_kill_idle_transaction.patch
+Patch136:	innodb_fake_changes.patch
+Patch137:	%{name}-innodb_deadlock_count.patch
+Patch138:	%{name}-bug580324.patch
+Patch139:	%{name}-bugfix48929.patch
+Patch140:	%{name}-query_cache_enhance.patch
+Patch141:	%{name}-control_online_alter_index.patch
+Patch142:	%{name}-log_connection_error.patch
+Patch143:	%{name}-mysql-syslog.patch
+Patch144:	%{name}-innodb_buffer_pool_shm.patch
+Patch145:	%{name}-error_pad.patch
+Patch146:	response_time_distribution.patch
+Patch147:	%{name}-remove_fcntl_excessive_calls.patch
+Patch148:	%{name}-sql_no_fcache.patch
+Patch149:	%{name}-show_slave_status_nolock.patch
+Patch150:	%{name}-innodb_fast_shutdown.patch
+Patch151:	%{name}-bug677407.patch
+Patch152:	%{name}-fix-bug671764.patch
+Patch153:	%{name}-mysql_remove_eol_carret.patch
+Patch154:	%{name}-innodb_expand_fast_index_creation.patch
+Patch155:	%{name}-innodb_bug60788.patch
+Patch156:	slave_timeout_fix.patch
+Patch157:	utf8_general50_ci.patch
+Patch158:	bug813587.patch
+Patch159:	innodb_bug47167_test_fix.patch
+Patch160:	disable_query_cache_28249_test_sporadic_failure.patch
+Patch161:	bug53761.patch
+Patch162:	xtradb_bug317074.patch
+Patch163:	subunit.patch
+Patch164:	warning_fixes.patch
+Patch165:	bug860910.patch
+Patch166:	bug45702.patch
 # </percona>
 URL:		http://www.mysql.com/products/community/
 BuildRequires:	autoconf
@@ -643,6 +649,12 @@ mv sphinx-*/mysqlse storage/sphinx
 %patch158 -p1
 %patch159 -p1
 %patch160 -p1
+%patch161 -p1
+%patch162 -p1
+%patch163 -p1
+%patch164 -p1
+%patch165 -p1
+%patch166 -p1
 # </percona>
 
 %build
diff --git a/bug45702.patch b/bug45702.patch
new file mode 100644
index 0000000..9100a73
--- /dev/null
+++ b/bug45702.patch
@@ -0,0 +1,725 @@
+--- a/include/my_sys.h
++++ b/include/my_sys.h
+@@ -346,8 +346,8 @@
+ typedef struct st_dynamic_array
+ {
+   uchar *buffer;
+-  uint elements,max_element;
+-  uint alloc_increment;
++  ulong elements, max_element;
++  ulong alloc_increment;
+   uint size_of_element;
+ } DYNAMIC_ARRAY;
+ 
+@@ -809,23 +809,23 @@
+ #define my_init_dynamic_array2(A,B,C,D,E) init_dynamic_array2(A,B,C,D,E CALLER_INFO)
+ #define my_init_dynamic_array2_ci(A,B,C,D,E) init_dynamic_array2(A,B,C,D,E ORIG_CALLER_INFO)
+ extern my_bool init_dynamic_array2(DYNAMIC_ARRAY *array,uint element_size,
+-                                   void *init_buffer, uint init_alloc, 
+-                                   uint alloc_increment
++                                   void *init_buffer, ulong init_alloc,
++                                   ulong alloc_increment
+                                    CALLER_INFO_PROTO);
+ /* init_dynamic_array() function is deprecated */
+ extern my_bool init_dynamic_array(DYNAMIC_ARRAY *array,uint element_size,
+-                                  uint init_alloc,uint alloc_increment
++                                  ulong init_alloc, ulong alloc_increment
+                                   CALLER_INFO_PROTO);
+ extern my_bool insert_dynamic(DYNAMIC_ARRAY *array,uchar * element);
+ extern uchar *alloc_dynamic(DYNAMIC_ARRAY *array);
+ extern uchar *pop_dynamic(DYNAMIC_ARRAY*);
+-extern my_bool set_dynamic(DYNAMIC_ARRAY *array,uchar * element,uint array_index);
+-extern my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements);
+-extern void get_dynamic(DYNAMIC_ARRAY *array,uchar * element,uint array_index);
++extern my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar * element, ulong array_index);
++extern my_bool allocate_dynamic(DYNAMIC_ARRAY *array, ulong max_elements);
++extern void get_dynamic(DYNAMIC_ARRAY *array, uchar * element, ulong array_index);
+ extern void delete_dynamic(DYNAMIC_ARRAY *array);
+-extern void delete_dynamic_element(DYNAMIC_ARRAY *array, uint array_index);
++extern void delete_dynamic_element(DYNAMIC_ARRAY *array, ulong array_index);
+ extern void freeze_size(DYNAMIC_ARRAY *array);
+-extern int  get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element);
++extern long get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element);
+ #define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element)
+ #define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index))
+ #define push_dynamic(A,B) insert_dynamic((A),(B))
+--- a/mysys/array.c
++++ b/mysys/array.c
+@@ -44,8 +44,8 @@
+ */
+ 
+ my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size,
+-                            void *init_buffer, uint init_alloc, 
+-                            uint alloc_increment CALLER_INFO_PROTO)
++                            void *init_buffer, ulong init_alloc, 
++                            ulong alloc_increment CALLER_INFO_PROTO)
+ {
+   DBUG_ENTER("init_dynamic_array");
+   if (!alloc_increment)
+@@ -76,8 +76,8 @@
+ } 
+ 
+ my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size,
+-                           uint init_alloc, 
+-                           uint alloc_increment CALLER_INFO_PROTO)
++                           ulong init_alloc,
++                           ulong alloc_increment CALLER_INFO_PROTO)
+ {
+   /* placeholder to preserve ABI */
+   return my_init_dynamic_array_ci(array, element_size, init_alloc, 
+@@ -200,7 +200,7 @@
+     FALSE	Ok
+ */
+ 
+-my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx)
++my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar* element, ulong idx)
+ {
+   if (idx >= array->elements)
+   {
+@@ -232,11 +232,11 @@
+     TRUE	Allocation of new memory failed
+ */
+ 
+-my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements)
++my_bool allocate_dynamic(DYNAMIC_ARRAY *array, ulong max_elements)
+ {
+   if (max_elements >= array->max_element)
+   {
+-    uint size;
++    ulong size;
+     uchar *new_ptr;
+     size= (max_elements + array->alloc_increment)/array->alloc_increment;
+     size*= array->alloc_increment;
+@@ -277,11 +277,11 @@
+       idx	Index of element wanted. 
+ */
+ 
+-void get_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx)
++void get_dynamic(DYNAMIC_ARRAY *array, uchar* element, ulong idx)
+ {
+   if (idx >= array->elements)
+   {
+-    DBUG_PRINT("warning",("To big array idx: %d, array size is %d",
++    DBUG_PRINT("warning",("To big array idx: %lu, array size is %lu",
+                           idx,array->elements));
+     bzero(element,array->size_of_element);
+     return;
+@@ -324,7 +324,7 @@
+       idx        Index of element to be deleted
+ */
+ 
+-void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx)
++void delete_dynamic_element(DYNAMIC_ARRAY *array, ulong idx)
+ {
+   char *ptr= (char*) array->buffer+array->size_of_element*idx;
+   array->elements--;
+@@ -344,7 +344,7 @@
+ 
+ void freeze_size(DYNAMIC_ARRAY *array)
+ {
+-  uint elements=max(array->elements,1);
++  ulong elements= max(array->elements, 1);
+ 
+   /*
+     Do nothing if we are using a static buffer
+@@ -372,7 +372,7 @@
+ 
+ */
+ 
+-int get_index_dynamic(DYNAMIC_ARRAY *array, uchar* element)
++long get_index_dynamic(DYNAMIC_ARRAY *array, uchar* element)
+ {
+   size_t ret;
+   if (array->buffer > element)
+--- a/storage/myisam/mi_check.c
++++ b/storage/myisam/mi_check.c
+@@ -2435,7 +2435,7 @@
+ 
+     if (_create_index_by_sort(&sort_param,
+ 			      (my_bool) (!(param->testflag & T_VERBOSE)),
+-			      (uint) param->sort_buffer_length))
++			      param->sort_buffer_length))
+     {
+       param->retry_repair=1;
+       goto err;
+--- a/storage/myisam/myisamdef.h
++++ b/storage/myisam/myisamdef.h
+@@ -347,10 +347,10 @@
+   int (*key_write)(struct st_mi_sort_param *, const void *);
+   void (*lock_in_memory)(MI_CHECK *);
+   NEAR int (*write_keys)(struct st_mi_sort_param *, register uchar **,
+-                     uint , struct st_buffpek *, IO_CACHE *);
+-  NEAR uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint);
++                         ulong, struct st_buffpek *, IO_CACHE *);
++  NEAR ulong (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint);
+   NEAR int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,uchar *,
+-                       uint, uint);
++                       uint, ulong);
+ } MI_SORT_PARAM;
+ 
+ 	/* Some defines used by isam-funktions */
+--- a/storage/myisam/sort.c
++++ b/storage/myisam/sort.c
+@@ -47,42 +47,42 @@
+ 
+ /* Functions defined in this file */
+ 
+-static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info,uint keys,
++static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, ulong keys,
+                                     uchar **sort_keys,
+-                                    DYNAMIC_ARRAY *buffpek,int *maxbuffer,
++                                    DYNAMIC_ARRAY *buffpek, long *maxbuffer,
+                                     IO_CACHE *tempfile,
+                                     IO_CACHE *tempfile_for_exceptions);
+ static int NEAR_F write_keys(MI_SORT_PARAM *info,uchar **sort_keys,
+-                             uint count, BUFFPEK *buffpek,IO_CACHE *tempfile);
++                             ulong count, BUFFPEK *buffpek,IO_CACHE *tempfile);
+ static int NEAR_F write_key(MI_SORT_PARAM *info, uchar *key,
+ 			    IO_CACHE *tempfile);
+ static int NEAR_F write_index(MI_SORT_PARAM *info,uchar * *sort_keys,
+-                              uint count);
+-static int NEAR_F merge_many_buff(MI_SORT_PARAM *info,uint keys,
++                              ulong count);
++static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, ulong keys,
+                                   uchar * *sort_keys,
+-                                  BUFFPEK *buffpek,int *maxbuffer,
++                                  BUFFPEK *buffpek, long *maxbuffer,
+                                   IO_CACHE *t_file);
+-static uint NEAR_F read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
+-                                  uint sort_length);
+-static int NEAR_F merge_buffers(MI_SORT_PARAM *info,uint keys,
++static ulong NEAR_F read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
++                                   uint sort_length);
++static int NEAR_F merge_buffers(MI_SORT_PARAM *info, ulong keys,
+                                 IO_CACHE *from_file, IO_CACHE *to_file,
+                                 uchar * *sort_keys, BUFFPEK *lastbuff,
+                                 BUFFPEK *Fb, BUFFPEK *Tb);
+-static int NEAR_F merge_index(MI_SORT_PARAM *,uint,uchar **,BUFFPEK *, int,
++static int NEAR_F merge_index(MI_SORT_PARAM *, ulong, uchar **, BUFFPEK *, long,
+                               IO_CACHE *);
+ static int flush_ft_buf(MI_SORT_PARAM *info);
+ 
+ static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info,uchar **sort_keys,
+-                                    uint count, BUFFPEK *buffpek,
++                                    ulong count, BUFFPEK *buffpek,
+                                     IO_CACHE *tempfile);
+-static uint NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek,
++static ulong NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile,BUFFPEK *buffpek,
+                                          uint sort_length);
+ static int NEAR_F write_merge_key(MI_SORT_PARAM *info, IO_CACHE *to_file,
+-                                  uchar *key, uint sort_length, uint count);
++                                  uchar *key, uint sort_length, ulong count);
+ static int NEAR_F write_merge_key_varlen(MI_SORT_PARAM *info,
+ 					 IO_CACHE *to_file,
+ 					 uchar* key, uint sort_length,
+-					 uint count);
++					 ulong count);
+ static inline int
+ my_var_write(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs);
+ 
+@@ -103,8 +103,9 @@
+ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
+ 			  ulong sortbuff_size)
+ {
+-  int error,maxbuffer,skr;
+-  uint memavl,old_memavl,keys,sort_length;
++  int error;
++  long maxbuffer, skr;
++  ulong memavl, old_memavl, keys, sort_length;
+   DYNAMIC_ARRAY buffpek;
+   ha_rows records;
+   uchar **sort_keys;
+@@ -138,25 +139,25 @@
+ 
+   while (memavl >= MIN_SORT_BUFFER)
+   {
+-    if ((records < UINT_MAX32) && 
++    if ((records < ULONG_MAX) &&
+        ((my_off_t) (records + 1) * 
+         (sort_length + sizeof(char*)) <= (my_off_t) memavl))
+-      keys= (uint)records+1;
++      keys= (ulong) records + 1;
+     else
+       do
+       {
+ 	skr=maxbuffer;
+-	if (memavl < sizeof(BUFFPEK)*(uint) maxbuffer ||
+-	    (keys=(memavl-sizeof(BUFFPEK)*(uint) maxbuffer)/
++        if (memavl < sizeof(BUFFPEK) * (ulong) maxbuffer ||
++            (keys = (memavl - sizeof(BUFFPEK) * (ulong) maxbuffer) /
+              (sort_length+sizeof(char*))) <= 1 ||
+-            keys < (uint) maxbuffer)
++            keys < (ulong) maxbuffer)
+ 	{
+ 	  mi_check_print_error(info->sort_info->param,
+ 			       "myisam_sort_buffer_size is too small");
+ 	  goto err;
+ 	}
+       }
+-      while ((maxbuffer= (int) (records/(keys-1)+1)) != skr);
++      while ((maxbuffer= (long) (records / (keys - 1) + 1)) != skr);
+ 
+     if ((sort_keys=(uchar **)my_malloc(keys*(sort_length+sizeof(char*))+
+ 				       HA_FT_MAXBYTELEN, MYF(0))))
+@@ -182,7 +183,7 @@
+   (*info->lock_in_memory)(info->sort_info->param);/* Everything is allocated */
+ 
+   if (!no_messages)
+-    printf("  - Searching for keys, allocating buffer for %d keys\n",keys);
++    printf("  - Searching for keys, allocating buffer for %lu keys\n", keys);
+ 
+   if ((records=find_all_keys(info,keys,sort_keys,&buffpek,&maxbuffer,
+                                   &tempfile,&tempfile_for_exceptions))
+@@ -192,7 +193,7 @@
+   {
+     if (!no_messages)
+       printf("  - Dumping %lu keys\n", (ulong) records);
+-    if (write_index(info,sort_keys, (uint) records))
++    if (write_index(info,sort_keys, (ulong) records))
+       goto err; /* purecov: inspected */
+   }
+   else
+@@ -256,13 +257,13 @@
+ 
+ /* Search after all keys and place them in a temp. file */
+ 
+-static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, uint keys,
++static ha_rows NEAR_F find_all_keys(MI_SORT_PARAM *info, ulong keys,
+ 				    uchar **sort_keys, DYNAMIC_ARRAY *buffpek,
+-				    int *maxbuffer, IO_CACHE *tempfile,
++				    long *maxbuffer, IO_CACHE *tempfile,
+ 				    IO_CACHE *tempfile_for_exceptions)
+ {
+   int error;
+-  uint idx;
++  ulong idx;
+   DBUG_ENTER("find_all_keys");
+ 
+   idx=error=0;
+@@ -312,8 +313,8 @@
+ {
+   MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg;
+   int error;
+-  uint memavl,old_memavl,keys,sort_length;
+-  uint idx, maxbuffer;
++  ulong memavl,old_memavl,keys,sort_length;
++  ulong idx, maxbuffer;
+   uchar **sort_keys=0;
+ 
+   LINT_INIT(keys);
+@@ -349,7 +350,7 @@
+     sort_keys= (uchar **) NULL;
+ 
+     memavl=       max(sort_param->sortbuff_size, MIN_SORT_BUFFER);
+-    idx=          (uint)sort_param->sort_info->max_records;
++    idx=          (ulong) sort_param->sort_info->max_records;
+     sort_length=  sort_param->key_length;
+     maxbuffer=    1;
+ 
+@@ -360,21 +361,21 @@
+         keys= idx+1;
+       else
+       {
+-        uint skr;
++        ulong skr;
+         do
+         {
+           skr= maxbuffer;
+           if (memavl < sizeof(BUFFPEK)*maxbuffer ||
+               (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
+                (sort_length+sizeof(char*))) <= 1 ||
+-              keys < (uint) maxbuffer)
++              keys < maxbuffer)
+           {
+             mi_check_print_error(sort_param->sort_info->param,
+                                  "myisam_sort_buffer_size is too small");
+             goto err;
+           }
+         }
+-        while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr);
++        while ((maxbuffer= (idx/(keys-1)+1)) != skr);
+       }
+       if ((sort_keys= (uchar**)
+            my_malloc(keys*(sort_length+sizeof(char*))+
+@@ -403,7 +404,7 @@
+     }
+ 
+     if (sort_param->sort_info->param->testflag & T_VERBOSE)
+-      printf("Key %d - Allocating buffer for %d keys\n",
++      printf("Key %d - Allocating buffer for %lu keys\n",
+              sort_param->key + 1, keys);
+     sort_param->sort_keys= sort_keys;
+ 
+@@ -560,7 +561,7 @@
+     }
+     if (sinfo->buffpek.elements)
+     {
+-      uint maxbuffer=sinfo->buffpek.elements-1;
++      ulong maxbuffer=sinfo->buffpek.elements-1;
+       if (!mergebuf)
+       {
+         length=param->sort_buffer_length;
+@@ -583,7 +584,7 @@
+           printf("Key %d  - Merging %u keys\n",sinfo->key+1, sinfo->keys);
+         if (merge_many_buff(sinfo, keys, (uchar **)mergebuf,
+ 			    dynamic_element(&sinfo->buffpek, 0, BUFFPEK *),
+-			    (int*) &maxbuffer, &sinfo->tempfile))
++			    (long *) &maxbuffer, &sinfo->tempfile))
+         {
+           got_error=1;
+           continue;
+@@ -648,7 +649,7 @@
+         /* Write all keys in memory to file for later merge */
+ 
+ static int NEAR_F write_keys(MI_SORT_PARAM *info, register uchar **sort_keys,
+-                             uint count, BUFFPEK *buffpek, IO_CACHE *tempfile)
++                             ulong count, BUFFPEK *buffpek, IO_CACHE *tempfile)
+ {
+   uchar **end;
+   uint sort_length=info->key_length;
+@@ -690,7 +691,7 @@
+ 
+ static int NEAR_F write_keys_varlen(MI_SORT_PARAM *info,
+ 				    register uchar **sort_keys,
+-                                    uint count, BUFFPEK *buffpek,
++                                    ulong count, BUFFPEK *buffpek,
+ 				    IO_CACHE *tempfile)
+ {
+   uchar **end;
+@@ -736,7 +737,7 @@
+ /* Write index */
+ 
+ static int NEAR_F write_index(MI_SORT_PARAM *info, register uchar **sort_keys,
+-                              register uint count)
++                              register ulong count)
+ {
+   DBUG_ENTER("write_index");
+ 
+@@ -753,11 +754,11 @@
+ 
+         /* Merge buffers to make < MERGEBUFF2 buffers */
+ 
+-static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, uint keys,
++static int NEAR_F merge_many_buff(MI_SORT_PARAM *info, ulong keys,
+                                   uchar **sort_keys, BUFFPEK *buffpek,
+-                                  int *maxbuffer, IO_CACHE *t_file)
++                                  long *maxbuffer, IO_CACHE *t_file)
+ {
+-  register int i;
++  register long i;
+   IO_CACHE t_file2, *from_file, *to_file, *temp;
+   BUFFPEK *lastbuff;
+   DBUG_ENTER("merge_many_buff");
+@@ -787,7 +788,7 @@
+     if (flush_io_cache(to_file))
+       break;                                    /* purecov: inspected */
+     temp=from_file; from_file=to_file; to_file=temp;
+-    *maxbuffer= (int) (lastbuff-buffpek)-1;
++    *maxbuffer= (long) (lastbuff-buffpek)-1;
+   }
+ cleanup:
+   close_cached_file(to_file);                   /* This holds old result */
+@@ -816,17 +817,17 @@
+     -1	Error
+ */
+ 
+-static uint NEAR_F read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
+-                                  uint sort_length)
++static ulong NEAR_F read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
++                                   uint sort_length)
+ {
+-  register uint count;
+-  uint length;
++  register ulong count;
++  ulong length;
+ 
+-  if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
++  if ((count=(ulong) min((ha_rows) buffpek->max_keys,buffpek->count)))
+   {
+     if (my_pread(fromfile->file,(uchar*) buffpek->base,
+                  (length= sort_length*count),buffpek->file_pos,MYF_RW))
+-      return((uint) -1);                        /* purecov: inspected */
++      return((ulong) -1);                        /* purecov: inspected */
+     buffpek->key=buffpek->base;
+     buffpek->file_pos+= length;                 /* New filepos */
+     buffpek->count-=    count;
+@@ -835,15 +836,15 @@
+   return (count*sort_length);
+ } /* read_to_buffer */
+ 
+-static uint NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek,
+-                                         uint sort_length)
++static ulong NEAR_F read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek,
++                                          uint sort_length)
+ {
+-  register uint count;
++  register ulong count;
+   uint16 length_of_key = 0;
+-  uint idx;
++  ulong idx;
+   uchar *buffp;
+ 
+-  if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
++  if ((count= (ulong) min((ha_rows) buffpek->max_keys,buffpek->count)))
+   {
+     buffp = buffpek->base;
+ 
+@@ -851,11 +852,11 @@
+     {
+       if (my_pread(fromfile->file,(uchar*)&length_of_key,sizeof(length_of_key),
+                    buffpek->file_pos,MYF_RW))
+-        return((uint) -1);
++        return((ulong) -1);
+       buffpek->file_pos+=sizeof(length_of_key);
+       if (my_pread(fromfile->file,(uchar*) buffp,length_of_key,
+                    buffpek->file_pos,MYF_RW))
+-        return((uint) -1);
++        return((ulong) -1);
+       buffpek->file_pos+=length_of_key;
+       buffp = buffp + sort_length;
+     }
+@@ -869,9 +870,9 @@
+ 
+ static int NEAR_F write_merge_key_varlen(MI_SORT_PARAM *info,
+ 					 IO_CACHE *to_file, uchar* key,
+-                                         uint sort_length, uint count)
++                                         uint sort_length, ulong count)
+ {
+-  uint idx;
++  ulong idx;
+   uchar *bufs = key;
+ 
+   for (idx=1;idx<=count;idx++)
+@@ -887,7 +888,7 @@
+ 
+ static int NEAR_F write_merge_key(MI_SORT_PARAM *info __attribute__((unused)),
+ 				  IO_CACHE *to_file, uchar *key,
+-				  uint sort_length, uint count)
++				  uint sort_length, ulong count)
+ {
+   return my_b_write(to_file, key, (size_t) sort_length*count);
+ }
+@@ -898,12 +899,13 @@
+ */
+ 
+ static int NEAR_F
+-merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
++merge_buffers(MI_SORT_PARAM *info, ulong keys, IO_CACHE *from_file,
+               IO_CACHE *to_file, uchar **sort_keys, BUFFPEK *lastbuff,
+               BUFFPEK *Fb, BUFFPEK *Tb)
+ {
+-  int error;
+-  uint sort_length,maxcount;
++  ulong error;
++  uint sort_length;
++  ulong maxcount;
+   ha_rows count;
+   my_off_t UNINIT_VAR(to_start_filepos);
+   uchar *strpos;
+@@ -913,7 +915,7 @@
+   DBUG_ENTER("merge_buffers");
+ 
+   count=error=0;
+-  maxcount=keys/((uint) (Tb-Fb) +1);
++  maxcount= keys / ((ulong) (Tb-Fb) + 1);
+   DBUG_ASSERT(maxcount > 0);
+   LINT_INIT(to_start_filepos);
+   if (to_file)
+@@ -921,7 +923,7 @@
+   strpos=(uchar*) sort_keys;
+   sort_length=info->key_length;
+ 
+-  if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
++  if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
+                  (int (*)(void*, uchar *,uchar*)) info->key_cmp,
+                  (void*) info))
+     DBUG_RETURN(1); /* purecov: inspected */
+@@ -931,9 +933,8 @@
+     count+= buffpek->count;
+     buffpek->base= strpos;
+     buffpek->max_keys=maxcount;
+-    strpos+= (uint) (error=(int) info->read_to_buffer(from_file,buffpek,
+-                                                      sort_length));
+-    if (error == -1)
++    strpos+= (error= info->read_to_buffer(from_file,buffpek, sort_length));
++    if (error == (ulong) -1)
+       goto err; /* purecov: inspected */
+     queue_insert(&queue,(uchar*) buffpek);
+   }
+@@ -965,10 +966,10 @@
+       buffpek->key+=sort_length;
+       if (! --buffpek->mem_count)
+       {
+-        if (!(error=(int) info->read_to_buffer(from_file,buffpek,sort_length)))
++        if (!(error= info->read_to_buffer(from_file,buffpek,sort_length)))
+         {
+           uchar *base=buffpek->base;
+-          uint max_keys=buffpek->max_keys;
++          ulong max_keys=buffpek->max_keys;
+ 
+           VOID(queue_remove(&queue,0));
+ 
+@@ -993,7 +994,7 @@
+           break;                /* One buffer have been removed */
+         }
+       }
+-      else if (error == -1)
++      else if (error == (ulong) -1)
+         goto err;               /* purecov: inspected */
+       queue_replaced(&queue);   /* Top element has been replaced */
+     }
+@@ -1026,23 +1027,23 @@
+       }
+     }
+   }
+-  while ((error=(int) info->read_to_buffer(from_file,buffpek,sort_length)) != -1 &&
+-         error != 0);
++  while ((error= info->read_to_buffer(from_file, buffpek, sort_length)) !=
++         (ulong) -1 && error != 0);
+ 
+   lastbuff->count=count;
+   if (to_file)
+     lastbuff->file_pos=to_start_filepos;
+ err:
+   delete_queue(&queue);
+-  DBUG_RETURN(error);
++  DBUG_RETURN(error != 0);
+ } /* merge_buffers */
+ 
+ 
+         /* Do a merge to output-file (save only positions) */
+ 
+ static int NEAR_F
+-merge_index(MI_SORT_PARAM *info, uint keys, uchar **sort_keys,
+-            BUFFPEK *buffpek, int maxbuffer, IO_CACHE *tempfile)
++merge_index(MI_SORT_PARAM *info, ulong keys, uchar **sort_keys,
++            BUFFPEK *buffpek, long maxbuffer, IO_CACHE *tempfile)
+ {
+   DBUG_ENTER("merge_index");
+   if (merge_buffers(info,keys,tempfile,(IO_CACHE*) 0,sort_keys,buffpek,buffpek,
+--- /dev/null
++++ b/mysql-test/r/percona_bug45702.result
+@@ -0,0 +1,21 @@
++CREATE TABLE t1 (a BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=MyISAM;
++INSERT INTO t1 VALUES (), (), (), (), (), (), (), ();
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++SET @old_myisam_sort_buffer_size = @@myisam_sort_buffer_size;
++SET @@myisam_sort_buffer_size = 4 * 1024 * 1024 * 1024;
++REPAIR TABLE t1;
++Table	Op	Msg_type	Msg_text
++test.t1	repair	status	OK
++- recovering (with sort) MyISAM-table 'MYSQLD_DATADIR/test/t1'
++Data records: 4096
++- Fixing index 1
++SET @@myisam_sort_buffer_size = @old_myisam_sort_buffer_size;
++DROP TABLE t1;
+--- /dev/null
++++ b/mysql-test/t/percona_bug45702.test
+@@ -0,0 +1,34 @@
++###############################################################################
++# Bug #45702: Impossible to specify myisam_sort_buffer > 4GB on 64 bit machines
++###############################################################################
++
++--source include/have_64bit.inc
++
++# Check that having data larger than MIN_SORT_BUFFER bytes can be handled by
++# _create_index_by_sort() with myisam_sort_buffer_size = 4 GB without errors.
++# The full test with large data volumes can not be a part of the test suite.
++
++CREATE TABLE t1 (a BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=MyISAM;
++INSERT INTO t1 VALUES (), (), (), (), (), (), (), ();
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++INSERT INTO t1 SELECT NULL FROM t1;
++
++SET @old_myisam_sort_buffer_size = @@myisam_sort_buffer_size;
++SET @@myisam_sort_buffer_size = 4 * 1024 * 1024 * 1024;
++
++REPAIR TABLE t1;
++
++--let $MYSQLD_DATADIR= `select @@datadir`
++--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
++--exec $MYISAMCHK -r --sort_buffer_size=4G $MYSQLD_DATADIR/test/t1
++
++SET @@myisam_sort_buffer_size = @old_myisam_sort_buffer_size;
++
++DROP TABLE t1;
+--- a/sql/opt_range.cc
++++ b/sql/opt_range.cc
+@@ -11524,7 +11524,7 @@
+   }
+   if (min_max_ranges.elements > 0)
+   {
+-    fprintf(DBUG_FILE, "%*susing %d quick_ranges for MIN/MAX:\n",
++    fprintf(DBUG_FILE, "%*susing %lu quick_ranges for MIN/MAX:\n",
+             indent, "", min_max_ranges.elements);
+   }
+ }
+--- a/mysys/my_pread.c
++++ b/mysys/my_pread.c
+@@ -48,6 +48,7 @@
+                 myf MyFlags)
+ {
+   size_t readbytes;
++  size_t total_readbytes= 0;
+   int error= 0;
+   DBUG_ENTER("my_pread");
+   DBUG_PRINT("my",("Fd: %d  Seek: %lu  Buffer: 0x%lx  Count: %u  MyFlags: %d",
+@@ -68,6 +69,9 @@
+     if ((error= ((readbytes= pread(Filedes, Buffer, Count, offset)) != Count)))
+       my_errno= errno ? errno : -1;
+ #endif
++    if (readbytes > 0)
++      total_readbytes+= readbytes;
++
+     if (error || readbytes != Count)
+     {
+       DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d",
+@@ -80,6 +84,24 @@
+         continue;                              /* Interrupted */
+       }
+ #endif
++      if (readbytes > 0 && readbytes < Count && errno == 0)
++      {
++        /*
++          pread() may return less bytes than requested even if enough bytes are
++          available according to the Linux man page.
++          This makes determining the end-of-file condition a bit harder.
++          We just do another pread() call to see if more bytes can be read,
++          since all my_pread() users expect it to always return all available
++          bytes. For end-of-file 0 bytes is returned. This can never be the case
++          for a partial read, since according to the man page, -1 is returned
++          with errno set to EINTR if no data has been read.
++        */
++        Buffer+= readbytes;
++        offset+= readbytes;
++        Count-= readbytes;
++
++        continue;
++      }
+       if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
+       {
+ 	if (readbytes == (size_t) -1)
+@@ -94,7 +116,7 @@
+     }
+     if (MyFlags & (MY_NABP | MY_FNABP))
+       DBUG_RETURN(0);				/* Read went ok; Return 0 */
+-    DBUG_RETURN(readbytes);			/* purecov: inspected */
++    DBUG_RETURN(total_readbytes);			/* purecov: inspected */
+   }
+ } /* my_pread */
+ 
diff --git a/bug53761.patch b/bug53761.patch
index 945cf17..5c2e7c9 100644
--- a/bug53761.patch
+++ b/bug53761.patch
@@ -5,7 +5,7 @@
 #
 --- a/storage/innodb_plugin/btr/btr0cur.c
 +++ b/storage/innodb_plugin/btr/btr0cur.c
-@@ -3117,6 +3117,7 @@
+@@ -3238,6 +3238,7 @@
  {
  	btr_path_t*	slot;
  	rec_t*		rec;
@@ -13,7 +13,7 @@
  
  	ut_a(cursor->path_arr);
  
-@@ -3139,8 +3140,155 @@
+@@ -3260,8 +3261,155 @@
  
  	slot = cursor->path_arr + (root_height - height);
  
@@ -170,7 +170,7 @@
  }
  
  /*******************************************************************//**
-@@ -3165,6 +3313,7 @@
+@@ -3286,6 +3434,7 @@
  	ibool		diverged_lot;
  	ulint		divergence_level;
  	ib_int64_t	n_rows;
@@ -178,7 +178,7 @@
  	ulint		i;
  	mtr_t		mtr;
  
-@@ -3207,6 +3356,7 @@
+@@ -3328,6 +3477,7 @@
  	/* We have the path information for the range in path1 and path2 */
  
  	n_rows = 1;
@@ -186,7 +186,7 @@
  	diverged = FALSE;	    /* This becomes true when the path is not
  				    the same any more */
  	diverged_lot = FALSE;	    /* This becomes true when the paths are
-@@ -3222,7 +3372,7 @@
+@@ -3343,7 +3493,7 @@
  		if (slot1->nth_rec == ULINT_UNDEFINED
  		    || slot2->nth_rec == ULINT_UNDEFINED) {
  
@@ -195,7 +195,7 @@
  				/* In trees whose height is > 1 our algorithm
  				tends to underestimate: multiply the estimate
  				by 2: */
-@@ -3234,7 +3384,9 @@
+@@ -3355,7 +3505,9 @@
  			to over 1 / 2 of the estimated rows in the whole
  			table */
  
@@ -206,7 +206,7 @@
  				n_rows = index->table->stat_n_rows / 2;
  
  				/* If there are just 0 or 1 rows in the table,
-@@ -3260,10 +3412,15 @@
+@@ -3381,10 +3533,15 @@
  					divergence_level = i;
  				}
  			} else {
@@ -226,7 +226,7 @@
  			}
  
  		} else if (diverged && !diverged_lot) {
-@@ -3287,8 +3444,9 @@
+@@ -3408,8 +3565,9 @@
  			}
  		} else if (diverged_lot) {
  
@@ -240,7 +240,7 @@
  }
 --- a/storage/innodb_plugin/include/btr0cur.h
 +++ b/storage/innodb_plugin/include/btr0cur.h
-@@ -652,6 +652,11 @@
+@@ -670,6 +670,11 @@
  				order); value ULINT_UNDEFINED
  				denotes array end */
  	ulint	n_recs;		/*!< number of records on the page */
@@ -407,3 +407,66 @@
  SELECT COUNT(*) FROM
  (SELECT * FROM t1 FORCE INDEX (idx,PRIMARY)
  WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t;
+--- a/mysql-test/r/index_merge_innodb.result
++++ b/mysql-test/r/index_merge_innodb.result
+@@ -346,7 +346,7 @@
+ FROM t1
+ WHERE c = 1 AND b = 1 AND d = 1;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	t1	index_merge	c,bd	c,bd	5,10	NULL	1	Using intersect(c,bd); Using where; Using index
++1	SIMPLE	t1	ref	c,bd	bd	10	const,const	2	Using where
+ CREATE TABLE t2 ( a INT )
+ SELECT a
+ FROM t1
+--- a/mysql-test/r/rowid_order_innodb.result
++++ b/mysql-test/r/rowid_order_innodb.result
+@@ -15,7 +15,7 @@
+ (10, 1, 1);
+ explain select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	t1	index_merge	key1,key2	key1,key2	5,5	NULL	4	Using sort_union(key1,key2); Using where
++1	SIMPLE	t1	index_merge	key1,key2	key1,key2	5,5	NULL	5	Using sort_union(key1,key2); Using where
+ select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
+ pk1	key1	key2
+ -100	1	1
+--- a/mysql-test/r/type_bit_innodb.result
++++ b/mysql-test/r/type_bit_innodb.result
+@@ -233,7 +233,7 @@
+ 127	403
+ explain select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
+ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+-1	SIMPLE	t1	range	a	a	2	NULL	19	Using where; Using index; Using filesort
++1	SIMPLE	t1	range	a	a	2	NULL	27	Using where; Using index; Using filesort
+ select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
+ a+0	b+0
+ 44	307
+--- a/mysql-test/r/endspace.result
++++ b/mysql-test/r/endspace.result
+@@ -201,12 +201,12 @@
+ text1
+ teststring	
+ teststring 
+-select text1, length(text1) from t1 where text1='teststring' or text1 like 'teststring_%';
++select text1, length(text1) from t1 where text1='teststring' or text1 like 'teststring_%' order by 1, 2;
+ text1	length(text1)
+ teststring		11
+ teststring	10
+ teststring 	11
+-select text1, length(text1) from t1 where text1='teststring' or text1 >= 'teststring\t';
++select text1, length(text1) from t1 where text1='teststring' or text1 >= 'teststring\t' order by 1, 2;
+ text1	length(text1)
+ teststring		11
+ teststring	10
+--- a/mysql-test/t/endspace.test
++++ b/mysql-test/t/endspace.test
+@@ -93,8 +93,8 @@
+ select * from t1 where text1 like 'teststring_%';
+ 
+ # The following gives wrong result in InnoDB
+-select text1, length(text1) from t1 where text1='teststring' or text1 like 'teststring_%';
+-select text1, length(text1) from t1 where text1='teststring' or text1 >= 'teststring\t';
++select text1, length(text1) from t1 where text1='teststring' or text1 like 'teststring_%' order by 1, 2;
++select text1, length(text1) from t1 where text1='teststring' or text1 >= 'teststring\t' order by 1, 2;
+ select concat('|', text1, '|') from t1 order by text1;
+ drop table t1;
+ 
diff --git a/bug860910.patch b/bug860910.patch
new file mode 100644
index 0000000..2590b62
--- /dev/null
+++ b/bug860910.patch
@@ -0,0 +1,92 @@
+# name       : bug860910.patch
+# maintainer : Alexey
+#
+# Fixes LP bug #860910 / MySQL bug #62557
+#
+--- /dev/null
++++ b/mysql-test/suite/rpl/r/percona_bug860910.result
+@@ -0,0 +1,17 @@
++*** Set up master (server_1) <-> master (server_2) replication  ***
++include/rpl_init.inc [topology=1->2->1]
++
++SELECT @@global.log_slave_updates;
++@@global.log_slave_updates
++1
++SELECT @@global.log_slave_updates;
++@@global.log_slave_updates
++1
++CREATE TABLE t1(a INT);
++SET @var:=0;
++INSERT INTO t1 VALUES (@var);
++INSERT INTO t1 VALUES (1);
++DROP TABLE t1;
++include/rpl_sync.inc
++include/check_slave_param.inc [Exec_Master_Log_Pos]
++include/rpl_end.inc
+--- /dev/null
++++ b/mysql-test/suite/rpl/t/percona_bug860910.cnf
+@@ -0,0 +1,8 @@
++!include ../my.cnf
++
++[mysqld.1]
++log-slave-updates
++
++[mysqld.2]
++log-slave-updates
++
+--- /dev/null
++++ b/mysql-test/suite/rpl/t/percona_bug860910.test
+@@ -0,0 +1,38 @@
++########################################################################
++# Bug #860910: SHOW SLAVE STATUS gives wrong output with master-master
++#              and using SET uservars
++########################################################################
++
++--echo *** Set up master (server_1) <-> master (server_2) replication  ***
++--let $rpl_topology= 1->2->1
++--source include/rpl_init.inc
++--echo
++
++--connection server_1
++SELECT @@global.log_slave_updates;
++
++--connection server_2
++SELECT @@global.log_slave_updates;
++
++--connection server_1
++CREATE TABLE t1(a INT);
++SET @var:=0;
++INSERT INTO t1 VALUES (@var);
++INSERT INTO t1 VALUES (1);
++
++DROP TABLE t1;
++
++# The following would hang with the bug not fixed due to incorrect
++# Exec_Master_Log_Pos
++--source include/rpl_sync.inc
++
++--connection server_2
++--let $master_log_pos= query_get_value(SHOW MASTER STATUS, Position, 1)
++
++--connection server_1
++--let $slave_param= Exec_Master_Log_Pos
++--let $slave_param_value= $master_log_pos
++--source include/check_slave_param.inc
++
++# Cleanup
++--source include/rpl_end.inc
+--- a/sql/log.cc
++++ b/sql/log.cc
+@@ -4629,6 +4629,12 @@
+                                  user_var_event->length,
+                                  user_var_event->type,
+                                  user_var_event->charset_number);
++            /*
++              These User_var_log_events must be logged with event_info's
++              server_id, rather than the current one.
++            */
++            e.server_id= event_info->server_id;
++
+             if (e.write(file))
+               goto err;
+             if (file == &log_file)
diff --git a/innodb_bug47167_test_fix.patch b/innodb_bug47167_test_fix.patch
index b6c249e..8a6671e 100644
--- a/innodb_bug47167_test_fix.patch
+++ b/innodb_bug47167_test_fix.patch
@@ -42,11 +42,3 @@
  
  # Following are negative tests, all should fail.
  --disable_warnings
---- a/mysql-test/include/have_innodb.inc
-+++ b/mysql-test/include/have_innodb.inc
-@@ -1,4 +1,4 @@
--if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED')`)
-+if (`select count(*)>0 from information_schema.plugins where plugin_name like 'xtradb%'`)
- {
-   --skip Test requires InnoDB.
- }
diff --git a/innodb_fake_changes.patch b/innodb_fake_changes.patch
new file mode 100644
index 0000000..14b33fd
--- /dev/null
+++ b/innodb_fake_changes.patch
@@ -0,0 +1,768 @@
+# name       : innodb_fake_changes.patch
+# introduced : 5.1.58
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+--- a/storage/innodb_plugin/btr/btr0cur.c
++++ b/storage/innodb_plugin/btr/btr0cur.c
+@@ -1046,6 +1046,11 @@
+ 	rec_t*		rec;
+ 	roll_ptr_t	roll_ptr;
+ 
++	if (thr && thr_get_trx(thr)->fake_changes) {
++		/* skip LOCK, UNDO */
++		return(DB_SUCCESS);
++	}
++
+ 	/* Check if we have to wait for a lock: enqueue an explicit lock
+ 	request if yes */
+ 
+@@ -1177,7 +1182,7 @@
+ 	}
+ #endif /* UNIV_DEBUG */
+ 
+-	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
++	ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ 	max_size = page_get_max_insert_size_after_reorganize(page, 1);
+ 	leaf = page_is_leaf(page);
+ 
+@@ -1272,6 +1277,12 @@
+ 		goto fail_err;
+ 	}
+ 
++	if (thr && thr_get_trx(thr)->fake_changes) {
++		/* skip CHANGE, LOG */
++		*big_rec = big_rec_vec;
++		return(err); /* == DB_SUCCESS */
++	}
++
+ 	page_cursor = btr_cur_get_page_cur(cursor);
+ 
+ 	/* Now, try the insert */
+@@ -1414,10 +1425,10 @@
+ 
+ 	*big_rec = NULL;
+ 
+-	ut_ad(mtr_memo_contains(mtr,
++	ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr,
+ 				dict_index_get_lock(btr_cur_get_index(cursor)),
+ 				MTR_MEMO_X_LOCK));
+-	ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
++	ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
+ 				MTR_MEMO_PAGE_X_FIX));
+ 
+ 	/* Try first an optimistic insert; reset the cursor flag: we do not
+@@ -1483,6 +1494,16 @@
+ 		}
+ 	}
+ 
++	if (thr && thr_get_trx(thr)->fake_changes) {
++		/* skip CHANGE, LOG */
++		if (n_extents > 0) {
++			fil_space_release_free_extents(index->space,
++						       n_reserved);
++		}
++		*big_rec = big_rec_vec;
++		return(DB_SUCCESS);
++	}
++
+ 	if (dict_index_get_page(index)
+ 	    == buf_block_get_page_no(btr_cur_get_block(cursor))) {
+ 
+@@ -1539,6 +1560,11 @@
+ 
+ 	ut_ad(cursor && update && thr && roll_ptr);
+ 
++	if (thr && thr_get_trx(thr)->fake_changes) {
++		/* skip LOCK, UNDO */
++		return(DB_SUCCESS);
++	}
++
+ 	rec = btr_cur_get_rec(cursor);
+ 	index = cursor->index;
+ 
+@@ -1837,6 +1863,14 @@
+ 		return(err);
+ 	}
+ 
++	if (trx->fake_changes) {
++		/* skip CHANGE, LOG */
++		if (UNIV_LIKELY_NULL(heap)) {
++			mem_heap_free(heap);
++		}
++		return(err); /* == DB_SUCCESS */
++	}
++
+ 	if (block->is_hashed) {
+ 		/* The function row_upd_changes_ord_field_binary works only
+ 		if the update vector was built for a clustered index, we must
+@@ -1939,7 +1973,7 @@
+ 	rec = btr_cur_get_rec(cursor);
+ 	index = cursor->index;
+ 	ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
+-	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
++	ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ 	/* The insert buffer tree should never be updated in place. */
+ 	ut_ad(!dict_index_is_ibuf(index));
+ 
+@@ -2053,6 +2087,11 @@
+ 		goto err_exit;
+ 	}
+ 
++	if (thr && thr_get_trx(thr)->fake_changes) {
++		/* skip CHANGE, LOG */
++		goto err_exit; /* == DB_SUCCESS */
++	}
++
+ 	/* Ok, we may do the replacement. Store on the page infimum the
+ 	explicit locks on rec, before deleting rec (see the comment in
+ 	btr_cur_pessimistic_update). */
+@@ -2203,9 +2242,9 @@
+ 	rec = btr_cur_get_rec(cursor);
+ 	index = cursor->index;
+ 
+-	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
++	ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, dict_index_get_lock(index),
+ 				MTR_MEMO_X_LOCK));
+-	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
++	ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+ #ifdef UNIV_ZIP_DEBUG
+ 	ut_a(!page_zip || page_zip_validate(page_zip, page));
+ #endif /* UNIV_ZIP_DEBUG */
+@@ -2293,6 +2332,9 @@
+ 
+ 		ut_ad(big_rec_vec == NULL);
+ 
++		/* fake_changes should not cause undo. so never reaches here */
++		ut_ad(!(trx->fake_changes));
++
+ 		btr_rec_free_updated_extern_fields(
+ 			index, rec, page_zip, offsets, update,
+ 			trx_is_recv(trx) ? RB_RECOVERY : RB_NORMAL, mtr);
+@@ -2331,6 +2373,12 @@
+ 		ut_ad(flags & BTR_KEEP_POS_FLAG);
+ 	}
+ 
++	if (trx->fake_changes) {
++		/* skip CHANGE, LOG */
++		err = DB_SUCCESS;
++		goto return_after_reservations;
++	}
++
+ 	/* Store state of explicit locks on rec on the page infimum record,
+ 	before deleting rec. The page infimum acts as a dummy carrier of the
+ 	locks, taking care also of lock releases, before we can move the locks
+@@ -2686,6 +2734,11 @@
+ 	ut_ad(dict_index_is_clust(index));
+ 	ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
+ 
++	if (thr && thr_get_trx(thr)->fake_changes) {
++		/* skip LOCK, UNDO, CHANGE, LOG */
++		return(DB_SUCCESS);
++	}
++
+ 	err = lock_clust_rec_modify_check_and_lock(flags, block,
+ 						   rec, index, offsets, thr);
+ 
+@@ -2823,6 +2876,11 @@
+ 	rec_t*		rec;
+ 	ulint		err;
+ 
++	if (thr && thr_get_trx(thr)->fake_changes) {
++		/* skip LOCK, CHANGE, LOG */
++		return(DB_SUCCESS);
++	}
++
+ 	block = btr_cur_get_block(cursor);
+ 	rec = btr_cur_get_rec(cursor);
+ 
+--- a/storage/innodb_plugin/handler/ha_innodb.cc
++++ b/storage/innodb_plugin/handler/ha_innodb.cc
+@@ -369,6 +369,12 @@
+   "The value 3 regards innodb_flush_log_at_trx_commit (default).",
+   NULL, NULL, 3, 0, 3, 0);
+ 
++static MYSQL_THDVAR_BOOL(fake_changes, PLUGIN_VAR_OPCMDARG,
++  "In the transaction after enabled, UPDATE, INSERT and DELETE only move the cursor to the records "
++  "and do nothing other operations (no changes, no ibuf, no undo, no transaction log) in the transaction. "
++  "This is to cause replication prefetch IO. ATTENTION: the transaction started after enabled is affected.",
++  NULL, NULL, FALSE);
++
+ 
+ static handler *innobase_create_handler(handlerton *hton,
+                                         TABLE_SHARE *table,
+@@ -1400,6 +1406,8 @@
+ 	trx->check_unique_secondary = !thd_test_options(
+ 		thd, OPTION_RELAXED_UNIQUE_CHECKS);
+ 
++	trx->fake_changes = THDVAR(thd, fake_changes);
++
+ #ifdef EXTENDED_SLOWLOG
+ 	if (thd_log_slow_verbosity(thd) & SLOG_V_INNODB) {
+ 		trx->take_stats = TRUE;
+@@ -2816,6 +2824,11 @@
+ 		trx_search_latch_release_if_reserved(trx);
+ 	}
+ 
++	if (trx->fake_changes && (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
++		innobase_rollback(hton, thd, all); /* rollback implicitly */
++		thd->main_da.reset_diagnostics_area(); /* because debug assertion code complains, if something left */
++		DBUG_RETURN(HA_ERR_WRONG_COMMAND);
++	}
+ 	/* The flag trx->active_trans is set to 1 in
+ 
+ 	1. ::external_lock(),
+@@ -7141,6 +7154,12 @@
+ 
+ 	trx = innobase_trx_allocate(thd);
+ 
++	if (trx->fake_changes) {
++		innobase_commit_low(trx);
++		trx_free_for_mysql(trx);
++		DBUG_RETURN(HA_ERR_WRONG_COMMAND);
++	}
++
+ 	/* Latch the InnoDB data dictionary exclusively so that no deadlocks
+ 	or lock waits can happen in it during a table create operation.
+ 	Drop table etc. do this latching in row0mysql.c. */
+@@ -7346,6 +7365,10 @@
+ 		DBUG_RETURN(HA_ERR_CRASHED);
+ 	}
+ 
++	if (prebuilt->trx->fake_changes) {
++		goto fallback;
++	}
++
+ 	/* Truncate the table in InnoDB */
+ 
+ 	error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx);
+@@ -7406,6 +7429,12 @@
+ 
+ 	trx = innobase_trx_allocate(thd);
+ 
++	if (trx->fake_changes) {
++		innobase_commit_low(trx);
++		trx_free_for_mysql(trx);
++		DBUG_RETURN(HA_ERR_WRONG_COMMAND);
++	}
++
+ 	name_len = strlen(name);
+ 
+ 	ut_a(name_len < 1000);
+@@ -7494,6 +7523,12 @@
+ 	trx->mysql_thd = NULL;
+ #else
+ 	trx = innobase_trx_allocate(thd);
++	if (trx->fake_changes) {
++		my_free(namebuf, MYF(0));
++		innobase_commit_low(trx);
++		trx_free_for_mysql(trx);
++		return; /* ignore */
++	}
+ #endif
+ 	row_drop_database_for_mysql(namebuf, trx);
+ 	my_free(namebuf, MYF(0));
+@@ -7601,6 +7636,11 @@
+ 	trx_search_latch_release_if_reserved(parent_trx);
+ 
+ 	trx = innobase_trx_allocate(thd);
++	if (trx->fake_changes) {
++		innobase_commit_low(trx);
++		trx_free_for_mysql(trx);
++		DBUG_RETURN(HA_ERR_WRONG_COMMAND);
++	}
+ 
+ 	error = innobase_rename_table(trx, from, to, TRUE);
+ 
+@@ -10373,6 +10413,10 @@
+ 		return(0);
+ 	}
+ 
++	if (trx->fake_changes) {
++		return(0);
++	}
++
+ 	thd_get_xid(thd, (MYSQL_XID*) &trx->xid);
+ 
+ 	/* Release a possible FIFO ticket and search latch. Since we will
+@@ -11905,6 +11949,7 @@
+   MYSQL_SYSVAR(use_purge_thread),
+   MYSQL_SYSVAR(pass_corrupt_table),
+   MYSQL_SYSVAR(lazy_drop_table),
++  MYSQL_SYSVAR(fake_changes),
+   NULL
+ };
+ 
+--- a/storage/innodb_plugin/handler/handler0alter.cc
++++ b/storage/innodb_plugin/handler/handler0alter.cc
+@@ -652,6 +652,9 @@
+ 	/* In case MySQL calls this in the middle of a SELECT query, release
+ 	possible adaptive hash latch to avoid deadlocks of threads. */
+ 	trx_search_latch_release_if_reserved(prebuilt->trx);
++	if (prebuilt->trx->fake_changes) {
++		DBUG_RETURN(HA_ERR_WRONG_COMMAND);
++	}
+ 
+ 	/* Check if the index name is reserved. */
+ 	if (innobase_index_name_is_reserved(user_thd, key_info, num_of_keys)) {
+@@ -678,6 +681,13 @@
+ 	/* Create a background transaction for the operations on
+ 	the data dictionary tables. */
+ 	trx = innobase_trx_allocate(user_thd);
++	if (trx->fake_changes) {
++		mem_heap_free(heap);
++		trx_general_rollback_for_mysql(trx, NULL);
++		trx_free_for_mysql(trx);
++		DBUG_RETURN(HA_ERR_WRONG_COMMAND);
++	}
++
+ 	trx_start_if_not_started(trx);
+ 
+ 	/* Create table containing all indexes to be built in this
+@@ -964,6 +974,10 @@
+ 	trx_search_latch_release_if_reserved(prebuilt->trx);
+ 	trx = prebuilt->trx;
+ 
++	if (trx->fake_changes) {
++		DBUG_RETURN(HA_ERR_WRONG_COMMAND);
++	}
++
+ 	/* Test and mark all the indexes to be dropped */
+ 
+ 	row_mysql_lock_data_dictionary(trx);
+@@ -1168,6 +1182,12 @@
+ 	/* Create a background transaction for the operations on
+ 	the data dictionary tables. */
+ 	trx = innobase_trx_allocate(user_thd);
++	if (trx->fake_changes) {
++		trx_general_rollback_for_mysql(trx, NULL);
++		trx_free_for_mysql(trx);
++		DBUG_RETURN(HA_ERR_WRONG_COMMAND);
++	}
++
+ 	trx_start_if_not_started(trx);
+ 
+ 	/* Flag this transaction as a dictionary operation, so that
+--- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c
++++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c
+@@ -2613,6 +2613,8 @@
+ 
+ 	ut_a(trx_sys_multiple_tablespace_format);
+ 
++	ut_ad(!(thr_get_trx(thr)->fake_changes));
++
+ 	do_merge = FALSE;
+ 
+ 	mutex_enter(&ibuf_mutex);
+--- a/storage/innodb_plugin/include/trx0trx.h
++++ b/storage/innodb_plugin/include/trx0trx.h
+@@ -509,6 +509,7 @@
+ 					150 bytes in the undo log size as then
+ 					we skip XA steps */
+ 	ulint		flush_log_at_trx_commit_session;
++	ulint		fake_changes;
+ 	ulint		flush_log_later;/* In 2PC, we hold the
+ 					prepare_commit mutex across
+ 					both phases. In that case, we
+--- a/storage/innodb_plugin/lock/lock0lock.c
++++ b/storage/innodb_plugin/lock/lock0lock.c
+@@ -3907,6 +3907,10 @@
+ 
+ 	trx = thr_get_trx(thr);
+ 
++	if (trx->fake_changes && mode == LOCK_IX) {
++		mode = LOCK_IS;
++	}
++
+ 	lock_mutex_enter_kernel();
+ 
+ 	/* Look for stronger locks the same trx already has on the table */
+@@ -5108,6 +5112,11 @@
+ 	}
+ 
+ 	trx = thr_get_trx(thr);
++
++	if (trx->fake_changes) {
++		return(DB_SUCCESS);
++	}
++
+ 	next_rec = page_rec_get_next_const(rec);
+ 	next_rec_heap_no = page_rec_get_heap_no(next_rec);
+ 
+@@ -5276,6 +5285,10 @@
+ 		return(DB_SUCCESS);
+ 	}
+ 
++	if (thr && thr_get_trx(thr)->fake_changes) {
++		return(DB_SUCCESS);
++	}
++
+ 	heap_no = rec_offs_comp(offsets)
+ 		? rec_get_heap_no_new(rec)
+ 		: rec_get_heap_no_old(rec);
+@@ -5334,6 +5347,10 @@
+ 		return(DB_SUCCESS);
+ 	}
+ 
++	if (thr && thr_get_trx(thr)->fake_changes) {
++		return(DB_SUCCESS);
++	}
++
+ 	heap_no = page_rec_get_heap_no(rec);
+ 
+ 	/* Another transaction cannot have an implicit lock on the record,
+@@ -5421,6 +5438,10 @@
+ 		return(DB_SUCCESS);
+ 	}
+ 
++	if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
++		mode = LOCK_S;
++	}
++
+ 	heap_no = page_rec_get_heap_no(rec);
+ 
+ 	lock_mutex_enter_kernel();
+@@ -5498,6 +5519,10 @@
+ 		return(DB_SUCCESS);
+ 	}
+ 
++	if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
++		mode = LOCK_S;
++	}
++
+ 	heap_no = page_rec_get_heap_no(rec);
+ 
+ 	lock_mutex_enter_kernel();
+--- a/storage/innodb_plugin/que/que0que.c
++++ b/storage/innodb_plugin/que/que0que.c
+@@ -1418,6 +1418,12 @@
+ 
+ 	ut_a(trx->error_state == DB_SUCCESS);
+ 
++	if (trx->fake_changes) {
++		/* fake_changes should not access to system tables */
++		fprintf(stderr, "InnoDB: ERROR: innodb_fake_changes tried to access to system tables.\n");
++		return(DB_ERROR);
++	}
++
+ 	if (reserve_dict_mutex) {
+ 		mutex_enter(&dict_sys->mutex);
+ 	}
+--- a/storage/innodb_plugin/row/row0ins.c
++++ b/storage/innodb_plugin/row/row0ins.c
+@@ -1512,6 +1512,11 @@
+ 	if (UNIV_LIKELY_NULL(heap)) {
+ 		mem_heap_free(heap);
+ 	}
++
++	if (trx->fake_changes) {
++		err = DB_SUCCESS;
++	}
++
+ 	return(err);
+ }
+ 
+@@ -2014,7 +2019,7 @@
+ 	}
+ 
+ 	btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
+-				    mode | BTR_INSERT | ignore_sec_unique,
++				    thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT | ignore_sec_unique),
+ 				    &cursor, 0, __FILE__, __LINE__, &mtr);
+ 
+ 	if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
+@@ -2074,7 +2079,7 @@
+ 
+ 			btr_cur_search_to_nth_level(index, 0, entry,
+ 						    PAGE_CUR_LE,
+-						    mode | BTR_INSERT,
++						    thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT),
+ 						    &cursor, 0,
+ 						    __FILE__, __LINE__, &mtr);
+ 		}
+@@ -2162,6 +2167,22 @@
+ 	mtr_commit(&mtr);
+ 
+ 	if (UNIV_LIKELY_NULL(big_rec)) {
++
++		if (thr_get_trx(thr)->fake_changes) {
++			/* skip store extern */
++			if (modify) {
++				dtuple_big_rec_free(big_rec);
++			} else {
++				dtuple_convert_back_big_rec(index, entry, big_rec);
++			}
++
++			if (UNIV_LIKELY_NULL(heap)) {
++				mem_heap_free(heap);
++			}
++
++			return(err);
++		}
++
+ 		mtr_start(&mtr);
+ 
+ 		btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
+--- a/storage/innodb_plugin/row/row0mysql.c
++++ b/storage/innodb_plugin/row/row0mysql.c
+@@ -1189,6 +1189,7 @@
+ 		prebuilt->table->stat_n_rows--;
+ 	}
+ 
++	if (!(trx->fake_changes))
+ 	row_update_statistics_if_needed(prebuilt->table);
+ 	trx->op_info = "";
+ 
+@@ -1449,6 +1450,7 @@
+ 	that changes indexed columns, UPDATEs that change only non-indexed
+ 	columns would not affect statistics. */
+ 	if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
++		if (!(trx->fake_changes))
+ 		row_update_statistics_if_needed(prebuilt->table);
+ 	}
+ 
+@@ -1667,6 +1669,7 @@
+ 		srv_n_rows_updated++;
+ 	}
+ 
++	if (!(trx->fake_changes))
+ 	row_update_statistics_if_needed(table);
+ 
+ 	return(err);
+--- a/storage/innodb_plugin/row/row0upd.c
++++ b/storage/innodb_plugin/row/row0upd.c
+@@ -1591,8 +1591,9 @@
+ 
+ 	mtr_start(&mtr);
+ 
+-	found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
+-				       &mtr);
++	found = row_search_index_entry(index, entry,
++				       trx->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF,
++				       &pcur, &mtr);
+ 	btr_cur = btr_pcur_get_btr_cur(&pcur);
+ 
+ 	rec = btr_cur_get_rec(btr_cur);
+@@ -1822,9 +1823,11 @@
+ 		the previous invocation of this function. Mark the
+ 		off-page columns in the entry inherited. */
+ 
++		if (!(trx->fake_changes)) {
+ 		change_ownership = row_upd_clust_rec_by_insert_inherit(
+ 			NULL, NULL, entry, node->update);
+ 		ut_a(change_ownership);
++		}
+ 		/* fall through */
+ 	case UPD_NODE_INSERT_CLUSTERED:
+ 		/* A lock wait occurred in row_ins_index_entry() in
+@@ -1854,7 +1857,7 @@
+ 		delete-marked old record, mark them disowned by the
+ 		old record and owned by the new entry. */
+ 
+-		if (rec_offs_any_extern(offsets)) {
++		if (rec_offs_any_extern(offsets) && !(trx->fake_changes)) {
+ 			change_ownership = row_upd_clust_rec_by_insert_inherit(
+ 				rec, offsets, entry, node->update);
+ 
+@@ -1982,7 +1985,8 @@
+ 	the same transaction do not modify the record in the meantime.
+ 	Therefore we can assert that the restoration of the cursor succeeds. */
+ 
+-	ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
++	ut_a(btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_TREE,
++				       pcur, mtr));
+ 
+ 	ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
+ 				    dict_table_is_comp(index->table)));
+@@ -1990,7 +1994,8 @@
+ 	err = btr_cur_pessimistic_update(
+ 		BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, btr_cur,
+ 		&heap, &big_rec, node->update, node->cmpl_info, thr, mtr);
+-	if (big_rec) {
++	/* skip store extern for fake_changes */
++	if (big_rec && !(thr_get_trx(thr)->fake_changes)) {
+ 		ulint		offsets_[REC_OFFS_NORMAL_SIZE];
+ 		rec_t*		rec;
+ 		rec_offs_init(offsets_);
+@@ -2132,7 +2137,8 @@
+ 
+ 	ut_a(pcur->rel_pos == BTR_PCUR_ON);
+ 
+-	success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
++	success = btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF,
++					    pcur, mtr);
+ 
+ 	if (!success) {
+ 		err = DB_RECORD_NOT_FOUND;
+--- a/storage/innodb_plugin/trx/trx0trx.c
++++ b/storage/innodb_plugin/trx/trx0trx.c
+@@ -114,6 +114,8 @@
+ 
+ 	trx->flush_log_at_trx_commit_session = 3; /* means to use innodb_flush_log_at_trx_commit value */
+ 
++	trx->fake_changes = FALSE;
++
+ 	trx->check_foreigns = TRUE;
+ 	trx->check_unique_secondary = TRUE;
+ 
+--- /dev/null
++++ b/mysql-test/r/percona_innodb_fake_changes.result
+@@ -0,0 +1,55 @@
++DROP TABLE IF EXISTS t1;
++# Checking variables
++SHOW VARIABLES LIKE 'innodb_fake_changes';
++Variable_name	Value
++innodb_fake_changes	OFF
++SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
++VARIABLE_VALUE
++OFF
++SET innodb_fake_changes=1;
++SHOW VARIABLES LIKE 'innodb_fake_changes';
++Variable_name	Value
++innodb_fake_changes	ON
++SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
++VARIABLE_VALUE
++ON
++SET innodb_fake_changes=default;
++SHOW VARIABLES LIKE 'innodb_fake_changes';
++Variable_name	Value
++innodb_fake_changes	OFF
++SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
++VARIABLE_VALUE
++OFF
++# Explicit COMMIT should fail when innodb_fake_changes is enabled
++# DML should be fine
++CREATE TABLE t1 (a INT) ENGINE=InnoDB;
++INSERT INTO t1 VALUES (1);
++SET autocommit=0;
++SET innodb_fake_changes=1;
++BEGIN;
++INSERT INTO t1 VALUES (2);
++UPDATE t1 SET a=0;
++DELETE FROM t1 LIMIT 1;
++SELECT * FROM t1;
++a
++1
++COMMIT;
++ERROR HY000: Got error 131 during COMMIT
++SET innodb_fake_changes=default;
++DROP TABLE t1;
++# DDL must result in error
++CREATE TABLE t1 (a INT) ENGINE=InnoDB;
++SET autocommit=0;
++SET innodb_fake_changes=1;
++BEGIN;
++CREATE TABLE t2 (a INT) ENGINE=InnoDB;
++ERROR HY000: Can't create table 'test.t2' (errno: 131)
++DROP TABLE t1;
++ERROR 42S02: Unknown table 't1'
++TRUNCATE TABLE t1;
++ERROR HY000: Got error 131 during COMMIT
++ALTER TABLE t1 ENGINE=MyISAM;
++ERROR HY000: Got error 131 during COMMIT
++ROLLBACK;
++SET innodb_fake_changes=default;
++DROP TABLE t1;
+--- /dev/null
++++ b/mysql-test/r/percona_innodb_fake_changes_locks.result
+@@ -0,0 +1,19 @@
++DROP TABLE IF EXISTS t1;
++# Verifying that X_LOCK not acquired
++CREATE TABLE t1 (a INT) ENGINE=InnoDB;
++INSERT INTO t1 VALUES (1);
++SET autocommit=0;
++SET innodb_fake_changes=1;
++BEGIN;
++SELECT * FROM t1 FOR UPDATE;
++a
++1
++SET innodb_lock_wait_timeout=3;
++UPDATE t1 SET a=2;
++ERROR HY000: Lock wait timeout exceeded; try restarting transaction
++SELECT * FROM t1 LOCK IN SHARE MODE;
++a
++1
++ROLLBACK;
++SET innodb_fake_changes=default;
++DROP TABLE t1;
+--- /dev/null
++++ b/mysql-test/t/percona_innodb_fake_changes.test
+@@ -0,0 +1,49 @@
++--source include/have_innodb_plugin.inc
++
++--disable_warnings
++DROP TABLE IF EXISTS t1;
++--enable_warnings
++
++
++--echo # Checking variables
++SHOW VARIABLES LIKE 'innodb_fake_changes';
++SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
++SET innodb_fake_changes=1;
++SHOW VARIABLES LIKE 'innodb_fake_changes';
++SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
++SET innodb_fake_changes=default;
++SHOW VARIABLES LIKE 'innodb_fake_changes';
++SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes';
++
++--echo # Explicit COMMIT should fail when innodb_fake_changes is enabled
++--echo # DML should be fine
++CREATE TABLE t1 (a INT) ENGINE=InnoDB;
++INSERT INTO t1 VALUES (1);
++SET autocommit=0;
++SET innodb_fake_changes=1;
++BEGIN;
++INSERT INTO t1 VALUES (2);
++UPDATE t1 SET a=0;
++DELETE FROM t1 LIMIT 1;
++SELECT * FROM t1;
++--error 1180
++COMMIT;
++SET innodb_fake_changes=default;
++DROP TABLE t1;
++
++--echo # DDL must result in error
++CREATE TABLE t1 (a INT) ENGINE=InnoDB;
++SET autocommit=0;
++SET innodb_fake_changes=1;
++BEGIN;
++--error 1005
++CREATE TABLE t2 (a INT) ENGINE=InnoDB;
++--error 1051
++DROP TABLE t1;
++--error 1180
++TRUNCATE TABLE t1;
++--error 1180
++ALTER TABLE t1 ENGINE=MyISAM;
++ROLLBACK;
++SET innodb_fake_changes=default;
++DROP TABLE t1;
+--- /dev/null
++++ b/mysql-test/t/percona_innodb_fake_changes_locks.test
+@@ -0,0 +1,24 @@
++--source include/have_innodb_plugin.inc
++
++--disable_warnings
++DROP TABLE IF EXISTS t1;
++--enable_warnings
++
++--echo # Verifying that X_LOCK not acquired
++CREATE TABLE t1 (a INT) ENGINE=InnoDB;
++INSERT INTO t1 VALUES (1);
++--connect (conn1,localhost,root,,)
++--connection conn1
++SET autocommit=0;
++SET innodb_fake_changes=1;
++BEGIN;
++SELECT * FROM t1 FOR UPDATE;
++--connection default
++SET innodb_lock_wait_timeout=3;
++--error 1205
++UPDATE t1 SET a=2;
++SELECT * FROM t1 LOCK IN SHARE MODE;
++--connection conn1
++ROLLBACK;
++SET innodb_fake_changes=default;
++DROP TABLE t1;
diff --git a/innodb_kill_idle_transaction.patch b/innodb_kill_idle_transaction.patch
new file mode 100644
index 0000000..9f7251c
--- /dev/null
+++ b/innodb_kill_idle_transaction.patch
@@ -0,0 +1,402 @@
+# name       : innodb_kill_idle_transaction.patch
+# introduced : 5.1.58
+# maintainer : Yasufumi
+#
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+--- a/include/mysql/plugin.h
++++ b/include/mysql/plugin.h
+@@ -847,6 +847,12 @@
+ */
+ void thd_set_ha_data(MYSQL_THD thd, const struct handlerton *hton,
+                      const void *ha_data);
++
++int thd_command(const MYSQL_THD thd);
++long long thd_start_time(const MYSQL_THD thd);
++void thd_kill(MYSQL_THD thd);
++#define EXTENDED_FOR_KILLIDLE
++
+ #ifdef __cplusplus
+ }
+ #endif
+--- a/include/mysql/plugin.h.pp
++++ b/include/mysql/plugin.h.pp
+@@ -150,3 +150,6 @@
+ void *thd_get_ha_data(const void* thd, const struct handlerton *hton);
+ void thd_set_ha_data(void* thd, const struct handlerton *hton,
+                      const void *ha_data);
++int thd_command(const void* thd);
++long long thd_start_time(const void* thd);
++void thd_kill(void* thd);
+--- a/sql/sql_class.cc
++++ b/sql/sql_class.cc
+@@ -470,6 +470,26 @@
+   return buffer;
+ }
+ 
++/* extend for kill session of idle transaction from engine */
++extern "C"
++int thd_command(const THD* thd)
++{
++  return (int) thd->command;
++}
++
++extern "C"
++long long thd_start_time(const THD* thd)
++{
++  return (long long) thd->start_time;
++}
++
++extern "C"
++void thd_kill(THD* thd)
++{
++  pthread_mutex_lock(&thd->LOCK_thd_data);
++  thd->awake(THD::KILL_CONNECTION);
++  pthread_mutex_unlock(&thd->LOCK_thd_data);
++}
+ 
+ /**
+   Implementation of Drop_table_error_handler::handle_error().
+--- a/storage/innodb_plugin/handler/ha_innodb.cc
++++ b/storage/innodb_plugin/handler/ha_innodb.cc
+@@ -2517,6 +2517,10 @@
+ 
+ 	innobase_commit_concurrency_init_default();
+ 
++#ifndef EXTENDED_FOR_KILLIDLE
++	srv_kill_idle_transaction = 0;
++#endif
++
+ 	/* Since we in this module access directly the fields of a trx
+ 	struct, and due to different headers and flags it might happen that
+ 	mutex_t has a different size in this module and in InnoDB
+@@ -11231,6 +11235,48 @@
+ 	return(false);
+ }
+ 
++/***********************************************************************
++functions for kill session of idle transaction */
++extern "C"
++ibool
++innobase_thd_is_idle(
++/*=================*/
++	const void*	thd)	/*!< in: thread handle (THD*) */
++{
++#ifdef EXTENDED_FOR_KILLIDLE
++	return(thd_command((const THD*) thd) == COM_SLEEP);
++#else
++	return(FALSE);
++#endif
++}
++
++extern "C"
++ib_int64_t
++innobase_thd_get_start_time(
++/*========================*/
++	const void*	thd)	/*!< in: thread handle (THD*) */
++{
++#ifdef EXTENDED_FOR_KILLIDLE
++	return((ib_int64_t)thd_start_time((const THD*) thd));
++#else
++	return(0); /*dummy value*/
++#endif
++}
++
++extern "C"
++void
++innobase_thd_kill(
++/*==============*/
++	void*	thd)
++{
++#ifdef EXTENDED_FOR_KILLIDLE
++	thd_kill((THD*) thd);
++#else
++	return;
++#endif
++}
++
++
+ static SHOW_VAR innodb_status_variables_export[]= {
+   {"Innodb",                   (char*) &show_innodb_vars, SHOW_FUNC},
+   {NullS, NullS, SHOW_LONG}
+@@ -11474,6 +11520,15 @@
+   "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
+   NULL, NULL, 500L, 1L, ~0L, 0);
+ 
++static MYSQL_SYSVAR_LONG(kill_idle_transaction, srv_kill_idle_transaction,
++  PLUGIN_VAR_RQCMDARG,
++#ifdef EXTENDED_FOR_KILLIDLE
++  "If non-zero value, the idle session with transaction which is idle over the value in seconds is killed by InnoDB.",
++#else
++  "No effect for this build.",
++#endif
++  NULL, NULL, 0, 0, LONG_MAX, 0);
++
+ static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
+   PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR,
+   "Number of file I/O threads in InnoDB.",
+@@ -11767,6 +11822,7 @@
+   MYSQL_SYSVAR(fast_checksum),
+   MYSQL_SYSVAR(commit_concurrency),
+   MYSQL_SYSVAR(concurrency_tickets),
++  MYSQL_SYSVAR(kill_idle_transaction),
+   MYSQL_SYSVAR(data_file_path),
+   MYSQL_SYSVAR(doublewrite_file),
+   MYSQL_SYSVAR(data_home_dir),
+--- a/storage/innodb_plugin/include/srv0srv.h
++++ b/storage/innodb_plugin/include/srv0srv.h
+@@ -282,6 +282,7 @@
+ extern ulint	srv_activity_count;
+ extern ulint	srv_fatal_semaphore_wait_threshold;
+ extern ulint	srv_dml_needed_delay;
++extern lint	srv_kill_idle_transaction;
+ 
+ extern mutex_t*	kernel_mutex_temp;/* mutex protecting the server, trx structs,
+ 				query threads, and lock table: we allocate
+--- a/storage/innodb_plugin/include/trx0trx.h
++++ b/storage/innodb_plugin/include/trx0trx.h
+@@ -600,6 +600,8 @@
+ 	ulint		mysql_process_no;/* since in Linux, 'top' reports
+ 					process id's and not thread id's, we
+ 					store the process number too */
++	time_t		idle_start;
++	ib_int64_t	last_stmt_start;
+ 	/*------------------------------*/
+ 	ulint		n_mysql_tables_in_use; /* number of Innobase tables
+ 					used in the processing of the current
+--- a/storage/innodb_plugin/srv/srv0srv.c
++++ b/storage/innodb_plugin/srv/srv0srv.c
+@@ -86,6 +86,11 @@
+ #include "trx0i_s.h"
+ #include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
+ 
++/* prototypes of new functions added to ha_innodb.cc for kill_idle_transaction */
++ibool		innobase_thd_is_idle(const void* thd);
++ib_int64_t	innobase_thd_get_start_time(const void* thd);
++void		innobase_thd_kill(void* thd);
++
+ /* prototypes for new functions added to ha_innodb.cc */
+ ibool	innobase_get_slow_log();
+ 
+@@ -100,6 +105,9 @@
+ /* The following is the maximum allowed duration of a lock wait. */
+ UNIV_INTERN ulint	srv_fatal_semaphore_wait_threshold = 600;
+ 
++/**/
++UNIV_INTERN lint	srv_kill_idle_transaction = 0;
++
+ /* How much data manipulation language (DML) statements need to be delayed,
+ in microseconds, in order to reduce the lagging of the purge thread. */
+ UNIV_INTERN ulint	srv_dml_needed_delay = 0;
+@@ -2557,6 +2565,36 @@
+ 		old_sema = sema;
+ 	}
+ 
++	if (srv_kill_idle_transaction && trx_sys) {
++		trx_t*	trx;
++		time_t	now;
++rescan_idle:
++		now = time(NULL);
++		mutex_enter(&kernel_mutex);
++		trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
++		while (trx) {
++			if (trx->conc_state == TRX_ACTIVE
++			    && trx->mysql_thd
++			    && innobase_thd_is_idle(trx->mysql_thd)) {
++				ib_int64_t	start_time; /* as stmt ID */
++
++				start_time = innobase_thd_get_start_time(trx->mysql_thd);
++				if (trx->last_stmt_start != start_time) {
++					trx->idle_start = now;
++					trx->last_stmt_start = start_time;
++				} else if (difftime(now, trx->idle_start)
++					   > srv_kill_idle_transaction) {
++					/* kill the session */
++					mutex_exit(&kernel_mutex);
++					innobase_thd_kill(trx->mysql_thd);
++					goto rescan_idle;
++				}
++			}
++			trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
++		}
++		mutex_exit(&kernel_mutex);
++	}
++
+ 	/* Flush stderr so that a database user gets the output
+ 	to possible MySQL error file */
+ 
+--- a/storage/innodb_plugin/trx/trx0trx.c
++++ b/storage/innodb_plugin/trx/trx0trx.c
+@@ -137,6 +137,9 @@
+ 	trx->mysql_relay_log_file_name = "";
+ 	trx->mysql_relay_log_pos = 0;
+ 
++	trx->idle_start = 0;
++	trx->last_stmt_start = 0;
++
+ 	mutex_create(&trx->undo_mutex, SYNC_TRX_UNDO);
+ 
+ 	trx->rseg = NULL;
+--- /dev/null
++++ b/mysql-test/r/percona_innodb_kill_idle_trx.result
+@@ -0,0 +1,41 @@
++DROP TABLE IF EXISTS t1;
++SET autocommit=0;
++CREATE TABLE t1 (a INT) ENGINE=InnoDB;
++SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
++Variable_name	Value
++innodb_kill_idle_transaction	0
++SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
++VARIABLE_NAME	VARIABLE_VALUE
++INNODB_KILL_IDLE_TRANSACTION	0
++SET GLOBAL innodb_kill_idle_transaction=1;
++SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
++Variable_name	Value
++innodb_kill_idle_transaction	1
++SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
++VARIABLE_NAME	VARIABLE_VALUE
++INNODB_KILL_IDLE_TRANSACTION	1
++BEGIN;
++INSERT INTO t1 VALUES (1),(2),(3);
++COMMIT;
++SELECT * FROM t1;
++a
++1
++2
++3
++BEGIN;
++INSERT INTO t1 VALUES (4),(5),(6);
++SELECT * FROM t1;
++ERROR HY000: MySQL server has gone away
++SELECT * FROM t1;
++a
++1
++2
++3
++DROP TABLE t1;
++SET GLOBAL innodb_kill_idle_transaction=0;
++SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
++Variable_name	Value
++innodb_kill_idle_transaction	0
++SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
++VARIABLE_NAME	VARIABLE_VALUE
++INNODB_KILL_IDLE_TRANSACTION	0
+--- /dev/null
++++ b/mysql-test/r/percona_innodb_kill_idle_trx_locks.result
+@@ -0,0 +1,45 @@
++DROP TABLE IF EXISTS t1;
++SET autocommit=0;
++CREATE TABLE t1 (a INT) ENGINE=InnoDB;
++SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
++Variable_name	Value
++innodb_kill_idle_transaction	0
++SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
++VARIABLE_NAME	VARIABLE_VALUE
++INNODB_KILL_IDLE_TRANSACTION	0
++SET GLOBAL innodb_kill_idle_transaction=5;
++SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
++Variable_name	Value
++innodb_kill_idle_transaction	5
++SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
++VARIABLE_NAME	VARIABLE_VALUE
++INNODB_KILL_IDLE_TRANSACTION	5
++BEGIN;
++INSERT INTO t1 VALUES (1),(2),(3);
++COMMIT;
++SELECT * FROM t1;
++a
++1
++2
++3
++### Locking rows. Lock should be released when idle trx is killed.
++BEGIN;
++SELECT * FROM t1 FOR UPDATE;
++a
++1
++2
++3
++UPDATE t1 set a=4;
++SELECT * FROM t1;
++a
++4
++4
++4
++DROP TABLE t1;
++SET GLOBAL innodb_kill_idle_transaction=0;
++SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
++Variable_name	Value
++innodb_kill_idle_transaction	0
++SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
++VARIABLE_NAME	VARIABLE_VALUE
++INNODB_KILL_IDLE_TRANSACTION	0
+--- /dev/null
++++ b/mysql-test/t/percona_innodb_kill_idle_trx.test
+@@ -0,0 +1,28 @@
++--source include/have_innodb.inc
++--disable_warnings
++DROP TABLE IF EXISTS t1; 
++--enable_warnings
++
++SET autocommit=0;
++CREATE TABLE t1 (a INT) ENGINE=InnoDB;
++
++--source include/percona_innodb_kill_idle_trx_show.inc
++SET GLOBAL innodb_kill_idle_transaction=1;
++--source include/percona_innodb_kill_idle_trx_show.inc
++
++BEGIN;
++INSERT INTO t1 VALUES (1),(2),(3);
++COMMIT;
++SELECT * FROM t1;
++
++BEGIN;
++INSERT INTO t1 VALUES (4),(5),(6);
++sleep 3;
++
++--enable_reconnect
++--error 2006 --error CR_SERVER_GONE_ERROR
++SELECT * FROM t1;
++SELECT * FROM t1;
++DROP TABLE t1;
++SET GLOBAL innodb_kill_idle_transaction=0;
++--source include/percona_innodb_kill_idle_trx_show.inc
+--- /dev/null
++++ b/mysql-test/t/percona_innodb_kill_idle_trx_locks.test
+@@ -0,0 +1,31 @@
++--source include/have_innodb.inc
++--disable_warnings
++DROP TABLE IF EXISTS t1;
++--enable_warnings
++
++SET autocommit=0;
++CREATE TABLE t1 (a INT) ENGINE=InnoDB;
++
++--source include/percona_innodb_kill_idle_trx_show.inc
++SET GLOBAL innodb_kill_idle_transaction=5;
++--source include/percona_innodb_kill_idle_trx_show.inc
++
++connect (conn1,localhost,root,,);
++connection conn1;
++
++BEGIN;
++INSERT INTO t1 VALUES (1),(2),(3);
++COMMIT;
++SELECT * FROM t1;
++
++--echo ### Locking rows. Lock should be released when idle trx is killed.
++BEGIN;
++SELECT * FROM t1 FOR UPDATE;
++
++connection default;
++UPDATE t1 set a=4;
++
++SELECT * FROM t1;
++DROP TABLE t1;
++SET GLOBAL innodb_kill_idle_transaction=0;
++--source include/percona_innodb_kill_idle_trx_show.inc
+--- /dev/null
++++ b/mysql-test/include/percona_innodb_kill_idle_trx_show.inc
+@@ -0,0 +1,2 @@
++SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
++SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
diff --git a/mysql-bug580324.patch b/mysql-bug580324.patch
index 01535b1..3459c76 100644
--- a/mysql-bug580324.patch
+++ b/mysql-bug580324.patch
@@ -24,7 +24,7 @@
      int4store(key + key_length, thd->server_id);
 --- a/sql/sql_parse.cc
 +++ b/sql/sql_parse.cc
-@@ -1342,10 +1342,12 @@
+@@ -1344,10 +1344,12 @@
      break;
  #else
    {
@@ -39,7 +39,7 @@
  
      /* used as fields initializator */
      lex_start(thd);
-@@ -1357,26 +1359,22 @@
+@@ -1359,26 +1361,22 @@
      /*
        We have name + wildcard in packet, separated by endzero
      */
@@ -77,7 +77,7 @@
  
      if (is_schema_db(table_list.db, table_list.db_length))
      {
-@@ -1385,9 +1383,6 @@
+@@ -1387,9 +1385,6 @@
          table_list.schema_table= schema_table;
      }
  
@@ -89,7 +89,7 @@
      if (lower_case_table_names)
 --- a/strings/ctype-utf8.c
 +++ b/strings/ctype-utf8.c
-@@ -4116,6 +4116,10 @@
+@@ -4118,6 +4118,10 @@
  {
    int code;
    char hex[]= "0123456789abcdef";
diff --git a/mysql-bugfix48929.patch b/mysql-bugfix48929.patch
index d97953f..266ba7b 100644
--- a/mysql-bugfix48929.patch
+++ b/mysql-bugfix48929.patch
@@ -18,7 +18,7 @@
   sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
 --- a/sql/mysqld.cc
 +++ b/sql/mysqld.cc
-@@ -55,6 +55,10 @@
+@@ -56,6 +56,10 @@
  #include "sp_rcontext.h"
  #include "sp_cache.h"
  
@@ -29,16 +29,25 @@
  #define mysqld_charset &my_charset_latin1
  
  #ifdef HAVE_purify
-@@ -5136,28 +5140,49 @@
+@@ -5137,31 +5141,58 @@
+ #ifndef EMBEDDED_LIBRARY
+ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
  {
-   my_socket sock,new_sock;
+-  my_socket sock,new_sock;
++  my_socket UNINIT_VAR(sock),new_sock;
    uint error_count=0;
 -  uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1);
 -  fd_set readFDs,clientFDs;
    THD *thd;
    struct sockaddr_in cAddr;
 -  int ip_flags=0,socket_flags=0,flags;
-+  int ip_flags=0,socket_flags=0,flags,retval;
++#if !defined(HAVE_POLL)
++  int ip_flags= 0;
++#endif
++#if defined(HAVE_SYS_UN_H) && !defined(HAVE_POLL)
++  int socket_flags= 0;
++#endif
++  int UNINIT_VAR(flags),retval;
    st_vio *vio_tmp;
 +#ifdef HAVE_POLL
 +  int socket_count= 0;
@@ -66,8 +75,9 @@
 +    socket_count++;
 +#else
      FD_SET(ip_sock,&clientFDs);
+-#ifdef HAVE_FCNTL
 +#endif
- #ifdef HAVE_FCNTL
++#if !defined (HAVE_POLL) && defined(HAVE_FCNTL)
      ip_flags = fcntl(ip_sock, F_GETFL, 0);
  #endif
    }
@@ -78,11 +88,13 @@
 +  socket_count++;
 +#else
    FD_SET(unix_sock,&clientFDs);
+-#ifdef HAVE_FCNTL
 +#endif
- #ifdef HAVE_FCNTL
++#if defined(HAVE_FCNTL) && defined(HAVE_SYS_UN_H) && !defined(HAVE_POLL)
    socket_flags=fcntl(unix_sock, F_GETFL, 0);
  #endif
-@@ -5167,12 +5192,15 @@
+ #endif
+@@ -5170,12 +5201,15 @@
    MAYBE_BROKEN_SYSCALL;
    while (!abort_loop)
    {
@@ -103,7 +115,7 @@
      {
        if (socket_errno != SOCKET_EINTR)
        {
-@@ -5182,7 +5210,7 @@
+@@ -5185,7 +5219,7 @@
        MAYBE_BROKEN_SYSCALL
        continue;
      }
@@ -112,7 +124,7 @@
      if (abort_loop)
      {
        MAYBE_BROKEN_SYSCALL;
-@@ -5190,6 +5218,21 @@
+@@ -5193,6 +5227,21 @@
      }
  
      /* Is this a new connection request ? */
@@ -134,7 +146,7 @@
  #ifdef HAVE_SYS_UN_H
      if (FD_ISSET(unix_sock,&readFDs))
      {
-@@ -5197,11 +5240,12 @@
+@@ -5200,11 +5249,12 @@
        flags= socket_flags;
      }
      else
diff --git a/mysql-control_online_alter_index.patch b/mysql-control_online_alter_index.patch
index 5c463cf..5a921fb 100644
--- a/mysql-control_online_alter_index.patch
+++ b/mysql-control_online_alter_index.patch
@@ -7,7 +7,7 @@
 # should be done or reviewed by the maintainer!
 --- a/sql/handler.h
 +++ b/sql/handler.h
-@@ -170,6 +170,19 @@
+@@ -171,6 +171,19 @@
  #define HA_ONLINE_DROP_UNIQUE_INDEX             (1L << 9) /*drop uniq. online*/
  #define HA_ONLINE_ADD_PK_INDEX                  (1L << 10)/*add prim. online*/
  #define HA_ONLINE_DROP_PK_INDEX                 (1L << 11)/*drop prim. online*/
@@ -29,7 +29,7 @@
    supported at all.
 --- a/sql/mysqld.cc
 +++ b/sql/mysqld.cc
-@@ -5911,6 +5911,7 @@
+@@ -5914,6 +5914,7 @@
    OPT_USERSTAT_RUNNING,
    OPT_THREAD_STATISTICS,
    OPT_OPTIMIZER_FIX,
@@ -37,7 +37,7 @@
    OPT_SUPPRESS_LOG_WARNING_1592,
    OPT_QUERY_CACHE_STRIP_COMMENTS,
    OPT_USE_GLOBAL_LONG_QUERY_TIME,
-@@ -5943,6 +5944,13 @@
+@@ -5946,6 +5947,13 @@
     "from libc.so",
     &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs,
     0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -53,7 +53,7 @@
     GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 --- a/sql/set_var.cc
 +++ b/sql/set_var.cc
-@@ -758,6 +758,11 @@
+@@ -760,6 +760,11 @@
  sys_engine_condition_pushdown(&vars, "engine_condition_pushdown",
  			      &SV::engine_condition_pushdown);
  
@@ -67,7 +67,7 @@
  static sys_var_thd_ulong
 --- a/sql/sql_class.h
 +++ b/sql/sql_class.h
-@@ -381,6 +381,8 @@
+@@ -383,6 +383,8 @@
    my_bool ndb_use_transactions;
    my_bool ndb_index_stat_enable;
  
@@ -94,7 +94,7 @@
        DBUG_RETURN(1);
 --- a/sql/sql_table.cc
 +++ b/sql/sql_table.cc
-@@ -7005,6 +7005,10 @@
+@@ -7023,6 +7023,10 @@
      uint  *idx_end_p;
  
      alter_flags= table->file->alter_table_flags(alter_info->flags);
diff --git a/mysql-error_pad.patch b/mysql-error_pad.patch
index c97b181..5402dab 100644
--- a/mysql-error_pad.patch
+++ b/mysql-error_pad.patch
@@ -7,7 +7,7 @@
 # should be done or reviewed by the maintainer!
 --- a/extra/comp_err.c
 +++ b/extra/comp_err.c
-@@ -30,11 +30,12 @@
+@@ -32,11 +32,12 @@
  #include <assert.h>
  #include <my_dir.h>
  
@@ -21,7 +21,7 @@
  static char *OUTFILE= (char*) "errmsg.sys";
  static char *HEADERFILE= (char*) "mysqld_error.h";
  static char *NAMEFILE= (char*) "mysqld_ername.h";
-@@ -89,6 +90,7 @@
+@@ -91,6 +92,7 @@
    const char *sql_code1;		/* sql state */
    const char *sql_code2;		/* ODBC state */
    struct errors *next_error;            /* Pointer to next error */
@@ -29,7 +29,7 @@
    DYNAMIC_ARRAY msg;                    /* All language texts for this error */
  };
  
-@@ -127,6 +129,7 @@
+@@ -129,6 +131,7 @@
  
  
  static struct languages *parse_charset_string(char *str);
@@ -37,7 +37,7 @@
  static struct errors *parse_error_string(char *ptr, int er_count);
  static struct message *parse_message_string(struct message *new_message,
  					    char *str);
-@@ -229,6 +232,11 @@
+@@ -231,6 +234,11 @@
  
    for (tmp_error= error_head; tmp_error; tmp_error= tmp_error->next_error)
    {
@@ -49,7 +49,7 @@
      /*
         generating mysqld_error.h
         fprintf() will automatically add \r on windows
-@@ -318,12 +326,29 @@
+@@ -320,12 +328,29 @@
  		"language\n", tmp_error->er_name, tmp_lang->lang_short_name);
  	goto err;
        }
@@ -83,7 +83,7 @@
      }
  
      /* continue with header of the errmsg.sys file */
-@@ -474,14 +499,26 @@
+@@ -476,14 +501,26 @@
  	DBUG_RETURN(0);
        continue;
      }
@@ -115,7 +115,7 @@
  
        /* add error to the list */
        *tail_error= current_error;
-@@ -822,78 +859,122 @@
+@@ -824,78 +861,122 @@
    DBUG_RETURN(new_message);
  }
  
diff --git a/mysql-i_s_innodb_buffer_pool_pages.patch b/mysql-i_s_innodb_buffer_pool_pages.patch
index fb7bc48..857053d 100644
--- a/mysql-i_s_innodb_buffer_pool_pages.patch
+++ b/mysql-i_s_innodb_buffer_pool_pages.patch
@@ -24,7 +24,7 @@
  /********************************************************************//**
 --- a/storage/innodb_plugin/handler/ha_innodb.cc
 +++ b/storage/innodb_plugin/handler/ha_innodb.cc
-@@ -11252,6 +11252,9 @@
+@@ -11248,6 +11248,9 @@
    innobase_system_variables, /* system variables */
    NULL /* reserved */
  },
@@ -773,7 +773,7 @@
  };
 --- a/storage/innodb_plugin/include/buf0buf.h
 +++ b/storage/innodb_plugin/include/buf0buf.h
-@@ -1286,6 +1286,15 @@
+@@ -1334,6 +1334,15 @@
  #define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
  /* @} */
  
diff --git a/mysql-innodb_adjust_defaults.patch b/mysql-innodb_adjust_defaults.patch
index eb8302b..fef2378 100644
--- a/mysql-innodb_adjust_defaults.patch
+++ b/mysql-innodb_adjust_defaults.patch
@@ -7,7 +7,7 @@
 # should be done or reviewed by the maintainer!
 --- a/storage/innodb_plugin/handler/ha_innodb.cc
 +++ b/storage/innodb_plugin/handler/ha_innodb.cc
-@@ -11296,7 +11296,7 @@
+@@ -11290,7 +11290,7 @@
  static MYSQL_SYSVAR_ULONG(use_purge_thread, srv_use_purge_thread,
    PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
    "Number of purge devoted threads. #### over 1 is EXPERIMENTAL ####",
@@ -16,7 +16,7 @@
  
  static MYSQL_SYSVAR_BOOL(overwrite_relay_log_info, innobase_overwrite_relay_log_info,
    PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
-@@ -11396,7 +11396,7 @@
+@@ -11390,7 +11390,7 @@
  static MYSQL_SYSVAR_BOOL(adaptive_flushing, srv_adaptive_flushing,
    PLUGIN_VAR_NOCMDARG,
    "Attempt flushing dirty pages to avoid IO bursts at checkpoints.",
@@ -25,7 +25,7 @@
  
  static MYSQL_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
    PLUGIN_VAR_RQCMDARG,
-@@ -11629,7 +11629,7 @@
+@@ -11628,7 +11628,7 @@
  static MYSQL_SYSVAR_ULONG(ibuf_active_contract, srv_ibuf_active_contract,
    PLUGIN_VAR_RQCMDARG,
    "Enable/Disable active_contract of insert buffer. 0:disable 1:enable",
@@ -34,7 +34,7 @@
  
  static MYSQL_SYSVAR_ULONG(ibuf_accel_rate, srv_ibuf_accel_rate,
    PLUGIN_VAR_RQCMDARG,
-@@ -11709,8 +11709,8 @@
+@@ -11708,8 +11708,8 @@
  };
  static MYSQL_SYSVAR_ENUM(adaptive_checkpoint, srv_adaptive_checkpoint,
    PLUGIN_VAR_RQCMDARG,
diff --git a/mysql-innodb_admin_command_base.patch b/mysql-innodb_admin_command_base.patch
index 6ec2d8a..7e8bdae 100644
--- a/mysql-innodb_admin_command_base.patch
+++ b/mysql-innodb_admin_command_base.patch
@@ -7,18 +7,18 @@
 # should be done or reviewed by the maintainer!
 --- a/storage/innodb_plugin/handler/ha_innodb.cc
 +++ b/storage/innodb_plugin/handler/ha_innodb.cc
-@@ -11608,6 +11608,7 @@
+@@ -11530,6 +11530,7 @@
+ i_s_innodb_cmp_reset,
+ i_s_innodb_cmpmem,
  i_s_innodb_cmpmem_reset,
- i_s_innodb_table_stats,
- i_s_innodb_index_stats,
 +i_s_innodb_admin_command,
  i_s_innodb_patches
  mysql_declare_plugin_end;
  
 --- a/storage/innodb_plugin/handler/i_s.cc
 +++ b/storage/innodb_plugin/handler/i_s.cc
-@@ -2947,3 +2947,139 @@
- 	STRUCT_FLD(system_vars, NULL),
+@@ -2602,3 +2602,139 @@
+ 	/* void* */
  	STRUCT_FLD(__reserved1, NULL)
  };
 +
@@ -159,17 +159,17 @@
 +};
 --- a/storage/innodb_plugin/handler/i_s.h
 +++ b/storage/innodb_plugin/handler/i_s.h
-@@ -40,5 +40,6 @@
+@@ -38,5 +38,6 @@
+ extern struct st_mysql_plugin	i_s_innodb_cmpmem_reset;
+ extern struct st_mysql_plugin	i_s_innodb_patches;
  extern struct st_mysql_plugin	i_s_innodb_rseg;
- extern struct st_mysql_plugin	i_s_innodb_table_stats;
- extern struct st_mysql_plugin	i_s_innodb_index_stats;
 +extern struct st_mysql_plugin	i_s_innodb_admin_command;
  
  #endif /* i_s_h */
 --- a/storage/innodb_plugin/handler/innodb_patch_info.h
 +++ b/storage/innodb_plugin/handler/innodb_patch_info.h
-@@ -38,5 +38,6 @@
- {"innodb_stats","Additional features about InnoDB statistics/optimizer","","http://www.percona.com/docs/wiki/percona-xtradb"},
+@@ -37,5 +37,6 @@
+ {"innodb_split_buf_pool_mutex","More fix of buffer_pool mutex","Spliting buf_pool_mutex and optimizing based on innodb_opt_lru_count","http://www.percona.com/docs/wiki/percona-xtradb"},
  {"innodb_recovery_patches","Bugfixes and adjustments about recovery process","","http://www.percona.com/docs/wiki/percona-xtradb"},
  {"innodb_purge_thread","Enable to use purge devoted thread","","http://www.percona.com/docs/wiki/percona-xtradb"},
 +{"innodb_admin_command_base","XtraDB specific command interface through i_s","","http://www.percona.com/docs/wiki/percona-xtradb"},
diff --git a/mysql-innodb_buffer_pool_shm.patch b/mysql-innodb_buffer_pool_shm.patch
index d6ae663..e57fd18 100644
--- a/mysql-innodb_buffer_pool_shm.patch
+++ b/mysql-innodb_buffer_pool_shm.patch
@@ -42,7 +42,7 @@
  
  static char*	internal_innobase_data_file_path	= NULL;
  
-@@ -2460,6 +2462,12 @@
+@@ -2472,6 +2474,12 @@
  
  	srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
  
@@ -55,7 +55,7 @@
  	srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
  
  	srv_n_file_io_threads = (ulint) innobase_file_io_threads;
-@@ -11472,6 +11480,16 @@
+@@ -11556,6 +11564,16 @@
    "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
    NULL, NULL, 128*1024*1024L, 32*1024*1024L, LONGLONG_MAX, 1024*1024L);
  
@@ -72,7 +72,7 @@
  static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
    PLUGIN_VAR_RQCMDARG,
    "Helps in performance tuning in heavily concurrent environments.",
-@@ -11760,6 +11778,8 @@
+@@ -11864,6 +11882,8 @@
    MYSQL_SYSVAR(additional_mem_pool_size),
    MYSQL_SYSVAR(autoextend_increment),
    MYSQL_SYSVAR(buffer_pool_size),
diff --git a/mysql-innodb_deadlock_count.patch b/mysql-innodb_deadlock_count.patch
index 86723f3..4c31dca 100644
--- a/mysql-innodb_deadlock_count.patch
+++ b/mysql-innodb_deadlock_count.patch
@@ -7,7 +7,7 @@
 # should be done or reviewed by the maintainer!
 --- a/storage/innodb_plugin/handler/ha_innodb.cc
 +++ b/storage/innodb_plugin/handler/ha_innodb.cc
-@@ -566,6 +566,8 @@
+@@ -576,6 +576,8 @@
    (char*) &export_vars.innodb_data_written,		  SHOW_LONG},
    {"dblwr_pages_written",
    (char*) &export_vars.innodb_dblwr_pages_written,	  SHOW_LONG},
@@ -28,8 +28,8 @@
  Gets the size of a lock struct.
 --- a/storage/innodb_plugin/include/srv0srv.h
 +++ b/storage/innodb_plugin/include/srv0srv.h
-@@ -689,6 +689,7 @@
- 	ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */
+@@ -695,6 +695,7 @@
+ 	ulint innodb_buffer_pool_read_ahead_rnd;/*!< srv_read_ahead_rnd */
  	ulint innodb_buffer_pool_read_ahead;	/*!< srv_read_ahead */
  	ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/
 +        ulint innodb_deadlocks;                 /* ??? */
@@ -48,7 +48,7 @@
  		break;
 --- a/storage/innodb_plugin/srv/srv0srv.c
 +++ b/storage/innodb_plugin/srv/srv0srv.c
-@@ -444,7 +444,7 @@
+@@ -458,7 +458,7 @@
  static ulint	srv_n_rows_updated_old		= 0;
  static ulint	srv_n_rows_deleted_old		= 0;
  static ulint	srv_n_rows_read_old		= 0;
@@ -57,7 +57,7 @@
  UNIV_INTERN ulint		srv_n_lock_wait_count		= 0;
  UNIV_INTERN ulint		srv_n_lock_wait_current_count	= 0;
  UNIV_INTERN ib_int64_t	srv_n_lock_wait_time		= 0;
-@@ -2155,6 +2155,8 @@
+@@ -2171,6 +2171,8 @@
  		= UT_LIST_GET_LEN(buf_pool->flush_list);
  	export_vars.innodb_buffer_pool_pages_free
  		= UT_LIST_GET_LEN(buf_pool->free);
diff --git a/mysql-innodb_dict_size_limit.patch b/mysql-innodb_dict_size_limit.patch
index 13e3713..c7c2d45 100644
--- a/mysql-innodb_dict_size_limit.patch
+++ b/mysql-innodb_dict_size_limit.patch
@@ -338,7 +338,7 @@
  	info = index->search_info;
 --- a/storage/innodb_plugin/handler/ha_innodb.cc
 +++ b/storage/innodb_plugin/handler/ha_innodb.cc
-@@ -560,6 +560,8 @@
+@@ -562,6 +562,8 @@
    (char*) &export_vars.innodb_dblwr_pages_written,	  SHOW_LONG},
    {"dblwr_writes",
    (char*) &export_vars.innodb_dblwr_writes,		  SHOW_LONG},
@@ -347,7 +347,7 @@
    {"have_atomic_builtins",
    (char*) &export_vars.innodb_have_atomic_builtins,	  SHOW_BOOL},
    {"log_waits",
-@@ -11386,6 +11388,11 @@
+@@ -11381,6 +11383,11 @@
    "Number of extra user rollback segments when create new database.",
    NULL, NULL, 0, 0, 126, 0);
  
@@ -359,7 +359,7 @@
  static struct st_mysql_sys_var* innobase_system_variables[]= {
    MYSQL_SYSVAR(additional_mem_pool_size),
    MYSQL_SYSVAR(autoextend_increment),
-@@ -11454,6 +11461,7 @@
+@@ -11449,6 +11456,7 @@
    MYSQL_SYSVAR(flush_log_at_trx_commit_session),
    MYSQL_SYSVAR(enable_unsafe_group_commit),
    MYSQL_SYSVAR(extra_rsegments),
@@ -448,7 +448,7 @@
  	/* TODO: should get the type information from MySQL */
 --- a/storage/innodb_plugin/include/srv0srv.h
 +++ b/storage/innodb_plugin/include/srv0srv.h
-@@ -219,7 +219,7 @@
+@@ -220,7 +220,7 @@
  extern ulint	srv_adaptive_checkpoint;
  
  extern ulint	srv_extra_rsegments;
@@ -457,7 +457,7 @@
  /*-------------------------------------------*/
  
  extern ulint	srv_n_rows_inserted;
-@@ -625,6 +625,7 @@
+@@ -626,6 +626,7 @@
  	ulint innodb_data_writes;		/*!< I/O write requests */
  	ulint innodb_data_written;		/*!< Data bytes written */
  	ulint innodb_data_reads;		/*!< I/O read requests */
@@ -467,7 +467,7 @@
  	ulint innodb_buffer_pool_pages_dirty;	/*!< Dirty data pages */
 --- a/storage/innodb_plugin/srv/srv0srv.c
 +++ b/storage/innodb_plugin/srv/srv0srv.c
-@@ -391,6 +391,7 @@
+@@ -393,6 +393,7 @@
  UNIV_INTERN ulint	srv_adaptive_checkpoint = 0; /* 0: none  1: reflex  2: estimate */
  
  UNIV_INTERN ulint	srv_extra_rsegments = 0; /* extra rseg for users */
@@ -475,7 +475,7 @@
  /*-------------------------------------------*/
  UNIV_INTERN ulong	srv_n_spin_wait_rounds	= 30;
  UNIV_INTERN ulong	srv_n_free_tickets_to_enter = 500;
-@@ -2091,6 +2092,7 @@
+@@ -2093,6 +2094,7 @@
  	export_vars.innodb_data_reads = os_n_file_reads;
  	export_vars.innodb_data_writes = os_n_file_writes;
  	export_vars.innodb_data_written = srv_data_written;
diff --git a/mysql-innodb_expand_fast_index_creation.patch b/mysql-innodb_expand_fast_index_creation.patch
index 091d54b..15e5437 100644
--- a/mysql-innodb_expand_fast_index_creation.patch
+++ b/mysql-innodb_expand_fast_index_creation.patch
@@ -7,7 +7,7 @@
 #
 --- a/client/client_priv.h
 +++ b/client/client_priv.h
-@@ -97,5 +97,6 @@
+@@ -99,5 +99,6 @@
    OPT_FIRST_SLAVE,
    OPT_ALL,
    OPT_NO_REMOVE_EOL_CARRET,
@@ -16,7 +16,7 @@
  };
 --- a/client/mysqldump.c
 +++ b/client/mysqldump.c
-@@ -45,6 +45,7 @@
+@@ -47,6 +47,7 @@
  #include <m_ctype.h>
  #include <hash.h>
  #include <stdarg.h>
@@ -24,7 +24,7 @@
  
  #include "client_priv.h"
  #include "mysql.h"
-@@ -134,6 +135,8 @@
+@@ -138,6 +139,8 @@
  
  static my_bool server_supports_sql_no_fcache= FALSE;
  
@@ -33,7 +33,7 @@
  /*
  Dynamic_string wrapper functions. In this file use these
  wrappers, they will terminate the process if there is
-@@ -179,6 +182,8 @@
+@@ -183,6 +186,8 @@
  
  HASH ignore_table;
  
@@ -42,7 +42,7 @@
  static struct my_option my_long_options[] =
  {
    {"all", OPT_ALL, "Deprecated. Use --create-options instead.",
-@@ -325,6 +330,11 @@
+@@ -329,6 +334,11 @@
     "be specified with both database and table names, e.g., "
     "--ignore-table=database.table.",
     0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -54,7 +54,7 @@
    {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.",
     &opt_ignore, &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
     0, 0},
-@@ -2246,6 +2256,128 @@
+@@ -2249,6 +2259,189 @@
  }
  
  /*
@@ -83,21 +83,24 @@
 +  SYNOPSIS
 +    skip_secondary_keys()
 +    create_str                SHOW CREATE TABLE output
++    has_pk                    TRUE, if the table has PRIMARY KEY
++                              (or UNIQUE key on non-nullable columns)
 +
 +
 +  DESCRIPTION
 +
-+    Stores all lines starting with "KEY" or "UNIQUE KEY" or "CONSTRAINT"
++    Stores all lines starting with "KEY" or "UNIQUE KEY"
 +    into skipped_keys_list and removes them from the input string.
 +    Ignoring FOREIGN KEYS constraints when creating the table is ok, because
 +    mysqldump sets foreign_key_checks to 0 anyway.
 +*/
 +
-+static void skip_secondary_keys(char *create_str)
++static void skip_secondary_keys(char *create_str, my_bool has_pk)
 +{
 +  char *ptr, *strend;
 +  char *last_comma = NULL;
 +  HASH ignored_columns;
++  my_bool pk_processed= FALSE;
 +
 +  if (hash_init(&ignored_columns, charset_info, 16, 0, 0,
 +                (hash_get_key) get_table_key,
@@ -110,6 +113,7 @@
 +  while (*ptr)
 +  {
 +    char *tmp, *orig_ptr, c;
++    my_bool UNINIT_VAR(is_unique);
 +
 +    orig_ptr= ptr;
 +    /* Skip leading whitespace */
@@ -124,9 +128,9 @@
 +
 +    /* Is it a secondary index definition? */
 +    if (c == '\n' &&
-+        (!strncmp(ptr, "UNIQUE KEY ", sizeof("UNIQUE KEY ") - 1) ||
-+         !strncmp(ptr, "KEY ", sizeof("KEY ") - 1) ||
-+         !strncmp(ptr, "CONSTRAINT ", sizeof("CONSTRAINT ") - 1)) &&
++        (((is_unique= !strncmp(ptr, "UNIQUE KEY ", sizeof("UNIQUE KEY ")-1)) &&
++          (pk_processed || !has_pk)) ||
++         !strncmp(ptr, "KEY ", sizeof("KEY ") - 1)) &&
 +        !contains_ignored_column(&ignored_columns, ptr))
 +    {
 +      char *data, *end= tmp - 1;
@@ -145,13 +149,25 @@
 +      if (last_comma != NULL)
 +      {
 +        *last_comma= ' ';
-+        last_comma = NULL;
 +      }
 +    }
 +    else
 +    {
 +      char *end;
 +
++      if (last_comma != NULL && *ptr != ')')
++      {
++        /*
++          It's not the last line of CREATE TABLE, so we have skipped a key
++          definition. We have to restore the last removed comma.
++        */
++        *last_comma= ',';
++      }
++
++      if ((has_pk && is_unique && !pk_processed) ||
++          !strncmp(ptr, "PRIMARY KEY ", sizeof("PRIMARY KEY ") - 1))
++        pk_processed= TRUE;
++
 +      if (strstr(ptr, "AUTO_INCREMENT") && *ptr == '`')
 +      {
 +        /*
@@ -180,20 +196,83 @@
 +}
 +
 +/*
++  Check if the table has a primary key defined either explicitly or
++  implicitly (i.e. a unique key on non-nullable columns).
++
++  SYNOPSIS
++    my_bool has_primary_key(const char *table_name)
++
++    table_name  quoted table name
++
++  RETURNS     TRUE if the table has a primary key
++
++  DESCRIPTION
++*/
++
++static my_bool has_primary_key(const char *table_name)
++{
++  MYSQL_RES  *res= NULL;
++  MYSQL_ROW  row;
++  char query_buff[QUERY_LENGTH];
++  my_bool has_pk= TRUE;
++
++  my_snprintf(query_buff, sizeof(query_buff),
++              "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE "
++              "TABLE_SCHEMA=DATABASE() AND TABLE_NAME='%s' AND "
++              "COLUMN_KEY='PRI'", table_name);
++  if (mysql_query(mysql, query_buff) || !(res= mysql_store_result(mysql)) ||
++      !(row= mysql_fetch_row(res)))
++  {
++    fprintf(stderr, "Warning: Couldn't determine if table %s has a "
++            "primary key (%s). "
++            "--innodb-optimize-keys may work inefficiently.\n",
++            table_name, mysql_error(mysql));
++    goto cleanup;
++  }
++
++  has_pk= atoi(row[0]) > 0;
++
++cleanup:
++  if (res)
++    mysql_free_result(res);
++
++  return has_pk;
++}
++
++
++/*
    get_table_structure -- retrievs database structure, prints out corresponding
    CREATE statement and fills out insert_pat if the table is the type we will
    be dumping.
-@@ -2486,6 +2618,9 @@
+@@ -2285,6 +2478,7 @@
+   int        len;
+   MYSQL_RES  *result;
+   MYSQL_ROW  row;
++  my_bool    UNINIT_VAR(has_pk);
+   DBUG_ENTER("get_table_structure");
+   DBUG_PRINT("enter", ("db: %s  table: %s", db, table));
+ 
+@@ -2326,6 +2520,9 @@
+   result_table=     quote_name(table, table_buff, 1);
+   opt_quoted_table= quote_name(table, table_buff2, 0);
+ 
++  if (opt_innodb_optimize_keys && !strcmp(table_type, "InnoDB"))
++    has_pk= has_primary_key(table);
++
+   if (opt_order_by_primary)
+     order_by= primary_key_fields(result_table);
+ 
+@@ -2489,6 +2686,9 @@
  
        row= mysql_fetch_row(result);
  
 +      if (opt_innodb_optimize_keys && !strcmp(table_type, "InnoDB"))
-+        skip_secondary_keys(row[1]);
++        skip_secondary_keys(row[1], has_pk);
 +
        fprintf(sql_file, (opt_compatible_mode & 3) ? "%s;\n" :
                "/*!40101 SET @saved_cs_client     = @@character_set_client */;\n"
                "/*!40101 SET character_set_client = utf8 */;\n"
-@@ -3578,6 +3713,27 @@
+@@ -3581,6 +3781,27 @@
        goto err;
      }
  
@@ -223,7 +302,7 @@
      {
 --- /dev/null
 +++ b/mysql-test/r/percona_mysqldump_innodb_optimize_keys.result
-@@ -0,0 +1,171 @@
+@@ -0,0 +1,367 @@
 +#
 +# Test the --innodb-optimize-keys option.
 +#
@@ -297,14 +376,15 @@
 +  `a` int(11) DEFAULT NULL,
 +  `b` varchar(255) DEFAULT NULL,
 +  `c` decimal(10,3) DEFAULT NULL,
-+  PRIMARY KEY (`id`) 
++  PRIMARY KEY (`id`),
++  CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t2` (`a`) ON DELETE CASCADE
 +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
 +/*!40101 SET character_set_client = @saved_cs_client */;
 +
 +LOCK TABLES `t1` WRITE;
 +/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
 +INSERT INTO `t1` VALUES (1,0,'0','0.000'),(2,1,'1','1.100'),(3,2,'2','2.200');
-+ALTER TABLE `t1` ADD UNIQUE KEY `uniq` (`c`,`a`), ADD KEY `b` (`b`), ADD KEY `a` (`a`), ADD CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t2` (`a`) ON DELETE CASCADE;
++ALTER TABLE `t1` ADD UNIQUE KEY `uniq` (`c`,`a`), ADD KEY `b` (`b`), ADD KEY `a` (`a`);
 +/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
 +UNLOCK TABLES;
 +DROP TABLE IF EXISTS `t2`;
@@ -395,31 +475,201 @@
 +
 +######################################
 +DROP TABLE t1, t2;
---- a/mysql-test/suite/innodb_plugin/r/innodb.result
-+++ b/mysql-test/suite/innodb_plugin/r/innodb.result
-@@ -1679,7 +1679,7 @@
- 71
- SELECT variable_value - @innodb_rows_inserted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_inserted';
- variable_value - @innodb_rows_inserted_orig
--1067
-+1109
- SELECT variable_value - @innodb_rows_updated_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_updated';
- variable_value - @innodb_rows_updated_orig
- 866
---- a/mysql-test/suite/innodb_plugin/t/innodb-index.test
-+++ b/mysql-test/suite/innodb_plugin/t/innodb-index.test
-@@ -97,6 +97,11 @@
- show create table t1;
- --error ER_MULTIPLE_PRI_KEY
- alter table t1 add primary key (c);
-+# Suppress the error log messages occuring on duplicate key error
-+# during ALTER TABLE when using fast index creation
-+--disable_query_log
-+call mtr.add_suppression("Cannot find index PRIMARY in InnoDB index translation table.");
-+--enable_query_log
- --error ER_DUP_ENTRY
- alter table t1 drop primary key, add primary key (b);
- create unique index c on t1 (c);
++CREATE TABLE t1 (
++a INT NOT NULL,
++UNIQUE KEY (a)) ENGINE=InnoDB;
++CREATE TABLE t2 (
++a INT NOT NULL,
++b INT NOT NULL,
++UNIQUE KEY (a,b)) ENGINE=InnoDB;
++CREATE TABLE t3 (
++a INT,
++b INT,
++UNIQUE KEY (a,b)) ENGINE=InnoDB;
++CREATE TABLE t4 (
++a INT NOT NULL,
++b INT NOT NULL,
++PRIMARY KEY (a,b),
++UNIQUE KEY(b)) ENGINE=InnoDB;
++SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
++TABLE_SCHEMA=DATABASE() AND
++TABLE_NAME='t1' AND
++COLUMN_KEY='PRI';
++COUNT(*)
++1
++SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
++TABLE_SCHEMA=DATABASE() AND
++TABLE_NAME='t2' AND
++COLUMN_KEY='PRI';
++COUNT(*)
++2
++SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
++TABLE_SCHEMA=DATABASE() AND
++TABLE_NAME='t3' AND
++COLUMN_KEY='PRI';
++COUNT(*)
++0
++SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
++TABLE_SCHEMA=DATABASE() AND
++TABLE_NAME='t4' AND
++COLUMN_KEY='PRI';
++COUNT(*)
++2
++INSERT INTO t1 VALUES (1), (2), (3);
++INSERT INTO t2 VALUES (1,1), (2,2), (3,3);
++INSERT INTO t3 SELECT * FROM t2;
++INSERT INTO t4 SELECT * FROM t2;
++######################################
++
++/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
++/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
++/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
++/*!40101 SET NAMES utf8 */;
++/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
++/*!40103 SET TIME_ZONE='+00:00' */;
++/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
++/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
++/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
++/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
++DROP TABLE IF EXISTS `t1`;
++/*!40101 SET @saved_cs_client     = @@character_set_client */;
++/*!40101 SET character_set_client = utf8 */;
++CREATE TABLE `t1` (
++  `a` int(11) NOT NULL,
++  UNIQUE KEY `a` (`a`)
++) ENGINE=InnoDB DEFAULT CHARSET=latin1;
++/*!40101 SET character_set_client = @saved_cs_client */;
++
++LOCK TABLES `t1` WRITE;
++/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
++INSERT INTO `t1` VALUES (1),(2),(3);
++/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
++UNLOCK TABLES;
++DROP TABLE IF EXISTS `t2`;
++/*!40101 SET @saved_cs_client     = @@character_set_client */;
++/*!40101 SET character_set_client = utf8 */;
++CREATE TABLE `t2` (
++  `a` int(11) NOT NULL,
++  `b` int(11) NOT NULL,
++  UNIQUE KEY `a` (`a`,`b`)
++) ENGINE=InnoDB DEFAULT CHARSET=latin1;
++/*!40101 SET character_set_client = @saved_cs_client */;
++
++LOCK TABLES `t2` WRITE;
++/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
++INSERT INTO `t2` VALUES (1,1),(2,2),(3,3);
++/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
++UNLOCK TABLES;
++DROP TABLE IF EXISTS `t3`;
++/*!40101 SET @saved_cs_client     = @@character_set_client */;
++/*!40101 SET character_set_client = utf8 */;
++CREATE TABLE `t3` (
++  `a` int(11) DEFAULT NULL,
++  `b` int(11) DEFAULT NULL 
++) ENGINE=InnoDB DEFAULT CHARSET=latin1;
++/*!40101 SET character_set_client = @saved_cs_client */;
++
++LOCK TABLES `t3` WRITE;
++/*!40000 ALTER TABLE `t3` DISABLE KEYS */;
++INSERT INTO `t3` VALUES (1,1),(2,2),(3,3);
++ALTER TABLE `t3` ADD UNIQUE KEY `a` (`a`,`b`);
++/*!40000 ALTER TABLE `t3` ENABLE KEYS */;
++UNLOCK TABLES;
++DROP TABLE IF EXISTS `t4`;
++/*!40101 SET @saved_cs_client     = @@character_set_client */;
++/*!40101 SET character_set_client = utf8 */;
++CREATE TABLE `t4` (
++  `a` int(11) NOT NULL,
++  `b` int(11) NOT NULL,
++  PRIMARY KEY (`a`,`b`) 
++) ENGINE=InnoDB DEFAULT CHARSET=latin1;
++/*!40101 SET character_set_client = @saved_cs_client */;
++
++LOCK TABLES `t4` WRITE;
++/*!40000 ALTER TABLE `t4` DISABLE KEYS */;
++INSERT INTO `t4` VALUES (1,1),(2,2),(3,3);
++ALTER TABLE `t4` ADD UNIQUE KEY `b` (`b`);
++/*!40000 ALTER TABLE `t4` ENABLE KEYS */;
++UNLOCK TABLES;
++/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
++
++/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
++/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
++/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
++/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
++/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
++/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
++/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
++
++######################################
++DROP TABLE t1, t2, t3, t4;
++CREATE TABLE t1 (
++id INT NOT NULL PRIMARY KEY
++) ENGINE=InnoDB;
++CREATE TABLE t2 (
++id INT NOT NULL AUTO_INCREMENT,
++a INT NOT NULL,
++PRIMARY KEY (id),
++KEY (a),
++FOREIGN KEY (a) REFERENCES t2 (id)
++) ENGINE=InnoDB;
++INSERT INTO t1 VALUES (1), (2), (3);
++INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3);
++######################################
++
++/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
++/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
++/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
++/*!40101 SET NAMES utf8 */;
++/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
++/*!40103 SET TIME_ZONE='+00:00' */;
++/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
++/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
++/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
++/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
++DROP TABLE IF EXISTS `t1`;
++/*!40101 SET @saved_cs_client     = @@character_set_client */;
++/*!40101 SET character_set_client = utf8 */;
++CREATE TABLE `t1` (
++  `id` int(11) NOT NULL,
++  PRIMARY KEY (`id`)
++) ENGINE=InnoDB DEFAULT CHARSET=latin1;
++/*!40101 SET character_set_client = @saved_cs_client */;
++
++LOCK TABLES `t1` WRITE;
++/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
++INSERT INTO `t1` VALUES (1),(2),(3);
++/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
++UNLOCK TABLES;
++DROP TABLE IF EXISTS `t2`;
++/*!40101 SET @saved_cs_client     = @@character_set_client */;
++/*!40101 SET character_set_client = utf8 */;
++CREATE TABLE `t2` (
++  `id` int(11) NOT NULL AUTO_INCREMENT,
++  `a` int(11) NOT NULL,
++  PRIMARY KEY (`id`),
++  CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t2` (`id`)
++) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
++/*!40101 SET character_set_client = @saved_cs_client */;
++
++LOCK TABLES `t2` WRITE;
++/*!40000 ALTER TABLE `t2` DISABLE KEYS */;
++INSERT INTO `t2` VALUES (1,1),(2,2),(3,3);
++ALTER TABLE `t2` ADD KEY `a` (`a`);
++/*!40000 ALTER TABLE `t2` ENABLE KEYS */;
++UNLOCK TABLES;
++/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
++
++/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
++/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
++/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
++/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
++/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
++/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
++/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
++
++######################################
++DROP TABLE t1, t2;
 --- a/mysql-test/suite/innodb_plugin/t/innodb.test
 +++ b/mysql-test/suite/innodb_plugin/t/innodb.test
 @@ -15,6 +15,12 @@
@@ -437,7 +687,7 @@
  # Save the original values of some variables in order to be able to
 --- /dev/null
 +++ b/mysql-test/t/percona_mysqldump_innodb_optimize_keys.test
-@@ -0,0 +1,94 @@
+@@ -0,0 +1,187 @@
 +# Embedded server doesn't support external clients
 +--source include/not_embedded.inc
 +
@@ -467,9 +717,8 @@
 +
 +DROP TABLE t1;
 +
-+
-+# Check that for InnoDB tables secondary and foreign keys are created
-+# after the data is dumped
++# Check that for InnoDB tables secondary keys are created after the data is
++# dumped but foreign ones are left in CREATE TABLE
 +
 +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
 +INSERT INTO t2 VALUES (0), (1), (2);
@@ -530,11 +779,105 @@
 +
 +DROP TABLE t1, t2;
 +
++########################################################################
++# Bug #851674: --innodb-optimize-keys does not work correctly with table
++#              without PRIMARY KEY
++########################################################################
++
++CREATE TABLE t1 (
++       a INT NOT NULL,
++       UNIQUE KEY (a)) ENGINE=InnoDB;
++
++CREATE TABLE t2 (
++       a INT NOT NULL,
++       b INT NOT NULL,
++       UNIQUE KEY (a,b)) ENGINE=InnoDB;
++
++CREATE TABLE t3 (
++       a INT,
++       b INT,
++       UNIQUE KEY (a,b)) ENGINE=InnoDB;
++
++CREATE TABLE t4 (
++       a INT NOT NULL,
++       b INT NOT NULL,
++       PRIMARY KEY (a,b),
++       UNIQUE KEY(b)) ENGINE=InnoDB;
++
++SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
++       TABLE_SCHEMA=DATABASE() AND
++       TABLE_NAME='t1' AND
++       COLUMN_KEY='PRI';
++SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
++       TABLE_SCHEMA=DATABASE() AND
++       TABLE_NAME='t2' AND
++       COLUMN_KEY='PRI';
++SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
++       TABLE_SCHEMA=DATABASE() AND
++       TABLE_NAME='t3' AND
++       COLUMN_KEY='PRI';
++SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE
++       TABLE_SCHEMA=DATABASE() AND
++       TABLE_NAME='t4' AND
++       COLUMN_KEY='PRI';
++
++INSERT INTO t1 VALUES (1), (2), (3);
++INSERT INTO t2 VALUES (1,1), (2,2), (3,3);
++INSERT INTO t3 SELECT * FROM t2;
++INSERT INTO t4 SELECT * FROM t2;
++
++--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 t3 t4 >$file
++
++--echo ######################################
++--cat_file $file
++--echo ######################################
++
++# Check that the resulting dump can be imported back
++
++--exec $MYSQL test < $file
++
++--remove_file $file
++
++DROP TABLE t1, t2, t3, t4;
++
++########################################################################
++# Bug #859078: --innodb-optimize-keys should ignore foreign keys
++########################################################################
++
++CREATE TABLE t1 (
++       id INT NOT NULL PRIMARY KEY
++) ENGINE=InnoDB;
++
++CREATE TABLE t2 (
++       id INT NOT NULL AUTO_INCREMENT,
++       a INT NOT NULL,
++       PRIMARY KEY (id),
++       KEY (a),
++       FOREIGN KEY (a) REFERENCES t2 (id)
++) ENGINE=InnoDB;
++
++INSERT INTO t1 VALUES (1), (2), (3);
++INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3);
++
++--exec $MYSQL_DUMP --skip-comments --innodb-optimize-keys test t1 t2 >$file
++
++--echo ######################################
++--cat_file $file
++--echo ######################################
++
++# Check that the resulting dump can be imported back
++
++--exec $MYSQL test < $file
++
++--remove_file $file
++
++DROP TABLE t1, t2;
++
 +# Wait till we reached the initial number of concurrent sessions
 +--source include/wait_until_count_sessions.inc
 --- a/sql/sql_lex.cc
 +++ b/sql/sql_lex.cc
-@@ -1494,6 +1494,9 @@
+@@ -1497,6 +1497,9 @@
    alter_list(rhs.alter_list, mem_root),
    key_list(rhs.key_list, mem_root),
    create_list(rhs.create_list, mem_root),
@@ -544,7 +887,7 @@
    flags(rhs.flags),
    keys_onoff(rhs.keys_onoff),
    tablespace_op(rhs.tablespace_op),
-@@ -1516,6 +1519,7 @@
+@@ -1519,6 +1522,7 @@
    list_copy_and_replace_each_value(alter_list, mem_root);
    list_copy_and_replace_each_value(key_list, mem_root);
    list_copy_and_replace_each_value(create_list, mem_root);
@@ -554,7 +897,7 @@
  
 --- a/sql/sql_lex.h
 +++ b/sql/sql_lex.h
-@@ -902,6 +902,9 @@
+@@ -904,6 +904,9 @@
    List<Alter_column>            alter_list;
    List<Key>                     key_list;
    List<Create_field>            create_list;
@@ -564,7 +907,7 @@
    uint                          flags;
    enum enum_enable_or_disable   keys_onoff;
    enum tablespace_op_type       tablespace_op;
-@@ -913,6 +916,8 @@
+@@ -915,6 +918,8 @@
  
  
    Alter_info() :
@@ -573,7 +916,7 @@
      flags(0),
      keys_onoff(LEAVE_AS_IS),
      tablespace_op(NO_TABLESPACE_OP),
-@@ -928,6 +933,9 @@
+@@ -930,6 +935,9 @@
      alter_list.empty();
      key_list.empty();
      create_list.empty();
@@ -585,24 +928,7 @@
      tablespace_op= NO_TABLESPACE_OP;
 --- a/sql/sql_table.cc
 +++ b/sql/sql_table.cc
-@@ -2560,7 +2560,7 @@
-       file                      The handler for the new table.
-       key_info_buffer     OUT   An array of KEY structs for the indexes.
-       key_count           OUT   The number of elements in the array.
--      select_field_count        The number of fields coming from a select table.
-+      select_field_count        The number of fields coming from a select table. 
- 
-   DESCRIPTION
-     Prepares the table and key structures for table creation.
-@@ -2915,7 +2915,6 @@
-   }
- 
-   /* Create keys */
--
-   List_iterator<Key> key_iterator(alter_info->key_list);
-   List_iterator<Key> key_iterator2(alter_info->key_list);
-   uint key_parts=0, fk_key_count=0;
-@@ -3015,6 +3014,14 @@
+@@ -3016,6 +3016,14 @@
    if (!*key_info_buffer || ! key_part_info)
      DBUG_RETURN(TRUE);				// Out of memory
  
@@ -617,7 +943,7 @@
    key_iterator.rewind();
    key_number=0;
    for (; (key=key_iterator++) ; key_number++)
-@@ -3393,8 +3400,26 @@
+@@ -3394,8 +3402,26 @@
        my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
        DBUG_RETURN(TRUE);
      }
@@ -644,7 +970,7 @@
    if (!unique_key && !primary_key &&
        (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
    {
-@@ -6093,6 +6118,10 @@
+@@ -6094,6 +6120,10 @@
    List<Create_field> new_create_list;
    /* New key definitions are added here */
    List<Key> new_key_list;
@@ -655,7 +981,7 @@
    List_iterator<Alter_drop> drop_it(alter_info->drop_list);
    List_iterator<Create_field> def_it(alter_info->create_list);
    List_iterator<Alter_column> alter_it(alter_info->alter_list);
-@@ -6105,6 +6134,7 @@
+@@ -6106,6 +6136,7 @@
    uint used_fields= create_info->used_fields;
    KEY *key_info=table->key_info;
    bool rc= TRUE;
@@ -663,7 +989,7 @@
  
    DBUG_ENTER("mysql_prepare_alter_table");
  
-@@ -6132,6 +6162,7 @@
+@@ -6133,6 +6164,7 @@
      char *tablespace= static_cast<char *>(thd->alloc(FN_LEN + 1));
      /*
         Regular alter table of disk stored table (no tablespace/storage change)
@@ -671,7 +997,7 @@
         Copy tablespace name
      */
      if (tablespace &&
-@@ -6282,7 +6313,23 @@
+@@ -6300,7 +6332,26 @@
    /*
      Collect all keys which isn't in drop list. Add only those
      for which some fields exists.
@@ -681,6 +1007,8 @@
 +    the InnoDB fast index creation. The following conditions must be
 +    met:
 +
++    - fast_index_creation is enabled for the current session
++    - expand_fast_index_creation is enabled for the current session;
 +    - we are going to create an InnoDB table (this is checked later when the
 +      target engine is known);
 +    - the key most be a non-UNIQUE one;
@@ -690,13 +1018,14 @@
 +      key constraints in the table.
 +  */
 +
-+  skip_secondary=
++  skip_secondary= thd->variables.online_alter_index &&
++    thd->variables.expand_fast_index_creation &&
 +    !table->file->get_foreign_key_list(thd, &f_key_list) &&
 +    f_key_list.elements == 0;
  
    for (uint i=0 ; i < table->s->keys ; i++,key_info++)
    {
-@@ -6385,6 +6432,8 @@
+@@ -6403,6 +6454,8 @@
                     test(key_info->flags & HA_GENERATED_KEY),
                     key_parts);
        new_key_list.push_back(key);
@@ -705,7 +1034,7 @@
      }
    }
    {
-@@ -6392,7 +6441,21 @@
+@@ -6410,7 +6463,21 @@
      while ((key=key_it++))			// Add new keys
      {
        if (key->type != Key::FOREIGN_KEY)
@@ -728,7 +1057,7 @@
        if (key->name &&
  	  !my_strcasecmp(system_charset_info,key->name,primary_key_name))
        {
-@@ -6441,12 +6504,100 @@
+@@ -6459,12 +6526,100 @@
    rc= FALSE;
    alter_info->create_list.swap(new_create_list);
    alter_info->key_list.swap(new_key_list);
@@ -829,7 +1158,7 @@
    Alter table
  
    SYNOPSIS
-@@ -7230,6 +7381,12 @@
+@@ -7248,6 +7403,12 @@
    else
      create_info->data_file_name=create_info->index_file_name=0;
  
@@ -842,7 +1171,7 @@
    DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock");
    /*
      Create a table with a temporary name.
-@@ -7286,15 +7443,33 @@
+@@ -7304,15 +7465,33 @@
    */
    if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
    {
@@ -876,3 +1205,230 @@
    }
    else
    {
+--- /dev/null
++++ b/mysql-test/r/percona_innodb_expand_fast_index_creation.result
+@@ -0,0 +1,67 @@
++SELECT @@expand_fast_index_creation;
++@@expand_fast_index_creation
++0
++CREATE TABLE t1(
++id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
++a CHAR(1) NOT NULL,
++b CHAR(36) NOT NULL) ENGINE=InnoDB;
++INSERT INTO t1(a,b) VALUES ('a','b');
++INSERT INTO t1(a,b) SELECT a,b FROM t1;
++INSERT INTO t1(a,b) SELECT a,b FROM t1;
++INSERT INTO t1(a,b) SELECT a,b FROM t1;
++INSERT INTO t1(a,b) SELECT a,b FROM t1;
++ALTER TABLE t1 ADD KEY (a);
++affected rows: 0
++info: Records: 0  Duplicates: 0  Warnings: 0
++EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
++id	1
++select_type	SIMPLE
++table	t1
++type	ALL
++possible_keys	a
++key	NULL
++key_len	NULL
++ref	NULL
++rows	16
++Extra	
++id	1
++select_type	SIMPLE
++table	t2
++type	ref
++possible_keys	a
++key	a
++key_len	1
++ref	test.t1.a
++rows	1
++Extra	Using where
++ALTER TABLE t1 DROP KEY a;
++SET expand_fast_index_creation = 1;
++SELECT @@expand_fast_index_creation;
++@@expand_fast_index_creation
++1
++ALTER TABLE t1 ADD KEY (a);
++affected rows: 0
++info: Records: 0  Duplicates: 0  Warnings: 0
++EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
++id	1
++select_type	SIMPLE
++table	t1
++type	ALL
++possible_keys	a
++key	NULL
++key_len	NULL
++ref	NULL
++rows	16
++Extra	
++id	1
++select_type	SIMPLE
++table	t2
++type	ALL
++possible_keys	a
++key	NULL
++key_len	NULL
++ref	NULL
++rows	16
++Extra	Using where; Using join buffer
++SET expand_fast_index_creation = 0;
++DROP TABLE t1;
+--- /dev/null
++++ b/mysql-test/t/percona_innodb_expand_fast_index_creation.test
+@@ -0,0 +1,46 @@
++--source include/have_innodb.inc
++
++SELECT @@expand_fast_index_creation;
++
++########################################################################
++# Bug #857590: Fast index creation does not update index statistics
++########################################################################
++
++CREATE TABLE t1(
++       id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
++       a CHAR(1) NOT NULL,
++       b CHAR(36) NOT NULL) ENGINE=InnoDB;
++
++INSERT INTO t1(a,b) VALUES ('a','b');
++INSERT INTO t1(a,b) SELECT a,b FROM t1;
++INSERT INTO t1(a,b) SELECT a,b FROM t1;
++INSERT INTO t1(a,b) SELECT a,b FROM t1;
++INSERT INTO t1(a,b) SELECT a,b FROM t1;
++
++# Check that fast index creation is used
++--enable_info
++ALTER TABLE t1 ADD KEY (a);
++--disable_info
++
++# The default (wrong) plan due to bogus statistics
++--vertical_results
++EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
++--horizontal_results
++
++ALTER TABLE t1 DROP KEY a;
++
++SET expand_fast_index_creation = 1;
++SELECT @@expand_fast_index_creation;
++
++# Check that stats are updated with the option enabled
++
++--enable_info
++ALTER TABLE t1 ADD KEY (a);
++--disable_info
++--vertical_results
++EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b;
++--horizontal_results
++
++SET expand_fast_index_creation = 0;
++
++DROP TABLE t1;
+--- a/storage/innodb_plugin/row/row0merge.c
++++ b/storage/innodb_plugin/row/row0merge.c
+@@ -56,6 +56,7 @@
+ #include "log0log.h"
+ #include "ut0sort.h"
+ #include "handler0alter.h"
++#include "ha_prototypes.h"
+ 
+ #ifdef UNIV_DEBUG
+ /** Set these in order ot enable debug printout. */
+@@ -2630,6 +2631,9 @@
+ 		}
+ 	}
+ 
++	if (trx->mysql_thd && thd_expand_fast_index_creation(trx->mysql_thd))
++		dict_update_statistics(new_table, FALSE, TRUE);
++
+ func_exit:
+ 	close(tmpfd);
+ 
+--- a/sql/mysqld.cc
++++ b/sql/mysqld.cc
+@@ -6061,7 +6061,8 @@
+   OPT_IGNORE_BUILTIN_INNODB,
+   OPT_BINLOG_DIRECT_NON_TRANS_UPDATE,
+   OPT_DEFAULT_CHARACTER_SET_OLD,
+-  OPT_MAX_LONG_DATA_SIZE
++  OPT_MAX_LONG_DATA_SIZE,
++  OPT_EXPAND_FAST_INDEX_CREATION
+ };
+ 
+ 
+@@ -6297,6 +6298,13 @@
+ each time the SQL thread starts.",
+    &opt_init_slave, &opt_init_slave, 0, GET_STR_ALLOC,
+    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
++  {"expand-fast-index-creation", OPT_EXPAND_FAST_INDEX_CREATION,
++   "Enable/disable improvements to the InnoDB fast index creation functionality. "
++   "Has no effect when fast index creation is disabled with the "
++   "fast-index-creation option",
++   &global_system_variables.expand_fast_index_creation,
++   &max_system_variables.expand_fast_index_creation,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, NULL},
+   {"language", 'L',
+    "Client error messages in given language. May be given as a full path.",
+    &language_ptr, &language_ptr, 0, GET_STR, REQUIRED_ARG,
+--- a/sql/set_var.cc
++++ b/sql/set_var.cc
+@@ -1056,6 +1056,9 @@
+                                                      SHOW_LONGLONG,
+                                                      get_myisam_mmap_size);
+ 
++static sys_var_thd_bool
++sys_expand_fast_index_creation(&vars,
++  "expand_fast_index_creation", &SV::expand_fast_index_creation);
+ 
+ bool sys_var::check(THD *thd, set_var *var)
+ {
+--- a/sql/sql_class.h
++++ b/sql/sql_class.h
+@@ -425,6 +425,8 @@
+   ulong      innodb_lock_que_wait_timer;
+   ulong      innodb_innodb_que_wait_timer;
+   ulong      innodb_page_access;
++
++  my_bool expand_fast_index_creation;
+ };
+ 
+ 
+--- a/storage/innodb_plugin/include/ha_prototypes.h
++++ b/storage/innodb_plugin/include/ha_prototypes.h
+@@ -276,4 +276,14 @@
+ /*================================*/
+ 	void*	thd);
+ 
++/******************************************************************//**
++Returns true if innodb_expand_fast_index_creation is enabled for the current
++session.
++ at return	the value of the server's innodb_expand_fast_index_creation variable */
++
++ibool
++thd_expand_fast_index_creation(
++/*==================*/
++	void*	thd);	/*!< in: thread handle (THD*) */
++
+ #endif
+--- a/storage/innodb_plugin/handler/ha_innodb.cc
++++ b/storage/innodb_plugin/handler/ha_innodb.cc
+@@ -770,6 +770,19 @@
+ 	return(THDVAR((THD*) thd, flush_log_at_trx_commit_session));
+ }
+ 
++/******************************************************************//**
++Returns true if expand_fast_index_creation is enabled for the current
++session.
++ at return	the value of the server's expand_fast_index_creation variable */
++extern "C" UNIV_INTERN
++ibool
++thd_expand_fast_index_creation(
++/*================================*/
++	void*	thd)
++{
++	return((ibool) (((THD*) thd)->variables.expand_fast_index_creation));
++}
++
+ /********************************************************************//**
+ Obtain the InnoDB transaction of a MySQL thread.
+ @return	reference to transaction pointer */
diff --git a/mysql-innodb_expand_import.patch b/mysql-innodb_expand_import.patch
index a802ede..c5b06e3 100644
--- a/mysql-innodb_expand_import.patch
+++ b/mysql-innodb_expand_import.patch
@@ -445,7 +445,7 @@
 +										ULINT_UNDEFINED, &heap);
 +								n_fields = rec_offs_n_fields(offsets);
 +								if (!offset) {
-+									offset = row_get_trx_id_offset(rec, index, offsets);
++									offset = row_get_trx_id_offset(index, offsets);
 +								}
 +								trx_write_trx_id(rec + offset, ut_dulint_create(0, 1));
 +
@@ -591,7 +591,7 @@
  	ut_free(buf2);
  
  	if (UNIV_UNLIKELY(space_id != id
-@@ -3117,6 +3642,271 @@
+@@ -3117,6 +3642,269 @@
  	os_file_close(file);
  	mem_free(filepath);
  
@@ -599,7 +599,6 @@
 +		ulint		page_no;
 +		ulint		zip_size;
 +		ulint		height;
-+		ulint		root_height = 0;
 +		rec_t*		node_ptr;
 +		dict_table_t*	table;
 +		dict_index_t*	index;
@@ -638,7 +637,6 @@
 +
 +			if (height == ULINT_UNDEFINED) {
 +				height = btr_page_get_level(page, &mtr);
-+				root_height = height;
 +			}
 +
 +			if (height == 0) {
@@ -696,7 +694,7 @@
 +						ULINT_UNDEFINED, &heap);
 +				n_fields = rec_offs_n_fields(offsets);
 +				if (!offset) {
<Skipped 11635 lines>
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/percona-server.git/commitdiff/bf636d07b36bfd2921b9ecf2033c78270355c98c



More information about the pld-cvs-commit mailing list