[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